repeated_assert/
macros.rs1#![allow(deprecated)]
2
3#[deprecated(
17 since = "0.2.0",
18 note = "Use `repeated_assert::that` or `repeated_assert::with_catch` instead."
19)]
20#[macro_export]
21macro_rules! repeated_assert {
22 ($repetitions:expr, $delay:expr; $($tt:tt)*) => {
23 for i in 0..$repetitions {
24 if i == $repetitions - 1 {
25 __repeated_assert!{ @final, $($tt)* }
26 } else {
27 if __repeated_assert!{ $($tt)* } {
28 break;
29 }
30 ::std::thread::sleep($delay);
31 }
32 }
33 };
34 ($repetitions:expr, $delay:expr, $repetitions_catch:expr, $catch:block; $($tt:tt)*) => {
35 for i in 0..$repetitions {
36 if i == $repetitions - 1 {
37 __repeated_assert!{ @final, $($tt)* }
38 } else if i == $repetitions_catch {
39 let thread_name = ::std::thread::current().name().unwrap_or("unnamed thread").to_owned();
40 println!("{}: executing repeated-assert catch block", thread_name);
41 $catch
42 ::std::thread::sleep($delay);
43 } else {
44 if __repeated_assert!{ $($tt)* } {
45 break;
46 }
47 ::std::thread::sleep($delay);
48 }
49 }
50 };
51}
52
53#[doc(hidden)]
54#[macro_export]
55macro_rules! __repeated_assert {
56 (@final, if $expr:expr;) => {
57 assert!($expr);
58 };
59 (@final, eq $left:expr, $right:expr;) => {
60 assert_eq!($left, $right, stringify!($left != $right));
61 };
62 (@final, if $expr:expr; $($tt:tt)+) => {
63 assert!($expr);
64 __repeated_assert!{ @final, $($tt)+ }
65 };
66 (@final, eq $left:expr, $right:expr; $($tt:tt)+) => {
67 assert_eq!($left, $right, stringify!($left != $right));
68 __repeated_assert!{ @final, $($tt)+ }
69 };
70 (@final, let $($pat:pat)|+ = $expr:expr; $($tt:tt)+) => {
71 match $expr {
72 $($pat)|+ => { __repeated_assert!{ @final, $($tt)+ } }
73 }
74 };
75 (if $expr:expr;) => {
76 $expr
77 };
78 (eq $left:expr, $right:expr;) => {
79 $left == $right
80 };
81 (if $expr:expr; $($tt:tt)+) => {
82 if $expr {
83 __repeated_assert!{ $($tt)+ }
84 } else {
85 false
86 }
87 };
88 (eq $left:expr, $right:expr; $($tt:tt)+) => {
89 if $left == $right {
90 __repeated_assert!{ $($tt)+ }
91 } else {
92 false
93 }
94 };
95 (let $($pat:pat)|+ = $expr:expr; $($tt:tt)+) => {
96 match $expr {
97 $($pat)|+ => { __repeated_assert!{ $($tt)+ } }
98 }
99 };
100}
101
102#[cfg(test)]
103mod tests {
104 use std::sync::{Arc, Mutex};
105 use std::thread;
106 use std::time::Duration;
107
108 static STEP_MS: u64 = 100;
109
110 fn spawn_thread(x: Arc<Mutex<i32>>) {
111 thread::spawn(move || loop {
112 thread::sleep(Duration::from_millis(10 * STEP_MS));
113 if let Ok(mut x) = x.lock() {
114 *x += 1;
115 }
116 });
117 }
118
119 #[test]
120 fn single_success() {
121 let x = Arc::new(Mutex::new(0));
122
123 spawn_thread(x.clone());
124
125 repeated_assert! { 5, Duration::from_millis(5 * STEP_MS);
126 if *x.lock().unwrap() > 0;
127 };
128 }
129
130 #[test]
131 #[should_panic(expected = "assertion failed: *x.lock().unwrap() > 0")]
132 fn single_failure() {
133 let x = Arc::new(Mutex::new(0));
134
135 spawn_thread(x.clone());
136
137 repeated_assert! { 3, Duration::from_millis(STEP_MS);
138 if *x.lock().unwrap() > 0;
139 };
140 }
141
142 #[test]
143 fn multiple_success() {
144 let x = Arc::new(Mutex::new(0));
145 let a = 11;
146 let b = 11;
147
148 spawn_thread(x.clone());
149
150 repeated_assert! { 5, Duration::from_millis(5 * STEP_MS);
151 if *x.lock().unwrap() > 0;
152 eq a, b;
153 };
154 }
155
156 #[test]
157 #[should_panic(expected = "assertion failed: *x.lock().unwrap() > 0")]
158 fn multiple_failure_1() {
159 let x = Arc::new(Mutex::new(0));
160 let a = 11;
161 let b = 11;
162
163 spawn_thread(x.clone());
164
165 repeated_assert! { 3, Duration::from_millis(STEP_MS);
166 if *x.lock().unwrap() > 0;
167 eq a, b;
168 };
169 }
170
171 #[test]
172 #[should_panic(expected = "a != b")]
173 fn multiple_failure_2() {
174 let x = Arc::new(Mutex::new(0));
175 let a = 11;
176 let b = 12;
177
178 spawn_thread(x.clone());
179
180 repeated_assert! { 5, Duration::from_millis(5 * STEP_MS);
181 if *x.lock().unwrap() > 0;
182 eq a, b;
183 };
184 }
185
186 #[test]
187 fn let_success() {
188 let x = Arc::new(Mutex::new(0));
189
190 spawn_thread(x.clone());
191
192 repeated_assert! { 5, Duration::from_millis(5 * STEP_MS);
193 let y = *x.lock().unwrap();
194 if y > 0;
195 };
196 }
197
198 #[test]
199 #[should_panic(expected = "assertion failed: y > 0")]
200 fn let_failure() {
201 let x = Arc::new(Mutex::new(0));
202
203 spawn_thread(x.clone());
204
205 repeated_assert! { 3, Duration::from_millis(STEP_MS);
206 let y = *x.lock().unwrap();
207 if y > 0;
208 };
209 }
210
211 #[test]
212 fn catch() {
213 let x = Arc::new(Mutex::new(-1_000));
214
215 spawn_thread(x.clone());
216
217 repeated_assert! { 10, Duration::from_millis(5 * STEP_MS), 5, {
218 *x.lock().unwrap() = 0;
219 };
220 if *x.lock().unwrap() > 0;
221 };
222 }
223}