Skip to content

Commit 9532eb5

Browse files
committed
Make test 'iter_panic_fuse' deterministic
Fixes rayon-rs#667 'panic_fuse' will only stop other threads 'as soon as possible' - if the other threads are fast enough, they might end up processing the entire rest of the iterator. This commit changes the test 'iter_panic_fuse' to properly take this into account, by creating a custom threadpool with only 1 thread. This makes the test deterministic - with only one thread, the panic is guaranmteed to be observed when the next item is processed, causing the desired early exit. I've also added the 'more-asserts' crate as a dev dependency, so that we can print out a more informative error message in 'iter_panic_fuse'
1 parent b8b97a1 commit 9532eb5

File tree

2 files changed

+28
-21
lines changed

2 files changed

+28
-21
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@ rand_xorshift = "0.1"
3434
serde = "1"
3535
serde_derive = "1"
3636
doc-comment = "0.3"
37+
more-asserts = "0.2.1"

tests/iter_panic.rs

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
extern crate rayon;
2+
#[macro_use]
3+
extern crate more_asserts;
24

35
use rayon::prelude::*;
46
use std::ops::Range;
@@ -22,26 +24,30 @@ fn iter_panic() {
2224

2325
#[test]
2426
fn iter_panic_fuse() {
25-
fn count(iter: impl ParallelIterator + UnwindSafe) -> usize {
26-
let count = AtomicUsize::new(0);
27-
let result = panic::catch_unwind(|| {
28-
iter.for_each(|_| {
29-
count.fetch_add(1, Ordering::Relaxed);
27+
// We only use a single thread in order to make the behavior
28+
// of 'panic_fuse' deterministic
29+
rayon::ThreadPoolBuilder::new().num_threads(1).build().unwrap().install(|| {
30+
fn count(iter: impl ParallelIterator + UnwindSafe) -> usize {
31+
let count = AtomicUsize::new(0);
32+
let result = panic::catch_unwind(|| {
33+
iter.for_each(|_| {
34+
count.fetch_add(1, Ordering::Relaxed);
35+
});
3036
});
31-
});
32-
assert!(result.is_err());
33-
count.into_inner()
34-
}
35-
36-
// Without `panic_fuse()`, we'll reach every item except the panicking one.
37-
let expected = ITER.len() - 1;
38-
let iter = ITER.into_par_iter().with_max_len(1);
39-
assert_eq!(count(iter.clone().inspect(check)), expected);
40-
41-
// With `panic_fuse()` anywhere in the chain, we'll reach fewer items.
42-
assert!(count(iter.clone().inspect(check).panic_fuse()) < expected);
43-
assert!(count(iter.clone().panic_fuse().inspect(check)) < expected);
44-
45-
// Try in reverse to be sure we hit the producer case.
46-
assert!(count(iter.clone().panic_fuse().inspect(check).rev()) < expected);
37+
assert!(result.is_err());
38+
count.into_inner()
39+
}
40+
41+
// Without `panic_fuse()`, we'll reach every item except the panicking one.
42+
let expected = ITER.len() - 1;
43+
let iter = ITER.into_par_iter().with_max_len(1);
44+
assert_eq!(count(iter.clone().inspect(check)), expected);
45+
46+
// With `panic_fuse()` anywhere in the chain, we'll reach fewer items.
47+
assert_lt!(count(iter.clone().inspect(check).panic_fuse()), expected);
48+
assert_lt!(count(iter.clone().panic_fuse().inspect(check)), expected);
49+
50+
// Try in reverse to be sure we hit the producer case.
51+
assert_lt!(count(iter.clone().panic_fuse().inspect(check).rev()), expected);
52+
});
4753
}

0 commit comments

Comments
 (0)