summaryrefslogtreecommitdiffstats
path: root/library/std/src/sync/lazy_lock/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/std/src/sync/lazy_lock/tests.rs143
1 files changed, 143 insertions, 0 deletions
diff --git a/library/std/src/sync/lazy_lock/tests.rs b/library/std/src/sync/lazy_lock/tests.rs
new file mode 100644
index 000000000..f11b66bfc
--- /dev/null
+++ b/library/std/src/sync/lazy_lock/tests.rs
@@ -0,0 +1,143 @@
+use crate::{
+ cell::LazyCell,
+ panic,
+ sync::{
+ atomic::{AtomicUsize, Ordering::SeqCst},
+ Mutex,
+ },
+ sync::{LazyLock, OnceLock},
+ thread,
+};
+
+fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
+ thread::spawn(f).join().unwrap()
+}
+
+#[test]
+fn lazy_default() {
+ static CALLED: AtomicUsize = AtomicUsize::new(0);
+
+ struct Foo(u8);
+ impl Default for Foo {
+ fn default() -> Self {
+ CALLED.fetch_add(1, SeqCst);
+ Foo(42)
+ }
+ }
+
+ let lazy: LazyCell<Mutex<Foo>> = <_>::default();
+
+ assert_eq!(CALLED.load(SeqCst), 0);
+
+ assert_eq!(lazy.lock().unwrap().0, 42);
+ assert_eq!(CALLED.load(SeqCst), 1);
+
+ lazy.lock().unwrap().0 = 21;
+
+ assert_eq!(lazy.lock().unwrap().0, 21);
+ assert_eq!(CALLED.load(SeqCst), 1);
+}
+
+#[test]
+fn lazy_poisoning() {
+ let x: LazyCell<String> = LazyCell::new(|| panic!("kaboom"));
+ for _ in 0..2 {
+ let res = panic::catch_unwind(panic::AssertUnwindSafe(|| x.len()));
+ assert!(res.is_err());
+ }
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn sync_lazy_new() {
+ static CALLED: AtomicUsize = AtomicUsize::new(0);
+ static SYNC_LAZY: LazyLock<i32> = LazyLock::new(|| {
+ CALLED.fetch_add(1, SeqCst);
+ 92
+ });
+
+ assert_eq!(CALLED.load(SeqCst), 0);
+
+ spawn_and_wait(|| {
+ let y = *SYNC_LAZY - 30;
+ assert_eq!(y, 62);
+ assert_eq!(CALLED.load(SeqCst), 1);
+ });
+
+ let y = *SYNC_LAZY - 30;
+ assert_eq!(y, 62);
+ assert_eq!(CALLED.load(SeqCst), 1);
+}
+
+#[test]
+fn sync_lazy_default() {
+ static CALLED: AtomicUsize = AtomicUsize::new(0);
+
+ struct Foo(u8);
+ impl Default for Foo {
+ fn default() -> Self {
+ CALLED.fetch_add(1, SeqCst);
+ Foo(42)
+ }
+ }
+
+ let lazy: LazyLock<Mutex<Foo>> = <_>::default();
+
+ assert_eq!(CALLED.load(SeqCst), 0);
+
+ assert_eq!(lazy.lock().unwrap().0, 42);
+ assert_eq!(CALLED.load(SeqCst), 1);
+
+ lazy.lock().unwrap().0 = 21;
+
+ assert_eq!(lazy.lock().unwrap().0, 21);
+ assert_eq!(CALLED.load(SeqCst), 1);
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn static_sync_lazy() {
+ static XS: LazyLock<Vec<i32>> = LazyLock::new(|| {
+ let mut xs = Vec::new();
+ xs.push(1);
+ xs.push(2);
+ xs.push(3);
+ xs
+ });
+
+ spawn_and_wait(|| {
+ assert_eq!(&*XS, &vec![1, 2, 3]);
+ });
+
+ assert_eq!(&*XS, &vec![1, 2, 3]);
+}
+
+#[test]
+fn static_sync_lazy_via_fn() {
+ fn xs() -> &'static Vec<i32> {
+ static XS: OnceLock<Vec<i32>> = OnceLock::new();
+ XS.get_or_init(|| {
+ let mut xs = Vec::new();
+ xs.push(1);
+ xs.push(2);
+ xs.push(3);
+ xs
+ })
+ }
+ assert_eq!(xs(), &vec![1, 2, 3]);
+}
+
+#[test]
+fn sync_lazy_poisoning() {
+ let x: LazyLock<String> = LazyLock::new(|| panic!("kaboom"));
+ for _ in 0..2 {
+ let res = panic::catch_unwind(|| x.len());
+ assert!(res.is_err());
+ }
+}
+
+#[test]
+fn is_sync_send() {
+ fn assert_traits<T: Send + Sync>() {}
+ assert_traits::<LazyLock<String>>();
+}