Skip to content

Commit 45e14f8

Browse files
committed
use custom test runner so that we can get proper test filtering
1 parent d136fdb commit 45e14f8

File tree

2 files changed

+44
-42
lines changed

2 files changed

+44
-42
lines changed

README.md

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ undergraduate research course at the [University of Saskatchewan][usask].
77

88
## Building Miri
99

10-
I recommend that you install [rustup][rustup] to obtain Rust. Then all you have
10+
We recommend that you install [rustup][rustup] to obtain Rust. Then all you have
1111
to do is:
1212

1313
```sh
@@ -117,11 +117,12 @@ Miri will often require using a locally built rustc. This includes getting a
117117
trace of the execution, as distributed rustc has `debug!` and `trace!` disabled.
118118

119119
The first-time setup for a local rustc looks as follows:
120-
```
120+
```sh
121121
git clone https://github.com/rust-lang/rust/ rustc
122122
cd rustc
123123
cp config.toml.example config.toml
124-
# Now edit `config.toml` and set `debug-assertions = true`
124+
# Now edit `config.toml` and set `debug-assertions = true` and `test-miri = true`.
125+
# The latter is important to build libstd with the right flags for miri.
125126
./x.py build src/rustc
126127
# You may have to change the architecture in the next command
127128
rustup toolchain link custom build/x86_64-unknown-linux-gnu/stage2
@@ -130,9 +131,20 @@ rustup override set custom
130131
```
131132
The `build` step can take 30 minutes and more.
132133

133-
Now you can `cargo build` Miri, and you can `cargo test` it. But the key point
134-
is, you can now run Miri with a trace of all execution steps:
134+
Now you can `cargo build` Miri, and you can `cargo test --release` it. `cargo
135+
test --release FILTER` only runs those tests that contain `FILTER` in their
136+
filename (including the base directory, e.g. `cargo test --release fail` will
137+
run all compile-fail tests). We recommend using `--release` to make test
138+
running take less time.
139+
140+
Notice that the "fullmir" tests only run if you have `MIRI_SYSROOT` set, the
141+
test runner does not realized that your libstd comes with full MIR. The
142+
following will set it correctly:
143+
```sh
144+
MIRI_SYSROOT=$(rustc --print sysroot) cargo test --release
145+
```
135146

147+
Moreover, you can now run Miri with a trace of all execution steps:
136148
```sh
137149
MIRI_LOG=debug cargo run tests/run-pass/vecs.rs
138150
```
@@ -141,9 +153,8 @@ Setting `MIRI_LOG` like this will configure logging for miri itself as well as
141153
the `rustc::mir::interpret` and `rustc_mir::interpret` modules in rustc. You
142154
can also do more targeted configuration, e.g. to debug the stacked borrows
143155
implementation:
144-
145156
```sh
146-
MIRI_LOG=miri::stacked_borrows=trace,rustc_mir::interpret=debug cargo run tests/run-pass/vecs.rs
157+
MIRI_LOG=rustc_mir::interpret=debug,miri::stacked_borrows cargo run tests/run-pass/vecs.rs
147158
```
148159

149160
In addition, you can set `MIRI_BACKTRACE=1` to get a backtrace of where an

tests/compiletest.rs

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
1-
#![feature(slice_concat_ext)]
2-
3-
extern crate compiletest_rs as compiletest;
4-
extern crate colored;
5-
6-
use colored::*;
1+
#![feature(slice_concat_ext, custom_test_frameworks)]
2+
#![test_runner(test_runner)]
73

84
use std::slice::SliceConcatExt;
95
use std::path::{PathBuf, Path};
106
use std::io::Write;
7+
use std::env;
118

12-
macro_rules! eprintln {
13-
($($arg:tt)*) => {
14-
let stderr = std::io::stderr();
15-
writeln!(stderr.lock(), $($arg)*).unwrap();
16-
}
17-
}
9+
use compiletest_rs as compiletest;
10+
use colored::*;
1811

