@@ -10,6 +10,7 @@ use crate::builder::Builder;
1010use std:: io:: { BufRead , BufReader , Write } ;
1111use std:: process:: { ChildStdout , Command , Stdio } ;
1212use std:: time:: Duration ;
13+ use yansi_term:: Color ;
1314
1415const TERSE_TESTS_PER_LINE : usize = 88 ;
1516
@@ -37,13 +38,12 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
3738 builder. verbose ( & format ! ( "running: {cmd:?}" ) ) ;
3839
3940 let mut process = cmd. spawn ( ) . unwrap ( ) ;
40- let stdout = process. stdout . take ( ) . unwrap ( ) ;
41- let verbose = builder. config . verbose_tests ;
42- let handle = std:: thread:: spawn ( move || Renderer :: new ( stdout, verbose) . render_all ( ) ) ;
4341
44- let result = process. wait ( ) . unwrap ( ) ;
45- handle. join ( ) . expect ( "test formatter thread failed" ) ;
42+ // This runs until the stdout of the child is closed, which means the child exited. We don't
43+ // run this on another thread since the builder is not Sync.
44+ Renderer :: new ( process. stdout . take ( ) . unwrap ( ) , builder) . render_all ( ) ;
4645
46+ let result = process. wait ( ) . unwrap ( ) ;
4747 if !result. success ( ) && builder. is_verbose ( ) {
4848 println ! (
4949 "\n \n command did not execute successfully: {cmd:?}\n \
@@ -54,21 +54,21 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
5454 result. success ( )
5555}
5656
57- struct Renderer {
57+ struct Renderer < ' a > {
5858 stdout : BufReader < ChildStdout > ,
5959 failures : Vec < TestOutcome > ,
60- verbose : bool ,
60+ builder : & ' a Builder < ' a > ,
6161 tests_count : Option < usize > ,
6262 executed_tests : usize ,
6363 terse_tests_in_line : usize ,
6464}
6565
66- impl Renderer {
67- fn new ( stdout : ChildStdout , verbose : bool ) -> Self {
66+ impl < ' a > Renderer < ' a > {
67+ fn new ( stdout : ChildStdout , builder : & ' a Builder < ' a > ) -> Self {
6868 Self {
6969 stdout : BufReader :: new ( stdout) ,
7070 failures : Vec :: new ( ) ,
71- verbose ,
71+ builder ,
7272 tests_count : None ,
7373 executed_tests : 0 ,
7474 terse_tests_in_line : 0 ,
@@ -99,7 +99,7 @@ impl Renderer {
9999
100100 fn render_test_outcome ( & mut self , outcome : Outcome < ' _ > , test : & TestOutcome ) {
101101 self . executed_tests += 1 ;
102- if self . verbose {
102+ if self . builder . config . verbose_tests {
103103 self . render_test_outcome_verbose ( outcome, test) ;
104104 } else {
105105 self . render_test_outcome_terse ( outcome, test) ;
@@ -109,12 +109,13 @@ impl Renderer {
109109 fn render_test_outcome_verbose ( & self , outcome : Outcome < ' _ > , test : & TestOutcome ) {
110110 if let Some ( exec_time) = test. exec_time {
111111 println ! (
112- "test {} ... {outcome } (in {:.2?})" ,
112+ "test {} ... {} (in {:.2?})" ,
113113 test. name,
114+ outcome. long( self . builder) ,
114115 Duration :: from_secs_f64( exec_time)
115116 ) ;
116117 } else {
117- println ! ( "test {} ... {outcome }" , test. name) ;
118+ println ! ( "test {} ... {}" , test. name, outcome . long ( self . builder ) ) ;
118119 }
119120 }
120121
@@ -130,20 +131,13 @@ impl Renderer {
130131 }
131132
132133 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- ) ;
134+ print ! ( "{}" , outcome. short( self . builder) ) ;
141135 let _ = std:: io:: stdout ( ) . flush ( ) ;
142136 }
143137
144138 fn render_suite_outcome ( & self , outcome : Outcome < ' _ > , suite : & SuiteOutcome ) {
145139 // The terse output doesn't end with a newline, so we need to add it ourselves.
146- if !self . verbose {
140+ if !self . builder . config . verbose_tests {
147141 println ! ( ) ;
148142 }
149143
@@ -163,8 +157,9 @@ impl Renderer {
163157 }
164158
165159 println ! (
166- "\n test result: {outcome }. {} passed; {} failed; {} ignored; {} measured; \
160+ "\n test result: {}. {} passed; {} failed; {} ignored; {} measured; \
167161 {} filtered out; finished in {:.2?}\n ",
162+ outcome. long( self . builder) ,
168163 suite. passed,
169164 suite. failed,
170165 suite. ignored,
@@ -213,13 +208,23 @@ enum Outcome<'a> {
213208 Ignored { reason : Option < & ' a str > } ,
214209}
215210
216- impl std :: fmt :: Display for Outcome < ' _ > {
217- fn fmt ( & self , f : & mut std :: fmt :: Formatter < ' _ > ) -> std :: fmt :: Result {
211+ impl Outcome < ' _ > {
212+ fn short ( & self , builder : & Builder < ' _ > ) -> String {
218213 match self {
219- Outcome :: Ok => f. write_str ( "ok" ) ,
220- Outcome :: Failed => f. write_str ( "FAILED" ) ,
221- Outcome :: Ignored { reason : None } => f. write_str ( "ignored" ) ,
222- Outcome :: Ignored { reason : Some ( reason) } => write ! ( f, "ignored, {reason}" ) ,
214+ Outcome :: Ok => builder. color_for_stdout ( Color :: Green , "." ) ,
215+ Outcome :: Failed => builder. color_for_stdout ( Color :: Red , "F" ) ,
216+ Outcome :: Ignored { .. } => builder. color_for_stdout ( Color :: Yellow , "i" ) ,
217+ }
218+ }
219+
220+ fn long ( & self , builder : & Builder < ' _ > ) -> String {
221+ match self {
222+ Outcome :: Ok => builder. color_for_stdout ( Color :: Green , "ok" ) ,
223+ Outcome :: Failed => builder. color_for_stdout ( Color :: Red , "FAILED" ) ,
224+ Outcome :: Ignored { reason : None } => builder. color_for_stdout ( Color :: Yellow , "ignored" ) ,
225+ Outcome :: Ignored { reason : Some ( reason) } => {
226+ builder. color_for_stdout ( Color :: Yellow , & format ! ( "ignored, {reason}" ) )
227+ }
223228 }
224229 }
225230}
0 commit comments