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.
This commit is contained in:
bors
2018-05-06 06:33:53 +00:00
16 changed files with 345 additions and 221 deletions

View File

@@ -64,6 +64,10 @@ The script accepts commands, flags, and arguments to determine what to do:
# execute tests in the standard library in stage0 # execute tests in the standard library in stage0
./x.py test --stage 0 src/libstd ./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 # execute all doc tests
./x.py test src/doc ./x.py test src/doc
``` ```

View File

@@ -25,7 +25,7 @@ use compile;
use install; use install;
use dist; use dist;
use util::{exe, libdir, add_lib_path}; use util::{exe, libdir, add_lib_path};
use {Build, Mode}; use {Build, Mode, DocTests};
use cache::{INTERNER, Interned, Cache}; use cache::{INTERNER, Interned, Cache};
use check; use check;
use test; use test;
@@ -591,6 +591,8 @@ impl<'a> Builder<'a> {
format!("{} {}", env::var("RUSTFLAGS").unwrap_or_default(), extra_args)); 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 // Customize the compiler we're running. Specify the compiler to cargo
// as our shim and then pass it some various options used to configure // as our shim and then pass it some various options used to configure
// how the actual compiler itself is called. // how the actual compiler itself is called.
@@ -607,7 +609,7 @@ impl<'a> Builder<'a> {
.env("RUSTC_LIBDIR", self.rustc_libdir(compiler)) .env("RUSTC_LIBDIR", self.rustc_libdir(compiler))
.env("RUSTC_RPATH", self.config.rust_rpath.to_string()) .env("RUSTC_RPATH", self.config.rust_rpath.to_string())
.env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc")) .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) self.rustdoc(compiler.host)
} else { } else {
PathBuf::from("/path/to/nowhere/rustdoc/not/required") 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 { if let Some(ref error_format) = self.config.rustc_error_format {
cargo.env("RUSTC_ERROR_FORMAT", 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))); cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.config.build)));
} }
@@ -1407,4 +1409,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"),
},
]);
}
} }

View File

@@ -19,7 +19,7 @@ use std::process;
use getopts::Options; use getopts::Options;
use Build; use {Build, DocTests};
use config::Config; use config::Config;
use metadata; use metadata;
use builder::Builder; use builder::Builder;
@@ -62,7 +62,7 @@ pub enum Subcommand {
test_args: Vec<String>, test_args: Vec<String>,
rustc_args: Vec<String>, rustc_args: Vec<String>,
fail_fast: bool, fail_fast: bool,
doc_tests: bool, doc_tests: DocTests,
}, },
Bench { Bench {
paths: Vec<PathBuf>, paths: Vec<PathBuf>,
@@ -171,7 +171,8 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
"extra options to pass the compiler when running tests", "extra options to pass the compiler when running tests",
"ARGS", "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"); }, "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
"clean" => { opts.optflag("", "all", "clean all build artifacts"); }, "clean" => { opts.optflag("", "all", "clean all build artifacts"); },
@@ -324,7 +325,13 @@ Arguments:
test_args: matches.opt_strs("test-args"), test_args: matches.opt_strs("test-args"),
rustc_args: matches.opt_strs("rustc-args"), rustc_args: matches.opt_strs("rustc-args"),
fail_fast: !matches.opt_present("no-fail-fast"), 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" => { "bench" => {
@@ -411,10 +418,10 @@ impl Subcommand {
} }
} }
pub fn doc_tests(&self) -> bool { pub fn doc_tests(&self) -> DocTests {
match *self { match *self {
Subcommand::Test { doc_tests, .. } => doc_tests, Subcommand::Test { doc_tests, .. } => doc_tests,
_ => false, _ => DocTests::Yes,
} }
} }
} }

View File

