1 | use core::{ |
2 | cell::Cell, |
3 | sync::atomic::{AtomicUsize, Ordering::SeqCst}, |
4 | }; |
5 | |
6 | use once_cell::unsync::Lazy; |
7 | |
8 | #[test] |
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] |
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] |
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] |
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] |
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] |
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 | fn 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 |
127 | fn arrrrrrrrrrrrrrrrrrrrrr() { |
128 | let lazy: Lazy<&String, _>; |
129 | { |
130 | let s = String::new(); |
131 | lazy = Lazy::new(|| &s); |
132 | _ = *lazy; |
133 | } |
134 | } |
135 | |