//! This file implements the various regression test suites that we execute on
//! our CI.
-extern crate build_helper;
-
use std::collections::HashSet;
use std::env;
+use std::ffi::OsString;
+use std::iter;
use std::fmt;
use std::fs::{self, File};
use std::path::{PathBuf, Path};
use std::process::Command;
use std::io::Read;
-use build_helper::output;
+use build_helper::{self, output};
use {Build, Compiler, Mode};
use dist;
use util::{self, dylib_path, dylib_path_var, exe};
-const ADB_TEST_DIR: &'static str = "/data/tmp/work";
+const ADB_TEST_DIR: &str = "/data/tmp/work";
/// The two modes of the test runner; tests or benchmarks.
#[derive(Copy, Clone)]
}
fn try_run(build: &Build, cmd: &mut Command) {
- if build.flags.cmd.no_fail_fast() {
+ if !build.fail_fast {
if !build.try_run(cmd) {
let failures = build.delayed_failures.get();
build.delayed_failures.set(failures + 1);
}
fn try_run_quiet(build: &Build, cmd: &mut Command) {
- if build.flags.cmd.no_fail_fast() {
+ if !build.fail_fast {
if !build.try_run_quiet(cmd) {
let failures = build.delayed_failures.get();
build.delayed_failures.set(failures + 1);
}
}
+// rules.test("check-linkchecker", "src/tools/linkchecker")
+// .dep(|s| s.name("tool-linkchecker").stage(0))
+// .dep(|s| s.name("default:doc"))
+// .default(build.config.docs)
+// .host(true)
+// .run(move |s| check::linkcheck(build, s.target));
/// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
///
/// This tool in `src/tools` will verify the validity of all our links in the
.arg(build.out.join(host).join("doc")));
}
+// rules.test("check-cargotest", "src/tools/cargotest")
+// .dep(|s| s.name("tool-cargotest").stage(0))
+// .dep(|s| s.name("librustc"))
+// .host(true)
+// .run(move |s| check::cargotest(build, s.stage, s.target));
/// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler.
///
/// This tool in `src/tools` will check out a few Rust projects and run `cargo
/// test` to ensure that we don't regress the test suites there.
pub fn cargotest(build: &Build, stage: u32, host: &str) {
- let ref compiler = Compiler::new(stage, host);
+ let compiler = Compiler::new(stage, host);
// Note that this is a short, cryptic, and not scoped directory name. This
// is currently to minimize the length of path on Windows where we otherwise
let _time = util::timeit();
let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest"));
- build.prepare_tool_cmd(compiler, &mut cmd);
- try_run(build, cmd.arg(&build.cargo)
+ build.prepare_tool_cmd(&compiler, &mut cmd);
+ try_run(build, cmd.arg(&build.initial_cargo)
.arg(&out_dir)
- .env("RUSTC", build.compiler_path(compiler))
- .env("RUSTDOC", build.rustdoc(compiler)));
+ .env("RUSTC", build.compiler_path(&compiler))
+ .env("RUSTDOC", build.rustdoc(&compiler)));
}
+//rules.test("check-cargo", "cargo")
+// .dep(|s| s.name("tool-cargo"))
+// .host(true)
+// .run(move |s| check::cargo(build, s.stage, s.target));
/// Runs `cargo test` for `cargo` packaged with Rust.
pub fn cargo(build: &Build, stage: u32, host: &str) {
- let ref compiler = Compiler::new(stage, host);
-
- // Configure PATH to find the right rustc. NB. we have to use PATH
- // and not RUSTC because the Cargo test suite has tests that will
- // fail if rustc is not spelled `rustc`.
- let path = build.sysroot(compiler).join("bin");
- let old_path = ::std::env::var("PATH").expect("");
- let sep = if cfg!(windows) { ";" } else {":" };
- let ref newpath = format!("{}{}{}", path.display(), sep, old_path);
+ let compiler = &Compiler::new(stage, host);
let mut cargo = build.cargo(compiler, Mode::Tool, host, "test");
cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml"));
- if build.flags.cmd.no_fail_fast() {
+ if !build.fail_fast {
cargo.arg("--no-fail-fast");
}
// available.
cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
- try_run(build, cargo.env("PATH", newpath));
+ try_run(build, cargo.env("PATH", &path_for_cargo(build, compiler)));
+}
+
+/// Runs `cargo test` for the rls.
+pub fn rls(build: &Build, stage: u32, host: &str) {
+ let compiler = &Compiler::new(stage, host);
+
+ let mut cargo = build.cargo(compiler, Mode::Tool, host, "test");
+ cargo.arg("--manifest-path").arg(build.src.join("src/tools/rls/Cargo.toml"));
+
+ // Don't build tests dynamically, just a pain to work with
+ cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
+
+ build.add_rustc_lib_path(compiler, &mut cargo);
+
+ try_run(build, &mut cargo);
}
+fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString {
+ // Configure PATH to find the right rustc. NB. we have to use PATH
+ // and not RUSTC because the Cargo test suite has tests that will
+ // fail if rustc is not spelled `rustc`.
+ let path = build.sysroot(compiler).join("bin");
+ let old_path = env::var_os("PATH").unwrap_or_default();
+ env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
+}
+
+//rules.test("check-tidy", "src/tools/tidy")
+// .dep(|s| s.name("tool-tidy").stage(0))
+// .default(true)
+// .host(true)
+// .only_build(true)
+// .run(move |s| check::tidy(build, s.target));
/// Runs the `tidy` tool as compiled in `stage` by the `host` compiler.
///
/// This tool in `src/tools` checks up on various bits and pieces of style and
build.out.join(host).join("test")
}
+// // ========================================================================
+// // Test targets
+// //
+// // Various unit tests and tests suites we can run
+// {
+// let mut suite = |name, path, mode, dir| {
+// rules.test(name, path)
+// .dep(|s| s.name("libtest"))
+// .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
+// .dep(|s| s.name("test-helpers"))
+// .dep(|s| s.name("remote-copy-libs"))
+// .default(mode != "pretty") // pretty tests don't run everywhere
+// .run(move |s| {
+// check::compiletest(build, &s.compiler(), s.target, mode, dir)
+// });
+// };
+//
+// suite("check-ui", "src/test/ui", "ui", "ui");
+// suite("check-rpass", "src/test/run-pass", "run-pass", "run-pass");
+// suite("check-cfail", "src/test/compile-fail", "compile-fail", "compile-fail");
+// suite("check-pfail", "src/test/parse-fail", "parse-fail", "parse-fail");
+// suite("check-rfail", "src/test/run-fail", "run-fail", "run-fail");
+// suite("check-rpass-valgrind", "src/test/run-pass-valgrind",
+// "run-pass-valgrind", "run-pass-valgrind");
+// suite("check-mir-opt", "src/test/mir-opt", "mir-opt", "mir-opt");
+// if build.config.codegen_tests {
+// suite("check-codegen", "src/test/codegen", "codegen", "codegen");
+// }
+// suite("check-codegen-units", "src/test/codegen-units", "codegen-units",
+// "codegen-units");
+// suite("check-incremental", "src/test/incremental", "incremental",
+// "incremental");
+// }
+//
+// if build.build.contains("msvc") {
+// // nothing to do for debuginfo tests
+// } else {
+// rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb")
+// .dep(|s| s.name("libtest"))
+// .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
+// .dep(|s| s.name("test-helpers"))
+// .dep(|s| s.name("debugger-scripts"))
+// .run(move |s| check::compiletest(build, &s.compiler(), s.target,
+// "debuginfo-lldb", "debuginfo"));
+// rules.test("check-debuginfo-gdb", "src/test/debuginfo-gdb")
+// .dep(|s| s.name("libtest"))
+// .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
+// .dep(|s| s.name("test-helpers"))
+// .dep(|s| s.name("debugger-scripts"))
+// .dep(|s| s.name("remote-copy-libs"))
+// .run(move |s| check::compiletest(build, &s.compiler(), s.target,
+// "debuginfo-gdb", "debuginfo"));
+// let mut rule = rules.test("check-debuginfo", "src/test/debuginfo");
+// rule.default(true);
+// if build.build.contains("apple") {
+// rule.dep(|s| s.name("check-debuginfo-lldb"));
+// } else {
+// rule.dep(|s| s.name("check-debuginfo-gdb"));
+// }
+// }
+//
+//
+//
+// {
+// let mut suite = |name, path, mode, dir| {
+// rules.test(name, path)
+// .dep(|s| s.name("librustc"))
+// .dep(|s| s.name("test-helpers"))
+// .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
+// .default(mode != "pretty")
+// .host(true)
+// .run(move |s| {
+// check::compiletest(build, &s.compiler(), s.target, mode, dir)
+// });
+// };
+//
+// suite("check-ui-full", "src/test/ui-fulldeps", "ui", "ui-fulldeps");
+// suite("check-rpass-full", "src/test/run-pass-fulldeps",
+// "run-pass", "run-pass-fulldeps");
+// suite("check-rfail-full", "src/test/run-fail-fulldeps",
+// "run-fail", "run-fail-fulldeps");
+// suite("check-cfail-full", "src/test/compile-fail-fulldeps",
+// "compile-fail", "compile-fail-fulldeps");
+// suite("check-rmake", "src/test/run-make", "run-make", "run-make");
+// suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc");
+// suite("check-pretty", "src/test/pretty", "pretty", "pretty");
+// suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty",
+// "run-pass");
+// suite("check-pretty-rfail", "src/test/run-fail/pretty", "pretty",
+// "run-fail");
+// suite("check-pretty-valgrind", "src/test/run-pass-valgrind/pretty", "pretty",
+// "run-pass-valgrind");
+// suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps/pretty",
+// "pretty", "run-pass-fulldeps");
+// suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps/pretty",
+// "pretty", "run-fail-fulldeps");
+// }
+
/// Executes the `compiletest` tool to run a suite of tests.
///
/// Compiles all tests with `compiler` for `target` with the specified
cmd.arg("--mode").arg(mode);
cmd.arg("--target").arg(target);
cmd.arg("--host").arg(compiler.host);
- cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build));
+ cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.build));
- if let Some(nodejs) = build.config.nodejs.as_ref() {
+ if let Some(ref nodejs) = build.config.nodejs {
cmd.arg("--nodejs").arg(nodejs);
}
cmd.arg("--docck-python").arg(build.python());
- if build.config.build.ends_with("apple-darwin") {
+ if build.build.ends_with("apple-darwin") {
// Force /usr/bin/python on macOS for LLDB tests because we're loading the
// LLDB plugin's compiled module which only works with the system python
// (namely not Homebrew-installed python)
cmd.args(&build.flags.cmd.test_args());
- if build.config.verbose() || build.flags.verbose() {
+ if build.is_verbose() {
cmd.arg("--verbose");
}
let llvm_components = output(Command::new(&llvm_config).arg("--components"));
let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
cmd.arg("--cc").arg(build.cc(target))
- .arg("--cxx").arg(build.cxx(target))
+ .arg("--cxx").arg(build.cxx(target).unwrap())
.arg("--cflags").arg(build.cflags(target).join(" "))
.arg("--llvm-components").arg(llvm_components.trim())
.arg("--llvm-cxxflags").arg(llvm_cxxflags.trim());
if build.remote_tested(target) {
cmd.arg("--remote-test-client")
- .arg(build.tool(&Compiler::new(0, &build.config.build),
+ .arg(build.tool(&Compiler::new(0, &build.build),
"remote-test-client"));
}
try_run(build, &mut cmd);
}
+// rules.test("check-docs", "src/doc")
+// .dep(|s| s.name("libtest"))
+// .default(true)
+// .host(true)
+// .run(move |s| check::docs(build, &s.compiler()));
/// Run `rustdoc --test` for all documentation in `src/doc`.
///
/// This will run all tests in our markdown documentation (e.g. the book)
while let Some(p) = stack.pop() {
if p.is_dir() {
- stack.extend(t!(p.read_dir()).map(|p| t!(p).path()).filter(|p| {
- p.extension().and_then(|s| s.to_str()) == Some("md") &&
- // The nostarch directory in the book is for no starch, and so isn't guaranteed to
- // build. We don't care if it doesn't build, so skip it.
- p.to_str().map_or(true, |p| !p.contains("nostarch"))
- }));
+ stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
continue
}
+ if p.extension().and_then(|s| s.to_str()) != Some("md") {
+ continue;
+ }
+
+ // The nostarch directory in the book is for no starch, and so isn't
+ // guaranteed to build. We don't care if it doesn't build, so skip it.
+ if p.to_str().map_or(false, |p| p.contains("nostarch")) {
+ continue;
+ }
+
markdown_test(build, compiler, &p);
}
}
+//rules.test("check-error-index", "src/tools/error_index_generator")
+// .dep(|s| s.name("libstd"))
+// .dep(|s| s.name("tool-error-index").host(s.host).stage(0))
+// .default(true)
+// .host(true)
+// .run(move |s| check::error_index(build, &s.compiler()));
/// Run the error index generator tool to execute the tests located in the error
/// index.
///
"error_index_generator")
.arg("markdown")
.arg(&output)
- .env("CFG_BUILD", &build.config.build));
+ .env("CFG_BUILD", &build.build));
markdown_test(build, compiler, &output);
}
}
}
+// for (krate, path, _default) in krates("std") {
+// rules.test(&krate.test_step, path)
+// .dep(|s| s.name("libtest"))
+// .dep(|s| s.name("remote-copy-libs"))
+// .run(move |s| check::krate(build, &s.compiler(), s.target,
+// Mode::Libstd, TestKind::Test,
+// Some(&krate.name)));
+// }
+// rules.test("check-std-all", "path/to/nowhere")
+// .dep(|s| s.name("libtest"))
+// .dep(|s| s.name("remote-copy-libs"))
+// .default(true)
+// .run(move |s| check::krate(build, &s.compiler(), s.target,
+// Mode::Libstd, TestKind::Test, None));
+//
+// // std benchmarks
+// for (krate, path, _default) in krates("std") {
+// rules.bench(&krate.bench_step, path)
+// .dep(|s| s.name("libtest"))
+// .dep(|s| s.name("remote-copy-libs"))
+// .run(move |s| check::krate(build, &s.compiler(), s.target,
+// Mode::Libstd, TestKind::Bench,
+// Some(&krate.name)));
+// }
+// rules.bench("bench-std-all", "path/to/nowhere")
+// .dep(|s| s.name("libtest"))
+// .dep(|s| s.name("remote-copy-libs"))
+// .default(true)
+// .run(move |s| check::krate(build, &s.compiler(), s.target,
+// Mode::Libstd, TestKind::Bench, None));
+//
+// for (krate, path, _default) in krates("test") {
+// rules.test(&krate.test_step, path)
+// .dep(|s| s.name("libtest"))
+// .dep(|s| s.name("remote-copy-libs"))
+// .run(move |s| check::krate(build, &s.compiler(), s.target,
+// Mode::Libtest, TestKind::Test,
+// Some(&krate.name)));
+// }
+// rules.test("check-test-all", "path/to/nowhere")
+// .dep(|s| s.name("libtest"))
+// .dep(|s| s.name("remote-copy-libs"))
+// .default(true)
+// .run(move |s| check::krate(build, &s.compiler(), s.target,
+// Mode::Libtest, TestKind::Test, None));
+// for (krate, path, _default) in krates("rustc-main") {
+// rules.test(&krate.test_step, path)
+// .dep(|s| s.name("librustc"))
+// .dep(|s| s.name("remote-copy-libs"))
+// .host(true)
+// .run(move |s| check::krate(build, &s.compiler(), s.target,
+// Mode::Librustc, TestKind::Test,
+// Some(&krate.name)));
+// }
+// rules.test("check-rustc-all", "path/to/nowhere")
+// .dep(|s| s.name("librustc"))
+// .dep(|s| s.name("remote-copy-libs"))
+// .default(true)
+// .host(true)
+// .run(move |s| check::krate(build, &s.compiler(), s.target,
+// Mode::Librustc, TestKind::Test, None));
+
/// Run all unit tests plus documentation tests for an entire crate DAG defined
/// by a `Cargo.toml`
///
cargo.arg("--manifest-path")
.arg(build.src.join(path).join("Cargo.toml"))
.arg("--features").arg(features);
- if test_kind.subcommand() == "test" && build.flags.cmd.no_fail_fast() {
+ if test_kind.subcommand() == "test" && !build.fail_fast {
cargo.arg("--no-fail-fast");
}
compiler: &Compiler,
target: &str,
mode: Mode) {
- let mut tests = Vec::new();
let out_dir = build.cargo_out(compiler, mode, target);
- find_tests(&out_dir.join("deps"), target, &mut tests);
+ let tests = find_tests(&out_dir.join("deps"), target);
+ let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured");
for test in tests {
- let test_file_name = test.to_string_lossy().into_owned();
- println!("running {}", test_file_name);
- let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured");
+ println!("running {}", test.display());
let mut cmd = Command::new(nodejs);
- cmd.arg(&test_file_name);
+ cmd.arg(&test);
if build.config.quiet_tests {
cmd.arg("--quiet");
}
compiler: &Compiler,
target: &str,
mode: Mode) {
- let mut tests = Vec::new();
let out_dir = build.cargo_out(compiler, mode, target);
- find_tests(&out_dir.join("deps"), target, &mut tests);
+ let tests = find_tests(&out_dir.join("deps"), target);
- let tool = build.tool(&Compiler::new(0, &build.config.build),
+ let tool = build.tool(&Compiler::new(0, &build.build),
"remote-test-client");
for test in tests {
let mut cmd = Command::new(&tool);
}
}
-fn find_tests(dir: &Path,
- target: &str,
- dst: &mut Vec<PathBuf>) {
+fn find_tests(dir: &Path, target: &str) -> Vec<PathBuf> {
+ let mut dst = Vec::new();
for e in t!(dir.read_dir()).map(|e| t!(e)) {
let file_type = t!(e.file_type());
if !file_type.is_file() {
dst.push(e.path());
}
}
+ dst
}
+// // Some test suites are run inside emulators or on remote devices, and most
+// // of our test binaries are linked dynamically which means we need to ship
+// // the standard library and such to the emulator ahead of time. This step
+// // represents this and is a dependency of all test suites.
+// //
+// // Most of the time this step is a noop (the `check::emulator_copy_libs`
+// // only does work if necessary). For some steps such as shipping data to
+// // QEMU we have to build our own tools so we've got conditional dependencies
+// // on those programs as well. Note that the remote test client is built for
+// // the build target (us) and the server is built for the target.
+// rules.test("remote-copy-libs", "path/to/nowhere")
+// .dep(|s| s.name("libtest"))
+// .dep(move |s| {
+// if build.remote_tested(s.target) {
+// s.name("tool-remote-test-client").target(s.host).stage(0)
+// } else {
+// Step::noop()
+// }
+// })
+// .dep(move |s| {
+// if build.remote_tested(s.target) {
+// s.name("tool-remote-test-server")
+// } else {
+// Step::noop()
+// }
+// })
+// .run(move |s| check::remote_copy_libs(build, &s.compiler(), s.target));
+//
pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
if !build.remote_tested(target) {
return
.join(exe("remote-test-server", target));
// Spawn the emulator and wait for it to come online
- let tool = build.tool(&Compiler::new(0, &build.config.build),
+ let tool = build.tool(&Compiler::new(0, &build.build),
"remote-test-client");
let mut cmd = Command::new(&tool);
cmd.arg("spawn-emulator")
}
}
+//rules.test("check-distcheck", "distcheck")
+// .dep(|s| s.name("dist-plain-source-tarball"))
+// .dep(|s| s.name("dist-src"))
+// .run(move |_| check::distcheck(build));
+
/// Run "distcheck", a 'make check' from a tarball
pub fn distcheck(build: &Build) {
- if build.config.build != "x86_64-unknown-linux-gnu" {
+ if build.build != "x86_64-unknown-linux-gnu" {
return
}
if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") {
.args(&build.config.configure_args)
.arg("--enable-vendor")
.current_dir(&dir));
- build.run(Command::new(build_helper::make(&build.config.build))
+ build.run(Command::new(build_helper::make(&build.build))
.arg("check")
.current_dir(&dir));
build.run(&mut cmd);
let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml");
- build.run(Command::new(&build.cargo)
+ build.run(Command::new(&build.initial_cargo)
.arg("generate-lockfile")
.arg("--manifest-path")
.arg(&toml)
.current_dir(&dir));
}
+//rules.test("check-bootstrap", "src/bootstrap")
+// .default(true)
+// .host(true)
+// .only_build(true)
+// .run(move |_| check::bootstrap(build));
+//
/// Test the build system itself
pub fn bootstrap(build: &Build) {
- let mut cmd = Command::new(&build.cargo);
+ let mut cmd = Command::new(&build.initial_cargo);
cmd.arg("test")
.current_dir(build.src.join("src/bootstrap"))
.env("CARGO_TARGET_DIR", build.out.join("bootstrap"))
.env("RUSTC_BOOTSTRAP", "1")
- .env("RUSTC", &build.rustc);
- if build.flags.cmd.no_fail_fast() {
+ .env("RUSTC", &build.initial_rustc);
+ if !build.fail_fast {
cmd.arg("--no-fail-fast");
}
cmd.arg("--").args(&build.flags.cmd.test_args());