aboutsummaryrefslogtreecommitdiff
path: root/crates/test_utils
diff options
context:
space:
mode:
Diffstat (limited to 'crates/test_utils')
-rw-r--r--crates/test_utils/src/lib.rs2
-rw-r--r--crates/test_utils/src/mark.rs78
2 files changed, 0 insertions, 80 deletions
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index 6041ab5e4..c5f859790 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -6,8 +6,6 @@
6//! * Extracting markup (mainly, `$0` markers) out of fixture strings. 6//! * Extracting markup (mainly, `$0` markers) out of fixture strings.
7//! * marks (see the eponymous module). 7//! * marks (see the eponymous module).
8 8
9#[macro_use]
10pub mod mark;
11pub mod bench_fixture; 9pub mod bench_fixture;
12mod fixture; 10mod fixture;
13 11
diff --git a/crates/test_utils/src/mark.rs b/crates/test_utils/src/mark.rs
deleted file mode 100644
index 97f5a93ad..000000000
--- a/crates/test_utils/src/mark.rs
+++ /dev/null
@@ -1,78 +0,0 @@
1//! This module implements manually tracked test coverage, which is useful for
2//! quickly finding a test responsible for testing a particular bit of code.
3//!
4//! See <https://matklad.github.io/2018/06/18/a-trick-for-test-maintenance.html>
5//! for details, but the TL;DR is that you write your test as
6//!
7//! ```
8//! #[test]
9//! fn test_foo() {
10//! mark::check!(test_foo);
11//! }
12//! ```
13//!
14//! and in the code under test you write
15//!
16//! ```
17//! # use test_utils::mark;
18//! # fn some_condition() -> bool { true }
19//! fn foo() {
20//! if some_condition() {
21//! mark::hit!(test_foo);
22//! }
23//! }
24//! ```
25//!
26//! This module then checks that executing the test indeed covers the specified
27//! function. This is useful if you come back to the `foo` function ten years
28//! later and wonder where the test are: now you can grep for `test_foo`.
29use std::sync::atomic::{AtomicUsize, Ordering};
30
31#[macro_export]
32macro_rules! _hit {
33 ($ident:ident) => {{
34 #[cfg(test)]
35 {
36 extern "C" {
37 #[no_mangle]
38 static $ident: std::sync::atomic::AtomicUsize;
39 }
40 unsafe {
41 $ident.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
42 }
43 }
44 }};
45}
46pub use _hit as hit;
47
48#[macro_export]
49macro_rules! _check {
50 ($ident:ident) => {
51 #[no_mangle]
52 static $ident: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
53 let _checker = $crate::mark::MarkChecker::new(&$ident);
54 };
55}
56pub use _check as check;
57
58pub struct MarkChecker {
59 mark: &'static AtomicUsize,
60 value_on_entry: usize,
61}
62
63impl MarkChecker {
64 pub fn new(mark: &'static AtomicUsize) -> MarkChecker {
65 let value_on_entry = mark.load(Ordering::Relaxed);
66 MarkChecker { mark, value_on_entry }
67 }
68}
69
70impl Drop for MarkChecker {
71 fn drop(&mut self) {
72 if std::thread::panicking() {
73 return;
74 }
75 let value_on_exit = self.mark.load(Ordering::Relaxed);
76 assert!(value_on_exit > self.value_on_entry, "mark was not hit")
77 }
78}