Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustbuild: Add support for crate tests + doctests #33282

Merged
merged 2 commits into from
May 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 77 additions & 2 deletions src/bootstrap/build/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fairly ugly function. Why search the dag like this and run cargo with a bunch of -p flags instead of calling cargo test on every individual crate?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running cargo test with a bunch of -p flags gives us the ability to compile all the crate tests in parallel (but run them sequentially). Ideally this'd just be cargo test --all, but unfortunately that's not implemented yet :(

Running cargo test on each individual crate would work, but we'd still have to discover the list of crates somewhere and we unfortunately wouldn't get the same parallelism :(

11 changes: 10 additions & 1 deletion src/bootstrap/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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"))
Expand Down Expand Up @@ -520,7 +530,6 @@ impl Build {
if self.config.rust_optimize {
cargo.arg("--release");
}
self.add_rustc_lib_path(compiler, &mut cargo);
return cargo
}

Expand Down
15 changes: 15 additions & 0 deletions src/bootstrap/build/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }),
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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 } => {
Expand Down
15 changes: 11 additions & 4 deletions src/bootstrap/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extern crate bootstrap;

use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use std::process::Command;

fn main() {
Expand All @@ -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
Expand Down
10 changes: 9 additions & 1 deletion src/bootstrap/rustdoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
1 change: 0 additions & 1 deletion src/liballoc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ version = "0.0.0"
[lib]
name = "alloc"
path = "lib.rs"
test = false

[dependencies]
core = { path = "../libcore" }
16 changes: 16 additions & 0 deletions src/liballoc_jemalloc/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(warnings)]

extern crate build_helper;
extern crate gcc;

Expand All @@ -18,6 +20,7 @@ use build_helper::run;

fn main() {
println!("cargo:rustc-cfg=cargobuild");
println!("cargo:rerun-if-changed=build.rs");

let target = env::var("TARGET").unwrap();
let host = env::var("HOST").unwrap();
Expand All @@ -40,6 +43,19 @@ fn main() {
let cflags = compiler.args().iter().map(|s| s.to_str().unwrap())
.collect::<Vec<_>>().join(" ");

let mut stack = src_dir.join("../jemalloc")
.read_dir().unwrap()
.map(|e| e.unwrap())
.collect::<Vec<_>>();
while let Some(entry) = stack.pop() {
let path = entry.path();
if entry.file_type().unwrap().is_dir() {
stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
} else {
println!("cargo:rerun-if-changed={}", path.display());
}
}

let mut cmd = Command::new("sh");
cmd.arg(src_dir.join("../jemalloc/configure").to_str().unwrap()
.replace("C:\\", "/c/")
Expand Down
5 changes: 4 additions & 1 deletion src/libcollections/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
4 changes: 4 additions & 0 deletions src/libcore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ build = "build.rs"
name = "core"
path = "lib.rs"
test = false

[[test]]
name = "coretest"
path = "../libcoretest/lib.rs"
3 changes: 3 additions & 0 deletions src/libcore/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(warnings)]

fn main() {
// Remove this whenever snapshots and rustbuild nightlies are synced.
println!("cargo:rustc-cfg=cargobuild");
println!("cargo:rerun-if-changed=build.rs")
}
12 changes: 1 addition & 11 deletions src/libflate/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/libpanic_abort/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ version = "0.0.0"

[lib]
path = "lib.rs"
test = false

[dependencies]
core = { path = "../libcore" }
Expand Down
1 change: 1 addition & 0 deletions src/libpanic_unwind/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ version = "0.0.0"

[lib]
path = "lib.rs"
test = false

[dependencies]
alloc = { path = "../liballoc" }
Expand Down
1 change: 0 additions & 1 deletion src/librand/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ version = "0.0.0"
[lib]
name = "rand"
path = "lib.rs"
test = false

[dependencies]
core = { path = "../libcore" }
1 change: 1 addition & 0 deletions src/librustc_bitflags/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ version = "0.0.0"
name = "rustc_bitflags"
path = "lib.rs"
test = false
doctest = false
1 change: 1 addition & 0 deletions src/librustc_borrowck/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ version = "0.0.0"
name = "rustc_borrowck"
path = "lib.rs"
crate-type = ["dylib"]
test = false

[dependencies]
log = { path = "../liblog" }
Expand Down
1 change: 1 addition & 0 deletions src/librustc_lint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ version = "0.0.0"
name = "rustc_lint"
path = "lib.rs"
crate-type = ["dylib"]
test = false

[dependencies]
log = { path = "../liblog" }
Expand Down
1 change: 1 addition & 0 deletions src/librustc_resolve/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ version = "0.0.0"
name = "rustc_resolve"
path = "lib.rs"
crate-type = ["dylib"]
test = false

[dependencies]
log = { path = "../liblog" }
Expand Down
1 change: 1 addition & 0 deletions src/librustc_trans/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ version = "0.0.0"
name = "rustc_trans"
path = "lib.rs"
crate-type = ["dylib"]
test = false

[dependencies]
arena = { path = "../libarena" }
Expand Down
1 change: 1 addition & 0 deletions src/librustc_typeck/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ version = "0.0.0"
name = "rustc_typeck"
path = "lib.rs"
crate-type = ["dylib"]
test = false

[dependencies]
log = { path = "../liblog" }
Expand Down
Loading