use super::*;
use std::sync::atomic::{AtomicUsize, Ordering};
fn add_to_counter((counter, amount): (&AtomicUsize, usize)) -> usize {
return counter.fetch_add(amount, Ordering::SeqCst) + amount;
}
fn panic_on_zero(state: usize) -> usize {
assert!(state != 0, "the job was given zero");
return state;
}
fn thread_of(_state: ()) -> std::thread::ThreadId {
return std::thread::current().id();
}
#[test]
fn every_state_runs_once_and_results_keep_their_order() {
let counter: AtomicUsize = AtomicUsize::new(0);
let states: Vec<(&AtomicUsize, usize)> = (1..=4).map(|amount| { return (&counter, amount); }).collect();
let results: Vec<std::thread::Result<usize>> = run_all_side_by_side(states, add_to_counter);
assert_eq!(results.len(), 4);
assert!(results.iter().all(Result::is_ok));
assert_eq!(counter.load(Ordering::SeqCst), 10, "each state added its amount once");
}
#[test]
fn a_job_that_panics_is_an_error_in_its_place() {
let results: Vec<std::thread::Result<usize>> = run_all_side_by_side(vec![1, 0, 3], panic_on_zero);
assert_eq!(results[0].as_ref().ok(), Some(&1));
assert!(results[1].is_err());
assert_eq!(results[2].as_ref().ok(), Some(&3));
}
#[test]
fn the_callers_function_runs_here_and_the_job_on_another_thread() {
let here: std::thread::ThreadId = std::thread::current().id();
let (from_thread, from_here) = run_beside_caller(((), thread_of), ((), thread_of));
assert_ne!(from_thread.expect("the thread"), here);
assert_eq!(from_here, here);
}
#[test]
fn jobs_run_in_turn_where_no_thread_starts() {
let _refused = crate::scoped_start::RefusedStarts::here();
let here: std::thread::ThreadId = std::thread::current().id();
let results: Vec<std::thread::Result<std::thread::ThreadId>> = run_all_side_by_side(vec![(), ()], thread_of);
for each in results {
assert_eq!(each.expect("the value"), here);
}
}