use std::sync::Arc;
use std::thread;
use std::time::Duration;
use crate::container::IocContainer;
use crate::errors::CoreError;
#[test]
fn test_create_child_scope_atomicity() {
let container = Arc::new({
let mut container = IocContainer::new();
container.build().unwrap();
container
});
let parent_scope_id = container.create_scope().unwrap();
let mut handles = vec![];
let container_clone = container.clone();
let parent_id = parent_scope_id.clone();
handles.push(thread::spawn(move || {
thread::sleep(Duration::from_micros(10));
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
let _ = container_clone.dispose_scope(&parent_id).await;
});
}));
for i in 0..5 {
let container_clone = container.clone();
let parent_id = parent_scope_id.clone();
handles.push(thread::spawn(move || {
thread::sleep(Duration::from_micros(i as u64 * 5));
match container_clone.create_child_scope(&parent_id) {
Ok(child_id) => {
assert!(
container_clone.create_child_scope(&child_id).is_ok(),
"Created child scope but it's not valid"
);
}
Err(CoreError::ServiceNotFound { .. }) => {
}
Err(e) => {
panic!("Unexpected error: {:?}", e);
}
}
}));
}
for handle in handles {
handle.join().unwrap();
}
}
#[test]
fn test_concurrent_scope_operations() {
let container = Arc::new({
let mut container = IocContainer::new();
container.build().unwrap();
container
});
let scope1 = container.create_scope().unwrap();
let scope2 = container.create_scope().unwrap();
let mut handles = vec![];
for i in 0..3 {
let container_clone = container.clone();
let parent = scope1.clone();
handles.push(thread::spawn(move || {
thread::sleep(Duration::from_micros(i * 10));
let _ = container_clone.create_child_scope(&parent);
}));
}
for i in 0..3 {
let container_clone = container.clone();
let parent = scope2.clone();
handles.push(thread::spawn(move || {
thread::sleep(Duration::from_micros(i * 10));
let _ = container_clone.create_child_scope(&parent);
}));
}
let container_clone = container.clone();
let scope_to_dispose = scope1.clone();
handles.push(thread::spawn(move || {
thread::sleep(Duration::from_micros(25));
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
let _ = container_clone.dispose_scope(&scope_to_dispose).await;
});
}));
for handle in handles {
handle.join().unwrap();
}
assert!(
container.create_child_scope(&scope2).is_ok(),
"Scope2 should still be valid after scope1 disposal"
);
}