about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2017-01-31 19:16:45 -0800
committerAlex Crichton <alex@alexcrichton.com>2017-02-06 08:44:27 -0800
commitc8e0d04878f38e8a91e7a6196fb18878da208887 (patch)
tree933bbae1638331b46e873288abbdabeea23a8940 /src/tools
parent9ad13c8d0204fb7cd9a3988a5a73f60efce39481 (diff)
downloadrust-c8e0d04878f38e8a91e7a6196fb18878da208887.tar.gz
rust-c8e0d04878f38e8a91e7a6196fb18878da208887.zip
compiletest: Add caching of test results
Don't re-run tests in compiletest if all the inputs haven't changed, manage
stamp files in the output directory.
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/compiletest/Cargo.toml1
-rw-r--r--src/tools/compiletest/src/header.rs6
-rw-r--r--src/tools/compiletest/src/main.rs40
-rw-r--r--src/tools/compiletest/src/runtest.rs2
4 files changed, 48 insertions, 1 deletions
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 3049875e86e..1fc98a78a7c 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -7,3 +7,4 @@ version = "0.0.0"
 log = "0.3"
 env_logger = { version = "0.3.5", default-features = false }
 rustc-serialize = "0.3"
+filetime = "0.1"
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 71d8d62c75b..522cd222c26 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -25,6 +25,7 @@ use extract_gdb_version;
 pub struct EarlyProps {
     pub ignore: bool,
     pub should_fail: bool,
+    pub aux: Vec<String>,
 }
 
 impl EarlyProps {
@@ -32,6 +33,7 @@ impl EarlyProps {
         let mut props = EarlyProps {
             ignore: false,
             should_fail: false,
+            aux: Vec::new(),
         };
 
         iter_header(testfile,
@@ -50,6 +52,10 @@ impl EarlyProps {
                 ignore_lldb(config, ln) ||
                 ignore_llvm(config, ln);
 
+            if let Some(s) = parse_aux_build(ln) {
+                props.aux.push(s);
+            }
+
             props.should_fail = props.should_fail || parse_name_directive(ln, "should-fail");
         });
 
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index c2997c8c160..6c63661d7fb 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -25,6 +25,7 @@ extern crate rustc_serialize;
 #[macro_use]
 extern crate log;
 extern crate env_logger;
+extern crate filetime;
 
 use std::env;
 use std::ffi::OsString;
@@ -32,6 +33,7 @@ use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
 use std::process::Command;
+use filetime::FileTime;
 use getopts::{optopt, optflag, reqopt};
 use common::Config;
 use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Mode};
@@ -457,7 +459,7 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn
     };
 
     // Debugging emscripten code doesn't make sense today
-    let mut ignore = early_props.ignore;
+    let mut ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props);
     if (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) &&
         config.target.contains("emscripten") {
         ignore = true;
@@ -473,6 +475,42 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn
     }
 }
 
+fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf {
+    let stamp_name = format!("{}-H-{}-T-{}-S-{}.stamp",
+                             testpaths.file.file_name().unwrap()
+                                           .to_str().unwrap(),
+                             config.host,
+                             config.target,
+                             config.stage_id);
+    config.build_base.canonicalize()
+          .unwrap_or(config.build_base.clone())
+          .join(stamp_name)
+}
+
+fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> bool {
+    let stamp = mtime(&stamp(config, testpaths));
+    let mut inputs = vec![
+        mtime(&testpaths.file),
+        mtime(&config.rustc_path),
+    ];
+    for aux in props.aux.iter() {
+        inputs.push(mtime(&testpaths.file.parent().unwrap()
+                                         .join("auxiliary")
+                                         .join(aux)));
+    }
+    for lib in config.run_lib_path.read_dir().unwrap() {
+        let lib = lib.unwrap();
+        inputs.push(mtime(&lib.path()));
+    }
+    inputs.iter().any(|input| *input > stamp)
+}
+
+fn mtime(path: &Path) -> FileTime {
+    fs::metadata(path).map(|f| {
+        FileTime::from_last_modification_time(&f)
+    }).unwrap_or(FileTime::zero())
+}
+
 pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName {
     // Convert a complete path to something like
     //
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index a8c46722e16..10d5f0d979f 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -80,6 +80,8 @@ pub fn run(config: Config, testpaths: &TestPaths) {
     }
 
     base_cx.complete_all();
+
+    File::create(::stamp(&config, &testpaths)).unwrap();
 }
 
 struct TestCx<'test> {