about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-03-28 17:49:02 -0400
committerNiko Matsakis <niko@alum.mit.edu>2016-04-06 12:42:46 -0400
commit068142a2e6d8a72e52091ccebd3368ffaf267643 (patch)
tree0349999e2e90268f37a3ad230be511fe2280bbd9
parent3fb40c1d95dd3a14ad14d71e3ec847a0a102bd49 (diff)
downloadrust-068142a2e6d8a72e52091ccebd3368ffaf267643.tar.gz
rust-068142a2e6d8a72e52091ccebd3368ffaf267643.zip
add incremental test runner and some tests
-rw-r--r--mk/tests.mk12
-rw-r--r--src/compiletest/common.rs5
-rw-r--r--src/compiletest/compiletest.rs3
-rw-r--r--src/compiletest/runtest.rs65
-rw-r--r--src/test/incremental/dirty_clean.rs54
-rw-r--r--src/test/incremental/hello_world.rs46
-rw-r--r--src/test/incremental/string_constant.rs58
7 files changed, 240 insertions, 3 deletions
diff --git a/mk/tests.mk b/mk/tests.mk
index 1a02b5c2281..0b8f0f80dea 100644
--- a/mk/tests.mk
+++ b/mk/tests.mk
@@ -305,6 +305,7 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
 	check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \
 	check-stage$(1)-T-$(2)-H-$(3)-debuginfo-gdb-exec \
 	check-stage$(1)-T-$(2)-H-$(3)-debuginfo-lldb-exec \
+	check-stage$(1)-T-$(2)-H-$(3)-incremental-exec \
 	check-stage$(1)-T-$(2)-H-$(3)-doc-exec \
 	check-stage$(1)-T-$(2)-H-$(3)-pretty-exec
 
@@ -481,6 +482,7 @@ DEBUGINFO_LLDB_RS := $(call rwildcard,$(S)src/test/debuginfo/,*.rs)
 CODEGEN_RS := $(call rwildcard,$(S)src/test/codegen/,*.rs)
 CODEGEN_CC := $(call rwildcard,$(S)src/test/codegen/,*.cc)
 CODEGEN_UNITS_RS := $(call rwildcard,$(S)src/test/codegen-units/,*.rs)
+INCREMENTAL_RS := $(call rwildcard,$(S)src/test/incremental/,*.rs)
 RUSTDOCCK_RS := $(call rwildcard,$(S)src/test/rustdoc/,*.rs)
 
 RPASS_TESTS := $(RPASS_RS)
@@ -496,6 +498,7 @@ DEBUGINFO_GDB_TESTS := $(DEBUGINFO_GDB_RS)
 DEBUGINFO_LLDB_TESTS := $(DEBUGINFO_LLDB_RS)
 CODEGEN_TESTS := $(CODEGEN_RS) $(CODEGEN_CC)
 CODEGEN_UNITS_TESTS := $(CODEGEN_UNITS_RS)
+INCREMENTAL_TESTS := $(INCREMENTAL_RS)
 RUSTDOCCK_TESTS := $(RUSTDOCCK_RS)
 
 CTEST_SRC_BASE_rpass = run-pass
@@ -558,6 +561,11 @@ CTEST_BUILD_BASE_codegen-units = codegen-units
 CTEST_MODE_codegen-units = codegen-units
 CTEST_RUNTOOL_codegen-units = $(CTEST_RUNTOOL)
 
+CTEST_SRC_BASE_incremental = incremental
+CTEST_BUILD_BASE_incremental = incremental
+CTEST_MODE_incremental = incremental
+CTEST_RUNTOOL_incremental = $(CTEST_RUNTOOL)
+
 CTEST_SRC_BASE_rustdocck = rustdoc
 CTEST_BUILD_BASE_rustdocck = rustdoc
 CTEST_MODE_rustdocck = rustdoc
@@ -681,6 +689,7 @@ CTEST_DEPS_debuginfo-lldb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_LLDB_TESTS) \
                                                $(S)src/etc/lldb_rust_formatters.py
 CTEST_DEPS_codegen_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_TESTS)
 CTEST_DEPS_codegen-units_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_UNITS_TESTS)
+CTEST_DEPS_incremental_$(1)-T-$(2)-H-$(3) = $$(INCREMENTAL_TESTS)
 CTEST_DEPS_rustdocck_$(1)-T-$(2)-H-$(3) = $$(RUSTDOCCK_TESTS) \
 		$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
 		$(S)src/etc/htmldocck.py
@@ -747,7 +756,7 @@ endif
 endef
 
 CTEST_NAMES = rpass rpass-valgrind rpass-full rfail-full cfail-full rfail cfail pfail \
