about summary refs log tree commit diff
path: root/src/libcore/tests
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2020-06-18 15:20:41 -0700
committerGitHub <noreply@github.com>2020-06-18 15:20:41 -0700
commit9262fc2a68133330a8f78c73afa54b3ff09724b5 (patch)
treee4c9f00006b7883d276aace4c0a92dbed7f0b67c /src/libcore/tests
parent49ab0cab618d9d1cb49220d7c253556a56148283 (diff)
parent3313bf62ac45fab2c39e49c788423153754087a9 (diff)
downloadrust-9262fc2a68133330a8f78c73afa54b3ff09724b5.tar.gz
rust-9262fc2a68133330a8f78c73afa54b3ff09724b5.zip
Rollup merge of #72628 - MikailBag:array-default-tests, r=shepmaster
Add tests for 'impl Default for [T; N]'

Related: #71690.
This pull request adds two tests:
- Even it T::default() panics, no leaks occur.
- [T; 0] is Default even if T is not.

I believe at some moment `Default` impl for arrays will be rewritten to use const generics instead of macros, and these tests will help to prevent behavior changes.
Diffstat (limited to 'src/libcore/tests')
-rw-r--r--src/libcore/tests/array.rs49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs
index c2a816f0a7d..4bc44e98fc8 100644
--- a/src/libcore/tests/array.rs
+++ b/src/libcore/tests/array.rs
@@ -241,3 +241,52 @@ fn iterator_drops() {
     }
     assert_eq!(i.get(), 5);
 }
+
+// This test does not work on targets without panic=unwind support.
+// To work around this problem, test is marked is should_panic, so it will
+// be automagically skipped on unsuitable targets, such as
+// wasm32-unknown-unkown.
+//
+// It means that we use panic for indicating success.
+#[test]
+#[should_panic(expected = "test succeeded")]
+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);
+    panic!("test succeeded")
+}
+
+#[test]
+fn empty_array_is_always_default() {
+    struct DoesNotImplDefault;
+
+    let _arr = <[DoesNotImplDefault; 0]>::default();
+}