77//! to reimplement all the rendering logic in this module because of that.
88
99use crate :: builder:: Builder ;
10- use std:: io:: { BufRead , BufReader } ;
10+ use std:: io:: { BufRead , BufReader , Write } ;
1111use std:: process:: { ChildStdout , Command , Stdio } ;
1212use std:: time:: Duration ;
1313
14+ const TERSE_TESTS_PER_LINE : usize = 88 ;
15+
1416pub ( crate ) fn try_run_tests ( builder : & Builder < ' _ > , cmd : & mut Command ) -> bool {
1517 if builder. config . dry_run ( ) {
1618 return true ;
@@ -36,7 +38,8 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
3638
3739 let mut process = cmd. spawn ( ) . unwrap ( ) ;
3840 let stdout = process. stdout . take ( ) . unwrap ( ) ;
39- let handle = std:: thread:: spawn ( move || Renderer :: new ( stdout) . render_all ( ) ) ;
41+ let verbose = builder. config . verbose_tests ;
42+ let handle = std:: thread:: spawn ( move || Renderer :: new ( stdout, verbose) . render_all ( ) ) ;
4043
4144 let result = process. wait ( ) . unwrap ( ) ;
4245 handle. join ( ) . expect ( "test formatter thread failed" ) ;
@@ -54,11 +57,22 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
5457struct Renderer {
5558 stdout : BufReader < ChildStdout > ,
5659 failures : Vec < TestOutcome > ,
60+ verbose : bool ,
61+ tests_count : Option < usize > ,
62+ executed_tests : usize ,
63+ terse_tests_in_line : usize ,
5764}
5865
5966impl Renderer {
60- fn new ( stdout : ChildStdout ) -> Self {
61- Self { stdout : BufReader :: new ( stdout) , failures : Vec :: new ( ) }
67+ fn new ( stdout : ChildStdout , verbose : bool ) -> Self {
68+ Self {
69+ stdout : BufReader :: new ( stdout) ,
70+ failures : Vec :: new ( ) ,
71+ verbose,
72+ tests_count : None ,
73+ executed_tests : 0 ,
74+ terse_tests_in_line : 0 ,
75+ }
6276 }
6377
6478 fn render_all ( mut self ) {
@@ -83,9 +97,13 @@ impl Renderer {
8397 }
8498 }
8599
86- fn render_test_outcome ( & self , outcome : Outcome < ' _ > , test : & TestOutcome ) {
87- // TODO: add support for terse output
88- self . render_test_outcome_verbose ( outcome, test) ;
100+ fn render_test_outcome ( & mut self , outcome : Outcome < ' _ > , test : & TestOutcome ) {
101+ self . executed_tests += 1 ;
102+ if self . verbose {
103+ self . render_test_outcome_verbose ( outcome, test) ;
104+ } else {
105+ self . render_test_outcome_terse ( outcome, test) ;
106+ }
89107 }
90108
91109 fn render_test_outcome_verbose ( & self , outcome : Outcome < ' _ > , test : & TestOutcome ) {
@@ -100,7 +118,35 @@ impl Renderer {
100118 }
101119 }
102120
121+ fn render_test_outcome_terse ( & mut self , outcome : Outcome < ' _ > , _: & TestOutcome ) {
122+ if self . terse_tests_in_line != 0 && self . terse_tests_in_line % TERSE_TESTS_PER_LINE == 0 {
123+ if let Some ( total) = self . tests_count {
124+ let total = total. to_string ( ) ;
125+ let executed = format ! ( "{:>width$}" , self . executed_tests - 1 , width = total. len( ) ) ;
126+ print ! ( " {executed}/{total}" ) ;
127+ }
128+ println ! ( ) ;
129+ self . terse_tests_in_line = 0 ;
130+ }
131+
132+ self . terse_tests_in_line += 1 ;
133+ print ! (
134+ "{}" ,
135+ match outcome {
136+ Outcome :: Ok => "." ,
137+ Outcome :: Failed => "F" ,
138+ Outcome :: Ignored { .. } => "i" ,
139+ }
140+ ) ;
141+ let _ = std:: io:: stdout ( ) . flush ( ) ;
142+ }
143+
103144 fn render_suite_outcome ( & self , outcome : Outcome < ' _ > , suite : & SuiteOutcome ) {
145+ // The terse output doesn't end with a newline, so we need to add it ourselves.
146+ if !self . verbose {
147+ println ! ( ) ;
148+ }
149+
104150 if !self . failures . is_empty ( ) {
105151 println ! ( "\n failures:\n " ) ;
106152 for failure in & self . failures {
@@ -132,6 +178,9 @@ impl Renderer {
132178 match message {
133179 Message :: Suite ( SuiteMessage :: Started { test_count } ) => {
134180 println ! ( "\n running {test_count} tests" ) ;
181+ self . executed_tests = 0 ;
182+ self . terse_tests_in_line = 0 ;
183+ self . tests_count = Some ( test_count) ;
135184 }
136185 Message :: Suite ( SuiteMessage :: Ok ( outcome) ) => {
137186 self . render_suite_outcome ( Outcome :: Ok , & outcome) ;
0 commit comments