mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-30 20:44:34 +00:00 
			
		
		
		
	 b8ae372e48
			
		
	
	
		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);
 | |
| }
 |