use std::sync::{Arc, Mutex};
use crate::EventSink;
pub struct MemoryEventSink {
events: Arc<Mutex<Vec<String>>>,
}
impl MemoryEventSink {
pub fn new() -> Self {
Self {
events: Arc::new(Mutex::new(Vec::new())),
}
}
pub fn events_handle(&self) -> Arc<Mutex<Vec<String>>> {
Arc::clone(&self.events)
}
pub fn drain(&self) -> Vec<String> {
self.events.lock().unwrap().drain(..).collect()
}
}
impl Default for MemoryEventSink {
fn default() -> Self {
Self::new()
}
}
impl EventSink for MemoryEventSink {
fn emit(&self, payload: &str) {
self.events.lock().unwrap().push(payload.to_string());
}
fn flush(&self) {}
}
#[macro_export]
macro_rules! event_sink_contract_tests {
($name:ident, $setup:expr $(,)?) => {
mod $name {
use $crate::EventSink as _;
use super::*;
#[test]
fn contract_emit_captures_payload() {
let sink = $setup;
sink.emit("hello");
let events = sink.drain();
assert_eq!(events, vec!["hello".to_string()]);
}
#[test]
fn contract_flush_is_noop() {
let sink = $setup;
sink.emit("a");
sink.flush();
let events = sink.drain();
assert_eq!(events.len(), 1);
}
#[test]
fn contract_emit_preserves_order() {
let sink = $setup;
sink.emit("first");
sink.emit("second");
sink.emit("third");
let events = sink.drain();
assert_eq!(events, vec!["first", "second", "third"]);
}
#[test]
fn contract_drain_clears_buffer() {
let sink = $setup;
sink.emit("x");
let first = sink.drain();
let second = sink.drain();
assert_eq!(first.len(), 1);
assert!(second.is_empty(), "drain should clear the buffer");
}
#[test]
fn contract_emit_empty_payload_is_stored() {
let sink = $setup;
sink.emit("");
let events = sink.drain();
assert_eq!(events, vec!["".to_string()]);
}
}
};
}
#[cfg(test)]
mod contract_tests {
use super::MemoryEventSink;
crate::event_sink_contract_tests!(memory, MemoryEventSink::new());
}