use parking_lot::Mutex;
use std::sync::Arc;
use thenodes::events::{dispatcher, model::LogEvent, sink::LogSink};
use thenodes::security::trust::promote_observed_to_trusted;
struct MemorySink {
events: Arc<Mutex<Vec<LogEvent>>>,
}
#[async_trait::async_trait]
impl LogSink for MemorySink {
async fn handle(&self, event: &LogEvent) {
self.events.lock().push(event.clone());
}
}
#[tokio::test]
async fn promotion_event_emitted() {
let tmp = tempfile::tempdir().unwrap();
let observed = tmp.path().join("observed");
let trusted = tmp.path().join("trusted");
std::fs::create_dir_all(&observed).unwrap();
let fingerprint = "deadbeef"; let pem = b"-----BEGIN CERTIFICATE-----\nFAKE\n-----END CERTIFICATE-----\n";
std::fs::write(observed.join(format!("{}.pem", fingerprint)), pem).unwrap();
let mem = Arc::new(MemorySink {
events: Arc::new(Mutex::new(Vec::new())),
});
dispatcher::init_events(vec![mem.clone()], 32).await;
let promoted = promote_observed_to_trusted(
observed.to_str().unwrap(),
trusted.to_str().unwrap(),
fingerprint,
)
.unwrap();
assert!(promoted, "expected promotion to succeed");
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
let evts = mem.events.lock();
let has_promotion = evts
.iter()
.any(|e| matches!(e, LogEvent::Promotion(pe) if pe.fingerprint == fingerprint));
assert!(
has_promotion,
"expected a PromotionEvent with matching fingerprint, got: {:?}",
*evts
);
}