about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2016-04-29 14:23:15 -0700
committerAlex Crichton <alex@alexcrichton.com>2016-05-12 08:52:20 -0700
commitbb9062a2967a5b772788aa14f742d8927ac040ba (patch)
tree26600100ee45d6ec7c95f4961954f8b8d4f6bd89
parent8d65591cf249a64bffa14ed49cb196af4eabac3c (diff)
downloadrust-bb9062a2967a5b772788aa14f742d8927ac040ba.tar.gz
rust-bb9062a2967a5b772788aa14f742d8927ac040ba.zip
rustbuild: Add support for crate tests + doctests
This commit adds support to rustbuild to run crate unit tests (those defined by
`#[test]`) as well as documentation tests. All tests are powered by `cargo test`
under the hood.

Each step requires the `libtest` library is built for that corresponding stage.
Ideally the `test` crate would be a dev-dependency, but for now it's just easier
to ensure that we sequence everything in the right order.

Currently no filtering is implemented, so there's not actually a method of
testing *only* libstd or *only* libcore, but rather entire swaths of crates are
tested all at once.

A few points of note here are:

* The `coretest` and `collectionstest` crates are just listed as `[[test]]`
  entires for `cargo test` to naturally pick up. This mean that `cargo test -p
  core` actually runs all the tests for libcore.
* Libraries that aren't tested all mention `test = false` in their `Cargo.toml`
* Crates aren't currently allowed to have dev-dependencies due to
  rust-lang/cargo#860, but we can likely alleviate this restriction once
  workspaces are implemented.

cc #31590
-rw-r--r--src/bootstrap/build/check.rs79
-rw-r--r--src/bootstrap/build/mod.rs11
-rw-r--r--src/bootstrap/build/step.rs15
-rw-r--r--src/bootstrap/rustc.rs15
-rw-r--r--src/bootstrap/rustdoc.rs10
-rw-r--r--src/liballoc/Cargo.toml1
-rw-r--r--src/libcollections/Cargo.toml5
-rw-r--r--src/libcore/Cargo.toml4
-rw-r--r--src/libflate/lib.rs12
-rw-r--r--src/libpanic_abort/Cargo.toml1
-rw-r--r--src/libpanic_unwind/Cargo.toml1
-rw-r--r--src/librand/Cargo.toml1
-rw-r--r--src/librustc_bitflags/Cargo.toml1
-rw-r--r--src/librustc_borrowck/Cargo.toml1
-rw-r--r--src/librustc_lint/Cargo.toml1
-rw-r--r--src/librustc_resolve/Cargo.toml1
-rw-r--r--src/librustc_trans/Cargo.toml1
-rw-r--r--src/librustc_typeck/Cargo.toml1
-rw-r--r--src/libstd/Cargo.toml1
-rw-r--r--src/libunwind/Cargo.toml1
-rw-r--r--src/rustc/Cargo.toml2
-rw-r--r--src/rustc/libc_shim/Cargo.toml1
-rw-r--r--src/rustc/std_shim/Cargo.toml2
-rw-r--r--src/rustc/test_shim/Cargo.toml2
24 files changed, 147 insertions, 23 deletions
diff --git a/src/bootstrap/build/check.rs b/src/bootstrap/build/check.rs
index 0cd96881b58..f12b0dadeac 100644
--- a/src/bootstrap/build/check.rs
+++ b/src/bootstrap/build/check.rs
@@ -13,13 +13,16 @@
 //! This file implements the various regression test suites that we execute on
 //! our CI.
 
-use std::fs;
+use std::env;
+use std::fs::{self, File};
+use std::io::prelude::*;
 use std::path::{PathBuf, Path};
 use std::process::Command;
 
 use build_helper::output;
+use bootstrap::{dylib_path, dylib_path_var};
 
-use build::{Build, Compiler};
+use build::{Build, Compiler, Mode};
 
 /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
 ///
@@ -222,3 +225,75 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) {
     cmd.arg("--test-args").arg(build.flags.args.join(" "));
     build.run(&mut cmd);
 }
