use ri::hooks::{RiHookBus, RiHookEvent, RiHookKind, RiModulePhase};
use ri::core::RiServiceContext;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
#[test]
fn test_module_phase_as_str() {
assert_eq!(RiModulePhase::Init.as_str(), "init");
assert_eq!(RiModulePhase::BeforeStart.as_str(), "before_start");
assert_eq!(RiModulePhase::Start.as_str(), "start");
assert_eq!(RiModulePhase::AfterStart.as_str(), "after_start");
assert_eq!(RiModulePhase::BeforeShutdown.as_str(), "before_shutdown");
assert_eq!(RiModulePhase::Shutdown.as_str(), "shutdown");
assert_eq!(RiModulePhase::AfterShutdown.as_str(), "after_shutdown");
assert_eq!(RiModulePhase::AsyncInit.as_str(), "async_init");
assert_eq!(RiModulePhase::AsyncBeforeStart.as_str(), "async_before_start");
assert_eq!(RiModulePhase::AsyncStart.as_str(), "async_start");
assert_eq!(RiModulePhase::AsyncAfterStart.as_str(), "async_after_start");
assert_eq!(RiModulePhase::AsyncBeforeShutdown.as_str(), "async_before_shutdown");
assert_eq!(RiModulePhase::AsyncShutdown.as_str(), "async_shutdown");
assert_eq!(RiModulePhase::AsyncAfterShutdown.as_str(), "async_after_shutdown");
}
#[test]
fn test_hook_bus_new() {
let hook_bus = RiHookBus::new();
}
#[test]
fn test_hook_bus_register_emit() {
let mut hook_bus = RiHookBus::new();
let ctx = RiServiceContext::new_default().unwrap();
let called = Arc::new(AtomicBool::new(false));
let called_handle = Arc::clone(&called);
hook_bus.register(RiHookKind::Startup, "test_hook".to_string(), move |_ctx, _event| {
called_handle.store(true, Ordering::SeqCst);
Ok(())
});
hook_bus.emit(&RiHookKind::Startup, &ctx).unwrap();
assert!(called.load(Ordering::SeqCst));
}
#[test]
fn test_hook_bus_register_emit_with() {
let mut hook_bus = RiHookBus::new();
let ctx = RiServiceContext::new_default().unwrap();
let called = Arc::new(AtomicBool::new(false));
let captured_event: Arc<Mutex<Option<RiHookEvent>>> = Arc::new(Mutex::new(None));
let called_handle = Arc::clone(&called);
let captured_handle: Arc<Mutex<Option<RiHookEvent>>> = Arc::clone(&captured_event);
hook_bus.register(RiHookKind::Startup, "test_hook".to_string(), move |_ctx, event| {
called_handle.store(true, Ordering::SeqCst);
*captured_handle.lock().unwrap() = Some(event.clone());
Ok(())
});
hook_bus.emit_with(
&RiHookKind::Startup,
&ctx,
Some("test_module"),
Some(RiModulePhase::Init)
).unwrap();
assert!(called.load(Ordering::SeqCst));
let captured = {
let guard = captured_event.lock().unwrap();
guard.clone()
};
if let Some(event) = captured {
assert_eq!(event.kind, RiHookKind::Startup);
assert_eq!(event.module, Some("test_module".to_string()));
assert_eq!(event.phase, Some(RiModulePhase::Init));
} else {
assert!(false, "Event was not captured");
}
}
#[test]
fn test_hook_bus_multiple_handlers() {
let mut hook_bus = RiHookBus::new();
let ctx = RiServiceContext::new_default().unwrap();
let called1 = Arc::new(AtomicBool::new(false));
let called2 = Arc::new(AtomicBool::new(false));
let called1_handle = Arc::clone(&called1);
let called2_handle = Arc::clone(&called2);
hook_bus.register(RiHookKind::Startup, "test_hook1".to_string(), move |_ctx, _event| {
called1_handle.store(true, Ordering::SeqCst);
Ok(())
});
hook_bus.register(RiHookKind::Startup, "test_hook2".to_string(), move |_ctx, _event| {
called2_handle.store(true, Ordering::SeqCst);
Ok(())
});
hook_bus.emit(&RiHookKind::Startup, &ctx).unwrap();
assert!(called1.load(Ordering::SeqCst));
assert!(called2.load(Ordering::SeqCst));
}
#[test]
fn test_hook_bus_different_hook_kinds() {
let mut hook_bus = RiHookBus::new();
let ctx = RiServiceContext::new_default().unwrap();
let startup_called = Arc::new(AtomicBool::new(false));
let shutdown_called = Arc::new(AtomicBool::new(false));
let startup_handle = Arc::clone(&startup_called);
let shutdown_handle = Arc::clone(&shutdown_called);
hook_bus.register(RiHookKind::Startup, "startup_hook".to_string(), move |_ctx, _event| {
startup_handle.store(true, Ordering::SeqCst);
Ok(())
});
hook_bus.register(RiHookKind::Shutdown, "shutdown_hook".to_string(), move |_ctx, _event| {
shutdown_handle.store(true, Ordering::SeqCst);
Ok(())
});
hook_bus.emit(&RiHookKind::Startup, &ctx).unwrap();
assert!(startup_called.load(Ordering::SeqCst));
assert!(!shutdown_called.load(Ordering::SeqCst));
hook_bus.emit(&RiHookKind::Shutdown, &ctx).unwrap();
assert!(startup_called.load(Ordering::SeqCst));
assert!(shutdown_called.load(Ordering::SeqCst));
}