blob: 597daaa749a06e2ec1f2e862b7bf1b7903926593 [file] [log] [blame]
use std::mem;
use std::any::Any;
use std::time::Duration;
use std::result;
use std::thread;
use std::panic;
use std::thread::Builder;
use std::thread::sleep;
use std::thread::ThreadId;
use std::boxed::Box;
use std::string::String;
use std::string::ToString;
use std::u32;
use std::sync::mpsc::{channel, Sender};
pub fn test_thread_unnamed_thread() {
thread::spawn(move|| {
assert!(thread::current().name().is_none());
}).join().ok().expect("thread panicked");
}
pub fn test_thread_named_thread() {
Builder::new().name("ada lovelace".to_string()).spawn(move|| {
assert!(thread::current().name().unwrap() == "ada lovelace".to_string());
}).unwrap().join().unwrap();
}
pub fn test_thread_run_basic(){
let (tx, rx) = channel();
thread::spawn(move|| {
tx.send(()).unwrap();
});
rx.recv().unwrap();
}
pub fn test_thread_spawn_sched() {
let (tx, rx) = channel();
fn f(i: i32, tx: Sender<()>) {
let tx = tx.clone();
thread::spawn(move|| {
if i == 0 {
tx.send(()).unwrap();
} else {
f(i - 1, tx);
}
});
}
f(9, tx);
rx.recv().unwrap();
}
pub fn test_thread_spawn_sched_childs_on_default_sched() {
let (tx, rx) = channel();
thread::spawn(move|| {
thread::spawn(move|| {
tx.send(()).unwrap();
});
});
rx.recv().unwrap();
}
fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Box<dyn Fn() + Send>) {
let (tx, rx) = channel();
let x: Box<_> = Box::new(1);
let x_in_parent = (&*x) as *const i32 as usize;
spawnfn(Box::new(move|| {
let x_in_child = (&*x) as *const i32 as usize;
tx.send(x_in_child).unwrap();
}));
let x_in_child = rx.recv().unwrap();
assert_eq!(x_in_parent, x_in_child);
}
pub fn test_thread_test_avoid_copying_the_body_spawn() {
avoid_copying_the_body(|v| {
thread::spawn(move || v());
});
}
pub fn test_thread_test_avoid_copying_the_body_thread_spawn() {
avoid_copying_the_body(|f| {
thread::spawn(move|| {
f();
});
})
}
pub fn test_thread_test_avoid_copying_the_body_join() {
avoid_copying_the_body(|f| {
let _ = thread::spawn(move|| {
f()
}).join();
})
}
pub fn test_thread_invalid_named_thread() {
should_panic!(Builder::new().name("ada l\0velace".to_string()).spawn(|| {}));
}
pub fn test_thread_join_panic() {
match thread::spawn(move|| {
panic!()
}).join() {
result::Result::Err(_) => (),
result::Result::Ok(()) => panic!()
}
}
pub fn test_thread_child_doesnt_ref_parent() {
// If the child refcounts the parent thread, this will stack overflow when
// climbing the thread tree to dereference each ancestor. (See #1789)
// (well, it would if the constant were 8000+ - I lowered it to be more
// valgrind-friendly. try this at home, instead..!)
const GENERATIONS: u32 = 16;
fn child_no(x: u32) -> Box<dyn Fn() + Send> {
return Box::new(move|| {
if x < GENERATIONS {
thread::spawn(move|| child_no(x+1)());
}
});
}
thread::spawn(|| child_no(0)());
}
pub fn test_thread_simple_newsched_spawn() {
let j = thread::spawn(move || {println!("test")});
let _res = j.join();
}
pub fn test_thread_try_panic_message_static_str() {
match thread::spawn(move|| {
panic!("static string");
}).join() {
Err(e) => {
type T = &'static str;
assert!(e.is::<T>());
assert_eq!(*e.downcast::<T>().unwrap(), "static string");
}
Ok(()) => panic!()
}
}
pub fn test_thread_try_panic_message_owned_str() {
match thread::spawn(move|| {
panic!("owned string".to_string());
}).join() {
Err(e) => {
type T = String;
assert!(e.is::<T>());
assert_eq!(*e.downcast::<T>().unwrap(), "owned string".to_string());
}
Ok(()) => panic!()
}
}
pub fn test_thread_try_panic_message_any() {
match thread::spawn(move|| {
panic!(Box::new(413u16) as Box<dyn Any + Send>);
}).join() {
Err(e) => {
type T = Box<dyn Any + Send>;
assert!(e.is::<T>());
let any = e.downcast::<T>().unwrap();
assert!(any.is::<u16>());
assert_eq!(*any.downcast::<u16>().unwrap(), 413);
}
Ok(()) => panic!()
}
}
pub fn test_thread_try_panic_message_unit_struct() {
struct Juju;
match thread::spawn(move|| {
panic!(Juju)
}).join() {
Err(ref e) if e.is::<Juju>() => {}
Err(_) | Ok(()) => panic!()
}
}
pub fn test_thread_park_timeout_unpark_before() {
for _ in 0..8 {
thread::current().unpark();
thread::park_timeout(Duration::from_millis(u32::MAX as u64));
}
}
pub fn test_thread_park_timeout_unpark_not_called() {
for i in 0..8{
println!("{:?} timeout in ", i);
thread::park_timeout(Duration::from_millis(1000));
println!("{:?} timeout", i);
}
}
pub fn test_thread_park_timeout_unpark_called_other_thread() {
for _ in 0..8 {
let th = thread::current();
let _guard = thread::spawn(move || {
sleep(Duration::from_millis(50));
println!("unpark");
th.unpark();
});
thread::park_timeout(Duration::from_millis(u32::MAX as u64));
}
}
pub fn test_thread_sleep_ms_smoke() {
thread::sleep(Duration::from_millis(10));
}
pub fn test_thread_size_of_option_thread_id() {
assert_eq!(mem::size_of::<Option<ThreadId>>(), mem::size_of::<ThreadId>());
}
pub fn test_thread_id_equal() {
assert!(thread::current().id() == thread::current().id());
}
pub fn test_thread_id_not_equal() {
let spawned_id = thread::spawn(|| thread::current().id()).join().unwrap();
assert!(thread::current().id() != spawned_id);
}