@@ -40,7 +40,7 @@ impl TestOpts {
40
40
/// Result of parsing the options.
41
41
pub type OptRes = Result < TestOpts , String > ;
42
42
/// Result of parsing the option part.
43
- type OptPartRes < T > = Result < Option < T > , String > ;
43
+ type OptPartRes < T > = Result < T , String > ;
44
44
45
45
fn optgroups ( ) -> getopts:: Options {
46
46
let mut opts = getopts:: Options :: new ( ) ;
@@ -186,36 +186,111 @@ Test Attributes:
186
186
) ;
187
187
}
188
188
189
- // FIXME: Copied from libsyntax until linkage errors are resolved. Issue #47566
190
- fn is_nightly ( ) -> bool {
191
- // Whether this is a feature-staged build, i.e., on the beta or stable channel
192
- let disable_unstable_features = option_env ! ( "CFG_DISABLE_UNSTABLE_FEATURES" ) . is_some ( ) ;
193
- // Whether we should enable unstable features for bootstrapping
194
- let bootstrap = env:: var ( "RUSTC_BOOTSTRAP" ) . is_ok ( ) ;
189
+ /// Parses command line arguments into test options.
190
+ /// Returns `None` if help was requested (since we only show help message and don't run tests),
191
+ /// returns `Some(Err(..))` if provided arguments are incorrect,
192
+ /// otherwise creates a `TestOpts` object and returns it.
193
+ pub fn parse_opts ( args : & [ String ] ) -> Option < OptRes > {
194
+ // Parse matches.
195
+ let opts = optgroups ( ) ;
196
+ let args = args. get ( 1 ..) . unwrap_or ( args) ;
197
+ let matches = match opts. parse ( args) {
198
+ Ok ( m) => m,
199
+ Err ( f) => return Some ( Err ( f. to_string ( ) ) ) ,
200
+ } ;
195
201
196
- bootstrap || !disable_unstable_features
202
+ // Check if help was requested.
203
+ if matches. opt_present ( "h" ) {
204
+ // Show help and do nothing more.
205
+ usage ( & args[ 0 ] , & opts) ;
206
+ return None ;
207
+ }
208
+
209
+ // Actually parse the opts.
210
+ let opts_result = parse_opts_impl ( matches) ;
211
+
212
+ Some ( opts_result)
197
213
}
198
214
199
215
// Gets the option value and checks if unstable features are enabled.
200
216
macro_rules! unstable_optflag {
201
217
( $matches: ident, $allow_unstable: ident, $option_name: literal) => { {
202
218
let opt = $matches. opt_present( $option_name) ;
203
219
if !$allow_unstable && opt {
204
- return Some ( Err ( format!(
220
+ return Err ( format!(
205
221
"The \" {}\" flag is only accepted on the nightly compiler" ,
206
222
$option_name
207
- ) ) ) ;
223
+ ) ) ;
208
224
}
209
225
210
226
opt
211
227
} } ;
212
228
}
213
229
230
+ // Implementation of `parse_opts` that doesn't care about help message
231
+ // and returns a `Result`.
232
+ fn parse_opts_impl ( matches : getopts:: Matches ) -> OptRes {
233
+ let allow_unstable = get_allow_unstable ( & matches) ?;
234
+
235
+ // Unstable flags
236
+ let exclude_should_panic = unstable_optflag ! ( matches, allow_unstable, "exclude-should-panic" ) ;
237
+ let include_ignored = unstable_optflag ! ( matches, allow_unstable, "include-ignored" ) ;
238
+ let time_options = get_time_options ( & matches, allow_unstable) ?;
239
+
240
+ let quiet = matches. opt_present ( "quiet" ) ;
241
+ let exact = matches. opt_present ( "exact" ) ;
242
+ let list = matches. opt_present ( "list" ) ;
243
+ let skip = matches. opt_strs ( "skip" ) ;
244
+
245
+ let bench_benchmarks = matches. opt_present ( "bench" ) ;
246
+ let run_tests = !bench_benchmarks || matches. opt_present ( "test" ) ;
247
+
248
+ let logfile = get_log_file ( & matches) ?;
249
+ let run_ignored = get_run_ignored ( & matches, include_ignored) ?;
250
+ let filter = get_filter ( & matches) ?;
251
+ let nocapture = get_nocapture ( & matches) ?;
252
+ let test_threads = get_test_threads ( & matches) ?;
253
+ let color = get_color_config ( & matches) ?;
254
+ let format = get_format ( & matches, quiet, allow_unstable) ?;
255
+
256
+ let options = Options :: new ( ) . display_output ( matches. opt_present ( "show-output" ) ) ;
257
+
258
+ let test_opts = TestOpts {
259
+ list,
260
+ filter,
261
+ filter_exact : exact,
262
+ exclude_should_panic,
263
+ run_ignored,
264
+ run_tests,
265
+ bench_benchmarks,
266
+ logfile,
267
+ nocapture,
268
+ color,
269
+ format,
270
+ test_threads,
271
+ skip,
272
+ time_options,
273
+ options,
274
+ } ;
275
+
276
+ Ok ( test_opts)
277
+ }
278
+
279
+ // FIXME: Copied from libsyntax until linkage errors are resolved. Issue #47566
280
+ fn is_nightly ( ) -> bool {
281
+ // Whether this is a feature-staged build, i.e., on the beta or stable channel
282
+ let disable_unstable_features = option_env ! ( "CFG_DISABLE_UNSTABLE_FEATURES" ) . is_some ( ) ;
283
+ // Whether we should enable unstable features for bootstrapping
284
+ let bootstrap = env:: var ( "RUSTC_BOOTSTRAP" ) . is_ok ( ) ;
285
+
286
+ bootstrap || !disable_unstable_features
287
+ }
288
+
214
289
// Gets the CLI options assotiated with `report-time` feature.
215
290
fn get_time_options (
216
291
matches : & getopts:: Matches ,
217
292
allow_unstable : bool )
218
- -> Option < OptPartRes < TestTimeOptions > > {
293
+ -> OptPartRes < Option < TestTimeOptions > > {
219
294
let report_time = unstable_optflag ! ( matches, allow_unstable, "report-time" ) ;
220
295
let colored_opt_str = matches. opt_str ( "report-time" ) ;
221
296
let mut report_time_colored = report_time && colored_opt_str == Some ( "colored" . into ( ) ) ;
@@ -232,71 +307,73 @@ fn get_time_options(
232
307
None
233
308
} ;
234
309
235
- Some ( Ok ( options) )
310
+ Ok ( options)
236
311
}
237
312
238
- // Parses command line arguments into test options
239
- pub fn parse_opts ( args : & [ String ] ) -> Option < OptRes > {
240
- let mut allow_unstable = false ;
241
- let opts = optgroups ( ) ;
242
- let args = args. get ( 1 ..) . unwrap_or ( args) ;
243
- let matches = match opts. parse ( args) {
244
- Ok ( m) => m,
245
- Err ( f) => return Some ( Err ( f. to_string ( ) ) ) ,
313
+ fn get_test_threads ( matches : & getopts:: Matches ) -> OptPartRes < Option < usize > > {
314
+ let test_threads = match matches. opt_str ( "test-threads" ) {
315
+ Some ( n_str) => match n_str. parse :: < usize > ( ) {
316
+ Ok ( 0 ) => return Err ( "argument for --test-threads must not be 0" . to_string ( ) ) ,
317
+ Ok ( n) => Some ( n) ,
318
+ Err ( e) => {
319
+ return Err ( format ! (
320
+ "argument for --test-threads must be a number > 0 \
321
+ (error: {})",
322
+ e
323
+ ) ) ;
324
+ }
325
+ } ,
326
+ None => None ,
246
327
} ;
247
328
248
- if let Some ( opt) = matches. opt_str ( "Z" ) {
249
- if !is_nightly ( ) {
250
- return Some ( Err (
251
- "the option `Z` is only accepted on the nightly compiler" . into ( ) ,
252
- ) ) ;
253
- }
329
+ Ok ( test_threads)
330
+ }
254
331
255
- match & * opt {
256
- "unstable-options" => {
257
- allow_unstable = true ;
258
- }
259
- _ => {
260
- return Some ( Err ( "Unrecognized option to `Z`" . into ( ) ) ) ;
332
+ fn get_format ( matches : & getopts:: Matches , quiet : bool , allow_unstable : bool ) -> OptPartRes < OutputFormat > {
333
+ let format = match matches. opt_str ( "format" ) . as_ref ( ) . map ( |s| & * * s) {
334
+ None if quiet => OutputFormat :: Terse ,
335
+ Some ( "pretty" ) | None => OutputFormat :: Pretty ,
336
+ Some ( "terse" ) => OutputFormat :: Terse ,
337
+ Some ( "json" ) => {
338
+ if !allow_unstable {
339
+ return Err (
340
+ "The \" json\" format is only accepted on the nightly compiler" . into ( ) ,
341
+ ) ;
261
342
}
343
+ OutputFormat :: Json
262
344
}
263
- } ;
264
345
265
- if matches. opt_present ( "h" ) {
266
- usage ( & args[ 0 ] , & opts) ;
267
- return None ;
268
- }
269
-
270
- let filter = if !matches. free . is_empty ( ) {
271
- Some ( matches. free [ 0 ] . clone ( ) )
272
- } else {
273
- None
346
+ Some ( v) => {
347
+ return Err ( format ! (
348
+ "argument for --format must be pretty, terse, or json (was \
349
+ {})",
350
+ v
351
+ ) ) ;
352
+ }
274
353
} ;
275
354
276
- let exclude_should_panic = unstable_optflag ! ( matches, allow_unstable, "exclude-should-panic" ) ;
355
+ Ok ( format)
356
+ }
277
357
278
- let include_ignored = unstable_optflag ! ( matches, allow_unstable, "include-ignored" ) ;
358
+ fn get_color_config ( matches : & getopts:: Matches ) -> OptPartRes < ColorConfig > {
359
+ let color = match matches. opt_str ( "color" ) . as_ref ( ) . map ( |s| & * * s) {
360
+ Some ( "auto" ) | None => ColorConfig :: AutoColor ,
361
+ Some ( "always" ) => ColorConfig :: AlwaysColor ,
362
+ Some ( "never" ) => ColorConfig :: NeverColor ,
279
363
280
- let run_ignored = match ( include_ignored, matches. opt_present ( "ignored" ) ) {
281
- ( true , true ) => {
282
- return Some ( Err (
283
- "the options --include-ignored and --ignored are mutually exclusive" . into ( ) ,
364
+ Some ( v) => {
365
+ return Err ( format ! (
366
+ "argument for --color must be auto, always, or never (was \
367
+ {})",
368
+ v
284
369
) ) ;
285
370
}
286
- ( true , false ) => RunIgnored :: Yes ,
287
- ( false , true ) => RunIgnored :: Only ,
288
- ( false , false ) => RunIgnored :: No ,
289
371
} ;
290
- let quiet = matches. opt_present ( "quiet" ) ;
291
- let exact = matches. opt_present ( "exact" ) ;
292
- let list = matches. opt_present ( "list" ) ;
293
372
294
- let logfile = matches. opt_str ( "logfile" ) ;
295
- let logfile = logfile. map ( |s| PathBuf :: from ( & s) ) ;
296
-
297
- let bench_benchmarks = matches. opt_present ( "bench" ) ;
298
- let run_tests = !bench_benchmarks || matches. opt_present ( "test" ) ;
373
+ Ok ( color)
374
+ }
299
375
376
+ fn get_nocapture ( matches : & getopts:: Matches ) -> OptPartRes < bool > {
300
377
let mut nocapture = matches. opt_present ( "nocapture" ) ;
301
378
if !nocapture {
302
379
nocapture = match env:: var ( "RUST_TEST_NOCAPTURE" ) {
@@ -305,80 +382,59 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
305
382
} ;
306
383
}
307
384
308
- let time_options = match get_time_options ( & matches, allow_unstable) {
309
- Some ( Ok ( val) ) => val,
310
- Some ( Err ( e) ) => return Some ( Err ( e) ) ,
311
- None => panic ! ( "Unexpected output from `get_time_options`" ) ,
312
- } ;
385
+ Ok ( nocapture)
386
+ }
313
387
314
- let test_threads = match matches. opt_str ( "test-threads" ) {
315
- Some ( n_str) => match n_str. parse :: < usize > ( ) {
316
- Ok ( 0 ) => return Some ( Err ( "argument for --test-threads must not be 0" . to_string ( ) ) ) ,
317
- Ok ( n) => Some ( n) ,
318
- Err ( e) => {
319
- return Some ( Err ( format ! (
320
- "argument for --test-threads must be a number > 0 \
321
- (error: {})",
322
- e
323
- ) ) ) ;
324
- }
325
- } ,
326
- None => None ,
388
+ fn get_run_ignored ( matches : & getopts:: Matches , include_ignored : bool ) -> OptPartRes < RunIgnored > {
389
+ let run_ignored = match ( include_ignored, matches. opt_present ( "ignored" ) ) {
390
+ ( true , true ) => {
391
+ return Err (
392
+ "the options --include-ignored and --ignored are mutually exclusive" . into ( ) ,
393
+ ) ;
394
+ }
395
+ ( true , false ) => RunIgnored :: Yes ,
396
+ ( false , true ) => RunIgnored :: Only ,
397
+ ( false , false ) => RunIgnored :: No ,
327
398
} ;
328
399
329
- let color = match matches. opt_str ( "color" ) . as_ref ( ) . map ( |s| & * * s) {
330
- Some ( "auto" ) | None => ColorConfig :: AutoColor ,
331
- Some ( "always" ) => ColorConfig :: AlwaysColor ,
332
- Some ( "never" ) => ColorConfig :: NeverColor ,
400
+ Ok ( run_ignored)
401
+ }
333
402
334
- Some ( v) => {
335
- return Some ( Err ( format ! (
336
- "argument for --color must be auto, always, or never (was \
337
- {})",
338
- v
339
- ) ) ) ;
340
- }
403
+ fn get_filter ( matches : & getopts:: Matches ) -> OptPartRes < Option < String > > {
404
+ let filter = if !matches. free . is_empty ( ) {
405
+ Some ( matches. free [ 0 ] . clone ( ) )
406
+ } else {
407
+ None
341
408
} ;
342
409
343
- let format = match matches . opt_str ( "format" ) . as_ref ( ) . map ( |s| & * * s ) {
344
- None if quiet => OutputFormat :: Terse ,
345
- Some ( "pretty" ) | None => OutputFormat :: Pretty ,
346
- Some ( "terse" ) => OutputFormat :: Terse ,
347
- Some ( "json" ) => {
348
- if !allow_unstable {
349
- return Some ( Err (
350
- "The \" json \" format is only accepted on the nightly compiler" . into ( ) ,
351
- ) ) ;
352
- }
353
- OutputFormat :: Json
410
+ Ok ( filter )
411
+ }
412
+
413
+ fn get_allow_unstable ( matches : & getopts :: Matches ) -> OptPartRes < bool > {
414
+ let mut allow_unstable = false ;
415
+
416
+ if let Some ( opt ) = matches . opt_str ( "Z" ) {
417
+ if ! is_nightly ( ) {
418
+ return Err (
419
+ "the option `Z` is only accepted on the nightly compiler" . into ( ) ,
420
+ ) ;
354
421
}
355
422
356
- Some ( v) => {
357
- return Some ( Err ( format ! (
358
- "argument for --format must be pretty, terse, or json (was \
359
- {})",
360
- v
361
- ) ) ) ;
423
+ match & * opt {
424
+ "unstable-options" => {
425
+ allow_unstable = true ;
426
+ }
427
+ _ => {
428
+ return Err ( "Unrecognized option to `Z`" . into ( ) ) ;
429
+ }
362
430
}
363
431
} ;
364
432
365
- let test_opts = TestOpts {
366
- list,
367
- filter,
368
- filter_exact : exact,
369
- exclude_should_panic,
370
- run_ignored,
371
- run_tests,
372
- bench_benchmarks,
373
- logfile,
374
- nocapture,
375
- color,
376
- format,
377
- test_threads,
378
- skip : matches. opt_strs ( "skip" ) ,
379
- time_options,
380
- options : Options :: new ( ) . display_output ( matches. opt_present ( "show-output" ) ) ,
381
- } ;
433
+ Ok ( allow_unstable)
434
+ }
435
+
436
+ fn get_log_file ( matches : & getopts:: Matches ) -> OptPartRes < Option < PathBuf > > {
437
+ let logfile = matches. opt_str ( "logfile" ) . map ( |s| PathBuf :: from ( & s) ) ;
382
438
383
- Some ( Ok ( test_opts ) )
439
+ Ok ( logfile )
384
440
}
0 commit comments