1 | use rayon::prelude::*; |
2 | |
3 | use std::panic; |
4 | use std::sync::atomic::AtomicUsize; |
5 | use std::sync::atomic::Ordering; |
6 | use std::sync::Mutex; |
7 | |
8 | #[test] |
9 | #[cfg_attr (not(panic = "unwind" ), ignore)] |
10 | fn collect_drop_on_unwind() { |
11 | struct Recorddrop<'a>(i64, &'a Mutex<Vec<i64>>); |
12 | |
13 | impl<'a> Drop for Recorddrop<'a> { |
14 | fn drop(&mut self) { |
15 | self.1.lock().unwrap().push(self.0); |
16 | } |
17 | } |
18 | |
19 | let test_collect_panic = |will_panic: bool| { |
20 | let test_vec_len = 1024; |
21 | let panic_point = 740; |
22 | |
23 | let mut inserts = Mutex::new(Vec::new()); |
24 | let mut drops = Mutex::new(Vec::new()); |
25 | |
26 | let mut a = (0..test_vec_len).collect::<Vec<_>>(); |
27 | let b = (0..test_vec_len).collect::<Vec<_>>(); |
28 | |
29 | let _result = panic::catch_unwind(panic::AssertUnwindSafe(|| { |
30 | let mut result = Vec::new(); |
31 | a.par_iter_mut() |
32 | .zip(&b) |
33 | .map(|(&mut a, &b)| { |
34 | if a > panic_point && will_panic { |
35 | panic!("unwinding for test" ); |
36 | } |
37 | let elt = a + b; |
38 | inserts.lock().unwrap().push(elt); |
39 | Recorddrop(elt, &drops) |
40 | }) |
41 | .collect_into_vec(&mut result); |
42 | |
43 | // If we reach this point, this must pass |
44 | assert_eq!(a.len(), result.len()); |
45 | })); |
46 | |
47 | let inserts = inserts.get_mut().unwrap(); |
48 | let drops = drops.get_mut().unwrap(); |
49 | println!("{:?}" , inserts); |
50 | println!("{:?}" , drops); |
51 | |
52 | assert_eq!(inserts.len(), drops.len(), "Incorrect number of drops" ); |
53 | // sort to normalize order |
54 | inserts.sort(); |
55 | drops.sort(); |
56 | assert_eq!(inserts, drops, "Incorrect elements were dropped" ); |
57 | }; |
58 | |
59 | for &should_panic in &[true, false] { |
60 | test_collect_panic(should_panic); |
61 | } |
62 | } |
63 | |
64 | #[test] |
65 | #[cfg_attr (not(panic = "unwind" ), ignore)] |
66 | fn collect_drop_on_unwind_zst() { |
67 | static INSERTS: AtomicUsize = AtomicUsize::new(0); |
68 | static DROPS: AtomicUsize = AtomicUsize::new(0); |
69 | |
70 | struct RecorddropZst; |
71 | |
72 | impl Drop for RecorddropZst { |
73 | fn drop(&mut self) { |
74 | DROPS.fetch_add(1, Ordering::SeqCst); |
75 | } |
76 | } |
77 | |
78 | let test_collect_panic = |will_panic: bool| { |
79 | INSERTS.store(0, Ordering::SeqCst); |
80 | DROPS.store(0, Ordering::SeqCst); |
81 | |
82 | let test_vec_len = 1024; |
83 | let panic_point = 740; |
84 | |
85 | let a = (0..test_vec_len).collect::<Vec<_>>(); |
86 | |
87 | let _result = panic::catch_unwind(panic::AssertUnwindSafe(|| { |
88 | let mut result = Vec::new(); |
89 | a.par_iter() |
90 | .map(|&a| { |
91 | if a > panic_point && will_panic { |
92 | panic!("unwinding for test" ); |
93 | } |
94 | INSERTS.fetch_add(1, Ordering::SeqCst); |
95 | RecorddropZst |
96 | }) |
97 | .collect_into_vec(&mut result); |
98 | |
99 | // If we reach this point, this must pass |
100 | assert_eq!(a.len(), result.len()); |
101 | })); |
102 | |
103 | let inserts = INSERTS.load(Ordering::SeqCst); |
104 | let drops = DROPS.load(Ordering::SeqCst); |
105 | |
106 | assert_eq!(inserts, drops, "Incorrect number of drops" ); |
107 | assert!(will_panic || drops == test_vec_len) |
108 | }; |
109 | |
110 | for &should_panic in &[true, false] { |
111 | test_collect_panic(should_panic); |
112 | } |
113 | } |
114 | |