use ek_event::{EVENT_TIMER, Event, EventEngine};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::time::Duration;
fn wait_for(cond: impl Fn() -> bool) -> bool {
for _ in 0..400 {
if cond() {
return true;
}
std::thread::sleep(Duration::from_millis(10));
}
cond()
}
#[test]
fn t1_timer_count_throttle() {
let engine = Arc::new(EventEngine::with_interval(Duration::from_millis(50)));
engine.start();
let fires = Arc::new(AtomicUsize::new(0)); let throttle = Arc::new(AtomicUsize::new(0)); let works = Arc::new(AtomicUsize::new(0));
let f = fires.clone();
let th = throttle.clone();
let w = works.clone();
engine.register(
EVENT_TIMER,
Arc::new(move |_| {
f.fetch_add(1, Ordering::SeqCst); let n = th.fetch_add(1, Ordering::SeqCst) + 1;
if n < 3 {
return;
}
w.fetch_add(1, Ordering::SeqCst);
th.store(0, Ordering::SeqCst);
}),
);
std::thread::sleep(Duration::from_millis(600));
let fired = fires.load(Ordering::SeqCst);
let worked = works.load(Ordering::SeqCst);
assert!(fired >= 7, "timer must fire repeatedly (fired {fired})");
assert!(
(2..=4).contains(&worked),
"throttled work must fire roughly every 3rd tick (fired {fired}, worked {worked})"
);
engine.stop();
}
#[test]
fn t2_timer_interleaved_with_business_events() {
let engine = Arc::new(EventEngine::with_interval(Duration::from_millis(30)));
engine.start();
let ticks_seen = Arc::new(AtomicUsize::new(0));
let seq = Arc::new(Mutex::new(Vec::<usize>::new()));
let s = seq.clone();
let seen_for_handler = ticks_seen.clone();
engine.register(
"eTick.",
Arc::new(move |e| {
let v = *e.data.downcast_ref::<usize>().unwrap();
s.lock().unwrap().push(v);
seen_for_handler.fetch_add(1, Ordering::SeqCst);
}),
);
let timer_seen = Arc::new(AtomicUsize::new(0));
let t = timer_seen.clone();
engine.register(
EVENT_TIMER,
Arc::new(move |_| {
t.fetch_add(1, Ordering::SeqCst);
}),
);
for i in 0..10usize {
engine.put(Event::with_data("eTick.", Arc::new(i))).unwrap();
std::thread::sleep(Duration::from_millis(30));
}
assert!(
wait_for(|| ticks_seen.load(Ordering::SeqCst) == 10),
"all 10 business events must be delivered"
);
assert!(
timer_seen.load(Ordering::SeqCst) >= 3,
"timer events must interleave with business events"
);
let got = seq.lock().unwrap().clone();
let expected: Vec<usize> = (0..10usize).collect();
assert_eq!(
got, expected,
"business order must be preserved despite timer interleave"
);
engine.stop();
}