blob: 21ef4e7fc8bac7b1b40ecbea1b9d46035f9f17f2 [file] [log] [blame]
use std::any::Any;
use std::boxed::Box;
use std::mem;
use std::panic;
use std::result;
use std::string::String;
use std::string::ToString;
use std::sync::mpsc::{channel, Sender};
use std::thread;
use std::thread::sleep;
use std::thread::Builder;
use std::thread::ThreadId;
use std::time::Duration;
use std::u32;
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::panic_any("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::panic_any(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::panic_any(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);
}