@@ -44,6 +44,7 @@ static TEST: AtomicUsize = AtomicUsize::new(0);
4444struct Config {
4545 verbose : bool ,
4646 sequential : bool ,
47+ batch : bool ,
4748 bind : SocketAddr ,
4849}
4950
@@ -52,6 +53,7 @@ impl Config {
5253 Config {
5354 verbose : false ,
5455 sequential : false ,
56+ batch : false ,
5557 bind : if cfg ! ( target_os = "android" ) || cfg ! ( windows) {
5658 ( [ 0 , 0 , 0 , 0 ] , 12345 ) . into ( )
5759 } else {
@@ -73,6 +75,7 @@ impl Config {
7375 }
7476 "--bind" => next_is_bind = true ,
7577 "--sequential" => config. sequential = true ,
78+ "--batch" => config. batch = true ,
7679 "--verbose" | "-v" => config. verbose = true ,
7780 "--help" | "-h" => {
7881 show_help ( ) ;
@@ -98,6 +101,7 @@ fn show_help() {
98101OPTIONS:
99102 --bind <IP>:<PORT> Specify IP address and port to listen for requests, e.g. "0.0.0.0:12345"
100103 --sequential Run only one test at a time
104+ --batch Send stdout and stderr in batch instead of streaming
101105 -v, --verbose Show status messages
102106 -h, --help Show this help screen
103107"# ,
@@ -268,22 +272,30 @@ fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>, conf
268272 // Some tests assume RUST_TEST_TMPDIR exists
269273 cmd. env ( "RUST_TEST_TMPDIR" , tmp. to_owned ( ) ) ;
270274
271- // Spawn the child and ferry over stdout/stderr to the socket in a framed
272- // fashion (poor man's style)
273- let mut child =
274- t ! ( cmd. stdin( Stdio :: null( ) ) . stdout( Stdio :: piped( ) ) . stderr( Stdio :: piped( ) ) . spawn( ) ) ;
275- drop ( lock) ;
276- let mut stdout = child. stdout . take ( ) . unwrap ( ) ;
277- let mut stderr = child. stderr . take ( ) . unwrap ( ) ;
278275 let socket = Arc :: new ( Mutex :: new ( reader. into_inner ( ) ) ) ;
279- let socket2 = socket. clone ( ) ;
280- let thread = thread:: spawn ( move || my_copy ( & mut stdout, 0 , & * socket2) ) ;
281- my_copy ( & mut stderr, 1 , & * socket) ;
282- thread. join ( ) . unwrap ( ) ;
283276
284- // Finally send over the exit status.
285- let status = t ! ( child. wait( ) ) ;
277+ let status = if config. batch {
278+ let child =
279+ t ! ( cmd. stdin( Stdio :: null( ) ) . stdout( Stdio :: piped( ) ) . stderr( Stdio :: piped( ) ) . output( ) ) ;
280+ batch_copy ( & child. stdout , 0 , & * socket) ;
281+ batch_copy ( & child. stderr , 1 , & * socket) ;
282+ child. status
283+ } else {
284+ // Spawn the child and ferry over stdout/stderr to the socket in a framed
285+ // fashion (poor man's style)
286+ let mut child =
287+ t ! ( cmd. stdin( Stdio :: null( ) ) . stdout( Stdio :: piped( ) ) . stderr( Stdio :: piped( ) ) . spawn( ) ) ;
288+ drop ( lock) ;
289+ let mut stdout = child. stdout . take ( ) . unwrap ( ) ;
290+ let mut stderr = child. stderr . take ( ) . unwrap ( ) ;
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 ( ) ;
295+ t ! ( child. wait( ) )
296+ } ;
286297
298+ // Finally send over the exit status.
287299 let ( which, code) = get_status_code ( & status) ;
288300
289301 t ! ( socket. lock( ) . unwrap( ) . write_all( & [
@@ -356,6 +368,17 @@ fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
356368 }
357369}
358370
371+ fn batch_copy ( buf : & [ u8 ] , which : u8 , dst : & Mutex < dyn Write > ) {
372+ let n = buf. len ( ) ;
373+ let mut dst = dst. lock ( ) . unwrap ( ) ;
374+ t ! ( dst. write_all( & [ which, ( n >> 24 ) as u8 , ( n >> 16 ) as u8 , ( n >> 8 ) as u8 , ( n >> 0 ) as u8 , ] ) ) ;
375+ if n > 0 {
376+ t ! ( dst. write_all( buf) ) ;
377+ // Marking buf finished
378+ t ! ( dst. write_all( & [ which, 0 , 0 , 0 , 0 , ] ) ) ;
379+ }
380+ }
381+
359382fn read_u32 ( r : & mut dyn Read ) -> u32 {
360383 let mut len = [ 0 ; 4 ] ;
361384 t ! ( r. read_exact( & mut len) ) ;
0 commit comments