blob: fa82654f452a498e3188884a875759699507f552 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
anyhow::{self, Error},
fidl_fidl_examples_routing_echo as fecho, fidl_fuchsia_logger as flogger,
fuchsia_async as fasync,
fuchsia_component::server as fserver,
fuchsia_component_test::{
Capability, ChildOptions, LocalComponentHandles, RealmBuilder, Ref, Route,
},
futures::{
stream::{self as stream, StreamExt, TryStreamExt},
TryFutureExt,
},
std::sync::Arc,
tracing::{info, subscriber},
};
async fn echo_server_mock(handles: LocalComponentHandles) -> Result<(), Error> {
// Create a new ServiceFs to host FIDL protocols from
let mut fs = fserver::ServiceFs::new();
let mut tasks = vec![];
let log_proxy = handles.connect_to_protocol::<flogger::LogSinkMarker>()?;
let (publisher, fut) = diagnostics_log::Publisher::new_with_proxy(
log_proxy,
diagnostics_log::PublishOptions::default(),
)?;
let _log_task = fasync::Task::spawn(fut);
let publisher: Arc<dyn subscriber::Subscriber + Sync + Send + 'static> = Arc::new(publisher);
// Add the echo protocol to the ServiceFs
fs.dir("svc").add_fidl_service(move |mut stream: fecho::EchoRequestStream| {
let publisher_clone = publisher.clone();
tasks.push(fasync::Task::local(async move {
while let Some(fecho::EchoRequest::EchoString { value, responder }) =
stream.try_next().await.expect("failed to serve echo service")
{
subscriber::with_default(publisher_clone.clone(), || {
info!("Got echo request: {:?}", value);
});
responder.send(value.as_ref().map(|s| &**s)).expect("failed to send echo response");
}
}));
});
// Run the ServiceFs on the outgoing directory handle from the mock handles
fs.serve_connection(handles.outgoing_dir.into_channel())?;
fs.collect::<()>().await;
Ok(())
}
/// Create and launch a child that spams 1000 logs. Launching a child to send logs allows
/// us to more effectively spam logs, since logging on fuchsia has safeguards against a single
/// component spamming too many logs.
async fn spam_logs_from_child() -> Result<(), Error> {
let builder = RealmBuilder::new().await?;
let echo_server = builder
.add_local_child(
"echo_server",
move |handles: LocalComponentHandles| Box::pin(echo_server_mock(handles)),
ChildOptions::new(),
)
.await?;
builder
.add_route(
Route::new()
.capability(Capability::protocol_by_name("fuchsia.logger.LogSink"))
.from(Ref::parent())
.to(&echo_server),
)
.await?;
builder
.add_route(
Route::new()
.capability(Capability::protocol_by_name("fidl.examples.routing.echo.Echo"))
.from(&echo_server)
.to(Ref::parent()),
)
.await?;
let realm = builder.build().await?;
let echo = realm.root.connect_to_protocol_at_exposed_dir::<fecho::EchoMarker>()?;
for _ in 0..500 {
assert_eq!(echo.echo_string(Some("hello")).await?, Some("hello".to_owned()));
}
Ok(())
}
#[fuchsia::test]
async fn spam_logs() {
stream::repeat_with(|| spam_logs_from_child().unwrap_or_else(|e| panic!("{:?}", e)))
.take(300)
.buffer_unordered(100)
.collect::<Vec<_>>()
.await;
}