use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
mod common;
use common::block_on;
#[test]
fn task_panic_resolves_join_handle_and_loop_survives() {
let (was_panicked, follow_up_value) = block_on(|| async {
let panicker = runite::spawn(async {
panic!("task boom");
});
let err = panicker
.await
.expect_err("a panicking task must not yield a value");
let follow_up = runite::spawn(async { 7u32 });
let value = follow_up
.await
.expect("follow-up task should complete after an isolated panic");
(err.is_panicked(), value)
});
assert!(
was_panicked,
"panicking task should resolve to JoinError::Panicked"
);
assert_eq!(follow_up_value, 7);
}
#[test]
fn blocking_task_panic_resolves_to_panicked() {
let (was_panicked, follow_up_value) = block_on(|| async {
let handle = runite::spawn_blocking(|| -> u32 { panic!("blocking boom") })
.expect("blocking task should queue");
let err = handle
.await
.expect_err("a panicking blocking task must not yield a value");
let follow_up =
runite::spawn_blocking(|| 11u32).expect("second blocking task should queue");
let value = follow_up
.await
.expect("follow-up blocking task should complete");
(err.is_panicked(), value)
});
assert!(
was_panicked,
"panicking blocking task should resolve to JoinError::Panicked"
);
assert_eq!(follow_up_value, 11);
}
#[test]
fn scheduled_closure_panic_does_not_kill_loop() {
let follow_up_ran = Arc::new(AtomicBool::new(false));
let follow_up_writer = Arc::clone(&follow_up_ran);
std::thread::spawn(move || {
runite::queue_macrotask(|| panic!("macrotask boom"));
runite::queue_macrotask(move || follow_up_writer.store(true, Ordering::SeqCst));
runite::run();
})
.join()
.expect("an isolated macrotask panic must not unwind out of run()");
assert!(
follow_up_ran.load(Ordering::SeqCst),
"a macrotask queued after a panicking one should still run"
);
}
#[test]
fn panic_does_not_strand_sibling_tasks() {
let completed = Arc::new(AtomicU32::new(0));
let completed_writer = Arc::clone(&completed);
block_on(move || async move {
let a = runite::spawn(async { 1u32 });
let panicker = runite::spawn(async { panic!("sibling boom") });
let b = runite::spawn(async { 2u32 });
completed_writer.fetch_add(a.await.expect("task a completes"), Ordering::SeqCst);
assert!(panicker.await.is_err());
completed_writer.fetch_add(b.await.expect("task b completes"), Ordering::SeqCst);
});
assert_eq!(completed.load(Ordering::SeqCst), 3);
}