1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use crate::reactor::*;
impl<S, T> Reactor<S> for [T]
where
T: Reactor<S>,
{
type Error = T::Error;
fn react(&mut self, state: &S) -> Result<(), Self::Error> {
for reducer in self {
reducer.react(state)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::mock::*;
use proptest::prelude::*;
prop_compose! {
pub(crate) fn length_and_index(max: usize)
(length in 1..=max)
(index in 0..length, length in Just(length))
-> (usize, usize) {
(length, index)
}
}
proptest! {
#[test]
fn ok(states: Vec<u8>, len in 0..=100usize) {
let reactors: &mut [Mock<_>] = &mut vec![Mock::default(); len];
for (i, state) in states.iter().enumerate() {
assert_eq!(react(reactors, state), Ok(()));
for reactor in reactors.iter() {
assert_eq!(reactor.calls(), &states[0..=i])
}
}
}
}
proptest! {
#[test]
fn err(state: u8, error: String, (len, at) in length_and_index(100)) {
let reactors: &mut [Mock<_, _>] = &mut vec![Mock::default(); len];
reactors[at].fail_if(state, &error[..]);
assert_eq!(react(reactors, &state), Err(&error[..]));
for reactor in reactors.iter().take(at + 1) {
assert_eq!(reactor.calls(), &[state])
}
for reactor in reactors.iter().skip(at + 1) {
assert_eq!(reactor.calls(), &[])
}
}
}
}