@@ -10,6 +10,7 @@ use std::io::{BufRead, BufReader, Read, Write};
10
10
use std:: process:: { ChildStdout , Stdio } ;
11
11
use std:: time:: Duration ;
12
12
13
+ use build_helper:: ci:: CiEnv ;
13
14
use termcolor:: { Color , ColorSpec , WriteColor } ;
14
15
15
16
use crate :: core:: builder:: Builder ;
@@ -91,7 +92,9 @@ struct Renderer<'a> {
91
92
/// Number of tests that were skipped due to already being up-to-date
92
93
/// (i.e. no relevant changes occurred since they last ran).
93
94
up_to_date_tests : usize ,
95
+ ignored_tests : usize ,
94
96
terse_tests_in_line : usize ,
97
+ ci_latest_logged_percentage : f64 ,
95
98
}
96
99
97
100
impl < ' a > Renderer < ' a > {
@@ -104,7 +107,9 @@ impl<'a> Renderer<'a> {
104
107
tests_count : None ,
105
108
executed_tests : 0 ,
106
109
up_to_date_tests : 0 ,
110
+ ignored_tests : 0 ,
107
111
terse_tests_in_line : 0 ,
112
+ ci_latest_logged_percentage : 0.0 ,
108
113
}
109
114
}
110
115
@@ -159,9 +164,12 @@ impl<'a> Renderer<'a> {
159
164
fn render_test_outcome ( & mut self , outcome : Outcome < ' _ > , test : & TestOutcome ) {
160
165
self . executed_tests += 1 ;
161
166
162
- // Keep this in sync with the "up-to-date" ignore message inserted by compiletest.
163
- if let Outcome :: Ignored { reason : Some ( "up-to-date" ) } = outcome {
164
- self . up_to_date_tests += 1 ;
167
+ if let Outcome :: Ignored { reason } = outcome {
168
+ self . ignored_tests += 1 ;
169
+ // Keep this in sync with the "up-to-date" ignore message inserted by compiletest.
170
+ if reason == Some ( "up-to-date" ) {
171
+ self . up_to_date_tests += 1 ;
172
+ }
165
173
}
166
174
167
175
#[ cfg( feature = "build-metrics" ) ]
@@ -179,6 +187,8 @@ impl<'a> Renderer<'a> {
179
187
180
188
if self . builder . config . verbose_tests {
181
189
self . render_test_outcome_verbose ( outcome, test) ;
190
+ } else if CiEnv :: is_ci ( ) {
191
+ self . render_test_outcome_ci ( outcome, test) ;
182
192
} else {
183
193
self . render_test_outcome_terse ( outcome, test) ;
184
194
}
@@ -209,6 +219,31 @@ impl<'a> Renderer<'a> {
209
219
let _ = std:: io:: stdout ( ) . flush ( ) ;
210
220
}
211
221
222
+ fn render_test_outcome_ci ( & mut self , outcome : Outcome < ' _ > , test : & TestOutcome ) {
223
+ if let Some ( total) = self . tests_count {
224
+ let percent = self . executed_tests as f64 / total as f64 ;
225
+
226
+ if self . ci_latest_logged_percentage + 0.10 < percent {
227
+ let total = total. to_string ( ) ;
228
+ let executed = format ! ( "{:>width$}" , self . executed_tests, width = total. len( ) ) ;
229
+ let pretty_percent = format ! ( "{:.0}%" , percent * 100.0 ) ;
230
+ let passed_tests = self . executed_tests - ( self . failures . len ( ) + self . ignored_tests ) ;
231
+ println ! (
232
+ "{:<4} -- {executed}/{total}, {:>total_indent$} passed, {} failed, {} ignored" ,
233
+ pretty_percent,
234
+ passed_tests,
235
+ self . failures. len( ) ,
236
+ self . ignored_tests,
237
+ total_indent = total. len( )
238
+ ) ;
239
+ self . ci_latest_logged_percentage += 0.10 ;
240
+ }
241
+ }
242
+
243
+ self . builder . colored_stdout ( |stdout| outcome. write_ci ( stdout, & test. name ) ) . unwrap ( ) ;
244
+ let _ = std:: io:: stdout ( ) . flush ( ) ;
245
+ }
246
+
212
247
fn render_suite_outcome ( & self , outcome : Outcome < ' _ > , suite : & SuiteOutcome ) {
213
248
// The terse output doesn't end with a newline, so we need to add it ourselves.
214
249
if !self . builder . config . verbose_tests {
@@ -378,6 +413,17 @@ impl Outcome<'_> {
378
413
}
379
414
writer. reset ( )
380
415
}
416
+
417
+ fn write_ci ( & self , writer : & mut dyn WriteColor , name : & str ) -> Result < ( ) , std:: io:: Error > {
418
+ match self {
419
+ Outcome :: Ok | Outcome :: BenchOk | Outcome :: Ignored { .. } => { }
420
+ Outcome :: Failed => {
421
+ writer. set_color ( ColorSpec :: new ( ) . set_fg ( Some ( Color :: Red ) ) ) ?;
422
+ writeln ! ( writer, " {name} ... FAILED" ) ?;
423
+ }
424
+ }
425
+ writer. reset ( )
426
+ }
381
427
}
382
428
383
429
#[ derive( serde_derive:: Deserialize ) ]
0 commit comments