@@ -16,11 +16,14 @@ use super::{
1616 unit_output:: TestOutputDisplay ,
1717} ;
1818use crate :: {
19+ cargo_config:: CargoConfigs ,
1920 config:: { CompiledDefaultFilter , LeakTimeoutResult , ScriptId } ,
2021 errors:: WriteEventError ,
2122 helpers:: { DisplayScriptInstance , DisplayTestInstance , plural} ,
2223 list:: { TestInstance , TestInstanceId } ,
23- reporter:: { events:: * , helpers:: Styles , imp:: ReporterStderr } ,
24+ reporter:: {
25+ displayer:: progress:: TerminalProgress , events:: * , helpers:: Styles , imp:: ReporterStderr ,
26+ } ,
2427} ;
2528use debug_ignore:: DebugIgnore ;
2629use indent_write:: io:: IndentWriter ;
@@ -46,7 +49,11 @@ pub(crate) struct DisplayReporterBuilder {
4649}
4750
4851impl DisplayReporterBuilder {
49- pub ( crate ) fn build ( self , output : ReporterStderr < ' _ > ) -> DisplayReporter < ' _ > {
52+ pub ( crate ) fn build < ' a > (
53+ self ,
54+ configs : & CargoConfigs ,
55+ output : ReporterStderr < ' a > ,
56+ ) -> DisplayReporter < ' a > {
5057 let mut styles: Box < Styles > = Box :: default ( ) ;
5158 if self . should_colorize {
5259 styles. colorize ( ) ;
@@ -72,31 +79,37 @@ impl DisplayReporterBuilder {
7279 }
7380
7481 let stderr = match output {
75- ReporterStderr :: Terminal if self . no_capture => {
76- // Do not use a progress bar if --no-capture is passed in. This is required since we
77- // pass down stderr to the child process.
78- //
79- // In the future, we could potentially switch to using a pty, in which case we could
80- // still potentially use the progress bar as a status bar. However, that brings
81- // about its own complications: what if a test's output doesn't include a newline?
82- // We might have to use a curses-like UI which would be a lot of work for not much
83- // gain.
84- ReporterStderrImpl :: TerminalWithoutBar
85- }
86- ReporterStderr :: Terminal if is_ci:: uncached ( ) => {
87- // Some CI environments appear to pretend to be a terminal. Disable the progress bar
88- // in these environments.
89- ReporterStderrImpl :: TerminalWithoutBar
90- }
91- ReporterStderr :: Terminal if self . hide_progress_bar => {
92- ReporterStderrImpl :: TerminalWithoutBar
93- }
94-
9582 ReporterStderr :: Terminal => {
96- let state = ProgressBarState :: new ( self . test_count , theme_characters. progress_chars ) ;
97- // Note: even if we create a progress bar here, if stderr is
98- // piped, indicatif will not show it.
99- ReporterStderrImpl :: TerminalWithBar { state }
83+ let progress_bar = if self . no_capture {
84+ // Do not use a progress bar if --no-capture is passed in.
85+ // This is required since we pass down stderr to the child
86+ // process.
87+ //
88+ // In the future, we could potentially switch to using a
89+ // pty, in which case we could still potentially use the
90+ // progress bar as a status bar. However, that brings about
91+ // its own complications: what if a test's output doesn't
92+ // include a newline? We might have to use a curses-like UI
93+ // which would be a lot of work for not much gain.
94+ None
95+ } else if is_ci:: uncached ( ) {
96+ // Some CI environments appear to pretend to be a terminal.
97+ // Disable the progress bar in these environments.
98+ None
99+ } else if self . hide_progress_bar {
100+ None
101+ } else {
102+ let state =
103+ ProgressBarState :: new ( self . test_count , theme_characters. progress_chars ) ;
104+ // Note: even if we create a progress bar here, if stderr is
105+ // piped, indicatif will not show it.
106+ Some ( state)
107+ } ;
108+ let term_progress = TerminalProgress :: new ( configs, & io:: stderr ( ) ) ;
109+ ReporterStderrImpl :: Terminal {
110+ progress_bar,
111+ term_progress,
112+ }
100113 }
101114 ReporterStderr :: Buffer ( buf) => ReporterStderrImpl :: Buffer ( buf) ,
102115 } ;
@@ -142,23 +155,37 @@ pub(crate) struct DisplayReporter<'a> {
142155impl < ' a > DisplayReporter < ' a > {
143156 pub ( crate ) fn write_event ( & mut self , event : & TestEvent < ' a > ) -> Result < ( ) , WriteEventError > {
144157 match & mut self . stderr {
145- ReporterStderrImpl :: TerminalWithBar { state } => {
146- // Write to a string that will be printed as a log line.
147- let mut buf: Vec < u8 > = Vec :: new ( ) ;
148- self . inner
149- . write_event_impl ( event, & mut buf)
150- . map_err ( WriteEventError :: Io ) ?;
151-
152- state. update_progress_bar ( event, & self . inner . styles ) ;
153- state. write_buf ( & buf) . map_err ( WriteEventError :: Io )
154- }
155- ReporterStderrImpl :: TerminalWithoutBar => {
156- // Write to a buffered stderr.
157- let mut writer = BufWriter :: new ( std:: io:: stderr ( ) ) ;
158- self . inner
159- . write_event_impl ( event, & mut writer)
160- . map_err ( WriteEventError :: Io ) ?;
161- writer. flush ( ) . map_err ( WriteEventError :: Io )
158+ ReporterStderrImpl :: Terminal {
159+ progress_bar,
160+ term_progress,
161+ } => {
162+ if let Some ( state) = progress_bar {
163+ // Write to a string that will be printed as a log line.
164+ let mut buf: Vec < u8 > = Vec :: new ( ) ;
165+ self . inner
166+ . write_event_impl ( event, & mut buf)
167+ . map_err ( WriteEventError :: Io ) ?;
168+
169+ state. update_progress_bar ( event, & self . inner . styles ) ;
170+ if let Some ( term_progress) = term_progress {
171+ term_progress
172+ . update_progress ( event, & mut buf)
173+ . map_err ( WriteEventError :: Io ) ?;
174+ }
175+ state. write_buf ( & buf) . map_err ( WriteEventError :: Io )
176+ } else {
177+ // Write to a buffered stderr.
178+ let mut writer = BufWriter :: new ( std:: io:: stderr ( ) ) ;
179+ self . inner
180+ . write_event_impl ( event, & mut writer)
181+ . map_err ( WriteEventError :: Io ) ?;
182+ if let Some ( state) = term_progress {
183+ state
184+ . update_progress ( event, & mut writer)
185+ . map_err ( WriteEventError :: Io ) ?;
186+ }
187+ writer. flush ( ) . map_err ( WriteEventError :: Io )
188+ }
162189 }
163190 ReporterStderrImpl :: Buffer ( buf) => self
164191 . inner
@@ -173,21 +200,26 @@ impl<'a> DisplayReporter<'a> {
173200}
174201
175202enum ReporterStderrImpl < ' a > {
176- TerminalWithBar {
177- // Reporter-specific progress bar state.
178- state : ProgressBarState ,
203+ Terminal {
204+ // Reporter-specific progress bar state. None if the progress bar is not
205+ // enabled.
206+ progress_bar : Option < ProgressBarState > ,
207+ // OSC 9 code progress reporting.
208+ term_progress : Option < TerminalProgress > ,
179209 } ,
180- TerminalWithoutBar ,
181210 Buffer ( & ' a mut Vec < u8 > ) ,
182211}
183212
184213impl ReporterStderrImpl < ' _ > {
185214 fn finish_and_clear_bar ( & self ) {
186215 match self {
187- ReporterStderrImpl :: TerminalWithBar { state } => {
216+ ReporterStderrImpl :: Terminal {
217+ progress_bar : Some ( state) ,
218+ ..
219+ } => {
188220 state. finish_and_clear ( ) ;
189221 }
190- ReporterStderrImpl :: TerminalWithoutBar | ReporterStderrImpl :: Buffer ( _) => { }
222+ ReporterStderrImpl :: Terminal { .. } | ReporterStderrImpl :: Buffer ( _) => { }
191223 }
192224 }
193225
@@ -512,6 +544,7 @@ impl<'a> DisplayReporterImpl<'a> {
512544 }
513545 TestEventKind :: RunBeginCancel {
514546 setup_scripts_running,
547+ current_stats : _,
515548 running,
516549 reason,
517550 } => {
@@ -544,6 +577,7 @@ impl<'a> DisplayReporterImpl<'a> {
544577 }
545578 TestEventKind :: RunBeginKill {
546579 setup_scripts_running,
580+ current_stats : _,
547581 running,
548582 reason,
549583 } => {
@@ -1794,6 +1828,7 @@ mod tests {
17941828 test_output:: { ChildExecutionOutput , ChildOutput , ChildSplitOutput } ,
17951829 } ;
17961830 use bytes:: Bytes ;
1831+ use camino:: Utf8PathBuf ;
17971832 use chrono:: Local ;
17981833 use nextest_metadata:: RustBinaryId ;
17991834 use smol_str:: SmolStr ;
@@ -1806,6 +1841,18 @@ mod tests {
18061841 where
18071842 F : FnOnce ( DisplayReporter < ' a > ) ,
18081843 {
1844+ // Start and end the search at the cwd -- we expect this to not match
1845+ // any results since it'll be the nextest-runner directory.
1846+ let current_dir = Utf8PathBuf :: try_from ( std:: env:: current_dir ( ) . expect ( "obtained cwd" ) )
1847+ . expect ( "cwd is valid UTF_8" ) ;
1848+ let configs = CargoConfigs :: new_with_isolation (
1849+ Vec :: < String > :: new ( ) ,
1850+ & current_dir,
1851+ & current_dir,
1852+ Vec :: new ( ) ,
1853+ )
1854+ . unwrap ( ) ;
1855+
18091856 let builder = DisplayReporterBuilder {
18101857 default_filter : CompiledDefaultFilter :: for_default_config ( ) ,
18111858 status_levels : StatusLevels {
@@ -1821,7 +1868,7 @@ mod tests {
18211868 no_output_indent : false ,
18221869 } ;
18231870 let output = ReporterStderr :: Buffer ( out) ;
1824- let reporter = builder. build ( output) ;
1871+ let reporter = builder. build ( & configs , output) ;
18251872 f ( reporter) ;
18261873 }
18271874
0 commit comments