114 lines
3.3 KiB
Rust
114 lines
3.3 KiB
Rust
|
use rayon::prelude::*;
|
||
|
|
||
|
use std::panic;
|
||
|
use std::sync::atomic::AtomicUsize;
|
||
|
use std::sync::atomic::Ordering;
|
||
|
use std::sync::Mutex;
|
||
|
|
||
|
#[test]
|
||
|
#[cfg_attr(not(panic = "unwind"), ignore)]
|
||
|
fn collect_drop_on_unwind() {
|
||
|
struct Recorddrop<'a>(i64, &'a Mutex<Vec<i64>>);
|
||
|
|
||
|
impl<'a> Drop for Recorddrop<'a> {
|
||
|
fn drop(&mut self) {
|
||
|
self.1.lock().unwrap().push(self.0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let test_collect_panic = |will_panic: bool| {
|
||
|
let test_vec_len = 1024;
|
||
|
let panic_point = 740;
|
||
|
|
||
|
let mut inserts = Mutex::new(Vec::new());
|
||
|
let mut drops = Mutex::new(Vec::new());
|
||
|
|
||
|
let mut a = (0..test_vec_len).collect::<Vec<_>>();
|
||
|
let b = (0..test_vec_len).collect::<Vec<_>>();
|
||
|
|
||
|
let _result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||
|
let mut result = Vec::new();
|
||
|
a.par_iter_mut()
|
||
|
.zip(&b)
|
||
|
.map(|(&mut a, &b)| {
|
||
|
if a > panic_point && will_panic {
|
||
|
panic!("unwinding for test");
|
||
|
}
|
||
|
let elt = a + b;
|
||
|
inserts.lock().unwrap().push(elt);
|
||
|
Recorddrop(elt, &drops)
|
||
|
})
|
||
|
.collect_into_vec(&mut result);
|
||
|
|
||
|
// If we reach this point, this must pass
|
||
|
assert_eq!(a.len(), result.len());
|
||
|
}));
|
||
|
|
||
|
let inserts = inserts.get_mut().unwrap();
|
||
|
let drops = drops.get_mut().unwrap();
|
||
|
println!("{:?}", inserts);
|
||
|
println!("{:?}", drops);
|
||
|
|
||
|
assert_eq!(inserts.len(), drops.len(), "Incorrect number of drops");
|
||
|
// sort to normalize order
|
||
|
inserts.sort();
|
||
|
drops.sort();
|
||
|
assert_eq!(inserts, drops, "Incorrect elements were dropped");
|
||
|
};
|
||
|
|
||
|
for &should_panic in &[true, false] {
|
||
|
test_collect_panic(should_panic);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
#[cfg_attr(not(panic = "unwind"), ignore)]
|
||
|
fn collect_drop_on_unwind_zst() {
|
||
|
static INSERTS: AtomicUsize = AtomicUsize::new(0);
|
||
|
static DROPS: AtomicUsize = AtomicUsize::new(0);
|
||
|
|
||
|
struct RecorddropZst;
|
||
|
|
||
|
impl Drop for RecorddropZst {
|
||
|
fn drop(&mut self) {
|
||
|
DROPS.fetch_add(1, Ordering::SeqCst);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let test_collect_panic = |will_panic: bool| {
|
||
|
INSERTS.store(0, Ordering::SeqCst);
|
||
|
DROPS.store(0, Ordering::SeqCst);
|
||
|
|
||
|
let test_vec_len = 1024;
|
||
|
let panic_point = 740;
|
||
|
|
||
|
let a = (0..test_vec_len).collect::<Vec<_>>();
|
||
|
|
||
|
let _result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||
|
let mut result = Vec::new();
|
||
|
a.par_iter()
|
||
|
.map(|&a| {
|
||
|
if a > panic_point && will_panic {
|
||
|
panic!("unwinding for test");
|
||
|
}
|
||
|
INSERTS.fetch_add(1, Ordering::SeqCst);
|
||
|
RecorddropZst
|
||
|
})
|
||
|
.collect_into_vec(&mut result);
|
||
|
|
||
|
// If we reach this point, this must pass
|
||
|
assert_eq!(a.len(), result.len());
|
||
|
}));
|
||
|
|
||
|
let inserts = INSERTS.load(Ordering::SeqCst);
|
||
|
let drops = DROPS.load(Ordering::SeqCst);
|
||
|
|
||
|
assert_eq!(inserts, drops, "Incorrect number of drops");
|
||
|
assert!(will_panic || drops == test_vec_len)
|
||
|
};
|
||
|
|
||
|
for &should_panic in &[true, false] {
|
||
|
test_collect_panic(should_panic);
|
||
|
}
|
||
|
}
|