Auto merge of #86272 - nagisa:nagisa/tidy-llvm-components, r=Mark-Simulacrum

tidy: verify that test revisions with --target have associated needs-llvm-components directives

This ensures that people who tend to write `--target` `#[no_core]` tests don't miss specifying the `needs-llvm-components` directive. This is necessary for the test suite to pass when LLVM is compiled with a subset of components enabled.

While here I also took the opportunity to implement a more fine-grained handling of the ignore directives, so that they are evaluated for each revision, rather than for the entire test. With this even if people have `arm` component disabled, only the revision that depends on the arm component will not run.

Fixes https://github.com/rust-lang/rust/issues/82405
This commit is contained in:
bors 2021-06-24 22:42:26 +00:00
commit d4e7cb3254
39 changed files with 517 additions and 407 deletions

View file

@ -2,8 +2,9 @@
// revisions: mips32 mips64
// assembly-output: emit-asm
//[mips32] compile-flags: --target mips-unknown-linux-gnu
//[mips32] needs-llvm-components: mips
//[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
// needs-llvm-components: mips
//[mips64] needs-llvm-components: mips
#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
#![crate_type = "rlib"]

View file

@ -2,8 +2,9 @@
// revisions: powerpc powerpc64
// assembly-output: emit-asm
//[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
//[powerpc] needs-llvm-components: powerpc
//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
// needs-llvm-components: powerpc
//[powerpc64] needs-llvm-components: powerpc
#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
#![crate_type = "rlib"]

View file

@ -2,9 +2,10 @@
// revisions: riscv64 riscv32
// assembly-output: emit-asm
//[riscv64] compile-flags: --target riscv64imac-unknown-none-elf
//[riscv64] needs-llvm-components: riscv
//[riscv32] compile-flags: --target riscv32imac-unknown-none-elf
//[riscv32] needs-llvm-components: riscv
// compile-flags: -C target-feature=+d
// needs-llvm-components: riscv
// min-system-llvm-version: 12.0
#![feature(no_core, lang_items, rustc_attrs)]

View file

@ -3,7 +3,9 @@
// assembly-output: emit-asm
// compile-flags: -O
//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
//[x86_64] needs-llvm-components: x86
//[i686] compile-flags: --target i686-unknown-linux-gnu
//[i686] needs-llvm-components: x86
// compile-flags: -C llvm-args=--x86-asm-syntax=intel
// compile-flags: -C target-feature=+avx512bw

View file

@ -2,7 +2,9 @@
// revisions: x86_64 i686
// assembly-output: emit-asm
//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
//[x86_64] needs-llvm-components: x86
//[i686] compile-flags: --target i686-unknown-linux-gnu
//[i686] needs-llvm-components: x86
// compile-flags: -C llvm-args=--x86-asm-syntax=intel
// compile-flags: -C target-feature=+avx512bw

View file

@ -1,10 +1,12 @@
// min-llvm-version: 12.0.0
// needs-llvm-components: aarch64 x86 powerpc
// revisions: x64 A64 ppc64le
// assembly-output: emit-asm
// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static
// [x64] needs-llvm-components: x86
// [A64] compile-flags: --target aarch64-unknown-linux-gnu -Crelocation-model=static
// [A64] needs-llvm-components: aarch64
// [ppc64le] compile-flags: --target powerpc64le-unknown-linux-gnu -Crelocation-model=static
// [ppc64le] needs-llvm-components: powerpc
#![feature(no_core, lang_items)]
#![no_core]

View file

@ -1,13 +1,16 @@
// Checks if the correct annotation for the efiapi ABI is passed to llvm.
// revisions:x86_64 i686 aarch64 arm riscv
// needs-llvm-components: aarch64 arm riscv
//[x86_64] compile-flags: --target x86_64-unknown-uefi
//[x86_64] needs-llvm-components: aarch64 arm riscv
//[i686] compile-flags: --target i686-unknown-linux-musl
//[i686] needs-llvm-components: aarch64 arm riscv
//[aarch64] compile-flags: --target aarch64-unknown-none
//[aarch64] needs-llvm-components: aarch64 arm riscv
//[arm] compile-flags: --target armv7r-none-eabi
//[arm] needs-llvm-components: aarch64 arm riscv
//[riscv] compile-flags: --target riscv64gc-unknown-none-elf
//[riscv] needs-llvm-components: aarch64 arm riscv
// compile-flags: -C no-prepopulate-passes
#![crate_type = "lib"]

View file

@ -1,5 +1,6 @@
// FIXME(nagisa): remove the flags here once all targets support `asm!`.
// FIXME(nagisa): remove the flags below once all targets support `asm!`.
// compile-flags: --target x86_64-unknown-linux-gnu
// needs-llvm-components: x86
// Verify we sanitize the special tokens for the LLVM inline-assembly, ensuring people won't
// inadvertently rely on the LLVM-specific syntax and features.

View file

@ -1,8 +1,9 @@
// revisions: WINDOWS ANDROID
// needs-llvm-components: x86 arm
// compile-flags: -C panic=abort
// [WINDOWS] compile-flags: --target=x86_64-pc-windows-msvc
// [WINDOWS] needs-llvm-components: x86
// [ANDROID] compile-flags: --target=armv7-linux-androideabi
// [ANDROID] needs-llvm-components: arm
#![feature(no_core, lang_items)]
#![crate_type = "lib"]

View file

@ -3,6 +3,7 @@
// See issue #60235.
// compile-flags: -O --target=i686-apple-darwin --crate-type=rlib
// needs-llvm-components: x86
// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9
#![feature(no_core, lang_items)]
#![no_core]

View file

@ -3,6 +3,7 @@
// See issue #60235.
// compile-flags: -O --target=i686-apple-darwin --crate-type=rlib
// needs-llvm-components: x86
// unset-rustc-env:MACOSX_DEPLOYMENT_TARGET
#![feature(no_core, lang_items)]
#![no_core]

View file

@ -1,9 +1,8 @@
//
// Checks that we correctly codegen extern "C" functions returning structs.
// See issue #52638.
// only-sparc64
// compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib
// needs-llvm-components: sparc
#![feature(no_core, lang_items)]
#![no_core]

View file

@ -3,6 +3,7 @@
// See issue #60235.
// compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib
// needs-llvm-components: x86
// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9
#![feature(no_core, lang_items)]
#![no_core]

View file

@ -3,6 +3,7 @@
// See issue #60235.
// compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib
// needs-llvm-components: x86
// unset-rustc-env:MACOSX_DEPLOYMENT_TARGET
#![feature(no_core, lang_items)]
#![no_core]

