about summary refs log tree commit diff
path: root/library/coretests/tests/mem.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/coretests/tests/mem.rs')
-rw-r--r--library/coretests/tests/mem.rs46
1 files changed, 46 insertions, 0 deletions
diff --git a/library/coretests/tests/mem.rs b/library/coretests/tests/mem.rs
index 9c15be4a8c4..e896c61ef48 100644
--- a/library/coretests/tests/mem.rs
+++ b/library/coretests/tests/mem.rs
@@ -1,5 +1,6 @@
 use core::mem::*;
 use core::{array, ptr};
+use std::cell::Cell;
 #[cfg(panic = "unwind")]
 use std::rc::Rc;
 
@@ -795,3 +796,48 @@ fn const_maybe_uninit_zeroed() {
 
     assert_eq!(unsafe { (*UNINIT.0.cast::<[[u8; SIZE]; 1]>())[0] }, [0u8; SIZE]);
 }
+
+#[test]
+fn drop_guards_only_dropped_by_closure_when_run() {
+    let value_drops = Cell::new(0);
+    let value = DropGuard::new((), |()| value_drops.set(1 + value_drops.get()));
+    let closure_drops = Cell::new(0);
+    let guard = DropGuard::new(value, |_| closure_drops.set(1 + closure_drops.get()));
+    assert_eq!(value_drops.get(), 0);
+    assert_eq!(closure_drops.get(), 0);
+    drop(guard);
+    assert_eq!(value_drops.get(), 1);
+    assert_eq!(closure_drops.get(), 1);
+}
+
+#[test]
+fn drop_guard_into_inner() {
+    let dropped = Cell::new(false);
+    let value = DropGuard::new(42, |_| dropped.set(true));
+    let guard = DropGuard::new(value, |_| dropped.set(true));
+    let inner = DropGuard::into_inner(guard);
+    assert_eq!(dropped.get(), false);
+    assert_eq!(*inner, 42);
+}
+
+#[test]
+#[cfg(panic = "unwind")]
+fn drop_guard_always_drops_value_if_closure_drop_unwinds() {
+    // Create a value with a destructor, which we will validate ran successfully.
+    let mut value_was_dropped = false;
+    let value_with_tracked_destruction = DropGuard::new((), |_| value_was_dropped = true);
+
+    // Create a closure that will begin unwinding when dropped.
+    let drop_bomb = DropGuard::new((), |_| panic!());
+    let closure_that_panics_on_drop = move |_| {
+        let _drop_bomb = drop_bomb;
+    };
+
+    // This will run the closure, which will panic when dropped. This should
+    // run the destructor of the value we passed, which we validate.
+    let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
+        let guard = DropGuard::new(value_with_tracked_destruction, closure_that_panics_on_drop);
+        DropGuard::into_inner(guard);
+    }));
+    assert!(value_was_dropped);
+}