@@ -139,24 +139,28 @@ impl BookTest {
139139 }
140140
141141 /// Checks that the contents of the given file matches the expected value.
142+ ///
143+ /// The path can use glob-style wildcards, but it must match only a single file.
142144 #[ track_caller]
143- pub fn check_file ( & mut self , path : & str , expected : impl IntoData ) -> & mut Self {
145+ pub fn check_file ( & mut self , path_pattern : & str , expected : impl IntoData ) -> & mut Self {
144146 if !self . built {
145147 self . build ( ) ;
146148 }
147- let path = self . dir . join ( path ) ;
149+ let path = glob_one ( & self . dir , path_pattern ) ;
148150 let actual = read_to_string ( & path) ;
149151 self . assert . eq ( actual, expected) ;
150152 self
151153 }
152154
153155 /// Checks that the given file contains the given string somewhere.
156+ ///
157+ /// The path can use glob-style wildcards, but it must match only a single file.
154158 #[ track_caller]
155- pub fn check_file_contains ( & mut self , path : & str , expected : & str ) -> & mut Self {
159+ pub fn check_file_contains ( & mut self , path_pattern : & str , expected : & str ) -> & mut Self {
156160 if !self . built {
157161 self . build ( ) ;
158162 }
159- let path = self . dir . join ( path ) ;
163+ let path = glob_one ( & self . dir , path_pattern ) ;
160164 let actual = read_to_string ( & path) ;
161165 assert ! (
162166 actual. contains( expected) ,
@@ -170,12 +174,14 @@ impl BookTest {
170174 /// Beware that using this is fragile, as it may be unable to catch
171175 /// regressions (it can't tell the difference between success, or the
172176 /// string being looked for changed).
177+ ///
178+ /// The path can use glob-style wildcards, but it must match only a single file.
173179 #[ track_caller]
174- pub fn check_file_doesnt_contain ( & mut self , path : & str , string : & str ) -> & mut Self {
180+ pub fn check_file_doesnt_contain ( & mut self , path_pattern : & str , string : & str ) -> & mut Self {
175181 if !self . built {
176182 self . build ( ) ;
177183 }
178- let path = self . dir . join ( path ) ;
184+ let path = glob_one ( & self . dir , path_pattern ) ;
179185 let actual = read_to_string ( & path) ;
180186 assert ! (
181187 !actual. contains( string) ,
@@ -511,3 +517,21 @@ pub fn read_to_string<P: AsRef<Path>>(path: P) -> String {
511517 . with_context ( || format ! ( "could not read file {path:?}" ) )
512518 . unwrap ( )
513519}
520+
521+ /// Returns the first path from the given glob pattern.
522+ pub fn glob_one < P : AsRef < Path > > ( path : P , pattern : & str ) -> PathBuf {
523+ let path = path. as_ref ( ) ;
524+ let mut matches = glob:: glob ( path. join ( pattern) . to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
525+ let Some ( first) = matches. next ( ) else {
526+ panic ! ( "expected at least one file at `{path:?}` with pattern `{pattern}`, found none" ) ;
527+ } ;
528+ let first = first. unwrap ( ) ;
529+ if let Some ( next) = matches. next ( ) {
530+ panic ! (
531+ "expected only one file for pattern `{pattern}` in `{path:?}`, \
532+ found `{first:?}` and `{:?}`",
533+ next. unwrap( )
534+ ) ;
535+ }
536+ first
537+ }
0 commit comments