@@ -254,10 +254,16 @@ pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>) {
254
254
Some ( Err ( msg) ) => panic ! ( "{:?}" , msg) ,
255
255
None => return ,
256
256
} ;
257
- match run_tests_console ( & opts, tests) {
258
- Ok ( true ) => { }
259
- Ok ( false ) => std:: process:: exit ( 101 ) ,
260
- Err ( e) => panic ! ( "io error when running tests: {:?}" , e) ,
257
+ if opts. list {
258
+ if let Err ( e) = list_tests_console ( & opts, tests) {
259
+ panic ! ( "io error when listing tests: {:?}" , e) ;
260
+ }
261
+ } else {
262
+ match run_tests_console ( & opts, tests) {
263
+ Ok ( true ) => { }
264
+ Ok ( false ) => std:: process:: exit ( 101 ) ,
265
+ Err ( e) => panic ! ( "io error when running tests: {:?}" , e) ,
266
+ }
261
267
}
262
268
}
263
269
@@ -300,6 +306,7 @@ pub enum ColorConfig {
300
306
}
301
307
302
308
pub struct TestOpts {
309
+ pub list : bool ,
303
310
pub filter : Option < String > ,
304
311
pub filter_exact : bool ,
305
312
pub run_ignored : bool ,
@@ -317,6 +324,7 @@ impl TestOpts {
317
324
#[ cfg( test) ]
318
325
fn new ( ) -> TestOpts {
319
326
TestOpts {
327
+ list : false ,
320
328
filter : None ,
321
329
filter_exact : false ,
322
330
run_ignored : false ,
@@ -340,6 +348,7 @@ fn optgroups() -> Vec<getopts::OptGroup> {
340
348
vec ! [ getopts:: optflag( "" , "ignored" , "Run ignored tests" ) ,
341
349
getopts:: optflag( "" , "test" , "Run tests and not benchmarks" ) ,
342
350
getopts:: optflag( "" , "bench" , "Run benchmarks instead of tests" ) ,
351
+ getopts:: optflag( "" , "list" , "List all tests and benchmarks" ) ,
343
352
getopts:: optflag( "h" , "help" , "Display this message (longer with --help)" ) ,
344
353
getopts:: optopt( "" , "logfile" , "Write logs to the specified file instead \
345
354
of stdout", "PATH" ) ,
@@ -411,6 +420,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
411
420
let run_ignored = matches. opt_present ( "ignored" ) ;
412
421
let quiet = matches. opt_present ( "quiet" ) ;
413
422
let exact = matches. opt_present ( "exact" ) ;
423
+ let list = matches. opt_present ( "list" ) ;
414
424
415
425
let logfile = matches. opt_str ( "logfile" ) ;
416
426
let logfile = logfile. map ( |s| PathBuf :: from ( & s) ) ;
@@ -451,6 +461,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
451
461
} ;
452
462
453
463
let test_opts = TestOpts {
464
+ list : list,
454
465
filter : filter,
455
466
filter_exact : exact,
456
467
run_ignored : run_ignored,
@@ -581,7 +592,8 @@ impl<T: Write> ConsoleTestState<T> {
581
592
}
582
593
}
583
594
584
- pub fn write_plain ( & mut self , s : & str ) -> io:: Result < ( ) > {
595
+ pub fn write_plain < S : AsRef < str > > ( & mut self , s : S ) -> io:: Result < ( ) > {
596
+ let s = s. as_ref ( ) ;
585
597
match self . out {
586
598
Pretty ( ref mut term) => {
587
599
term. write_all ( s. as_bytes ( ) ) ?;
@@ -635,25 +647,28 @@ impl<T: Write> ConsoleTestState<T> {
635
647
TEST_WARN_TIMEOUT_S ) )
636
648
}
637
649
638
- pub fn write_log ( & mut self , test : & TestDesc , result : & TestResult ) -> io:: Result < ( ) > {
650
+ pub fn write_log < S : AsRef < str > > ( & mut self , msg : S ) -> io:: Result < ( ) > {
651
+ let msg = msg. as_ref ( ) ;
639
652
match self . log_out {
640
653
None => Ok ( ( ) ) ,
641
- Some ( ref mut o) => {
642
- let s = format ! ( "{} {}\n " ,
643
- match * result {
644
- TrOk => "ok" . to_owned( ) ,
645
- TrFailed => "failed" . to_owned( ) ,
646
- TrFailedMsg ( ref msg) => format!( "failed: {}" , msg) ,
647
- TrIgnored => "ignored" . to_owned( ) ,
648
- TrMetrics ( ref mm) => mm. fmt_metrics( ) ,
649
- TrBench ( ref bs) => fmt_bench_samples( bs) ,
650
- } ,
651
- test. name) ;
652
- o. write_all ( s. as_bytes ( ) )
653
- }
654
+ Some ( ref mut o) => o. write_all ( msg. as_bytes ( ) ) ,
654
655
}
655
656
}
656
657
658
+ pub fn write_log_result ( & mut self , test : & TestDesc , result : & TestResult ) -> io:: Result < ( ) > {
659
+ self . write_log (
660
+ format ! ( "{} {}\n " ,
661
+ match * result {
662
+ TrOk => "ok" . to_owned( ) ,
663
+ TrFailed => "failed" . to_owned( ) ,
664
+ TrFailedMsg ( ref msg) => format!( "failed: {}" , msg) ,
665
+ TrIgnored => "ignored" . to_owned( ) ,
666
+ TrMetrics ( ref mm) => mm. fmt_metrics( ) ,
667
+ TrBench ( ref bs) => fmt_bench_samples( bs) ,
668
+ } ,
669
+ test. name) )
670
+ }
671
+
657
672
pub fn write_failures ( & mut self ) -> io:: Result < ( ) > {
658
673
self . write_plain ( "\n failures:\n " ) ?;
659
674
let mut failures = Vec :: new ( ) ;
@@ -746,6 +761,49 @@ pub fn fmt_bench_samples(bs: &BenchSamples) -> String {
746
761
output
747
762
}
748
763
764
+ // List the tests to console, and optionally to logfile. Filters are honored.
765
+ pub fn list_tests_console ( opts : & TestOpts , tests : Vec < TestDescAndFn > ) -> io:: Result < ( ) > {
766
+ let mut st = ConsoleTestState :: new ( opts, None :: < io:: Stdout > ) ?;
767
+
768
+ let mut ntest = 0 ;
769
+ let mut nbench = 0 ;
770
+ let mut nmetric = 0 ;
771
+
772
+ for test in filter_tests ( & opts, tests) {
773
+ use TestFn :: * ;
774
+
775
+ let TestDescAndFn { desc : TestDesc { name, .. } , testfn } = test;
776
+
777
+ let fntype = match testfn {
778
+ StaticTestFn ( ..) | DynTestFn ( ..) => { ntest += 1 ; "test" } ,
779
+ StaticBenchFn ( ..) | DynBenchFn ( ..) => { nbench += 1 ; "benchmark" } ,
780
+ StaticMetricFn ( ..) | DynMetricFn ( ..) => { nmetric += 1 ; "metric" } ,
781
+ } ;
782
+
783
+ st. write_plain ( format ! ( "{}: {}\n " , name, fntype) ) ?;
784
+ st. write_log ( format ! ( "{} {}\n " , fntype, name) ) ?;
785
+ }
786
+
787
+ fn plural ( count : u32 , s : & str ) -> String {
788
+ match count {
789
+ 1 => format ! ( "{} {}" , 1 , s) ,
790
+ n => format ! ( "{} {}s" , n, s) ,
791
+ }
792
+ }
793
+
794
+ if !opts. quiet {
795
+ if ntest != 0 || nbench != 0 || nmetric != 0 {
796
+ st. write_plain ( "\n " ) ?;
797
+ }
798
+ st. write_plain ( format ! ( "{}, {}, {}\n " ,
799
+ plural( ntest, "test" ) ,
800
+ plural( nbench, "benchmark" ) ,
801
+ plural( nmetric, "metric" ) ) ) ?;
802
+ }
803
+
804
+ Ok ( ( ) )
805
+ }
806
+
749
807
// A simple console test runner
750
808
pub fn run_tests_console ( opts : & TestOpts , tests : Vec < TestDescAndFn > ) -> io:: Result < bool > {
751
809
@@ -755,7 +813,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
755
813
TeWait ( ref test, padding) => st. write_test_start ( test, padding) ,
756
814
TeTimeout ( ref test) => st. write_timeout ( test) ,
757
815
TeResult ( test, result, stdout) => {
758
- st. write_log ( & test, & result) ?;
816
+ st. write_log_result ( & test, & result) ?;
759
817
st. write_result ( & result) ?;
760
818
match result {
761
819
TrOk => st. passed += 1 ,
0 commit comments