about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorEric Huss <eric@huss.org>2021-09-19 09:57:19 -0700
committerEric Huss <eric@huss.org>2021-09-23 12:16:51 -0700
commit2da6e669488791bd2d36e3a35fa2e4e4e02bc647 (patch)
tree145f1558d3635ac1ba881285f3339d0f737dcd3a /src/tools
parent0132f8258ae0fbc4f2b461b28d510222d22aa979 (diff)
downloadrust-2da6e669488791bd2d36e3a35fa2e4e4e02bc647.tar.gz
rust-2da6e669488791bd2d36e3a35fa2e4e4e02bc647.zip
Support incremental in compiletest for non-incremental modes.
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/compiletest/src/common.rs6
-rw-r--r--src/tools/compiletest/src/header.rs28
-rw-r--r--src/tools/compiletest/src/runtest.rs54
3 files changed, 56 insertions, 32 deletions
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 99b0a3454e8..cd0a56d08d8 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -459,3 +459,9 @@ pub fn output_base_dir(config: &Config, testpaths: &TestPaths, revision: Option<
 pub fn output_base_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
     output_base_dir(config, testpaths, revision).join(testpaths.file.file_stem().unwrap())
 }
+
+/// Absolute path to the directory to use for incremental compilation. Example:
+///   /path/to/build/host-triple/test/ui/relative/testname.mode/testname.inc
+pub fn incremental_dir(config: &Config, testpaths: &TestPaths) -> PathBuf {
+    output_base_name(config, testpaths, None).with_extension("inc")
+}
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 28089e85b55..efd85502799 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -113,6 +113,21 @@ pub struct TestProps {
     // testing harness and used when generating compilation
     // arguments. (In particular, it propagates to the aux-builds.)
     pub incremental_dir: Option<PathBuf>,
+    // If `true`, this test will use incremental compilation.
+    //
+    // This can be set manually with the `incremental` header, or implicitly
+    // by being a part of an incremental mode test. Using the `incremental`
+    // header should be avoided if possible; using an incremental mode test is
+    // preferred. Incremental mode tests support multiple passes, which can
+    // verify that the incremental cache can be loaded properly after being
+    // created. Just setting the header will only verify the behavior with
+    // creating an incremental cache, but doesn't check that it is created
+    // correctly.
+    //
+    // Compiletest will create the incremental directory, and ensure it is
+    // empty before the test starts. Incremental mode tests will reuse the
+    // incremental directory between passes in the same test.
+    pub incremental: bool,
     // How far should the test proceed while still passing.
     pass_mode: Option<PassMode>,
     // Ignore `--pass` overrides from the command line for this test.
@@ -163,6 +178,7 @@ impl TestProps {
             pretty_compare_only: false,
             forbid_output: vec![],
             incremental_dir: None,
+            incremental: false,
             pass_mode: None,
             fail_mode: None,
             ignore_pass: false,
@@ -350,6 +366,10 @@ impl TestProps {
                 if !self.stderr_per_bitwidth {
                     self.stderr_per_bitwidth = config.parse_stderr_per_bitwidth(ln);
                 }
+
+                if !self.incremental {
+                    self.incremental = config.parse_incremental(ln);
+                }
             });
         }
 
@@ -360,6 +380,10 @@ impl TestProps {
             self.failure_status = 101;
         }
 
+        if config.mode == Mode::Incremental {
+            self.incremental = true;
+        }
+
         for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
             if let Ok(val) = env::var(key) {
                 if self.exec_env.iter().find(|&&(ref x, _)| x == key).is_none() {
@@ -731,6 +755,10 @@ impl Config {
     fn parse_edition(&self, line: &str) -> Option<String> {
         self.parse_name_value_directive(line, "edition")
     }
+
+    fn parse_incremental(&self, line: &str) -> bool {
+        self.parse_name_directive(line, "incremental")
+    }
 }
 
 fn expand_variables(mut value: String, config: &Config) -> String {
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 51a4d74109a..2a4bb9eb88b 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1,7 +1,7 @@
 // ignore-tidy-filelength
 
 use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT};
-use crate::common::{output_base_dir, output_base_name, output_testname_unique};
+use crate::common::{incremental_dir, output_base_dir, output_base_name, output_testname_unique};
 use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJson, Ui};
 use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc};
 use crate::common::{CompareMode, FailMode, PassMode};
