Skip to content

Commit aa4bba3

Browse files
author
Adam Reichold
committed
Avoid dependency on Rust nightly for capturing test output
Instead of using unstable API available only on Rust nightly, this uses the gag crate to capture stdout and stderr of the test scenarios. This has one downside though, that crate currently works only on Unix-like systems. But it is strictly more general as it redirects file descriptors instead of just change the Rust-specific stdout and stderr locked readers and writers.
1 parent 1df5b19 commit aa4bba3

File tree

5 files changed

+22
-53
lines changed

5 files changed

+22
-53
lines changed

Cargo.toml

+2-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ repository = "https://github.com/bbqsrc/cucumber-rust"
99
documentation = "https://docs.rs/cucumber_rust"
1010
homepage = "https://github.com/bbqsrc/cucumber-rust"
1111
edition = "2018"
12-
build = "build.rs"
1312

1413
[badges]
1514
travis-ci = { repository = "bbqsrc/cucumber-rust" }
@@ -26,9 +25,5 @@ pathdiff = "^0.1.0"
2625
textwrap = { version = "0.11", features = ["term_size"] }
2726
clap = "^2.32.0"
2827
globwalk = "0.7"
29-
30-
[build-dependencies]
31-
rustc_version = "0.2"
32-
33-
[features]
34-
nightly = []
28+
gag = "0.1"
29+
tempfile = "3.0"

build.rs

-7
This file was deleted.

src/cli.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub fn make_app() -> Result<CliOptions, CliError> {
5959
let feature = matches.value_of("feature").map(|v| v.to_string());
6060
let tag = matches.value_of("tag").map(|v| v.to_string());
6161

62-
let suppress_output = cfg!(feature = "nightly") && !matches.is_present("nocapture");
62+
let suppress_output = !matches.is_present("nocapture");
6363

6464
Ok(CliOptions {
6565
feature,

src/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9-
#![cfg_attr(feature = "nightly", feature(set_stdio))]
10-
119
pub extern crate gherkin_rust as gherkin;
1210
pub extern crate globwalk;
1311
pub extern crate regex;

src/panic_trap.rs

+19-36
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
use std::io::{self, Write};
1+
use std::io::{Read, Seek, SeekFrom};
22
use std::ops::Deref;
33
use std::panic;
44
use std::sync::{Arc, Mutex};
55

6+
use gag::Redirect;
7+
use tempfile::tempfile;
8+
69
#[derive(Clone)]
710
pub struct PanicDetails {
811
pub payload: String,
@@ -29,19 +32,6 @@ impl PanicDetails {
2932
}
3033
}
3134

32-
#[derive(Default)]
33-
struct Sink(Arc<Mutex<Vec<u8>>>);
34-
35-
impl Write for Sink {
36-
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
37-
Write::write(&mut *self.0.lock().unwrap(), data)
38-
}
39-
40-
fn flush(&mut self) -> io::Result<()> {
41-
self.0.lock().unwrap().flush()
42-
}
43-
}
44-
4535
pub struct PanicTrap<T> {
4636
pub stdout: Vec<u8>,
4737
pub result: Result<T, PanicDetails>,
@@ -56,35 +46,28 @@ impl<T> PanicTrap<T> {
5646
}
5747
}
5848

59-
#[cfg(feature = "nightly")]
6049
fn run_quietly<F: FnOnce() -> T>(f: F) -> PanicTrap<T> {
61-
let stdout_sink = Arc::new(Mutex::new(vec![]));
62-
let stdout_sink_hook = stdout_sink.clone();
63-
let old_io = (
64-
io::set_print(Some(Box::new(Sink(stdout_sink.clone())))),
65-
io::set_panic(Some(Box::new(Sink(stdout_sink)))),
66-
);
67-
68-
let loud_panic_trap = PanicTrap::run_loudly(f);
69-
70-
io::set_print(old_io.0);
71-
io::set_panic(old_io.1);
72-
73-
let stdout = stdout_sink_hook
74-
.lock()
75-
.expect("Stdout mutex poisoned")
76-
.clone();
50+
let mut tmp = tempfile().unwrap();
51+
52+
let loud_panic_trap = {
53+
let _stdout =
54+
Redirect::stdout(tmp.try_clone().unwrap()).expect("Failed to capture stdout");
55+
let _stderr =
56+
Redirect::stderr(tmp.try_clone().unwrap()).expect("Failed to capture stderr");
57+
58+
PanicTrap::run_loudly(f)
59+
};
60+
61+
let mut stdout = Vec::new();
62+
tmp.seek(SeekFrom::Start(0)).unwrap();
63+
tmp.read_to_end(&mut stdout).unwrap();
64+
7765
PanicTrap {
7866
stdout,
7967
result: loud_panic_trap.result,
8068
}
8169
}
8270

83-
#[cfg(not(feature = "nightly"))]
84-
fn run_quietly<F: FnOnce() -> T>(_f: F) -> PanicTrap<T> {
85-
panic!("PanicTrap cannot run quietly without the 'nightly' feature");
86-
}
87-
8871
fn run_loudly<F: FnOnce() -> T>(f: F) -> PanicTrap<T> {
8972
let last_panic = Arc::new(Mutex::new(None));
9073

0 commit comments

Comments
 (0)