View file

@ -13,7 +13,7 @@ LL | .intel_syntax noprefix
| ^
error: unknown directive
--> $DIR/inline-syntax.rs:29:15
--> $DIR/inline-syntax.rs:31:15
|
LL | asm!(".intel_syntax noprefix", "nop");
| ^
@ -25,7 +25,7 @@ LL | .intel_syntax noprefix
| ^
error: unknown directive
--> $DIR/inline-syntax.rs:32:15
--> $DIR/inline-syntax.rs:34:15
|
LL | asm!(".intel_syntax aaa noprefix", "nop");
| ^
@ -37,7 +37,7 @@ LL | .intel_syntax aaa noprefix
| ^
error: unknown directive
--> $DIR/inline-syntax.rs:35:15
--> $DIR/inline-syntax.rs:37:15
|
LL | asm!(".att_syntax noprefix", "nop");
| ^
@ -49,7 +49,7 @@ LL | .att_syntax noprefix
| ^
error: unknown directive
--> $DIR/inline-syntax.rs:38:15
--> $DIR/inline-syntax.rs:40:15
|
LL | asm!(".att_syntax bbb noprefix", "nop");
| ^
@ -61,7 +61,7 @@ LL | .att_syntax bbb noprefix
| ^
error: unknown directive
--> $DIR/inline-syntax.rs:41:15
--> $DIR/inline-syntax.rs:43:15
|
LL | asm!(".intel_syntax noprefix; nop");
| ^
@ -73,7 +73,7 @@ LL | .intel_syntax noprefix; nop
| ^
error: unknown directive
--> $DIR/inline-syntax.rs:47:13
--> $DIR/inline-syntax.rs:49:13
|
LL | .intel_syntax noprefix
| ^

View file

@ -1,11 +1,13 @@
// needs-llvm-components: arm
// revisions: x86_64 arm
//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
//[x86_64] check-pass
//[x86_64] needs-llvm-components: x86
//[x86_64_allowed] compile-flags: --target x86_64-unknown-linux-gnu
//[x86_64_allowed] check-pass
//[x86_64_allowed] needs-llvm-components: x86
//[arm] compile-flags: --target armv7-unknown-linux-gnueabihf
//[arm] build-fail
//[arm] needs-llvm-components: arm
#![feature(no_core, lang_items, rustc_attrs)]
#![crate_type = "rlib"]

View file

@ -1,5 +1,5 @@
warning: avoid using `.intel_syntax`, Intel syntax is the default
--> $DIR/inline-syntax.rs:55:14
--> $DIR/inline-syntax.rs:57:14
|
LL | global_asm!(".intel_syntax noprefix", "nop");
| ^^^^^^^^^^^^^^^^^^^^^^
@ -7,37 +7,37 @@ LL | global_asm!(".intel_syntax noprefix", "nop");
= note: `#[warn(bad_asm_style)]` on by default
warning: avoid using `.intel_syntax`, Intel syntax is the default
--> $DIR/inline-syntax.rs:29:15
--> $DIR/inline-syntax.rs:31:15
|
LL | asm!(".intel_syntax noprefix", "nop");
| ^^^^^^^^^^^^^^^^^^^^^^
warning: avoid using `.intel_syntax`, Intel syntax is the default
--> $DIR/inline-syntax.rs:32:15
--> $DIR/inline-syntax.rs:34:15
|
LL | asm!(".intel_syntax aaa noprefix", "nop");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
--> $DIR/inline-syntax.rs:35:15
--> $DIR/inline-syntax.rs:37:15
|
LL | asm!(".att_syntax noprefix", "nop");
| ^^^^^^^^^^^^^^^^^^^^
warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
--> $DIR/inline-syntax.rs:38:15
--> $DIR/inline-syntax.rs:40:15
|
LL | asm!(".att_syntax bbb noprefix", "nop");
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: avoid using `.intel_syntax`, Intel syntax is the default
--> $DIR/inline-syntax.rs:41:15
--> $DIR/inline-syntax.rs:43:15
|
LL | asm!(".intel_syntax noprefix; nop");
| ^^^^^^^^^^^^^^^^^^^^^^
warning: avoid using `.intel_syntax`, Intel syntax is the default
--> $DIR/inline-syntax.rs:47:13
--> $DIR/inline-syntax.rs:49:13
|
LL | .intel_syntax noprefix
| ^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,8 +1,8 @@
// revisions: nll_target
// The following revisions are disabled due to missing support from two-phase beyond autorefs
// The nll_beyond revision is disabled due to missing support from two-phase beyond autorefs
//[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-beyond-autoref
//[nll_beyond] should-fail
//[nll_beyond]should-fail
//[nll_target]compile-flags: -Z borrowck=mir

View file