1912
fn miri_path() -> PathBuf {
2013
if rustc_test_suite().is_some() {
@@ -37,9 +30,21 @@ fn have_fullmir() -> bool {
3730
std::env::var("MIRI_SYSROOT").is_ok() || rustc_test_suite().is_some()
3831
}
3932

33+
fn mk_config(mode: &str) -> compiletest::Config {
34+
let mut config = compiletest::Config::default();
35+
config.mode = mode.parse().expect("Invalid mode");
36+
config.rustc_path = miri_path();
37+
if rustc_test_suite().is_some() {
38+
config.run_lib_path = rustc_lib_path();
39+
config.compile_lib_path = rustc_lib_path();
40+
}
41+
config.filter = env::args().nth(1);
42+
config
43+
}
44+
4045
fn compile_fail(sysroot: &Path, path: &str, target: &str, host: &str, need_fullmir: bool, opt: bool) {
4146
if need_fullmir && !have_fullmir() {
42-
eprintln!("{}", format!(
47+
eprintln!("{}\n", format!(
4348
"## Skipping compile-fail tests in {} against miri for target {} due to missing mir",
4449
path,
4550
target
@@ -65,23 +70,17 @@ fn compile_fail(sysroot: &Path, path: &str, target: &str, host: &str, need_fullm
6570
flags.push("-Zmir-opt-level=1".to_owned());
6671
}
6772

68-
let mut config = compiletest::Config::default().tempdir();
69-
config.mode = "compile-fail".parse().expect("Invalid mode");
70-
config.rustc_path = miri_path();
71-
if rustc_test_suite().is_some() {
72-
config.run_lib_path = rustc_lib_path();
73-
config.compile_lib_path = rustc_lib_path();
74-
}
75-
config.src_base = PathBuf::from(path.to_string());
76-
config.target_rustcflags = Some(flags.join(" "));
73+
let mut config = mk_config("compile-fail");
74+
config.src_base = PathBuf::from(path);
7775
config.target = target.to_owned();
7876
config.host = host.to_owned();
79-
compiletest::run_tests(&config);
77+
config.target_rustcflags = Some(flags.join(" "));
78+
compiletest::run_tests(&config.tempdir()); // FIXME: `tempdir` can be done by `mk_config` once `ConfigWithTemp` is exposed as type from compiletest
8079
}
8180

8281
fn miri_pass(sysroot: &Path, path: &str, target: &str, host: &str, need_fullmir: bool, opt: bool) {
8382
if need_fullmir && !have_fullmir() {
84-
eprintln!("{}", format!(
83+
eprintln!("{}\n", format!(
8584
"## Skipping run-pass tests in {} against miri for target {} due to missing mir",
8685
path,
8786
target
@@ -104,18 +103,12 @@ fn miri_pass(sysroot: &Path, path: &str, target: &str, host: &str, need_fullmir:
104103
flags.push("-Zmir-opt-level=3".to_owned());
105104
}
106105

107-
let mut config = compiletest::Config::default().tempdir();
108-
config.mode = "ui".parse().expect("Invalid mode");
106+
let mut config = mk_config("ui");
109107
config.src_base = PathBuf::from(path);
110108
config.target = target.to_owned();
111109
config.host = host.to_owned();
112-
config.rustc_path = miri_path();
113-
if rustc_test_suite().is_some() {
114-
config.run_lib_path = rustc_lib_path();
115-
config.compile_lib_path = rustc_lib_path();
116-
}
117110
config.target_rustcflags = Some(flags.join(" "));
118-
compiletest::run_tests(&config);
111+
compiletest::run_tests(&config.tempdir()); // FIXME: `tempdir` can be done by `mk_config` once `ConfigWithTemp` is exposed as type from compiletest
119112
}
120113

121114
fn is_target_dir<P: Into<PathBuf>>(path: P) -> bool {
@@ -151,7 +144,6 @@ fn get_sysroot() -> PathBuf {
151144

152145
fn get_host() -> String {
153146
let rustc = rustc_test_suite().unwrap_or(PathBuf::from("rustc"));
154-
println!("using rustc at {}", rustc.display());
155147
let host = std::process::Command::new(rustc)
156148
.arg("-vV")
157149
.output()
@@ -184,8 +176,7 @@ fn compile_fail_miri(opt: bool) {
184176
compile_fail(&sysroot, "tests/compile-fail-fullmir", &host, &host, true, opt);
185177
}
186178

187-
#[test]
188-
fn test() {
179+
fn test_runner(_tests: &[&()]) {
189180
// We put everything into a single test to avoid the parallelism `cargo test`
190181
// introduces. We still get parallelism within our tests because `compiletest`
191182
// uses `libtest` which runs jobs in parallel.

0 commit comments

Comments
 (0)