@@ -30,8 +30,8 @@ pub struct Config {
30
30
pub mode : Mode ,
31
31
pub program : PathBuf ,
32
32
pub output_conflict_handling : OutputConflictHandling ,
33
- /// Only run tests with this string in their path/name
34
- pub path_filter : Option < String > ,
33
+ /// Only run tests with one of these strings in their path/name
34
+ pub path_filter : Vec < String > ,
35
35
}
36
36
37
37
#[ derive( Debug ) ]
@@ -61,6 +61,7 @@ pub fn run_tests(config: Config) {
61
61
let failures = Mutex :: new ( vec ! [ ] ) ;
62
62
let succeeded = AtomicUsize :: default ( ) ;
63
63
let ignored = AtomicUsize :: default ( ) ;
64
+ let filtered = AtomicUsize :: default ( ) ;
64
65
65
66
crossbeam:: scope ( |s| {
66
67
for _ in 0 ..std:: thread:: available_parallelism ( ) . unwrap ( ) . get ( ) {
@@ -77,22 +78,22 @@ pub fn run_tests(config: Config) {
77
78
if !path. extension ( ) . map ( |ext| ext == "rs" ) . unwrap_or ( false ) {
78
79
continue ;
79
80
}
80
- if let Some ( path_filter) = & config. path_filter {
81
- if !path. display ( ) . to_string ( ) . contains ( path_filter) {
82
- ignored. fetch_add ( 1 , Ordering :: Relaxed ) ;
83
- eprintln ! (
84
- "{} .. {}" ,
85
- path. display( ) ,
86
- "ignored (command line filter)" . yellow( )
87
- ) ;
81
+ if !config. path_filter . is_empty ( ) {
82
+ let path_display = path. display ( ) . to_string ( ) ;
83
+ if !config. path_filter . iter ( ) . any ( |filter| path_display. contains ( filter) ) {
84
+ filtered. fetch_add ( 1 , Ordering :: Relaxed ) ;
88
85
continue ;
89
86
}
90
87
}
91
88
let comments = Comments :: parse_file ( & path) ;
92
89
// Ignore file if only/ignore rules do (not) apply
93
90
if ignore_file ( & comments, & target) {
94
91
ignored. fetch_add ( 1 , Ordering :: Relaxed ) ;
95
- eprintln ! ( "{} .. {}" , path. display( ) , "ignored" . yellow( ) ) ;
92
+ eprintln ! (
93
+ "{} ... {}" ,
94
+ path. display( ) ,
95
+ "ignored (in-test comment)" . yellow( )
96
+ ) ;
96
97
continue ;
97
98
}
98
99
// Run the test for all revisions
@@ -101,7 +102,7 @@ pub fn run_tests(config: Config) {
101
102
{
102
103
let ( m, errors) = run_test ( & path, & config, & target, & revision, & comments) ;
103
104
104
- // Using `format ` to prevent messages from threads from getting intermingled.
105
+ // Using a single `eprintln! ` to prevent messages from threads from getting intermingled.
105
106
let mut msg = format ! ( "{} " , path. display( ) ) ;
106
107
if !revision. is_empty ( ) {
107
108
write ! ( msg, "(revision `{revision}`) " ) . unwrap ( ) ;
@@ -125,6 +126,7 @@ pub fn run_tests(config: Config) {
125
126
let failures = failures. into_inner ( ) . unwrap ( ) ;
126
127
let succeeded = succeeded. load ( Ordering :: Relaxed ) ;
127
128
let ignored = ignored. load ( Ordering :: Relaxed ) ;
129
+ let filtered = filtered. load ( Ordering :: Relaxed ) ;
128
130
if !failures. is_empty ( ) {
129
131
for ( path, miri, revision, errors) in & failures {
130
132
eprintln ! ( ) ;
@@ -168,19 +170,22 @@ pub fn run_tests(config: Config) {
168
170
}
169
171
}
170
172
eprintln ! (
171
- "{} tests failed, {} tests passed, {} ignored" ,
173
+ "test result: {}. {} tests failed, {} tests passed, {} ignored, {} filtered out" ,
174
+ "FAIL" . red( ) ,
172
175
failures. len( ) . to_string( ) . red( ) . bold( ) ,
173
176
succeeded. to_string( ) . green( ) ,
174
- ignored. to_string( ) . yellow( )
177
+ ignored. to_string( ) . yellow( ) ,
178
+ filtered. to_string( ) . yellow( ) ,
175
179
) ;
176
180
std:: process:: exit ( 1 ) ;
177
181
}
178
182
eprintln ! ( ) ;
179
183
eprintln ! (
180
- "test result: {}. {} tests passed, {} ignored" ,
184
+ "test result: {}. {} tests passed, {} ignored, {} filtered out " ,
181
185
"ok" . green( ) ,
182
186
succeeded. to_string( ) . green( ) ,
183
- ignored. to_string( ) . yellow( )
187
+ ignored. to_string( ) . yellow( ) ,
188
+ filtered. to_string( ) . yellow( ) ,
184
189
) ;
185
190
eprintln ! ( ) ;
186
191
}
@@ -230,6 +235,34 @@ fn run_test(
230
235
}
231
236
let output = miri. output ( ) . expect ( "could not execute miri" ) ;
232
237
let mut errors = config. mode . ok ( output. status ) ;
238
+ check_test_result (
239
+ path,
240
+ config,
241
+ target,
242
+ revision,
243
+ comments,
244
+ & mut errors,
245
+ & output. stdout ,
246
+ & output. stderr ,
247
+ ) ;
248
+ ( miri, errors)
249
+ }
250
+
251
+ fn check_test_result (
252
+ path : & Path ,
253
+ config : & Config ,
254
+ target : & str ,
255
+ revision : & str ,
256
+ comments : & Comments ,
257
+ errors : & mut Errors ,
258
+ stdout : & [ u8 ] ,
259
+ stderr : & [ u8 ] ,
260
+ ) {
261
+ // Always remove annotation comments from stderr.
262
+ let annotations = Regex :: new ( r"\s*//~.*" ) . unwrap ( ) ;
263
+ let stderr = std:: str:: from_utf8 ( stderr) . unwrap ( ) ;
264
+ let stderr = annotations. replace_all ( stderr, "" ) ;
265
+ let stdout = std:: str:: from_utf8 ( stdout) . unwrap ( ) ;
233
266
// Check output files (if any)
234
267
let revised = |extension : & str | {
235
268
if revision. is_empty ( ) {
@@ -240,41 +273,36 @@ fn run_test(
240
273
} ;
241
274
// Check output files against actual output
242
275
check_output (
243
- & output . stderr ,
276
+ & stderr,
244
277
path,
245
- & mut errors,
278
+ errors,
246
279
revised ( "stderr" ) ,
247
280
target,
248
281
& config. stderr_filters ,
249
282
& config,
250
283
comments,
251
284
) ;
252
285
check_output (
253
- & output . stdout ,
286
+ & stdout,
254
287
path,
255
- & mut errors,
288
+ errors,
256
289
revised ( "stdout" ) ,
257
290
target,
258
291
& config. stdout_filters ,
259
292
& config,
260
293
comments,
261
294
) ;
262
295
// Check error annotations in the source against output
263
- check_annotations ( & output. stderr , & mut errors, config, revision, comments) ;
264
- ( miri, errors)
296
+ check_annotations ( & stderr, errors, config, revision, comments) ;
265
297
}
266
298
267
299
fn check_annotations (
268
- unnormalized_stderr : & [ u8 ] ,
300
+ unnormalized_stderr : & str ,
269
301
errors : & mut Errors ,
270
302
config : & Config ,
271
303
revision : & str ,
272
304
comments : & Comments ,
273
305
) {
274
- let unnormalized_stderr = std:: str:: from_utf8 ( unnormalized_stderr) . unwrap ( ) ;
275
- // erase annotations from the stderr so they don't match themselves
276
- let annotations = Regex :: new ( r"\s*//~.*" ) . unwrap ( ) ;
277
- let unnormalized_stderr = annotations. replace ( unnormalized_stderr, "" ) ;
278
306
let mut found_annotation = false ;
279
307
if let Some ( ( ref error_pattern, definition_line) ) = comments. error_pattern {
280
308
if !unnormalized_stderr. contains ( error_pattern) {
@@ -312,7 +340,7 @@ fn check_annotations(
312
340
}
313
341
314
342
fn check_output (
315
- output : & [ u8 ] ,
343
+ output : & str ,
316
344
path : & Path ,
317
345
errors : & mut Errors ,
318
346
kind : String ,
@@ -321,7 +349,6 @@ fn check_output(
321
349
config : & Config ,
322
350
comments : & Comments ,
323
351
) {
324
- let output = std:: str:: from_utf8 ( & output) . unwrap ( ) ;
325
352
let output = normalize ( path, output, filters, comments) ;
326
353
let path = output_path ( path, comments, kind, target) ;
327
354
match config. output_conflict_handling {
0 commit comments