///
/// If cfg is not None (i.e., in an incremental test), then we look
/// for `//[X]~` instead, where `X` is the current `cfg`.
-pub fn load_errors(testfile: &Path, cfg: &Option<String>) -> Vec<ExpectedError> {
+pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec<ExpectedError> {
let rdr = BufReader::new(File::open(testfile).unwrap());
// `last_nonfollow_error` tracks the most recently seen
// updating it in the map callback below.)
let mut last_nonfollow_error = None;
- let tag = match *cfg {
- Some(ref rev) => format!("//[{}]~", rev),
+ let tag = match cfg {
+ Some(rev) => format!("//[{}]~", rev),
None => format!("//~")
};
#[derive(Clone, Debug)]
pub struct TestProps {
- // For the main test file, this is initialized to `None`. But
- // when running tests that test multiple revisions, such as
- // incremental tests, we will set this to `Some(foo)` where `foo`
- // is the current revision identifier.
- //
- // Note that, unlike the other options here, this value is never
- // loaded from the input file (though it is always set to one of
- // the values listed in the vec `self.revisions`, which is loaded
- // from the file).
- pub revision: Option<String>,
// Lines that should be expected, in order, on standard out
pub error_patterns: Vec<String> ,
// Extra flags to pass to the compiler
let pretty_compare_only = false;
let forbid_output = Vec::new();
let mut props = TestProps {
- revision: None,
error_patterns: error_patterns,
compile_flags: vec![],
run_flags: run_flags,
}
}
+
+fn for_each_revision<OP>(config: &Config, props: &TestProps, testpaths: &TestPaths,
+ mut op: OP)
+ where OP: FnMut(&Config, &TestProps, &TestPaths, Option<&str>)
+{
+ if props.revisions.is_empty() {
+ op(config, props, testpaths, None)
+ } else {
+ 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!("--cfg"),
+ format!("{}", revision),
+ ]);
+ op(config, &revision_props, testpaths, Some(revision));
+ }
+ }
+}
+
fn run_cfail_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
+ for_each_revision(config, props, testpaths, run_cfail_test_revision);
+}
+
+fn run_cfail_test_revision(config: &Config,
+ props: &TestProps,
+ testpaths: &TestPaths,
+ revision: Option<&str>) {
let proc_res = compile_test(config, props, testpaths);
if proc_res.status.success() {
}
let output_to_check = get_output(props, &proc_res);
- let expected_errors = errors::load_errors(&testpaths.file, &props.revision);
+ let expected_errors = errors::load_errors(&testpaths.file, revision);
if !expected_errors.is_empty() {
if !props.error_patterns.is_empty() {
fatal("both error pattern and expected errors specified");
}
fn run_rfail_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
+ for_each_revision(config, props, testpaths, run_rfail_test_revision);
+}
+
+fn run_rfail_test_revision(config: &Config,
+ props: &TestProps,
+ testpaths: &TestPaths,
+ _revision: Option<&str>) {
let proc_res = compile_test(config, props, testpaths);
if !proc_res.status.success() {
}
fn run_rpass_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
+ for_each_revision(config, props, testpaths, run_rpass_test_revision);
+}
+
+fn run_rpass_test_revision(config: &Config,
+ props: &TestProps,
+ testpaths: &TestPaths,
+ _revision: Option<&str>) {
let proc_res = compile_test(config, props, testpaths);
if !proc_res.status.success() {
}
fn run_valgrind_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
+ assert!(props.revisions.is_empty(), "revisions not relevant to rpass tests");
+
if config.valgrind_path.is_none() {
assert!(!config.force_valgrind);
return run_rpass_test(config, props, testpaths);
}
fn run_codegen_units_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
+ assert!(props.revisions.is_empty(), "revisions not relevant to codegen units");
+
let proc_res = compile_test(config, props, testpaths);
if !proc_res.status.success() {
.map(|s| (&s[prefix.len()..]).to_string())
.collect();
- let expected: HashSet<String> = errors::load_errors(&testpaths.file, &props.revision)
+ let expected: HashSet<String> = errors::load_errors(&testpaths.file, None)
.iter()
.map(|e| e.msg.trim().to_string())
.collect();