use {
super::super::*,
crate::ipc::{EventBus, EventScope},
std::sync::{
Arc,
atomic::{AtomicBool, AtomicUsize, Ordering},
},
};
#[test]
fn test_runtime_new() {
let runtime = Runtime::new();
assert_eq!(runtime.state(), RuntimeState::Booting);
assert!(runtime.is_idle());
}
#[test]
fn test_runtime_with_config() {
let config = RuntimeConfig {
work_queue_capacity: 100,
priority_queue_capacity: 50,
batch_size: 8,
max_timers: 64,
};
let runtime = Runtime::with_config(config);
assert_eq!(runtime.state(), RuntimeState::Booting);
}
#[test]
fn test_runtime_boot() {
let mut runtime = Runtime::new();
assert_eq!(runtime.state(), RuntimeState::Booting);
runtime.boot();
assert_eq!(runtime.state(), RuntimeState::Running);
}
#[test]
#[should_panic(expected = "boot() called when not in Booting state")]
fn test_runtime_boot_twice_panics() {
let mut runtime = Runtime::new();
runtime.boot();
runtime.boot(); }
#[test]
fn test_runtime_shutdown() {
let mut runtime = Runtime::new();
runtime.boot();
assert_eq!(runtime.state(), RuntimeState::Running);
runtime.shutdown();
assert_eq!(runtime.state(), RuntimeState::Stopping);
}
#[test]
fn test_runtime_emergency_stop() {
let mut runtime = Runtime::new();
runtime.boot();
runtime.emergency_stop();
assert_eq!(runtime.state(), RuntimeState::Emergency);
}
#[test]
fn test_runtime_shutdown_via_command() {
let mut runtime = Runtime::new();
runtime.boot();
let sender = runtime.command_sender();
sender.send(RuntimeCommand::Shutdown).unwrap();
runtime.tick();
assert_eq!(runtime.state(), RuntimeState::Stopping);
}
#[test]
fn test_runtime_schedule_work() {
let mut runtime = Runtime::new();
runtime.boot();
let executed = Arc::new(AtomicBool::new(false));
let executed_clone = Arc::clone(&executed);
assert!(runtime.schedule_work(move || {
executed_clone.store(true, Ordering::SeqCst);
}));
runtime.tick();
assert!(executed.load(Ordering::SeqCst));
}
#[test]
fn test_runtime_schedule_work_not_running() {
let runtime = Runtime::new(); assert!(!runtime.schedule_work(|| {}));
}
#[test]
fn test_runtime_schedule_task() {
let mut runtime = Runtime::new();
runtime.boot();
let executed = Arc::new(AtomicBool::new(false));
let executed_clone = Arc::clone(&executed);
let task = Task::new(move || {
executed_clone.store(true, Ordering::SeqCst);
});
assert!(runtime.schedule_task(task));
runtime.tick();
assert!(executed.load(Ordering::SeqCst));
}
#[test]
fn test_runtime_schedule_work_with_priority() {
let mut runtime = Runtime::new();
runtime.boot();
let order = Arc::new(std::sync::Mutex::new(Vec::new()));
let order1 = Arc::clone(&order);
runtime.schedule_work_with_priority(Priority::LOW, move || {
order1.lock().unwrap().push("low");
});
let order2 = Arc::clone(&order);
runtime.schedule_work_with_priority(Priority::HIGH, move || {
order2.lock().unwrap().push("high");
});
runtime.tick();
runtime.tick();
let result = order.lock().unwrap().clone();
assert_eq!(result.len(), 2);
}
#[test]
fn test_runtime_render_pending() {
let mut runtime = Runtime::new();
assert!(!runtime.is_render_pending());
runtime.request_render();
assert!(runtime.is_render_pending());
assert!(runtime.take_render_pending());
assert!(!runtime.is_render_pending());
}
#[test]
fn test_runtime_scope() {
let mut runtime = Runtime::new();
assert!(runtime.current_scope().is_none());
let scope = EventScope::new();
runtime.set_scope(scope);
assert!(runtime.current_scope().is_some());
runtime.clear_scope();
assert!(runtime.current_scope().is_none());
}
#[test]
fn test_runtime_is_idle() {
let mut runtime = Runtime::new();
runtime.boot();
assert!(runtime.is_idle());
runtime.schedule_work(|| {});
assert!(!runtime.is_idle());
runtime.tick();
assert!(runtime.is_idle());
}
#[test]
fn test_runtime_stats() {
let mut runtime = Runtime::new();
runtime.boot();
runtime.schedule_work(|| {});
runtime.schedule_work(|| panic!("intentional panic"));
let stats = runtime.stats();
assert_eq!(stats.state, RuntimeState::Running);
assert_eq!(stats.work_queue_len, 2);
assert_eq!(stats.tasks_executed, 0);
runtime.tick();
let stats = runtime.stats();
assert_eq!(stats.work_queue_len, 0);
assert_eq!(stats.tasks_executed, 1);
assert_eq!(stats.tasks_failed, 1);
}
#[test]
fn test_runtime_tick_returns_false_on_stop() {
let mut runtime = Runtime::new();
runtime.boot();
assert!(runtime.tick());
runtime.shutdown();
assert!(!runtime.tick());
}
#[test]
fn test_runtime_tick_drains_on_shutdown() {
let mut runtime = Runtime::new();
runtime.boot();
let counter = Arc::new(AtomicUsize::new(0));
for _ in 0..5 {
let counter_clone = Arc::clone(&counter);
runtime.schedule_work(move || {
counter_clone.fetch_add(1, Ordering::SeqCst);
});
}
runtime.shutdown();
runtime.tick();
assert_eq!(counter.load(Ordering::SeqCst), 5);
}
#[test]
fn test_runtime_run() {
let mut runtime = Runtime::new();
runtime.boot();
let counter = Arc::new(AtomicUsize::new(0));
let counter_clone = Arc::clone(&counter);
runtime.schedule_work(move || {
counter_clone.fetch_add(1, Ordering::SeqCst);
});
let sender = runtime.command_sender();
sender.send(RuntimeCommand::Shutdown).unwrap();
runtime.run();
assert_eq!(counter.load(Ordering::SeqCst), 1);
assert!(runtime.state().is_shutting_down());
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_runtime_debug() {
let runtime = Runtime::new();
let debug_str = format!("{runtime:?}");
assert!(debug_str.contains("Runtime"));
assert!(debug_str.contains("Booting"));
}
#[test]
fn test_runtime_with_event_bus() {
let bus = Arc::new(EventBus::new());
let bus_clone = Arc::clone(&bus);
let runtime = Runtime::new().with_event_bus(bus);
assert!(Arc::ptr_eq(runtime.event_bus(), &bus_clone));
}
#[test]
fn test_runtime_command_schedule_task() {
let mut runtime = Runtime::new();
runtime.boot();
let executed = Arc::new(AtomicBool::new(false));
let executed_clone = Arc::clone(&executed);
let task = Task::new(move || {
executed_clone.store(true, Ordering::SeqCst);
});
let sender = runtime.command_sender();
sender.send(RuntimeCommand::ScheduleTask(task)).unwrap();
runtime.tick();
runtime.tick();
assert!(executed.load(Ordering::SeqCst));
}
#[test]
fn test_runtime_send() {
fn assert_send<T: Send>() {}
assert_send::<Runtime>();
}
#[test]
fn test_runtime_schedule_delayed() {
let mut runtime = Runtime::new();
runtime.boot();
let counter = Arc::new(AtomicUsize::new(0));
let counter_clone = Arc::clone(&counter);
let handle = runtime.schedule_delayed(std::time::Duration::ZERO, move || {
counter_clone.fetch_add(1, Ordering::SeqCst);
});
assert!(!handle.is_failed());
runtime.tick();
runtime.tick();
assert_eq!(counter.load(Ordering::SeqCst), 1);
}
#[test]
fn test_runtime_schedule_periodic() {
let mut runtime = Runtime::new();
runtime.boot();
let counter = Arc::new(AtomicUsize::new(0));
let counter_clone = Arc::clone(&counter);
let handle = runtime.schedule_periodic(std::time::Duration::ZERO, move || {
counter_clone.fetch_add(1, Ordering::SeqCst);
});
let _ = handle.detach();
for _ in 0..4 {
runtime.tick();
}
assert!(counter.load(Ordering::SeqCst) >= 1);
}
#[test]
fn test_runtime_cancel_timer() {
let mut runtime = Runtime::new();
runtime.boot();
let handle = runtime.schedule_delayed(std::time::Duration::from_mins(1), || {});
let id = handle.detach();
assert!(runtime.cancel_timer(id));
}
#[test]
fn test_runtime_timer_wheel() {
let runtime = Runtime::new();
let wheel = runtime.timer_wheel();
assert_eq!(wheel.pending_count(), 0);
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_runtime_queue_event() {
use crate::ipc::{DynEvent, Event};
#[derive(Debug)]
struct TestEvent;
impl Event for TestEvent {}
let mut runtime = Runtime::new();
runtime.boot();
let event = DynEvent::new(TestEvent);
assert!(runtime.queue_event(event));
}
#[test]
fn test_runtime_emergency_via_command() {
let mut runtime = Runtime::new();
runtime.boot();
let sender = runtime.command_sender();
sender.send(RuntimeCommand::Emergency).unwrap();
runtime.tick();
assert_eq!(runtime.state(), RuntimeState::Emergency);
}
#[test]
fn test_runtime_schedule_work_when_stopping() {
let mut runtime = Runtime::new();
runtime.boot();
runtime.shutdown();
assert!(!runtime.schedule_work(|| {}));
}
#[test]
fn test_runtime_schedule_task_not_running() {
let runtime = Runtime::new(); let task = Task::new(|| {});
assert!(!runtime.schedule_task(task));
}
#[test]
fn test_runtime_default() {
let runtime = Runtime::default();
assert_eq!(runtime.state(), RuntimeState::Booting);
}
#[test]
fn test_runtime_work_queue() {
let runtime = Runtime::new();
assert!(runtime.work_queue().is_empty());
}
#[test]
fn test_runtime_schedule_work_with_priority_not_running() {
let runtime = Runtime::new(); assert!(!runtime.schedule_work_with_priority(Priority::HIGH, || {}));
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_runtime_command_schedule_task_when_stopping() {
let mut runtime = Runtime::new();
runtime.boot();
let executed = Arc::new(AtomicBool::new(false));
let executed_clone = Arc::clone(&executed);
let sender = runtime.command_sender();
sender.send(RuntimeCommand::Shutdown).unwrap();
sender
.send(RuntimeCommand::ScheduleTask(Task::new(move || {
executed_clone.store(true, Ordering::SeqCst);
})))
.unwrap();
runtime.tick();
assert_eq!(runtime.state(), RuntimeState::Stopping);
}
#[test]
fn test_runtime_shutdown_from_booting() {
let mut runtime = Runtime::new();
runtime.shutdown();
assert_eq!(runtime.state(), RuntimeState::Booting);
}
#[test]
fn test_runtime_emergency_stop_from_booting() {
let mut runtime = Runtime::new();
runtime.emergency_stop();
assert_eq!(runtime.state(), RuntimeState::Emergency);
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_runtime_dispatch_events_with_scope() {
use crate::ipc::{DynEvent, Event, EventScope};
#[derive(Debug)]
struct ScopeTestEvent;
impl Event for ScopeTestEvent {}
let mut runtime = Runtime::new();
runtime.boot();
let scope = EventScope::new();
scope.increment();
scope.increment();
runtime.set_scope(scope.clone());
let event = DynEvent::new(ScopeTestEvent);
runtime.queue_event(event);
runtime.tick();
assert!(scope.in_flight() < 2);
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_runtime_config_debug_clone() {
let config = RuntimeConfig::default();
let cloned = config;
assert_eq!(cloned.batch_size, DEFAULT_BATCH_SIZE);
let debug = format!("{config:?}");
assert!(debug.contains("RuntimeConfig"));
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_runtime_command_debug() {
let cmd = RuntimeCommand::Shutdown;
let debug = format!("{cmd:?}");
assert!(debug.contains("Shutdown"));
}
#[test]
fn test_runtime_stats_default() {
let stats = RuntimeStats::default();
assert_eq!(stats.state, RuntimeState::Booting);
assert_eq!(stats.tasks_executed, 0);
}
#[test]
fn test_runtime_tick_emergency_returns_false() {
let mut runtime = Runtime::new();
runtime.boot();
runtime.emergency_stop();
assert!(!runtime.tick());
}
#[test]
fn test_runtime_schedule_work_when_emergency() {
let mut runtime = Runtime::new();
runtime.boot();
runtime.emergency_stop();
assert_eq!(runtime.state(), RuntimeState::Emergency);
assert!(!runtime.schedule_work(|| {}));
}
#[test]
fn test_runtime_schedule_work_with_priority_when_emergency() {
let mut runtime = Runtime::new();
runtime.boot();
runtime.emergency_stop();
assert!(!runtime.schedule_work_with_priority(Priority::HIGH, || {}));
}
#[test]
fn test_runtime_schedule_task_when_emergency() {
let mut runtime = Runtime::new();
runtime.boot();
runtime.emergency_stop();
let task = Task::new(|| {});
assert!(!runtime.schedule_task(task));
}
#[test]
fn test_runtime_shutdown_when_already_stopping() {
let mut runtime = Runtime::new();
runtime.boot();
runtime.shutdown(); assert_eq!(runtime.state(), RuntimeState::Stopping);
runtime.shutdown();
assert_eq!(runtime.state(), RuntimeState::Stopping);
}