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