77//! to reimplement all the rendering logic in this module because of that.
88
99use crate :: builder:: Builder ;
10- use std:: io:: { BufRead , BufReader , Write } ;
10+ use std:: io:: { BufRead , BufReader , Read , Write } ;
1111use std:: process:: { ChildStdout , Command , Stdio } ;
1212use std:: time:: Duration ;
1313use termcolor:: { Color , ColorSpec , WriteColor } ;
@@ -20,15 +20,15 @@ pub(crate) fn add_flags_and_try_run_tests(builder: &Builder<'_>, cmd: &mut Comma
2020 }
2121 cmd. args ( & [ "-Z" , "unstable-options" , "--format" , "json" ] ) ;
2222
23- try_run_tests ( builder, cmd)
23+ try_run_tests ( builder, cmd, false )
2424}
2525
26- pub ( crate ) fn try_run_tests ( builder : & Builder < ' _ > , cmd : & mut Command ) -> bool {
26+ pub ( crate ) fn try_run_tests ( builder : & Builder < ' _ > , cmd : & mut Command , stream : bool ) -> bool {
2727 if builder. config . dry_run ( ) {
2828 return true ;
2929 }
3030
31- if !run_tests ( builder, cmd) {
31+ if !run_tests ( builder, cmd, stream ) {
3232 if builder. fail_fast {
3333 crate :: detail_exit_macro!( 1 ) ;
3434 } else {
@@ -41,7 +41,7 @@ pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
4141 }
4242}
4343
44- fn run_tests ( builder : & Builder < ' _ > , cmd : & mut Command ) -> bool {
44+ fn run_tests ( builder : & Builder < ' _ > , cmd : & mut Command , stream : bool ) -> bool {
4545 cmd. stdout ( Stdio :: piped ( ) ) ;
4646
4747 builder. verbose ( & format ! ( "running: {cmd:?}" ) ) ;
@@ -50,7 +50,12 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
5050
5151 // This runs until the stdout of the child is closed, which means the child exited. We don't
5252 // run this on another thread since the builder is not Sync.
53- Renderer :: new ( process. stdout . take ( ) . unwrap ( ) , builder) . render_all ( ) ;
53+ let renderer = Renderer :: new ( process. stdout . take ( ) . unwrap ( ) , builder) ;
54+ if stream {
55+ renderer. stream_all ( ) ;
56+ } else {
57+ renderer. render_all ( ) ;
58+ }
5459
5560 let result = process. wait_with_output ( ) . unwrap ( ) ;
5661 if !result. status . success ( ) && builder. is_verbose ( ) {
@@ -112,6 +117,23 @@ impl<'a> Renderer<'a> {
112117 }
113118 }
114119
120+ /// Renders the stdout characters one by one
121+ fn stream_all ( mut self ) {
122+ let mut buffer = [ 0 ; 1 ] ;
123+ loop {
124+ match self . stdout . read ( & mut buffer) {
125+ Ok ( 0 ) => break ,
126+ Ok ( _) => {
127+ let mut stdout = std:: io:: stdout ( ) ;
128+ stdout. write_all ( & buffer) . unwrap ( ) ;
129+ let _ = stdout. flush ( ) ;
130+ }
131+ Err ( err) if err. kind ( ) == std:: io:: ErrorKind :: UnexpectedEof => break ,
132+ Err ( err) => panic ! ( "failed to read output of test runner: {err}" ) ,
133+ }
134+ }
135+ }
136+
115137 fn render_test_outcome ( & mut self , outcome : Outcome < ' _ > , test : & TestOutcome ) {
116138 self . executed_tests += 1 ;
117139
0 commit comments