use singleton_registry::define_registry;
use std::sync::Arc;
#[test]
fn test_multiple_isolated_registries() {
define_registry!(database);
define_registry!(cache);
define_registry!(config);
database::register("postgresql://localhost".to_string());
cache::register("redis://localhost".to_string());
config::register("app_config".to_string());
let db: Arc<String> = database::get().unwrap();
let cache_val: Arc<String> = cache::get().unwrap();
let cfg: Arc<String> = config::get().unwrap();
assert_eq!(&**db, "postgresql://localhost");
assert_eq!(&**cache_val, "redis://localhost");
assert_eq!(&**cfg, "app_config");
}
#[test]
fn test_same_type_different_registries() {
define_registry!(reg_a);
define_registry!(reg_b);
reg_a::register(100i32);
reg_b::register(200i32);
let a: Arc<i32> = reg_a::get().unwrap();
let b: Arc<i32> = reg_b::get().unwrap();
assert_eq!(*a, 100);
assert_eq!(*b, 200);
}
#[test]
fn test_registry_does_not_leak_between_instances() {
define_registry!(isolated_a);
define_registry!(isolated_b);
isolated_a::register("only in A".to_string());
assert!(isolated_a::contains::<String>().unwrap());
assert!(!isolated_b::contains::<String>().unwrap());
let result: Result<Arc<String>, _> = isolated_b::get();
assert!(result.is_err());
}
#[test]
fn test_multiple_types_in_multiple_registries() {
define_registry!(multi_a);
define_registry!(multi_b);
multi_a::register(42i32);
multi_a::register("hello".to_string());
multi_b::register(std::f64::consts::PI);
multi_b::register(true);
assert!(multi_a::contains::<i32>().unwrap());
assert!(multi_a::contains::<String>().unwrap());
assert!(!multi_a::contains::<f64>().unwrap());
assert!(!multi_a::contains::<bool>().unwrap());
assert!(multi_b::contains::<f64>().unwrap());
assert!(multi_b::contains::<bool>().unwrap());
assert!(!multi_b::contains::<i32>().unwrap());
assert!(!multi_b::contains::<String>().unwrap());
}
#[test]
fn test_registry_scoping() {
mod module_a {
use singleton_registry::define_registry;
define_registry!(scoped);
pub fn setup() {
scoped::register("module A".to_string());
}
pub fn get_value() -> String {
use std::sync::Arc;
let val: Arc<String> = scoped::get().unwrap();
val.to_string()
}
}
mod module_b {
use singleton_registry::define_registry;
define_registry!(scoped);
pub fn setup() {
scoped::register("module B".to_string());
}
pub fn get_value() -> String {
use std::sync::Arc;
let val: Arc<String> = scoped::get().unwrap();
val.to_string()
}
}
module_a::setup();
module_b::setup();
assert_eq!(module_a::get_value(), "module A");
assert_eq!(module_b::get_value(), "module B");
}
#[test]
fn test_registry_with_tracing_isolation() {
define_registry!(traced_a);
define_registry!(traced_b);
let events = Arc::new(std::sync::Mutex::new(Vec::new()));
let events_clone = events.clone();
traced_a::set_trace_callback(move |event| {
events_clone.lock().unwrap().push(format!("{}", event));
});
traced_a::register(1i32);
traced_b::register(2i32);
let count = events.lock().unwrap().len();
let e0 = events.lock().unwrap()[0].clone();
let e1 = events.lock().unwrap()[1].clone();
assert_eq!(count, 2);
assert!(e0.contains("register"));
assert!(e1.contains("register_completed"));
}