]> git.proxmox.com Git - rustc.git/blame - vendor/once_cell/tests/it.rs
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / vendor / once_cell / tests / it.rs
CommitLineData
e1599b0c
XL
1mod unsync {
2 use core::{
3 cell::Cell,
4 sync::atomic::{AtomicUsize, Ordering::SeqCst},
5 };
6
7 use once_cell::unsync::{Lazy, OnceCell};
8
9 #[test]
10 fn once_cell() {
11 let c = OnceCell::new();
12 assert!(c.get().is_none());
13 c.get_or_init(|| 92);
14 assert_eq!(c.get(), Some(&92));
15
16 c.get_or_init(|| panic!("Kabom!"));
17 assert_eq!(c.get(), Some(&92));
18 }
19
20 #[test]
21 fn once_cell_get_mut() {
22 let mut c = OnceCell::new();
23 assert!(c.get_mut().is_none());
24 c.set(90).unwrap();
25 *c.get_mut().unwrap() += 2;
26 assert_eq!(c.get_mut(), Some(&mut 92));
27 }
28
29 #[test]
30 fn once_cell_drop() {
31 static DROP_CNT: AtomicUsize = AtomicUsize::new(0);
32 struct Dropper;
33 impl Drop for Dropper {
34 fn drop(&mut self) {
35 DROP_CNT.fetch_add(1, SeqCst);
36 }
37 }
38
39 let x = OnceCell::new();
40 x.get_or_init(|| Dropper);
41 assert_eq!(DROP_CNT.load(SeqCst), 0);
42 drop(x);
43 assert_eq!(DROP_CNT.load(SeqCst), 1);
44 }
45
46 #[test]
47 fn unsync_once_cell_drop_empty() {
48 let x = OnceCell::<String>::new();
49 drop(x);
50 }
51
52 #[test]
53 fn clone() {
54 let s = OnceCell::new();
55 let c = s.clone();
56 assert!(c.get().is_none());
57
58 s.set("hello".to_string()).unwrap();
59 let c = s.clone();
60 assert_eq!(c.get().map(String::as_str), Some("hello"));
61 }
62
63 #[test]
64 fn from_impl() {
65 assert_eq!(OnceCell::from("value").get(), Some(&"value"));
66 assert_ne!(OnceCell::from("foo").get(), Some(&"bar"));
67 }
68
69 #[test]
70 fn partialeq_impl() {
71 assert!(OnceCell::from("value") == OnceCell::from("value"));
72 assert!(OnceCell::from("foo") != OnceCell::from("bar"));
73
74 assert!(OnceCell::<String>::new() == OnceCell::new());
75 assert!(OnceCell::<String>::new() != OnceCell::from("value".to_owned()));
76 }
77
78 #[test]
79 fn into_inner() {
80 let cell: OnceCell<String> = OnceCell::new();
81 assert_eq!(cell.into_inner(), None);
82 let cell = OnceCell::new();
83 cell.set("hello".to_string()).unwrap();
84 assert_eq!(cell.into_inner(), Some("hello".to_string()));
85 }
86
87 #[test]
88 fn debug_impl() {
89 let cell = OnceCell::new();
90 assert_eq!(format!("{:?}", cell), "OnceCell(Uninit)");
91 cell.set("hello".to_string()).unwrap();
92 assert_eq!(format!("{:?}", cell), "OnceCell(\"hello\")");
93 }
94
95 #[test]
96 fn lazy_new() {
97 let called = Cell::new(0);
98 let x = Lazy::new(|| {
99 called.set(called.get() + 1);
100 92
101 });
102
103 assert_eq!(called.get(), 0);
104
105 let y = *x - 30;
106 assert_eq!(y, 62);
107 assert_eq!(called.get(), 1);
108
109 let y = *x - 30;
110 assert_eq!(y, 62);
111 assert_eq!(called.get(), 1);
112 }
113
f035d41b
XL
114 #[test]
115 fn lazy_deref_mut() {
116 let called = Cell::new(0);
117 let mut x = Lazy::new(|| {
118 called.set(called.get() + 1);
119 92
120 });
121
122 assert_eq!(called.get(), 0);
123
124 let y = *x - 30;
125 assert_eq!(y, 62);
126 assert_eq!(called.get(), 1);
127
128 *x /= 2;
129 assert_eq!(*x, 46);
130 assert_eq!(called.get(), 1);
131 }
132
e1599b0c
XL
133 #[test]
134 fn lazy_default() {
135 static CALLED: AtomicUsize = AtomicUsize::new(0);
136
137 struct Foo(u8);
138 impl Default for Foo {
139 fn default() -> Self {
140 CALLED.fetch_add(1, SeqCst);
141 Foo(42)
142 }
143 }
144
145 let lazy: Lazy<std::sync::Mutex<Foo>> = <_>::default();
146
147 assert_eq!(CALLED.load(SeqCst), 0);
148
149 assert_eq!(lazy.lock().unwrap().0, 42);
150 assert_eq!(CALLED.load(SeqCst), 1);
151
152 lazy.lock().unwrap().0 = 21;
153
154 assert_eq!(lazy.lock().unwrap().0, 21);
155 assert_eq!(CALLED.load(SeqCst), 1);
156 }
157
6a06907d
XL
158 #[test]
159 fn lazy_into_value() {
160 let l: Lazy<i32, _> = Lazy::new(|| panic!());
161 assert!(matches!(Lazy::into_value(l), Err(_)));
162 let l = Lazy::new(|| -> i32 { 92 });
163 Lazy::force(&l);
164 assert!(matches!(Lazy::into_value(l), Ok(92)));
165 }
166
e1599b0c 167 #[test]
e1599b0c
XL
168 #[cfg(feature = "std")]
169 fn lazy_poisoning() {
170 let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
171 for _ in 0..2 {
172 let res = std::panic::catch_unwind(|| x.len());
173 assert!(res.is_err());
174 }
175 }
176
177 #[test]
178 fn aliasing_in_get() {
f035d41b 179 let x = OnceCell::new();
e1599b0c
XL
180 x.set(42).unwrap();
181 let at_x = x.get().unwrap(); // --- (shared) borrow of inner `Option<T>` --+
182 let _ = x.set(27); // <-- temporary (unique) borrow of inner `Option<T>` |
183 println!("{}", at_x); // <------- up until here ---------------------------+
184 }
f035d41b
XL
185
186 #[test]
187 #[should_panic(expected = "reentrant init")]
188 fn reentrant_init() {
189 let x: OnceCell<Box<i32>> = OnceCell::new();
190 let dangling_ref: Cell<Option<&i32>> = Cell::new(None);
191 x.get_or_init(|| {
192 let r = x.get_or_init(|| Box::new(92));
193 dangling_ref.set(Some(r));
194 Box::new(62)
195 });
196 eprintln!("use after free: {:?}", dangling_ref.get().unwrap());
197 }
3dfed10e
XL
198
199 #[test]
200 // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669
201 fn arrrrrrrrrrrrrrrrrrrrrr() {
202 let cell = OnceCell::new();
203 {
204 let s = String::new();
205 cell.set(&s).unwrap();
206 }
207 }
e1599b0c
XL
208}
209
210#[cfg(feature = "std")]
211mod sync {
212 use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
213
5869c6ff 214 use crossbeam_utils::thread::scope;
e1599b0c 215
5869c6ff 216 use once_cell::sync::{Lazy, OnceCell};
e1599b0c
XL
217
218 #[test]
219 fn once_cell() {
220 let c = OnceCell::new();
221 assert!(c.get().is_none());
222 scope(|s| {
223 s.spawn(|_| {
224 c.get_or_init(|| 92);
225 assert_eq!(c.get(), Some(&92));
226 });
227 })
228 .unwrap();
229 c.get_or_init(|| panic!("Kabom!"));
230 assert_eq!(c.get(), Some(&92));
231 }
232
233 #[test]
234 fn once_cell_get_mut() {
235 let mut c = OnceCell::new();
236 assert!(c.get_mut().is_none());
237 c.set(90).unwrap();
238 *c.get_mut().unwrap() += 2;
239 assert_eq!(c.get_mut(), Some(&mut 92));
240 }
241
f035d41b
XL
242 #[test]
243 fn once_cell_get_unchecked() {
244 let c = OnceCell::new();
245 c.set(92).unwrap();
246 unsafe {
247 assert_eq!(c.get_unchecked(), &92);
248 }
249 }
250
e1599b0c
XL
251 #[test]
252 fn once_cell_drop() {
253 static DROP_CNT: AtomicUsize = AtomicUsize::new(0);
254 struct Dropper;
255 impl Drop for Dropper {
256 fn drop(&mut self) {
257 DROP_CNT.fetch_add(1, SeqCst);
258 }
259 }
260
261 let x = OnceCell::new();
262 scope(|s| {
263 s.spawn(|_| {
264 x.get_or_init(|| Dropper);
265 assert_eq!(DROP_CNT.load(SeqCst), 0);
266 drop(x);
267 });
268 })
269 .unwrap();
270 assert_eq!(DROP_CNT.load(SeqCst), 1);
271 }
272
273 #[test]
274 fn once_cell_drop_empty() {
275 let x = OnceCell::<String>::new();
276 drop(x);
277 }
278
279 #[test]
280 fn clone() {
281 let s = OnceCell::new();
282 let c = s.clone();
283 assert!(c.get().is_none());
284
285 s.set("hello".to_string()).unwrap();
286 let c = s.clone();
287 assert_eq!(c.get().map(String::as_str), Some("hello"));
288 }
289
290 #[test]
e1599b0c
XL
291 fn get_or_try_init() {
292 let cell: OnceCell<String> = OnceCell::new();
293 assert!(cell.get().is_none());
294
295 let res =
296 std::panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() }));
297 assert!(res.is_err());
298 assert!(cell.get().is_none());
299
300 assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
301
302 assert_eq!(
303 cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())),
304 Ok(&"hello".to_string())
305 );
306 assert_eq!(cell.get(), Some(&"hello".to_string()));
307 }
308
309 #[test]
310 fn from_impl() {
311 assert_eq!(OnceCell::from("value").get(), Some(&"value"));
312 assert_ne!(OnceCell::from("foo").get(), Some(&"bar"));
313 }
314
315 #[test]
316 fn partialeq_impl() {
317 assert!(OnceCell::from("value") == OnceCell::from("value"));
318 assert!(OnceCell::from("foo") != OnceCell::from("bar"));
319
320 assert!(OnceCell::<String>::new() == OnceCell::new());
321 assert!(OnceCell::<String>::new() != OnceCell::from("value".to_owned()));
322 }
323
324 #[test]
325 fn into_inner() {
326 let cell: OnceCell<String> = OnceCell::new();
327 assert_eq!(cell.into_inner(), None);
328 let cell = OnceCell::new();
329 cell.set("hello".to_string()).unwrap();
330 assert_eq!(cell.into_inner(), Some("hello".to_string()));
331 }
332
333 #[test]
334 fn debug_impl() {
335 let cell = OnceCell::new();
336 assert_eq!(format!("{:#?}", cell), "OnceCell(Uninit)");
337 cell.set(vec!["hello", "world"]).unwrap();
338 assert_eq!(
339 format!("{:#?}", cell),
340 r#"OnceCell(
341 [
342 "hello",
343 "world",
344 ],
345)"#
346 );
347 }
348
349 #[test]
f035d41b 350 #[cfg_attr(miri, ignore)] // miri doesn't support processes
e1599b0c
XL
351 fn reentrant_init() {
352 let examples_dir = {
353 let mut exe = std::env::current_exe().unwrap();
354 exe.pop();
355 exe.pop();
356 exe.push("examples");
357 exe
358 };
359 let bin = examples_dir
360 .join("reentrant_init_deadlocks")
361 .with_extension(std::env::consts::EXE_EXTENSION);
362 let mut guard = Guard { child: std::process::Command::new(bin).spawn().unwrap() };
363 std::thread::sleep(std::time::Duration::from_secs(2));
364 let status = guard.child.try_wait().unwrap();
365 assert!(status.is_none());
366
367 struct Guard {
368 child: std::process::Child,
369 }
370
371 impl Drop for Guard {
372 fn drop(&mut self) {
373 let _ = self.child.kill();
374 }
375 }
376 }
377
378 #[test]
379 fn lazy_new() {
380 let called = AtomicUsize::new(0);
381 let x = Lazy::new(|| {
382 called.fetch_add(1, SeqCst);
383 92
384 });
385
386 assert_eq!(called.load(SeqCst), 0);
387
388 scope(|s| {
389 s.spawn(|_| {
390 let y = *x - 30;
391 assert_eq!(y, 62);
392 assert_eq!(called.load(SeqCst), 1);
393 });
394 })
395 .unwrap();
396
397 let y = *x - 30;
398 assert_eq!(y, 62);
399 assert_eq!(called.load(SeqCst), 1);
400 }
401
f035d41b
XL
402 #[test]
403 fn lazy_deref_mut() {
404 let called = AtomicUsize::new(0);
405 let mut x = Lazy::new(|| {
406 called.fetch_add(1, SeqCst);
407 92
408 });
409
410 assert_eq!(called.load(SeqCst), 0);
411
412 let y = *x - 30;
413 assert_eq!(y, 62);
414 assert_eq!(called.load(SeqCst), 1);
415
416 *x /= 2;
417 assert_eq!(*x, 46);
418 assert_eq!(called.load(SeqCst), 1);
419 }
420
e1599b0c
XL
421 #[test]
422 fn lazy_default() {
423 static CALLED: AtomicUsize = AtomicUsize::new(0);
424
425 struct Foo(u8);
426 impl Default for Foo {
427 fn default() -> Self {
428 CALLED.fetch_add(1, SeqCst);
429 Foo(42)
430 }
431 }
432
433 let lazy: Lazy<std::sync::Mutex<Foo>> = <_>::default();
434
435 assert_eq!(CALLED.load(SeqCst), 0);
436
437 assert_eq!(lazy.lock().unwrap().0, 42);
438 assert_eq!(CALLED.load(SeqCst), 1);
439
440 lazy.lock().unwrap().0 = 21;
441
442 assert_eq!(lazy.lock().unwrap().0, 21);
443 assert_eq!(CALLED.load(SeqCst), 1);
444 }
445
446 #[test]
e1599b0c
XL
447 fn static_lazy() {
448 static XS: Lazy<Vec<i32>> = Lazy::new(|| {
449 let mut xs = Vec::new();
450 xs.push(1);
451 xs.push(2);
452 xs.push(3);
453 xs
454 });
455 scope(|s| {
456 s.spawn(|_| {
457 assert_eq!(&*XS, &vec![1, 2, 3]);
458 });
459 })
460 .unwrap();
461 assert_eq!(&*XS, &vec![1, 2, 3]);
462 }
463
464 #[test]
e1599b0c
XL
465 fn static_lazy_via_fn() {
466 fn xs() -> &'static Vec<i32> {
467 static XS: OnceCell<Vec<i32>> = OnceCell::new();
468 XS.get_or_init(|| {
469 let mut xs = Vec::new();
470 xs.push(1);
471 xs.push(2);
472 xs.push(3);
473 xs
474 })
475 }
476 assert_eq!(xs(), &vec![1, 2, 3]);
477 }
478
6a06907d
XL
479 #[test]
480 fn lazy_into_value() {
481 let l: Lazy<i32, _> = Lazy::new(|| panic!());
482 assert!(matches!(Lazy::into_value(l), Err(_)));
483 let l = Lazy::new(|| -> i32 { 92 });
484 Lazy::force(&l);
485 assert!(matches!(Lazy::into_value(l), Ok(92)));
486 }
487
e1599b0c 488 #[test]
e1599b0c
XL
489 fn lazy_poisoning() {
490 let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
491 for _ in 0..2 {
492 let res = std::panic::catch_unwind(|| x.len());
493 assert!(res.is_err());
494 }
495 }
496
497 #[test]
498 fn once_cell_is_sync_send() {
499 fn assert_traits<T: Send + Sync>() {}
500 assert_traits::<OnceCell<String>>();
501 assert_traits::<Lazy<String>>();
502 }
503
504 #[test]
e1599b0c
XL
505 fn eval_once_macro() {
506 macro_rules! eval_once {
507 (|| -> $ty:ty {
508 $($body:tt)*
509 }) => {{
510 static ONCE_CELL: OnceCell<$ty> = OnceCell::new();
511 fn init() -> $ty {
512 $($body)*
513 }
514 ONCE_CELL.get_or_init(init)
515 }};
516 }
517
518 let fib: &'static Vec<i32> = eval_once! {
519 || -> Vec<i32> {
520 let mut res = vec![1, 1];
521 for i in 0..10 {
522 let next = res[i] + res[i + 1];
523 res.push(next);
524 }
525 res
526 }
527 };
528 assert_eq!(fib[5], 8)
529 }
530
531 #[test]
5869c6ff 532 #[cfg_attr(miri, ignore)] // FIXME: deadlocks, likely caused by https://github.com/rust-lang/miri/issues/1388
e1599b0c
XL
533 fn once_cell_does_not_leak_partially_constructed_boxes() {
534 let n_tries = 100;
535 let n_readers = 10;
536 let n_writers = 3;
537 const MSG: &str = "Hello, World";
538
539 for _ in 0..n_tries {
540 let cell: OnceCell<String> = OnceCell::new();
541 scope(|scope| {
542 for _ in 0..n_readers {
543 scope.spawn(|_| loop {
544 if let Some(msg) = cell.get() {
545 assert_eq!(msg, MSG);
546 break;
547 }
548 });
549 }
550 for _ in 0..n_writers {
f035d41b 551 let _ = scope.spawn(|_| cell.set(MSG.to_owned()));
e1599b0c
XL
552 }
553 })
554 .unwrap()
555 }
556 }
557
558 #[test]
f035d41b 559 #[cfg_attr(miri, ignore)] // miri doesn't support Barrier
e1599b0c
XL
560 fn get_does_not_block() {
561 use std::sync::Barrier;
562
563 let cell = OnceCell::new();
564 let barrier = Barrier::new(2);
565 scope(|scope| {
566 scope.spawn(|_| {
567 cell.get_or_init(|| {
568 barrier.wait();
569 barrier.wait();
570 "hello".to_string()
571 });
572 });
573 barrier.wait();
574 assert_eq!(cell.get(), None);
575 barrier.wait();
576 })
577 .unwrap();
578 assert_eq!(cell.get(), Some(&"hello".to_string()));
579 }
3dfed10e
XL
580
581 #[test]
582 // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669
583 fn arrrrrrrrrrrrrrrrrrrrrr() {
584 let cell = OnceCell::new();
585 {
586 let s = String::new();
587 cell.set(&s).unwrap();
588 }
589 }
e1599b0c 590}
5869c6ff 591
6a06907d 592#[cfg(feature = "race")]
5869c6ff
XL
593mod race {
594 use std::{
595 num::NonZeroUsize,
596 sync::{
597 atomic::{AtomicUsize, Ordering::SeqCst},
598 Barrier,
599 },
600 };
601
602 use crossbeam_utils::thread::scope;
603
604 use once_cell::race::{OnceBool, OnceNonZeroUsize};
605
606 #[test]
607 fn once_non_zero_usize_smoke_test() {
608 let cnt = AtomicUsize::new(0);
609 let cell = OnceNonZeroUsize::new();
610 let val = NonZeroUsize::new(92).unwrap();
611 scope(|s| {
612 s.spawn(|_| {
613 assert_eq!(
614 cell.get_or_init(|| {
615 cnt.fetch_add(1, SeqCst);
616 val
617 }),
618 val
619 );
620 assert_eq!(cnt.load(SeqCst), 1);
621
622 assert_eq!(
623 cell.get_or_init(|| {
624 cnt.fetch_add(1, SeqCst);
625 val
626 }),
627 val
628 );
629 assert_eq!(cnt.load(SeqCst), 1);
630 });
631 })
632 .unwrap();
633 assert_eq!(cell.get(), Some(val));
634 assert_eq!(cnt.load(SeqCst), 1);
635 }
636
637 #[test]
638 fn once_non_zero_usize_set() {
639 let val1 = NonZeroUsize::new(92).unwrap();
640 let val2 = NonZeroUsize::new(62).unwrap();
641
642 let cell = OnceNonZeroUsize::new();
643
644 assert!(cell.set(val1).is_ok());
645 assert_eq!(cell.get(), Some(val1));
646
647 assert!(cell.set(val2).is_err());
648 assert_eq!(cell.get(), Some(val1));
649 }
650
651 #[test]
652 fn once_non_zero_usize_first_wins() {
653 let val1 = NonZeroUsize::new(92).unwrap();
654 let val2 = NonZeroUsize::new(62).unwrap();
655
656 let cell = OnceNonZeroUsize::new();
657
658 let b1 = Barrier::new(2);
659 let b2 = Barrier::new(2);
660 let b3 = Barrier::new(2);
661 scope(|s| {
662 s.spawn(|_| {
663 let r1 = cell.get_or_init(|| {
664 b1.wait();
665 b2.wait();
666 val1
667 });
668 assert_eq!(r1, val1);
669 b3.wait();
670 });
671 b1.wait();
672 s.spawn(|_| {
673 let r2 = cell.get_or_init(|| {
674 b2.wait();
675 b3.wait();
676 val2
677 });
678 assert_eq!(r2, val1);
679 });
680 })
681 .unwrap();
682
683 assert_eq!(cell.get(), Some(val1));
684 }
685
686 #[test]
687 fn once_bool_smoke_test() {
688 let cnt = AtomicUsize::new(0);
689 let cell = OnceBool::new();
690 scope(|s| {
691 s.spawn(|_| {
692 assert_eq!(
693 cell.get_or_init(|| {
694 cnt.fetch_add(1, SeqCst);
695 false
696 }),
697 false
698 );
699 assert_eq!(cnt.load(SeqCst), 1);
700
701 assert_eq!(
702 cell.get_or_init(|| {
703 cnt.fetch_add(1, SeqCst);
704 false
705 }),
706 false
707 );
708 assert_eq!(cnt.load(SeqCst), 1);
709 });
710 })
711 .unwrap();
712 assert_eq!(cell.get(), Some(false));
713 assert_eq!(cnt.load(SeqCst), 1);
714 }
715
716 #[test]
717 fn once_bool_set() {
718 let cell = OnceBool::new();
719
720 assert!(cell.set(false).is_ok());
721 assert_eq!(cell.get(), Some(false));
722
723 assert!(cell.set(true).is_err());
724 assert_eq!(cell.get(), Some(false));
725 }
726}
727
6a06907d 728#[cfg(all(feature = "race", feature = "alloc"))]
5869c6ff
XL
729mod race_once_box {
730 use std::sync::{
731 atomic::{AtomicUsize, Ordering::SeqCst},
732 Arc, Barrier,
733 };
734
735 use crossbeam_utils::thread::scope;
736 use once_cell::race::OnceBox;
737
738 #[derive(Default)]
739 struct Heap {
740 total: Arc<AtomicUsize>,
741 }
742
743 #[derive(Debug)]
744 struct Pebble<T> {
745 val: T,
746 total: Arc<AtomicUsize>,
747 }
748
749 impl<T> Drop for Pebble<T> {
750 fn drop(&mut self) {
751 self.total.fetch_sub(1, SeqCst);
752 }
753 }
754
755 impl Heap {
756 fn total(&self) -> usize {
757 self.total.load(SeqCst)
758 }
759 fn new_pebble<T>(&self, val: T) -> Pebble<T> {
760 self.total.fetch_add(1, SeqCst);
761 Pebble { val, total: Arc::clone(&self.total) }
762 }
763 }
764
765 #[test]
766 fn once_box_smoke_test() {
767 let heap = Heap::default();
768 let global_cnt = AtomicUsize::new(0);
769 let cell = OnceBox::new();
770 let b = Barrier::new(128);
771 scope(|s| {
772 for _ in 0..128 {
773 s.spawn(|_| {
774 let local_cnt = AtomicUsize::new(0);
775 cell.get_or_init(|| {
776 global_cnt.fetch_add(1, SeqCst);
777 local_cnt.fetch_add(1, SeqCst);
778 b.wait();
779 Box::new(heap.new_pebble(()))
780 });
781 assert_eq!(local_cnt.load(SeqCst), 1);
782
783 cell.get_or_init(|| {
784 global_cnt.fetch_add(1, SeqCst);
785 local_cnt.fetch_add(1, SeqCst);
786 Box::new(heap.new_pebble(()))
787 });
788 assert_eq!(local_cnt.load(SeqCst), 1);
789 });
790 }
791 })
792 .unwrap();
793 assert!(cell.get().is_some());
794 assert!(global_cnt.load(SeqCst) > 10);
795
796 assert_eq!(heap.total(), 1);
797 drop(cell);
798 assert_eq!(heap.total(), 0);
799 }
800
801 #[test]
802 fn once_box_set() {
803 let heap = Heap::default();
804 let cell = OnceBox::new();
805 assert!(cell.get().is_none());
806
807 assert!(cell.set(Box::new(heap.new_pebble("hello"))).is_ok());
808 assert_eq!(cell.get().unwrap().val, "hello");
809 assert_eq!(heap.total(), 1);
810
811 assert!(cell.set(Box::new(heap.new_pebble("world"))).is_err());
812 assert_eq!(cell.get().unwrap().val, "hello");
813 assert_eq!(heap.total(), 1);
814
815 drop(cell);
816 assert_eq!(heap.total(), 0);
817 }
818
819 #[test]
820 fn once_box_first_wins() {
821 let cell = OnceBox::new();
822 let val1 = 92;
823 let val2 = 62;
824
825 let b1 = Barrier::new(2);
826 let b2 = Barrier::new(2);
827 let b3 = Barrier::new(2);
828 scope(|s| {
829 s.spawn(|_| {
830 let r1 = cell.get_or_init(|| {
831 b1.wait();
832 b2.wait();
833 Box::new(val1)
834 });
835 assert_eq!(*r1, val1);
836 b3.wait();
837 });
838 b1.wait();
839 s.spawn(|_| {
840 let r2 = cell.get_or_init(|| {
841 b2.wait();
842 b3.wait();
843 Box::new(val2)
844 });
845 assert_eq!(*r2, val1);
846 });
847 })
848 .unwrap();
849
850 assert_eq!(cell.get(), Some(&val1));
851 }
852
853 #[test]
854 fn once_box_reentrant() {
855 let cell = OnceBox::new();
856 let res = cell.get_or_init(|| {
857 cell.get_or_init(|| Box::new("hello".to_string()));
858 Box::new("world".to_string())
859 });
860 assert_eq!(res, "hello");
861 }
6a06907d
XL
862
863 #[test]
864 fn once_box_default() {
865 struct Foo;
866
867 let cell: OnceBox<Foo> = Default::default();
868 assert!(cell.get().is_none());
869 }
5869c6ff 870}