-	debuginfo-gdb debuginfo-lldb codegen codegen-units rustdocck
+	debuginfo-gdb debuginfo-lldb codegen codegen-units rustdocck incremental
 
 $(foreach host,$(CFG_HOST), \
  $(eval $(foreach target,$(CFG_TARGET), \
@@ -945,6 +954,7 @@ TEST_GROUPS = \
 	debuginfo-lldb \
 	codegen \
 	codegen-units \
+    incremental \
 	doc \
 	$(foreach docname,$(DOC_NAMES),doc-$(docname)) \
 	pretty \
diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs
index bfcc1759b95..a6960ff1785 100644
--- a/src/compiletest/common.rs
+++ b/src/compiletest/common.rs
@@ -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)
     }
 }
diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs
index 787d77bc56c..1c06b2a23d5 100644
--- a/src/compiletest/compiletest.rs
+++ b/src/compiletest/compiletest.rs
@@ -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"),
diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index 24fd413ef09..802b967ed7d 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -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");
+        }
+    }
+}
diff --git a/src/test/incremental/dirty_clean.rs b/src/test/incremental/dirty_clean.rs
new file mode 100644
index 00000000000..f0e596baa2d
--- /dev/null
+++ b/src/test/incremental/dirty_clean.rs
@@ -0,0 +1,54 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// revisions: rpass1 cfail2
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+// Sanity check for the dirty-clean system. Give the opposite
+// annotations that we expect to see, so that we check that errors are
+// reported.
+
+fn main() { }
+
+mod x {
+    #[cfg(rpass1)]
+    pub fn x() -> usize {
+        22
+    }
+
+    #[cfg(cfail2)]
+    pub fn x() -> u32 {
+        22
+    }
+}
+
+mod y {
+    use x;
+
+    #[rustc_clean(label="TypeckItemBody", cfg="cfail2")]
+    #[rustc_clean(label="TransCrateItem", cfg="cfail2")]
+    pub fn y() {
+        //[cfail2]~^ ERROR `TypeckItemBody("y::y")` not found in dep graph, but should be clean
+        //[cfail2]~| ERROR `TransCrateItem("y::y")` not found in dep graph, but should be clean
+        x::x();
+    }
+}
+
+mod z {
+    #[rustc_dirty(label="TypeckItemBody", cfg="cfail2")]
+    #[rustc_dirty(label="TransCrateItem", cfg="cfail2")]
+    pub fn z() {
+        //[cfail2]~^ ERROR `TypeckItemBody("z::z")` found in dep graph, but should be dirty
+        // FIXME(#32014) -- TransCrateItem ought to be clean, but it is in fact
+        // dirty, hence we don't see an error here.
+    }
+}
diff --git a/src/test/incremental/hello_world.rs b/src/test/incremental/hello_world.rs
new file mode 100644
index 00000000000..f98ae188bad
--- /dev/null
+++ b/src/test/incremental/hello_world.rs
@@ -0,0 +1,46 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// revisions: rpass1 rpass2
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+fn main() { }
+
+mod x {
+    #[cfg(rpass1)]
+    pub fn x() -> i32 {
+        1
+    }
+
+    #[cfg(rpass2)]
+    pub fn x() -> i32 {
+        2
+    }
+}
+
+mod y {
+    use x;
+
+    #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
+    pub fn y() {
+        x::x();
+    }
+}
+
+mod z {
+    use y;
+
+    #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
+    pub fn z() {
+        y::y();
+    }
+}
diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs
new file mode 100644
index 00000000000..1acca8b2952
--- /dev/null
+++ b/src/test/incremental/string_constant.rs
@@ -0,0 +1,58 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// revisions: rpass1 rpass2
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+// Here the only thing which changes is the string constant in `x`.
+// Therefore, the compiler deduces (correctly) that typeck is not
+// needed even for callers of `x`.
+//
+// It is not entirely clear why `TransCrateItem` invalidates `y` and
+// `z`, actually, I think it's because of the structure of
+// trans. -nmatsakis
+
+fn main() { }
+
+mod x {
+    #[cfg(rpass1)]
+    pub fn x() {
+        println!("1");
+    }
+
+    #[cfg(rpass2)]
+    #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
+    #[rustc_dirty(label="TransCrateItem", cfg="rpass2")]
+    pub fn x() {
+        println!("2");
+    }
+}
+
+mod y {
+    use x;
+
+    #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
+    #[rustc_dirty(label="TransCrateItem", cfg="rpass2")]
+    pub fn y() {
+        x::x();
+    }
+}
+
+mod z {
+    use y;
+
+    #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
+    #[rustc_dirty(label="TransCrateItem", cfg="rpass2")]
+    pub fn z() {
+        y::y();
+    }
+}