use std::clone::Clone;
use std::convert::Into;
use std::sync::Arc;
use std::sync::Mutex;
use crate::thread::{Handle, Pending};
use crate::{Nursery, Waitable};
pub struct Counter {
count: i32,
}
impl Counter {
pub fn incr(&mut self) {
self.count += 1;
}
}
#[test]
fn thread_handle_runs_failure_handler() {
let mut err_counter = 0;
{
let mut h = Handle::new(move || {
panic!("Aaahhh!");
})
.with_handler(Box::new(|| err_counter += 1));
h.wait();
}
assert_eq!(err_counter, 1);
}
#[test]
fn thread_handle_runs() {
let counter = Arc::new(Mutex::new(Counter { count: 0 }));
let h_counter = counter.clone();
let mut h = Handle::new(move || {
let mut c = h_counter.lock().unwrap();
c.incr();
});
h.wait();
assert_eq!(counter.lock().unwrap().count, 1);
}
#[test]
fn thread_handle_wait_is_idempotent() {
let counter = Arc::new(Mutex::new(Counter { count: 0 }));
let h_counter = counter.clone();
let mut h = Handle::new(move || {
let mut c = h_counter.lock().unwrap();
c.incr();
});
h.wait();
h.wait();
assert_eq!(counter.lock().unwrap().count, 1);
}
#[test]
fn nursery_runs_handles() {
let counter = Arc::new(Mutex::new(Counter { count: 0 }));
let h_counter = counter.clone();
let h1 = Pending::new(move || {
let mut c = h_counter.lock().unwrap();
c.incr();
});
let h_counter = counter.clone();
let h2 = Pending::new(move || {
let mut c = h_counter.lock().unwrap();
c.incr();
});
let mut nursery = Nursery::new();
nursery.schedule(Box::new(h1));
nursery.schedule(Box::new(h2));
nursery.wait();
assert_eq!(counter.lock().unwrap().count, 2);
}
#[test]
fn child_nursery_runs_handles() {
let counter = Arc::new(Mutex::new(Counter { count: 0 }));
let h_counter = counter.clone();
let h1 = Pending::new(move || {
let mut c = h_counter.lock().unwrap();
c.incr();
});
let h_counter = counter.clone();
let h2 = Pending::new(move || {
let mut c = h_counter.lock().unwrap();
c.incr();
});
let mut child = Nursery::new();
child.schedule(Box::new(h1));
child.schedule(Box::new(h2));
let mut parent = Nursery::new();
parent.adopt(child.into());
parent.wait();
assert_eq!(counter.lock().unwrap().count, 2);
}
#[test]
fn nursery_wait_is_idempotent() {
let counter = Arc::new(Mutex::new(Counter { count: 0 }));
let h_counter = counter.clone();
let h1 = Pending::new(move || {
let mut c = h_counter.lock().unwrap();
c.incr();
});
let h_counter = counter.clone();
let h2 = Pending::new(move || {
let mut c = h_counter.lock().unwrap();
c.incr();
});
let mut nursery = Nursery::new();
nursery.schedule(Box::new(h1));
nursery.wait();
nursery.schedule(Box::new(h2));
nursery.wait();
nursery.wait();
assert_eq!(counter.lock().unwrap().count, 2);
}
#[test]
fn child_nursery_wait_is_idempotent() {
let counter = Arc::new(Mutex::new(Counter { count: 0 }));
let h_counter = counter.clone();
let h1 = Pending::new(move || {
let mut c = h_counter.lock().unwrap();
c.incr();
});
let h_counter = counter.clone();
let h2 = Pending::new(move || {
let mut c = h_counter.lock().unwrap();
c.incr();
});
let mut child = Nursery::new();
child.schedule(Box::new(h1));
child.schedule(Box::new(h2));
child.wait();
let mut parent = Nursery::new();
parent.adopt(child.into());
parent.wait();
assert_eq!(counter.lock().unwrap().count, 2);
}
#[test]
fn dropped_nurseries_wait_on_all_children() {
let counter = Arc::new(Mutex::new(Counter { count: 0 }));
{
let h_counter = counter.clone();
let h1 = Pending::new(move || {
let mut c = h_counter.lock().unwrap();
c.incr();
});
let h_counter = counter.clone();
let h2 = Pending::new(move || {
let mut c = h_counter.lock().unwrap();
c.incr();
});
let mut child = Nursery::new();
child.schedule(Box::new(h1));
child.schedule(Box::new(h2));
let mut parent = Nursery::new();
parent.adopt(child.into());
}
assert_eq!(counter.lock().unwrap().count, 2);
}