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