+
+/// Run all unit tests plus documentation tests for an entire crate DAG defined
+/// by a `Cargo.toml`
+///
+/// This is what runs tests for crates like the standard library, compiler, etc.
+/// It essentially is the driver for running `cargo test`.
+///
+/// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
+/// arguments, and those arguments are discovered from `Cargo.lock`.
+pub fn krate(build: &Build,
+             compiler: &Compiler,
+             target: &str,
+             mode: Mode) {
+    let (name, path, features) = match mode {
+        Mode::Libstd => ("libstd", "src/rustc/std_shim", build.std_features()),
+        Mode::Libtest => ("libtest", "src/rustc/test_shim", String::new()),
+        Mode::Librustc => ("librustc", "src/rustc", build.rustc_features()),
+        _ => panic!("can only test libraries"),
+    };
+    println!("Testing {} stage{} ({} -> {})", name, compiler.stage,
+             compiler.host, target);
+
+    // Build up the base `cargo test` command.
+    let mut cargo = build.cargo(compiler, mode, target, "test");
+    cargo.arg("--manifest-path")
+         .arg(build.src.join(path).join("Cargo.toml"))
+         .arg("--features").arg(features);
+
+    // Generate a list of `-p` arguments to pass to the `cargo test` invocation
+    // by crawling the corresponding Cargo.lock file.
+    let lockfile = build.src.join(path).join("Cargo.lock");
+    let mut contents = String::new();
+    t!(t!(File::open(&lockfile)).read_to_string(&mut contents));
+    let mut lines = contents.lines();
+    while let Some(line) = lines.next() {
+        let prefix = "name = \"";
+        if !line.starts_with(prefix) {
+            continue
+        }
+        lines.next(); // skip `version = ...`
+
+        // skip crates.io or otherwise non-path crates
+        if let Some(line) = lines.next() {
+            if line.starts_with("source") {
+                continue
+            }
+        }
+
+        let crate_name = &line[prefix.len()..line.len() - 1];
+
+        // Right now jemalloc is our only target-specific crate in the sense
+        // that it's not present on all platforms. Custom skip it here for now,
+        // but if we add more this probably wants to get more generalized.
+        if crate_name.contains("jemalloc") {
+            continue
+        }
+
+        cargo.arg("-p").arg(crate_name);
+    }
+
+    // The tests are going to run with the *target* libraries, so we need to
+    // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
+    //
+    // Note that to run the compiler we need to run with the *host* libraries,
+    // but our wrapper scripts arrange for that to be the case anyway.
+    let mut dylib_path = dylib_path();
+    dylib_path.insert(0, build.sysroot_libdir(compiler, target));
+    cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
+    cargo.args(&build.flags.args);
+
+    build.run(&mut cargo);
+}
diff --git a/src/bootstrap/build/mod.rs b/src/bootstrap/build/mod.rs
index b38532fb3df..44f161fb487 100644
--- a/src/bootstrap/build/mod.rs
+++ b/src/bootstrap/build/mod.rs
@@ -380,6 +380,15 @@ impl Build {
                     check::compiletest(self, &compiler, target.target,
                                        "run-make", "run-make")
                 }
+                CheckCrateStd { compiler } => {
+                    check::krate(self, &compiler, target.target, Mode::Libstd)
+                }
+                CheckCrateTest { compiler } => {
+                    check::krate(self, &compiler, target.target, Mode::Libtest)
+                }
+                CheckCrateRustc { compiler } => {
+                    check::krate(self, &compiler, target.target, Mode::Librustc)
+                }
 
                 DistDocs { stage } => dist::docs(self, stage, target.target),
                 DistMingw { _dummy } => dist::mingw(self, target.target),
@@ -485,6 +494,7 @@ impl Build {
                   self.config.rust_debug_assertions.to_string())
              .env("RUSTC_SNAPSHOT", &self.rustc)
              .env("RUSTC_SYSROOT", self.sysroot(compiler))
+             .env("RUSTC_LIBDIR", self.rustc_libdir(compiler))
              .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir())
              .env("RUSTC_RPATH", self.config.rust_rpath.to_string())
              .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc"))
@@ -520,7 +530,6 @@ impl Build {
         if self.config.rust_optimize {
             cargo.arg("--release");
         }
-        self.add_rustc_lib_path(compiler, &mut cargo);
         return cargo
     }
 
