1use std::sync::Mutex;
8
9#[macro_export]
11macro_rules! assert_lt {
12 ($x:expr, $y:expr) => {
13 assert!(
14 $x < $y,
15 "assertion `{} < {}` failed; actual: {:?} is not less than {:?}",
16 stringify!($x),
17 stringify!($y),
18 $x,
19 $y
20 );
21 };
22}
23
24#[macro_export]
26macro_rules! assert_leq {
27 ($x:expr, $y:expr) => {
28 assert!(
29 $x <= $y,
30 "assertion `{} <= {}` failed; actual: {:?} is not less than or equal to {:?}",
31 stringify!($x),
32 stringify!($y),
33 $x,
34 $y
35 );
36 };
37}
38
39#[macro_export]
41macro_rules! assert_gt {
42 ($x:expr, $y:expr) => {
43 assert!(
44 $x > $y,
45 "assertion `{} > {}` failed; actual: {:?} is not greater than {:?}",
46 stringify!($x),
47 stringify!($y),
48 $x,
49 $y
50 );
51 };
52}
53
54#[macro_export]
56macro_rules! assert_geq {
57 ($x:expr, $y:expr) => {
58 assert!(
59 $x >= $y,
60 "assertion `{} >= {}` failed; actual: {:?} is not greater than or equal to {:?}",
61 stringify!($x),
62 stringify!($y),
63 $x,
64 $y
65 );
66 };
67}
68
69#[macro_export]
76macro_rules! assert_near {
77 ($x: expr, $y: expr, $delta: expr) => {
78 let difference = $x - $y;
79 assert!(
80 (-$delta..=$delta).contains(&difference),
81 "assertion `{} is near {} (within delta {})` failed; actual: |{:?} - {:?}| > {:?}",
82 stringify!($x),
83 stringify!($y),
84 stringify!($delta),
85 $x,
86 $y,
87 $delta
88 );
89 };
90}
91
92pub struct Counter {
146 count: Mutex<usize>,
147}
148
149impl Counter {
150 pub fn new(initial: usize) -> Self {
152 Counter { count: Mutex::new(initial) }
153 }
154
155 pub fn inc(&self) -> usize {
157 let mut count = self.count.lock().unwrap();
158 *count += 1;
159 *count
160 }
161
162 pub fn get(&self) -> usize {
164 *self.count.lock().unwrap()
165 }
166}
167
168impl std::fmt::Debug for Counter {
169 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170 f.debug_struct("Counter").field("count", &self.get()).finish()
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177 use lazy_static::lazy_static;
178 use std::collections::BTreeSet;
179 use std::sync::mpsc;
180 use std::sync::mpsc::{Receiver, Sender};
181 use std::thread;
182
183 #[derive(Debug, PartialEq, PartialOrd)]
184 struct NotDisplay {
185 x: i32,
186 }
187
188 impl core::ops::Sub for NotDisplay {
189 type Output = Self;
190
191 fn sub(self, other: Self) -> Self {
192 NotDisplay { x: self.x - other.x }
193 }
194 }
195
196 impl core::ops::Neg for NotDisplay {
197 type Output = Self;
198
199 fn neg(self) -> Self {
200 NotDisplay { x: -self.x }
201 }
202 }
203
204 #[test]
205 fn test_assert_lt_passes() {
206 assert_lt!(1, 2);
207 assert_lt!(1u8, 2u8);
208 assert_lt!(1u16, 2u16);
209 assert_lt!(1u32, 2u32);
210 assert_lt!(1u64, 2u64);
211 assert_lt!(-1, 3);
212 assert_lt!(-1i8, 3i8);
213 assert_lt!(-1i16, 3i16);
214 assert_lt!(-1i32, 3i32);
215 assert_lt!(-1i64, 3i64);
216 assert_lt!(-2.0, 7.0);
217 assert_lt!(-2.0f32, 7.0f32);
218 assert_lt!(-2.0f64, 7.0f64);
219 assert_lt!('a', 'b');
220 assert_lt!(NotDisplay { x: 1 }, NotDisplay { x: 2 });
221 }
222
223 #[test]
224 #[should_panic(expected = "assertion `a < b` failed; actual: 2 is not less than 2")]
225 fn test_assert_lt_fails_a_equals_b() {
226 let a = 2;
227 let b = 2;
228 assert_lt!(a, b);
229 }
230
231 #[test]
232 #[should_panic(expected = "assertion `a < b` failed; actual: 5 is not less than 2")]
233 fn test_assert_lt_fails_a_greater_than_b() {
234 let a = 5;
235 let b = 2;
236 assert_lt!(a, b);
237 }
238
239 #[test]
240 fn test_assert_leq_passes() {
241 assert_leq!(1, 2);
242 assert_leq!(2, 2);
243 assert_leq!(-2.0, 3.0);
244 assert_leq!(3.0, 3.0);
245 assert_leq!('a', 'b');
246 assert_leq!('b', 'b');
247 assert_leq!(NotDisplay { x: 1 }, NotDisplay { x: 2 });
248 assert_leq!(NotDisplay { x: 2 }, NotDisplay { x: 2 });
249 }
250
251 #[test]
252 #[should_panic(
253 expected = "assertion `a <= b` failed; actual: 3 is not less than or equal to 2"
254 )]
255 fn test_assert_leq_fails() {
256 let a = 3;
257 let b = 2;
258 assert_leq!(a, b);
259 }
260
261 #[test]
262 fn test_assert_gt_passes() {
263 assert_gt!(2, 1);
264 assert_gt!(2u8, 1u8);
265 assert_gt!(2u16, 1u16);
266 assert_gt!(2u32, 1u32);
267 assert_gt!(2u64, 1u64);
268 assert_gt!(3, -1);
269 assert_gt!(3i8, -1i8);
270 assert_gt!(3i16, -1i16);
271 assert_gt!(3i32, -1i32);
272 assert_gt!(3i64, -1i64);
273 assert_gt!(7.0, -2.0);
274 assert_gt!(7.0f32, -2.0f32);
275 assert_gt!(7.0f64, -2.0f64);
276 assert_gt!('b', 'a');
277 assert_gt!(NotDisplay { x: 2 }, NotDisplay { x: 1 });
278 }
279
280 #[test]
281 #[should_panic(expected = "assertion `a > b` failed; actual: 2 is not greater than 2")]
282 fn test_assert_gt_fails_a_equals_b() {
283 let a = 2;
284 let b = 2;
285 assert_gt!(a, b);
286 }
287
288 #[test]
289 #[should_panic(expected = "assertion `a > b` failed; actual: -1 is not greater than 2")]
290 fn test_assert_gt_fails_a_less_than_b() {
291 let a = -1;
292 let b = 2;
293 assert_gt!(a, b);
294 }
295
296 #[test]
297 fn test_assert_geq_passes() {
298 assert_geq!(2, 1);
299 assert_geq!(2, 2);
300 assert_geq!(3.0, -2.0);
301 assert_geq!(3.0, 3.0);
302 assert_geq!('b', 'a');
303 assert_geq!('b', 'b');
304 assert_geq!(NotDisplay { x: 2 }, NotDisplay { x: 1 });
305 assert_geq!(NotDisplay { x: 2 }, NotDisplay { x: 2 });
306 }
307
308 #[test]
309 #[should_panic(
310 expected = "assertion `a >= b` failed; actual: 2 is not greater than or equal to 3"
311 )]
312 fn test_assert_geq_fails() {
313 let a = 2;
314 let b = 3;
315 assert_geq!(a, b);
316 }
317
318 #[test]
319 fn test_assert_near_passes() {
320 assert_near!(1.0001, 1.0, 0.01);
322 assert_near!(1.0, 1.0001, 0.01);
323 assert_near!(1.0, 1.0, 0.0);
324
325 assert_near!(1.0001f32, 1.0f32, 0.01f32);
327 assert_near!(1.0001f64, 1.0f64, 0.01f64);
328 assert_near!(7, 5, 2);
329 assert_near!(7i8, 5i8, 2i8);
330 assert_near!(7i16, 5i16, 2i16);
331 assert_near!(7i32, 5i32, 2i32);
332 assert_near!(7i64, 5i64, 2i64);
333
334 assert_near!(NotDisplay { x: 7 }, NotDisplay { x: 5 }, NotDisplay { x: 2 });
335 }
336
337 #[test]
338 #[should_panic]
339 fn test_assert_near_fails() {
340 assert_near!(1.00001, 1.0, 1e-8);
341 }
342
343 #[test]
345 #[should_panic(
346 expected = "assertion `a is near b (within delta d)` failed; actual: |3 - 5| > 1"
347 )]
348 fn test_assert_near_fails_with_message() {
349 let a = 3;
350 let b = 5;
351 let d = 1;
352 assert_near!(a, b, d);
353 }
354
355 #[test]
356 fn test_inc() {
357 lazy_static! {
358 static ref CALL_COUNT: Counter = Counter::new(0);
359 }
360
361 CALL_COUNT.inc();
362
363 assert_eq!(CALL_COUNT.get(), 1);
364 }
365
366 #[test]
367 fn test_incs_from_10() {
368 lazy_static! {
369 static ref CALL_COUNT: Counter = Counter::new(10);
370 }
371
372 CALL_COUNT.inc();
373 CALL_COUNT.inc();
374 CALL_COUNT.inc();
375
376 assert_eq!(CALL_COUNT.get(), 13);
377 }
378
379 #[test]
380 fn async_counts() {
381 lazy_static! {
382 static ref CALL_COUNT: Counter = Counter::new(0);
383 }
384
385 let (tx, rx): (Sender<usize>, Receiver<usize>) = mpsc::channel();
386 let mut children = Vec::new();
387
388 static NTHREADS: usize = 10;
389
390 for _ in 0..NTHREADS {
391 let thread_tx = tx.clone();
392 let child = thread::spawn(move || {
393 let new_value = CALL_COUNT.inc();
394 thread_tx.send(new_value).unwrap();
395 println!("Sent: {} (OK if out of order)", new_value);
396 });
397
398 children.push(child);
399 }
400
401 let mut ordered_ids: BTreeSet<usize> = BTreeSet::new();
402 for _ in 0..NTHREADS {
403 let received_id = rx.recv().unwrap();
404 println!("Received: {} (OK if in yet a different order)", received_id);
405 ordered_ids.insert(received_id);
406 }
407
408 for child in children {
410 child.join().expect("child thread panicked");
411 }
412
413 assert_eq!(CALL_COUNT.get(), NTHREADS);
415
416 let mut expected_id: usize = 1;
419 for id in ordered_ids.iter() {
420 assert_eq!(*id, expected_id);
421 expected_id += 1;
422 }
423 }
424
425 #[test]
426 fn debug_format_counter() {
427 let counter = Counter::new(0);
428 assert_eq!(format!("{:?}", counter), "Counter { count: 0 }");
429 }
430}