use moonpool_sim::{Event, SimWorld};
use std::time::Duration;
#[test]
fn deterministic_event_execution_order() {
fn run_simulation() -> Vec<Duration> {
let mut sim = SimWorld::new();
let mut execution_times = Vec::new();
sim.schedule_event(Event::Timer { task_id: 1 }, Duration::from_millis(100));
sim.schedule_event(Event::Timer { task_id: 2 }, Duration::from_millis(50));
sim.schedule_event(Event::Timer { task_id: 3 }, Duration::from_millis(100)); sim.schedule_event(Event::Timer { task_id: 4 }, Duration::from_millis(75));
sim.schedule_event(Event::Timer { task_id: 5 }, Duration::from_millis(100));
while sim.has_pending_events() {
let had_events = sim.step();
execution_times.push(sim.current_time());
if !had_events {
break; }
}
execution_times
}
let results: Vec<Vec<Duration>> = (0..10).map(|_| run_simulation()).collect();
let first_result = &results[0];
for (i, result) in results.iter().enumerate().skip(1) {
assert_eq!(
result,
first_result,
"Run {} produced different execution times than the first run. Expected: {:?}, Got: {:?}",
i + 1,
first_result,
result
);
}
let expected_times = vec![
Duration::from_millis(50), Duration::from_millis(75), Duration::from_millis(100), Duration::from_millis(100), Duration::from_millis(100), ];
assert_eq!(first_result, &expected_times);
}
#[test]
fn same_time_events_sequence_order() {
let mut sim = SimWorld::new();
let target_time = Duration::from_millis(100);
sim.schedule_event_at(Event::Timer { task_id: 10 }, target_time);
sim.schedule_event_at(Event::Timer { task_id: 20 }, target_time);
sim.schedule_event_at(Event::Timer { task_id: 30 }, target_time);
sim.schedule_event_at(Event::Timer { task_id: 40 }, target_time);
assert_eq!(sim.pending_event_count(), 4);
assert_eq!(sim.current_time(), Duration::ZERO);
assert!(sim.step());
assert_eq!(sim.current_time(), target_time);
assert!(sim.step());
assert_eq!(sim.current_time(), target_time);
assert!(sim.step());
assert_eq!(sim.current_time(), target_time);
assert!(!sim.step()); assert_eq!(sim.current_time(), target_time);
assert!(!sim.has_pending_events());
assert_eq!(sim.pending_event_count(), 0);
}
#[test]
fn interleaved_scheduling_consistency() {
fn create_sim_variant_1() -> SimWorld {
let sim = SimWorld::new();
sim.schedule_event_at(Event::Timer { task_id: 1 }, Duration::from_millis(100));
sim.schedule_event_at(Event::Timer { task_id: 2 }, Duration::from_millis(100));
sim.schedule_event_at(Event::Timer { task_id: 3 }, Duration::from_millis(100));
sim
}
fn create_sim_variant_2() -> SimWorld {
let sim = SimWorld::new();
sim.schedule_event_at(Event::Timer { task_id: 3 }, Duration::from_millis(100));
sim.schedule_event_at(Event::Timer { task_id: 2 }, Duration::from_millis(100));
sim.schedule_event_at(Event::Timer { task_id: 1 }, Duration::from_millis(100));
sim
}
fn create_sim_variant_3() -> SimWorld {
let sim = SimWorld::new();
sim.schedule_event_at(Event::Timer { task_id: 2 }, Duration::from_millis(100));
sim.schedule_event_at(Event::Timer { task_id: 1 }, Duration::from_millis(100));
sim.schedule_event_at(Event::Timer { task_id: 3 }, Duration::from_millis(100));
sim
}
let mut sim1 = create_sim_variant_1();
let mut sim2 = create_sim_variant_2();
let mut sim3 = create_sim_variant_3();
sim1.run_until_empty();
sim2.run_until_empty();
sim3.run_until_empty();
assert_eq!(sim1.current_time(), Duration::from_millis(100));
assert_eq!(sim2.current_time(), Duration::from_millis(100));
assert_eq!(sim3.current_time(), Duration::from_millis(100));
assert!(!sim1.has_pending_events());
assert!(!sim2.has_pending_events());
assert!(!sim3.has_pending_events());
}
#[test]
fn time_advancement_deterministic() {
let mut sim = SimWorld::new();
sim.schedule_event(Event::Timer { task_id: 3 }, Duration::from_millis(150));
sim.schedule_event(Event::Timer { task_id: 1 }, Duration::from_millis(50));
sim.schedule_event(Event::Timer { task_id: 2 }, Duration::from_millis(100));
assert_eq!(sim.current_time(), Duration::ZERO);
assert_eq!(sim.pending_event_count(), 3);
assert!(sim.step());
assert_eq!(sim.current_time(), Duration::from_millis(50));
assert_eq!(sim.pending_event_count(), 2);
assert!(sim.step());
assert_eq!(sim.current_time(), Duration::from_millis(100));
assert_eq!(sim.pending_event_count(), 1);
assert!(!sim.step()); assert_eq!(sim.current_time(), Duration::from_millis(150));
assert_eq!(sim.pending_event_count(), 0);
assert!(!sim.has_pending_events());
}
#[test]
fn empty_simulation_behavior() {
let mut sim = SimWorld::new();
assert_eq!(sim.current_time(), Duration::ZERO);
assert!(!sim.has_pending_events());
assert_eq!(sim.pending_event_count(), 0);
assert!(!sim.step());
assert_eq!(sim.current_time(), Duration::ZERO);
sim.run_until_empty();
assert_eq!(sim.current_time(), Duration::ZERO);
assert!(!sim.has_pending_events());
}