diff --git a/src/bootstrap/build/step.rs b/src/bootstrap/build/step.rs
index 4a336589b44..c494d965a19 100644
--- a/src/bootstrap/build/step.rs
+++ b/src/bootstrap/build/step.rs
@@ -120,6 +120,9 @@ macro_rules! targets {
             (check_docs, CheckDocs { compiler: Compiler<'a> }),
             (check_error_index, CheckErrorIndex { compiler: Compiler<'a> }),
             (check_rmake, CheckRMake { compiler: Compiler<'a> }),
+            (check_crate_std, CheckCrateStd { compiler: Compiler<'a> }),
+            (check_crate_test, CheckCrateTest { compiler: Compiler<'a> }),
+            (check_crate_rustc, CheckCrateRustc { compiler: Compiler<'a> }),
 
             // Distribution targets, creating tarballs
             (dist, Dist { stage: u32 }),
@@ -376,6 +379,9 @@ impl<'a> Step<'a> {
                     self.check_cfail(compiler),
                     self.check_rfail(compiler),
                     self.check_pfail(compiler),
+                    self.check_crate_std(compiler),
+                    self.check_crate_test(compiler),
+                    self.check_crate_rustc(compiler),
                     self.check_codegen(compiler),
                     self.check_codegen_units(compiler),
                     self.check_debuginfo(compiler),
@@ -437,6 +443,15 @@ impl<'a> Step<'a> {
             Source::CheckErrorIndex { compiler } => {
                 vec![self.libstd(compiler), self.tool_error_index(compiler.stage)]
             }
+            Source::CheckCrateStd { compiler } => {
+                vec![self.libtest(compiler)]
+            }
+            Source::CheckCrateTest { compiler } => {
+                vec![self.libtest(compiler)]
+            }
+            Source::CheckCrateRustc { compiler } => {
+                vec![self.libtest(compiler)]
+            }
 
             Source::ToolLinkchecker { stage } |
             Source::ToolTidy { stage } => {
diff --git a/src/bootstrap/rustc.rs b/src/bootstrap/rustc.rs
index 046bc34438c..97decedf91d 100644
--- a/src/bootstrap/rustc.rs
+++ b/src/bootstrap/rustc.rs
@@ -29,6 +29,7 @@ extern crate bootstrap;
 
 use std::env;
 use std::ffi::OsString;
+use std::path::PathBuf;
 use std::process::Command;
 
 fn main() {
@@ -43,16 +44,22 @@ fn main() {
     // have the standard library built yet and may not be able to produce an
     // executable. Otherwise we just use the standard compiler we're
     // bootstrapping with.
-    let rustc = if target.is_none() {
-        env::var_os("RUSTC_SNAPSHOT").unwrap()
+    let (rustc, libdir) = if target.is_none() {
+        ("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR")
     } else {
-        env::var_os("RUSTC_REAL").unwrap()
+        ("RUSTC_REAL", "RUSTC_LIBDIR")
     };
     let stage = env::var("RUSTC_STAGE").unwrap();
 
+    let rustc = env::var_os(rustc).unwrap();
+    let libdir = env::var_os(libdir).unwrap();
+    let mut dylib_path = bootstrap::dylib_path();
+    dylib_path.insert(0, PathBuf::from(libdir));
+
     let mut cmd = Command::new(rustc);
     cmd.args(&args)
-       .arg("--cfg").arg(format!("stage{}", stage));
+       .arg("--cfg").arg(format!("stage{}", stage))
+       .env(bootstrap::dylib_path_var(), env::join_paths(&dylib_path).unwrap());
 
     if let Some(target) = target {
         // The stage0 compiler has a special sysroot distinct from what we
diff --git a/src/bootstrap/rustdoc.rs b/src/bootstrap/rustdoc.rs
index 8c618196113..88ac26d32f6 100644
--- a/src/bootstrap/rustdoc.rs
+++ b/src/bootstrap/rustdoc.rs
@@ -12,17 +12,25 @@
 //!
 //! See comments in `src/bootstrap/rustc.rs` for more information.
 
+extern crate bootstrap;
+
 use std::env;
 use std::process::Command;
+use std::path::PathBuf;
 
 fn main() {
     let args = env::args_os().skip(1).collect::<Vec<_>>();
     let rustdoc = env::var_os("RUSTDOC_REAL").unwrap();
+    let libdir = env::var_os("RUSTC_LIBDIR").unwrap();
+
+    let mut dylib_path = bootstrap::dylib_path();
+    dylib_path.insert(0, PathBuf::from(libdir));
 
     let mut cmd = Command::new(rustdoc);
     cmd.args(&args)
        .arg("--cfg").arg(format!("stage{}", env::var("RUSTC_STAGE").unwrap()))
-       .arg("--cfg").arg("dox");
+       .arg("--cfg").arg("dox")
+       .env(bootstrap::dylib_path_var(), env::join_paths(&dylib_path).unwrap());
     std::process::exit(match cmd.status() {
         Ok(s) => s.code().unwrap_or(1),
         Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml
index 5da0f1a10b9..0889ca9fc84 100644
--- a/src/liballoc/Cargo.toml
+++ b/src/liballoc/Cargo.toml
@@ -6,7 +6,6 @@ version = "0.0.0"
 [lib]
 name = "alloc"
 path = "lib.rs"
-test = false
 
 [dependencies]
 core = { path = "../libcore" }
diff --git a/src/libcollections/Cargo.toml b/src/libcollections/Cargo.toml
index 18e322ff74f..65d456e750f 100644
--- a/src/libcollections/Cargo.toml
+++ b/src/libcollections/Cargo.toml
@@ -6,9 +6,12 @@ version = "0.0.0"
 [lib]
 name = "collections"
 path = "lib.rs"
-test = false
 
 [dependencies]
 alloc = { path = "../liballoc" }
 core = { path = "../libcore" }
 rustc_unicode = { path = "../librustc_unicode" }
+
+[[test]]
+name = "collectionstest"
+path = "../libcollectionstest/lib.rs"
diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml
index 98f941f0057..02fe574b81e 100644
--- a/src/libcore/Cargo.toml
+++ b/src/libcore/Cargo.toml
@@ -8,3 +8,7 @@ build = "build.rs"
 name = "core"
 path = "lib.rs"
 test = false
+
+[[test]]
+name = "coretest"
+path = "../libcoretest/lib.rs"
diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs
index 1cc008c5ee9..b578b064d67 100644
--- a/src/libflate/lib.rs
+++ b/src/libflate/lib.rs
@@ -27,11 +27,7 @@
 #![feature(libc)]
 #![feature(staged_api)]
 #![feature(unique)]
-#![cfg_attr(test, feature(rustc_private, rand))]
-
-#[cfg(test)]
-#[macro_use]
-extern crate log;
+#![cfg_attr(test, feature(rand))]
 
 extern crate libc;
 
@@ -175,14 +171,8 @@ mod tests {
             for _ in 0..2000 {
                 input.extend_from_slice(r.choose(&words).unwrap());
             }
-            debug!("de/inflate of {} bytes of random word-sequences",
-                   input.len());
             let cmp = deflate_bytes(&input);
             let out = inflate_bytes(&cmp).unwrap();
-            debug!("{} bytes deflated to {} ({:.1}% size)",
-                   input.len(),
-                   cmp.len(),
-                   100.0 * ((cmp.len() as f64) / (input.len() as f64)));
             assert_eq!(&*input, &*out);
         }
     }
diff --git a/src/libpanic_abort/Cargo.toml b/src/libpanic_abort/Cargo.toml
index a7905703f59..9d62be64fc4 100644
--- a/src/libpanic_abort/Cargo.toml
+++ b/src/libpanic_abort/Cargo.toml
@@ -5,6 +5,7 @@ version = "0.0.0"
 
 [lib]
 path = "lib.rs"
+test = false
 
 [dependencies]
 core = { path = "../libcore" }
diff --git a/src/libpanic_unwind/Cargo.toml b/src/libpanic_unwind/Cargo.toml
index 27edecd6f96..18f37a8bb17 100644
--- a/src/libpanic_unwind/Cargo.toml
+++ b/src/libpanic_unwind/Cargo.toml
@@ -5,6 +5,7 @@ version = "0.0.0"
 
 [lib]
 path = "lib.rs"
+test = false
 
 [dependencies]
 alloc = { path = "../liballoc" }
diff --git a/src/librand/Cargo.toml b/src/librand/Cargo.toml
index 784654c0859..86b061db054 100644
--- a/src/librand/Cargo.toml
+++ b/src/librand/Cargo.toml
@@ -6,7 +6,6 @@ version = "0.0.0"
 [lib]
 name = "rand"
 path = "lib.rs"
-test = false
 
 [dependencies]
 core = { path = "../libcore" }
diff --git a/src/librustc_bitflags/Cargo.toml b/src/librustc_bitflags/Cargo.toml
index 926ed5960d6..d1e66dcf935 100644
--- a/src/librustc_bitflags/Cargo.toml
+++ b/src/librustc_bitflags/Cargo.toml
@@ -7,3 +7,4 @@ version = "0.0.0"
 name = "rustc_bitflags"
 path = "lib.rs"
 test = false
+doctest = false
diff --git a/src/librustc_borrowck/Cargo.toml b/src/librustc_borrowck/Cargo.toml
index 6da87f97fb7..fbc267aaa6a 100644
--- a/src/librustc_borrowck/Cargo.toml
+++ b/src/librustc_borrowck/Cargo.toml
@@ -7,6 +7,7 @@ version = "0.0.0"
 name = "rustc_borrowck"
 path = "lib.rs"
 crate-type = ["dylib"]
+test = false
 
 [dependencies]
 log = { path = "../liblog" }
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
index 3f0cd397e76..7674cc529be 100644
--- a/src/librustc_lint/Cargo.toml
+++ b/src/librustc_lint/Cargo.toml
@@ -7,6 +7,7 @@ version = "0.0.0"
 name = "rustc_lint"
 path = "lib.rs"
 crate-type = ["dylib"]
+test = false
 
 [dependencies]
 log = { path = "../liblog" }
diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml
index 217445715a8..a63460d912d 100644
--- a/src/librustc_resolve/Cargo.toml
+++ b/src/librustc_resolve/Cargo.toml
@@ -7,6 +7,7 @@ version = "0.0.0"
 name = "rustc_resolve"
 path = "lib.rs"
 crate-type = ["dylib"]
+test = false
 
 [dependencies]
 log = { path = "../liblog" }
diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml
index ccb430fbb78..9a0580472b4 100644
--- a/src/librustc_trans/Cargo.toml
+++ b/src/librustc_trans/Cargo.toml
@@ -7,6 +7,7 @@ version = "0.0.0"
 name = "rustc_trans"
 path = "lib.rs"
 crate-type = ["dylib"]
+test = false
 
 [dependencies]
 arena = { path = "../libarena" }
diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml
index e9dabf16eae..a0c4c7534fa 100644
--- a/src/librustc_typeck/Cargo.toml
+++ b/src/librustc_typeck/Cargo.toml
@@ -7,6 +7,7 @@ version = "0.0.0"
 name = "rustc_typeck"
 path = "lib.rs"
 crate-type = ["dylib"]
+test = false
 
 [dependencies]
 log = { path = "../liblog" }
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 6d33fb311cf..eded6e24f3e 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -8,7 +8,6 @@ build = "build.rs"
 name = "std"
 path = "lib.rs"
 crate-type = ["dylib", "rlib"]
-test = false
 
 [dependencies]
 alloc = { path = "../liballoc" }
diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml
index dca222c49d0..b537c6b1b71 100644
--- a/src/libunwind/Cargo.toml
+++ b/src/libunwind/Cargo.toml
@@ -7,6 +7,7 @@ build = "build.rs"
 [lib]
 name = "unwind"
 path = "lib.rs"
+test = false
 
 [dependencies]
 core = { path = "../libcore" }
diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml
index 7431c35efba..24499cb8f08 100644
--- a/src/rustc/Cargo.toml
+++ b/src/rustc/Cargo.toml
@@ -13,6 +13,8 @@ path = "rustdoc.rs"
 
 [profile.release]
 opt-level = 2
+[profile.bench]
+opt-level = 2
 
 # These options are controlled from our rustc wrapper script, so turn them off
 # here and have them controlled elsewhere.
diff --git a/src/rustc/libc_shim/Cargo.toml b/src/rustc/libc_shim/Cargo.toml
index a7860b50e08..8fc713e0f1b 100644
--- a/src/rustc/libc_shim/Cargo.toml
+++ b/src/rustc/libc_shim/Cargo.toml
@@ -15,6 +15,7 @@ build = "build.rs"
 [lib]
 name = "libc"
 path = "../../liblibc/src/lib.rs"
+test = false
 
 [dependencies]
 core = { path = "../../libcore" }
diff --git a/src/rustc/std_shim/Cargo.toml b/src/rustc/std_shim/Cargo.toml
index 1ce3937157d..5602ef866b8 100644
--- a/src/rustc/std_shim/Cargo.toml
+++ b/src/rustc/std_shim/Cargo.toml
@@ -30,6 +30,8 @@ path = "lib.rs"
 
 [profile.release]
 opt-level = 2
+[profile.bench]
+opt-level = 2
 
 # These options are controlled from our rustc wrapper script, so turn them off
 # here and have them controlled elsewhere.
diff --git a/src/rustc/test_shim/Cargo.toml b/src/rustc/test_shim/Cargo.toml
index bf576650486..87f2ccd51e8 100644
--- a/src/rustc/test_shim/Cargo.toml
+++ b/src/rustc/test_shim/Cargo.toml
@@ -14,6 +14,8 @@ path = "lib.rs"
 
 [profile.release]
 opt-level = 2
+[profile.bench]
+opt-level = 2
 
 # These options are controlled from our rustc wrapper script, so turn them off
 # here and have them controlled elsewhere.