summaryrefslogtreecommitdiff
path: root/cli/tools/test.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tools/test.rs')
-rw-r--r--cli/tools/test.rs98
1 files changed, 66 insertions, 32 deletions
diff --git a/cli/tools/test.rs b/cli/tools/test.rs
index 9a84774bf..d3ab9dbb0 100644
--- a/cli/tools/test.rs
+++ b/cli/tools/test.rs
@@ -138,7 +138,7 @@ pub struct TestPlan {
pub enum TestEvent {
Plan(TestPlan),
Wait(TestDescription),
- Output(TestOutput),
+ Output(Vec<u8>),
Result(TestDescription, TestResult, u64),
StepWait(TestStepDescription),
StepResult(TestStepDescription, TestStepResult, u64),
@@ -198,7 +198,7 @@ impl TestSummary {
pub trait TestReporter {
fn report_plan(&mut self, plan: &TestPlan);
fn report_wait(&mut self, description: &TestDescription);
- fn report_output(&mut self, output: &TestOutput);
+ fn report_output(&mut self, output: &[u8]);
fn report_result(
&mut self,
description: &TestDescription,
@@ -340,7 +340,7 @@ impl TestReporter for PrettyTestReporter {
self.in_test_count += 1;
}
- fn report_output(&mut self, output: &TestOutput) {
+ fn report_output(&mut self, output: &[u8]) {
if !self.echo_output {
return;
}
@@ -350,16 +350,10 @@ impl TestReporter for PrettyTestReporter {
println!();
println!("{}", colors::gray("------- output -------"));
}
- match output {
- TestOutput::String(line) => {
- // output everything to stdout in order to prevent
- // stdout and stderr racing
- print!("{}", line)
- }
- TestOutput::Bytes(bytes) => {
- std::io::stdout().write_all(bytes).unwrap();
- }
- }
+
+ // output everything to stdout in order to prevent
+ // stdout and stderr racing
+ std::io::stdout().write_all(output).unwrap();
}
fn report_result(
@@ -587,19 +581,18 @@ async fn test_specifier(
permissions: Permissions,
specifier: ModuleSpecifier,
mode: TestMode,
- channel: UnboundedSender<TestEvent>,
+ sender: TestEventSender,
options: TestSpecifierOptions,
) -> Result<(), AnyError> {
- let (stdout, stderr) = create_stdout_stderr_pipes(channel.clone());
let mut worker = create_main_worker(
&ps,
specifier.clone(),
permissions,
- vec![ops::testing::init(channel.clone())],
+ vec![ops::testing::init(sender.clone())],
Stdio {
stdin: StdioPipe::Inherit,
- stdout: StdioPipe::File(stdout),
- stderr: StdioPipe::File(stderr),
+ stdout: StdioPipe::File(sender.stdout()),
+ stderr: StdioPipe::File(sender.stderr()),
},
);
@@ -951,6 +944,7 @@ async fn test_specifiers(
};
let (sender, mut receiver) = unbounded_channel::<TestEvent>();
+ let sender = TestEventSender::new(sender);
let concurrent_jobs = options.concurrent_jobs;
let fail_fast = options.fail_fast;
@@ -1455,20 +1449,61 @@ pub async fn run_tests_with_watch(
Ok(())
}
-/// Creates the stdout and stderr pipes and returns the writers for stdout and stderr.
-pub fn create_stdout_stderr_pipes(
+pub struct TestEventSender {
sender: UnboundedSender<TestEvent>,
-) -> (std::fs::File, std::fs::File) {
- let (stdout_reader, stdout_writer) = os_pipe::pipe().unwrap();
- let (stderr_reader, stderr_writer) = os_pipe::pipe().unwrap();
+ stdout_writer: os_pipe::PipeWriter,
+ stderr_writer: os_pipe::PipeWriter,
+}
- start_output_redirect_thread(stdout_reader, sender.clone());
- start_output_redirect_thread(stderr_reader, sender);
+impl Clone for TestEventSender {
+ fn clone(&self) -> Self {
+ Self {
+ sender: self.sender.clone(),
+ stdout_writer: self.stdout_writer.try_clone().unwrap(),
+ stderr_writer: self.stderr_writer.try_clone().unwrap(),
+ }
+ }
+}
- (
- pipe_writer_to_file(stdout_writer),
- pipe_writer_to_file(stderr_writer),
- )
+impl TestEventSender {
+ pub fn new(sender: UnboundedSender<TestEvent>) -> Self {
+ let (stdout_reader, stdout_writer) = os_pipe::pipe().unwrap();
+ let (stderr_reader, stderr_writer) = os_pipe::pipe().unwrap();
+
+ start_output_redirect_thread(stdout_reader, sender.clone());
+ start_output_redirect_thread(stderr_reader, sender.clone());
+
+ Self {
+ sender,
+ stdout_writer,
+ stderr_writer,
+ }
+ }
+
+ pub fn stdout(&self) -> std::fs::File {
+ pipe_writer_to_file(self.stdout_writer.try_clone().unwrap())
+ }
+
+ pub fn stderr(&self) -> std::fs::File {
+ pipe_writer_to_file(self.stderr_writer.try_clone().unwrap())
+ }
+
+ pub fn send(&mut self, message: TestEvent) -> Result<(), AnyError> {
+ // for any event that finishes collecting output, we need to
+ // ensure that the collected stdout and stderr pipes are flushed
+ if matches!(
+ message,
+ TestEvent::Result(_, _, _)
+ | TestEvent::StepWait(_)
+ | TestEvent::StepResult(_, _, _)
+ ) {
+ self.stdout_writer.flush().unwrap();
+ self.stderr_writer.flush().unwrap();
+ }
+
+ self.sender.send(message)?;
+ Ok(())
+ }
}
#[cfg(windows)]
@@ -1497,10 +1532,9 @@ fn start_output_redirect_thread(
Ok(0) | Err(_) => break,
Ok(size) => size,
};
+
if sender
- .send(TestEvent::Output(TestOutput::Bytes(
- buffer[0..size].to_vec(),
- )))
+ .send(TestEvent::Output(buffer[0..size].to_vec()))
.is_err()
{
break;