@@ -8,83 +8,108 @@ use std::path::Path;
88
99use crate :: { fs, regex} ;
1010
11- fn print < ' a , ' e , A : AsRef < str > , E : AsRef < str > > (
12- assertion_kind : & str ,
13- haystack : & ' a A ,
14- needle : & ' e E ,
15- ) -> ( & ' a str , & ' e str ) {
16- let haystack = haystack. as_ref ( ) ;
17- let needle = needle. as_ref ( ) ;
18- eprintln ! ( "{assertion_kind}:" ) ;
19- eprintln ! ( "=== HAYSTACK ===" ) ;
20- eprintln ! ( "{}" , haystack) ;
21- eprintln ! ( "=== NEEDLE ===" ) ;
22- eprintln ! ( "{}" , needle) ;
23- ( haystack, needle)
24- }
25-
2611/// Assert that `actual` is equal to `expected`.
2712#[ track_caller]
2813pub fn assert_equals < A : AsRef < str > , E : AsRef < str > > ( actual : A , expected : E ) {
2914 let actual = actual. as_ref ( ) ;
3015 let expected = expected. as_ref ( ) ;
31- eprintln ! ( "=== ACTUAL TEXT ===" ) ;
32- eprintln ! ( "{}" , actual) ;
33- eprintln ! ( "=== EXPECTED ===" ) ;
34- eprintln ! ( "{}" , expected) ;
16+
3517 if actual != expected {
36- panic ! ( "expected text was not found in actual text" ) ;
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+
26+ struct SearchDetails < ' assertion_name , ' haystack , ' needle > {
27+ assertion_name : & ' assertion_name str ,
28+ haystack : & ' haystack str ,
29+ needle : & ' needle str ,
30+ }
31+
32+ impl < ' 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) ;
3739 }
3840}
3941
4042/// Assert that `haystack` contains `needle`.
4143#[ track_caller]
4244pub fn assert_contains < H : AsRef < str > , N : AsRef < str > > ( haystack : H , needle : N ) {
43- let ( haystack, needle) = print ( "assert_contains" , & haystack, & needle) ;
45+ let haystack = haystack. as_ref ( ) ;
46+ let needle = needle. as_ref ( ) ;
4447 if !haystack. contains ( needle) {
48+ SearchDetails { assertion_name : "assert_contains" , haystack, needle } . dump ( ) ;
4549 panic ! ( "needle was not found in haystack" ) ;
4650 }
4751}
4852
4953/// Assert that `haystack` does not contain `needle`.
5054#[ track_caller]
5155pub fn assert_not_contains < H : AsRef < str > , N : AsRef < str > > ( haystack : H , needle : N ) {
52- let ( haystack, needle) = print ( "assert_not_contains" , & haystack, & needle) ;
56+ let haystack = haystack. as_ref ( ) ;
57+ let needle = needle. as_ref ( ) ;
5358 if haystack. contains ( needle) {
59+ SearchDetails { assertion_name : "assert_not_contains" , haystack, needle } . dump ( ) ;
5460 panic ! ( "needle was unexpectedly found in haystack" ) ;
5561 }
5662}
5763
58- /// Assert that `haystack` contains the regex pattern `needle`.
64+ /// Assert that `haystack` contains the regex `needle`.
5965#[ track_caller]
6066pub fn assert_contains_regex < H : AsRef < str > , N : AsRef < str > > ( haystack : H , needle : N ) {
61- let ( haystack, needle) = print ( "assert_contains_regex" , & haystack, & needle) ;
67+ let haystack = haystack. as_ref ( ) ;
68+ let needle = needle. as_ref ( ) ;
6269 let re = regex:: Regex :: new ( needle) . unwrap ( ) ;
6370 if !re. is_match ( haystack) {
64- panic ! ( "needle was not found in haystack" ) ;
71+ SearchDetails { assertion_name : "assert_contains_regex" , haystack, needle } . dump ( ) ;
72+ panic ! ( "regex was not found in haystack" ) ;
6573 }
6674}
6775
68- /// Assert that `haystack` does not contain the regex pattern `needle`.
76+ /// Assert that `haystack` does not contain the regex `needle`.
6977#[ track_caller]
7078pub fn assert_not_contains_regex < H : AsRef < str > , N : AsRef < str > > ( haystack : H , needle : N ) {
71- let ( haystack, needle) = print ( "assert_not_contains_regex" , & haystack, & needle) ;
79+ let haystack = haystack. as_ref ( ) ;
80+ let needle = needle. as_ref ( ) ;
7281 let re = regex:: Regex :: new ( needle) . unwrap ( ) ;
7382 if re. is_match ( haystack) {
74- panic ! ( "needle was unexpectedly found in haystack" ) ;
83+ SearchDetails { assertion_name : "assert_not_contains_regex" , haystack, needle } . dump ( ) ;
84+ panic ! ( "regex was unexpectedly found in haystack" ) ;
7585 }
7686}
7787
78- /// Assert that `haystack` contains `needle` a `count ` number of times.
88+ /// Assert that `haystack` contains regex `needle` an `expected_count ` number of times.
7989#[ track_caller]
80- pub fn assert_count_is < H : AsRef < str > , N : AsRef < str > > ( count : usize , haystack : H , needle : N ) {
81- let ( haystack, needle) = print ( "assert_count_is" , & haystack, & needle) ;
82- if count != haystack. matches ( needle) . count ( ) {
83- panic ! ( "needle did not appear {count} times in haystack" ) ;
90+ pub 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+ ) ;
84108 }
85109}
86110
87111/// Assert that all files in `dir1` exist and have the same content in `dir2`
112+ // FIXME(#135037): not robust against symlinks, lacks sanity test coverage.
88113pub fn assert_dirs_are_equal ( dir1 : impl AsRef < Path > , dir2 : impl AsRef < Path > ) {
89114 let dir2 = dir2. as_ref ( ) ;
90115 fs:: read_dir_entries ( dir1, |entry_path| {
0 commit comments