]> git.lizzy.rs Git - rust.git/blob - library/std/src/thread/tests.rs
Rollup merge of #76722 - ssomers:btree_send_sync, r=Mark-Simulacrum
[rust.git] / library / std / src / thread / tests.rs
1 use super::Builder;
2 use crate::any::Any;
3 use crate::mem;
4 use crate::result;
5 use crate::sync::mpsc::{channel, Sender};
6 use crate::thread::{self, ThreadId};
7 use crate::time::Duration;
8
9 // !!! These tests are dangerous. If something is buggy, they will hang, !!!
10 // !!! instead of exiting cleanly. This might wedge the buildbots.       !!!
11
12 #[test]
13 fn test_unnamed_thread() {
14     thread::spawn(move || {
15         assert!(thread::current().name().is_none());
16     })
17     .join()
18     .ok()
19     .expect("thread panicked");
20 }
21
22 #[test]
23 fn test_named_thread() {
24     Builder::new()
25         .name("ada lovelace".to_string())
26         .spawn(move || {
27             assert!(thread::current().name().unwrap() == "ada lovelace".to_string());
28         })
29         .unwrap()
30         .join()
31         .unwrap();
32 }
33
34 #[test]
35 #[should_panic]
36 fn test_invalid_named_thread() {
37     let _ = Builder::new().name("ada l\0velace".to_string()).spawn(|| {});
38 }
39
40 #[test]
41 fn test_run_basic() {
42     let (tx, rx) = channel();
43     thread::spawn(move || {
44         tx.send(()).unwrap();
45     });
46     rx.recv().unwrap();
47 }
48
49 #[test]
50 fn test_join_panic() {
51     match thread::spawn(move || panic!()).join() {
52         result::Result::Err(_) => (),
53         result::Result::Ok(()) => panic!(),
54     }
55 }
56
57 #[test]
58 fn test_spawn_sched() {
59     let (tx, rx) = channel();
60
61     fn f(i: i32, tx: Sender<()>) {
62         let tx = tx.clone();
63         thread::spawn(move || {
64             if i == 0 {
65                 tx.send(()).unwrap();
66             } else {
67                 f(i - 1, tx);
68             }
69         });
70     }
71     f(10, tx);
72     rx.recv().unwrap();
73 }
74
75 #[test]
76 fn test_spawn_sched_childs_on_default_sched() {
77     let (tx, rx) = channel();
78
79     thread::spawn(move || {
80         thread::spawn(move || {
81             tx.send(()).unwrap();
82         });
83     });
84
85     rx.recv().unwrap();
86 }
87
88 fn avoid_copying_the_body<F>(spawnfn: F)
89 where
90     F: FnOnce(Box<dyn Fn() + Send>),
91 {
92     let (tx, rx) = channel();
93
94     let x: Box<_> = box 1;
95     let x_in_parent = (&*x) as *const i32 as usize;
96
97     spawnfn(Box::new(move || {
98         let x_in_child = (&*x) as *const i32 as usize;
99         tx.send(x_in_child).unwrap();
100     }));
101
102     let x_in_child = rx.recv().unwrap();
103     assert_eq!(x_in_parent, x_in_child);
104 }
105
106 #[test]
107 fn test_avoid_copying_the_body_spawn() {
108     avoid_copying_the_body(|v| {
109         thread::spawn(move || v());
110     });
111 }
112
113 #[test]
114 fn test_avoid_copying_the_body_thread_spawn() {
115     avoid_copying_the_body(|f| {
116         thread::spawn(move || {
117             f();
118         });
119     })
120 }
121
122 #[test]
123 fn test_avoid_copying_the_body_join() {
124     avoid_copying_the_body(|f| {
125         let _ = thread::spawn(move || f()).join();
126     })
127 }
128
129 #[test]
130 fn test_child_doesnt_ref_parent() {
131     // If the child refcounts the parent thread, this will stack overflow when
132     // climbing the thread tree to dereference each ancestor. (See #1789)
133     // (well, it would if the constant were 8000+ - I lowered it to be more
134     // valgrind-friendly. try this at home, instead..!)
135     const GENERATIONS: u32 = 16;
136     fn child_no(x: u32) -> Box<dyn Fn() + Send> {
137         return Box::new(move || {
138             if x < GENERATIONS {
139                 thread::spawn(move || child_no(x + 1)());
140             }
141         });
142     }
143     thread::spawn(|| child_no(0)());
144 }
145
146 #[test]
147 fn test_simple_newsched_spawn() {
148     thread::spawn(move || {});
149 }
150
151 #[test]
152 fn test_try_panic_message_static_str() {
153     match thread::spawn(move || {
154         panic!("static string");
155     })
156     .join()
157     {
158         Err(e) => {
159             type T = &'static str;
160             assert!(e.is::<T>());
161             assert_eq!(*e.downcast::<T>().unwrap(), "static string");
162         }
163         Ok(()) => panic!(),
164     }
165 }
166
167 #[test]
168 fn test_try_panic_message_owned_str() {
169     match thread::spawn(move || {
170         panic!("owned string".to_string());
171     })
172     .join()
173     {
174         Err(e) => {
175             type T = String;
176             assert!(e.is::<T>());
177             assert_eq!(*e.downcast::<T>().unwrap(), "owned string".to_string());
178         }
179         Ok(()) => panic!(),
180     }
181 }
182
183 #[test]
184 fn test_try_panic_message_any() {
185     match thread::spawn(move || {
186         panic!(box 413u16 as Box<dyn Any + Send>);
187     })
188     .join()
189     {
190         Err(e) => {
191             type T = Box<dyn Any + Send>;
192             assert!(e.is::<T>());
193             let any = e.downcast::<T>().unwrap();
194             assert!(any.is::<u16>());
195             assert_eq!(*any.downcast::<u16>().unwrap(), 413);
196         }
197         Ok(()) => panic!(),
198     }
199 }
200
201 #[test]
202 fn test_try_panic_message_unit_struct() {
203     struct Juju;
204
205     match thread::spawn(move || panic!(Juju)).join() {
206         Err(ref e) if e.is::<Juju>() => {}
207         Err(_) | Ok(()) => panic!(),
208     }
209 }
210
211 #[test]
212 fn test_park_timeout_unpark_before() {
213     for _ in 0..10 {
214         thread::current().unpark();
215         thread::park_timeout(Duration::from_millis(u32::MAX as u64));
216     }
217 }
218
219 #[test]
220 fn test_park_timeout_unpark_not_called() {
221     for _ in 0..10 {
222         thread::park_timeout(Duration::from_millis(10));
223     }
224 }
225
226 #[test]
227 fn test_park_timeout_unpark_called_other_thread() {
228     for _ in 0..10 {
229         let th = thread::current();
230
231         let _guard = thread::spawn(move || {
232             super::sleep(Duration::from_millis(50));
233             th.unpark();
234         });
235
236         thread::park_timeout(Duration::from_millis(u32::MAX as u64));
237     }
238 }
239
240 #[test]
241 fn sleep_ms_smoke() {
242     thread::sleep(Duration::from_millis(2));
243 }
244
245 #[test]
246 fn test_size_of_option_thread_id() {
247     assert_eq!(mem::size_of::<Option<ThreadId>>(), mem::size_of::<ThreadId>());
248 }
249
250 #[test]
251 fn test_thread_id_equal() {
252     assert!(thread::current().id() == thread::current().id());
253 }
254
255 #[test]
256 fn test_thread_id_not_equal() {
257     let spawned_id = thread::spawn(|| thread::current().id()).join().unwrap();
258     assert!(thread::current().id() != spawned_id);
259 }
260
261 // NOTE: the corresponding test for stderr is in ui/thread-stderr, due
262 // to the test harness apparently interfering with stderr configuration.