summaryrefslogtreecommitdiffstats
path: root/library/alloc/tests/vec.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:11:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:11:28 +0000
commit94a0819fe3a0d679c3042a77bfe6a2afc505daea (patch)
tree2b827afe6a05f3538db3f7803a88c4587fe85648 /library/alloc/tests/vec.rs
parentAdding upstream version 1.64.0+dfsg1. (diff)
downloadrustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.tar.xz
rustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.zip
Adding upstream version 1.66.0+dfsg1.upstream/1.66.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/alloc/tests/vec.rs')
-rw-r--r--library/alloc/tests/vec.rs341
1 files changed, 197 insertions, 144 deletions
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index b797e2375..e02711870 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -294,6 +294,22 @@ fn test_retain() {
}
#[test]
+fn test_retain_predicate_order() {
+ for to_keep in [true, false] {
+ let mut number_of_executions = 0;
+ let mut vec = vec![1, 2, 3, 4];
+ let mut next_expected = 1;
+ vec.retain(|&x| {
+ assert_eq!(next_expected, x);
+ next_expected += 1;
+ number_of_executions += 1;
+ to_keep
+ });
+ assert_eq!(number_of_executions, 4);
+ }
+}
+
+#[test]
fn test_retain_pred_panic_with_hole() {
let v = (0..5).map(Rc::new).collect::<Vec<_>>();
catch_unwind(AssertUnwindSafe(|| {
@@ -355,6 +371,35 @@ fn test_retain_drop_panic() {
}
#[test]
+fn test_retain_maybeuninits() {
+ // This test aimed to be run under miri.
+ use core::mem::MaybeUninit;
+ let mut vec: Vec<_> = [1i32, 2, 3, 4].map(|v| MaybeUninit::new(vec![v])).into();
+ vec.retain(|x| {
+ // SAFETY: Retain must visit every element of Vec in original order and exactly once.
+ // Our values is initialized at creation of Vec.
+ let v = unsafe { x.assume_init_ref()[0] };
+ if v & 1 == 0 {
+ return true;
+ }
+ // SAFETY: Value is initialized.
+ // Value wouldn't be dropped by `Vec::retain`
+ // because `MaybeUninit` doesn't drop content.
+ drop(unsafe { x.assume_init_read() });
+ false
+ });
+ let vec: Vec<i32> = vec
+ .into_iter()
+ .map(|x| unsafe {
+ // SAFETY: All values dropped in retain predicate must be removed by `Vec::retain`.
+ // Remaining values are initialized.
+ x.assume_init()[0]
+ })
+ .collect();
+ assert_eq!(vec, [2, 4]);
+}
+
+#[test]
fn test_dedup() {
fn case(a: Vec<i32>, b: Vec<i32>) {
let mut v = a;
@@ -795,6 +840,36 @@ fn test_drain_leak() {
}
#[test]
+fn test_drain_keep_rest() {
+ let mut v = vec![0, 1, 2, 3, 4, 5, 6];
+ let mut drain = v.drain(1..6);
+ assert_eq!(drain.next(), Some(1));
+ assert_eq!(drain.next_back(), Some(5));
+ assert_eq!(drain.next(), Some(2));
+
+ drain.keep_rest();
+ assert_eq!(v, &[0, 3, 4, 6]);
+}
+
+#[test]
+fn test_drain_keep_rest_all() {
+ let mut v = vec![0, 1, 2, 3, 4, 5, 6];
+ v.drain(1..6).keep_rest();
+ assert_eq!(v, &[0, 1, 2, 3, 4, 5, 6]);
+}
+
+#[test]
+fn test_drain_keep_rest_none() {
+ let mut v = vec![0, 1, 2, 3, 4, 5, 6];
+ let mut drain = v.drain(1..6);
+
+ drain.by_ref().for_each(drop);
+
+ drain.keep_rest();
+ assert_eq!(v, &[0, 6]);
+}
+
+#[test]
fn test_splice() {
let mut v = vec![1, 2, 3, 4, 5];
let a = [10, 11, 12];
@@ -1030,6 +1105,12 @@ fn test_into_iter_drop_allocator() {
}
#[test]
+fn test_into_iter_zst() {
+ for _ in vec![[0u64; 0]].into_iter() {}
+ for _ in vec![[0u64; 0]; 5].into_iter().rev() {}
+}
+
+#[test]
fn test_from_iter_specialization() {
let src: Vec<usize> = vec![0usize; 1];
let srcptr = src.as_ptr();
@@ -1110,48 +1191,53 @@ fn test_from_iter_specialization_panic_during_iteration_drops() {
}
#[test]
-fn test_from_iter_specialization_panic_during_drop_leaks() {
- static mut DROP_COUNTER: usize = 0;
+fn test_from_iter_specialization_panic_during_drop_doesnt_leak() {
+ static mut DROP_COUNTER_OLD: [usize; 5] = [0; 5];
+ static mut DROP_COUNTER_NEW: [usize; 2] = [0; 2];
#[derive(Debug)]
- enum Droppable {
- DroppedTwice(Box<i32>),
- PanicOnDrop,
- }
+ struct Old(usize);
- impl Drop for Droppable {
+ impl Drop for Old {
fn drop(&mut self) {
- match self {
- Droppable::DroppedTwice(_) => {
- unsafe {
- DROP_COUNTER += 1;
- }
- println!("Dropping!")
- }
- Droppable::PanicOnDrop => {
- if !std::thread::panicking() {
- panic!();
- }
- }
+ unsafe {
+ DROP_COUNTER_OLD[self.0] += 1;
}
+
+ if self.0 == 3 {
+ panic!();
+ }
+
+ println!("Dropped Old: {}", self.0);
}
}
- let mut to_free: *mut Droppable = core::ptr::null_mut();
- let mut cap = 0;
+ #[derive(Debug)]
+ struct New(usize);
+
+ impl Drop for New {
+ fn drop(&mut self) {
+ unsafe {
+ DROP_COUNTER_NEW[self.0] += 1;
+ }
+
+ println!("Dropped New: {}", self.0);
+ }
+ }
let _ = std::panic::catch_unwind(AssertUnwindSafe(|| {
- let mut v = vec![Droppable::DroppedTwice(Box::new(123)), Droppable::PanicOnDrop];
- to_free = v.as_mut_ptr();
- cap = v.capacity();
- let _ = v.into_iter().take(0).collect::<Vec<_>>();
+ let v = vec![Old(0), Old(1), Old(2), Old(3), Old(4)];
+ let _ = v.into_iter().map(|x| New(x.0)).take(2).collect::<Vec<_>>();
}));
- assert_eq!(unsafe { DROP_COUNTER }, 1);
- // clean up the leak to keep miri happy
- unsafe {
- drop(Vec::from_raw_parts(to_free, 0, cap));
- }
+ assert_eq!(unsafe { DROP_COUNTER_OLD[0] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_OLD[1] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_OLD[2] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_OLD[3] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_OLD[4] }, 1);
+
+ assert_eq!(unsafe { DROP_COUNTER_NEW[0] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_NEW[1] }, 1);
}
// regression test for issue #85322. Peekable previously implemented InPlaceIterable,
@@ -1489,6 +1575,35 @@ fn drain_filter_unconsumed() {
}
#[test]
+fn test_drain_filter_keep_rest() {
+ let mut v = vec![0, 1, 2, 3, 4, 5, 6];
+ let mut drain = v.drain_filter(|&mut x| x % 2 == 0);
+ assert_eq!(drain.next(), Some(0));
+ assert_eq!(drain.next(), Some(2));
+
+ drain.keep_rest();
+ assert_eq!(v, &[1, 3, 4, 5, 6]);
+}
+
+#[test]
+fn test_drain_filter_keep_rest_all() {
+ let mut v = vec![0, 1, 2, 3, 4, 5, 6];
+ v.drain_filter(|_| true).keep_rest();
+ assert_eq!(v, &[0, 1, 2, 3, 4, 5, 6]);
+}
+
+#[test]
+fn test_drain_filter_keep_rest_none() {
+ let mut v = vec![0, 1, 2, 3, 4, 5, 6];
+ let mut drain = v.drain_filter(|_| true);
+
+ drain.by_ref().for_each(drop);
+
+ drain.keep_rest();
+ assert_eq!(v, &[]);
+}
+
+#[test]
fn test_reserve_exact() {
// This is all the same as test_reserve
@@ -1527,12 +1642,6 @@ fn test_try_reserve() {
const MAX_CAP: usize = isize::MAX as usize;
const MAX_USIZE: usize = usize::MAX;
- // On 16/32-bit, we check that allocations don't exceed isize::MAX,
- // on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
- // Any platform that succeeds for these requests is technically broken with
- // ptr::offset because LLVM is the worst.
- let guards_against_isize = usize::BITS < 64;
-
{
// Note: basic stuff is checked by test_reserve
let mut empty_bytes: Vec<u8> = Vec::new();
@@ -1546,35 +1655,19 @@ fn test_try_reserve() {
panic!("isize::MAX shouldn't trigger an overflow!");
}
- if guards_against_isize {
- // Check isize::MAX + 1 does count as overflow
- assert_matches!(
- empty_bytes.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()),
- Err(CapacityOverflow),
- "isize::MAX + 1 should trigger an overflow!"
- );
-
- // Check usize::MAX does count as overflow
- assert_matches!(
- empty_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
- Err(CapacityOverflow),
- "usize::MAX should trigger an overflow!"
- );
- } else {
- // Check isize::MAX + 1 is an OOM
- assert_matches!(
- empty_bytes.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()),
- Err(AllocError { .. }),
- "isize::MAX + 1 should trigger an OOM!"
- );
-
- // Check usize::MAX is an OOM
- assert_matches!(
- empty_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
- Err(AllocError { .. }),
- "usize::MAX should trigger an OOM!"
- );
- }
+ // Check isize::MAX + 1 does count as overflow
+ assert_matches!(
+ empty_bytes.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()),
+ Err(CapacityOverflow),
+ "isize::MAX + 1 should trigger an overflow!"
+ );
+
+ // Check usize::MAX does count as overflow
+ assert_matches!(
+ empty_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
+ Err(CapacityOverflow),
+ "usize::MAX should trigger an overflow!"
+ );
}
{
@@ -1587,19 +1680,13 @@ fn test_try_reserve() {
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10).map_err(|e| e.kind()) {
panic!("isize::MAX shouldn't trigger an overflow!");
}
- if guards_against_isize {
- assert_matches!(
- ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
- Err(CapacityOverflow),
- "isize::MAX + 1 should trigger an overflow!"
- );
- } else {
- assert_matches!(
- ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
- Err(AllocError { .. }),
- "isize::MAX + 1 should trigger an OOM!"
- );
- }
+
+ assert_matches!(
+ ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
+ Err(CapacityOverflow),
+ "isize::MAX + 1 should trigger an overflow!"
+ );
+
// Should always overflow in the add-to-len
assert_matches!(
ten_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
@@ -1620,19 +1707,13 @@ fn test_try_reserve() {
{
panic!("isize::MAX shouldn't trigger an overflow!");
}
- if guards_against_isize {
- assert_matches!(
- ten_u32s.try_reserve(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
- Err(CapacityOverflow),
- "isize::MAX + 1 should trigger an overflow!"
- );
- } else {
- assert_matches!(
- ten_u32s.try_reserve(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
- Err(AllocError { .. }),
- "isize::MAX + 1 should trigger an OOM!"
- );
- }
+
+ assert_matches!(
+ ten_u32s.try_reserve(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
+ Err(CapacityOverflow),
+ "isize::MAX + 1 should trigger an overflow!"
+ );
+
// Should fail in the mul-by-size
assert_matches!(
ten_u32s.try_reserve(MAX_USIZE - 20).map_err(|e| e.kind()),
@@ -1652,8 +1733,6 @@ fn test_try_reserve_exact() {
const MAX_CAP: usize = isize::MAX as usize;
const MAX_USIZE: usize = usize::MAX;
- let guards_against_isize = size_of::<usize>() < 8;
-
{
let mut empty_bytes: Vec<u8> = Vec::new();
@@ -1666,31 +1745,17 @@ fn test_try_reserve_exact() {
panic!("isize::MAX shouldn't trigger an overflow!");
}
- if guards_against_isize {
- assert_matches!(
- empty_bytes.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()),
- Err(CapacityOverflow),
- "isize::MAX + 1 should trigger an overflow!"
- );
-
- assert_matches!(
- empty_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
- Err(CapacityOverflow),
- "usize::MAX should trigger an overflow!"
- );
- } else {
- assert_matches!(
- empty_bytes.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()),
- Err(AllocError { .. }),
- "isize::MAX + 1 should trigger an OOM!"
- );
-
- assert_matches!(
- empty_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
- Err(AllocError { .. }),
- "usize::MAX should trigger an OOM!"
- );
- }
+ assert_matches!(
+ empty_bytes.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()),
+ Err(CapacityOverflow),
+ "isize::MAX + 1 should trigger an overflow!"
+ );
+
+ assert_matches!(
+ empty_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
+ Err(CapacityOverflow),
+ "usize::MAX should trigger an overflow!"
+ );
}
{
@@ -1706,19 +1771,13 @@ fn test_try_reserve_exact() {
{
panic!("isize::MAX shouldn't trigger an overflow!");
}
- if guards_against_isize {
- assert_matches!(
- ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
- Err(CapacityOverflow),
- "isize::MAX + 1 should trigger an overflow!"
- );
- } else {
- assert_matches!(
- ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
- Err(AllocError { .. }),
- "isize::MAX + 1 should trigger an OOM!"
- );
- }
+
+ assert_matches!(
+ ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
+ Err(CapacityOverflow),
+ "isize::MAX + 1 should trigger an overflow!"
+ );
+
assert_matches!(
ten_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
Err(CapacityOverflow),
@@ -1739,19 +1798,13 @@ fn test_try_reserve_exact() {
{
panic!("isize::MAX shouldn't trigger an overflow!");
}
- if guards_against_isize {
- assert_matches!(
- ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
- Err(CapacityOverflow),
- "isize::MAX + 1 should trigger an overflow!"
- );
- } else {
- assert_matches!(
- ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
- Err(AllocError { .. }),
- "isize::MAX + 1 should trigger an OOM!"
- );
- }
+
+ assert_matches!(
+ ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
+ Err(CapacityOverflow),
+ "isize::MAX + 1 should trigger an overflow!"
+ );
+
assert_matches!(
ten_u32s.try_reserve_exact(MAX_USIZE - 20).map_err(|e| e.kind()),
Err(CapacityOverflow),