@@ -21,6 +21,8 @@ pub struct TestOpts {
21
21
pub nocapture : bool ,
22
22
pub color : ColorConfig ,
23
23
pub format : OutputFormat ,
24
+ pub shuffle : bool ,
25
+ pub shuffle_seed : Option < u64 > ,
24
26
pub test_threads : Option < usize > ,
25
27
pub skip : Vec < String > ,
26
28
pub time_options : Option < TestTimeOptions > ,
@@ -138,6 +140,13 @@ fn optgroups() -> getopts::Options {
138
140
139
141
`CRITICAL_TIME` here means the limit that should not be exceeded by test.
140
142
" ,
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" ,
141
150
) ;
142
151
opts
143
152
}
@@ -155,6 +164,12 @@ By default, all tests are run in parallel. This can be altered with the
155
164
--test-threads flag or the RUST_TEST_THREADS environment variable when running
156
165
tests (set it to 1).
157
166
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
+
158
173
All tests have their standard output and standard error captured by default.
159
174
This can be overridden with the --nocapture flag or setting RUST_TEST_NOCAPTURE
160
175
environment variable to a value other than "0". Logging is not captured by default.
@@ -218,6 +233,21 @@ macro_rules! unstable_optflag {
218
233
} } ;
219
234
}
220
235
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
+
221
251
// Implementation of `parse_opts` that doesn't care about help message
222
252
// and returns a `Result`.
223
253
fn parse_opts_impl ( matches : getopts:: Matches ) -> OptRes {
@@ -227,6 +257,8 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
227
257
let force_run_in_process = unstable_optflag ! ( matches, allow_unstable, "force-run-in-process" ) ;
228
258
let exclude_should_panic = unstable_optflag ! ( matches, allow_unstable, "exclude-should-panic" ) ;
229
259
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) ?;
230
262
231
263
let include_ignored = matches. opt_present ( "include-ignored" ) ;
232
264
let quiet = matches. opt_present ( "quiet" ) ;
@@ -260,6 +292,8 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
260
292
nocapture,
261
293
color,
262
294
format,
295
+ shuffle,
296
+ shuffle_seed,
263
297
test_threads,
264
298
skip,
265
299
time_options,
@@ -303,6 +337,46 @@ fn get_time_options(
303
337
Ok ( options)
304
338
}
305
339
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
+
306
380
fn get_test_threads ( matches : & getopts:: Matches ) -> OptPartRes < Option < usize > > {
307
381
let test_threads = match matches. opt_str ( "test-threads" ) {
308
382
Some ( n_str) => match n_str. parse :: < usize > ( ) {
0 commit comments