#[cfg(test)]
pub mod test_mocks {
use crate::{buffer::BufferReader, protocol::EventPayload, tracing::read_tracing_event};
use core::cell::RefCell;
thread_local! {
static WRITE_HOOK: RefCell<Option<Box<dyn FnMut(&[u8])>>> = RefCell::new(None);
static RAW_TIME_HOOK: RefCell<Option<Box<dyn FnMut() -> u32>>> = RefCell::new(None);
static SYS_TIME_HOOK: RefCell<Option<Box<dyn FnMut() -> u64>>> = RefCell::new(None);
}
#[unsafe(no_mangle)]
fn write_tracing_data(data: &[u8]) {
WRITE_HOOK.with(|hook| {
if let Some(h) = hook.borrow_mut().as_mut() {
return h(data);
}
println!(
"Warning: write_tracing_data called without mock! Data len: {}",
data.len()
);
});
}
#[unsafe(no_mangle)]
fn get_tracing_raw_ticks() -> u32 {
RAW_TIME_HOOK.with(|hook| {
if let Some(h) = hook.borrow_mut().as_mut() {
return h();
}
println!("Warning: get_tracing_raw_ticks called without mock! Returning 0.");
0
})
}
#[unsafe(no_mangle)]
fn get_system_time_us() -> u64 {
SYS_TIME_HOOK.with(|hook| {
if let Some(h) = hook.borrow_mut().as_mut() {
return h();
}
println!("Warning: get_system_time_us called without mock! Returning 0.");
0
})
}
pub fn with_mocks<W, T, S, F>(write_fn: W, raw_time_fn: T, sys_time_fn: S, test_body: F)
where
W: FnMut(&[u8]) + 'static,
T: FnMut() -> u32 + 'static,
S: FnMut() -> u64 + 'static,
F: FnOnce(),
{
WRITE_HOOK.with(|h| *h.borrow_mut() = Some(Box::new(write_fn)));
RAW_TIME_HOOK.with(|h| *h.borrow_mut() = Some(Box::new(raw_time_fn)));
SYS_TIME_HOOK.with(|h| *h.borrow_mut() = Some(Box::new(sys_time_fn)));
test_body();
WRITE_HOOK.with(|h| *h.borrow_mut() = None);
RAW_TIME_HOOK.with(|h| *h.borrow_mut() = None);
SYS_TIME_HOOK.with(|h| *h.borrow_mut() = None);
}
pub fn mock_time_provider() -> u32 {
123_456_789
}
pub fn mock_trace_writer(expected: EventPayload) -> impl Fn(&[u8]) {
move |data: &[u8]| {
let mut buffer = BufferReader::new(data);
let (timestamp, event) =
read_tracing_event(&mut buffer).expect("Failed to read tracing event");
assert_eq!(event, expected);
assert_eq!(timestamp.delta(), 123_456_789);
}
}
}