run_make_support/assertion_helpers/
mod.rs
1#[cfg(test)]
4mod tests;
5
6use std::panic;
7use std::path::Path;
8
9use crate::{fs, regex};
10
11#[track_caller]
13pub fn assert_equals<A: AsRef<str>, E: AsRef<str>>(actual: A, expected: E) {
14 let actual = actual.as_ref();
15 let expected = expected.as_ref();
16
17 if actual != expected {
18 eprintln!("=== ACTUAL TEXT ===");
19 eprintln!("{}", actual);
20 eprintln!("=== EXPECTED ===");
21 eprintln!("{}", expected);
22 panic!("expected text does not match actual text");
23 }
24}
25
26struct SearchDetails<'assertion_name, 'haystack, 'needle> {
27 assertion_name: &'assertion_name str,
28 haystack: &'haystack str,
29 needle: &'needle str,
30}
31
32impl<'assertion_name, 'haystack, 'needle> SearchDetails<'assertion_name, 'haystack, 'needle> {
33 fn dump(&self) {
34 eprintln!("{}:", self.assertion_name);
35 eprintln!("=== HAYSTACK ===");
36 eprintln!("{}", self.haystack);
37 eprintln!("=== NEEDLE ===");
38 eprintln!("{}", self.needle);
39 }
40}
41
42#[track_caller]
44pub fn assert_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
45 let haystack = haystack.as_ref();
46 let needle = needle.as_ref();
47 if !haystack.contains(needle) {
48 SearchDetails { assertion_name: "assert_contains", haystack, needle }.dump();
49 panic!("needle was not found in haystack");
50 }
51}
52
53#[track_caller]
55pub fn assert_not_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
56 let haystack = haystack.as_ref();
57 let needle = needle.as_ref();
58 if haystack.contains(needle) {
59 SearchDetails { assertion_name: "assert_not_contains", haystack, needle }.dump();
60 panic!("needle was unexpectedly found in haystack");
61 }
62}
63
64#[track_caller]
66pub fn assert_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
67 let haystack = haystack.as_ref();
68 let needle = needle.as_ref();
69 let re = regex::Regex::new(needle).unwrap();
70 if !re.is_match(haystack) {
71 SearchDetails { assertion_name: "assert_contains_regex", haystack, needle }.dump();
72 panic!("regex was not found in haystack");
73 }
74}
75
76#[track_caller]
78pub fn assert_not_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
79 let haystack = haystack.as_ref();
80 let needle = needle.as_ref();
81 let re = regex::Regex::new(needle).unwrap();
82 if re.is_match(haystack) {
83 SearchDetails { assertion_name: "assert_not_contains_regex", haystack, needle }.dump();
84 panic!("regex was unexpectedly found in haystack");
85 }
86}
87
88#[track_caller]
90pub fn assert_count_is<H: AsRef<str>, N: AsRef<str>>(
91 expected_count: usize,
92 haystack: H,
93 needle: N,
94) {
95 let haystack = haystack.as_ref();
96 let needle = needle.as_ref();
97
98 let actual_count = haystack.matches(needle).count();
99 if expected_count != actual_count {
100 let count_fmt = format!(
101 "assert_count_is (expected_count = {expected_count}, actual_count = {actual_count})"
102 );
103 SearchDetails { assertion_name: &count_fmt, haystack, needle }.dump();
104 panic!(
105 "regex did not appear {expected_count} times in haystack (expected_count = \
106 {expected_count}, actual_count = {actual_count})"
107 );
108 }
109}
110
111pub fn assert_dirs_are_equal(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
114 let dir2 = dir2.as_ref();
115 fs::read_dir_entries(dir1, |entry_path| {
116 let entry_name = entry_path.file_name().unwrap();
117 if entry_path.is_dir() {
118 assert_dirs_are_equal(&entry_path, &dir2.join(entry_name));
119 } else {
120 let path2 = dir2.join(entry_name);
121 let file1 = fs::read(&entry_path);
122 let file2 = fs::read(&path2);
123
124 assert!(
128 file1 == file2,
129 "`{}` and `{}` have different content",
130 entry_path.display(),
131 path2.display(),
132 );
133 }
134 });
135}