From fd3d965a7bb97695a80221c3479aea02c9470ba5 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Thu, 30 Jun 2016 15:49:57 -0700 Subject: [PATCH 1/2] Refactor tests and add a compile_pass suite. --- tests/compile-pass/README.md | 3 + tests/compile-pass/trivial.rs | 12 ++++ tests/compiletest.rs | 116 ++++++++++++++++++++++++---------- 3 files changed, 96 insertions(+), 35 deletions(-) create mode 100644 tests/compile-pass/README.md create mode 100644 tests/compile-pass/trivial.rs diff --git a/tests/compile-pass/README.md b/tests/compile-pass/README.md new file mode 100644 index 0000000000..13b5ebb9ff --- /dev/null +++ b/tests/compile-pass/README.md @@ -0,0 +1,3 @@ +These are tests that make it through the compiler but do not necessarily +run. These should be equivalent to the run-pass tests, but we aren't quite there +yet. diff --git a/tests/compile-pass/trivial.rs b/tests/compile-pass/trivial.rs new file mode 100644 index 0000000000..fb4c522f1a --- /dev/null +++ b/tests/compile-pass/trivial.rs @@ -0,0 +1,12 @@ +#![allow(dead_code)] +#![no_std] +#![no_core] + +fn empty() {} + +fn unit_var() { + let x = (); + x +} + +fn main() {} diff --git a/tests/compiletest.rs b/tests/compiletest.rs index a6d3498b78..d5c69437f6 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -3,7 +3,9 @@ extern crate compiletest_rs as compiletest; use std::path::{PathBuf, Path}; use std::io::Write; -fn compile_fail(sysroot: &str) { +#[test] #[ignore] +fn compile_fail() { + let sysroot = &find_sysroot(); let flags = format!("--sysroot {} -Dwarnings", sysroot); for_all_targets(sysroot, |target| { let mut config = compiletest::default_config(); @@ -18,48 +20,58 @@ fn compile_fail(sysroot: &str) { }); } -fn run_pass() { - let mut config = compiletest::default_config(); - config.mode = "run-pass".parse().expect("Invalid mode"); - config.src_base = PathBuf::from("tests/run-pass".to_string()); - compiletest::run_tests(&config); -} +#[test] +fn compile_pass() { + let sysroot = find_sysroot(); + for_all_targets(&sysroot, |target| { + for file in std::fs::read_dir("tests/compile-pass").unwrap() { + let file = file.unwrap(); + let path = file.path(); -fn for_all_targets(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; + if !file.metadata().unwrap().is_file() || !path.to_str().unwrap().ends_with(".rs") { + continue; + } + + let stderr = std::io::stderr(); + write!(stderr.lock(), "test [compile-pass] {} ... ", path.display()).unwrap(); + let mut cmd = std::process::Command::new("target/debug/mir2wasm"); + cmd.arg(path); + cmd.arg("-Dwarnings"); + 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); + + match cmd.output() { + Ok(ref output) if output.status.success() => writeln!(stderr.lock(), "ok").unwrap(), + Ok(output) => { + writeln!(stderr.lock(), "FAILED with exit code {:?}", output.status.code()).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(); + panic!("some tests failed"); + } + Err(e) => { + writeln!(stderr.lock(), "FAILED: {}", e).unwrap(); + panic!("some tests failed"); + }, + } } let stderr = std::io::stderr(); - writeln!(stderr.lock(), "running tests for target {}", target).unwrap(); - f(target); - } + writeln!(stderr.lock(), "").unwrap(); + }); } #[test] -fn empty_test() { - // show the test harness is running by getting at least one - // successful test. +fn run_pass() { + let mut config = compiletest::default_config(); + config.mode = "run-pass".parse().expect("Invalid mode"); + config.src_base = PathBuf::from("tests/run-pass".to_string()); + compiletest::run_tests(&config); } #[test] #[ignore] -fn compile_test() { - // 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(), - }; - compile_fail(&sysroot); - run_pass(); +fn miri_run_pass() { + let sysroot = find_sysroot(); for_all_targets(&sysroot, |target| { for file in std::fs::read_dir("tests/run-pass").unwrap() { let file = file.unwrap(); @@ -71,7 +83,7 @@ fn compile_test() { let stderr = std::io::stderr(); write!(stderr.lock(), "test [miri-pass] {} ... ", path.display()).unwrap(); - let mut cmd = std::process::Command::new("target/debug/miri"); + let mut cmd = std::process::Command::new("target/debug/mir2wasm"); cmd.arg(path); cmd.arg("-Dwarnings"); cmd.arg(format!("--target={}", target)); @@ -98,3 +110,37 @@ fn compile_test() { writeln!(stderr.lock(), "").unwrap(); }); } + +fn for_all_targets(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 empty_test() { + // show the test harness is running by getting at least one + // successful test. +} + +fn find_sysroot() -> String { + // 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")); + 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(), + } +} From b051c64d944d2bd2f96f9683e9b3649793ed5ae6 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Thu, 30 Jun 2016 16:52:06 -0700 Subject: [PATCH 2/2] Make mir2wasm correctly report exit status, so test framework can detect failures. Add support for xfail tests in compile-pass. --- src/bin/mir2wasm.rs | 6 +++++- tests/compile-pass/enum.rs | 24 ++++++++++++++++++++++++ tests/compile-pass/trivial.rs | 11 +++-------- tests/compiletest.rs | 35 ++++++++++++++++++++++++++++++----- 4 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 tests/compile-pass/enum.rs diff --git a/src/bin/mir2wasm.rs b/src/bin/mir2wasm.rs index d2941fd7b2..5cfe5c9275 100644 --- a/src/bin/mir2wasm.rs +++ b/src/bin/mir2wasm.rs @@ -14,6 +14,7 @@ extern { } use mir2wasm::trans; use rustc::session::Session; use rustc_driver::{driver, CompilerCalls}; +use std::process; struct MiriCompilerCalls; @@ -42,5 +43,8 @@ fn main() { let mut args: Vec = std::env::args().collect(); args.push("--target=arm-unknown-linux-gnueabi".to_string()); - rustc_driver::run_compiler(&args, &mut MiriCompilerCalls); + match rustc_driver::run_compiler(&args, &mut MiriCompilerCalls) { + (Ok(_), _) => process::exit(0), + (Err(code), _) => process::exit(code as i32) + } } diff --git a/tests/compile-pass/enum.rs b/tests/compile-pass/enum.rs new file mode 100644 index 0000000000..473db1385a --- /dev/null +++ b/tests/compile-pass/enum.rs @@ -0,0 +1,24 @@ +// xfail + +#![feature(lang_items, no_core)] +#![allow(dead_code)] +#![no_core] + +#[lang="sized"] +trait Sized {} + +#[lang="copy"] +trait Copy {} + +enum Tag { + A(isize), + B(isize) +} + +fn main() { + let a = Tag::A(5); + match a { + Tag::A(i) => i, + Tag::B(i) => i, + }; +} diff --git a/tests/compile-pass/trivial.rs b/tests/compile-pass/trivial.rs index fb4c522f1a..f2b7175d11 100644 --- a/tests/compile-pass/trivial.rs +++ b/tests/compile-pass/trivial.rs @@ -1,12 +1,7 @@ -#![allow(dead_code)] -#![no_std] +#![feature(lang_items, no_core)] #![no_core] -fn empty() {} - -fn unit_var() { - let x = (); - x -} +#[lang="sized"] +trait Sized {} fn main() {} diff --git a/tests/compiletest.rs b/tests/compiletest.rs index d5c69437f6..8d775db1a5 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -1,7 +1,8 @@ extern crate compiletest_rs as compiletest; +use std::fs::File; +use std::io::{Read, Write}; use std::path::{PathBuf, Path}; -use std::io::Write; #[test] #[ignore] fn compile_fail() { @@ -20,10 +21,21 @@ fn compile_fail() { }); } +fn should_ignore(filename: &Path) -> bool { + let mut file = File::open(filename).expect("could not open file"); + let mut source = String::new(); + + file.read_to_string(&mut source).expect("could not read file"); + + return source.contains("xfail") +} + #[test] fn compile_pass() { let sysroot = find_sysroot(); for_all_targets(&sysroot, |target| { + let (mut pass, mut fail, mut ignored) = (0, 0, 0); + for file in std::fs::read_dir("tests/compile-pass").unwrap() { let file = file.unwrap(); let path = file.path(); @@ -32,6 +44,11 @@ fn compile_pass() { continue; } + if should_ignore(&path) { + ignored += 1; + continue; + } + let stderr = std::io::stderr(); write!(stderr.lock(), "test [compile-pass] {} ... ", path.display()).unwrap(); let mut cmd = std::process::Command::new("target/debug/mir2wasm"); @@ -43,21 +60,29 @@ fn compile_pass() { cmd.env(compiletest::procsrv::dylib_env_var(), paths); match cmd.output() { - Ok(ref output) if output.status.success() => writeln!(stderr.lock(), "ok").unwrap(), + Ok(ref output) if output.status.success() => { + writeln!(stderr.lock(), "ok").unwrap(); + pass += 1; + } Ok(output) => { writeln!(stderr.lock(), "FAILED with exit code {:?}", output.status.code()).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(); - panic!("some tests failed"); + fail += 1; } Err(e) => { writeln!(stderr.lock(), "FAILED: {}", e).unwrap(); - panic!("some tests failed"); + fail += 1; }, } } let stderr = std::io::stderr(); - writeln!(stderr.lock(), "").unwrap(); + writeln!(stderr.lock(), + "[compile-pass] {} passed; {} failed; {} ignored", + pass, fail, ignored).unwrap(); + if fail > 0 { + panic!("some compile-pass tests failed") + } }); }