use std::io;
use std::sync::{Arc, Mutex};
use std::thread;
use ticklog::{info, Level, LogSink};
struct CaptureSink {
lines: Arc<Mutex<Vec<String>>>,
}
impl LogSink for CaptureSink {
fn accept(&mut self, line: &[u8], _level: Level) -> io::Result<()> {
self.lines
.lock()
.unwrap()
.push(String::from_utf8_lossy(line).into_owned());
Ok(())
}
}
fn any_line_contains(lines: &[String], needle: &str) -> bool {
lines.iter().any(|line| line.contains(needle))
}
#[test]
fn worker_thread_records_survive_its_exit_and_guard_shutdown() {
let lines = Arc::new(Mutex::new(Vec::new()));
let sink = CaptureSink {
lines: Arc::clone(&lines),
};
let guard = ticklog::builder()
.sink(sink)
.max_level(Level::Info)
.build()
.expect("first build in a fresh process must succeed");
info!("main before worker");
let worker = thread::spawn(|| {
info!("worker record {}", 7);
});
worker.join().expect("worker thread must not panic");
info!("main after worker");
drop(guard);
let captured = lines.lock().unwrap();
assert!(
any_line_contains(&captured, "worker record 7"),
"the exited worker's record must still be delivered, got {captured:?}"
);
assert!(any_line_contains(&captured, "main before worker"));
assert!(any_line_contains(&captured, "main after worker"));
}