@@ -21,6 +21,8 @@ pub struct TestOpts {
2121 pub nocapture : bool ,
2222 pub color : ColorConfig ,
2323 pub format : OutputFormat ,
24+ pub shuffle : bool ,
25+ pub shuffle_seed : Option < u64 > ,
2426 pub test_threads : Option < usize > ,
2527 pub skip : Vec < String > ,
2628 pub time_options : Option < TestTimeOptions > ,
@@ -138,6 +140,13 @@ fn optgroups() -> getopts::Options {
138140
139141 `CRITICAL_TIME` here means the limit that should not be exceeded by test.
140142 " ,
143+ )
144+ . optflag ( "" , "shuffle" , "Run tests in random order" )
145+ . optopt (
146+ "" ,
147+ "shuffle-seed" ,
148+ "Run tests in random order; seed the random number generator with SEED" ,
149+ "SEED" ,
141150 ) ;
142151 opts
143152}
@@ -155,6 +164,12 @@ By default, all tests are run in parallel. This can be altered with the
155164--test-threads flag or the RUST_TEST_THREADS environment variable when running
156165tests (set it to 1).
157166
167+ By default, the tests are run in alphabetical order. Use --shuffle or set
168+ RUST_TEST_SHUFFLE to run the tests in random order. Pass the generated
169+ "shuffle seed" to --shuffle-seed (or set RUST_TEST_SHUFFLE_SEED) to run the
170+ tests in the same order again. Note that --shuffle and --shuffle-seed do not
171+ affect whether the tests are run in parallel.
172+
158173All tests have their standard output and standard error captured by default.
159174This can be overridden with the --nocapture flag or setting RUST_TEST_NOCAPTURE
160175environment variable to a value other than "0". Logging is not captured by default.
@@ -218,6 +233,21 @@ macro_rules! unstable_optflag {
218233 } } ;
219234}
220235
236+ // Gets the option value and checks if unstable features are enabled.
237+ macro_rules! unstable_optopt {
238+ ( $matches: ident, $allow_unstable: ident, $option_name: literal) => { {
239+ let opt = $matches. opt_str( $option_name) ;
240+ if !$allow_unstable && opt. is_some( ) {
241+ return Err ( format!(
242+ "The \" {}\" option is only accepted on the nightly compiler with -Z unstable-options" ,
243+ $option_name
244+ ) ) ;
245+ }
246+
247+ opt
248+ } } ;
249+ }
250+
221251// Implementation of `parse_opts` that doesn't care about help message
222252// and returns a `Result`.
223253fn parse_opts_impl ( matches : getopts:: Matches ) -> OptRes {
@@ -227,6 +257,8 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
227257 let force_run_in_process = unstable_optflag ! ( matches, allow_unstable, "force-run-in-process" ) ;
228258 let exclude_should_panic = unstable_optflag ! ( matches, allow_unstable, "exclude-should-panic" ) ;
229259 let time_options = get_time_options ( & matches, allow_unstable) ?;
260+ let shuffle = get_shuffle ( & matches, allow_unstable) ?;
261+ let shuffle_seed = get_shuffle_seed ( & matches, allow_unstable) ?;
230262
231263 let include_ignored = matches. opt_present ( "include-ignored" ) ;
232264 let quiet = matches. opt_present ( "quiet" ) ;
@@ -260,6 +292,8 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
260292 nocapture,
261293 color,
262294 format,
295+ shuffle,
296+ shuffle_seed,
263297 test_threads,
264298 skip,
265299 time_options,
@@ -303,6 +337,46 @@ fn get_time_options(
303337 Ok ( options)
304338}
305339
340+ fn get_shuffle ( matches : & getopts:: Matches , allow_unstable : bool ) -> OptPartRes < bool > {
341+ let mut shuffle = unstable_optflag ! ( matches, allow_unstable, "shuffle" ) ;
342+ if !shuffle {
343+ shuffle = match env:: var ( "RUST_TEST_SHUFFLE" ) {
344+ Ok ( val) => & val != "0" ,
345+ Err ( _) => false ,
346+ } ;
347+ }
348+
349+ Ok ( shuffle)
350+ }
351+
352+ fn get_shuffle_seed ( matches : & getopts:: Matches , allow_unstable : bool ) -> OptPartRes < Option < u64 > > {
353+ let mut shuffle_seed = match unstable_optopt ! ( matches, allow_unstable, "shuffle-seed" ) {
354+ Some ( n_str) => match n_str. parse :: < u64 > ( ) {
355+ Ok ( n) => Some ( n) ,
356+ Err ( e) => {
357+ return Err ( format ! (
358+ "argument for --shuffle-seed must be a number \
359+ (error: {})",
360+ e
361+ ) ) ;
362+ }
363+ } ,
364+ None => None ,
365+ } ;
366+
367+ if shuffle_seed. is_none ( ) {
368+ shuffle_seed = match env:: var ( "RUST_TEST_SHUFFLE_SEED" ) {
369+ Ok ( val) => match val. parse :: < u64 > ( ) {
370+ Ok ( n) => Some ( n) ,
371+ Err ( _) => panic ! ( "RUST_TEST_SHUFFLE_SEED is `{}`, should be a number." , val) ,
372+ } ,
373+ Err ( _) => None ,
374+ } ;
375+ }
376+
377+ Ok ( shuffle_seed)
378+ }
379+
306380fn get_test_threads ( matches : & getopts:: Matches ) -> OptPartRes < Option < usize > > {
307381 let test_threads = match matches. opt_str ( "test-threads" ) {
308382 Some ( n_str) => match n_str. parse :: < usize > ( ) {
0 commit comments