Skip to content

rustbuild: Allow quick testing of libstd and libcore at stage0 #50466

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

Merged
merged 9 commits into from
May 6, 2018
4 changes: 4 additions & 0 deletions src/bootstrap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ The script accepts commands, flags, and arguments to determine what to do:
# execute tests in the standard library in stage0
./x.py test --stage 0 src/libstd

# execute tests in the core and standard library in stage0,
# without running doc tests (thus avoid depending on building the compiler)
./x.py test --stage 0 --no-doc src/libcore src/libstd

# execute all doc tests
./x.py test src/doc
```
Expand Down
43 changes: 40 additions & 3 deletions src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use compile;
use install;
use dist;
use util::{exe, libdir, add_lib_path};
use {Build, Mode};
use {Build, Mode, DocTests};
use cache::{INTERNER, Interned, Cache};
use check;
use test;
Expand Down Expand Up @@ -591,6 +591,8 @@ impl<'a> Builder<'a> {
format!("{} {}", env::var("RUSTFLAGS").unwrap_or_default(), extra_args));
}

let want_rustdoc = self.doc_tests != DocTests::No;

// Customize the compiler we're running. Specify the compiler to cargo
// as our shim and then pass it some various options used to configure
// how the actual compiler itself is called.
Expand All @@ -607,7 +609,7 @@ impl<'a> Builder<'a> {
.env("RUSTC_LIBDIR", self.rustc_libdir(compiler))
.env("RUSTC_RPATH", self.config.rust_rpath.to_string())
.env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc"))
.env("RUSTDOC_REAL", if cmd == "doc" || cmd == "test" {
.env("RUSTDOC_REAL", if cmd == "doc" || (cmd == "test" && want_rustdoc) {
self.rustdoc(compiler.host)
} else {
PathBuf::from("/path/to/nowhere/rustdoc/not/required")
Expand All @@ -624,7 +626,7 @@ impl<'a> Builder<'a> {
if let Some(ref error_format) = self.config.rustc_error_format {
cargo.env("RUSTC_ERROR_FORMAT", error_format);
}
if cmd != "build" && cmd != "check" {
if cmd != "build" && cmd != "check" && want_rustdoc {
cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.config.build)));
}

Expand Down Expand Up @@ -1403,4 +1405,39 @@ mod __test {
},
]);
}

#[test]
fn test_with_no_doc_stage0() {
let mut config = configure(&[], &[]);
config.stage = Some(0);
config.cmd = Subcommand::Test {
paths: vec!["src/libstd".into()],
test_args: vec![],
rustc_args: vec![],
fail_fast: true,
doc_tests: DocTests::No,
};

let build = Build::new(config);
let mut builder = Builder::new(&build);

let host = INTERNER.intern_str("A");

builder.run_step_descriptions(
&[StepDescription::from::<test::Crate>()],
&["src/libstd".into()],
);

// Ensure we don't build any compiler artifacts.
assert!(builder.cache.all::<compile::Rustc>().is_empty());
assert_eq!(first(builder.cache.all::<test::Crate>()), &[
test::Crate {
compiler: Compiler { host, stage: 0 },
target: host,
mode: Mode::Libstd,
test_kind: test::TestKind::Test,
krate: INTERNER.intern_str("std"),
},
]);
}
}
19 changes: 13 additions & 6 deletions src/bootstrap/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use std::process;

use getopts::Options;

use Build;
use {Build, DocTests};
use config::Config;
use metadata;
use builder::Builder;
Expand Down Expand Up @@ -62,7 +62,7 @@ pub enum Subcommand {
test_args: Vec<String>,
rustc_args: Vec<String>,
fail_fast: bool,
doc_tests: bool,
doc_tests: DocTests,
},
Bench {
paths: Vec<PathBuf>,
Expand Down Expand Up @@ -171,7 +171,8 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
"extra options to pass the compiler when running tests",
"ARGS",
);
opts.optflag("", "doc", "run doc tests");
opts.optflag("", "no-doc", "do not run doc tests");
opts.optflag("", "doc", "only run doc tests");
},
"bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
"clean" => { opts.optflag("", "all", "clean all build artifacts"); },
Expand Down Expand Up @@ -324,7 +325,13 @@ Arguments:
test_args: matches.opt_strs("test-args"),
rustc_args: matches.opt_strs("rustc-args"),
fail_fast: !matches.opt_present("no-fail-fast"),
doc_tests: matches.opt_present("doc"),
doc_tests: if matches.opt_present("doc") {
DocTests::Only
} else if matches.opt_present("no-doc") {
DocTests::No
} else {
DocTests::Yes
}
}
}
"bench" => {
Expand Down Expand Up @@ -411,10 +418,10 @@ impl Subcommand {
}
}

pub fn doc_tests(&self) -> bool {
pub fn doc_tests(&self) -> DocTests {
match *self {
Subcommand::Test { doc_tests, .. } => doc_tests,
_ => false,
_ => DocTests::Yes,
}
}
}
Expand Down
14 changes: 12 additions & 2 deletions src/bootstrap/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,16 @@ pub struct Compiler {
host: Interned<String>,
}

#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum DocTests {
// Default, run normal tests and doc tests.
Yes,
// Do not run any doc tests.
No,
// Only run doc tests.
Only,
}

/// Global configuration for the build system.
///
/// This structure transitively contains all configuration for the build system.
Expand All @@ -233,7 +243,7 @@ pub struct Build {
rustfmt_info: channel::GitInfo,
local_rebuild: bool,
fail_fast: bool,
doc_tests: bool,
doc_tests: DocTests,
verbosity: usize,

// Targets for which to build.
Expand Down Expand Up @@ -294,7 +304,7 @@ impl Crate {
///
/// These entries currently correspond to the various output directories of the
/// build system, with each mod generating output in a different directory.
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Mode {
/// Build the standard library, placing output in the "stageN-std" directory.
Libstd,
Expand Down
26 changes: 16 additions & 10 deletions src/bootstrap/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ use dist;
use native;
use tool::{self, Tool};
use util::{self, dylib_path, dylib_path_var};
use Mode;
use {Mode, DocTests};
use toolstate::ToolState;

const ADB_TEST_DIR: &str = "/data/tmp/work";

/// The two modes of the test runner; tests or benchmarks.
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
pub enum TestKind {
/// Run `cargo test`
Test,
Expand Down Expand Up @@ -1407,13 +1407,13 @@ impl Step for CrateNotDefault {
}


#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Crate {
compiler: Compiler,
target: Interned<String>,
mode: Mode,
test_kind: TestKind,
krate: Interned<String>,
pub compiler: Compiler,
pub target: Interned<String>,
pub mode: Mode,
pub test_kind: TestKind,
pub krate: Interned<String>,
}

impl Step for Crate {
Expand Down Expand Up @@ -1519,8 +1519,14 @@ impl Step for Crate {
if test_kind.subcommand() == "test" && !builder.fail_fast {
cargo.arg("--no-fail-fast");
}
if builder.doc_tests {
cargo.arg("--doc");
match builder.doc_tests {
DocTests::Only => {
cargo.arg("--doc");
}
DocTests::No => {
cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
}
DocTests::Yes => {}
}

cargo.arg("-p").arg(krate);
Expand Down
9 changes: 9 additions & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.
//
// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
// this, both the generated test artifact and the linked libtest (which
// transitively includes libcore) will both define the same set of lang items,
// and this will cause the E0152 "duplicate lang item found" error. See
// discussion in #50466 for details.
//
// This cfg won't affect doc tests.
#![cfg(not(test))]

#![stable(feature = "core", since = "1.6.0")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
Expand Down
82 changes: 0 additions & 82 deletions src/libcore/slice/memchr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,85 +135,3 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
// find the byte before the point the body loop stopped
text[..offset].iter().rposition(|elt| *elt == x)
}

// test fallback implementations on all platforms
#[test]
fn matches_one() {
assert_eq!(Some(0), memchr(b'a', b"a"));
}

#[test]
fn matches_begin() {
assert_eq!(Some(0), memchr(b'a', b"aaaa"));
}

#[test]
fn matches_end() {
assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
}

#[test]
fn matches_nul() {
assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
}

#[test]
fn matches_past_nul() {
assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
}

#[test]
fn no_match_empty() {
assert_eq!(None, memchr(b'a', b""));
}

#[test]
fn no_match() {
assert_eq!(None, memchr(b'a', b"xyz"));
}

#[test]
fn matches_one_reversed() {
assert_eq!(Some(0), memrchr(b'a', b"a"));
}

#[test]
fn matches_begin_reversed() {
assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
}

#[test]
fn matches_end_reversed() {
assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
}

#[test]
fn matches_nul_reversed() {
assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
}

#[test]
fn matches_past_nul_reversed() {
assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
}

#[test]
fn no_match_empty_reversed() {
assert_eq!(None, memrchr(b'a', b""));
}

#[test]
fn no_match_reversed() {
assert_eq!(None, memrchr(b'a', b"xyz"));
}

#[test]
fn each_alignment_reversed() {
let mut data = [1u8; 64];
let needle = 2;
let pos = 40;
data[pos] = needle;
for start in 0..16 {
assert_eq!(Some(pos - start), memrchr(needle, &data[start..]));
}
}
2 changes: 2 additions & 0 deletions src/libcore/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#![feature(reverse_bits)]
#![feature(inclusive_range_methods)]
#![feature(iterator_find_map)]
#![feature(slice_internals)]

extern crate core;
extern crate test;
Expand Down Expand Up @@ -74,4 +75,5 @@ mod result;
mod slice;
mod str;
mod str_lossy;
mod time;
mod tuple;
1 change: 1 addition & 0 deletions src/libcore/tests/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ mod tests {
}

#[test]
#[cfg(not(stage0))]
fn test_reverse_bits() {
assert_eq!(A.reverse_bits().reverse_bits(), A);
assert_eq!(B.reverse_bits().reverse_bits(), B);
Expand Down
Loading