Skip to content

Commit

Permalink
Rollup merge of #99386 - AngelicosPhosphoros:add_retain_test_maybeuni…
Browse files Browse the repository at this point in the history
…nit, r=JohnTitor

Add tests that check `Vec::retain` predicate execution order.

This behaviour is documented for `Vec::retain` which means that there is code that rely on that but there weren't tests about that.
  • Loading branch information
Dylan-DPC authored Aug 22, 2022
2 parents a4950ef + 85a9c74 commit 33b5ce6
Showing 1 changed file with 45 additions and 0 deletions.
45 changes: 45 additions & 0 deletions library/alloc/tests/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,22 @@ fn test_retain() {
assert_eq!(vec, [2, 4]);
}

#[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<_>>();
Expand Down Expand Up @@ -354,6 +370,35 @@ fn test_retain_drop_panic() {
assert!(v.iter().all(|r| Rc::strong_count(r) == 1));
}

#[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>) {
Expand Down

0 comments on commit 33b5ce6

Please sign in to comment.