about summary refs log tree commit diff
path: root/src/libcore/tests/array.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcore/tests/array.rs')
-rw-r--r--src/libcore/tests/array.rs41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs
index c2a816f0a7d..41855a9a8cb 100644
--- a/src/libcore/tests/array.rs
+++ b/src/libcore/tests/array.rs
@@ -241,3 +241,44 @@ fn iterator_drops() {
     }
     assert_eq!(i.get(), 5);
 }
+
+#[test]
+fn array_default_impl_avoids_leaks_on_panic() {
+    use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+    static COUNTER: AtomicUsize = AtomicUsize::new(0);
+    #[derive(Debug)]
+    struct Bomb(usize);
+
+    impl Default for Bomb {
+        fn default() -> Bomb {
+            if COUNTER.load(Relaxed) == 3 {
+                panic!("bomb limit exceeded");
+            }
+
+            COUNTER.fetch_add(1, Relaxed);
+            Bomb(COUNTER.load(Relaxed))
+        }
+    }
+
+    impl Drop for Bomb {
+        fn drop(&mut self) {
+            COUNTER.fetch_sub(1, Relaxed);
+        }
+    }
+
+    let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default());
+    let panic_msg = match res {
+        Ok(_) => unreachable!(),
+        Err(p) => p.downcast::<&'static str>().unwrap(),
+    };
+    assert_eq!(*panic_msg, "bomb limit exceeded");
+    // check that all bombs are successfully dropped
+    assert_eq!(COUNTER.load(Relaxed), 0);
+}
+
+#[test]
+fn empty_array_is_always_default() {
+    struct DoesNotImplDefault;
+
+    let _arr = <[DoesNotImplDefault; 0]>::default();
+}