about summary refs log tree commit diff
path: root/library/std/src/thread/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/thread/tests.rs')
-rw-r--r--library/std/src/thread/tests.rs262
1 files changed, 262 insertions, 0 deletions
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
new file mode 100644
index 00000000000..16ad366fc12
--- /dev/null
+++ b/library/std/src/thread/tests.rs
@@ -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.