use super::*;
#[test]
fn test_moirai_creation() {
let moirai = Moirai::new().unwrap();
assert!(moirai.worker_count() > 0);
}
#[test]
fn test_builder() {
let moirai = Moirai::builder()
.worker_threads(4)
.async_threads(2)
.build()
.unwrap();
assert_eq!(moirai.worker_count(), 4);
}
#[test]
fn test_spawn_fn() {
let moirai = Moirai::new().unwrap();
let handle = moirai.spawn_fn(|| (0..100).sum::<i32>());
assert!(handle.id().0 > 0 && handle.id().0 < 100);
{
std::thread::sleep(std::time::Duration::from_millis(10));
if let Some(result) = handle.join() {
assert_eq!(result, Ok(4950)); }
}
}
#[test]
fn test_task_panic_handling() {
let moirai = Moirai::new().unwrap();
let handle = moirai.spawn_fn(|| {
panic!("Task intentionally panicked!");
});
std::thread::sleep(std::time::Duration::from_millis(50));
assert!(handle.id().0 > 0);
let _result = handle.join();
}
#[test]
fn test_spawn_async() {
let moirai = Moirai::new().unwrap();
let handle = moirai.spawn_async(async { 42 });
assert!(handle.id().0 > 0 && handle.id().0 < 100);
}
#[test]
fn test_scope_completes_borrowed_jobs() {
let moirai = Moirai::builder().worker_threads(2).build().unwrap();
let sum = std::sync::atomic::AtomicUsize::new(0);
moirai
.scope(|scope| {
for value in 1..=32 {
let sum = ∑
scope.spawn(move |_| {
sum.fetch_add(value, std::sync::atomic::Ordering::Relaxed);
})?;
}
Ok(())
})
.unwrap();
assert_eq!(sum.load(std::sync::atomic::Ordering::Relaxed), 528);
moirai.shutdown();
}
#[test]
fn test_indexed_fan_out_completes_borrowed_jobs() {
let moirai = Moirai::builder().worker_threads(2).build().unwrap();
let sum = std::sync::atomic::AtomicUsize::new(0);
moirai
.for_each_indexed(32, |index| {
sum.fetch_add(index + 1, std::sync::atomic::Ordering::Relaxed);
})
.unwrap();
assert_eq!(sum.load(std::sync::atomic::Ordering::Relaxed), 528);
moirai.shutdown();
}
#[test]
fn test_indexed_map_reduce_returns_value() {
let moirai = Moirai::builder().worker_threads(2).build().unwrap();
let sum = moirai
.map_reduce_indexed(32, 0usize, |index| index + 1, usize::wrapping_add)
.unwrap();
assert_eq!(sum, 528);
moirai.shutdown();
}
#[test]
fn test_join_waits_for_public_spawned_tasks() {
let moirai = Moirai::builder().worker_threads(2).build().unwrap();
let barrier = std::sync::Arc::new(std::sync::Barrier::new(3));
let b = barrier.clone();
let handle1 = moirai.spawn_fn(move || {
b.wait();
1
});
let b = barrier.clone();
let handle2 = moirai.spawn_fn(move || {
b.wait();
2
});
assert!(moirai.has_work());
barrier.wait();
moirai.join().unwrap();
assert!(!moirai.has_work());
let results = vec![
handle1.join().unwrap().unwrap(),
handle2.join().unwrap().unwrap(),
];
assert_eq!(results, vec![1, 2]);
moirai.shutdown();
}
#[test]
fn test_repeated_public_spawn_join_completes() {
let moirai = Moirai::builder().worker_threads(4).build().unwrap();
for value in 0..1_048_576usize {
let handle = moirai.spawn_fn(move || value.wrapping_add(1));
assert_eq!(handle.join().unwrap().unwrap(), value.wrapping_add(1));
}
moirai.shutdown();
}
#[test]
fn test_global_runtime() {
let runtime1 = global();
let runtime2 = global();
assert!(std::ptr::eq(runtime1, runtime2));
}
#[test]
fn test_global_spawn() {
let handle = spawn_fn(|| "hello world");
assert!(handle.id().0 < 100); }
#[test]
fn test_task_with_priority() {
let moirai = Moirai::new().unwrap();
let _context = TaskContext::new(TaskId::new(42))
.with_priority(Priority::High)
.with_name("test_task");
let task = moirai_core::task::TaskBuilder::new()
.with_id(TaskId::new(0))
.build(|| "high priority task");
let handle = moirai.spawn_with_priority(task, Priority::High);
assert!(handle.id().0 > 0 && handle.id().0 < 100);
}
#[test]
fn test_task_builder() {
let task = TaskBuilder::new()
.priority(Priority::High)
.name("test_task")
.build(|| 42);
assert_eq!(task.context().priority, Priority::High);
assert_eq!(task.context().name, Some("test_task"));
assert_eq!(task.execute(), 42);
}
#[test]
fn test_task_chaining() {
let task = moirai_core::task::TaskBuilder::new()
.with_id(TaskId::new(1))
.build(|| 21);
let chained = task.then(|x| x * 2);
assert_eq!(chained.execute(), 42);
}
#[test]
fn test_task_mapping() {
let task = moirai_core::task::TaskBuilder::new()
.with_id(TaskId::new(1))
.build(|| 21);
let mapped = task.map(|x| x * 2);
assert_eq!(mapped.execute(), 42);
}
#[test]
fn test_task_result_retrieval() {
let moirai = Moirai::new().unwrap();
let handle1 = moirai.spawn_fn(|| 42 * 2);
let handle2 = moirai.spawn_fn(|| format!("Hello, {}", "Moirai"));
let handle3 = moirai.spawn_fn(|| (1..=10).product::<i32>());
assert!(handle1.id().0 < 100);
assert!(handle2.id().0 < 100);
assert!(handle3.id().0 < 100);
std::thread::sleep(std::time::Duration::from_millis(50));
let result1 = handle1.join();
let result2 = handle2.join();
let result3 = handle3.join();
println!("Result 1: {result1:?}");
println!("Result 2: {result2:?}");
println!("Result 3: {result3:?}");
if let Some(result) = result1 {
assert_eq!(result, Ok(84));
}
if let Some(result) = result2 {
assert_eq!(result, Ok("Hello, Moirai".to_string()));
}
if let Some(result) = result3 {
assert_eq!(result, Ok(3_628_800)); }
}
#[test]
fn distributed_feature_does_not_add_facade_remote_closure_execution() {
let moirai = Moirai::builder().build().unwrap();
let handle = moirai.spawn_fn(|| "computed locally".to_string());
let result = handle.join().expect("local task handle must be attached");
assert_eq!(result, Ok("computed locally".to_string()));
moirai.shutdown();
}