8
8
use std:: collections:: VecDeque ;
9
9
use std:: ffi:: OsString ;
10
10
use std:: fmt:: Write ;
11
+ use std:: num:: NonZeroUsize ;
11
12
use std:: path:: { Path , PathBuf } ;
12
13
use std:: process:: { Command , ExitStatus } ;
13
14
use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
@@ -32,6 +33,8 @@ mod tests;
32
33
#[ derive( Debug ) ]
33
34
pub struct Config {
34
35
/// Arguments passed to the binary that is executed.
36
+ /// Take care to only append unless you actually meant to overwrite the defaults.
37
+ /// Overwriting the defaults may make `//~ ERROR` style comments stop working.
35
38
pub args : Vec < OsString > ,
36
39
/// `None` to run on the host, otherwise a target triple
37
40
pub target : Option < String > ,
@@ -53,23 +56,28 @@ pub struct Config {
53
56
pub dependency_builder : Option < DependencyBuilder > ,
54
57
/// Print one character per test instead of one line
55
58
pub quiet : bool ,
59
+ /// How many threads to use for running tests. Defaults to number of cores
60
+ pub num_test_threads : NonZeroUsize ,
56
61
}
57
62
58
63
impl Default for Config {
59
64
fn default ( ) -> Self {
60
65
Self {
61
- args : vec ! [ ] ,
66
+ args : vec ! [ "--error-format=json" . into ( ) ] ,
62
67
target : None ,
63
68
stderr_filters : vec ! [ ] ,
64
69
stdout_filters : vec ! [ ] ,
65
70
root_dir : PathBuf :: new ( ) ,
66
- mode : Mode :: Fail ,
71
+ mode : Mode :: Fail {
72
+ require_patterns : true ,
73
+ } ,
67
74
program : PathBuf :: from ( "rustc" ) ,
68
75
output_conflict_handling : OutputConflictHandling :: Error ,
69
76
path_filter : vec ! [ ] ,
70
77
dependencies_crate_manifest_path : None ,
71
78
dependency_builder : None ,
72
79
quiet : true ,
80
+ num_test_threads : std:: thread:: available_parallelism ( ) . unwrap ( ) ,
73
81
}
74
82
}
75
83
}
@@ -104,9 +112,6 @@ pub type Filter = Vec<(Regex, &'static str)>;
104
112
pub fn run_tests ( mut config : Config ) -> Result < ( ) > {
105
113
eprintln ! ( " Compiler flags: {:?}" , config. args) ;
106
114
107
- // Get the triple with which to run the tests
108
- let target = config. target . clone ( ) . unwrap_or_else ( || config. get_host ( ) ) ;
109
-
110
115
let dependencies = build_dependencies ( & config) ?;
111
116
for ( name, dependency) in dependencies. dependencies {
112
117
config. args . push ( "--extern" . into ( ) ) ;
@@ -119,7 +124,14 @@ pub fn run_tests(mut config: Config) -> Result<()> {
119
124
config. args . push ( "-L" . into ( ) ) ;
120
125
config. args . push ( import_path. into ( ) ) ;
121
126
}
122
- let config = config;
127
+ run_tests_generic ( config, |path| {
128
+ path. extension ( ) . map ( |ext| ext == "rs" ) . unwrap_or ( false )
129
+ } )
130
+ }
131
+
132
+ pub fn run_tests_generic ( config : Config , file_filter : impl Fn ( & Path ) -> bool + Sync ) -> Result < ( ) > {
133
+ // Get the triple with which to run the tests
134
+ let target = config. target . clone ( ) . unwrap_or_else ( || config. get_host ( ) ) ;
123
135
124
136
// A channel for files to process
125
137
let ( submit, receive) = crossbeam:: channel:: unbounded ( ) ;
@@ -148,7 +160,7 @@ pub fn run_tests(mut config: Config) -> Result<()> {
148
160
for entry in entries {
149
161
todo. push_back ( entry. path ( ) ) ;
150
162
}
151
- } else if path . extension ( ) . map ( |ext| ext == "rs" ) . unwrap_or ( false ) {
163
+ } else if file_filter ( & path ) {
152
164
// Forward .rs files to the test workers.
153
165
submit. send ( path) . unwrap ( ) ;
154
166
}
@@ -198,7 +210,7 @@ pub fn run_tests(mut config: Config) -> Result<()> {
198
210
let mut threads = vec ! [ ] ;
199
211
200
212
// Create N worker threads that receive files to test.
201
- for _ in 0 ..std :: thread :: available_parallelism ( ) . unwrap ( ) . get ( ) {
213
+ for _ in 0 ..config . num_test_threads . get ( ) {
202
214
let finished_files_sender = finished_files_sender. clone ( ) ;
203
215
threads. push ( s. spawn ( |_| -> Result < ( ) > {
204
216
let finished_files_sender = finished_files_sender;
@@ -412,7 +424,6 @@ fn run_test(
412
424
if !revision. is_empty ( ) {
413
425
miri. arg ( format ! ( "--cfg={revision}" ) ) ;
414
426
}
415
- miri. arg ( "--error-format=json" ) ;
416
427
for arg in & comments. compile_flags {
417
428
miri. arg ( arg) ;
418
429
}
@@ -586,7 +597,12 @@ fn check_annotations(
586
597
comments. error_pattern . is_some ( ) || !comments. error_matches . is_empty ( ) ,
587
598
) {
588
599
( Mode :: Pass , true ) | ( Mode :: Panic , true ) => errors. push ( Error :: PatternFoundInPassTest ) ,
589
- ( Mode :: Fail , false ) => errors. push ( Error :: NoPatternsFound ) ,
600
+ (
601
+ Mode :: Fail {
602
+ require_patterns : true ,
603
+ } ,
604
+ false ,
605
+ ) => errors. push ( Error :: NoPatternsFound ) ,
590
606
_ => { }
591
607
}
592
608
}
@@ -695,18 +711,23 @@ impl Config {
695
711
696
712
#[ derive( Copy , Clone , Debug ) ]
697
713
pub enum Mode {
698
- // The test passes a full execution of the rustc driver
714
+ /// The test passes a full execution of the rustc driver
699
715
Pass ,
700
- // The rustc driver panicked
716
+ /// The rustc driver panicked
701
717
Panic ,
702
- // The rustc driver emitted an error
703
- Fail ,
718
+ /// The rustc driver emitted an error
719
+ Fail {
720
+ /// Whether failing tests must have error patterns. Set to false if you just care about .stderr output.
721
+ require_patterns : bool ,
722
+ } ,
704
723
}
705
724
706
725
impl Mode {
707
726
fn ok ( self , status : ExitStatus ) -> Errors {
708
727
match ( status. code ( ) , self ) {
709
- ( Some ( 1 ) , Mode :: Fail ) | ( Some ( 101 ) , Mode :: Panic ) | ( Some ( 0 ) , Mode :: Pass ) => vec ! [ ] ,
728
+ ( Some ( 1 ) , Mode :: Fail { .. } ) | ( Some ( 101 ) , Mode :: Panic ) | ( Some ( 0 ) , Mode :: Pass ) => {
729
+ vec ! [ ]
730
+ }
710
731
_ => vec ! [ Error :: ExitStatus ( self , status) ] ,
711
732
}
712
733
}
0 commit comments