@@ -10,6 +10,7 @@ use crate::builder::Builder;
10
10
use std:: io:: { BufRead , BufReader , Write } ;
11
11
use std:: process:: { ChildStdout , Command , Stdio } ;
12
12
use std:: time:: Duration ;
13
+ use yansi_term:: Color ;
13
14
14
15
const TERSE_TESTS_PER_LINE : usize = 88 ;
15
16
@@ -37,13 +38,12 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
37
38
builder. verbose ( & format ! ( "running: {cmd:?}" ) ) ;
38
39
39
40
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 ( ) ) ;
43
41
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 ( ) ;
46
45
46
+ let result = process. wait ( ) . unwrap ( ) ;
47
47
if !result. success ( ) && builder. is_verbose ( ) {
48
48
println ! (
49
49
"\n \n command did not execute successfully: {cmd:?}\n \
@@ -54,21 +54,21 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
54
54
result. success ( )
55
55
}
56
56
57
- struct Renderer {
57
+ struct Renderer < ' a > {
58
58
stdout : BufReader < ChildStdout > ,
59
59
failures : Vec < TestOutcome > ,
60
- verbose : bool ,
60
+ builder : & ' a Builder < ' a > ,
61
61
tests_count : Option < usize > ,
62
62
executed_tests : usize ,
63
63
terse_tests_in_line : usize ,
64
64
}
65
65
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 {
68
68
Self {
69
69
stdout : BufReader :: new ( stdout) ,
70
70
failures : Vec :: new ( ) ,
71
- verbose ,
71
+ builder ,
72
72
tests_count : None ,
73
73
executed_tests : 0 ,
74
74
terse_tests_in_line : 0 ,
@@ -99,7 +99,7 @@ impl Renderer {
99
99
100
100
fn render_test_outcome ( & mut self , outcome : Outcome < ' _ > , test : & TestOutcome ) {
101
101
self . executed_tests += 1 ;
102
- if self . verbose {
102
+ if self . builder . config . verbose_tests {
103
103
self . render_test_outcome_verbose ( outcome, test) ;
104
104
} else {
105
105
self . render_test_outcome_terse ( outcome, test) ;
@@ -109,12 +109,13 @@ impl Renderer {
109
109
fn render_test_outcome_verbose ( & self , outcome : Outcome < ' _ > , test : & TestOutcome ) {
110
110
if let Some ( exec_time) = test. exec_time {
111
111
println ! (
112
- "test {} ... {outcome } (in {:.2?})" ,
112
+ "test {} ... {} (in {:.2?})" ,
113
113
test. name,
114
+ outcome. long( self . builder) ,
114
115
Duration :: from_secs_f64( exec_time)
115
116
) ;
116
117
} else {
117
- println ! ( "test {} ... {outcome }" , test. name) ;
118
+ println ! ( "test {} ... {}" , test. name, outcome . long ( self . builder ) ) ;
118
119
}
119
120
}
120
121
@@ -130,20 +131,13 @@ impl Renderer {
130
131
}
131
132
132
133
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) ) ;
141
135
let _ = std:: io:: stdout ( ) . flush ( ) ;
142
136
}
143
137
144
138
fn render_suite_outcome ( & self , outcome : Outcome < ' _ > , suite : & SuiteOutcome ) {
145
139
// 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 {
147
141
println ! ( ) ;
148
142
}
149
143
@@ -163,8 +157,9 @@ impl Renderer {
163
157
}
164
158
165
159
println ! (
166
- "\n test result: {outcome }. {} passed; {} failed; {} ignored; {} measured; \
160
+ "\n test result: {}. {} passed; {} failed; {} ignored; {} measured; \
167
161
{} filtered out; finished in {:.2?}\n ",
162
+ outcome. long( self . builder) ,
168
163
suite. passed,
169
164
suite. failed,
170
165
suite. ignored,
@@ -213,13 +208,23 @@ enum Outcome<'a> {
213
208
Ignored { reason : Option < & ' a str > } ,
214
209
}
215
210
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 {
218
213
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
+ }
223
228
}
224
229
}
225
230
}
0 commit comments