about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/alloc/Cargo.toml4
-rw-r--r--library/alloc/src/collections/vec_deque/tests.rs55
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/tests/vec_deque_alloc_error.rs49
4 files changed, 54 insertions, 55 deletions
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index e8afed6b35a..7bc0bddcafc 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -20,6 +20,10 @@ rand_xorshift = "0.3.0"
 name = "alloctests"
 path = "tests/lib.rs"
 
+[[test]]
+name = "vec_deque_alloc_error"
+path = "tests/vec_deque_alloc_error.rs"
+
 [[bench]]
 name = "allocbenches"
 path = "benches/lib.rs"
diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs
index 5329ad1aed5..f8ce4ca9788 100644
--- a/library/alloc/src/collections/vec_deque/tests.rs
+++ b/library/alloc/src/collections/vec_deque/tests.rs
@@ -1,11 +1,4 @@
-#![feature(alloc_error_hook)]
-
-use crate::alloc::{AllocError, Layout};
-use core::{iter::TrustedLen, ptr::NonNull};
-use std::{
-    alloc::{set_alloc_error_hook, take_alloc_error_hook, System},
-    panic::{catch_unwind, AssertUnwindSafe},
-};
+use core::iter::TrustedLen;
 
 use super::*;
 
@@ -798,52 +791,6 @@ fn test_shrink_to() {
 }
 
 #[test]
-fn test_shrink_to_unwind() {
-    // This tests that `shrink_to` leaves the deque in a consistent state when
-    // the call to `RawVec::shrink_to_fit` unwinds. The code is adapted from #123369
-    // but changed to hopefully not have any UB even if the test fails.
-
-    struct BadAlloc;
-
-    unsafe impl Allocator for BadAlloc {
-        fn allocate(&self, l: Layout) -> Result<NonNull<[u8]>, AllocError> {
-            // We allocate zeroed here so that the whole buffer of the deque
-            // is always initialized. That way, even if the deque is left in
-            // an inconsistent state, no uninitialized memory should be accessed.
-            System.allocate_zeroed(l)
-        }
-
-        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
-            unsafe { System.deallocate(ptr, layout) }
-        }
-
-        unsafe fn shrink(
-            &self,
-            _ptr: NonNull<u8>,
-            _old_layout: Layout,
-            _new_layout: Layout,
-        ) -> Result<NonNull<[u8]>, AllocError> {
-            Err(AllocError)
-        }
-    }
-
-    // preserve the old error hook just in case.
-    let old_error_hook = take_alloc_error_hook();
-    set_alloc_error_hook(|_| panic!("alloc error"));
-
-    let mut v = VecDeque::with_capacity_in(15, BadAlloc);
-    v.push_back(1);
-    v.push_front(2);
-    // This should unwind because it calls `BadAlloc::shrink` and then `handle_alloc_error` which unwinds.
-    assert!(catch_unwind(AssertUnwindSafe(|| v.shrink_to_fit())).is_err());
-    // This should only pass if the deque is left in a consistent state.
-    assert_eq!(v, [2, 1]);
-
-    // restore the old error hook.
-    set_alloc_error_hook(old_error_hook);
-}
-
-#[test]
 fn test_shrink_to_fit() {
     // This test checks that every single combination of head and tail position,
     // is tested. Capacity 15 should be large enough to cover every case.
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index d607926f8d4..91b83cfe011 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -92,7 +92,6 @@
 // tidy-alphabetical-start
 #![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))]
 #![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))]
-#![cfg_attr(test, feature(alloc_error_hook))]
 #![cfg_attr(test, feature(is_sorted))]
 #![cfg_attr(test, feature(new_uninit))]
 #![feature(alloc_layout_extra)]
diff --git a/library/alloc/tests/vec_deque_alloc_error.rs b/library/alloc/tests/vec_deque_alloc_error.rs
new file mode 100644
index 00000000000..c11f4556da9
--- /dev/null
+++ b/library/alloc/tests/vec_deque_alloc_error.rs
@@ -0,0 +1,49 @@
+#![feature(alloc_error_hook, allocator_api)]
+
+use std::{
+    alloc::{set_alloc_error_hook, AllocError, Allocator, Layout, System},
+    collections::VecDeque,
+    panic::{catch_unwind, AssertUnwindSafe},
+    ptr::NonNull,
+};
+
+#[test]
+fn test_shrink_to_unwind() {
+    // This tests that `shrink_to` leaves the deque in a consistent state when
+    // the call to `RawVec::shrink_to_fit` unwinds. The code is adapted from #123369
+    // but changed to hopefully not have any UB even if the test fails.
+
+    struct BadAlloc;
+
+    unsafe impl Allocator for BadAlloc {
+        fn allocate(&self, l: Layout) -> Result<NonNull<[u8]>, AllocError> {
+            // We allocate zeroed here so that the whole buffer of the deque
+            // is always initialized. That way, even if the deque is left in
+            // an inconsistent state, no uninitialized memory should be accessed.
+            System.allocate_zeroed(l)
+        }
+
+        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
+            unsafe { System.deallocate(ptr, layout) }
+        }
+
+        unsafe fn shrink(
+            &self,
+            _ptr: NonNull<u8>,
+            _old_layout: Layout,
+            _new_layout: Layout,
+        ) -> Result<NonNull<[u8]>, AllocError> {
+            Err(AllocError)
+        }
+    }
+
+    set_alloc_error_hook(|_| panic!("alloc error"));
+
+    let mut v = VecDeque::with_capacity_in(15, BadAlloc);
+    v.push_back(1);
+    v.push_front(2);
+    // This should unwind because it calls `BadAlloc::shrink` and then `handle_alloc_error` which unwinds.
+    assert!(catch_unwind(AssertUnwindSafe(|| v.shrink_to_fit())).is_err());
+    // This should only pass if the deque is left in a consistent state.
+    assert_eq!(v, [2, 1]);
+}