@@ -276,7 +276,7 @@ impl TestReporterBuilder {
276276 }
277277
278278 ReporterStderr :: Terminal => {
279- let progress_bar = ProgressBar :: new ( test_list. test_count ( ) as u64 ) ;
279+ let bar = ProgressBar :: new ( test_list. test_count ( ) as u64 ) ;
280280 // Emulate Cargo's style.
281281 let test_count_width = format ! ( "{}" , test_list. test_count( ) ) . len ( ) ;
282282 // Create the template using the width as input. This is a little confusing -- {{foo}}
@@ -289,7 +289,7 @@ impl TestReporterBuilder {
289289 "{{prefix:>12}} [{{elapsed_precise:>9}}] [{{wide_bar}}] \
290290 {{pos:>{test_count_width}}}/{{len:{test_count_width}}}: {{msg}} "
291291 ) ;
292- progress_bar . set_style (
292+ bar . set_style (
293293 ProgressStyle :: default_bar ( )
294294 . progress_chars ( "=> " )
295295 . template ( & template)
@@ -300,10 +300,13 @@ impl TestReporterBuilder {
300300 //
301301 // This used to be unbuffered, but that option went away from indicatif 0.17.0. The
302302 // refresh rate is now 20hz so that it's double the steady tick rate.
303- progress_bar . set_draw_target ( ProgressDrawTarget :: stderr_with_hz ( 20 ) ) ;
303+ bar . set_draw_target ( ProgressDrawTarget :: stderr_with_hz ( 20 ) ) ;
304304 // Enable a steady tick 10 times a second.
305- progress_bar. enable_steady_tick ( Duration :: from_millis ( 100 ) ) ;
306- ReporterStderrImpl :: TerminalWithBar ( progress_bar)
305+ bar. enable_steady_tick ( Duration :: from_millis ( 100 ) ) ;
306+ ReporterStderrImpl :: TerminalWithBar {
307+ bar,
308+ state : ProgressBarState :: new ( ) ,
309+ }
307310 }
308311 ReporterStderr :: Buffer ( buf) => ReporterStderrImpl :: Buffer ( buf) ,
309312 } ;
@@ -337,22 +340,115 @@ impl TestReporterBuilder {
337340}
338341
339342enum ReporterStderrImpl < ' a > {
340- TerminalWithBar ( ProgressBar ) ,
343+ TerminalWithBar {
344+ bar : ProgressBar ,
345+ // Reporter-specific progress bar state.
346+ state : ProgressBarState ,
347+ } ,
341348 TerminalWithoutBar ,
342349 Buffer ( & ' a mut Vec < u8 > ) ,
343350}
344351
345352impl ReporterStderrImpl < ' _ > {
346353 fn finish_and_clear_bar ( & self ) {
347354 match self {
348- ReporterStderrImpl :: TerminalWithBar ( bar) => {
355+ ReporterStderrImpl :: TerminalWithBar { bar, .. } => {
349356 bar. finish_and_clear ( ) ;
350357 }
351358 ReporterStderrImpl :: TerminalWithoutBar | ReporterStderrImpl :: Buffer ( _) => { }
352359 }
353360 }
354361}
355362
363+ #[ derive( Debug ) ]
364+ struct ProgressBarState {
365+ // Reasons for hiding the progress bar. We show the progress bar if none of
366+ // these are set and hide it if any of them are set.
367+ //
368+ // indicatif cannot handle this kind of "stacked" state management so it
369+ // falls on us to do so.
370+ hidden_no_capture : bool ,
371+ hidden_run_paused : bool ,
372+ }
373+
374+ impl ProgressBarState {
375+ fn new ( ) -> Self {
376+ Self {
377+ hidden_no_capture : false ,
378+ hidden_run_paused : false ,
379+ }
380+ }
381+
382+ fn should_hide ( & self ) -> bool {
383+ self . hidden_no_capture || self . hidden_run_paused
384+ }
385+
386+ fn update_progress_bar (
387+ & mut self ,
388+ event : & TestEvent < ' _ > ,
389+ styles : & Styles ,
390+ progress_bar : & ProgressBar ,
391+ ) {
392+ let before_should_hide = self . should_hide ( ) ;
393+
394+ match & event. kind {
395+ TestEventKind :: SetupScriptStarted { no_capture, .. } => {
396+ // Hide the progress bar if either stderr or stdout are being passed through.
397+ if * no_capture {
398+ self . hidden_no_capture = true ;
399+ }
400+ }
401+ TestEventKind :: SetupScriptFinished { no_capture, .. } => {
402+ // Restore the progress bar if it was hidden.
403+ if * no_capture {
404+ self . hidden_no_capture = false ;
405+ }
406+ }
407+ TestEventKind :: TestStarted {
408+ current_stats,
409+ running,
410+ cancel_state,
411+ ..
412+ }
413+ | TestEventKind :: TestFinished {
414+ current_stats,
415+ running,
416+ cancel_state,
417+ ..
418+ } => {
419+ progress_bar. set_prefix ( progress_bar_prefix ( current_stats, * cancel_state, styles) ) ;
420+ progress_bar. set_message ( progress_bar_msg ( current_stats, * running, styles) ) ;
421+ // If there are skipped tests, the initial run count will be lower than when constructed
422+ // in ProgressBar::new.
423+ progress_bar. set_length ( current_stats. initial_run_count as u64 ) ;
424+ progress_bar. set_position ( current_stats. finished_count as u64 ) ;
425+ }
426+ TestEventKind :: RunPaused { .. } => {
427+ // Pausing the run should hide the progress bar since we'll exit
428+ // to the terminal immediately after.
429+ self . hidden_run_paused = true ;
430+ }
431+ TestEventKind :: RunContinued { .. } => {
432+ // Continuing the run should show the progress bar since we'll
433+ // continue to output to it.
434+ self . hidden_run_paused = false ;
435+ }
436+ TestEventKind :: RunBeginCancel { .. } => {
437+ progress_bar. set_prefix ( progress_bar_cancel_prefix ( styles) ) ;
438+ }
439+ _ => { }
440+ }
441+
442+ let after_should_hide = self . should_hide ( ) ;
443+
444+ match ( before_should_hide, after_should_hide) {
445+ ( false , true ) => progress_bar. set_draw_target ( ProgressDrawTarget :: hidden ( ) ) ,
446+ ( true , false ) => progress_bar. set_draw_target ( ProgressDrawTarget :: stderr ( ) ) ,
447+ _ => { }
448+ }
449+ }
450+ }
451+
356452/// Functionality to report test results to stderr, JUnit, and/or structured,
357453/// machine-readable results to stdout
358454pub struct TestReporter < ' a > {
@@ -387,19 +483,19 @@ impl<'a> TestReporter<'a> {
387483 /// Report this test event to the given writer.
388484 fn write_event ( & mut self , event : TestEvent < ' a > ) -> Result < ( ) , WriteEventError > {
389485 match & mut self . stderr {
390- ReporterStderrImpl :: TerminalWithBar ( progress_bar ) => {
486+ ReporterStderrImpl :: TerminalWithBar { bar , state } => {
391487 // Write to a string that will be printed as a log line.
392488 let mut buf: Vec < u8 > = Vec :: new ( ) ;
393489 self . inner
394490 . write_event_impl ( & event, & mut buf)
395491 . map_err ( WriteEventError :: Io ) ?;
396- // ProgressBar::println doesn't print status lines if the bar is hidden. The suspend
397- // method prints it in both cases.
398- progress_bar. suspend ( || {
492+
493+ state. update_progress_bar ( & event, & self . inner . styles , bar) ;
494+ // ProgressBar::println doesn't print status lines if the bar is
495+ // hidden. The suspend method prints it in all cases.
496+ bar. suspend ( || {
399497 _ = std:: io:: stderr ( ) . write_all ( & buf) ;
400498 } ) ;
401-
402- update_progress_bar ( & event, & self . inner . styles , progress_bar) ;
403499 }
404500 ReporterStderrImpl :: TerminalWithoutBar => {
405501 // Write to a buffered stderr.
@@ -422,46 +518,6 @@ impl<'a> TestReporter<'a> {
422518 }
423519}
424520
425- fn update_progress_bar ( event : & TestEvent < ' _ > , styles : & Styles , progress_bar : & ProgressBar ) {
426- match & event. kind {
427- TestEventKind :: SetupScriptStarted { no_capture, .. } => {
428- // Hide the progress bar if either stderr or stdout are being passed through.
429- if * no_capture {
430- progress_bar. set_draw_target ( ProgressDrawTarget :: hidden ( ) ) ;
431- }
432- }
433- TestEventKind :: SetupScriptFinished { no_capture, .. } => {
434- // Restore the progress bar if it was hidden.
435- if * no_capture {
436- progress_bar. set_draw_target ( ProgressDrawTarget :: stderr ( ) ) ;
437- }
438- }
439- TestEventKind :: TestStarted {
440- current_stats,
441- running,
442- cancel_state,
443- ..
444- }
445- | TestEventKind :: TestFinished {
446- current_stats,
447- running,
448- cancel_state,
449- ..
450- } => {
451- progress_bar. set_prefix ( progress_bar_prefix ( current_stats, * cancel_state, styles) ) ;
452- progress_bar. set_message ( progress_bar_msg ( current_stats, * running, styles) ) ;
453- // If there are skipped tests, the initial run count will be lower than when constructed
454- // in ProgressBar::new.
455- progress_bar. set_length ( current_stats. initial_run_count as u64 ) ;
456- progress_bar. set_position ( current_stats. finished_count as u64 ) ;
457- }
458- TestEventKind :: RunBeginCancel { .. } => {
459- progress_bar. set_prefix ( progress_bar_cancel_prefix ( styles) ) ;
460- }
461- _ => { }
462- }
463- }
464-
465521fn progress_bar_cancel_prefix ( styles : & Styles ) -> String {
466522 format ! ( "{:>12}" , "Cancelling" . style( styles. fail) )
467523}
0 commit comments