@ -1,13 +1,21 @@
// build-pass
// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
// only-thumbv8m.main-none-eabi
#![feature(abi_c_cmse_nonsecure_call)]
#![no_std]
// needs-llvm-components: arm
#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)]
#![no_core]
#[lang="sized"]
pub trait Sized { }
#[lang="copy"]
pub trait Copy { }
extern "rust-intrinsic" {
pub fn transmute<T, U>(e: T) -> U;
}
#[no_mangle]
pub fn test(a: u32, b: u32, c: u32, d: u32) -> u32 {
let non_secure_function = unsafe {
core::mem::transmute::<usize, extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u32>(
transmute::<usize, extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u32>(
0x10000004,
)
};

View file

@ -1,12 +1,22 @@
// build-fail
// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
// only-thumbv8m.main-none-eabi
#![feature(abi_c_cmse_nonsecure_call)]
#![no_std]
// needs-llvm-components: arm
// min-llvm-version: 11.0
#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)]
#![no_core]
#[lang="sized"]
pub trait Sized { }
#[lang="copy"]
pub trait Copy { }
extern "rust-intrinsic" {
pub fn transmute<T, U>(e: T) -> U;
}
#[no_mangle]
pub fn test(a: u32, b: u32, c: u32, d: u32, e: u32) -> u32 {
let non_secure_function = unsafe {
core::mem::transmute::<
transmute::<
usize,
extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32>
(

View file

@ -1,6 +1,8 @@
// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
// only-thumbv8m.main-none-eabi
#![feature(abi_c_cmse_nonsecure_call)]
#![no_std]
// needs-llvm-components: arm
#![feature(abi_c_cmse_nonsecure_call, lang_items, no_core)]
#![no_core]
#[lang="sized"]
trait Sized { }
pub extern "C-cmse-nonsecure-call" fn test() {} //~ ERROR [E0781]

View file

@ -1,8 +1,8 @@
error[E0781]: the `"cmse-nonsecure-call"` ABI is only allowed on function pointers.
--> $DIR/wrong-abi-location-1.rs:6:1
error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers.
--> $DIR/wrong-abi-location-1.rs:8:1
|
LL | pub extern "C-cmse-nonsecure-call" fn test() {} //~ ERROR [E0781]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | pub extern "C-cmse-nonsecure-call" fn test() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -1,7 +1,9 @@
// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
// only-thumbv8m.main-none-eabi
#![feature(abi_c_cmse_nonsecure_call)]
#![no_std]
// needs-llvm-components: arm
#![feature(abi_c_cmse_nonsecure_call, lang_items, no_core)]
#![no_core]
#[lang="sized"]
trait Sized { }
extern "C-cmse-nonsecure-call" { //~ ERROR [E0781]
fn test();

View file

@ -1,8 +1,8 @@
error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers.
--> $DIR/wrong-abi-location-2.rs:6:1
--> $DIR/wrong-abi-location-2.rs:8:1
|
LL | / extern "C-cmse-nonsecure-call" {
LL | | fn test(); //~ ERROR [E0781]
LL | | fn test();
LL | | }
| |_^

View file

@ -1,11 +1,15 @@
// build-pass
// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
// only-thumbv8m.main-none-eabi
#![feature(cmse_nonsecure_entry)]
#![no_std]
// needs-llvm-components: arm
#![feature(cmse_nonsecure_entry, no_core, lang_items)]
#![no_core]
#[lang="sized"]
trait Sized { }
#[lang="copy"]
trait Copy { }
#[no_mangle]
#[cmse_nonsecure_entry]
pub extern "C" fn entry_function(a: u32, b: u32, c: u32, d: u32) -> u32 {
a + b + c + d
pub extern "C" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
d
}

View file

@ -1,10 +1,16 @@
// build-fail
// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
// only-thumbv8m.main-none-eabi
#![feature(cmse_nonsecure_entry)]
#![no_std]
// needs-llvm-components: arm
// min-llvm-version: 11.0
#![feature(cmse_nonsecure_entry, no_core, lang_items)]
#![no_core]
#[lang="sized"]
trait Sized { }
#[lang="copy"]
trait Copy { }
#[no_mangle]
#[cmse_nonsecure_entry]
pub extern "C" fn entry_function(a: u32, b: u32, c: u32, d: u32, e: u32) -> u32 { //~ ERROR
a + b + c + d + e
pub extern "C" fn entry_function(_: u32, _: u32, _: u32, _: u32, e: u32) -> u32 {
e
}

View file

@ -1,10 +1,13 @@
// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
// only-thumbv8m.main-none-eabi
#![feature(cmse_nonsecure_entry)]
#![no_std]
// needs-llvm-components: arm
#![feature(cmse_nonsecure_entry, no_core, lang_items)]
#![no_core]
#[lang="sized"]
trait Sized { }
#[no_mangle]
#[cmse_nonsecure_entry]
pub fn entry_function(a: u32, b: u32, c: u32, d: u32) -> u32 { //~ ERROR [E0776]
a + b + c + d
//~^ ERROR `#[cmse_nonsecure_entry]` requires C ABI [E0776]
pub fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
d
}

View file

@ -1,5 +1,5 @@
error[E0776]: `#[cmse_nonsecure_entry]` functions require C ABI
--> $DIR/wrong-abi.rs:7:1
error[E0776]: `#[cmse_nonsecure_entry]` requires C ABI
--> $DIR/wrong-abi.rs:9:1
|
LL | #[cmse_nonsecure_entry]
| ^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,4 +1,5 @@
// compile-flags: --target x86_64-unknown-uefi
// needs-llvm-components: x86
// rustc-env:CARGO=/usr/bin/cargo
// rustc-env:RUSTUP_HOME=/home/bors/.rustup
#![no_core]

View file

@ -1,5 +1,5 @@
error[E0463]: can't find crate for `core`
--> $DIR/missing-std.rs:5:1
--> $DIR/missing-std.rs:6:1
|
LL | extern crate core;
| ^^^^^^^^^^^^^^^^^^ can't find crate

View file

@ -1,4 +1,5 @@
// compile-flags: -Z sanitizer=address -C target-feature=+crt-static --target x86_64-unknown-linux-gnu
// needs-llvm-components: x86
#![feature(no_core)]
#![no_core]

View file

@ -1,4 +1,5 @@
// compile-flags: -Z sanitizer=address -Z sanitizer=memory --target x86_64-unknown-linux-gnu
// needs-llvm-components: x86
// error-pattern: error: `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory`
#![feature(no_core)]

View file

@ -1,4 +1,5 @@
// compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu
// needs-llvm-components: x86
// error-pattern: error: leak sanitizer is not supported for this target
#![feature(no_core)]
#![no_core]

View file

@ -27,8 +27,6 @@ enum ParsedNameDirective {
/// the test.
#[derive(Default)]
pub struct EarlyProps {
pub ignore: bool,
pub should_fail: bool,
pub aux: Vec<String>,
pub aux_crate: Vec<(String, String)>,
pub revisions: Vec<String>,
@ -36,251 +34,22 @@ pub struct EarlyProps {
impl EarlyProps {
pub fn from_file(config: &Config, testfile: &Path) -> Self {
let file = File::open(testfile).unwrap();
let file = File::open(testfile).expect("open test file to parse earlyprops");
Self::from_reader(config, testfile, file)
}
pub fn from_reader<R: Read>(config: &Config, testfile: &Path, rdr: R) -> Self {
let mut props = EarlyProps::default();
let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some();
let rustc_has_sanitizer_support = env::var_os("RUSTC_SANITIZER_SUPPORT").is_some();
let has_asm_support = util::has_asm_support(&config.target);
let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_hwasan = util::HWASAN_SUPPORTED_TARGETS.contains(&&*config.target);
// for `-Z gcc-ld=lld`
let has_rust_lld = config
.compile_lib_path
.join("rustlib")
.join(&config.target)
.join("bin")
.join("gcc-ld")
.join(if config.host.contains("windows") { "ld.exe" } else { "ld" })
.exists();
iter_header(testfile, None, rdr, &mut |ln| {
// we should check if any only-<platform> exists and if it exists
// and does not matches the current platform, skip the test
if !props.ignore {
props.ignore = match config.parse_cfg_name_directive(ln, "ignore") {
ParsedNameDirective::Match => true,
ParsedNameDirective::NoMatch => props.ignore,
};
if config.has_cfg_prefix(ln, "only") {
props.ignore = match config.parse_cfg_name_directive(ln, "only") {
ParsedNameDirective::Match => props.ignore,
ParsedNameDirective::NoMatch => true,
};
}
if ignore_llvm(config, ln) {
props.ignore = true;
}
if config.run_clang_based_tests_with.is_none()
&& config.parse_needs_matching_clang(ln)
{
props.ignore = true;
}
if !has_asm_support && config.parse_name_directive(ln, "needs-asm-support") {
props.ignore = true;
}
if !rustc_has_profiler_support && config.parse_needs_profiler_support(ln) {
props.ignore = true;
}
if !config.run_enabled() && config.parse_name_directive(ln, "needs-run-enabled") {
props.ignore = true;
}
if !rustc_has_sanitizer_support
&& config.parse_name_directive(ln, "needs-sanitizer-support")
{
props.ignore = true;
}
if !has_asan && config.parse_name_directive(ln, "needs-sanitizer-address") {
props.ignore = true;
}
if !has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak") {
props.ignore = true;
}
if !has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory") {
props.ignore = true;
}
if !has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread") {
props.ignore = true;
}
if !has_hwasan && config.parse_name_directive(ln, "needs-sanitizer-hwaddress") {
props.ignore = true;
}
if config.target_panic == PanicStrategy::Abort
&& config.parse_name_directive(ln, "needs-unwind")
{
props.ignore = true;
}
if config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln) {
props.ignore = true;
}
if config.debugger == Some(Debugger::Cdb) && ignore_cdb(config, ln) {
props.ignore = true;
}
if config.debugger == Some(Debugger::Gdb) && ignore_gdb(config, ln) {
props.ignore = true;
}
if config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln) {
props.ignore = true;
}
if !has_rust_lld && config.parse_name_directive(ln, "needs-rust-lld") {
props.ignore = true;
}
}
iter_header(testfile, rdr, &mut |_, ln| {
if let Some(s) = config.parse_aux_build(ln) {
props.aux.push(s);
}
if let Some(ac) = config.parse_aux_crate(ln) {
props.aux_crate.push(ac);
}
config.parse_and_update_revisions(ln, &mut props.revisions);
props.should_fail = props.should_fail || config.parse_name_directive(ln, "should-fail");
});
return props;
fn ignore_cdb(config: &Config, line: &str) -> bool {
if let Some(actual_version) = config.cdb_version {
if let Some(min_version) = line.strip_prefix("min-cdb-version:").map(str::trim) {
let min_version = extract_cdb_version(min_version).unwrap_or_else(|| {
panic!("couldn't parse version range: {:?}", min_version);
});
// Ignore if actual version is smaller than the minimum
// required version
return actual_version < min_version;
}
}
false
}
fn ignore_gdb(config: &Config, line: &str) -> bool {
if let Some(actual_version) = config.gdb_version {
if let Some(rest) = line.strip_prefix("min-gdb-version:").map(str::trim) {
let (start_ver, end_ver) = extract_version_range(rest, extract_gdb_version)
.unwrap_or_else(|| {
panic!("couldn't parse version range: {:?}", rest);
});
if start_ver != end_ver {
panic!("Expected single GDB version")
}
// Ignore if actual version is smaller than the minimum
// required version
return actual_version < start_ver;
} else if let Some(rest) = line.strip_prefix("ignore-gdb-version:").map(str::trim) {
let (min_version, max_version) =
extract_version_range(rest, extract_gdb_version).unwrap_or_else(|| {
panic!("couldn't parse version range: {:?}", rest);
});
if max_version < min_version {
panic!("Malformed GDB version range: max < min")
}
return actual_version >= min_version && actual_version <= max_version;
}
}
false
}
fn ignore_lldb(config: &Config, line: &str) -> bool {
if let Some(actual_version) = config.lldb_version {
if let Some(min_version) = line.strip_prefix("min-lldb-version:").map(str::trim) {
let min_version = min_version.parse().unwrap_or_else(|e| {
panic!(
"Unexpected format of LLDB version string: {}\n{:?}",
min_version, e
);
});
// Ignore if actual version is smaller the minimum required
// version
actual_version < min_version
} else {
line.starts_with("rust-lldb") && !config.lldb_native_rust
}
} else {
false
}
}
fn ignore_llvm(config: &Config, line: &str) -> bool {
if config.system_llvm && line.starts_with("no-system-llvm") {
return true;
}
if let Some(needed_components) =
config.parse_name_value_directive(line, "needs-llvm-components")
{
let components: HashSet<_> = config.llvm_components.split_whitespace().collect();
if let Some(missing_component) = needed_components
.split_whitespace()
.find(|needed_component| !components.contains(needed_component))
{
if env::var_os("COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS").is_some() {
panic!("missing LLVM component: {}", missing_component);
}
return true;
}
}
if let Some(actual_version) = config.llvm_version {
if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) {
let min_version = extract_llvm_version(rest).unwrap();
// Ignore if actual version is smaller the minimum required
// version
actual_version < min_version
} else if let Some(rest) =
line.strip_prefix("min-system-llvm-version:").map(str::trim)
{
let min_version = extract_llvm_version(rest).unwrap();
// Ignore if using system LLVM and actual version
// is smaller the minimum required version
config.system_llvm && actual_version < min_version
} else if let Some(rest) = line.strip_prefix("ignore-llvm-version:").map(str::trim)
{
// Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
let (v_min, v_max) = extract_version_range(rest, extract_llvm_version)
.unwrap_or_else(|| {
panic!("couldn't parse version range: {:?}", rest);
});
if v_max < v_min {
panic!("Malformed LLVM version range: max < min")
}
// Ignore if version lies inside of range.
actual_version >= v_min && actual_version <= v_max
} else {
false
}
} else {
false
}
}
}
}
@ -440,7 +209,11 @@ impl TestProps {
if !testfile.is_dir() {
let file = File::open(testfile).unwrap();
iter_header(testfile, cfg, file, &mut |ln| {
iter_header(testfile, file, &mut |revision, ln| {
if revision.is_some() && revision != cfg {
return;
}
if let Some(ep) = config.parse_error_pattern(ln) {
self.error_patterns.push(ep);
}
@ -672,12 +445,12 @@ impl TestProps {
}
}
fn iter_header<R: Read>(testfile: &Path, cfg: Option<&str>, rdr: R, it: &mut dyn FnMut(&str)) {
fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>, &str)) {
if testfile.is_dir() {
return;
}
let comment = if testfile.to_string_lossy().ends_with(".rs") { "//" } else { "#" };
let comment = if testfile.extension().map(|e| e == "rs") == Some(true) { "//" } else { "#" };
let mut rdr = BufReader::new(rdr);
let mut ln = String::new();
@ -699,18 +472,12 @@ fn iter_header<R: Read>(testfile: &Path, cfg: Option<&str>, rdr: R, it: &mut dyn
if let Some(close_brace) = ln.find(']') {
let open_brace = ln.find('[').unwrap();
let lncfg = &ln[open_brace + 1..close_brace];
let matches = match cfg {
Some(s) => s == &lncfg[..],
None => false,
};
if matches {
it(ln[(close_brace + 1)..].trim_start());
}
it(Some(lncfg), ln[(close_brace + 1)..].trim_start());
} else {
panic!("malformed condition directive: expected `{}[foo]`, found `{}`", comment, ln)
}
} else if ln.starts_with(comment) {
it(ln[comment.len()..].trim_start());
it(None, ln[comment.len()..].trim_start());
}
}
}
@ -1026,11 +793,12 @@ pub fn extract_llvm_version(version: &str) -> Option<u32> {
Some(version)
}
// Takes a directive of the form "<version1> [- <version2>]",
// returns the numeric representation of <version1> and <version2> as
// tuple: (<version1> as u32, <version2> as u32)
// If the <version2> part is omitted, the second component of the tuple
// is the same as <version1>.
/// Takes a directive of the form "<version1> [- <version2>]",
/// returns the numeric representation of <version1> and <version2> as
/// tuple: (<version1> as u32, <version2> as u32)
///
/// If the <version2> part is omitted, the second component of the tuple
/// is the same as <version1>.
fn extract_version_range<F>(line: &str, parse: F) -> Option<(u32, u32)>
where
F: Fn(&str) -> Option<u32>,
@ -1056,3 +824,199 @@ where
Some((min, max))
}
pub fn make_test_description<R: Read>(
config: &Config,
name: test::TestName,
path: &Path,
src: R,
cfg: Option<&str>,
) -> test::TestDesc {
let mut ignore = false;
let mut should_fail = false;
let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some();
let rustc_has_sanitizer_support = env::var_os("RUSTC_SANITIZER_SUPPORT").is_some();
let has_asm_support = util::has_asm_support(&config.target);
let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_hwasan = util::HWASAN_SUPPORTED_TARGETS.contains(&&*config.target);
// for `-Z gcc-ld=lld`
let has_rust_lld = config
.compile_lib_path
.join("rustlib")
.join(&config.target)
.join("bin")
.join("gcc-ld")
.join(if config.host.contains("windows") { "ld.exe" } else { "ld" })
.exists();
iter_header(path, src, &mut |revision, ln| {
if revision.is_some() && revision != cfg {
return;
}
ignore = match config.parse_cfg_name_directive(ln, "ignore") {
ParsedNameDirective::Match => true,
ParsedNameDirective::NoMatch => ignore,
};
if config.has_cfg_prefix(ln, "only") {
ignore = match config.parse_cfg_name_directive(ln, "only") {
ParsedNameDirective::Match => ignore,
ParsedNameDirective::NoMatch => true,
};
}
ignore |= ignore_llvm(config, ln);
ignore |=
config.run_clang_based_tests_with.is_none() && config.parse_needs_matching_clang(ln);
ignore |= !has_asm_support && config.parse_name_directive(ln, "needs-asm-support");
ignore |= !rustc_has_profiler_support && config.parse_needs_profiler_support(ln);
ignore |= !config.run_enabled() && config.parse_name_directive(ln, "needs-run-enabled");
ignore |= !rustc_has_sanitizer_support
&& config.parse_name_directive(ln, "needs-sanitizer-support");
ignore |= !has_asan && config.parse_name_directive(ln, "needs-sanitizer-address");
ignore |= !has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak");
ignore |= !has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory");
ignore |= !has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread");
ignore |= !has_hwasan && config.parse_name_directive(ln, "needs-sanitizer-hwaddress");
ignore |= config.target_panic == PanicStrategy::Abort
&& config.parse_name_directive(ln, "needs-unwind");
ignore |= config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln);
ignore |= config.debugger == Some(Debugger::Cdb) && ignore_cdb(config, ln);
ignore |= config.debugger == Some(Debugger::Gdb) && ignore_gdb(config, ln);
ignore |= config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln);
ignore |= !has_rust_lld && config.parse_name_directive(ln, "needs-rust-lld");
should_fail |= config.parse_name_directive(ln, "should-fail");
});
// The `should-fail` annotation doesn't apply to pretty tests,
// since we run the pretty printer across all tests by default.
// If desired, we could add a `should-fail-pretty` annotation.
let should_panic = match config.mode {
crate::common::Pretty => test::ShouldPanic::No,
_ if should_fail => test::ShouldPanic::Yes,
_ => test::ShouldPanic::No,
};
test::TestDesc {
name,
ignore,
should_panic,
allow_fail: false,
#[cfg(not(bootstrap))]
compile_fail: false,
#[cfg(not(bootstrap))]
no_run: false,
test_type: test::TestType::Unknown,
}
}
fn ignore_cdb(config: &Config, line: &str) -> bool {
if let Some(actual_version) = config.cdb_version {
if let Some(min_version) = line.strip_prefix("min-cdb-version:").map(str::trim) {
let min_version = extract_cdb_version(min_version).unwrap_or_else(|| {
panic!("couldn't parse version range: {:?}", min_version);
});
// Ignore if actual version is smaller than the minimum
// required version
return actual_version < min_version;
}
}
false
}
fn ignore_gdb(config: &Config, line: &str) -> bool {
if let Some(actual_version) = config.gdb_version {
if let Some(rest) = line.strip_prefix("min-gdb-version:").map(str::trim) {
let (start_ver, end_ver) = extract_version_range(rest, extract_gdb_version)
.unwrap_or_else(|| {
panic!("couldn't parse version range: {:?}", rest);
});
if start_ver != end_ver {
panic!("Expected single GDB version")
}
// Ignore if actual version is smaller than the minimum
// required version
return actual_version < start_ver;
} else if let Some(rest) = line.strip_prefix("ignore-gdb-version:").map(str::trim) {
let (min_version, max_version) = extract_version_range(rest, extract_gdb_version)
.unwrap_or_else(|| {
panic!("couldn't parse version range: {:?}", rest);
});
if max_version < min_version {
panic!("Malformed GDB version range: max < min")
}
return actual_version >= min_version && actual_version <= max_version;
}
}
false
}
fn ignore_lldb(config: &Config, line: &str) -> bool {
if let Some(actual_version) = config.lldb_version {
if let Some(min_version) = line.strip_prefix("min-lldb-version:").map(str::trim) {
let min_version = min_version.parse().unwrap_or_else(|e| {
panic!("Unexpected format of LLDB version string: {}\n{:?}", min_version, e);
});
// Ignore if actual version is smaller the minimum required
// version
actual_version < min_version
} else {
line.starts_with("rust-lldb") && !config.lldb_native_rust
}
} else {
false
}
}
fn ignore_llvm(config: &Config, line: &str) -> bool {
if config.system_llvm && line.starts_with("no-system-llvm") {
return true;
}
if let Some(needed_components) =
config.parse_name_value_directive(line, "needs-llvm-components")
{
let components: HashSet<_> = config.llvm_components.split_whitespace().collect();
if let Some(missing_component) = needed_components
.split_whitespace()
.find(|needed_component| !components.contains(needed_component))
{
if env::var_os("COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS").is_some() {
panic!("missing LLVM component: {}", missing_component);
}
return true;
}
}
if let Some(actual_version) = config.llvm_version {
if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) {
let min_version = extract_llvm_version(rest).unwrap();
// Ignore if actual version is smaller the minimum required
// version
actual_version < min_version
} else if let Some(rest) = line.strip_prefix("min-system-llvm-version:").map(str::trim) {
let min_version = extract_llvm_version(rest).unwrap();
// Ignore if using system LLVM and actual version
// is smaller the minimum required version
config.system_llvm && actual_version < min_version
} else if let Some(rest) = line.strip_prefix("ignore-llvm-version:").map(str::trim) {
// Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
let (v_min, v_max) =
extract_version_range(rest, extract_llvm_version).unwrap_or_else(|| {
panic!("couldn't parse version range: {:?}", rest);
});
if v_max < v_min {
panic!("Malformed LLVM version range: max < min")
}
// Ignore if version lies inside of range.
actual_version >= v_min && actual_version <= v_max
} else {
false
}
} else {
false
}
}

View file

@ -1,7 +1,7 @@
use std::path::Path;
use crate::common::{Config, Debugger};
use crate::header::{parse_normalization_string, EarlyProps};
use crate::header::{make_test_description, parse_normalization_string, EarlyProps};
#[test]
fn test_parse_normalization_string() {
@ -66,6 +66,13 @@ fn parse_rs(config: &Config, contents: &str) -> EarlyProps {
EarlyProps::from_reader(config, Path::new("a.rs"), bytes)
}
fn check_ignore(config: &Config, contents: &str) -> bool {
let tn = test::DynTestName(String::new());
let p = Path::new("a.rs");
let d = make_test_description(&config, tn, p, std::io::Cursor::new(contents), None);
d.ignore
}
fn parse_makefile(config: &Config, contents: &str) -> EarlyProps {
let bytes = contents.as_bytes();
EarlyProps::from_reader(config, Path::new("Makefile"), bytes)
@ -74,9 +81,13 @@ fn parse_makefile(config: &Config, contents: &str) -> EarlyProps {
#[test]
fn should_fail() {
let config = config();
let tn = test::DynTestName(String::new());
let p = Path::new("a.rs");
assert!(!parse_rs(&config, "").should_fail);
assert!(parse_rs(&config, "// should-fail").should_fail);
let d = make_test_description(&config, tn.clone(), p, std::io::Cursor::new(""), None);
assert_eq!(d.should_panic, test::ShouldPanic::No);
let d = make_test_description(&config, tn, p, std::io::Cursor::new("// should-fail"), None);
assert_eq!(d.should_panic, test::ShouldPanic::Yes);
}
#[test]
@ -112,10 +123,10 @@ fn no_system_llvm() {
let mut config = config();
config.system_llvm = false;
assert!(!parse_rs(&config, "// no-system-llvm").ignore);
assert!(!check_ignore(&config, "// no-system-llvm"));
config.system_llvm = true;
assert!(parse_rs(&config, "// no-system-llvm").ignore);
assert!(check_ignore(&config, "// no-system-llvm"));
}
#[test]
@ -123,16 +134,16 @@ fn llvm_version() {
let mut config = config();
config.llvm_version = Some(80102);
assert!(parse_rs(&config, "// min-llvm-version: 9.0").ignore);
assert!(check_ignore(&config, "// min-llvm-version: 9.0"));
config.llvm_version = Some(90001);
assert!(parse_rs(&config, "// min-llvm-version: 9.2").ignore);
assert!(check_ignore(&config, "// min-llvm-version: 9.2"));
config.llvm_version = Some(90301);
assert!(!parse_rs(&config, "// min-llvm-version: 9.2").ignore);
assert!(!check_ignore(&config, "// min-llvm-version: 9.2"));
config.llvm_version = Some(100000);
assert!(!parse_rs(&config, "// min-llvm-version: 9.0").ignore);
assert!(!check_ignore(&config, "// min-llvm-version: 9.0"));
}
#[test]
@ -140,16 +151,16 @@ fn ignore_target() {
let mut config = config();
config.target = "x86_64-unknown-linux-gnu".to_owned();
assert!(parse_rs(&config, "// ignore-x86_64-unknown-linux-gnu").ignore);
assert!(parse_rs(&config, "// ignore-x86_64").ignore);
assert!(parse_rs(&config, "// ignore-linux").ignore);
assert!(parse_rs(&config, "// ignore-gnu").ignore);
assert!(parse_rs(&config, "// ignore-64bit").ignore);
assert!(check_ignore(&config, "// ignore-x86_64-unknown-linux-gnu"));
assert!(check_ignore(&config, "// ignore-x86_64"));
assert!(check_ignore(&config, "// ignore-linux"));
assert!(check_ignore(&config, "// ignore-gnu"));
assert!(check_ignore(&config, "// ignore-64bit"));
assert!(!parse_rs(&config, "// ignore-i686").ignore);
assert!(!parse_rs(&config, "// ignore-windows").ignore);
assert!(!parse_rs(&config, "// ignore-msvc").ignore);
assert!(!parse_rs(&config, "// ignore-32bit").ignore);
assert!(!check_ignore(&config, "// ignore-i686"));
assert!(!check_ignore(&config, "// ignore-windows"));
assert!(!check_ignore(&config, "// ignore-msvc"));
assert!(!check_ignore(&config, "// ignore-32bit"));
}
#[test]
@ -157,16 +168,16 @@ fn only_target() {
let mut config = config();
config.target = "x86_64-pc-windows-gnu".to_owned();
assert!(parse_rs(&config, "// only-i686").ignore);
assert!(parse_rs(&config, "// only-linux").ignore);
assert!(parse_rs(&config, "// only-msvc").ignore);
assert!(parse_rs(&config, "// only-32bit").ignore);
assert!(check_ignore(&config, "// only-i686"));
assert!(check_ignore(&config, "// only-linux"));
assert!(check_ignore(&config, "// only-msvc"));
assert!(check_ignore(&config, "// only-32bit"));
assert!(!parse_rs(&config, "// only-x86_64-pc-windows-gnu").ignore);
assert!(!parse_rs(&config, "// only-x86_64").ignore);
assert!(!parse_rs(&config, "// only-windows").ignore);
assert!(!parse_rs(&config, "// only-gnu").ignore);
assert!(!parse_rs(&config, "// only-64bit").ignore);
assert!(!check_ignore(&config, "// only-x86_64-pc-windows-gnu"));
assert!(!check_ignore(&config, "// only-x86_64"));
assert!(!check_ignore(&config, "// only-windows"));
assert!(!check_ignore(&config, "// only-gnu"));
assert!(!check_ignore(&config, "// only-64bit"));
}
#[test]
@ -174,8 +185,8 @@ fn stage() {
let mut config = config();
config.stage_id = "stage1".to_owned();
assert!(parse_rs(&config, "// ignore-stage1").ignore);
assert!(!parse_rs(&config, "// ignore-stage2").ignore);
assert!(check_ignore(&config, "// ignore-stage1"));
assert!(!check_ignore(&config, "// ignore-stage2"));
}
#[test]
@ -183,26 +194,26 @@ fn cross_compile() {
let mut config = config();
config.host = "x86_64-apple-darwin".to_owned();
config.target = "wasm32-unknown-unknown".to_owned();
assert!(parse_rs(&config, "// ignore-cross-compile").ignore);
assert!(check_ignore(&config, "// ignore-cross-compile"));
config.target = config.host.clone();
assert!(!parse_rs(&config, "// ignore-cross-compile").ignore);
assert!(!check_ignore(&config, "// ignore-cross-compile"));
}
#[test]
fn debugger() {
let mut config = config();
config.debugger = None;
assert!(!parse_rs(&config, "// ignore-cdb").ignore);
assert!(!check_ignore(&config, "// ignore-cdb"));
config.debugger = Some(Debugger::Cdb);
assert!(parse_rs(&config, "// ignore-cdb").ignore);
assert!(check_ignore(&config, "// ignore-cdb"));
config.debugger = Some(Debugger::Gdb);
assert!(parse_rs(&config, "// ignore-gdb").ignore);
assert!(check_ignore(&config, "// ignore-gdb"));
config.debugger = Some(Debugger::Lldb);
assert!(parse_rs(&config, "// ignore-lldb").ignore);
assert!(check_ignore(&config, "// ignore-lldb"));
}
#[test]
@ -211,17 +222,17 @@ fn sanitizers() {
// Target that supports all sanitizers:
config.target = "x86_64-unknown-linux-gnu".to_owned();
assert!(!parse_rs(&config, "// needs-sanitizer-address").ignore);
assert!(!parse_rs(&config, "// needs-sanitizer-leak").ignore);
assert!(!parse_rs(&config, "// needs-sanitizer-memory").ignore);
assert!(!parse_rs(&config, "// needs-sanitizer-thread").ignore);
assert!(!check_ignore(&config, "// needs-sanitizer-address"));
assert!(!check_ignore(&config, "// needs-sanitizer-leak"));
assert!(!check_ignore(&config, "// needs-sanitizer-memory"));
assert!(!check_ignore(&config, "// needs-sanitizer-thread"));
// Target that doesn't support sanitizers:
config.target = "wasm32-unknown-emscripten".to_owned();
assert!(parse_rs(&config, "// needs-sanitizer-address").ignore);
assert!(parse_rs(&config, "// needs-sanitizer-leak").ignore);
assert!(parse_rs(&config, "// needs-sanitizer-memory").ignore);
assert!(parse_rs(&config, "// needs-sanitizer-thread").ignore);
assert!(check_ignore(&config, "// needs-sanitizer-address"));
assert!(check_ignore(&config, "// needs-sanitizer-leak"));
assert!(check_ignore(&config, "// needs-sanitizer-memory"));
assert!(check_ignore(&config, "// needs-sanitizer-thread"));
}
#[test]
@ -229,10 +240,10 @@ fn asm_support() {
let mut config = config();
config.target = "avr-unknown-gnu-atmega328".to_owned();
assert!(parse_rs(&config, "// needs-asm-support").ignore);
assert!(check_ignore(&config, "// needs-asm-support"));
config.target = "i686-unknown-netbsd".to_owned();
assert!(!parse_rs(&config, "// needs-asm-support").ignore);
assert!(!check_ignore(&config, "// needs-asm-support"));
}
#[test]
@ -240,13 +251,13 @@ fn channel() {
let mut config = config();
config.channel = "beta".into();
assert!(parse_rs(&config, "// ignore-beta").ignore);
assert!(parse_rs(&config, "// only-nightly").ignore);
assert!(parse_rs(&config, "// only-stable").ignore);
assert!(check_ignore(&config, "// ignore-beta"));
assert!(check_ignore(&config, "// only-nightly"));
assert!(check_ignore(&config, "// only-stable"));
assert!(!parse_rs(&config, "// only-beta").ignore);
assert!(!parse_rs(&config, "// ignore-nightly").ignore);
assert!(!parse_rs(&config, "// ignore-stable").ignore);
assert!(!check_ignore(&config, "// only-beta"));
assert!(!check_ignore(&config, "// ignore-nightly"));
assert!(!check_ignore(&config, "// ignore-stable"));
}
#[test]

View file

@ -8,7 +8,7 @@ extern crate test;
use crate::common::{
expected_output_path, output_base_dir, output_relative_path, PanicStrategy, UI_EXTENSIONS,
};
use crate::common::{CompareMode, Config, Debugger, Mode, PassMode, Pretty, TestPaths};
use crate::common::{CompareMode, Config, Debugger, Mode, PassMode, TestPaths};
use crate::util::logv;
use getopts::Options;
use std::env;
@ -22,7 +22,7 @@ use test::ColorConfig;
use tracing::*;
use walkdir::WalkDir;
use self::header::EarlyProps;
use self::header::{make_test_description, EarlyProps};
#[cfg(test)]
mod tests;
@ -620,26 +620,13 @@ pub fn is_test(file_name: &OsString) -> bool {
}
fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test::TestDescAndFn> {
let early_props = if config.mode == Mode::RunMake {
// Allow `ignore` directives to be in the Makefile.
EarlyProps::from_file(config, &testpaths.file.join("Makefile"))
let test_path = if config.mode == Mode::RunMake {
// Parse directives in the Makefile
testpaths.file.join("Makefile")
} else {
EarlyProps::from_file(config, &testpaths.file)
};
// The `should-fail` annotation doesn't apply to pretty tests,
// since we run the pretty printer across all tests by default.
// If desired, we could add a `should-fail-pretty` annotation.
let should_panic = match config.mode {
Pretty => test::ShouldPanic::No,
_ => {
if early_props.should_fail {
test::ShouldPanic::Yes
} else {
test::ShouldPanic::No
}
}
PathBuf::from(&testpaths.file)
};
let early_props = EarlyProps::from_file(config, &test_path);
// Incremental tests are special, they inherently cannot be run in parallel.
// `runtest::run` will be responsible for iterating over revisions.
@ -651,29 +638,20 @@ fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test
revisions
.into_iter()
.map(|revision| {
let ignore = early_props.ignore
// Ignore tests that already run and are up to date with respect to inputs.
|| is_up_to_date(
config,
testpaths,
&early_props,
revision.map(|s| s.as_str()),
inputs,
);
test::TestDescAndFn {
desc: test::TestDesc {
name: make_test_name(config, testpaths, revision),
ignore,
should_panic,
allow_fail: false,
#[cfg(not(bootstrap))]
compile_fail: false,
#[cfg(not(bootstrap))]
no_run: false,
test_type: test::TestType::Unknown,
},
testfn: make_test_closure(config, testpaths, revision),
}
let src_file =
std::fs::File::open(&test_path).expect("open test file to parse ignores");
let cfg = revision.map(|v| &**v);
let test_name = crate::make_test_name(config, testpaths, revision);
let mut desc = make_test_description(config, test_name, &test_path, src_file, cfg);
// Ignore tests that already run and are up to date with respect to inputs.
desc.ignore |= is_up_to_date(
config,
testpaths,
&early_props,
revision.map(|s| s.as_str()),
inputs,
);
test::TestDescAndFn { desc, testfn: make_test_closure(config, testpaths, revision) }
})
.collect()
}

View file

@ -47,6 +47,7 @@ pub mod extdeps;
pub mod features;
pub mod pal;
pub mod style;
pub mod target_specific_tests;
pub mod ui_tests;
pub mod unit_tests;
pub mod unstable_book;

View file

@ -55,6 +55,8 @@ fn main() {
}
}
check!(target_specific_tests, &src_path);
// Checks that are done on the cargo workspace.
check!(deps, &root_path, &cargo);
check!(extdeps, &root_path);

View file

@ -0,0 +1,96 @@
//! Tidy check to ensure that all target specific tests (those that require a `--target` flag)
//! also require the pre-requisite LLVM components to run.
use std::collections::BTreeMap;
use std::path::Path;
const COMMENT: &str = "//";
const LLVM_COMPONENTS_HEADER: &str = "needs-llvm-components:";
const COMPILE_FLAGS_HEADER: &str = "compile-flags:";
/// Iterate through compiletest headers in a test contents.
///
/// Adjusted from compiletest/src/header.rs.
fn iter_header<'a>(contents: &'a str, it: &mut dyn FnMut(Option<&'a str>, &'a str)) {
for ln in contents.lines() {
let ln = ln.trim();
if ln.starts_with(COMMENT) && ln[COMMENT.len()..].trim_start().starts_with('[') {
if let Some(close_brace) = ln.find(']') {
let open_brace = ln.find('[').unwrap();
let lncfg = &ln[open_brace + 1..close_brace];
it(Some(lncfg), ln[(close_brace + 1)..].trim_start());
} else {
panic!("malformed condition directive: expected `//[foo]`, found `{}`", ln)
}
} else if ln.starts_with(COMMENT) {
it(None, ln[COMMENT.len()..].trim_start());
}
}
}
#[derive(Default, Debug)]
struct RevisionInfo<'a> {
target_arch: Option<&'a str>,
llvm_components: Option<Vec<&'a str>>,
}
pub fn check(path: &Path, bad: &mut bool) {
let tests = path.join("test");
super::walk(
&tests,
&mut |path| path.extension().map(|p| p == "rs") == Some(false),
&mut |entry, content| {
let file = entry.path().display();
let mut header_map = BTreeMap::new();
iter_header(content, &mut |cfg, directive| {
if let Some(value) = directive.strip_prefix(LLVM_COMPONENTS_HEADER) {
let info = header_map.entry(cfg).or_insert(RevisionInfo::default());
let comp_vec = info.llvm_components.get_or_insert(Vec::new());
for component in value.split(' ') {
let component = component.trim();
if !component.is_empty() {
comp_vec.push(component);
}
}
} else if directive.starts_with(COMPILE_FLAGS_HEADER) {
let compile_flags = &directive[COMPILE_FLAGS_HEADER.len()..];
if let Some((_, v)) = compile_flags.split_once("--target") {
if let Some((arch, _)) =
v.trim_start_matches(|c| c == ' ' || c == '=').split_once("-")
{
let info = header_map.entry(cfg).or_insert(RevisionInfo::default());
info.target_arch.replace(arch);
} else {
eprintln!("{}: seems to have a malformed --target value", file);
*bad = true;
}
}
}
});
for (rev, RevisionInfo { target_arch, llvm_components }) in &header_map {
let rev = rev.unwrap_or("[unspecified]");
match (target_arch, llvm_components) {
(None, None) => {}
(Some(_), None) => {
eprintln!(
"{}: revision {} should specify `{}` as it has `--target` set",
file, rev, LLVM_COMPONENTS_HEADER
);
*bad = true;
}
(None, Some(_)) => {
eprintln!(
"{}: revision {} should not specify `{}` as it doesn't need `--target`",
file, rev, LLVM_COMPONENTS_HEADER
);
*bad = true;
}
(Some(_), Some(_)) => {
// FIXME: check specified components against the target architectures we
// gathered.
}
}
}
},
);
}