summaryrefslogtreecommitdiffstats
path: root/src/bootstrap/render_tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap/render_tests.rs')
-rw-r--r--src/bootstrap/render_tests.rs47
1 files changed, 35 insertions, 12 deletions
diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/render_tests.rs
index fa0a48066..98a468c88 100644
--- a/src/bootstrap/render_tests.rs
+++ b/src/bootstrap/render_tests.rs
@@ -7,7 +7,7 @@
//! to reimplement all the rendering logic in this module because of that.
use crate::builder::Builder;
-use std::io::{BufRead, BufReader, Write};
+use std::io::{BufRead, BufReader, Read, Write};
use std::process::{ChildStdout, Command, Stdio};
use std::time::Duration;
use termcolor::{Color, ColorSpec, WriteColor};
@@ -20,17 +20,17 @@ pub(crate) fn add_flags_and_try_run_tests(builder: &Builder<'_>, cmd: &mut Comma
}
cmd.args(&["-Z", "unstable-options", "--format", "json"]);
- try_run_tests(builder, cmd)
+ try_run_tests(builder, cmd, false)
}
-pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
+pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bool) -> bool {
if builder.config.dry_run() {
return true;
}
- if !run_tests(builder, cmd) {
+ if !run_tests(builder, cmd, stream) {
if builder.fail_fast {
- crate::detail_exit(1);
+ crate::detail_exit_macro!(1);
} else {
let mut failures = builder.delayed_failures.borrow_mut();
failures.push(format!("{cmd:?}"));
@@ -41,7 +41,7 @@ pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
}
}
-fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
+fn run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bool) -> bool {
cmd.stdout(Stdio::piped());
builder.verbose(&format!("running: {cmd:?}"));
@@ -50,7 +50,12 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
// This runs until the stdout of the child is closed, which means the child exited. We don't
// run this on another thread since the builder is not Sync.
- Renderer::new(process.stdout.take().unwrap(), builder).render_all();
+ let renderer = Renderer::new(process.stdout.take().unwrap(), builder);
+ if stream {
+ renderer.stream_all();
+ } else {
+ renderer.render_all();
+ }
let result = process.wait_with_output().unwrap();
if !result.status.success() && builder.is_verbose() {
@@ -88,10 +93,10 @@ impl<'a> Renderer<'a> {
}
fn render_all(mut self) {
- let mut line = String::new();
+ let mut line = Vec::new();
loop {
line.clear();
- match self.stdout.read_line(&mut line) {
+ match self.stdout.read_until(b'\n', &mut line) {
Ok(_) => {}
Err(err) if err.kind() == std::io::ErrorKind::UnexpectedEof => break,
Err(err) => panic!("failed to read output of test runner: {err}"),
@@ -100,13 +105,31 @@ impl<'a> Renderer<'a> {
break;
}
- match serde_json::from_str(&line) {
+ match serde_json::from_slice(&line) {
Ok(parsed) => self.render_message(parsed),
Err(_err) => {
// Handle non-JSON output, for example when --nocapture is passed.
- print!("{line}");
- let _ = std::io::stdout().flush();
+ let mut stdout = std::io::stdout();
+ stdout.write_all(&line).unwrap();
+ let _ = stdout.flush();
+ }
+ }
+ }
+ }
+
+ /// Renders the stdout characters one by one
+ fn stream_all(mut self) {
+ let mut buffer = [0; 1];
+ loop {
+ match self.stdout.read(&mut buffer) {
+ Ok(0) => break,
+ Ok(_) => {
+ let mut stdout = std::io::stdout();
+ stdout.write_all(&buffer).unwrap();
+ let _ = stdout.flush();
}
+ Err(err) if err.kind() == std::io::ErrorKind::UnexpectedEof => break,
+ Err(err) => panic!("failed to read output of test runner: {err}"),
}
}
}