Keep reading buffered test process output after it has exited (#2923)
This commit is contained in:
parent
595d75d5fb
commit
3db5ecb80e
|
|
@ -8,11 +8,11 @@ use tracing::instrument;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::os::unix::process::ExitStatusExt;
|
use std::os::unix::process::ExitStatusExt;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::Infallible as NoDir,
|
convert::Infallible as NoDir,
|
||||||
fmt::{self, Write as _},
|
fmt::{self, Write as _},
|
||||||
io::BufRead,
|
io::{BufRead, BufReader, Lines, Read, Write as _},
|
||||||
io::{BufReader, Lines, Read},
|
|
||||||
path::Path,
|
path::Path,
|
||||||
process::{Child, ChildStderr, ChildStdout, Command, ExitStatus, Output, Stdio},
|
process::{Child, ChildStderr, ChildStdout, Command, ExitStatus, Output, Stdio},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
|
|
@ -286,10 +286,17 @@ impl<T> TestChild<T> {
|
||||||
L: Iterator<Item = std::io::Result<String>>,
|
L: Iterator<Item = std::io::Result<String>>,
|
||||||
{
|
{
|
||||||
let re = regex::Regex::new(regex).expect("regex must be valid");
|
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() {
|
let line = if let Some(line) = lines.next() {
|
||||||
line?
|
line?
|
||||||
} else {
|
} else {
|
||||||
|
// When the child process closes its output,
|
||||||
|
// and we've read all of the buffered output,
|
||||||
|
// stop checking for any more output.
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -297,14 +304,15 @@ impl<T> TestChild<T> {
|
||||||
// can be preserved. May cause weird reordering for stdout / stderr.
|
// can be preserved. May cause weird reordering for stdout / stderr.
|
||||||
// Uses stdout even if the original lines were from stderr.
|
// Uses stdout even if the original lines were from stderr.
|
||||||
if self.bypass_test_capture {
|
if self.bypass_test_capture {
|
||||||
// send lines to the terminal (or process stdout file redirect)
|
// Send lines directly to the terminal (or process stdout file redirect).
|
||||||
use std::io::Write;
|
|
||||||
#[allow(clippy::explicit_write)]
|
#[allow(clippy::explicit_write)]
|
||||||
writeln!(std::io::stdout(), "{}", line).unwrap();
|
writeln!(std::io::stdout(), "{}", line).unwrap();
|
||||||
} else {
|
} 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);
|
println!("{}", line);
|
||||||
}
|
}
|
||||||
|
// Some OSes require a flush to send all output to the terminal.
|
||||||
|
std::io::stdout().lock().flush()?;
|
||||||
|
|
||||||
if re.is_match(&line) {
|
if re.is_match(&line) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue