@@ -40,7 +40,7 @@ impl TestOpts {
4040/// Result of parsing the options.
4141pub type OptRes = Result < TestOpts , String > ;
4242/// Result of parsing the option part.
43- type OptPartRes < T > = Result < Option < T > , String > ;
43+ type OptPartRes < T > = Result < T , String > ;
4444
4545fn optgroups ( ) -> getopts:: Options {
4646 let mut opts = getopts:: Options :: new ( ) ;
@@ -186,36 +186,111 @@ Test Attributes:
186186 ) ;
187187}
188188
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+ } ;
195201
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)
197213}
198214
199215// Gets the option value and checks if unstable features are enabled.
200216macro_rules! unstable_optflag {
201217 ( $matches: ident, $allow_unstable: ident, $option_name: literal) => { {
202218 let opt = $matches. opt_present( $option_name) ;
203219 if !$allow_unstable && opt {
204- return Some ( Err ( format!(
220+ return Err ( format!(
205221 "The \" {}\" flag is only accepted on the nightly compiler" ,
206222 $option_name
207- ) ) ) ;
223+ ) ) ;
208224 }
209225
210226 opt
211227 } } ;
212228}
213229
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+
214289// Gets the CLI options assotiated with `report-time` feature.
215290fn get_time_options (
216291 matches : & getopts:: Matches ,
217292 allow_unstable : bool )
218- -> Option < OptPartRes < TestTimeOptions > > {
293+ -> OptPartRes < Option < TestTimeOptions > > {
219294 let report_time = unstable_optflag ! ( matches, allow_unstable, "report-time" ) ;
220295 let colored_opt_str = matches. opt_str ( "report-time" ) ;
221296 let mut report_time_colored = report_time && colored_opt_str == Some ( "colored" . into ( ) ) ;
@@ -232,71 +307,73 @@ fn get_time_options(
232307 None
233308 } ;
234309
235- Some ( Ok ( options) )
310+ Ok ( options)
236311}
237312
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 ,
246327 } ;
247328
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+ }
254331
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+ ) ;
261342 }
343+ OutputFormat :: Json
262344 }
263- } ;
264345
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+ }
274353 } ;
275354
276- let exclude_should_panic = unstable_optflag ! ( matches, allow_unstable, "exclude-should-panic" ) ;
355+ Ok ( format)
356+ }
277357
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 ,
279363
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
284369 ) ) ;
285370 }
286- ( true , false ) => RunIgnored :: Yes ,
287- ( false , true ) => RunIgnored :: Only ,
288- ( false , false ) => RunIgnored :: No ,
289371 } ;
290- let quiet = matches. opt_present ( "quiet" ) ;
291- let exact = matches. opt_present ( "exact" ) ;
292- let list = matches. opt_present ( "list" ) ;
293372
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+ }
299375
376+ fn get_nocapture ( matches : & getopts:: Matches ) -> OptPartRes < bool > {
300377 let mut nocapture = matches. opt_present ( "nocapture" ) ;
301378 if !nocapture {
302379 nocapture = match env:: var ( "RUST_TEST_NOCAPTURE" ) {
@@ -305,80 +382,59 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
305382 } ;
306383 }
307384
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+ }
313387
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 ,
327398 } ;
328399
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+ }
333402
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
341408 } ;
342409
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+ ) ;
354421 }
355422
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+ }
362430 }
363431 } ;
364432
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) ) ;
382438
383- Some ( Ok ( test_opts ) )
439+ Ok ( logfile )
384440}
0 commit comments