std: move "mod tests/benches" to separate files
Also doing fmt inplace as requested.
This commit is contained in:
parent
db6cbfc49c
commit
a4e926daee
120 changed files with 16569 additions and 16699 deletions
|
@ -2,6 +2,12 @@
|
|||
|
||||
#![unstable(feature = "thread_local_internals", issue = "none")]
|
||||
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
mod tests;
|
||||
|
||||
#[cfg(test)]
|
||||
mod dynamic_tests;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::fmt;
|
||||
|
||||
|
@ -547,203 +553,3 @@ pub mod os {
|
|||
key.os.set(ptr::null_mut());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
mod tests {
|
||||
use crate::cell::{Cell, UnsafeCell};
|
||||
use crate::sync::mpsc::{channel, Sender};
|
||||
use crate::thread;
|
||||
|
||||
struct Foo(Sender<()>);
|
||||
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
let Foo(ref s) = *self;
|
||||
s.send(()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke_no_dtor() {
|
||||
thread_local!(static FOO: Cell<i32> = Cell::new(1));
|
||||
|
||||
FOO.with(|f| {
|
||||
assert_eq!(f.get(), 1);
|
||||
f.set(2);
|
||||
});
|
||||
let (tx, rx) = channel();
|
||||
let _t = thread::spawn(move || {
|
||||
FOO.with(|f| {
|
||||
assert_eq!(f.get(), 1);
|
||||
});
|
||||
tx.send(()).unwrap();
|
||||
});
|
||||
rx.recv().unwrap();
|
||||
|
||||
FOO.with(|f| {
|
||||
assert_eq!(f.get(), 2);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn states() {
|
||||
struct Foo;
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
assert!(FOO.try_with(|_| ()).is_err());
|
||||
}
|
||||
}
|
||||
thread_local!(static FOO: Foo = Foo);
|
||||
|
||||
thread::spawn(|| {
|
||||
assert!(FOO.try_with(|_| ()).is_ok());
|
||||
})
|
||||
.join()
|
||||
.ok()
|
||||
.expect("thread panicked");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke_dtor() {
|
||||
thread_local!(static FOO: UnsafeCell<Option<Foo>> = UnsafeCell::new(None));
|
||||
|
||||
let (tx, rx) = channel();
|
||||
let _t = thread::spawn(move || unsafe {
|
||||
let mut tx = Some(tx);
|
||||
FOO.with(|f| {
|
||||
*f.get() = Some(Foo(tx.take().unwrap()));
|
||||
});
|
||||
});
|
||||
rx.recv().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn circular() {
|
||||
struct S1;
|
||||
struct S2;
|
||||
thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
|
||||
thread_local!(static K2: UnsafeCell<Option<S2>> = UnsafeCell::new(None));
|
||||
static mut HITS: u32 = 0;
|
||||
|
||||
impl Drop for S1 {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
HITS += 1;
|
||||
if K2.try_with(|_| ()).is_err() {
|
||||
assert_eq!(HITS, 3);
|
||||
} else {
|
||||
if HITS == 1 {
|
||||
K2.with(|s| *s.get() = Some(S2));
|
||||
} else {
|
||||
assert_eq!(HITS, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Drop for S2 {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
HITS += 1;
|
||||
assert!(K1.try_with(|_| ()).is_ok());
|
||||
assert_eq!(HITS, 2);
|
||||
K1.with(|s| *s.get() = Some(S1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thread::spawn(move || {
|
||||
drop(S1);
|
||||
})
|
||||
.join()
|
||||
.ok()
|
||||
.expect("thread panicked");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn self_referential() {
|
||||
struct S1;
|
||||
thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
|
||||
|
||||
impl Drop for S1 {
|
||||
fn drop(&mut self) {
|
||||
assert!(K1.try_with(|_| ()).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
thread::spawn(move || unsafe {
|
||||
K1.with(|s| *s.get() = Some(S1));
|
||||
})
|
||||
.join()
|
||||
.ok()
|
||||
.expect("thread panicked");
|
||||
}
|
||||
|
||||
// Note that this test will deadlock if TLS destructors aren't run (this
|
||||
// requires the destructor to be run to pass the test).
|
||||
#[test]
|
||||
fn dtors_in_dtors_in_dtors() {
|
||||
struct S1(Sender<()>);
|
||||
thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
|
||||
thread_local!(static K2: UnsafeCell<Option<Foo>> = UnsafeCell::new(None));
|
||||
|
||||
impl Drop for S1 {
|
||||
fn drop(&mut self) {
|
||||
let S1(ref tx) = *self;
|
||||
unsafe {
|
||||
let _ = K2.try_with(|s| *s.get() = Some(Foo(tx.clone())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (tx, rx) = channel();
|
||||
let _t = thread::spawn(move || unsafe {
|
||||
let mut tx = Some(tx);
|
||||
K1.with(|s| *s.get() = Some(S1(tx.take().unwrap())));
|
||||
});
|
||||
rx.recv().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod dynamic_tests {
|
||||
use crate::cell::RefCell;
|
||||
use crate::collections::HashMap;
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
||||
fn square(i: i32) -> i32 {
|
||||
i * i
|
||||
}
|
||||
thread_local!(static FOO: i32 = square(3));
|
||||
|
||||
FOO.with(|f| {
|
||||
assert_eq!(*f, 9);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hashmap() {
|
||||
fn map() -> RefCell<HashMap<i32, i32>> {
|
||||
let mut m = HashMap::new();
|
||||
m.insert(1, 2);
|
||||
RefCell::new(m)
|
||||
}
|
||||
thread_local!(static FOO: RefCell<HashMap<i32, i32>> = map());
|
||||
|
||||
FOO.with(|map| {
|
||||
assert_eq!(map.borrow()[&1], 2);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refcell_vec() {
|
||||
thread_local!(static FOO: RefCell<Vec<u32>> = RefCell::new(vec![1, 2, 3]));
|
||||
|
||||
FOO.with(|vec| {
|
||||
assert_eq!(vec.borrow().len(), 3);
|
||||
vec.borrow_mut().push(4);
|
||||
assert_eq!(vec.borrow()[3], 4);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
40
library/std/src/thread/local/dynamic_tests.rs
Normal file
40
library/std/src/thread/local/dynamic_tests.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use crate::cell::RefCell;
|
||||
use crate::collections::HashMap;
|
||||
use crate::thread_local;
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
||||
fn square(i: i32) -> i32 {
|
||||
i * i
|
||||
}
|
||||
thread_local!(static FOO: i32 = square(3));
|
||||
|
||||
FOO.with(|f| {
|
||||
assert_eq!(*f, 9);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hashmap() {
|
||||
fn map() -> RefCell<HashMap<i32, i32>> {
|
||||
let mut m = HashMap::new();
|
||||
m.insert(1, 2);
|
||||
RefCell::new(m)
|
||||
}
|
||||
thread_local!(static FOO: RefCell<HashMap<i32, i32>> = map());
|
||||
|
||||
FOO.with(|map| {
|
||||
assert_eq!(map.borrow()[&1], 2);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refcell_vec() {
|
||||
thread_local!(static FOO: RefCell<Vec<u32>> = RefCell::new(vec![1, 2, 3]));
|
||||
|
||||
FOO.with(|vec| {
|
||||
assert_eq!(vec.borrow().len(), 3);
|
||||
vec.borrow_mut().push(4);
|
||||
assert_eq!(vec.borrow()[3], 4);
|
||||
});
|
||||
}
|
154
library/std/src/thread/local/tests.rs
Normal file
154
library/std/src/thread/local/tests.rs
Normal file
|
@ -0,0 +1,154 @@
|
|||
use crate::cell::{Cell, UnsafeCell};
|
||||
use crate::sync::mpsc::{channel, Sender};
|
||||
use crate::thread;
|
||||
use crate::thread_local;
|
||||
|
||||
struct Foo(Sender<()>);
|
||||
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
let Foo(ref s) = *self;
|
||||
s.send(()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke_no_dtor() {
|
||||
thread_local!(static FOO: Cell<i32> = Cell::new(1));
|
||||
|
||||
FOO.with(|f| {
|
||||
assert_eq!(f.get(), 1);
|
||||
f.set(2);
|
||||
});
|
||||
let (tx, rx) = channel();
|
||||
let _t = thread::spawn(move || {
|
||||
FOO.with(|f| {
|
||||
assert_eq!(f.get(), 1);
|
||||
});
|
||||
tx.send(()).unwrap();
|
||||
});
|
||||
rx.recv().unwrap();
|
||||
|
||||
FOO.with(|f| {
|
||||
assert_eq!(f.get(), 2);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn states() {
|
||||
struct Foo;
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
assert!(FOO.try_with(|_| ()).is_err());
|
||||
}
|
||||
}
|
||||
thread_local!(static FOO: Foo = Foo);
|
||||
|
||||
thread::spawn(|| {
|
||||
assert!(FOO.try_with(|_| ()).is_ok());
|
||||
})
|
||||
.join()
|
||||
.ok()
|
||||
.expect("thread panicked");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke_dtor() {
|
||||
thread_local!(static FOO: UnsafeCell<Option<Foo>> = UnsafeCell::new(None));
|
||||
|
||||
let (tx, rx) = channel();
|
||||
let _t = thread::spawn(move || unsafe {
|
||||
let mut tx = Some(tx);
|
||||
FOO.with(|f| {
|
||||
*f.get() = Some(Foo(tx.take().unwrap()));
|
||||
});
|
||||
});
|
||||
rx.recv().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn circular() {
|
||||
struct S1;
|
||||
struct S2;
|
||||
thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
|
||||
thread_local!(static K2: UnsafeCell<Option<S2>> = UnsafeCell::new(None));
|
||||
static mut HITS: u32 = 0;
|
||||
|
||||
impl Drop for S1 {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
HITS += 1;
|
||||
if K2.try_with(|_| ()).is_err() {
|
||||
assert_eq!(HITS, 3);
|
||||
} else {
|
||||
if HITS == 1 {
|
||||
K2.with(|s| *s.get() = Some(S2));
|
||||
} else {
|
||||
assert_eq!(HITS, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Drop for S2 {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
HITS += 1;
|
||||
assert!(K1.try_with(|_| ()).is_ok());
|
||||
assert_eq!(HITS, 2);
|
||||
K1.with(|s| *s.get() = Some(S1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thread::spawn(move || {
|
||||
drop(S1);
|
||||
})
|
||||
.join()
|
||||
.ok()
|
||||
.expect("thread panicked");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn self_referential() {
|
||||
struct S1;
|
||||
thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
|
||||
|
||||
impl Drop for S1 {
|
||||
fn drop(&mut self) {
|
||||
assert!(K1.try_with(|_| ()).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
thread::spawn(move || unsafe {
|
||||
K1.with(|s| *s.get() = Some(S1));
|
||||
})
|
||||
.join()
|
||||
.ok()
|
||||
.expect("thread panicked");
|
||||
}
|
||||
|
||||
// Note that this test will deadlock if TLS destructors aren't run (this
|
||||
// requires the destructor to be run to pass the test).
|
||||
#[test]
|
||||
fn dtors_in_dtors_in_dtors() {
|
||||
struct S1(Sender<()>);
|
||||
thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
|
||||
thread_local!(static K2: UnsafeCell<Option<Foo>> = UnsafeCell::new(None));
|
||||
|
||||
impl Drop for S1 {
|
||||
fn drop(&mut self) {
|
||||
let S1(ref tx) = *self;
|
||||
unsafe {
|
||||
let _ = K2.try_with(|s| *s.get() = Some(Foo(tx.clone())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (tx, rx) = channel();
|
||||
let _t = thread::spawn(move || unsafe {
|
||||
let mut tx = Some(tx);
|
||||
K1.with(|s| *s.get() = Some(S1(tx.take().unwrap())));
|
||||
});
|
||||
rx.recv().unwrap();
|
||||
}
|
|
@ -145,6 +145,9 @@
|
|||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
mod tests;
|
||||
|
||||
use crate::any::Any;
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::ffi::{CStr, CString};
|
||||
|
@ -1470,273 +1473,3 @@ fn _assert_sync_and_send() {
|
|||
_assert_both::<JoinHandle<()>>();
|
||||
_assert_both::<Thread>();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Tests
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
mod tests {
|
||||
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<F>(spawnfn: F)
|
||||
where
|
||||
F: FnOnce(Box<dyn Fn() + Send>),
|
||||
{
|
||||
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<dyn Fn() + Send> {
|
||||
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::<T>());
|
||||
assert_eq!(*e.downcast::<T>().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::<T>());
|
||||
assert_eq!(*e.downcast::<T>().unwrap(), "owned string".to_string());
|
||||
}
|
||||
Ok(()) => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_panic_message_any() {
|
||||
match thread::spawn(move || {
|
||||
panic!(box 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!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_panic_message_unit_struct() {
|
||||
struct Juju;
|
||||
|
||||
match thread::spawn(move || panic!(Juju)).join() {
|
||||
Err(ref e) if e.is::<Juju>() => {}
|
||||
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::<Option<ThreadId>>(), mem::size_of::<ThreadId>());
|
||||
}
|
||||
|
||||
#[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.
|
||||
}
|
||||
|
|
262
library/std/src/thread/tests.rs
Normal file
262
library/std/src/thread/tests.rs
Normal file
|
@ -0,0 +1,262 @@
|
|||
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<F>(spawnfn: F)
|
||||
where
|
||||
F: FnOnce(Box<dyn Fn() + Send>),
|
||||
{
|
||||
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<dyn Fn() + Send> {
|
||||
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::<T>());
|
||||
assert_eq!(*e.downcast::<T>().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::<T>());
|
||||
assert_eq!(*e.downcast::<T>().unwrap(), "owned string".to_string());
|
||||
}
|
||||
Ok(()) => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_panic_message_any() {
|
||||
match thread::spawn(move || {
|
||||
panic!(box 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!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_panic_message_unit_struct() {
|
||||
struct Juju;
|
||||
|
||||
match thread::spawn(move || panic!(Juju)).join() {
|
||||
Err(ref e) if e.is::<Juju>() => {}
|
||||
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::<Option<ThreadId>>(), mem::size_of::<ThreadId>());
|
||||
}
|
||||
|
||||
#[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.
|
Loading…
Add table
Add a link
Reference in a new issue