Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ptr/tests/moving_ptr.rs
30635 views
1
//! Tests for [`bevy_ptr::MovingPtr`] with panic behavior.
2
3
#![allow(unsafe_code, reason = "unsafe is needed to use bevy_ptr::MovingPtr")]
4
5
use bevy_ptr::MovingPtr;
6
7
use core::cell::Cell;
8
use core::mem::MaybeUninit;
9
use core::panic::AssertUnwindSafe;
10
11
use std::panic::catch_unwind;
12
13
#[test]
14
fn moving_ptr_assign_drop_is_unwind_safe() {
15
struct IncAndPanicOnDrop<'a>(&'a Cell<u32>);
16
impl<'a> Drop for IncAndPanicOnDrop<'a> {
17
fn drop(&mut self) {
18
self.0.set(self.0.get() + 1);
19
20
// Panic, but avoid double-panics to avoid aborts.
21
if !std::thread::panicking() {
22
panic!();
23
}
24
}
25
}
26
27
let drops1 = Cell::new(0);
28
let drops2 = Cell::new(0);
29
30
let mut value1 = MaybeUninit::new(IncAndPanicOnDrop(&drops1));
31
let mut value2 = IncAndPanicOnDrop(&drops2);
32
33
_ = catch_unwind(AssertUnwindSafe(|| {
34
// SAFETY:
35
// - value1 is initialized
36
// - we're not using value1 after this point.
37
let moving_ptr = unsafe { MovingPtr::from_value(&mut value1) };
38
39
// This should drop value2 and overwrite it with value1 no matter what happen.
40
// If the overwrite doesn't happen then it is unsound and the second pair of asserts will fail.
41
moving_ptr.assign_to(&mut value2);
42
}));
43
44
assert_eq!(drops1.get(), 0);
45
assert_eq!(drops2.get(), 1);
46
47
// Now drop value2, which should now hold value1. We expect this to drop value1 and increase drops1.
48
_ = catch_unwind(AssertUnwindSafe(|| drop(value2)));
49
50
assert_eq!(drops1.get(), 1);
51
assert_eq!(drops2.get(), 1);
52
}
53
54