Skip to content

Commit 12397e9

Browse files
committed
Make enum usage explicit and fix tests
1 parent c951882 commit 12397e9

File tree

14 files changed

+289
-161
lines changed

14 files changed

+289
-161
lines changed

src/libtest/bench.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
//! Benchmarking module.
22
use super::{
3-
BenchMode, MonitorMsg, Sender, Sink, TestDesc, TestResult
3+
event::CompletedTest,
4+
helpers::sink::Sink,
5+
options::BenchMode,
6+
types::TestDesc,
7+
test_result::TestResult,
8+
Sender,
49
};
510

611
use crate::stats;
@@ -182,7 +187,7 @@ where
182187
}
183188
}
184189

185-
pub fn benchmark<F>(desc: TestDesc, monitor_ch: Sender<MonitorMsg>, nocapture: bool, f: F)
190+
pub fn benchmark<F>(desc: TestDesc, monitor_ch: Sender<CompletedTest>, nocapture: bool, f: F)
186191
where
187192
F: FnMut(&mut Bencher),
188193
{
@@ -195,8 +200,8 @@ where
195200
let data = Arc::new(Mutex::new(Vec::new()));
196201
let oldio = if !nocapture {
197202
Some((
198-
io::set_print(Some(Box::new(Sink(data.clone())))),
199-
io::set_panic(Some(Box::new(Sink(data.clone())))),
203+
io::set_print(Some(Sink::new_boxed(&data))),
204+
io::set_panic(Some(Sink::new_boxed(&data))),
200205
))
201206
} else {
202207
None
@@ -235,7 +240,8 @@ where
235240
};
236241

237242
let stdout = data.lock().unwrap().to_vec();
238-
monitor_ch.send((desc, test_result, None, stdout)).unwrap();
243+
let message = CompletedTest::new(desc, test_result, None, stdout);
244+
monitor_ch.send(message).unwrap();
239245
}
240246

241247
pub fn run_once<F>(f: F)

src/libtest/console.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Module providing interface for running tests in the console.
22
33
use std::fs::File;
4-
use std::io::prelude::*;
4+
use std::io::prelude::Write;
55
use std::io;
66

77
use term;
@@ -192,7 +192,8 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
192192

