4 use crate::panic::panic_any;
7 atomic::{AtomicBool, Ordering},
8 mpsc::{channel, Sender},
11 use crate::thread::{self, Scope, ThreadId};
12 use crate::time::Duration;
13 use crate::time::Instant;
15 // !!! These tests are dangerous. If something is buggy, they will hang, !!!
16 // !!! instead of exiting cleanly. This might wedge the buildbots. !!!
19 fn test_unnamed_thread() {
20 thread::spawn(move || {
21 assert!(thread::current().name().is_none());
25 .expect("thread panicked");
29 fn test_named_thread() {
31 .name("ada lovelace".to_string())
33 assert!(thread::current().name().unwrap() == "ada lovelace".to_string());
42 fn test_invalid_named_thread() {
43 let _ = Builder::new().name("ada l\0velace".to_string()).spawn(|| {});
48 let (tx, rx) = channel();
49 thread::spawn(move || {
56 fn test_is_finished() {
57 let b = Arc::new(Barrier::new(2));
58 let t = thread::spawn({
66 // Thread is definitely running here, since it's still waiting for the barrier.
67 assert_eq!(t.is_finished(), false);
69 // Unblock the barrier.
72 // Now check that t.is_finished() becomes true within a reasonable time.
73 let start = Instant::now();
74 while !t.is_finished() {
75 assert!(start.elapsed() < Duration::from_secs(2));
76 thread::sleep(Duration::from_millis(15));
79 // Joining the thread should not block for a significant time now.
80 let join_time = Instant::now();
81 assert_eq!(t.join().unwrap(), 1234);
82 assert!(join_time.elapsed() < Duration::from_secs(2));
86 fn test_join_panic() {
87 match thread::spawn(move || panic!()).join() {
88 result::Result::Err(_) => (),
89 result::Result::Ok(()) => panic!(),
94 fn test_spawn_sched() {
95 let (tx, rx) = channel();
97 fn f(i: i32, tx: Sender<()>) {
99 thread::spawn(move || {
101 tx.send(()).unwrap();
112 fn test_spawn_sched_childs_on_default_sched() {
113 let (tx, rx) = channel();
115 thread::spawn(move || {
116 thread::spawn(move || {
117 tx.send(()).unwrap();
124 fn avoid_copying_the_body<F>(spawnfn: F)
126 F: FnOnce(Box<dyn Fn() + Send>),
128 let (tx, rx) = channel();
130 let x: Box<_> = Box::new(1);
131 let x_in_parent = (&*x) as *const i32 as usize;
133 spawnfn(Box::new(move || {
134 let x_in_child = (&*x) as *const i32 as usize;
135 tx.send(x_in_child).unwrap();
138 let x_in_child = rx.recv().unwrap();
139 assert_eq!(x_in_parent, x_in_child);
143 fn test_avoid_copying_the_body_spawn() {
144 avoid_copying_the_body(|v| {
145 thread::spawn(move || v());
150 fn test_avoid_copying_the_body_thread_spawn() {
151 avoid_copying_the_body(|f| {
152 thread::spawn(move || {
159 fn test_avoid_copying_the_body_join() {
160 avoid_copying_the_body(|f| {
161 let _ = thread::spawn(move || f()).join();
166 fn test_child_doesnt_ref_parent() {
167 // If the child refcounts the parent thread, this will stack overflow when
168 // climbing the thread tree to dereference each ancestor. (See #1789)
169 // (well, it would if the constant were 8000+ - I lowered it to be more
170 // valgrind-friendly. try this at home, instead..!)
171 const GENERATIONS: u32 = 16;
172 fn child_no(x: u32) -> Box<dyn Fn() + Send> {
173 return Box::new(move || {
175 thread::spawn(move || child_no(x + 1)());
179 thread::spawn(|| child_no(0)());
183 fn test_simple_newsched_spawn() {
184 thread::spawn(move || {});
188 fn test_try_panic_message_string_literal() {
189 match thread::spawn(move || {
190 panic!("static string");
195 type T = &'static str;
196 assert!(e.is::<T>());
197 assert_eq!(*e.downcast::<T>().unwrap(), "static string");
204 fn test_try_panic_any_message_owned_str() {
205 match thread::spawn(move || {
206 panic_any("owned string".to_string());
212 assert!(e.is::<T>());
213 assert_eq!(*e.downcast::<T>().unwrap(), "owned string".to_string());
220 fn test_try_panic_any_message_any() {
221 match thread::spawn(move || {
222 panic_any(Box::new(413u16) as Box<dyn Any + Send>);
227 type T = Box<dyn Any + Send>;
228 assert!(e.is::<T>());
229 let any = e.downcast::<T>().unwrap();
230 assert!(any.is::<u16>());
231 assert_eq!(*any.downcast::<u16>().unwrap(), 413);
238 fn test_try_panic_any_message_unit_struct() {
241 match thread::spawn(move || panic_any(Juju)).join() {
242 Err(ref e) if e.is::<Juju>() => {}
243 Err(_) | Ok(()) => panic!(),
248 fn test_park_timeout_unpark_before() {
250 thread::current().unpark();
251 thread::park_timeout(Duration::from_millis(u32::MAX as u64));
256 fn test_park_timeout_unpark_not_called() {
258 thread::park_timeout(Duration::from_millis(10));
263 fn test_park_timeout_unpark_called_other_thread() {
265 let th = thread::current();
267 let _guard = thread::spawn(move || {
268 super::sleep(Duration::from_millis(50));
272 thread::park_timeout(Duration::from_millis(u32::MAX as u64));
277 fn sleep_ms_smoke() {
278 thread::sleep(Duration::from_millis(2));
282 fn test_size_of_option_thread_id() {
283 assert_eq!(mem::size_of::<Option<ThreadId>>(), mem::size_of::<ThreadId>());
287 fn test_thread_id_equal() {
288 assert!(thread::current().id() == thread::current().id());
292 fn test_thread_id_not_equal() {
293 let spawned_id = thread::spawn(|| thread::current().id()).join().unwrap();
294 assert!(thread::current().id() != spawned_id);
298 fn test_scoped_threads_drop_result_before_join() {
299 let actually_finished = &AtomicBool::new(false);
300 struct X<'scope, 'env>(&'scope Scope<'scope, 'env>, &'env AtomicBool);
301 impl Drop for X<'_, '_> {
303 thread::sleep(Duration::from_millis(20));
304 let actually_finished = self.1;
305 self.0.spawn(move || {
306 thread::sleep(Duration::from_millis(20));
307 actually_finished.store(true, Ordering::Relaxed);
313 thread::sleep(Duration::from_millis(20));
314 X(s, actually_finished)
317 assert!(actually_finished.load(Ordering::Relaxed));
321 fn test_scoped_threads_nll() {
322 // this is mostly a *compilation test* for this exact function:
328 // let's also run it for good measure