1 use core::{
2 cell::Cell,
3 sync::atomic::{AtomicUsize, Ordering::SeqCst},
4 };
5
6 use once_cell::unsync::Lazy;
7
8 #[test]
lazy_new()9 fn 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]
lazy_deref_mut()28 fn 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]
lazy_force_mut()47 fn 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]
lazy_get_mut()63 fn 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]
lazy_default()82 fn 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]
lazy_into_value()107 fn 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")]
117 #[cfg(not(target_os = "android"))]
lazy_poisoning()118 fn lazy_poisoning() {
119 let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
120 for _ in 0..2 {
121 let res = std::panic::catch_unwind(|| x.len());
122 assert!(res.is_err());
123 }
124 }
125
126 #[test]
127 // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669
arrrrrrrrrrrrrrrrrrrrrr()128 fn arrrrrrrrrrrrrrrrrrrrrr() {
129 let lazy: Lazy<&String, _>;
130 {
131 let s = String::new();
132 lazy = Lazy::new(|| &s);
133 _ = *lazy;
134 }
135 }
136