@@ -210,6 +210,16 @@ pub struct Compiler {
host: Interned<String>, 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. /// Global configuration for the build system.
/// ///
/// This structure transitively contains all 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, rustfmt_info: channel::GitInfo,
local_rebuild: bool, local_rebuild: bool,
fail_fast: bool, fail_fast: bool,
doc_tests: bool, doc_tests: DocTests,
verbosity: usize, verbosity: usize,
// Targets for which to build. // Targets for which to build.
@@ -294,7 +304,7 @@ impl Crate {
/// ///
/// These entries currently correspond to the various output directories of the /// These entries currently correspond to the various output directories of the
/// build system, with each mod generating output in a different directory. /// 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 { pub enum Mode {
/// Build the standard library, placing output in the "stageN-std" directory. /// Build the standard library, placing output in the "stageN-std" directory.
Libstd, Libstd,

View File

@@ -32,13 +32,13 @@ use dist;
use native; use native;
use tool::{self, Tool}; use tool::{self, Tool};
use util::{self, dylib_path, dylib_path_var}; use util::{self, dylib_path, dylib_path_var};
use Mode; use {Mode, DocTests};
use toolstate::ToolState; use toolstate::ToolState;
const ADB_TEST_DIR: &str = "/data/tmp/work"; const ADB_TEST_DIR: &str = "/data/tmp/work";
/// The two modes of the test runner; tests or benchmarks. /// 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 { pub enum TestKind {
/// Run `cargo test` /// Run `cargo test`
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 { pub struct Crate {
compiler: Compiler, pub compiler: Compiler,
target: Interned<String>, pub target: Interned<String>,
mode: Mode, pub mode: Mode,
test_kind: TestKind, pub test_kind: TestKind,
krate: Interned<String>, pub krate: Interned<String>,
} }
impl Step for Crate { impl Step for Crate {
@@ -1519,8 +1519,14 @@ impl Step for Crate {
if test_kind.subcommand() == "test" && !builder.fail_fast { if test_kind.subcommand() == "test" && !builder.fail_fast {
cargo.arg("--no-fail-fast"); cargo.arg("--no-fail-fast");
} }
if builder.doc_tests { match builder.doc_tests {
cargo.arg("--doc"); DocTests::Only => {
cargo.arg("--doc");
}
DocTests::No => {
cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
}
DocTests::Yes => {}
} }
cargo.arg("-p").arg(krate); cargo.arg("-p").arg(krate);

View File

@@ -50,6 +50,15 @@
// Since libcore defines many fundamental lang items, all tests live in a // Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues. // 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")] #![stable(feature = "core", since = "1.6.0")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",

View File

@@ -135,85 +135,3 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
// find the byte before the point the body loop stopped // find the byte before the point the body loop stopped
text[..offset].iter().rposition(|elt| *elt == x) 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..]));
}
}

View File

@@ -46,6 +46,7 @@
#![feature(reverse_bits)] #![feature(reverse_bits)]
#![feature(inclusive_range_methods)] #![feature(inclusive_range_methods)]
#![feature(iterator_find_map)] #![feature(iterator_find_map)]
#![feature(slice_internals)]
extern crate core; extern crate core;
extern crate test; extern crate test;
@@ -74,4 +75,5 @@ mod result;
mod slice; mod slice;
mod str; mod str;
mod str_lossy; mod str_lossy;
mod time;
mod tuple; mod tuple;

View File

@@ -98,6 +98,7 @@ mod tests {
} }
#[test] #[test]
#[cfg(not(stage0))]
fn test_reverse_bits() { fn test_reverse_bits() {
assert_eq!(A.reverse_bits().reverse_bits(), A); assert_eq!(A.reverse_bits().reverse_bits(), A);
assert_eq!(B.reverse_bits().reverse_bits(), B); assert_eq!(B.reverse_bits().reverse_bits(), B);

View File

@@ -550,3 +550,89 @@ fn sort_unstable() {
v.sort_unstable(); v.sort_unstable();
assert!(v == [0xDEADBEEF]); 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..]));
}
}
}

124
src/libcore/tests/time.rs Normal file
View File

@@ -0,0 +1,124 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
let _ = Duration::new(0, 0) - Duration::new(0, 1);
}
#[test]
#[should_panic]
fn sub_bad2() {
let _ = 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);
}

View File

@@ -481,119 +481,3 @@ impl<'a> Sum<&'a Duration> for Duration {
iter.fold(Duration::new(0, 0), |a, b| a + *b) 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);
}
}

View File

@@ -330,10 +330,10 @@
// with a rustc without jemalloc. // with a rustc without jemalloc.
// FIXME(#44236) shouldn't need MSVC logic // FIXME(#44236) shouldn't need MSVC logic
#![cfg_attr(all(not(target_env = "msvc"), #![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))] feature(global_allocator))]
#[cfg(all(not(target_env = "msvc"), #[cfg(all(not(target_env = "msvc"),
any(stage0, feature = "force_alloc_system")))] any(all(stage0, not(test)), feature = "force_alloc_system")))]
#[global_allocator] #[global_allocator]
static ALLOC: alloc_system::System = alloc_system::System; static ALLOC: alloc_system::System = alloc_system::System;

View File

@@ -51,6 +51,7 @@ pub mod pal;
pub mod deps; pub mod deps;
pub mod ui_tests; pub mod ui_tests;
pub mod unstable_book; pub mod unstable_book;
pub mod libcoretest;
fn filter_dirs(path: &Path) -> bool { fn filter_dirs(path: &Path) -> bool {
let skip = [ let skip = [

View File

@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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()
);
}
},
);
}

View File

@@ -41,6 +41,7 @@ fn main() {
features::check(&path, &mut bad, quiet); features::check(&path, &mut bad, quiet);
pal::check(&path, &mut bad); pal::check(&path, &mut bad);
unstable_book::check(&path, &mut bad); unstable_book::check(&path, &mut bad);
libcoretest::check(&path, &mut bad);
if !args.iter().any(|s| *s == "--no-vendor") { if !args.iter().any(|s| *s == "--no-vendor") {
deps::check(&path, &mut bad); deps::check(&path, &mut bad);
} }