blob: fbca222eb96e3df33fbcb15878d236b770a0742d [file] [log] [blame]
// Copyright 2020 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::Error;
use archivist_lib::logs::redact::{REDACTED_CANARY_MESSAGE, UNREDACTED_CANARY_MESSAGE};
use diagnostics_data::LogsData;
use diagnostics_reader::{ArchiveReader, Logs};
use fidl_fuchsia_diagnostics::ArchiveAccessorMarker;
use fidl_fuchsia_sys::ComponentControllerEvent;
use fuchsia_async::Task;
use fuchsia_component::client::launcher;
use fuchsia_component::client::{App, AppBuilder};
use futures::prelude::*;
use std::{
fs::{create_dir_all, remove_dir_all, write, File},
path::Path,
};
use tracing::debug;
#[fuchsia::test]
async fn canary_is_redacted_with_filtering() {
debug!("test started");
let env = TestEnv::with_filtering().await.unwrap();
let redacted = env.get_feedback_canary().await;
assert_eq!(redacted.msg().unwrap().trim_end(), REDACTED_CANARY_MESSAGE);
}
#[fuchsia::test]
async fn canary_is_unredacted_without_filtering() {
debug!("test started");
let env = TestEnv::without_filtering().await.unwrap();
let redacted = env.get_feedback_canary().await;
assert_eq!(redacted.msg().unwrap().trim_end(), UNREDACTED_CANARY_MESSAGE);
}
const ARCHIVIST_URL: &str =
"fuchsia-pkg://fuchsia.com/test-logs-redaction#meta/own-logs-consuming-archivist.cmx";
const ARCHIVIST_CONFIG: &[u8] = include_bytes!("../configs/archivist_config.json");
struct TestEnv {
_archivist: App,
_monitor_archivist: Task<()>,
feedback_reader: ArchiveReader,
all_reader: ArchiveReader,
}
impl TestEnv {
/// Get the redaction canary message from the FeedbackArchiveAccessor reader. Relies on ordering
/// being identical between ArchiveAccessor snapshot and FeedbackArchiveAccessor snapshot.
async fn get_feedback_canary(&self) -> LogsData {
debug!("retrieving logs from feedback accessor");
let feedback_logs = self.feedback_reader.snapshot::<Logs>().await.unwrap();
let all_logs = self.all_reader.snapshot::<Logs>().await.unwrap();
let (unredacted, redacted) = all_logs
.into_iter()
.zip(feedback_logs)
.find(|(u, _)| u.msg().unwrap().contains(UNREDACTED_CANARY_MESSAGE))
.unwrap();
debug!(unredacted = %unredacted.msg().unwrap());
redacted
}
async fn without_filtering() -> Result<Self, Error> {
Self::new(false).await
}
async fn with_filtering() -> Result<Self, Error> {
Self::new(true).await
}
async fn new(filter: bool) -> Result<Self, Error> {
debug!(%filter, "creating test environment");
let config_path = Path::new("/tmp/config/data");
let feedback_path = config_path.join("feedback");
remove_dir_all(config_path).unwrap_or_default();
create_dir_all(&feedback_path)?;
write(config_path.join("archivist_config.json"), ARCHIVIST_CONFIG)?;
// VERY IMPORTANT -- the feedback pipeline disables all filtering if no files present
write(feedback_path.join("empty.cfg"), b"")?;
if !filter {
write(
config_path.join("feedback/DISABLE_FILTERING.txt"),
"This file disables filtering",
)?;
}
let _archivist = AppBuilder::new(ARCHIVIST_URL)
.add_dir_to_namespace("/config/data".into(), File::open(config_path)?)?
.spawn(&launcher()?)?;
// first we'll wait for the archivist to start, then make sure it doesn't stop in the background
let mut component_stream = _archivist.controller().take_event_stream();
let handle_termination = |code, reason| {
panic!("Archivist terminated unexpectedly. Code: {}. Reason: {:?}", code, reason);
};
debug!("waiting for archivist to start");
match component_stream.try_next().await?.unwrap() {
ComponentControllerEvent::OnDirectoryReady {} => debug!("archivist directory ready"),
ComponentControllerEvent::OnTerminated { return_code, termination_reason } => {
handle_termination(return_code, termination_reason)
}
}
let _monitor_archivist = Task::spawn(async move {
while let Some(next) = component_stream.try_next().await.unwrap() {
match next {
ComponentControllerEvent::OnDirectoryReady {} => {
panic!("received dir ready 2x")
}
ComponentControllerEvent::OnTerminated { return_code, termination_reason } => {
handle_termination(return_code, termination_reason)
}
}
}
});
let all_reader = ArchiveReader::new()
.with_archive(_archivist.connect_to_service::<ArchiveAccessorMarker>().unwrap());
let feedback_reader = ArchiveReader::new().with_archive(
_archivist
.connect_to_named_service::<ArchiveAccessorMarker>(
"fuchsia.diagnostics.FeedbackArchiveAccessor",
)
.unwrap(),
);
debug!("test env created");
Ok(TestEnv { _archivist, all_reader, feedback_reader, _monitor_archivist })
}
}