blob: 242b45d9c799afb1a19e357f72278ecd16cb94ba [file] [log] [blame]
// Copyright 2024 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::puppet::LogMessage;
use diagnostics_data::LogsData;
use fidl_fuchsia_diagnostics::Severity;
use futures::{Stream, StreamExt};
type LogStreamItem = Result<LogsData, diagnostics_reader::Error>;
pub(crate) trait LogStream: Stream<Item = LogStreamItem> + Unpin {}
impl<T: Stream<Item = LogStreamItem> + Unpin> LogStream for T {}
/// Asserts that an ordered sequence of contiguous messages appears next in the log output.
///
/// This may completely drain `logs`. Log messages are only matched if they come from a
/// component with moniker `component_moniker`.
///
/// # Panics
///
/// Panics if any the contiguous sequence of messages is not found.
pub(crate) async fn assert_logs_sequence<S: LogStream>(
mut logs: S,
component_moniker: &str,
messages: Vec<LogMessage>,
) {
let mut m = 0; // the number of matches so far.
for (expected_severity, expected_message) in &messages {
let data = logs.next().await.expect("got log response").expect("log isn't an error");
if !logs_data_matches(data, component_moniker, expected_severity, expected_message) {
fail_on_incomplete_match(messages, m);
return; // Rust thinks this loop can iterate again if this return statement is removed.
}
m += 1;
}
}
fn logs_data_matches(
data: LogsData,
component_moniker: &str,
severity: &Severity,
message: &str,
) -> bool {
return data.moniker == component_moniker
&& data.msg().unwrap() == message
&& data.metadata.severity == *severity;
}
// Panics with an error message indicating that only `m` items of `expected_sequence`
// were matched, and highlights which items weren't found.
fn fail_on_incomplete_match(expected_sequence: Vec<LogMessage>, m: usize) {
let mut err = "ERROR: some log messages were not found (+got, -want):\n".to_string();
for (i, (severity, message)) in expected_sequence.iter().enumerate() {
let symbol = if i < m { "+" } else { "-" };
err += &format!("{symbol} [{severity:?}] {message}\n");
}
panic!("{err}");
}