Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create a miri-pass test that allows us to run miri for arbitrary targets #27

Merged
merged 11 commits into from
Jun 16, 2016
5 changes: 1 addition & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
language: rust
rust:
- nightly
matrix:
allow_failures:
- rust: nightly
before_script:
- |
pip install 'travis-cargo<0.2' --user &&
export PATH=$HOME/.local/bin:$PATH
script:
- |
travis-cargo build &&
env RUST_SYSROOT=$HOME/rust travis-cargo build &&
env RUST_SYSROOT=$HOME/rust travis-cargo test
notifications:
email:
Expand Down
10 changes: 8 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ log = "0.3.6"
log_settings = "0.1.1"

[dev-dependencies]
compiletest_rs = "0.1.1"
compiletest_rs = "0.2"
4 changes: 3 additions & 1 deletion src/bin/miri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use miri::{
Frame,
};
use rustc::session::Session;
use rustc_driver::{driver, CompilerCalls};
use rustc_driver::{driver, CompilerCalls, Compilation};
use rustc::ty::{TyCtxt, subst};
use rustc::hir::def_id::DefId;

Expand All @@ -31,6 +31,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
) -> driver::CompileController<'a> {
let mut control = driver::CompileController::basic();

control.after_analysis.stop = Compilation::Stop;
control.after_analysis.callback = Box::new(|state| {
state.session.abort_if_errors();

Expand Down Expand Up @@ -70,6 +71,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
}
}
}
state.session.abort_if_errors();
});

control
Expand Down
94 changes: 70 additions & 24 deletions tests/compiletest.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,89 @@
extern crate compiletest_rs as compiletest;

use std::path::PathBuf;
use std::path::{PathBuf, Path};
use std::io::Write;

fn run_mode(mode: &'static str) {
fn run_mode(dir: &'static str, mode: &'static str, sysroot: &str) {
// Disable rustc's new error fomatting. It breaks these tests.
std::env::remove_var("RUST_NEW_ERROR_FORMAT");

// Taken from https://github.com/Manishearth/rust-clippy/pull/911.
let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
let sysroot = match (home, toolchain) {
(Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
_ => option_env!("RUST_SYSROOT")
.expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
.to_owned(),
};
let flags = format!("--sysroot {} -Dwarnings", sysroot);

// FIXME: read directories in sysroot/lib/rustlib and generate the test targets from that
let targets = &["x86_64-unknown-linux-gnu", "i686-unknown-linux-gnu"];

for &target in targets {
use std::io::Write;
let stderr = std::io::stderr();
write!(stderr.lock(), "running tests for target {}", target).unwrap();
for_all_targets(sysroot, |target| {
let mut config = compiletest::default_config();
config.host_rustcflags = Some(flags.clone());
config.mode = mode.parse().expect("Invalid mode");
config.run_lib_path = format!("{}/lib/rustlib/{}/lib", sysroot, target);
config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
config.rustc_path = "target/debug/miri".into();
config.src_base = PathBuf::from(format!("tests/{}", mode));
config.src_base = PathBuf::from(format!("tests/{}", dir));
config.target = target.to_owned();
config.target_rustcflags = Some(flags.clone());
compiletest::run_tests(&config);
});
}

fn for_all_targets<F: FnMut(String)>(sysroot: &str, mut f: F) {
for target in std::fs::read_dir(format!("{}/lib/rustlib/", sysroot)).unwrap() {
let target = target.unwrap();
if !target.metadata().unwrap().is_dir() {
continue;
}
let target = target.file_name().into_string().unwrap();
if target == "etc" {
continue;
}
let stderr = std::io::stderr();
writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
f(target);
}
}

#[test]
fn compile_test() {
run_mode("compile-fail");
run_mode("run-pass");
let mut failed = false;
// Taken from https://github.com/Manishearth/rust-clippy/pull/911.
let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
let sysroot = match (home, toolchain) {
(Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
_ => option_env!("RUST_SYSROOT")
.expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
.to_owned(),
};
run_mode("compile-fail", "compile-fail", &sysroot);
for_all_targets(&sysroot, |target| {
for file in std::fs::read_dir("tests/run-pass").unwrap() {
let file = file.unwrap();
if !file.metadata().unwrap().is_file() {
continue;
}
let file = file.path();
let stderr = std::io::stderr();
write!(stderr.lock(), "test [miri-pass] {} ", file.to_str().unwrap()).unwrap();
let mut cmd = std::process::Command::new("target/debug/miri");
cmd.arg(file);
cmd.arg("-Dwarnings");
cmd.arg(format!("--target={}", target));
let libs = Path::new(&sysroot).join("lib");
let sysroot = libs.join("rustlib").join(&target).join("lib");
let paths = std::env::join_paths(&[libs, sysroot]).unwrap();
cmd.env(compiletest::procsrv::dylib_env_var(), paths);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this cmd never gets executed, only args and env are set.

match cmd.output() {
Ok(ref output) if output.status.success() => writeln!(stderr.lock(), "ok").unwrap(),
Ok(output) => {
failed = true;
writeln!(stderr.lock(), "FAILED with exit code {}", output.status.code().unwrap_or(0)).unwrap();
writeln!(stderr.lock(), "stdout: \n {}", std::str::from_utf8(&output.stdout).unwrap()).unwrap();
writeln!(stderr.lock(), "stderr: \n {}", std::str::from_utf8(&output.stderr).unwrap()).unwrap();
}
Err(e) => {
failed = true;
writeln!(stderr.lock(), "FAILED: {}", e).unwrap();
},
}
}
let stderr = std::io::stderr();
writeln!(stderr.lock(), "").unwrap();
});
if failed {
panic!("some tests failed");
}
}