From 1733f5e1c0a69c853adebf718fc7b4f81a1d257b Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 00:04:06 +0800 Subject: [PATCH 1/9] Added `./x.py test --no-doc` option. This enables `./x.py test --stage 0 src/libstd --no-doc` and ensures the stage2-rustc and rustdoc need to be built. --- src/bootstrap/builder.rs | 8 +++++--- src/bootstrap/flags.rs | 19 +++++++++++++------ src/bootstrap/lib.rs | 12 +++++++++++- src/bootstrap/test.rs | 12 +++++++++--- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 08bb8ab481513..408e61ef54869 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -25,7 +25,7 @@ use compile; use install; use dist; use util::{exe, libdir, add_lib_path}; -use {Build, Mode}; +use {Build, Mode, DocTestsOption}; use cache::{INTERNER, Interned, Cache}; use check; use test; @@ -591,6 +591,8 @@ impl<'a> Builder<'a> { format!("{} {}", env::var("RUSTFLAGS").unwrap_or_default(), extra_args)); } + let want_rustdoc = self.doc_tests != DocTestsOption::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. @@ -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") @@ -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))); } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 3eb9dca2aa835..fb7c8ba135139 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -19,7 +19,7 @@ use std::process; use getopts::Options; -use Build; +use {Build, DocTestsOption}; use config::Config; use metadata; use builder::Builder; @@ -62,7 +62,7 @@ pub enum Subcommand { test_args: Vec, rustc_args: Vec, fail_fast: bool, - doc_tests: bool, + doc_tests: DocTestsOption, }, Bench { paths: Vec, @@ -171,7 +171,8 @@ To learn more about a subcommand, run `./x.py -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"); }, @@ -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") { + DocTestsOption::Only + } else if matches.opt_present("no-doc") { + DocTestsOption::No + } else { + DocTestsOption::Yes + } } } "bench" => { @@ -411,10 +418,10 @@ impl Subcommand { } } - pub fn doc_tests(&self) -> bool { + pub fn doc_tests(&self) -> DocTestsOption { match *self { Subcommand::Test { doc_tests, .. } => doc_tests, - _ => false, + _ => DocTestsOption::Yes, } } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 0a7f0e5ff4ee2..624319485be05 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -210,6 +210,16 @@ pub struct Compiler { host: Interned, } +#[derive(PartialEq, Eq, Copy, Clone, Debug)] +pub enum DocTestsOption { + // 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. @@ -233,7 +243,7 @@ pub struct Build { rustfmt_info: channel::GitInfo, local_rebuild: bool, fail_fast: bool, - doc_tests: bool, + doc_tests: DocTestsOption, verbosity: usize, // Targets for which to build. diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index e8c40dfdb0ad2..0d430c300368e 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -32,7 +32,7 @@ use dist; use native; use tool::{self, Tool}; use util::{self, dylib_path, dylib_path_var}; -use Mode; +use {Mode, DocTestsOption}; use toolstate::ToolState; const ADB_TEST_DIR: &str = "/data/tmp/work"; @@ -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 { + DocTestsOption::Only => { + cargo.arg("--doc"); + } + DocTestsOption::No => { + cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]); + } + DocTestsOption::Yes => {} } cargo.arg("-p").arg(krate); From be9d6690b22c7bdf46dda7f83ca61b69f58ce78b Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 02:33:01 +0800 Subject: [PATCH 2/9] Added test case. --- src/bootstrap/builder.rs | 35 +++++++++++++++++++++++++++++++++++ src/bootstrap/lib.rs | 2 +- src/bootstrap/test.rs | 14 +++++++------- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 408e61ef54869..da12fbdb942e4 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1405,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: DocTestsOption::No, + }; + + let build = Build::new(config); + let mut builder = Builder::new(&build); + + let host = INTERNER.intern_str("A"); + + builder.run_step_descriptions( + &[StepDescription::from::()], + &["src/libstd".into()], + ); + + // Ensure we don't build any compiler artifacts. + assert!(builder.cache.all::().is_empty()); + assert_eq!(first(builder.cache.all::()), &[ + test::Crate { + compiler: Compiler { host, stage: 0 }, + target: host, + mode: Mode::Libstd, + test_kind: test::TestKind::Test, + krate: INTERNER.intern_str("std"), + }, + ]); + } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 624319485be05..ff9a262e2cc76 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -304,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, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 0d430c300368e..2f0e3868f89ae 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -38,7 +38,7 @@ 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, @@ -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, - mode: Mode, - test_kind: TestKind, - krate: Interned, + pub compiler: Compiler, + pub target: Interned, + pub mode: Mode, + pub test_kind: TestKind, + pub krate: Interned, } impl Step for Crate { From 3ddd67ba5356b96806f039e1e8997af63c3a6ee1 Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Tue, 1 May 2018 13:43:05 +0200 Subject: [PATCH 3/9] Move libcore/time tests from `time.rs` to `tests/time.rs` All other tests of libcore reside in the tests/ directory, too. Apparently the tests of `time.rs` weren't run before, at least not by `x.py test src/libcore`. --- src/libcore/tests/lib.rs | 1 + src/libcore/tests/time.rs | 122 ++++++++++++++++++++++++++++++++++++++ src/libcore/time.rs | 116 ------------------------------------ 3 files changed, 123 insertions(+), 116 deletions(-) create mode 100644 src/libcore/tests/time.rs diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index f6750c590b33a..340879c6b8515 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -74,4 +74,5 @@ mod result; mod slice; mod str; mod str_lossy; +mod time; mod tuple; diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs new file mode 100644 index 0000000000000..9e6f284859c66 --- /dev/null +++ b/src/libcore/tests/time.rs @@ -0,0 +1,122 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::time::Duration; + +#[test] +fn creation() { + assert!(Duration::from_secs(1) != Duration::from_secs(0)); + assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), + Duration::from_secs(3)); + assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), + Duration::new(4, 10 * 1_000_000)); + assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); +} + +#[test] +fn secs() { + assert_eq!(Duration::new(0, 0).as_secs(), 0); + assert_eq!(Duration::from_secs(1).as_secs(), 1); + assert_eq!(Duration::from_millis(999).as_secs(), 0); + assert_eq!(Duration::from_millis(1001).as_secs(), 1); +} + +#[test] +fn nanos() { + assert_eq!(Duration::new(0, 0).subsec_nanos(), 0); + assert_eq!(Duration::new(0, 5).subsec_nanos(), 5); + assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1); + assert_eq!(Duration::from_secs(1).subsec_nanos(), 0); + assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000); + assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000); +} + +#[test] +fn add() { + assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), + Duration::new(0, 1)); + assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), + Duration::new(1, 1)); +} + +#[test] +fn checked_add() { + assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), + Some(Duration::new(0, 1))); + assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)), + Some(Duration::new(1, 1))); + assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::core::u64::MAX, 0)), None); +} + +#[test] +fn sub() { + assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), + Duration::new(0, 1)); + assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), + Duration::new(0, 1)); + assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), + Duration::new(0, 999_999_999)); +} + +#[test] +fn checked_sub() { + let zero = Duration::new(0, 0); + let one_nano = Duration::new(0, 1); + let one_sec = Duration::new(1, 0); + assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1))); + assert_eq!(one_sec.checked_sub(one_nano), + Some(Duration::new(0, 999_999_999))); + assert_eq!(zero.checked_sub(one_nano), None); + assert_eq!(zero.checked_sub(one_sec), None); +} + +#[test] #[should_panic] +fn sub_bad1() { + Duration::new(0, 0) - Duration::new(0, 1); +} + +#[test] #[should_panic] +fn sub_bad2() { + Duration::new(0, 0) - Duration::new(1, 0); +} + +#[test] +fn mul() { + assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2)); + assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3)); + assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4)); + assert_eq!(Duration::new(0, 500_000_001) * 4000, + Duration::new(2000, 4000)); +} + +#[test] +fn checked_mul() { + assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2))); + assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3))); + assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4))); + assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), + Some(Duration::new(2000, 4000))); + assert_eq!(Duration::new(::core::u64::MAX - 1, 0).checked_mul(2), None); +} + +#[test] +fn div() { + assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); + assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); + assert_eq!(Duration::new(99, 999_999_000) / 100, + Duration::new(0, 999_999_990)); +} + +#[test] +fn checked_div() { + assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); + assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); + assert_eq!(Duration::new(2, 0).checked_div(0), None); +} diff --git a/src/libcore/time.rs b/src/libcore/time.rs index e22fe450bb1f6..8e8b1691c657a 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -481,119 +481,3 @@ impl<'a> Sum<&'a Duration> for Duration { iter.fold(Duration::new(0, 0), |a, b| a + *b) } } - -#[cfg(test)] -mod tests { - use super::Duration; - - #[test] - fn creation() { - assert!(Duration::from_secs(1) != Duration::from_secs(0)); - assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), - Duration::from_secs(3)); - assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), - Duration::new(4, 10 * 1_000_000)); - assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); - } - - #[test] - fn secs() { - assert_eq!(Duration::new(0, 0).as_secs(), 0); - assert_eq!(Duration::from_secs(1).as_secs(), 1); - assert_eq!(Duration::from_millis(999).as_secs(), 0); - assert_eq!(Duration::from_millis(1001).as_secs(), 1); - } - - #[test] - fn nanos() { - assert_eq!(Duration::new(0, 0).subsec_nanos(), 0); - assert_eq!(Duration::new(0, 5).subsec_nanos(), 5); - assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1); - assert_eq!(Duration::from_secs(1).subsec_nanos(), 0); - assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000); - assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000); - } - - #[test] - fn add() { - assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), - Duration::new(0, 1)); - assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), - Duration::new(1, 1)); - } - - #[test] - fn checked_add() { - assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), - Some(Duration::new(0, 1))); - assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)), - Some(Duration::new(1, 1))); - assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::u64::MAX, 0)), None); - } - - #[test] - fn sub() { - assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), - Duration::new(0, 1)); - assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), - Duration::new(0, 1)); - assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), - Duration::new(0, 999_999_999)); - } - - #[test] - fn checked_sub() { - let zero = Duration::new(0, 0); - let one_nano = Duration::new(0, 1); - let one_sec = Duration::new(1, 0); - assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1))); - assert_eq!(one_sec.checked_sub(one_nano), - Some(Duration::new(0, 999_999_999))); - assert_eq!(zero.checked_sub(one_nano), None); - assert_eq!(zero.checked_sub(one_sec), None); - } - - #[test] #[should_panic] - fn sub_bad1() { - Duration::new(0, 0) - Duration::new(0, 1); - } - - #[test] #[should_panic] - fn sub_bad2() { - Duration::new(0, 0) - Duration::new(1, 0); - } - - #[test] - fn mul() { - assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2)); - assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3)); - assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4)); - assert_eq!(Duration::new(0, 500_000_001) * 4000, - Duration::new(2000, 4000)); - } - - #[test] - fn checked_mul() { - assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2))); - assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3))); - assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4))); - assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), - Some(Duration::new(2000, 4000))); - assert_eq!(Duration::new(::u64::MAX - 1, 0).checked_mul(2), None); - } - - #[test] - fn div() { - assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); - assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); - assert_eq!(Duration::new(99, 999_999_000) / 100, - Duration::new(0, 999_999_990)); - } - - #[test] - fn checked_div() { - assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); - assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); - assert_eq!(Duration::new(2, 0).checked_div(0), None); - } -} From 10ab98da8c8e53ab7b89eff489e09d352522889e Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Tue, 1 May 2018 15:07:15 +0200 Subject: [PATCH 4/9] Fix warning in `core::time` tests --- src/libcore/tests/time.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs index 9e6f284859c66..042c523f25f25 100644 --- a/src/libcore/tests/time.rs +++ b/src/libcore/tests/time.rs @@ -77,14 +77,16 @@ fn checked_sub() { assert_eq!(zero.checked_sub(one_sec), None); } -#[test] #[should_panic] +#[test] +#[should_panic] fn sub_bad1() { - Duration::new(0, 0) - Duration::new(0, 1); + let _ = Duration::new(0, 0) - Duration::new(0, 1); } -#[test] #[should_panic] +#[test] +#[should_panic] fn sub_bad2() { - Duration::new(0, 0) - Duration::new(1, 0); + let _ = Duration::new(0, 0) - Duration::new(1, 0); } #[test] From 13e07a4e180e964717a0f71f0fc40260bab7d84a Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 00:53:48 +0800 Subject: [PATCH 5/9] Move the tests in src/libcore/slice/memchr.rs as well. --- src/libcore/slice/memchr.rs | 82 ----------------------------------- src/libcore/tests/slice.rs | 86 +++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 82 deletions(-) diff --git a/src/libcore/slice/memchr.rs b/src/libcore/slice/memchr.rs index 469404f7f6bb0..7b62e7b0620fd 100644 --- a/src/libcore/slice/memchr.rs +++ b/src/libcore/slice/memchr.rs @@ -135,85 +135,3 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option { // 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..])); - } -} diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 53fdfa0682742..c81e5e97cbb7a 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -550,3 +550,89 @@ fn sort_unstable() { v.sort_unstable(); assert!(v == [0xDEADBEEF]); } + +pub mod memchr { + use core::slice::memchr::{memchr, memrchr}; + + // 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..])); + } + } +} From f24915b67fafe33e87e685d884ff63389b6967cb Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 00:54:12 +0800 Subject: [PATCH 6/9] Added a tidy test to ensure libcore cannot contain any tests. --- src/tools/tidy/src/lib.rs | 1 + src/tools/tidy/src/libcoretest.rs | 34 +++++++++++++++++++++++++++++++ src/tools/tidy/src/main.rs | 1 + 3 files changed, 36 insertions(+) create mode 100644 src/tools/tidy/src/libcoretest.rs diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index fa22743664014..022ef57503aaa 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -51,6 +51,7 @@ pub mod pal; pub mod deps; pub mod ui_tests; pub mod unstable_book; +pub mod libcoretest; fn filter_dirs(path: &Path) -> bool { let skip = [ diff --git a/src/tools/tidy/src/libcoretest.rs b/src/tools/tidy/src/libcoretest.rs new file mode 100644 index 0000000000000..ef8b55186b104 --- /dev/null +++ b/src/tools/tidy/src/libcoretest.rs @@ -0,0 +1,34 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Tidy check to ensure `#[test]` is not used directly inside `libcore`. +//! +//! `#![no_core]` libraries cannot be tested directly due to duplicating lang +//! item. All tests must be written externally in `libcore/tests`. + +use std::path::Path; +use std::fs::read_to_string; + +pub fn check(path: &Path, bad: &mut bool) { + let libcore_path = path.join("libcore"); + super::walk( + &libcore_path, + &mut |subpath| t!(subpath.strip_prefix(&libcore_path)).starts_with("tests"), + &mut |subpath| { + if t!(read_to_string(subpath)).contains("#[test]") { + tidy_error!( + bad, + "{} contains #[test]; libcore tests must be placed inside `src/libcore/tests/`", + subpath.display() + ); + } + }, + ); +} diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 2497419279560..7b86650823a43 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -41,6 +41,7 @@ fn main() { features::check(&path, &mut bad, quiet); pal::check(&path, &mut bad); unstable_book::check(&path, &mut bad); + libcoretest::check(&path, &mut bad); if !args.iter().any(|s| *s == "--no-vendor") { deps::check(&path, &mut bad); } From 02f6a0335f99378b2e7d630e00aabdeb57a5bd25 Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 01:02:05 +0800 Subject: [PATCH 7/9] Some final touches to ensure `./x.py test --stage 0 src/lib*` works --- src/libcore/lib.rs | 1 + src/libcore/tests/lib.rs | 1 + src/libcore/tests/num/uint_macros.rs | 1 + src/libstd/lib.rs | 4 ++-- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 04dd42583d406..37f9dcc7e32a0 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -50,6 +50,7 @@ // Since libcore defines many fundamental lang items, all tests live in a // separate crate, libcoretest, to avoid bizarre issues. +#![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", diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 340879c6b8515..5e98e40e0d5e6 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -46,6 +46,7 @@ #![feature(reverse_bits)] #![feature(inclusive_range_methods)] #![feature(iterator_find_map)] +#![feature(slice_internals)] extern crate core; extern crate test; diff --git a/src/libcore/tests/num/uint_macros.rs b/src/libcore/tests/num/uint_macros.rs index ca6906f731047..257f6ea20d4ea 100644 --- a/src/libcore/tests/num/uint_macros.rs +++ b/src/libcore/tests/num/uint_macros.rs @@ -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); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index fc05833e28503..d41739ab02c6a 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -330,10 +330,10 @@ // with a rustc without jemalloc. // FIXME(#44236) shouldn't need MSVC logic #![cfg_attr(all(not(target_env = "msvc"), - any(stage0, feature = "force_alloc_system")), + any(all(stage0, not(test)), feature = "force_alloc_system")), feature(global_allocator))] #[cfg(all(not(target_env = "msvc"), - any(stage0, feature = "force_alloc_system")))] + any(all(stage0, not(test)), feature = "force_alloc_system")))] #[global_allocator] static ALLOC: alloc_system::System = alloc_system::System; From 169f58b712e793ea43b90a6008a21b777bf4102f Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 03:29:19 +0800 Subject: [PATCH 8/9] Added some simple documentation. --- src/bootstrap/README.md | 4 ++++ src/libcore/lib.rs | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 9ff681ac68087..98c353eb6ec8c 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -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 ``` diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 37f9dcc7e32a0..54f35d17974fb 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -50,6 +50,14 @@ // 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")] From 05af55bd8052576bc172d635f8eb9207ccedfd29 Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 03:30:42 +0800 Subject: [PATCH 9/9] s/DocTestsOption/DocTests/g --- src/bootstrap/builder.rs | 6 +++--- src/bootstrap/flags.rs | 14 +++++++------- src/bootstrap/lib.rs | 4 ++-- src/bootstrap/test.rs | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index da12fbdb942e4..1002764027291 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -25,7 +25,7 @@ use compile; use install; use dist; use util::{exe, libdir, add_lib_path}; -use {Build, Mode, DocTestsOption}; +use {Build, Mode, DocTests}; use cache::{INTERNER, Interned, Cache}; use check; use test; @@ -591,7 +591,7 @@ impl<'a> Builder<'a> { format!("{} {}", env::var("RUSTFLAGS").unwrap_or_default(), extra_args)); } - let want_rustdoc = self.doc_tests != DocTestsOption::No; + 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 @@ -1415,7 +1415,7 @@ mod __test { test_args: vec![], rustc_args: vec![], fail_fast: true, - doc_tests: DocTestsOption::No, + doc_tests: DocTests::No, }; let build = Build::new(config); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index fb7c8ba135139..5315a3028ffa9 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -19,7 +19,7 @@ use std::process; use getopts::Options; -use {Build, DocTestsOption}; +use {Build, DocTests}; use config::Config; use metadata; use builder::Builder; @@ -62,7 +62,7 @@ pub enum Subcommand { test_args: Vec, rustc_args: Vec, fail_fast: bool, - doc_tests: DocTestsOption, + doc_tests: DocTests, }, Bench { paths: Vec, @@ -326,11 +326,11 @@ Arguments: rustc_args: matches.opt_strs("rustc-args"), fail_fast: !matches.opt_present("no-fail-fast"), doc_tests: if matches.opt_present("doc") { - DocTestsOption::Only + DocTests::Only } else if matches.opt_present("no-doc") { - DocTestsOption::No + DocTests::No } else { - DocTestsOption::Yes + DocTests::Yes } } } @@ -418,10 +418,10 @@ impl Subcommand { } } - pub fn doc_tests(&self) -> DocTestsOption { + pub fn doc_tests(&self) -> DocTests { match *self { Subcommand::Test { doc_tests, .. } => doc_tests, - _ => DocTestsOption::Yes, + _ => DocTests::Yes, } } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index ff9a262e2cc76..e53fef0678613 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -211,7 +211,7 @@ pub struct Compiler { } #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub enum DocTestsOption { +pub enum DocTests { // Default, run normal tests and doc tests. Yes, // Do not run any doc tests. @@ -243,7 +243,7 @@ pub struct Build { rustfmt_info: channel::GitInfo, local_rebuild: bool, fail_fast: bool, - doc_tests: DocTestsOption, + doc_tests: DocTests, verbosity: usize, // Targets for which to build. diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 2f0e3868f89ae..cbb952bab61b2 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -32,7 +32,7 @@ use dist; use native; use tool::{self, Tool}; use util::{self, dylib_path, dylib_path_var}; -use {Mode, DocTestsOption}; +use {Mode, DocTests}; use toolstate::ToolState; const ADB_TEST_DIR: &str = "/data/tmp/work"; @@ -1520,13 +1520,13 @@ impl Step for Crate { cargo.arg("--no-fail-fast"); } match builder.doc_tests { - DocTestsOption::Only => { + DocTests::Only => { cargo.arg("--doc"); } - DocTestsOption::No => { + DocTests::No => { cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]); } - DocTestsOption::Yes => {} + DocTests::Yes => {} } cargo.arg("-p").arg(krate);