@@ -229,18 +229,24 @@ pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) {
         print!("\n\n");
     }
     debug!("running {:?}", testpaths.file.display());
-    let props = TestProps::from_file(&testpaths.file, revision, &config);
+    let mut props = TestProps::from_file(&testpaths.file, revision, &config);
+    if props.incremental {
+        props.incremental_dir = Some(incremental_dir(&config, testpaths));
+    }
 
     let cx = TestCx { config: &config, props: &props, testpaths, revision };
     create_dir_all(&cx.output_base_dir()).unwrap();
+    if props.incremental {
+        cx.init_incremental_test();
+    }
 
     if config.mode == Incremental {
         // Incremental tests are special because they cannot be run in
         // parallel.
         assert!(!props.revisions.is_empty(), "Incremental tests require revisions.");
-        cx.init_incremental_test();
         for revision in &props.revisions {
-            let revision_props = TestProps::from_file(&testpaths.file, Some(revision), &config);
+            let mut revision_props = TestProps::from_file(&testpaths.file, Some(revision), &config);
+            revision_props.incremental_dir = props.incremental_dir.clone();
             let rev_cx = TestCx {
                 config: &config,
                 props: &revision_props,
@@ -2937,7 +2943,7 @@ impl<'test> TestCx<'test> {
         // incremental workproduct directory.  Delete any old
         // incremental work products that may be there from prior
         // runs.
-        let incremental_dir = self.incremental_dir();
+        let incremental_dir = self.props.incremental_dir.as_ref().unwrap();
         if incremental_dir.exists() {
             // Canonicalizing the path will convert it to the //?/ format
             // on Windows, which enables paths longer than 260 character
@@ -2947,7 +2953,7 @@ impl<'test> TestCx<'test> {
         fs::create_dir_all(&incremental_dir).unwrap();
 
         if self.config.verbose {
-            print!("init_incremental_test: incremental_dir={}", incremental_dir.display());
+            println!("init_incremental_test: incremental_dir={}", incremental_dir.display());
         }
     }
 
@@ -2974,46 +2980,30 @@ impl<'test> TestCx<'test> {
         let revision = self.revision.expect("incremental tests require a list of revisions");
 
         // Incremental workproduct directory should have already been created.
-        let incremental_dir = self.incremental_dir();
+        let incremental_dir = self.props.incremental_dir.as_ref().unwrap();
         assert!(incremental_dir.exists(), "init_incremental_test failed to create incremental dir");
 
-        // Add an extra flag pointing at the incremental directory.
-        let mut revision_props = self.props.clone();
-        revision_props.incremental_dir = Some(incremental_dir);
-
-        let revision_cx = TestCx {
-            config: self.config,
-            props: &revision_props,
-            testpaths: self.testpaths,
-            revision: self.revision,
-        };
-
         if self.config.verbose {
-            print!("revision={:?} revision_props={:#?}", revision, revision_props);
+            print!("revision={:?} props={:#?}", revision, self.props);
         }
 
         if revision.starts_with("rpass") {
-            if revision_cx.props.should_ice {
-                revision_cx.fatal("can only use should-ice in cfail tests");
+            if self.props.should_ice {
+                self.fatal("can only use should-ice in cfail tests");
             }
-            revision_cx.run_rpass_test();
+            self.run_rpass_test();
         } else if revision.starts_with("rfail") {
-            if revision_cx.props.should_ice {
-                revision_cx.fatal("can only use should-ice in cfail tests");
+            if self.props.should_ice {
+                self.fatal("can only use should-ice in cfail tests");
             }
-            revision_cx.run_rfail_test();
+            self.run_rfail_test();
         } else if revision.starts_with("cfail") {
-            revision_cx.run_cfail_test();
+            self.run_cfail_test();
         } else {
-            revision_cx.fatal("revision name must begin with rpass, rfail, or cfail");
+            self.fatal("revision name must begin with rpass, rfail, or cfail");
         }
     }
 
-    /// Directory where incremental work products are stored.
-    fn incremental_dir(&self) -> PathBuf {
-        self.output_base_name().with_extension("inc")
-    }
-
     fn run_rmake_test(&self) {
         let cwd = env::current_dir().unwrap();
         let src_root = self.config.src_base.parent().unwrap().parent().unwrap().parent().unwrap();