@@ -132,7 +132,8 @@ pub fn run_tests(config: Config) -> Result<()> {
132132 } ;
133133
134134 run_tests_generic (
135- config,
135+ vec ! [ config] ,
136+ std:: thread:: available_parallelism ( ) . unwrap ( ) ,
136137 args,
137138 default_file_filter,
138139 default_per_file_config,
@@ -142,7 +143,7 @@ pub fn run_tests(config: Config) -> Result<()> {
142143
143144/// The filter used by `run_tests` to only run on `.rs` files
144145/// and those specified in the command line args.
145- pub fn default_file_filter ( path : & Path , args : & Args ) -> bool {
146+ pub fn default_file_filter ( path : & Path , args : & Args , _config : & Config ) -> bool {
146147 path. extension ( ) . is_some_and ( |ext| ext == "rs" ) && default_filter_by_arg ( path, args)
147148}
148149
@@ -156,13 +157,11 @@ pub fn default_filter_by_arg(path: &Path, args: &Args) -> bool {
156157}
157158
158159/// The default per-file config used by `run_tests`.
159- pub fn default_per_file_config ( config : & Config , path : & Path ) -> Option < Config > {
160- let mut config = config. clone ( ) ;
160+ pub fn default_per_file_config ( config : & mut Config , file_contents : & [ u8 ] ) {
161161 // Heuristic:
162162 // * if the file contains `#[test]`, automatically pass `--cfg test`.
163163 // * if the file does not contain `fn main()` or `#[start]`, automatically pass `--crate-type=lib`.
164164 // This avoids having to spam `fn main() {}` in almost every test.
165- let file_contents = std:: fs:: read ( path) . unwrap ( ) ;
166165 if file_contents. find ( b"#[proc_macro" ) . is_some ( ) {
167166 config. program . args . push ( "--crate-type=proc-macro" . into ( ) )
168167 } else if file_contents. find ( b"#[test]" ) . is_some ( ) {
@@ -172,7 +171,6 @@ pub fn default_per_file_config(config: &Config, path: &Path) -> Option<Config> {
172171 {
173172 config. program . args . push ( "--crate-type=lib" . into ( ) ) ;
174173 }
175- Some ( config)
176174}
177175
178176/// Create a command for running a single file, with the settings from the `config` argument.
@@ -220,24 +218,29 @@ struct TestRun {
220218
221219/// A version of `run_tests` that allows more fine-grained control over running tests.
222220pub fn run_tests_generic (
223- mut config : Config ,
221+ mut configs : Vec < Config > ,
222+ num_threads : NonZeroUsize ,
224223 args : Args ,
225- file_filter : impl Fn ( & Path , & Args ) -> bool + Sync ,
226- per_file_config : impl Fn ( & Config , & Path ) -> Option < Config > + Sync ,
224+ file_filter : impl Fn ( & Path , & Args , & Config ) -> bool + Sync ,
225+ per_file_config : impl Fn ( & mut Config , & [ u8 ] ) + Sync ,
227226 status_emitter : impl StatusEmitter + Send ,
228227) -> Result < ( ) > {
229- config. fill_host_and_target ( ) ?;
228+ for config in & mut configs {
229+ config. fill_host_and_target ( ) ?;
230+ }
230231
231232 let build_manager = BuildManager :: new ( & status_emitter) ;
232233
233234 let mut results = vec ! [ ] ;
234235
235236 run_and_collect (
236- config . num_test_threads . get ( ) ,
237+ num_threads ,
237238 |submit| {
238239 let mut todo = VecDeque :: new ( ) ;
239- todo. push_back ( config. root_dir . clone ( ) ) ;
240- while let Some ( path) = todo. pop_front ( ) {
240+ for config in configs {
241+ todo. push_back ( ( config. root_dir . clone ( ) , config) ) ;
242+ }
243+ while let Some ( ( path, config) ) = todo. pop_front ( ) {
241244 if path. is_dir ( ) {
242245 if path. file_name ( ) . unwrap ( ) == "auxiliary" {
243246 continue ;
@@ -250,28 +253,22 @@ pub fn run_tests_generic(
250253 . unwrap ( ) ;
251254 entries. sort_by_key ( |e| e. file_name ( ) ) ;
252255 for entry in entries {
253- todo. push_back ( entry. path ( ) ) ;
256+ todo. push_back ( ( entry. path ( ) , config . clone ( ) ) ) ;
254257 }
255- } else if file_filter ( & path, & args) {
258+ } else if file_filter ( & path, & args, & config ) {
256259 let status = status_emitter. register_test ( path) ;
257260 // Forward .rs files to the test workers.
258- submit. send ( status) . unwrap ( ) ;
261+ submit. send ( ( status, config ) ) . unwrap ( ) ;
259262 }
260263 }
261264 } ,
262265 |receive, finished_files_sender| -> Result < ( ) > {
263- for status in receive {
266+ for ( status, mut config ) in receive {
264267 let path = status. path ( ) ;
265- let maybe_config;
266- let config = match per_file_config ( & config, path) {
267- None => & config,
268- Some ( config) => {
269- maybe_config = config;
270- & maybe_config
271- }
272- } ;
268+ let file_contents = std:: fs:: read ( path) . unwrap ( ) ;
269+ per_file_config ( & mut config, & file_contents) ;
273270 let result = match std:: panic:: catch_unwind ( || {
274- parse_and_test_file ( & build_manager, & status, config)
271+ parse_and_test_file ( & build_manager, & status, & config, file_contents )
275272 } ) {
276273 Ok ( Ok ( res) ) => res,
277274 Ok ( Err ( err) ) => {
@@ -351,7 +348,7 @@ pub fn run_tests_generic(
351348/// A generic multithreaded runner that has a thread for producing work,
352349/// a thread for collecting work, and `num_threads` threads for doing the work.
353350pub fn run_and_collect < SUBMISSION : Send , RESULT : Send > (
354- num_threads : usize ,
351+ num_threads : NonZeroUsize ,
355352 submitter : impl FnOnce ( Sender < SUBMISSION > ) + Send ,
356353 runner : impl Sync + Fn ( & Receiver < SUBMISSION > , Sender < RESULT > ) -> Result < ( ) > ,
357354 collector : impl FnOnce ( Receiver < RESULT > ) + Send ,
@@ -373,7 +370,7 @@ pub fn run_and_collect<SUBMISSION: Send, RESULT: Send>(
373370 let mut threads = vec ! [ ] ;
374371
375372 // Create N worker threads that receive files to test.
376- for _ in 0 ..num_threads {
373+ for _ in 0 ..num_threads. get ( ) {
377374 let finished_files_sender = finished_files_sender. clone ( ) ;
378375 threads. push ( s. spawn ( || runner ( & receive, finished_files_sender) ) ) ;
379376 }
@@ -389,8 +386,9 @@ fn parse_and_test_file(
389386 build_manager : & BuildManager < ' _ > ,
390387 status : & dyn TestStatus ,
391388 config : & Config ,
389+ file_contents : Vec < u8 > ,
392390) -> Result < Vec < TestRun > , Errored > {
393- let comments = parse_comments_in_file ( status . path ( ) ) ?;
391+ let comments = parse_comments ( & file_contents ) ?;
394392 // Run the test for all revisions
395393 let revisions = comments
396394 . revisions
@@ -413,19 +411,14 @@ fn parse_and_test_file(
413411 . collect ( ) )
414412}
415413
416- fn parse_comments_in_file ( path : & Path ) -> Result < Comments , Errored > {
417- match Comments :: parse_file ( path ) {
418- Ok ( Ok ( comments) ) => Ok ( comments) ,
419- Ok ( Err ( errors) ) => Err ( Errored {
414+ fn parse_comments ( file_contents : & [ u8 ] ) -> Result < Comments , Errored > {
415+ match Comments :: parse ( file_contents ) {
416+ Ok ( comments) => Ok ( comments) ,
417+ Err ( errors) => Err ( Errored {
420418 command : Command :: new ( "parse comments" ) ,
421419 errors,
422420 stderr : vec ! [ ] ,
423421 } ) ,
424- Err ( err) => Err ( Errored {
425- command : Command :: new ( "parse comments" ) ,
426- errors : vec ! [ ] ,
427- stderr : format ! ( "{err:?}" ) . into ( ) ,
428- } ) ,
429422 }
430423}
431424
@@ -467,7 +460,8 @@ fn build_aux(
467460 config : & Config ,
468461 build_manager : & BuildManager < ' _ > ,
469462) -> std:: result:: Result < Vec < OsString > , Errored > {
470- let comments = parse_comments_in_file ( aux_file) ?;
463+ let file_contents = std:: fs:: read ( aux_file) . unwrap ( ) ;
464+ let comments = parse_comments ( & file_contents) ?;
471465 assert_eq ! (
472466 comments. revisions, None ,
473467 "aux builds cannot specify revisions"
@@ -495,7 +489,7 @@ fn build_aux(
495489 }
496490 } ) ;
497491
498- let mut config = default_per_file_config ( & config, aux_file ) . unwrap ( ) ;
492+ default_per_file_config ( & mut config, & file_contents ) ;
499493
500494 // Put aux builds into a separate directory per path so that multiple aux files
501495 // from different directories (but with the same file name) don't collide.
@@ -615,7 +609,12 @@ impl dyn TestStatus {
615609 . stdout ( Stdio :: piped ( ) )
616610 . stdin ( Stdio :: null ( ) )
617611 . spawn ( )
618- . unwrap_or_else ( |err| panic ! ( "could not execute {cmd:?}: {err}" ) ) ;
612+ . unwrap_or_else ( |err| {
613+ panic ! (
614+ "could not spawn `{:?}` as a process: {err}" ,
615+ cmd. get_program( )
616+ )
617+ } ) ;
619618
620619 let stdout = ReadHelper :: from ( child. stdout . take ( ) . unwrap ( ) ) ;
621620 let mut stderr = ReadHelper :: from ( child. stderr . take ( ) . unwrap ( ) ) ;
0 commit comments