use std::{any::TypeId, sync::Arc};
use kabel::{DI, DIK, ServiceCollection};
pub trait Greeter: Send + Sync {
fn greet(&self) -> String;
}
pub struct EnglishGreeter {
pub name: String,
}
impl Greeter for EnglishGreeter {
fn greet(&self) -> String { format!("Hello, {}!", self.name) }
}
pub struct SpanishGreeter;
impl Greeter for SpanishGreeter {
fn greet(&self) -> String { "¡Hola!".to_string() }
}
pub struct KeyA;
pub struct KeyB;
#[test]
fn test_singleton_trait() {
let sc = ServiceCollection::new();
let greeter: Arc<dyn Greeter> = Arc::new(EnglishGreeter {
name: "World".to_string(),
});
sc.add_singleton_trait::<dyn Greeter>(greeter).unwrap();
let resolved = sc.dir::<dyn Greeter>().unwrap();
assert_eq!(resolved.greet(), "Hello, World!");
}
#[test]
fn test_singleton_trait_keyed() {
let sc = ServiceCollection::new();
let eng: Arc<dyn Greeter> = Arc::new(EnglishGreeter {
name: "Alice".to_string(),
});
let esp: Arc<dyn Greeter> = Arc::new(SpanishGreeter);
sc.add_singleton_trait_keyed::<dyn Greeter>(eng, TypeId::of::<KeyA>())
.unwrap();
sc.add_singleton_trait_keyed::<dyn Greeter>(esp, TypeId::of::<KeyB>())
.unwrap();
let res_a = sc.dikr::<dyn Greeter, KeyA>().unwrap();
assert_eq!(res_a.greet(), "Hello, Alice!");
let res_b = sc.dikr::<dyn Greeter, KeyB>().unwrap();
assert_eq!(res_b.greet(), "¡Hola!");
}
#[test]
fn test_transient_trait() {
let sc = ServiceCollection::new();
let counter = std::sync::atomic::AtomicUsize::new(0);
let counter_arc = Arc::new(counter);
let counter_clone = counter_arc.clone();
sc.add_transient_trait::<dyn Greeter, _>(move || {
let count = counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
Arc::new(EnglishGreeter {
name: format!("User #{}", count),
}) as Arc<dyn Greeter>
})
.unwrap();
let g1 = sc.dir::<dyn Greeter>().unwrap();
let g2 = sc.dir::<dyn Greeter>().unwrap();
assert_eq!(g1.greet(), "Hello, User #0!");
assert_eq!(g2.greet(), "Hello, User #1!");
}
#[test]
fn test_scoped_trait() {
let sc = ServiceCollection::new();
let counter = Arc::new(std::sync::atomic::AtomicUsize::new(0));
let counter_clone = counter.clone();
sc.add_scoped_trait::<dyn Greeter, _>(move || {
let count = counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
Arc::new(EnglishGreeter {
name: format!("ScopeInstance #{}", count),
}) as Arc<dyn Greeter>
})
.unwrap();
let scope1 = sc.create_scope();
let scope2 = sc.create_scope();
let scope_provider1 =
Arc::new(Arc::new(ScopeDummy(scope1)) as Arc<dyn kabel::scope::ScopeProvider>);
let scope_provider2 =
Arc::new(Arc::new(ScopeDummy(scope2)) as Arc<dyn kabel::scope::ScopeProvider>);
let g1_a = sc.disr::<dyn Greeter>(scope_provider1.clone()).unwrap();
let g1_b = sc.disr::<dyn Greeter>(scope_provider1.clone()).unwrap();
assert_eq!(g1_a.greet(), "Hello, ScopeInstance #0!");
assert_eq!(g1_b.greet(), "Hello, ScopeInstance #0!");
let g2_a = sc.disr::<dyn Greeter>(scope_provider2.clone()).unwrap();
assert_eq!(g2_a.greet(), "Hello, ScopeInstance #1!");
}
struct ScopeDummy(Arc<kabel::scope::Scope>);
impl kabel::scope::ScopeProvider for ScopeDummy {
fn provide_scope(
&self,
) -> Result<Arc<kabel::scope::Scope>, kabel::error::ServiceNotFoundError> {
Ok(self.0.clone())
}
}
#[test]
fn test_di_wrapper_struct() {
let sc = ServiceCollection::new();
let greeter: Arc<dyn Greeter> = Arc::new(EnglishGreeter {
name: "Bob".to_string(),
});
sc.add_singleton_trait::<dyn Greeter>(greeter).unwrap();
let resolved = sc.dir::<dyn Greeter>().unwrap();
let di_wrapper: DI<dyn Greeter> = DI(resolved);
assert_eq!(di_wrapper.0.greet(), "Hello, Bob!");
let greeter_k: Arc<dyn Greeter> = Arc::new(SpanishGreeter);
sc.add_singleton_trait_keyed::<dyn Greeter>(greeter_k, TypeId::of::<KeyA>())
.unwrap();
let resolved_k = sc.dikr::<dyn Greeter, KeyA>().unwrap();
let dik_wrapper: DIK<dyn Greeter, KeyA> = DIK(resolved_k, std::marker::PhantomData);
assert_eq!(dik_wrapper.0.greet(), "¡Hola!");
}