193193
// A simple console test runner
194194
pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<bool> {
195-
fn callback(
195+
// A callback handling events that occure during test execution.
196+
fn on_test_event(
196197
event: &TestEvent,
197198
st: &mut ConsoleTestState,
198199
out: &mut dyn OutputFormatter,
@@ -205,9 +206,14 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
205206
TestEvent::TeFilteredOut(filtered_out) => Ok(st.filtered_out = filtered_out),
206207
TestEvent::TeWait(ref test) => out.write_test_start(test),
207208
TestEvent::TeTimeout(ref test) => out.write_timeout(test),
208-
TestEvent::TeResult(test, result, exec_time, stdout) => {
209-
st.write_log_result(&test, &result, exec_time.as_ref())?;
210-
out.write_result(&test, &result, exec_time.as_ref(), &*stdout, &st)?;
209+
TestEvent::TeResult(completed_test) => {
210+
let test = completed_test.desc;
211+
let result = &completed_test.result;
212+
let exec_time = &completed_test.exec_time;
213+
let stdout = completed_test.stdout;
214+
215+
st.write_log_result(&test, result, exec_time.as_ref())?;
216+
out.write_result(&test, result, exec_time.as_ref(), &*stdout, st)?;
211217
match result {
212218
TestResult::TrOk => {
213219
st.passed += 1;
@@ -280,7 +286,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
280286
}
281287
}
282288

283-
run_tests(opts, tests, |x| callback(&x, &mut st, &mut *out))?;
289+
run_tests(opts, tests, |x| on_test_event(&x, &mut st, &mut *out))?;
284290

285291
assert!(st.current_test_count() == st.total);
286292

src/libtest/event.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,32 @@ use super::types::TestDesc;
55
use super::test_result::TestResult;
66
use super::time::TestExecTime;
77

8-
#[derive(Clone)]
8+
#[derive(Debug, Clone)]
9+
pub struct CompletedTest {
10+
pub desc: TestDesc,
11+
pub result: TestResult,
12+
pub exec_time: Option<TestExecTime>,
13+
pub stdout: Vec<u8>,
14+
}
15+
16+
impl CompletedTest {
17+
pub fn new(desc: TestDesc, result: TestResult, exec_time: Option<TestExecTime>, stdout: Vec<u8>) -> Self {
18+
Self {
19+
desc,
20+
result,
21+
exec_time,
22+
stdout,
23+
}
24+
}
25+
}
26+
27+
unsafe impl Send for CompletedTest {}
28+
29+
#[derive(Debug, Clone)]
930
pub enum TestEvent {
1031
TeFiltered(Vec<TestDesc>),
1132
TeWait(TestDesc),
12-
TeResult(TestDesc, TestResult, Option<TestExecTime>, Vec<u8>),
33+
TeResult(CompletedTest),
1334
TeTimeout(TestDesc),
1435
TeFilteredOut(usize),
1536
}

src/libtest/formatters/json.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
1-
use super::*;
2-
use super::console::{ConsoleTestState, OutputLocation};
1+
use std::{
2+
io,
3+
io::prelude::Write,
4+
borrow::Cow,
5+
};
6+
7+
use crate::{
8+
types::TestDesc,
9+
time,
10+
test_result::TestResult,
11+
console::{ConsoleTestState, OutputLocation},
12+
};
13+
use super::OutputFormatter;
314

415
pub(crate) struct JsonFormatter<T> {
516
out: OutputLocation<T>,
@@ -81,21 +92,21 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
8192
stdout: &[u8],
8293
state: &ConsoleTestState,
8394
) -> io::Result<()> {
84-
let stdout = if (state.options.display_output || *result != TrOk) && stdout.len() > 0 {
95+
let stdout = if (state.options.display_output || *result != TestResult::TrOk) && stdout.len() > 0 {
8596
Some(String::from_utf8_lossy(stdout))
8697
} else {
8798
None
8899
};
89100
match *result {
90-
TrOk => {
101+
TestResult::TrOk => {
91102
self.write_event("test", desc.name.as_slice(), "ok", exec_time, stdout, None)
92103
}
93104

94-
TrFailed => {
105+
TestResult::TrFailed => {
95106
self.write_event("test", desc.name.as_slice(), "failed", exec_time, stdout, None)
96107
}
97108

98-
TrTimedFail => self.write_event(
109+
TestResult::TrTimedFail => self.write_event(
99110
"test",
100111
desc.name.as_slice(),
101112
"failed",
@@ -104,7 +115,7 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
104115
Some(r#""reason": "time limit exceeded""#),
105116
),
106117

107-
TrFailedMsg(ref m) => self.write_event(
118+
TestResult::TrFailedMsg(ref m) => self.write_event(
108119
"test",
109120
desc.name.as_slice(),
110121
"failed",
@@ -113,11 +124,11 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
113124
Some(&*format!(r#""message": "{}""#, EscapedString(m))),
114125
),
115126

116-
TrIgnored => {
127+
TestResult::TrIgnored => {
117128
self.write_event("test", desc.name.as_slice(), "ignored", exec_time, stdout, None)
118129
}
119130

120-
TrAllowedFail => self.write_event(
131+
TestResult::TrAllowedFail => self.write_event(
121132
"test",
122133
desc.name.as_slice(),
123134
"allowed_failure",
@@ -126,7 +137,7 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
126137
None,
127138
),
128139

129-
TrBench(ref bs) => {
140+
TestResult::TrBench(ref bs) => {
130141
let median = bs.ns_iter_summ.median as usize;
131142
let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;
132143

src/libtest/formatters/mod.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1-
use super::*;
2-
use super::console::ConsoleTestState;
1+
use std::{
2+
io,
3+
io::prelude::Write,
4+
};
5+
6+
use crate::{
7+
types::{TestDesc, TestName},
8+
time,
9+
test_result::TestResult,
10+
console::{ConsoleTestState},
11+
};
312

413
mod pretty;
514
mod json;

src/libtest/formatters/pretty.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
1-
use super::*;
2-
use super::console::{ConsoleTestState, OutputLocation};
1+
use std::{
2+
io,
3+
io::prelude::Write,
4+
};
5+
6+
use crate::{
7+
types::TestDesc,
8+
time,
9+
test_result::TestResult,
10+
console::{ConsoleTestState, OutputLocation},
11+
bench::fmt_bench_samples,
12+
};
13+
use super::OutputFormatter;
314

415
pub(crate) struct PrettyFormatter<T> {
516
out: OutputLocation<T>,
@@ -204,15 +215,15 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {
204215
}
205216

206217
match *result {
207-
TrOk => self.write_ok()?,
208-
TrFailed | TrFailedMsg(_) => self.write_failed()?,
209-
TrIgnored => self.write_ignored()?,
210-
TrAllowedFail => self.write_allowed_fail()?,
211-
TrBench(ref bs) => {
218+
TestResult::TrOk => self.write_ok()?,
219+
TestResult::TrFailed | TestResult::TrFailedMsg(_) => self.write_failed()?,
220+
TestResult::TrIgnored => self.write_ignored()?,
221+
TestResult::TrAllowedFail => self.write_allowed_fail()?,
222+
TestResult::TrBench(ref bs) => {
212223
self.write_bench()?;
213224
self.write_plain(&format!(": {}", fmt_bench_samples(bs)))?;
214225
}
215-
TrTimedFail => self.write_time_failed()?,
226+
TestResult::TrTimedFail => self.write_time_failed()?,
216227
}
217228

218229
self.write_time(desc, exec_time)?;

src/libtest/formatters/terse.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
1-
use super::*;
2-
use super::console::{ConsoleTestState, OutputLocation};
1+
use std::{
2+
io,
3+
io::prelude::Write,
4+
};
5+
6+
use crate::{
7+
types::TestDesc,
8+
time,
9+
test_result::TestResult,
10+
types::NamePadding,
11+
console::{ConsoleTestState, OutputLocation},
12+
bench::fmt_bench_samples,
13+
};
14+
use super::OutputFormatter;
15+
16+
// insert a '\n' after 100 tests in quiet mode
17+
const QUIET_MODE_MAX_COLUMN: usize = 100;
318

419
pub(crate) struct TerseFormatter<T> {
520
out: OutputLocation<T>,
@@ -164,7 +179,7 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
164179
// in order to indicate benchmarks.
165180
// When running benchmarks, terse-mode should still print their name as if
166181
// it is the Pretty formatter.
167-
if !self.is_multithreaded && desc.name.padding() == PadOnRight {
182+
if !self.is_multithreaded && desc.name.padding() == NamePadding::PadOnRight {
168183
self.write_test_name(desc)?;
169184
}
170185

@@ -180,11 +195,11 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
180195
_: &ConsoleTestState,
181196
) -> io::Result<()> {
182197
match *result {
183-
TrOk => self.write_ok(),
184-
TrFailed | TrFailedMsg(_) | TrTimedFail => self.write_failed(),
185-
TrIgnored => self.write_ignored(),
186-
TrAllowedFail => self.write_allowed_fail(),
187-
TrBench(ref bs) => {
198+
TestResult::TrOk => self.write_ok(),
199+
TestResult::TrFailed | TestResult::TrFailedMsg(_) | TestResult::TrTimedFail => self.write_failed(),
200+
TestResult::TrIgnored => self.write_ignored(),
201+
TestResult::TrAllowedFail => self.write_allowed_fail(),
202+
TestResult::TrBench(ref bs) => {
188203
if self.is_multithreaded {
189204
self.write_test_name(desc)?;
190205
}

src/libtest/helpers/exit_code.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//! Helper module to detect subprocess exit code.
2+
3+
use std::process::ExitStatus;
4+
5+
#[cfg(not(unix))]
6+
pub fn get_exit_code(status: ExitStatus) -> Result<i32, String> {
7+
status.code().ok_or("received no exit code from child process".into())
8+
}
9+
10+
#[cfg(unix)]
11+
pub fn get_exit_code(status: ExitStatus) -> Result<i32, String> {
12+
use std::os::unix::process::ExitStatusExt;
13+
match status.code() {
14+
Some(code) => Ok(code),
15+
None => match status.signal() {
16+
Some(signal) => Err(format!("child process exited with signal {}", signal)),
17+
None => Err("child process exited with unknown signal".into()),
18+
}
19+
}
20+
}

src/libtest/helpers/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@
44
pub mod concurrency;
55
pub mod isatty;
66
pub mod metrics;
7+
pub mod sink;
8+
pub mod exit_code;

src/libtest/helpers/sink.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//! Module providing a helper structure to capture output in subprocesses.
2+
3+
use std::{
4+
io,
5+
io::prelude::Write,
6+
sync::{Arc, Mutex},
7+
};
8+
9+
pub struct Sink(Arc<Mutex<Vec<u8>>>);
10+
11+
impl Sink {
12+
pub fn new_boxed(data: &Arc<Mutex<Vec<u8>>>) -> Box<Self> {
13+
Box::new(Self(data.clone()))
14+
}
15+
}
16+
17+
impl Write for Sink {
18+
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
19+
Write::write(&mut *self.0.lock().unwrap(), data)
20+
}
21+
fn flush(&mut self) -> io::Result<()> {
22+
Ok(())
23+
}
24+
}

0 commit comments

Comments
 (0)