@@ -46,6 +46,7 @@ const NUMBER_OF_RETRIES: usize = 5;
4646struct Config {
4747 verbose : bool ,
4848 sequential : bool ,
49+ batch : bool ,
4950 bind : SocketAddr ,
5051}
5152
@@ -54,6 +55,7 @@ impl Config {
5455 Config {
5556 verbose : false ,
5657 sequential : false ,
58+ batch : false ,
5759 bind : if cfg ! ( target_os = "android" ) || cfg ! ( windows) {
5860 ( [ 0 , 0 , 0 , 0 ] , 12345 ) . into ( )
5961 } else {
@@ -75,6 +77,7 @@ impl Config {
7577 }
7678 "--bind" => next_is_bind = true ,
7779 "--sequential" => config. sequential = true ,
80+ "--batch" => config. batch = true ,
7881 "--verbose" | "-v" => config. verbose = true ,
7982 "--help" | "-h" => {
8083 show_help ( ) ;
@@ -100,6 +103,7 @@ fn show_help() {
100103OPTIONS:
101104 --bind <IP>:<PORT> Specify IP address and port to listen for requests, e.g. "0.0.0.0:12345"
102105 --sequential Run only one test at a time
106+ --batch Send stdout and stderr in batch instead of streaming
103107 -v, --verbose Show status messages
104108 -h, --help Show this help screen
105109"# ,
@@ -280,22 +284,30 @@ fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>, conf
280284 // Some tests assume RUST_TEST_TMPDIR exists
281285 cmd. env ( "RUST_TEST_TMPDIR" , tmp. to_owned ( ) ) ;
282286
283- // Spawn the child and ferry over stdout/stderr to the socket in a framed
284- // fashion (poor man's style)
285- let mut child =
286- t ! ( cmd. stdin( Stdio :: null( ) ) . stdout( Stdio :: piped( ) ) . stderr( Stdio :: piped( ) ) . spawn( ) ) ;
287- drop ( lock) ;
288- let mut stdout = child. stdout . take ( ) . unwrap ( ) ;
289- let mut stderr = child. stderr . take ( ) . unwrap ( ) ;
290287 let socket = Arc :: new ( Mutex :: new ( reader. into_inner ( ) ) ) ;
291- let socket2 = socket. clone ( ) ;
292- let thread = thread:: spawn ( move || my_copy ( & mut stdout, 0 , & * socket2) ) ;
293- my_copy ( & mut stderr, 1 , & * socket) ;
294- thread. join ( ) . unwrap ( ) ;
295288
296- // Finally send over the exit status.
297- let status = t ! ( child. wait( ) ) ;
289+ let status = if config. batch {
290+ let child =
291+ t ! ( cmd. stdin( Stdio :: null( ) ) . stdout( Stdio :: piped( ) ) . stderr( Stdio :: piped( ) ) . output( ) ) ;
292+ batch_copy ( & child. stdout , 0 , & * socket) ;
293+ batch_copy ( & child. stderr , 1 , & * socket) ;
294+ child. status
295+ } else {
296+ // Spawn the child and ferry over stdout/stderr to the socket in a framed
297+ // fashion (poor man's style)
298+ let mut child =
299+ t ! ( cmd. stdin( Stdio :: null( ) ) . stdout( Stdio :: piped( ) ) . stderr( Stdio :: piped( ) ) . spawn( ) ) ;
300+ drop ( lock) ;
301+ let mut stdout = child. stdout . take ( ) . unwrap ( ) ;
302+ let mut stderr = child. stderr . take ( ) . unwrap ( ) ;
303+ let socket2 = socket. clone ( ) ;
304+ let thread = thread:: spawn ( move || my_copy ( & mut stdout, 0 , & * socket2) ) ;
305+ my_copy ( & mut stderr, 1 , & * socket) ;
306+ thread. join ( ) . unwrap ( ) ;
307+ t ! ( child. wait( ) )
308+ } ;
298309
310+ // Finally send over the exit status.
299311 let ( which, code) = get_status_code ( & status) ;
300312
301313 t ! ( socket. lock( ) . unwrap( ) . write_all( & [
@@ -368,6 +380,17 @@ fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
368380 }
369381}
370382
383+ fn batch_copy ( buf : & [ u8 ] , which : u8 , dst : & Mutex < dyn Write > ) {
384+ let n = buf. len ( ) ;
385+ let mut dst = dst. lock ( ) . unwrap ( ) ;
386+ t ! ( dst. write_all( & [ which, ( n >> 24 ) as u8 , ( n >> 16 ) as u8 , ( n >> 8 ) as u8 , ( n >> 0 ) as u8 , ] ) ) ;
387+ if n > 0 {
388+ t ! ( dst. write_all( buf) ) ;
389+ // Marking buf finished
390+ t ! ( dst. write_all( & [ which, 0 , 0 , 0 , 0 , ] ) ) ;
391+ }
392+ }
393+
371394fn read_u32 ( r : & mut dyn Read ) -> u32 {
372395 let mut len = [ 0 ; 4 ] ;
373396 t ! ( r. read_exact( & mut len) ) ;
0 commit comments