Skip to content

Commit 6f721f5

Browse files
committed
Auto merge of #50466 - kennytm:rustbuild-stage0-lib-test, r=Mark-Simulacrum
rustbuild: Allow quick testing of libstd and libcore at stage0 This PR implemented two features: 1. Added a `--no-doc` flag to allow testing a crate *without* doc tests. In this mode, we don't need to build rustdoc, and thus we can skip building the stage2 compiler. (Ideally stage0 test should use the bootstrap rustdoc, but I don't want to mess up the core builder logic here) 2. Moved all libcore tests externally and added a tidy test to ensure we don't accidentally add `#[test]` into libcore. After this PR, one could run `./x.py test --stage 0 --no-doc src/libstd` to test `libstd` without building the compiler, thus enables us to quickly test new library features.
2 parents ce0cb14 + 05af55b commit 6f721f5

File tree

16 files changed

+345
-221
lines changed

16 files changed

+345
-221
lines changed

src/bootstrap/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ The script accepts commands, flags, and arguments to determine what to do:
6464
# execute tests in the standard library in stage0
6565
./x.py test --stage 0 src/libstd
6666
67+
# execute tests in the core and standard library in stage0,
68+
# without running doc tests (thus avoid depending on building the compiler)
69+
./x.py test --stage 0 --no-doc src/libcore src/libstd
70+
6771
# execute all doc tests
6872
./x.py test src/doc
6973
```

src/bootstrap/builder.rs

+40-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use compile;
2525
use install;
2626
use dist;
2727
use util::{exe, libdir, add_lib_path};
28-
use {Build, Mode};
28+
use {Build, Mode, DocTests};
2929
use cache::{INTERNER, Interned, Cache};
3030
use check;
3131
use test;
@@ -591,6 +591,8 @@ impl<'a> Builder<'a> {
591591
format!("{} {}", env::var("RUSTFLAGS").unwrap_or_default(), extra_args));
592592
}
593593

594+
let want_rustdoc = self.doc_tests != DocTests::No;
595+
594596
// Customize the compiler we're running. Specify the compiler to cargo
595597
// as our shim and then pass it some various options used to configure
596598
// how the actual compiler itself is called.
@@ -607,7 +609,7 @@ impl<'a> Builder<'a> {
607609
.env("RUSTC_LIBDIR", self.rustc_libdir(compiler))
608610
.env("RUSTC_RPATH", self.config.rust_rpath.to_string())
609611
.env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc"))
610-
.env("RUSTDOC_REAL", if cmd == "doc" || cmd == "test" {
612+
.env("RUSTDOC_REAL", if cmd == "doc" || (cmd == "test" && want_rustdoc) {
611613
self.rustdoc(compiler.host)
612614
} else {
613615
PathBuf::from("/path/to/nowhere/rustdoc/not/required")
@@ -624,7 +626,7 @@ impl<'a> Builder<'a> {
624626
if let Some(ref error_format) = self.config.rustc_error_format {
625627
cargo.env("RUSTC_ERROR_FORMAT", error_format);
626628
}
627-
if cmd != "build" && cmd != "check" {
629+
if cmd != "build" && cmd != "check" && want_rustdoc {
628630
cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.config.build)));
629631
}
630632

@@ -1407,4 +1409,39 @@ mod __test {
14071409
},
14081410
]);
14091411
}
1412+
1413+
#[test]
1414+
fn test_with_no_doc_stage0() {
1415+
let mut config = configure(&[], &[]);
1416+
config.stage = Some(0);
1417+
config.cmd = Subcommand::Test {
1418+
paths: vec!["src/libstd".into()],
1419+
test_args: vec![],
1420+
rustc_args: vec![],
1421+
fail_fast: true,
1422+
doc_tests: DocTests::No,
1423+
};
1424+
1425+
let build = Build::new(config);
1426+
let mut builder = Builder::new(&build);
1427+
1428+
let host = INTERNER.intern_str("A");
1429+
1430+
builder.run_step_descriptions(
1431+
&[StepDescription::from::<test::Crate>()],
1432+
&["src/libstd".into()],
1433+
);
1434+
1435+
// Ensure we don't build any compiler artifacts.
1436+
assert!(builder.cache.all::<compile::Rustc>().is_empty());
1437+
assert_eq!(first(builder.cache.all::<test::Crate>()), &[
1438+
test::Crate {
1439+
compiler: Compiler { host, stage: 0 },
1440+
target: host,
1441+
mode: Mode::Libstd,
1442+
test_kind: test::TestKind::Test,
1443+
krate: INTERNER.intern_str("std"),
1444+
},
1445+
]);
1446+
}
14101447
}

src/bootstrap/flags.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use std::process;
1919

2020
use getopts::Options;
2121

22-
use Build;
22+
use {Build, DocTests};
2323
use config::Config;
2424
use metadata;
2525
use builder::Builder;
@@ -62,7 +62,7 @@ pub enum Subcommand {
6262
test_args: Vec<String>,
6363
rustc_args: Vec<String>,
6464
fail_fast: bool,
65-
doc_tests: bool,
65+
doc_tests: DocTests,
6666
},
6767
Bench {
6868
paths: Vec<PathBuf>,
@@ -171,7 +171,8 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
171171
"extra options to pass the compiler when running tests",
172172
"ARGS",
173173
);
174-
opts.optflag("", "doc", "run doc tests");
174+
opts.optflag("", "no-doc", "do not run doc tests");
175+
opts.optflag("", "doc", "only run doc tests");
175176
},
176177
"bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
177178
"clean" => { opts.optflag("", "all", "clean all build artifacts"); },
@@ -324,7 +325,13 @@ Arguments:
324325
test_args: matches.opt_strs("test-args"),
325326
rustc_args: matches.opt_strs("rustc-args"),
326327
fail_fast: !matches.opt_present("no-fail-fast"),
327-
doc_tests: matches.opt_present("doc"),
328+
doc_tests: if matches.opt_present("doc") {
329+
DocTests::Only
330+
} else if matches.opt_present("no-doc") {
331+
DocTests::No
332+
} else {
333+
DocTests::Yes
334+
}
328335
}
329336
}
330337
"bench" => {
@@ -411,10 +418,10 @@ impl Subcommand {
411418
}
412419
}
413420

414-
pub fn doc_tests(&self) -> bool {
421+
pub fn doc_tests(&self) -> DocTests {
415422
match *self {
416423
Subcommand::Test { doc_tests, .. } => doc_tests,
417-
_ => false,
424+
_ => DocTests::Yes,
418425
}
419426
}
420427
}

src/bootstrap/lib.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,16 @@ pub struct Compiler {
210210
host: Interned<String>,
211211
}
212212

213+
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
214+
pub enum DocTests {
215+
// Default, run normal tests and doc tests.
216+
Yes,
217+
// Do not run any doc tests.
218+
No,
219+
// Only run doc tests.
220+
Only,
221+
}
222+
213223
/// Global configuration for the build system.
214224
///
215225
/// This structure transitively contains all configuration for the build system.
@@ -233,7 +243,7 @@ pub struct Build {
233243
rustfmt_info: channel::GitInfo,
234244
local_rebuild: bool,
235245
fail_fast: bool,
236-
doc_tests: bool,
246+
doc_tests: DocTests,
237247
verbosity: usize,
238248

239249
// Targets for which to build.
@@ -294,7 +304,7 @@ impl Crate {
294304
///
295305
/// These entries currently correspond to the various output directories of the
296306
/// build system, with each mod generating output in a different directory.
297-
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
307+
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
298308
pub enum Mode {
299309
/// Build the standard library, placing output in the "stageN-std" directory.
300310
Libstd,

src/bootstrap/test.rs

+16-10
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ use dist;
3232
use native;
3333
use tool::{self, Tool};
3434
use util::{self, dylib_path, dylib_path_var};
35-
use Mode;
35+
use {Mode, DocTests};
3636
use toolstate::ToolState;
3737

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

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

14091409

1410-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1410+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
14111411
pub struct Crate {
1412-
compiler: Compiler,
1413-
target: Interned<String>,
1414-
mode: Mode,
1415-
test_kind: TestKind,
1416-
krate: Interned<String>,
1412+
pub compiler: Compiler,
1413+
pub target: Interned<String>,
1414+
pub mode: Mode,
1415+
pub test_kind: TestKind,
1416+
pub krate: Interned<String>,
14171417
}
14181418

14191419
impl Step for Crate {
@@ -1519,8 +1519,14 @@ impl Step for Crate {
15191519
if test_kind.subcommand() == "test" && !builder.fail_fast {
15201520
cargo.arg("--no-fail-fast");
15211521
}
1522-
if builder.doc_tests {
1523-
cargo.arg("--doc");
1522+
match builder.doc_tests {
1523+
DocTests::Only => {
1524+
cargo.arg("--doc");
1525+
}
1526+
DocTests::No => {
1527+
cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
1528+
}
1529+
DocTests::Yes => {}
15241530
}
15251531

15261532
cargo.arg("-p").arg(krate);

src/libcore/lib.rs

+9
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@
5050
5151
// Since libcore defines many fundamental lang items, all tests live in a
5252
// separate crate, libcoretest, to avoid bizarre issues.
53+
//
54+
// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
55+
// this, both the generated test artifact and the linked libtest (which
56+
// transitively includes libcore) will both define the same set of lang items,
57+
// and this will cause the E0152 "duplicate lang item found" error. See
58+
// discussion in #50466 for details.
59+
//
60+
// This cfg won't affect doc tests.
61+
#![cfg(not(test))]
5362

5463
#![stable(feature = "core", since = "1.6.0")]
5564
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",

src/libcore/slice/memchr.rs

-82
Original file line numberDiff line numberDiff line change
@@ -135,85 +135,3 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
135135
// find the byte before the point the body loop stopped
136136
text[..offset].iter().rposition(|elt| *elt == x)
137137
}
138-
139-
// test fallback implementations on all platforms
140-
#[test]
141-
fn matches_one() {
142-
assert_eq!(Some(0), memchr(b'a', b"a"));
143-
}
144-
145-
#[test]
146-
fn matches_begin() {
147-
assert_eq!(Some(0), memchr(b'a', b"aaaa"));
148-
}
149-
150-
#[test]
151-
fn matches_end() {
152-
assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
153-
}
154-
155-
#[test]
156-
fn matches_nul() {
157-
assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
158-
}
159-
160-
#[test]
161-
fn matches_past_nul() {
162-
assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
163-
}
164-
165-
#[test]
166-
fn no_match_empty() {
167-
assert_eq!(None, memchr(b'a', b""));
168-
}
169-
170-
#[test]
171-
fn no_match() {
172-
assert_eq!(None, memchr(b'a', b"xyz"));
173-
}
174-
175-
#[test]
176-
fn matches_one_reversed() {
177-
assert_eq!(Some(0), memrchr(b'a', b"a"));
178-
}
179-
180-
#[test]
181-
fn matches_begin_reversed() {
182-
assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
183-
}
184-
185-
#[test]
186-
fn matches_end_reversed() {
187-
assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
188-
}
189-
190-
#[test]
191-
fn matches_nul_reversed() {
192-
assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
193-
}
194-
195-
#[test]
196-
fn matches_past_nul_reversed() {
197-
assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
198-
}
199-
200-
#[test]
201-
fn no_match_empty_reversed() {
202-
assert_eq!(None, memrchr(b'a', b""));
203-
}
204-
205-
#[test]
206-
fn no_match_reversed() {
207-
assert_eq!(None, memrchr(b'a', b"xyz"));
208-
}
209-
210-
#[test]
211-
fn each_alignment_reversed() {
212-
let mut data = [1u8; 64];
213-
let needle = 2;
214-
let pos = 40;
215-
data[pos] = needle;
216-
for start in 0..16 {
217-
assert_eq!(Some(pos - start), memrchr(needle, &data[start..]));
218-
}
219-
}

src/libcore/tests/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#![feature(reverse_bits)]
4747
#![feature(inclusive_range_methods)]
4848
#![feature(iterator_find_map)]
49+
#![feature(slice_internals)]
4950

5051
extern crate core;
5152
extern crate test;
@@ -74,4 +75,5 @@ mod result;
7475
mod slice;
7576
mod str;
7677
mod str_lossy;
78+
mod time;
7779
mod tuple;

src/libcore/tests/num/uint_macros.rs

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ mod tests {
9898
}
9999

100100
#[test]
101+
#[cfg(not(stage0))]
101102
fn test_reverse_bits() {
102103
assert_eq!(A.reverse_bits().reverse_bits(), A);
103104
assert_eq!(B.reverse_bits().reverse_bits(), B);

0 commit comments

Comments
 (0)