From 3db5ecb80e280cb677367975c84e414de98d5ba6 Mon Sep 17 00:00:00 2001 From: teor Date: Thu, 21 Oct 2021 11:40:39 +1000 Subject: [PATCH] Keep reading buffered test process output after it has exited (#2923) --- zebra-test/src/command.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/zebra-test/src/command.rs b/zebra-test/src/command.rs index 3b446e46..ba042f65 100644 --- a/zebra-test/src/command.rs +++ b/zebra-test/src/command.rs @@ -8,11 +8,11 @@ use tracing::instrument; #[cfg(unix)] use std::os::unix::process::ExitStatusExt; + use std::{ convert::Infallible as NoDir, fmt::{self, Write as _}, - io::BufRead, - io::{BufReader, Lines, Read}, + io::{BufRead, BufReader, Lines, Read, Write as _}, path::Path, process::{Child, ChildStderr, ChildStdout, Command, ExitStatus, Output, Stdio}, time::{Duration, Instant}, @@ -286,10 +286,17 @@ impl TestChild { L: Iterator>, { let re = regex::Regex::new(regex).expect("regex must be valid"); - while !self.past_deadline() && self.is_running() { + + // We don't check `is_running` here, + // because we want to read to the end of the buffered output, + // even if the child process has exited. + while !self.past_deadline() { let line = if let Some(line) = lines.next() { line? } else { + // When the child process closes its output, + // and we've read all of the buffered output, + // stop checking for any more output. break; }; @@ -297,14 +304,15 @@ impl TestChild { // can be preserved. May cause weird reordering for stdout / stderr. // Uses stdout even if the original lines were from stderr. if self.bypass_test_capture { - // send lines to the terminal (or process stdout file redirect) - use std::io::Write; + // Send lines directly to the terminal (or process stdout file redirect). #[allow(clippy::explicit_write)] writeln!(std::io::stdout(), "{}", line).unwrap(); } else { - // if the test fails, the test runner captures and displays it + // If the test fails, the test runner captures and displays this output. println!("{}", line); } + // Some OSes require a flush to send all output to the terminal. + std::io::stdout().lock().flush()?; if re.is_match(&line) { return Ok(());