mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-11-03 22:49:17 +00:00 
			
		
		
		
	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);
 | 
						|
}
 |