1use core::{
2 cell::Cell,
3 sync::atomic::{AtomicUsize, Ordering::SeqCst},
4};
5
6use once_cell::unsync::Lazy;
7
8#[test]
9fn lazy_new() {
10 let called = Cell::new(0);
11 let x = Lazy::new(|| {
12 called.set(called.get() + 1);
13 92
14 });
15
16 assert_eq!(called.get(), 0);
17
18 let y = *x - 30;
19 assert_eq!(y, 62);
20 assert_eq!(called.get(), 1);
21
22 let y = *x - 30;
23 assert_eq!(y, 62);
24 assert_eq!(called.get(), 1);
25}
26
27#[test]
28fn lazy_deref_mut() {
29 let called = Cell::new(0);
30 let mut x = Lazy::new(|| {
31 called.set(called.get() + 1);
32 92
33 });
34
35 assert_eq!(called.get(), 0);
36
37 let y = *x - 30;
38 assert_eq!(y, 62);
39 assert_eq!(called.get(), 1);
40
41 *x /= 2;
42 assert_eq!(*x, 46);
43 assert_eq!(called.get(), 1);
44}
45
46#[test]
47fn lazy_force_mut() {
48 let called = Cell::new(0);
49 let mut x = Lazy::new(|| {
50 called.set(called.get() + 1);
51 92
52 });
53 assert_eq!(called.get(), 0);
54 let v = Lazy::force_mut(&mut x);
55 assert_eq!(called.get(), 1);
56
57 *v /= 2;
58 assert_eq!(*x, 46);
59 assert_eq!(called.get(), 1);
60}
61
62#[test]
63fn lazy_get_mut() {
64 let called = Cell::new(0);
65 let mut x: Lazy<u32, _> = Lazy::new(|| {
66 called.set(called.get() + 1);
67 92
68 });
69
70 assert_eq!(called.get(), 0);
71 assert_eq!(*x, 92);
72
73 let mut_ref: &mut u32 = Lazy::get_mut(&mut x).unwrap();
74 assert_eq!(called.get(), 1);
75
76 *mut_ref /= 2;
77 assert_eq!(*x, 46);
78 assert_eq!(called.get(), 1);
79}
80
81#[test]
82fn lazy_default() {
83 static CALLED: AtomicUsize = AtomicUsize::new(0);
84
85 struct Foo(u8);
86 impl Default for Foo {
87 fn default() -> Self {
88 CALLED.fetch_add(1, SeqCst);
89 Foo(42)
90 }
91 }
92
93 let lazy: Lazy<std::sync::Mutex<Foo>> = <_>::default();
94
95 assert_eq!(CALLED.load(SeqCst), 0);
96
97 assert_eq!(lazy.lock().unwrap().0, 42);
98 assert_eq!(CALLED.load(SeqCst), 1);
99
100 lazy.lock().unwrap().0 = 21;
101
102 assert_eq!(lazy.lock().unwrap().0, 21);
103 assert_eq!(CALLED.load(SeqCst), 1);
104}
105
106#[test]
107fn lazy_into_value() {
108 let l: Lazy<i32, _> = Lazy::new(|| panic!());
109 assert!(matches!(Lazy::into_value(l), Err(_)));
110 let l = Lazy::new(|| -> i32 { 92 });
111 Lazy::force(&l);
112 assert!(matches!(Lazy::into_value(l), Ok(92)));
113}
114
115#[test]
116#[cfg(feature = "std")]
117fn lazy_poisoning() {
118 let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
119 for _ in 0..2 {
120 let res = std::panic::catch_unwind(|| x.len());
121 assert!(res.is_err());
122 }
123}
124
125#[test]
126// https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669
127fn arrrrrrrrrrrrrrrrrrrrrr() {
128 let lazy: Lazy<&String, _>;
129 {
130 let s = String::new();
131 lazy = Lazy::new(|| &s);
132 _ = *lazy;
133 }
134}
135