mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Move test_shrink_to_unwind
to its own file.
This way, no other test can be tripped up by `test_shrink_to_unwind` changing the alloc error hook.
This commit is contained in:
parent
ffe8510e3d
commit
5cb53bc34d
@ -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"
|
||||
|
@ -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::*;
|
||||
|
||||
@ -797,52 +790,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,
|
||||
|
@ -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)]
|
||||
|
49
library/alloc/tests/vec_deque_alloc_error.rs
Normal file
49
library/alloc/tests/vec_deque_alloc_error.rs
Normal file
@ -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]);
|
||||
}
|
Loading…
Reference in New Issue
Block a user