mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-28 11:17:26 +03:00
b8ae372e48
This removes two minor OnceLock tests which test private methods. The rest of the tests should be more than enough to catch mistakes in those private methods. Also makes ReentrantLock::try_lock public. And finally it makes the mpmc tests actually run.
168 lines
4.0 KiB
Rust
168 lines
4.0 KiB
Rust
use std::cell::LazyCell;
|
|
use std::sync::atomic::AtomicUsize;
|
|
use std::sync::atomic::Ordering::SeqCst;
|
|
use std::sync::{LazyLock, Mutex, OnceLock};
|
|
use std::{panic, 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]
|
|
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
|
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(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
|
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(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
|
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]
|
|
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
|
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());
|
|
}
|
|
}
|
|
|
|
// Check that we can infer `T` from closure's type.
|
|
#[test]
|
|
fn lazy_type_inference() {
|
|
let _ = LazyCell::new(|| ());
|
|
}
|
|
|
|
#[test]
|
|
fn is_sync_send() {
|
|
fn assert_traits<T: Send + Sync>() {}
|
|
assert_traits::<LazyLock<String>>();
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic = "has previously been poisoned"]
|
|
fn lazy_force_mut_panic() {
|
|
let mut lazy = LazyLock::<String>::new(|| panic!());
|
|
panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
|
let _ = LazyLock::force_mut(&mut lazy);
|
|
}))
|
|
.unwrap_err();
|
|
let _ = &*lazy;
|
|
}
|
|
|
|
#[test]
|
|
fn lazy_force_mut() {
|
|
let s = "abc".to_owned();
|
|
let mut lazy = LazyLock::new(move || s);
|
|
LazyLock::force_mut(&mut lazy);
|
|
let p = LazyLock::force_mut(&mut lazy);
|
|
p.clear();
|
|
LazyLock::force_mut(&mut lazy);
|
|
}
|