@@ -57,6 +57,7 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
5757struct Renderer < ' a > {
5858 stdout : BufReader < ChildStdout > ,
5959 failures : Vec < TestOutcome > ,
60+ benches : Vec < BenchOutcome > ,
6061 builder : & ' a Builder < ' a > ,
6162 tests_count : Option < usize > ,
6263 executed_tests : usize ,
@@ -67,6 +68,7 @@ impl<'a> Renderer<'a> {
6768 fn new ( stdout : ChildStdout , builder : & ' a Builder < ' a > ) -> Self {
6869 Self {
6970 stdout : BufReader :: new ( stdout) ,
71+ benches : Vec :: new ( ) ,
7072 failures : Vec :: new ( ) ,
7173 builder,
7274 tests_count : None ,
@@ -104,7 +106,7 @@ impl<'a> Renderer<'a> {
104106 self . builder . metrics . record_test (
105107 & test. name ,
106108 match outcome {
107- Outcome :: Ok => crate :: metrics:: TestOutcome :: Passed ,
109+ Outcome :: Ok | Outcome :: BenchOk => crate :: metrics:: TestOutcome :: Passed ,
108110 Outcome :: Failed => crate :: metrics:: TestOutcome :: Failed ,
109111 Outcome :: Ignored { reason } => crate :: metrics:: TestOutcome :: Ignored {
110112 ignore_reason : reason. map ( |s| s. to_string ( ) ) ,
@@ -169,6 +171,26 @@ impl<'a> Renderer<'a> {
169171 }
170172 }
171173
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+
172194 println ! (
173195 "\n test result: {}. {} passed; {} failed; {} ignored; {} measured; \
174196 {} filtered out; finished in {:.2?}\n ",
@@ -196,6 +218,21 @@ impl<'a> Renderer<'a> {
196218 Message :: Suite ( SuiteMessage :: Failed ( outcome) ) => {
197219 self . render_suite_outcome ( Outcome :: Failed , & outcome) ;
198220 }
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+ }
199236 Message :: Test ( TestMessage :: Ok ( outcome) ) => {
200237 self . render_test_outcome ( Outcome :: Ok , & outcome) ;
201238 }
@@ -210,13 +247,13 @@ impl<'a> Renderer<'a> {
210247 self . failures . push ( outcome) ;
211248 }
212249 Message :: Test ( TestMessage :: Started ) => { } // Not useful
213- Message :: Test ( TestMessage :: Bench ) => todo ! ( "benchmarks are not supported yet" ) ,
214250 }
215251 }
216252}
217253
218254enum Outcome < ' a > {
219255 Ok ,
256+ BenchOk ,
220257 Failed ,
221258 Ignored { reason : Option < & ' a str > } ,
222259}
@@ -225,6 +262,7 @@ impl Outcome<'_> {
225262 fn short ( & self , builder : & Builder < ' _ > ) -> String {
226263 match self {
227264 Outcome :: Ok => builder. color_for_stdout ( Color :: Green , "." ) ,
265+ Outcome :: BenchOk => builder. color_for_stdout ( Color :: Cyan , "b" ) ,
228266 Outcome :: Failed => builder. color_for_stdout ( Color :: Red , "F" ) ,
229267 Outcome :: Ignored { .. } => builder. color_for_stdout ( Color :: Yellow , "i" ) ,
230268 }
@@ -233,6 +271,7 @@ impl Outcome<'_> {
233271 fn long ( & self , builder : & Builder < ' _ > ) -> String {
234272 match self {
235273 Outcome :: Ok => builder. color_for_stdout ( Color :: Green , "ok" ) ,
274+ Outcome :: BenchOk => builder. color_for_stdout ( Color :: Cyan , "benchmarked" ) ,
236275 Outcome :: Failed => builder. color_for_stdout ( Color :: Red , "FAILED" ) ,
237276 Outcome :: Ignored { reason : None } => builder. color_for_stdout ( Color :: Yellow , "ignored" ) ,
238277 Outcome :: Ignored { reason : Some ( reason) } => {
@@ -247,6 +286,7 @@ impl Outcome<'_> {
247286enum Message {
248287 Suite ( SuiteMessage ) ,
249288 Test ( TestMessage ) ,
289+ Bench ( BenchOutcome ) ,
250290}
251291
252292#[ derive( serde_derive:: Deserialize ) ]
@@ -273,11 +313,16 @@ enum TestMessage {
273313 Ok ( TestOutcome ) ,
274314 Failed ( TestOutcome ) ,
275315 Ignored ( TestOutcome ) ,
276- // Ignored messages:
277- Bench ,
278316 Started ,
279317}
280318
319+ #[ derive( serde_derive:: Deserialize ) ]
320+ struct BenchOutcome {
321+ name : String ,
322+ median : u64 ,
323+ deviation : u64 ,
324+ }
325+
281326#[ derive( serde_derive:: Deserialize ) ]
282327struct TestOutcome {
283328 name : String ,
0 commit comments