use mati_core::mcp::metadata::{
install_panic_hook, is_lifecycle_log_preopened, record_lifecycle_event,
};
fn read_log(root: &std::path::Path) -> String {
std::fs::read_to_string(root.join("lifecycle.log")).unwrap_or_default()
}
#[test]
fn panic_hook_preopens_lifecycle_fd_and_routes_correctly() {
assert!(
!is_lifecycle_log_preopened(),
"lifecycle fd must not be preopened before install_panic_hook"
);
let dir_a = tempfile::tempdir().unwrap();
let root_a = dir_a.path().to_path_buf();
install_panic_hook(root_a.clone());
assert!(
is_lifecycle_log_preopened(),
"install_panic_hook must populate LIFECYCLE_LOG_FILE on success"
);
record_lifecycle_event(&root_a, "evt_match", "matching root");
let log_a = read_log(&root_a);
assert!(
log_a.contains("\tevt_match\tmatching root\n"),
"matching-root event missing from rootA log; contents:\n{log_a}"
);
let dir_b = tempfile::tempdir().unwrap();
let root_b = dir_b.path().to_path_buf();
record_lifecycle_event(&root_b, "evt_fallback", "other root");
let log_b = read_log(&root_b);
assert!(
log_b.contains("\tevt_fallback\tother root\n"),
"fallback-path event missing from rootB log; contents:\n{log_b}"
);
let log_a_after = read_log(&root_a);
assert!(
!log_a_after.contains("evt_fallback"),
"fallback-path event leaked into rootA — path-equality check failed.\n\
rootA log after mismatched write:\n{log_a_after}"
);
let marker = "preopen-test-panic-marker-9b32f1";
let payload = marker.to_string();
let handle = std::thread::spawn(move || {
let _ = std::panic::catch_unwind(move || {
panic!("{payload}");
});
});
handle
.join()
.expect("panicking thread joined cleanly after catch_unwind");
let log_panic = read_log(&root_a);
assert!(
log_panic.contains("\tpanic\t"),
"no `panic` lifecycle event recorded in rootA log; contents:\n{log_panic}"
);
assert!(
log_panic.contains(marker),
"panic payload marker `{marker}` missing from rootA log; contents:\n{log_panic}"
);
}