makepad/tools/run/fixture/diff/vec_retain.rs

44 lines
1.9 KiB
Rust

// diff_fast corpus program: Vec::retain / retain_mut (Relax's std ports real alloc's two-loop form):
// kept order, drops of removed elements, and the Vec after a predicate panics midway (real std keeps
// the unvisited tail, shifted over the holes). rustc --test -O and `makepad test` (all tiers) must
// print identical D lines.
use std::cell::Cell;
use std::rc::Rc;
macro_rules! d { ($($a:tt)*) => { println!("D {}", format!($($a)*)) } }
fn rounds(f: fn()) {
let ms: u64 = std::env::var("DIFF_SLEEP_MS").ok().and_then(|v| v.parse().ok()).unwrap_or(0);
for r in 0..4 { f(); if r < 3 && ms > 0 { std::thread::sleep(std::time::Duration::from_millis(ms)); } }
}
#[test]
fn run() { rounds(work); }
struct T(u32, Rc<Cell<u32>>);
impl Drop for T { fn drop(&mut self) { self.1.set(self.1.get() + 1); } }
fn work() {
let mut a: Vec<u32> = (0..50).collect();
a.retain(|x| x % 3 != 0);
d!("retain u32 {} {:?}", a.len(), &a[..8]);
let mut all: Vec<u32> = (0..10).collect();
all.retain(|_| true);
d!("keep all {:?}", all);
let mut none: Vec<u32> = (0..10).collect();
none.retain(|_| false);
d!("keep none {}", none.len());
let mut m: Vec<u32> = (0..20).collect();
m.retain_mut(|x| { *x *= 2; *x % 4 == 0 });
d!("retain_mut {:?}", m);
let drops = Rc::new(Cell::new(0));
let mut v: Vec<T> = (0..12).map(|i| T(i, drops.clone())).collect();
v.retain(|t| t.0 % 2 == 1);
d!("drops after retain {} left {:?}", drops.get(), v.iter().map(|t| t.0).collect::<Vec<_>>());
drops.set(0);
let mut p: Vec<T> = (0..12).map(|i| T(i, drops.clone())).collect();
let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
p.retain(|t| {
if t.0 == 7 { panic!("stop") }
t.0 % 3 != 0
});
}));
d!("panicked {} drops {} vec {:?}", r.is_err(), drops.get(), p.iter().map(|t| t.0).collect::<Vec<_>>());
}