use crate::test_tracing_capture::with_test_subscriber;
use anyhow::{Context, Result, ensure};
use std::path::Path;
use tracing_subscriber::filter::LevelFilter;
use super::diagnostics::path_hash;
pub(super) fn capture_events<T, E>(
test: impl FnOnce() -> std::result::Result<T, E>,
) -> std::result::Result<(T, Vec<String>), E> {
with_test_subscriber(LevelFilter::TRACE, |captured| {
let value = test()?;
Ok((value, captured.snapshot()))
})
}
pub(super) fn find_event<'a>(events: &'a [String], message: &str) -> Result<&'a String> {
events
.iter()
.find(|event| event.contains(message))
.with_context(|| format!("expected event containing {message:?} in {events:?}"))
}
pub(super) struct EventAssertion<'a> {
event: &'a str,
path: &'a Path,
}
impl<'a> EventAssertion<'a> {
pub(super) fn new(event: &'a str, path: &'a Path) -> Self {
Self { event, path }
}
pub(super) fn ensure_bounded_path_fields(&self) -> Result<()> {
let hash = path_hash(self.path);
ensure!(
self.event.contains(&format!("path_hash=\"{hash}\""))
|| self.event.contains(&format!("path_hash=Some(\"{hash}\")"))
|| self.event.contains(&format!("path_hash={hash}")),
"event should include path hash for {}: {}",
self.path.display(),
self.event
);
self.ensure_raw_path_absent()?;
Ok(())
}
pub(super) fn ensure_raw_path_absent(&self) -> Result<()> {
ensure!(
!self.event.contains(self.path.to_string_lossy().as_ref()),
"event should not include raw path {}: {}",
self.path.display(),
self.event
);
if let Some(file_name) = self.path.file_name() {
ensure!(
!self.event.contains(file_name.to_string_lossy().as_ref()),
"event should not include path file name {}: {}",
file_name.to_string_lossy(),
self.event
);
}
Ok(())
}
pub(super) fn ensure_private_event_fields(&self, formatted_error: &str) -> Result<()> {
self.ensure_raw_path_absent()?;
ensure!(
!self.event.contains(formatted_error),
"event should not include formatted error text: {}",
self.event
);
Ok(())
}
pub(super) fn normalize_path_hash(&self) -> Result<String> {
self.ensure_bounded_path_fields()?;
Ok(self.event.replace(&path_hash(self.path), "[path_hash]"))
}
}
pub(crate) fn assert_bounded_path_event(event: &str, path: &Path) -> Result<()> {
EventAssertion::new(event, path).ensure_bounded_path_fields()
}