7
7
//! to reimplement all the rendering logic in this module because of that.
8
8
9
9
use crate :: builder:: Builder ;
10
- use std:: io:: { BufRead , BufReader , Write } ;
10
+ use std:: io:: { BufRead , BufReader , Read , Write } ;
11
11
use std:: process:: { ChildStdout , Command , Stdio } ;
12
12
use std:: time:: Duration ;
13
13
use termcolor:: { Color , ColorSpec , WriteColor } ;
@@ -20,15 +20,15 @@ pub(crate) fn add_flags_and_try_run_tests(builder: &Builder<'_>, cmd: &mut Comma
20
20
}
21
21
cmd. args ( & [ "-Z" , "unstable-options" , "--format" , "json" ] ) ;
22
22
23
- try_run_tests ( builder, cmd)
23
+ try_run_tests ( builder, cmd, false )
24
24
}
25
25
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 {
27
27
if builder. config . dry_run ( ) {
28
28
return true ;
29
29
}
30
30
31
- if !run_tests ( builder, cmd) {
31
+ if !run_tests ( builder, cmd, stream ) {
32
32
if builder. fail_fast {
33
33
crate :: detail_exit_macro!( 1 ) ;
34
34
} else {
@@ -41,7 +41,7 @@ pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
41
41
}
42
42
}
43
43
44
- fn run_tests ( builder : & Builder < ' _ > , cmd : & mut Command ) -> bool {
44
+ fn run_tests ( builder : & Builder < ' _ > , cmd : & mut Command , stream : bool ) -> bool {
45
45
cmd. stdout ( Stdio :: piped ( ) ) ;
46
46
47
47
builder. verbose ( & format ! ( "running: {cmd:?}" ) ) ;
@@ -50,7 +50,12 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
50
50
51
51
// This runs until the stdout of the child is closed, which means the child exited. We don't
52
52
// 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
+ }
54
59
55
60
let result = process. wait_with_output ( ) . unwrap ( ) ;
56
61
if !result. status . success ( ) && builder. is_verbose ( ) {
@@ -112,6 +117,23 @@ impl<'a> Renderer<'a> {
112
117
}
113
118
}
114
119
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
+
115
137
fn render_test_outcome ( & mut self , outcome : Outcome < ' _ > , test : & TestOutcome ) {
116
138
self . executed_tests += 1 ;
117
139
0 commit comments