use super::Builder; use crate::any::Any; use crate::mem; use crate::result; use crate::sync::mpsc::{channel, Sender}; use crate::thread::{self, ThreadId}; use crate::time::Duration; // !!! These tests are dangerous. If something is buggy, they will hang, !!! // !!! instead of exiting cleanly. This might wedge the buildbots. !!! #[test] fn test_unnamed_thread() { thread::spawn(move || { assert!(thread::current().name().is_none()); }) .join() .ok() .expect("thread panicked"); } #[test] fn test_named_thread() { Builder::new() .name("ada lovelace".to_string()) .spawn(move || { assert!(thread::current().name().unwrap() == "ada lovelace".to_string()); }) .unwrap() .join() .unwrap(); } #[test] #[should_panic] fn test_invalid_named_thread() { let _ = Builder::new().name("ada l\0velace".to_string()).spawn(|| {}); } #[test] fn test_run_basic() { let (tx, rx) = channel(); thread::spawn(move || { tx.send(()).unwrap(); }); rx.recv().unwrap(); } #[test] fn test_join_panic() { match thread::spawn(move || panic!()).join() { result::Result::Err(_) => (), result::Result::Ok(()) => panic!(), } } #[test] fn test_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(10, tx); rx.recv().unwrap(); } #[test] fn test_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(spawnfn: F) where F: FnOnce(Box), { let (tx, rx) = channel(); let x: Box<_> = box 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); } #[test] fn test_avoid_copying_the_body_spawn() { avoid_copying_the_body(|v| { thread::spawn(move || v()); }); } #[test] fn test_avoid_copying_the_body_thread_spawn() { avoid_copying_the_body(|f| { thread::spawn(move || { f(); }); }) } #[test] fn test_avoid_copying_the_body_join() { avoid_copying_the_body(|f| { let _ = thread::spawn(move || f()).join(); }) } #[test] fn test_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 { return Box::new(move || { if x < GENERATIONS { thread::spawn(move || child_no(x + 1)()); } }); } thread::spawn(|| child_no(0)()); } #[test] fn test_simple_newsched_spawn() { thread::spawn(move || {}); } #[test] fn test_try_panic_message_static_str() { match thread::spawn(move || { panic!("static string"); }) .join() { Err(e) => { type T = &'static str; assert!(e.is::()); assert_eq!(*e.downcast::().unwrap(), "static string"); } Ok(()) => panic!(), } } #[test] fn test_try_panic_message_owned_str() { match thread::spawn(move || { panic!("owned string".to_string()); }) .join() { Err(e) => { type T = String; assert!(e.is::()); assert_eq!(*e.downcast::().unwrap(), "owned string".to_string()); } Ok(()) => panic!(), } } #[test] fn test_try_panic_message_any() { match thread::spawn(move || { panic!(box 413u16 as Box); }) .join() { Err(e) => { type T = Box; assert!(e.is::()); let any = e.downcast::().unwrap(); assert!(any.is::()); assert_eq!(*any.downcast::().unwrap(), 413); } Ok(()) => panic!(), } } #[test] fn test_try_panic_message_unit_struct() { struct Juju; match thread::spawn(move || panic!(Juju)).join() { Err(ref e) if e.is::() => {} Err(_) | Ok(()) => panic!(), } } #[test] fn test_park_timeout_unpark_before() { for _ in 0..10 { thread::current().unpark(); thread::park_timeout(Duration::from_millis(u32::MAX as u64)); } } #[test] fn test_park_timeout_unpark_not_called() { for _ in 0..10 { thread::park_timeout(Duration::from_millis(10)); } } #[test] fn test_park_timeout_unpark_called_other_thread() { for _ in 0..10 { let th = thread::current(); let _guard = thread::spawn(move || { super::sleep(Duration::from_millis(50)); th.unpark(); }); thread::park_timeout(Duration::from_millis(u32::MAX as u64)); } } #[test] fn sleep_ms_smoke() { thread::sleep(Duration::from_millis(2)); } #[test] fn test_size_of_option_thread_id() { assert_eq!(mem::size_of::>(), mem::size_of::()); } #[test] fn test_thread_id_equal() { assert!(thread::current().id() == thread::current().id()); } #[test] fn test_thread_id_not_equal() { let spawned_id = thread::spawn(|| thread::current().id()).join().unwrap(); assert!(thread::current().id() != spawned_id); } // NOTE: the corresponding test for stderr is in ui/thread-stderr, due // to the test harness apparently interfering with stderr configuration.