blob: 30dea9b81f7b006b0aa327ab00212bb8b2ca8273 [file] [log] [blame]
// Copyright 2018 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 crate::{logs::utils::Listener, test_topology};
use diagnostics_reader::{ArchiveReader, Logs};
use fidl_fuchsia_archivist_test as ftest;
use fidl_fuchsia_diagnostics::{ArchiveAccessorMarker, Severity};
use fidl_fuchsia_logger::{LogFilterOptions, LogLevelFilter, LogMarker, LogMessage, LogProxy};
use fuchsia_async as fasync;
use fuchsia_component::client;
use fuchsia_syslog_listener as syslog_listener;
use fuchsia_zircon as zx;
use futures::{channel::mpsc, Stream, StreamExt};
use tracing::{info, warn};
fn run_listener(tag: &str, proxy: LogProxy) -> impl Stream<Item = LogMessage> {
let options = LogFilterOptions {
filter_by_pid: false,
pid: 0,
min_severity: LogLevelFilter::None,
verbosity: 0,
filter_by_tid: false,
tid: 0,
tags: vec![tag.to_string()],
};
let (send_logs, recv_logs) = mpsc::unbounded();
let l = Listener { send_logs };
fasync::Task::spawn(async move {
let fut =
syslog_listener::run_log_listener_with_proxy(&proxy, l, Some(&options), false, None);
if let Err(e) = fut.await {
panic!("test fail {e:?}");
}
})
.detach();
recv_logs
}
#[fuchsia::test(logging = false)]
async fn listen_for_syslog() {
let random = rand::random::<u16>();
let tag = "logger_integration_rust".to_string() + &random.to_string();
diagnostics_log::initialize(diagnostics_log::PublishOptions::default().tags(&[&tag])).unwrap();
let log_proxy = client::connect_to_protocol::<LogMarker>().unwrap();
let incoming = run_listener(&tag, log_proxy);
info!("my msg: {}", 10);
warn!("log crate: {}", 20);
let mut logs: Vec<LogMessage> = incoming.take(2).collect().await;
// sort logs to account for out-of-order arrival
logs.sort_by(|a, b| a.time.cmp(&b.time));
assert_eq!(2, logs.len());
assert_eq!(logs[1].tags.len(), 1);
assert_eq!(logs[0].tags[0], tag);
assert_eq!(logs[0].severity, LogLevelFilter::Info as i32);
assert_eq!(logs[0].msg, "my msg: 10");
assert_eq!(logs[1].tags.len(), 1);
assert_eq!(logs[1].tags[0], tag);
assert_eq!(logs[1].severity, LogLevelFilter::Warn as i32);
assert_eq!(logs[1].msg, "log crate: 20");
}
#[fuchsia::test]
async fn listen_for_klog() {
let realm_proxy = test_topology::create_realm(ftest::RealmOptions {
archivist_config: Some(ftest::ArchivistConfig {
enable_klog: Some(true),
..Default::default()
}),
..Default::default()
})
.await
.unwrap();
let log_proxy = realm_proxy.connect_to_protocol::<LogMarker>().await.unwrap();
let logs = run_listener("klog", log_proxy);
let msg = format!("logger_integration_rust test_klog {}", rand::random::<u64>());
let resource = zx::Resource::from(zx::Handle::invalid());
let debuglog = zx::DebugLog::create(&resource, zx::DebugLogOpts::empty()).unwrap();
debuglog.write(msg.as_bytes()).unwrap();
logs.filter(|m| futures::future::ready(m.msg == msg)).next().await;
}
#[fuchsia::test]
async fn listen_for_syslog_routed_stdio() {
let realm_proxy = test_topology::create_realm(ftest::RealmOptions {
puppets: Some(vec![test_topology::PuppetDeclBuilder::new("stdio-puppet").into()]),
..Default::default()
})
.await
.unwrap();
let accessor = realm_proxy
.connect_to_protocol::<ArchiveAccessorMarker>()
.await
.expect("ArchiveAccessor unavailable");
info!("Connected to Accessor");
let mut reader = ArchiveReader::new();
reader.with_archive(accessor);
let (mut logs, mut errors) = reader.snapshot_then_subscribe::<Logs>().unwrap().split_streams();
let _errors = fasync::Task::spawn(async move {
if let Some(e) = errors.next().await {
panic!("error in subscription: {e}");
}
});
let puppet = test_topology::connect_to_puppet(&realm_proxy, "stdio-puppet").await.unwrap();
info!("Connected to puppet");
// Ensure the component already started by waiting for its initial interest change.
assert_eq!(Some(Severity::Info), puppet.wait_for_interest_change().await.unwrap().severity);
let msg = format!("logger_integration_rust test_klog stdout {}", rand::random::<u64>());
puppet.println(&msg).await.unwrap();
info!("printed '{msg}' to stdout");
logs.by_ref().filter(|m| futures::future::ready(m.msg().unwrap() == msg)).next().await;
let msg = format!("logger_integration_rust test_klog stderr {}", rand::random::<u64>());
puppet.eprintln(&msg).await.unwrap();
info!("Printed '{msg}' to stderr");
logs.filter(|m| futures::future::ready(m.msg().unwrap() == msg)).next().await;
// TODO(https://fxbug.dev/42126316): add test for multiline log once behavior is defined.
}