Skip to content

Commit 32c5125

Browse files
committed
Add a cargo-inspired testsuite
1 parent 2a3defd commit 32c5125

File tree

3 files changed

+191
-0
lines changed

3 files changed

+191
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ serde_json = "1.0"
2626
serde_derive = "1.0"
2727
rustfix = "0.5"
2828
tester = "0.8"
29+
lazy_static = "1.4"
2930

3031
[target."cfg(unix)".dependencies]
3132
libc = "0.2"

tests/bless.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//! Tests for the `bless` option
2+
3+
extern crate compiletest_rs as compiletest;
4+
5+
mod test_support;
6+
use test_support::{testsuite, TestsuiteBuilder, GLOBAL_ROOT};
7+
use compiletest::Config;
8+
9+
fn setup(mode: &str) -> (Config, TestsuiteBuilder) {
10+
let builder = testsuite(mode);
11+
let mut config = Config::default();
12+
let cfg_mode = mode.parse().expect("Invalid mode");
13+
config.mode = cfg_mode;
14+
config.src_base = builder.root.clone();
15+
config.build_base = GLOBAL_ROOT.join("build_base");
16+
17+
(config, builder)
18+
}
19+
20+
#[test]
21+
fn test_bless_new_file() {
22+
let (mut config, builder) = setup("ui");
23+
config.bless = true;
24+
25+
builder.mk_file(
26+
"foobar.rs",
27+
r#"
28+
#[warn(unused_variables)]
29+
fn main() {
30+
let abc = "foobar";
31+
}
32+
"#,
33+
);
34+
compiletest::run_tests(&config);
35+
36+
// Blessing should cause the stderr to be created directly
37+
assert!(builder.file_contents("foobar.stderr").contains("unused variable"));
38+
39+
// And a second run of the tests, with blessing disabled should work just fine
40+
config.bless = false;
41+
compiletest::run_tests(&config);
42+
}
43+
44+
#[test]
45+
fn test_bless_update_file() {
46+
let (mut config, builder) = setup("ui");
47+
config.bless = true;
48+
49+
builder.mk_file(
50+
"foobar2.rs",
51+
r#"
52+
#[warn(unused_variables)]
53+
fn main() {
54+
let abc = "foobar_update";
55+
}
56+
"#,
57+
);
58+
builder.mk_file(
59+
"foobar2.stderr",
60+
r#"
61+
warning: unused variable: `abc`
62+
--> $DIR/foobar2.rs:4:27
63+
|
64+
4 | let abc = "foobar";
65+
| ^^^ help: if this is intentional, prefix it with an underscore: `_abc`
66+
|
67+
note: the lint level is defined here
68+
--> $DIR/foobar2.rs:2:26
69+
|
70+
2 | #[warn(unused_variables)]
71+
| ^^^^^^^^^^^^^^^^
72+
73+
warning: 1 warning emitted
74+
"#,
75+
);
76+
compiletest::run_tests(&config);
77+
78+
// Blessing should cause the stderr to be created directly
79+
assert!(builder.file_contents("foobar2.stderr").contains("unused variable"));
80+
assert!(builder.file_contents("foobar2.stderr").contains("foobar_update"));
81+
82+
// And a second run of the tests, with blessing disabled should work just fine
83+
config.bless = false;
84+
compiletest::run_tests(&config);
85+
}

tests/test_support/mod.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//! Provides a simple way to set up compiletest sample testsuites used in testing.
2+
//!
3+
//! Inspired by cargo's `cargo-test-support` crate:
4+
//! https://github.com/rust-lang/cargo/tree/master/crates/cargo-test-support
5+
use std::env;
6+
use std::fs;
7+
use std::path::{Path, PathBuf};
8+
use std::cell::RefCell;
9+
use std::sync::atomic::{AtomicUsize, Ordering};
10+
11+
12+
static COMPILETEST_INTEGRATION_TEST_DIR: &str = "cit";
13+
14+
thread_local! {
15+
static TEST_ID: RefCell<Option<usize>> = RefCell::new(None);
16+
}
17+
18+
lazy_static::lazy_static! {
19+
pub static ref GLOBAL_ROOT: PathBuf = {
20+
let mut path = env::current_exe().unwrap();
21+
path.pop(); // chop off exe name
22+
path.pop(); // chop off 'deps' part
23+
path.pop(); // chop off 'debug'
24+
25+
path.push(COMPILETEST_INTEGRATION_TEST_DIR);
26+
path.mkdir_p();
27+
path
28+
};
29+
}
30+
31+
pub fn testsuite(mode: &str) -> TestsuiteBuilder {
32+
let builder = TestsuiteBuilder::new(mode);
33+
builder.build();
34+
builder
35+
}
36+
37+
pub struct TestsuiteBuilder {
38+
pub root: PathBuf,
39+
}
40+
41+
impl TestsuiteBuilder {
42+
pub fn new(mode: &str) -> Self {
43+
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
44+
45+
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
46+
TEST_ID.with(|n| *n.borrow_mut() = Some(id));
47+
let root = GLOBAL_ROOT.join(format!("id{}", TEST_ID.with(|n|n.borrow().unwrap()))).join(mode);
48+
root.mkdir_p();
49+
50+
Self {
51+
root,
52+
}
53+
}
54+
55+
56+
/// Creates a new file to be used for the integration test
57+
pub fn mk_file(&self, path: &str, body: &str) {
58+
self.root.mkdir_p();
59+
fs::write(self.root.join(&path), &body)
60+
.unwrap_or_else(|e| panic!("could not create file {}: {}", path, e));
61+
}
62+
63+
/// Returns the contents of the file
64+
pub fn file_contents(&self, name: &str) -> String {
65+
fs::read_to_string(self.root.join(name)).expect("Unable to read file")
66+
}
67+
68+
// Sets up a new testsuite root directory
69+
fn build(&self) {
70+
// Cleanup before we run the next test
71+
self.rm_root();
72+
73+
// Create the new directory
74+
self.root.mkdir_p();
75+
}
76+
77+
/// Deletes the root directory and all its contents
78+
fn rm_root(&self) {
79+
self.root.rm_rf();
80+
}
81+
}
82+
83+
pub trait PathExt {
84+
fn rm_rf(&self);
85+
fn mkdir_p(&self);
86+
}
87+
88+
impl PathExt for Path {
89+
fn rm_rf(&self) {
90+
if self.is_dir() {
91+
if let Err(e) = fs::remove_dir_all(self) {
92+
panic!("failed to remove {:?}: {:?}", self, e)
93+
}
94+
} else {
95+
if let Err(e) = fs::remove_file(self) {
96+
panic!("failed to remove {:?}: {:?}", self, e)
97+
}
98+
}
99+
}
100+
101+
fn mkdir_p(&self) {
102+
fs::create_dir_all(self)
103+
.unwrap_or_else(|e| panic!("failed to mkdir_p {}: {}", self.display(), e))
104+
}
105+
}

0 commit comments

Comments
 (0)