add incremental test runner and some tests

This commit is contained in:
Niko Matsakis 2016-03-28 17:49:02 -04:00
parent 3fb40c1d95
commit 068142a2e6
7 changed files with 240 additions and 3 deletions

View file

@ -25,7 +25,8 @@ pub enum Mode {
DebugInfoLldb,
Codegen,
Rustdoc,
CodegenUnits
CodegenUnits,
Incremental,
}
impl FromStr for Mode {
@ -43,6 +44,7 @@ impl FromStr for Mode {
"codegen" => Ok(Codegen),
"rustdoc" => Ok(Rustdoc),
"codegen-units" => Ok(CodegenUnits),
"incremental" => Ok(Incremental),
_ => Err(()),
}
}
@ -62,6 +64,7 @@ impl fmt::Display for Mode {
Codegen => "codegen",
Rustdoc => "rustdoc",
CodegenUnits => "codegen-units",
Incremental => "incremental",
}, f)
}
}

View file

@ -71,7 +71,8 @@ pub fn parse_config(args: Vec<String> ) -> Config {
reqopt("", "aux-base", "directory to find auxiliary test files", "PATH"),
reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET"),
reqopt("", "mode", "which sort of compile tests to run",
"(compile-fail|parse-fail|run-fail|run-pass|run-pass-valgrind|pretty|debug-info)"),
"(compile-fail|parse-fail|run-fail|run-pass|\
run-pass-valgrind|pretty|debug-info|incremental)"),
optflag("", "ignored", "run tests marked as ignored"),
optopt("", "runtool", "supervisor program to run tests under \
(eg. emulator, valgrind)", "PROGRAM"),

View file

@ -11,6 +11,7 @@
use common::Config;
use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits};
use common::{Incremental};
use errors::{self, ErrorKind};
use header::TestProps;
use header;
@ -59,6 +60,7 @@ pub fn run(config: Config, testpaths: &TestPaths) {
Codegen => run_codegen_test(&config, &props, &testpaths),
Rustdoc => run_rustdoc_test(&config, &props, &testpaths),
CodegenUnits => run_codegen_units_test(&config, &props, &testpaths),
Incremental => run_incremental_test(&config, &props, &testpaths),
}
}
@ -1966,3 +1968,66 @@ fn run_codegen_units_test(config: &Config, props: &TestProps, testpaths: &TestPa
panic!();
}
}
fn run_incremental_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
// Basic plan for a test incremental/foo/bar.rs:
// - load list of revisions pass1, fail2, pass3
// - each should begin with `pass` or `fail`
// - if `pass`, expect compile to succeed
// - if `fail`, expect errors from file
// - create a directory build/foo/bar.incremental
// - compile foo/bar.rs with -Z incremental=.../foo/bar.incremental and -C pass1
// - because name of revision starts with "pass", expect success
// - compile foo/bar.rs with -Z incremental=.../foo/bar.incremental and -C fail2
// - because name of revision starts with "fail", expect an error
// - load expected errors as usual, but filter for those that end in `[fail2]`
// - compile foo/bar.rs with -Z incremental=.../foo/bar.incremental and -C pass3
// - because name of revision starts with "pass", expect success
// - execute build/foo/bar.exe and save output
//
// FIXME -- use non-incremental mode as an oracle? That doesn't apply
// to #[rustc_dirty] and clean tests I guess
assert!(!props.revisions.is_empty(), "incremental tests require a list of revisions");
let output_base_name = output_base_name(config, testpaths);
// Create the incremental workproduct directory.
let incremental_dir = output_base_name.with_extension("incremental");
if incremental_dir.exists() {
fs::remove_dir_all(&incremental_dir).unwrap();
}
fs::create_dir_all(&incremental_dir).unwrap();
if config.verbose {
print!("incremental_dir={}", incremental_dir.display());
}
for revision in &props.revisions {
let mut revision_props = props.clone();
header::load_props_into(&mut revision_props, &testpaths.file, Some(&revision));
revision_props.compile_flags.extend(vec![
format!("-Z"),
format!("incremental={}", incremental_dir.display()),
format!("--cfg"),
format!("{}", revision),
]);
if config.verbose {
print!("revision={:?} revision_props={:#?}", revision, revision_props);
}
if revision.starts_with("rpass") {
run_rpass_test_revision(config, &revision_props, testpaths, Some(&revision));
} else if revision.starts_with("rfail") {
run_rfail_test_revision(config, &revision_props, testpaths, Some(&revision));
} else if revision.starts_with("cfail") {
run_cfail_test_revision(config, &revision_props, testpaths, Some(&revision));
} else {
fatal(
Some(revision),
"revision name must begin with rpass, rfail, or cfail");
}
}
}