@@ -57,6 +57,7 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
57
57
struct Renderer < ' a > {
58
58
stdout : BufReader < ChildStdout > ,
59
59
failures : Vec < TestOutcome > ,
60
+ benches : Vec < BenchOutcome > ,
60
61
builder : & ' a Builder < ' a > ,
61
62
tests_count : Option < usize > ,
62
63
executed_tests : usize ,
@@ -67,6 +68,7 @@ impl<'a> Renderer<'a> {
67
68
fn new ( stdout : ChildStdout , builder : & ' a Builder < ' a > ) -> Self {
68
69
Self {
69
70
stdout : BufReader :: new ( stdout) ,
71
+ benches : Vec :: new ( ) ,
70
72
failures : Vec :: new ( ) ,
71
73
builder,
72
74
tests_count : None ,
@@ -104,7 +106,7 @@ impl<'a> Renderer<'a> {
104
106
self . builder . metrics . record_test (
105
107
& test. name ,
106
108
match outcome {
107
- Outcome :: Ok => crate :: metrics:: TestOutcome :: Passed ,
109
+ Outcome :: Ok | Outcome :: BenchOk => crate :: metrics:: TestOutcome :: Passed ,
108
110
Outcome :: Failed => crate :: metrics:: TestOutcome :: Failed ,
109
111
Outcome :: Ignored { reason } => crate :: metrics:: TestOutcome :: Ignored {
110
112
ignore_reason : reason. map ( |s| s. to_string ( ) ) ,
@@ -169,6 +171,26 @@ impl<'a> Renderer<'a> {
169
171
}
170
172
}
171
173
174
+ if !self . benches . is_empty ( ) {
175
+ println ! ( "\n benchmarks:" ) ;
176
+
177
+ let mut rows = Vec :: new ( ) ;
178
+ for bench in & self . benches {
179
+ rows. push ( (
180
+ & bench. name ,
181
+ format ! ( "{:.2?}/iter" , Duration :: from_nanos( bench. median) ) ,
182
+ format ! ( "+/- {:.2?}" , Duration :: from_nanos( bench. deviation) ) ,
183
+ ) ) ;
184
+ }
185
+
186
+ let max_0 = rows. iter ( ) . map ( |r| r. 0 . len ( ) ) . max ( ) . unwrap_or ( 0 ) ;
187
+ let max_1 = rows. iter ( ) . map ( |r| r. 1 . len ( ) ) . max ( ) . unwrap_or ( 0 ) ;
188
+ let max_2 = rows. iter ( ) . map ( |r| r. 2 . len ( ) ) . max ( ) . unwrap_or ( 0 ) ;
189
+ for row in & rows {
190
+ println ! ( " {:<max_0$} {:>max_1$} {:>max_2$}" , row. 0 , row. 1 , row. 2 ) ;
191
+ }
192
+ }
193
+
172
194
println ! (
173
195
"\n test result: {}. {} passed; {} failed; {} ignored; {} measured; \
174
196
{} filtered out; finished in {:.2?}\n ",
@@ -196,6 +218,21 @@ impl<'a> Renderer<'a> {
196
218
Message :: Suite ( SuiteMessage :: Failed ( outcome) ) => {
197
219
self . render_suite_outcome ( Outcome :: Failed , & outcome) ;
198
220
}
221
+ Message :: Bench ( outcome) => {
222
+ // The formatting for benchmarks doesn't replicate 1:1 the formatting libtest
223
+ // outputs, mostly because libtest's formatting is broken in terse mode, which is
224
+ // the default used by our monorepo. We use a different formatting instead:
225
+ // successful benchmarks are just showed as "benchmarked"/"b", and the details are
226
+ // outputted at the bottom like failures.
227
+ let fake_test_outcome = TestOutcome {
228
+ name : outcome. name . clone ( ) ,
229
+ exec_time : None ,
230
+ stdout : None ,
231
+ reason : None ,
232
+ } ;
233
+ self . render_test_outcome ( Outcome :: BenchOk , & fake_test_outcome) ;
234
+ self . benches . push ( outcome) ;
235
+ }
199
236
Message :: Test ( TestMessage :: Ok ( outcome) ) => {
200
237
self . render_test_outcome ( Outcome :: Ok , & outcome) ;
201
238
}
@@ -210,13 +247,13 @@ impl<'a> Renderer<'a> {
210
247
self . failures . push ( outcome) ;
211
248
}
212
249
Message :: Test ( TestMessage :: Started ) => { } // Not useful
213
- Message :: Test ( TestMessage :: Bench ) => todo ! ( "benchmarks are not supported yet" ) ,
214
250
}
215
251
}
216
252
}
217
253
218
254
enum Outcome < ' a > {
219
255
Ok ,
256
+ BenchOk ,
220
257
Failed ,
221
258
Ignored { reason : Option < & ' a str > } ,
222
259
}
@@ -225,6 +262,7 @@ impl Outcome<'_> {
225
262
fn short ( & self , builder : & Builder < ' _ > ) -> String {
226
263
match self {
227
264
Outcome :: Ok => builder. color_for_stdout ( Color :: Green , "." ) ,
265
+ Outcome :: BenchOk => builder. color_for_stdout ( Color :: Cyan , "b" ) ,
228
266
Outcome :: Failed => builder. color_for_stdout ( Color :: Red , "F" ) ,
229
267
Outcome :: Ignored { .. } => builder. color_for_stdout ( Color :: Yellow , "i" ) ,
230
268
}
@@ -233,6 +271,7 @@ impl Outcome<'_> {
233
271
fn long ( & self , builder : & Builder < ' _ > ) -> String {
234
272
match self {
235
273
Outcome :: Ok => builder. color_for_stdout ( Color :: Green , "ok" ) ,
274
+ Outcome :: BenchOk => builder. color_for_stdout ( Color :: Cyan , "benchmarked" ) ,
236
275
Outcome :: Failed => builder. color_for_stdout ( Color :: Red , "FAILED" ) ,
237
276
Outcome :: Ignored { reason : None } => builder. color_for_stdout ( Color :: Yellow , "ignored" ) ,
238
277
Outcome :: Ignored { reason : Some ( reason) } => {
@@ -247,6 +286,7 @@ impl Outcome<'_> {
247
286
enum Message {
248
287
Suite ( SuiteMessage ) ,
249
288
Test ( TestMessage ) ,
289
+ Bench ( BenchOutcome ) ,
250
290
}
251
291
252
292
#[ derive( serde_derive:: Deserialize ) ]
@@ -273,11 +313,16 @@ enum TestMessage {
273
313
Ok ( TestOutcome ) ,
274
314
Failed ( TestOutcome ) ,
275
315
Ignored ( TestOutcome ) ,
276
- // Ignored messages:
277
- Bench ,
278
316
Started ,
279
317
}
280
318
319
+ #[ derive( serde_derive:: Deserialize ) ]
320
+ struct BenchOutcome {
321
+ name : String ,
322
+ median : u64 ,
323
+ deviation : u64 ,
324
+ }
325
+
281
326
#[ derive( serde_derive:: Deserialize ) ]
282
327
struct TestOutcome {
283
328
name : String ,
0 commit comments