• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![warn(rust_2018_idioms)]
2 #![cfg(feature = "full")]
3 
4 use std::mem;
5 use std::ops::Drop;
6 use std::sync::atomic::{AtomicU32, Ordering};
7 use tokio::sync::OnceCell;
8 
9 #[test]
drop_cell()10 fn drop_cell() {
11     static NUM_DROPS: AtomicU32 = AtomicU32::new(0);
12 
13     struct Foo {}
14 
15     let fooer = Foo {};
16 
17     impl Drop for Foo {
18         fn drop(&mut self) {
19             NUM_DROPS.fetch_add(1, Ordering::Release);
20         }
21     }
22 
23     {
24         let once_cell = OnceCell::new();
25         let prev = once_cell.set(fooer);
26         assert!(prev.is_ok())
27     }
28     assert!(NUM_DROPS.load(Ordering::Acquire) == 1);
29 }
30 
31 #[test]
drop_cell_new_with()32 fn drop_cell_new_with() {
33     static NUM_DROPS: AtomicU32 = AtomicU32::new(0);
34 
35     struct Foo {}
36 
37     let fooer = Foo {};
38 
39     impl Drop for Foo {
40         fn drop(&mut self) {
41             NUM_DROPS.fetch_add(1, Ordering::Release);
42         }
43     }
44 
45     {
46         let once_cell = OnceCell::new_with(Some(fooer));
47         assert!(once_cell.initialized());
48     }
49     assert!(NUM_DROPS.load(Ordering::Acquire) == 1);
50 }
51 
52 #[test]
drop_into_inner()53 fn drop_into_inner() {
54     static NUM_DROPS: AtomicU32 = AtomicU32::new(0);
55 
56     struct Foo {}
57 
58     let fooer = Foo {};
59 
60     impl Drop for Foo {
61         fn drop(&mut self) {
62             NUM_DROPS.fetch_add(1, Ordering::Release);
63         }
64     }
65 
66     let once_cell = OnceCell::new();
67     assert!(once_cell.set(fooer).is_ok());
68     let fooer = once_cell.into_inner();
69     let count = NUM_DROPS.load(Ordering::Acquire);
70     assert!(count == 0);
71     drop(fooer);
72     let count = NUM_DROPS.load(Ordering::Acquire);
73     assert!(count == 1);
74 }
75 
76 #[test]
drop_into_inner_new_with()77 fn drop_into_inner_new_with() {
78     static NUM_DROPS: AtomicU32 = AtomicU32::new(0);
79 
80     struct Foo {}
81 
82     let fooer = Foo {};
83 
84     impl Drop for Foo {
85         fn drop(&mut self) {
86             NUM_DROPS.fetch_add(1, Ordering::Release);
87         }
88     }
89 
90     let once_cell = OnceCell::new_with(Some(fooer));
91     let fooer = once_cell.into_inner();
92     let count = NUM_DROPS.load(Ordering::Acquire);
93     assert!(count == 0);
94     mem::drop(fooer);
95     let count = NUM_DROPS.load(Ordering::Acquire);
96     assert!(count == 1);
97 }
98 
99 #[test]
from()100 fn from() {
101     let cell = OnceCell::from(2);
102     assert_eq!(*cell.get().unwrap(), 2);
103 }
104 
105 #[cfg(feature = "parking_lot")]
106 mod parking_lot {
107     use super::*;
108 
109     use tokio::runtime;
110     use tokio::sync::SetError;
111     use tokio::time;
112 
113     use std::time::Duration;
114 
func1() -> u32115     async fn func1() -> u32 {
116         5
117     }
118 
func2() -> u32119     async fn func2() -> u32 {
120         time::sleep(Duration::from_millis(1)).await;
121         10
122     }
123 
func_err() -> Result<u32, ()>124     async fn func_err() -> Result<u32, ()> {
125         Err(())
126     }
127 
func_ok() -> Result<u32, ()>128     async fn func_ok() -> Result<u32, ()> {
129         Ok(10)
130     }
131 
func_panic() -> u32132     async fn func_panic() -> u32 {
133         time::sleep(Duration::from_millis(1)).await;
134         panic!();
135     }
136 
sleep_and_set() -> u32137     async fn sleep_and_set() -> u32 {
138         // Simulate sleep by pausing time and waiting for another thread to
139         // resume clock when calling `set`, then finding the cell being initialized
140         // by this call
141         time::sleep(Duration::from_millis(2)).await;
142         5
143     }
144 
advance_time_and_set( cell: &'static OnceCell<u32>, v: u32, ) -> Result<(), SetError<u32>>145     async fn advance_time_and_set(
146         cell: &'static OnceCell<u32>,
147         v: u32,
148     ) -> Result<(), SetError<u32>> {
149         time::advance(Duration::from_millis(1)).await;
150         cell.set(v)
151     }
152 
153     #[test]
get_or_init()154     fn get_or_init() {
155         let rt = runtime::Builder::new_current_thread()
156             .enable_time()
157             .start_paused(true)
158             .build()
159             .unwrap();
160 
161         static ONCE: OnceCell<u32> = OnceCell::const_new();
162 
163         rt.block_on(async {
164             let handle1 = rt.spawn(async { ONCE.get_or_init(func1).await });
165             let handle2 = rt.spawn(async { ONCE.get_or_init(func2).await });
166 
167             time::advance(Duration::from_millis(1)).await;
168             time::resume();
169 
170             let result1 = handle1.await.unwrap();
171             let result2 = handle2.await.unwrap();
172 
173             assert_eq!(*result1, 5);
174             assert_eq!(*result2, 5);
175         });
176     }
177 
178     #[test]
get_or_init_panic()179     fn get_or_init_panic() {
180         let rt = runtime::Builder::new_current_thread()
181             .enable_time()
182             .build()
183             .unwrap();
184 
185         static ONCE: OnceCell<u32> = OnceCell::const_new();
186 
187         rt.block_on(async {
188             time::pause();
189 
190             let handle1 = rt.spawn(async { ONCE.get_or_init(func1).await });
191             let handle2 = rt.spawn(async { ONCE.get_or_init(func_panic).await });
192 
193             time::advance(Duration::from_millis(1)).await;
194 
195             let result1 = handle1.await.unwrap();
196             let result2 = handle2.await.unwrap();
197 
198             assert_eq!(*result1, 5);
199             assert_eq!(*result2, 5);
200         });
201     }
202 
203     #[test]
set_and_get()204     fn set_and_get() {
205         let rt = runtime::Builder::new_current_thread()
206             .enable_time()
207             .build()
208             .unwrap();
209 
210         static ONCE: OnceCell<u32> = OnceCell::const_new();
211 
212         rt.block_on(async {
213             let _ = rt.spawn(async { ONCE.set(5) }).await;
214             let value = ONCE.get().unwrap();
215             assert_eq!(*value, 5);
216         });
217     }
218 
219     #[test]
get_uninit()220     fn get_uninit() {
221         static ONCE: OnceCell<u32> = OnceCell::const_new();
222         let uninit = ONCE.get();
223         assert!(uninit.is_none());
224     }
225 
226     #[test]
set_twice()227     fn set_twice() {
228         static ONCE: OnceCell<u32> = OnceCell::const_new();
229 
230         let first = ONCE.set(5);
231         assert_eq!(first, Ok(()));
232         let second = ONCE.set(6);
233         assert!(second.err().unwrap().is_already_init_err());
234     }
235 
236     #[test]
set_while_initializing()237     fn set_while_initializing() {
238         let rt = runtime::Builder::new_current_thread()
239             .enable_time()
240             .build()
241             .unwrap();
242 
243         static ONCE: OnceCell<u32> = OnceCell::const_new();
244 
245         rt.block_on(async {
246             time::pause();
247 
248             let handle1 = rt.spawn(async { ONCE.get_or_init(sleep_and_set).await });
249             let handle2 = rt.spawn(async { advance_time_and_set(&ONCE, 10).await });
250 
251             time::advance(Duration::from_millis(2)).await;
252 
253             let result1 = handle1.await.unwrap();
254             let result2 = handle2.await.unwrap();
255 
256             assert_eq!(*result1, 5);
257             assert!(result2.err().unwrap().is_initializing_err());
258         });
259     }
260 
261     #[test]
get_or_try_init()262     fn get_or_try_init() {
263         let rt = runtime::Builder::new_current_thread()
264             .enable_time()
265             .start_paused(true)
266             .build()
267             .unwrap();
268 
269         static ONCE: OnceCell<u32> = OnceCell::const_new();
270 
271         rt.block_on(async {
272             let handle1 = rt.spawn(async { ONCE.get_or_try_init(func_err).await });
273             let handle2 = rt.spawn(async { ONCE.get_or_try_init(func_ok).await });
274 
275             time::advance(Duration::from_millis(1)).await;
276             time::resume();
277 
278             let result1 = handle1.await.unwrap();
279             assert!(result1.is_err());
280 
281             let result2 = handle2.await.unwrap();
282             assert_eq!(*result2.unwrap(), 10);
283         });
284     }
285 }
286