mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Implement infra support for migrating from //
to //@
ui test directives
This commit is contained in:
parent
d2e8ecd8bd
commit
e53d6dd35b
@ -6,6 +6,7 @@ use std::io::BufReader;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use regex::Regex;
|
||||
use tracing::*;
|
||||
|
||||
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
|
||||
@ -46,18 +47,32 @@ impl EarlyProps {
|
||||
|
||||
pub fn from_reader<R: Read>(config: &Config, testfile: &Path, rdr: R) -> Self {
|
||||
let mut props = EarlyProps::default();
|
||||
iter_header(testfile, rdr, &mut |_, ln, _| {
|
||||
config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| {
|
||||
r.trim().to_string()
|
||||
});
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
directives::AUX_CRATE,
|
||||
&mut props.aux_crate,
|
||||
Config::parse_aux_crate,
|
||||
);
|
||||
config.parse_and_update_revisions(ln, &mut props.revisions);
|
||||
});
|
||||
let mut poisoned = false;
|
||||
iter_header(
|
||||
config.mode,
|
||||
&config.suite,
|
||||
&mut poisoned,
|
||||
testfile,
|
||||
rdr,
|
||||
&mut |_, _, ln, _| {
|
||||
config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| {
|
||||
r.trim().to_string()
|
||||
});
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
directives::AUX_CRATE,
|
||||
&mut props.aux_crate,
|
||||
Config::parse_aux_crate,
|
||||
);
|
||||
config.parse_and_update_revisions(ln, &mut props.revisions);
|
||||
},
|
||||
);
|
||||
|
||||
if poisoned {
|
||||
eprintln!("errors encountered during EarlyProps parsing: {}", testfile.display());
|
||||
panic!("errors encountered during EarlyProps parsing");
|
||||
}
|
||||
|
||||
return props;
|
||||
}
|
||||
}
|
||||
@ -306,205 +321,233 @@ impl TestProps {
|
||||
if !testfile.is_dir() {
|
||||
let file = File::open(testfile).unwrap();
|
||||
|
||||
iter_header(testfile, file, &mut |revision, ln, _| {
|
||||
if revision.is_some() && revision != cfg {
|
||||
return;
|
||||
}
|
||||
let mut poisoned = false;
|
||||
|
||||
use directives::*;
|
||||
iter_header(
|
||||
config.mode,
|
||||
&config.suite,
|
||||
&mut poisoned,
|
||||
testfile,
|
||||
file,
|
||||
&mut |revision, _, ln, _| {
|
||||
if revision.is_some() && revision != cfg {
|
||||
return;
|
||||
}
|
||||
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
ERROR_PATTERN,
|
||||
&mut self.error_patterns,
|
||||
|r| r,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
REGEX_ERROR_PATTERN,
|
||||
&mut self.regex_error_patterns,
|
||||
|r| r,
|
||||
);
|
||||
use directives::*;
|
||||
|
||||
fn split_flags(flags: &str) -> Vec<String> {
|
||||
// Individual flags can be single-quoted to preserve spaces; see
|
||||
// <https://github.com/rust-lang/rust/pull/115948/commits/957c5db6>.
|
||||
flags
|
||||
.split("'")
|
||||
.enumerate()
|
||||
.flat_map(
|
||||
|(i, f)| {
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
ERROR_PATTERN,
|
||||
&mut self.error_patterns,
|
||||
|r| r,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
REGEX_ERROR_PATTERN,
|
||||
&mut self.regex_error_patterns,
|
||||
|r| r,
|
||||
);
|
||||
|
||||
fn split_flags(flags: &str) -> Vec<String> {
|
||||
// Individual flags can be single-quoted to preserve spaces; see
|
||||
// <https://github.com/rust-lang/rust/pull/115948/commits/957c5db6>.
|
||||
flags
|
||||
.split("'")
|
||||
.enumerate()
|
||||
.flat_map(|(i, f)| {
|
||||
if i % 2 == 1 { vec![f] } else { f.split_whitespace().collect() }
|
||||
},
|
||||
)
|
||||
.map(move |s| s.to_owned())
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
})
|
||||
.map(move |s| s.to_owned())
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
|
||||
self.compile_flags.extend(split_flags(&flags));
|
||||
}
|
||||
if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() {
|
||||
panic!("`compiler-flags` directive should be spelled `compile-flags`");
|
||||
}
|
||||
if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
|
||||
self.compile_flags.extend(split_flags(&flags));
|
||||
}
|
||||
if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() {
|
||||
panic!("`compiler-flags` directive should be spelled `compile-flags`");
|
||||
}
|
||||
|
||||
if let Some(edition) = config.parse_edition(ln) {
|
||||
self.compile_flags.push(format!("--edition={}", edition.trim()));
|
||||
has_edition = true;
|
||||
}
|
||||
if let Some(edition) = config.parse_edition(ln) {
|
||||
self.compile_flags.push(format!("--edition={}", edition.trim()));
|
||||
has_edition = true;
|
||||
}
|
||||
|
||||
config.parse_and_update_revisions(ln, &mut self.revisions);
|
||||
config.parse_and_update_revisions(ln, &mut self.revisions);
|
||||
|
||||
config.set_name_value_directive(ln, RUN_FLAGS, &mut self.run_flags, |r| r);
|
||||
config.set_name_value_directive(ln, RUN_FLAGS, &mut self.run_flags, |r| r);
|
||||
|
||||
if self.pp_exact.is_none() {
|
||||
self.pp_exact = config.parse_pp_exact(ln, testfile);
|
||||
}
|
||||
if self.pp_exact.is_none() {
|
||||
self.pp_exact = config.parse_pp_exact(ln, testfile);
|
||||
}
|
||||
|
||||
config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice);
|
||||
config.set_name_directive(ln, BUILD_AUX_DOCS, &mut self.build_aux_docs);
|
||||
config.set_name_directive(ln, FORCE_HOST, &mut self.force_host);
|
||||
config.set_name_directive(ln, CHECK_STDOUT, &mut self.check_stdout);
|
||||
config.set_name_directive(ln, CHECK_RUN_RESULTS, &mut self.check_run_results);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
DONT_CHECK_COMPILER_STDOUT,
|
||||
&mut self.dont_check_compiler_stdout,
|
||||
);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
DONT_CHECK_COMPILER_STDERR,
|
||||
&mut self.dont_check_compiler_stderr,
|
||||
);
|
||||
config.set_name_directive(ln, NO_PREFER_DYNAMIC, &mut self.no_prefer_dynamic);
|
||||
config.set_name_directive(ln, PRETTY_EXPANDED, &mut self.pretty_expanded);
|
||||
config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice);
|
||||
config.set_name_directive(ln, BUILD_AUX_DOCS, &mut self.build_aux_docs);
|
||||
config.set_name_directive(ln, FORCE_HOST, &mut self.force_host);
|
||||
config.set_name_directive(ln, CHECK_STDOUT, &mut self.check_stdout);
|
||||
config.set_name_directive(ln, CHECK_RUN_RESULTS, &mut self.check_run_results);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
DONT_CHECK_COMPILER_STDOUT,
|
||||
&mut self.dont_check_compiler_stdout,
|
||||
);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
DONT_CHECK_COMPILER_STDERR,
|
||||
&mut self.dont_check_compiler_stderr,
|
||||
);
|
||||
config.set_name_directive(ln, NO_PREFER_DYNAMIC, &mut self.no_prefer_dynamic);
|
||||
config.set_name_directive(ln, PRETTY_EXPANDED, &mut self.pretty_expanded);
|
||||
|
||||
if let Some(m) = config.parse_name_value_directive(ln, PRETTY_MODE) {
|
||||
self.pretty_mode = m;
|
||||
}
|
||||
if let Some(m) = config.parse_name_value_directive(ln, PRETTY_MODE) {
|
||||
self.pretty_mode = m;
|
||||
}
|
||||
|
||||
config.set_name_directive(ln, PRETTY_COMPARE_ONLY, &mut self.pretty_compare_only);
|
||||
config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| {
|
||||
r.trim().to_string()
|
||||
});
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
AUX_CRATE,
|
||||
&mut self.aux_crates,
|
||||
Config::parse_aux_crate,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
EXEC_ENV,
|
||||
&mut self.exec_env,
|
||||
Config::parse_env,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
UNSET_EXEC_ENV,
|
||||
&mut self.unset_exec_env,
|
||||
|r| r,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
RUSTC_ENV,
|
||||
&mut self.rustc_env,
|
||||
Config::parse_env,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
UNSET_RUSTC_ENV,
|
||||
&mut self.unset_rustc_env,
|
||||
|r| r,
|
||||
);
|
||||
config.push_name_value_directive(ln, FORBID_OUTPUT, &mut self.forbid_output, |r| r);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
CHECK_TEST_LINE_NUMBERS_MATCH,
|
||||
&mut self.check_test_line_numbers_match,
|
||||
);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
PRETTY_COMPARE_ONLY,
|
||||
&mut self.pretty_compare_only,
|
||||
);
|
||||
config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| {
|
||||
r.trim().to_string()
|
||||
});
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
AUX_CRATE,
|
||||
&mut self.aux_crates,
|
||||
Config::parse_aux_crate,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
EXEC_ENV,
|
||||
&mut self.exec_env,
|
||||
Config::parse_env,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
UNSET_EXEC_ENV,
|
||||
&mut self.unset_exec_env,
|
||||
|r| r,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
RUSTC_ENV,
|
||||
&mut self.rustc_env,
|
||||
Config::parse_env,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
UNSET_RUSTC_ENV,
|
||||
&mut self.unset_rustc_env,
|
||||
|r| r,
|
||||
);
|
||||
config.push_name_value_directive(
|
||||
ln,
|
||||
FORBID_OUTPUT,
|
||||
&mut self.forbid_output,
|
||||
|r| r,
|
||||
);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
CHECK_TEST_LINE_NUMBERS_MATCH,
|
||||
&mut self.check_test_line_numbers_match,
|
||||
);
|
||||
|
||||
self.update_pass_mode(ln, cfg, config);
|
||||
self.update_fail_mode(ln, config);
|
||||
self.update_pass_mode(ln, cfg, config);
|
||||
self.update_fail_mode(ln, config);
|
||||
|
||||
config.set_name_directive(ln, IGNORE_PASS, &mut self.ignore_pass);
|
||||
config.set_name_directive(ln, IGNORE_PASS, &mut self.ignore_pass);
|
||||
|
||||
if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stdout") {
|
||||
self.normalize_stdout.push(rule);
|
||||
}
|
||||
if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stderr") {
|
||||
self.normalize_stderr.push(rule);
|
||||
}
|
||||
if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stdout") {
|
||||
self.normalize_stdout.push(rule);
|
||||
}
|
||||
if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stderr") {
|
||||
self.normalize_stderr.push(rule);
|
||||
}
|
||||
|
||||
if let Some(code) = config
|
||||
.parse_name_value_directive(ln, FAILURE_STATUS)
|
||||
.and_then(|code| code.trim().parse::<i32>().ok())
|
||||
{
|
||||
self.failure_status = Some(code);
|
||||
}
|
||||
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
DONT_CHECK_FAILURE_STATUS,
|
||||
&mut self.dont_check_failure_status,
|
||||
);
|
||||
|
||||
config.set_name_directive(ln, RUN_RUSTFIX, &mut self.run_rustfix);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
RUSTFIX_ONLY_MACHINE_APPLICABLE,
|
||||
&mut self.rustfix_only_machine_applicable,
|
||||
);
|
||||
config.set_name_value_directive(
|
||||
ln,
|
||||
ASSEMBLY_OUTPUT,
|
||||
&mut self.assembly_output,
|
||||
|r| r.trim().to_string(),
|
||||
);
|
||||
config.set_name_directive(ln, STDERR_PER_BITWIDTH, &mut self.stderr_per_bitwidth);
|
||||
config.set_name_directive(ln, INCREMENTAL, &mut self.incremental);
|
||||
|
||||
// Unlike the other `name_value_directive`s this needs to be handled manually,
|
||||
// because it sets a `bool` flag.
|
||||
if let Some(known_bug) = config.parse_name_value_directive(ln, KNOWN_BUG) {
|
||||
let known_bug = known_bug.trim();
|
||||
if known_bug == "unknown"
|
||||
|| known_bug.split(',').all(|issue_ref| {
|
||||
issue_ref
|
||||
.trim()
|
||||
.split_once('#')
|
||||
.filter(|(_, number)| {
|
||||
number.chars().all(|digit| digit.is_numeric())
|
||||
})
|
||||
.is_some()
|
||||
})
|
||||
if let Some(code) = config
|
||||
.parse_name_value_directive(ln, FAILURE_STATUS)
|
||||
.and_then(|code| code.trim().parse::<i32>().ok())
|
||||
{
|
||||
self.known_bug = true;
|
||||
} else {
|
||||
self.failure_status = Some(code);
|
||||
}
|
||||
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
DONT_CHECK_FAILURE_STATUS,
|
||||
&mut self.dont_check_failure_status,
|
||||
);
|
||||
|
||||
config.set_name_directive(ln, RUN_RUSTFIX, &mut self.run_rustfix);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
RUSTFIX_ONLY_MACHINE_APPLICABLE,
|
||||
&mut self.rustfix_only_machine_applicable,
|
||||
);
|
||||
config.set_name_value_directive(
|
||||
ln,
|
||||
ASSEMBLY_OUTPUT,
|
||||
&mut self.assembly_output,
|
||||
|r| r.trim().to_string(),
|
||||
);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
STDERR_PER_BITWIDTH,
|
||||
&mut self.stderr_per_bitwidth,
|
||||
);
|
||||
config.set_name_directive(ln, INCREMENTAL, &mut self.incremental);
|
||||
|
||||
// Unlike the other `name_value_directive`s this needs to be handled manually,
|
||||
// because it sets a `bool` flag.
|
||||
if let Some(known_bug) = config.parse_name_value_directive(ln, KNOWN_BUG) {
|
||||
let known_bug = known_bug.trim();
|
||||
if known_bug == "unknown"
|
||||
|| known_bug.split(',').all(|issue_ref| {
|
||||
issue_ref
|
||||
.trim()
|
||||
.split_once('#')
|
||||
.filter(|(_, number)| {
|
||||
number.chars().all(|digit| digit.is_numeric())
|
||||
})
|
||||
.is_some()
|
||||
})
|
||||
{
|
||||
self.known_bug = true;
|
||||
} else {
|
||||
panic!(
|
||||
"Invalid known-bug value: {known_bug}\nIt requires comma-separated issue references (`#000` or `chalk#000`) or `known-bug: unknown`."
|
||||
);
|
||||
}
|
||||
} else if config.parse_name_directive(ln, KNOWN_BUG) {
|
||||
panic!(
|
||||
"Invalid known-bug value: {known_bug}\nIt requires comma-separated issue references (`#000` or `chalk#000`) or `known-bug: unknown`."
|
||||
"Invalid known-bug attribute, requires comma-separated issue references (`#000` or `chalk#000`) or `known-bug: unknown`."
|
||||
);
|
||||
}
|
||||
} else if config.parse_name_directive(ln, KNOWN_BUG) {
|
||||
panic!(
|
||||
"Invalid known-bug attribute, requires comma-separated issue references (`#000` or `chalk#000`) or `known-bug: unknown`."
|
||||
|
||||
config.set_name_value_directive(
|
||||
ln,
|
||||
MIR_UNIT_TEST,
|
||||
&mut self.mir_unit_test,
|
||||
|s| s.trim().to_string(),
|
||||
);
|
||||
config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
COMPARE_OUTPUT_LINES_BY_SUBSET,
|
||||
&mut self.compare_output_lines_by_subset,
|
||||
);
|
||||
}
|
||||
|
||||
config.set_name_value_directive(ln, MIR_UNIT_TEST, &mut self.mir_unit_test, |s| {
|
||||
s.trim().to_string()
|
||||
});
|
||||
config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base);
|
||||
config.set_name_directive(
|
||||
ln,
|
||||
COMPARE_OUTPUT_LINES_BY_SUBSET,
|
||||
&mut self.compare_output_lines_by_subset,
|
||||
);
|
||||
if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) {
|
||||
self.llvm_cov_flags.extend(split_flags(&flags));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) {
|
||||
self.llvm_cov_flags.extend(split_flags(&flags));
|
||||
}
|
||||
});
|
||||
if poisoned {
|
||||
eprintln!("errors encountered during TestProps parsing: {}", testfile.display());
|
||||
panic!("errors encountered during TestProps parsing");
|
||||
}
|
||||
}
|
||||
|
||||
if self.should_ice {
|
||||
@ -628,15 +671,143 @@ pub fn line_directive<'line>(
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>, &str, usize)) {
|
||||
iter_header_extra(testfile, rdr, &[], it)
|
||||
fn iter_header<R: Read>(
|
||||
mode: Mode,
|
||||
suite: &str,
|
||||
poisoned: &mut bool,
|
||||
testfile: &Path,
|
||||
rdr: R,
|
||||
it: &mut dyn FnMut(Option<&str>, &str, &str, usize),
|
||||
) {
|
||||
iter_header_extra(mode, suite, poisoned, testfile, rdr, &[], it)
|
||||
}
|
||||
|
||||
/// This is generated by collecting directives from ui tests and then extracting their directive
|
||||
/// names. This is **not** an exhaustive list of all possible directives. Instead, this is a
|
||||
/// best-effort approximation for diagnostics.
|
||||
const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
|
||||
"aux-build",
|
||||
"aux-crate",
|
||||
"build-fail",
|
||||
"build-pass",
|
||||
"check-fail",
|
||||
"check-pass",
|
||||
"check-run-results",
|
||||
"check-stdout",
|
||||
"compile-flags",
|
||||
"dont-check-compiler-stderr",
|
||||
"dont-check-compiler-stdout",
|
||||
"dont-check-failure-status",
|
||||
"edition",
|
||||
"error-pattern",
|
||||
"exec-env",
|
||||
"failure-status",
|
||||
"forbid-output",
|
||||
"force-host",
|
||||
"ignore-32bit",
|
||||
"ignore-64bit",
|
||||
"ignore-aarch64",
|
||||
"ignore-aarch64-unknown-linux-gnu",
|
||||
"ignore-android",
|
||||
"ignore-arm",
|
||||
"ignore-compare-mode-next-solver",
|
||||
"ignore-compare-mode-polonius",
|
||||
"ignore-cross-compile",
|
||||
"ignore-debug",
|
||||
"ignore-emscripten",
|
||||
"ignore-endian-big",
|
||||
"ignore-freebsd",
|
||||
"ignore-fuchsia",
|
||||
"ignore-gnu",
|
||||
"ignore-haiku",
|
||||
"ignore-horizon",
|
||||
"ignore-i686-pc-windows-msvc",
|
||||
"ignore-ios",
|
||||
"ignore-llvm-version",
|
||||
"ignore-macos",
|
||||
"ignore-msvc",
|
||||
"ignore-musl",
|
||||
"ignore-netbsd",
|
||||
"ignore-nightly",
|
||||
"ignore-nto",
|
||||
"ignore-nvptx64",
|
||||
"ignore-openbsd",
|
||||
"ignore-pass",
|
||||
"ignore-sgx",
|
||||
"ignore-spirv",
|
||||
"ignore-test",
|
||||
"ignore-thumbv8m.base-none-eabi",
|
||||
"ignore-thumbv8m.main-none-eabi",
|
||||
"ignore-uwp",
|
||||
"ignore-vxworks",
|
||||
"ignore-wasm",
|
||||
"ignore-wasm32",
|
||||
"ignore-wasm32-bare",
|
||||
"ignore-windows",
|
||||
"ignore-x86",
|
||||
"incremental",
|
||||
"known-bug",
|
||||
"min-llvm-version",
|
||||
"needs-asm-support",
|
||||
"needs-dlltool",
|
||||
"needs-dynamic-linking",
|
||||
"needs-llvm-components",
|
||||
"needs-profiler-support",
|
||||
"needs-relocation-model-pic",
|
||||
"needs-run-enabled",
|
||||
"needs-sanitizer-address",
|
||||
"needs-sanitizer-cfi",
|
||||
"needs-sanitizer-hwaddress",
|
||||
"needs-sanitizer-leak",
|
||||
"needs-sanitizer-memory",
|
||||
"needs-sanitizer-support",
|
||||
"needs-sanitizer-thread",
|
||||
"needs-unwind",
|
||||
"needs-xray",
|
||||
"no-prefer-dynamic",
|
||||
"normalize-stderr-32bit",
|
||||
"normalize-stderr-64bit",
|
||||
"normalize-stderr-test",
|
||||
"normalize-stdout-test",
|
||||
"only-32bit",
|
||||
"only-64bit",
|
||||
"only-aarch64",
|
||||
"only-gnu",
|
||||
"only-i686-pc-windows-msvc",
|
||||
"only-linux",
|
||||
"only-macos",
|
||||
"only-msvc",
|
||||
"only-nightly",
|
||||
"only-wasm32",
|
||||
"only-windows",
|
||||
"only-x86",
|
||||
"only-x86_64",
|
||||
"only-x86_64-pc-windows-msvc",
|
||||
"only-x86_64-unknown-linux-gnu",
|
||||
"pp-exact",
|
||||
"pretty-expanded",
|
||||
"regex-error-pattern",
|
||||
"remap-src-base",
|
||||
"revisions",
|
||||
"run-fail",
|
||||
"run-flags",
|
||||
"run-pass",
|
||||
"run-rustfix",
|
||||
"rustc-env",
|
||||
"rustfix-only-machine-applicable",
|
||||
"should-fail",
|
||||
"stderr-per-bitwidth",
|
||||
"unset-rustc-env",
|
||||
];
|
||||
|
||||
fn iter_header_extra(
|
||||
mode: Mode,
|
||||
suite: &str,
|
||||
poisoned: &mut bool,
|
||||
testfile: &Path,
|
||||
rdr: impl Read,
|
||||
extra_directives: &[&str],
|
||||
it: &mut dyn FnMut(Option<&str>, &str, usize),
|
||||
it: &mut dyn FnMut(Option<&str>, &str, &str, usize),
|
||||
) {
|
||||
if testfile.is_dir() {
|
||||
return;
|
||||
@ -645,15 +816,21 @@ fn iter_header_extra(
|
||||
// Process any extra directives supplied by the caller (e.g. because they
|
||||
// are implied by the test mode), with a dummy line number of 0.
|
||||
for directive in extra_directives {
|
||||
it(None, directive, 0);
|
||||
it(None, directive, directive, 0);
|
||||
}
|
||||
|
||||
let comment = if testfile.extension().is_some_and(|e| e == "rs") { "//" } else { "#" };
|
||||
let comment = if testfile.extension().is_some_and(|e| e == "rs") {
|
||||
if mode == Mode::Ui && suite == "ui" { "//@" } else { "//" }
|
||||
} else {
|
||||
"#"
|
||||
};
|
||||
|
||||
let mut rdr = BufReader::with_capacity(1024, rdr);
|
||||
let mut ln = String::new();
|
||||
let mut line_number = 0;
|
||||
|
||||
let revision_magic_comment = Regex::new("//(\\[.*\\])?~.*").unwrap();
|
||||
|
||||
loop {
|
||||
line_number += 1;
|
||||
ln.clear();
|
||||
@ -664,11 +841,56 @@ fn iter_header_extra(
|
||||
// Assume that any directives will be found before the first
|
||||
// module or function. This doesn't seem to be an optimization
|
||||
// with a warm page cache. Maybe with a cold one.
|
||||
let orig_ln = &ln;
|
||||
let ln = ln.trim();
|
||||
if ln.starts_with("fn") || ln.starts_with("mod") {
|
||||
return;
|
||||
|
||||
// First try to accept `ui_test` style comments
|
||||
} else if let Some((lncfg, ln)) = line_directive(comment, ln) {
|
||||
it(lncfg, ln, line_number);
|
||||
it(lncfg, orig_ln, ln, line_number);
|
||||
} else if mode == Mode::Ui && suite == "ui" && !revision_magic_comment.is_match(ln) {
|
||||
let Some((_, rest)) = line_directive("//", ln) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if rest.trim_start().starts_with(':') {
|
||||
// This is likely a markdown link:
|
||||
// `[link_name]: https://example.org`
|
||||
continue;
|
||||
}
|
||||
|
||||
let rest = rest.trim_start();
|
||||
|
||||
for candidate in DIAGNOSTICS_DIRECTIVE_NAMES.iter() {
|
||||
if rest.starts_with(candidate) {
|
||||
let Some(prefix_removed) = rest.strip_prefix(candidate) else {
|
||||
// We have a comment that's *successfully* parsed as an legacy-style
|
||||
// directive. We emit an error here to warn the user.
|
||||
*poisoned = true;
|
||||
eprintln!(
|
||||
"error: detected legacy-style directives in ui test: {}:{}, please use `ui_test`-style directives `//@` instead:{:#?}",
|
||||
testfile.display(),
|
||||
line_number,
|
||||
line_directive("//", ln),
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
if prefix_removed.starts_with([' ', ':']) {
|
||||
// We have a comment that's *successfully* parsed as an legacy-style
|
||||
// directive. We emit an error here to warn the user.
|
||||
*poisoned = true;
|
||||
eprintln!(
|
||||
"error: detected legacy-style directives in ui test: {}:{}, please use `ui_test`-style directives `//@` instead:{:#?}",
|
||||
testfile.display(),
|
||||
line_number,
|
||||
line_directive("//", ln),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -946,49 +1168,77 @@ pub fn make_test_description<R: Read>(
|
||||
_ => &[],
|
||||
};
|
||||
|
||||
iter_header_extra(path, src, extra_directives, &mut |revision, ln, line_number| {
|
||||
if revision.is_some() && revision != cfg {
|
||||
return;
|
||||
}
|
||||
let mut local_poisoned = false;
|
||||
|
||||
macro_rules! decision {
|
||||
($e:expr) => {
|
||||
match $e {
|
||||
IgnoreDecision::Ignore { reason } => {
|
||||
ignore = true;
|
||||
// The ignore reason must be a &'static str, so we have to leak memory to
|
||||
// create it. This is fine, as the header is parsed only at the start of
|
||||
// compiletest so it won't grow indefinitely.
|
||||
ignore_message = Some(&*Box::leak(Box::<str>::from(reason)));
|
||||
}
|
||||
IgnoreDecision::Error { message } => {
|
||||
eprintln!("error: {}:{line_number}: {message}", path.display());
|
||||
*poisoned = true;
|
||||
return;
|
||||
}
|
||||
IgnoreDecision::Continue => {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
decision!(cfg::handle_ignore(config, ln));
|
||||
decision!(cfg::handle_only(config, ln));
|
||||
decision!(needs::handle_needs(&cache.needs, config, ln));
|
||||
decision!(ignore_llvm(config, ln));
|
||||
decision!(ignore_cdb(config, ln));
|
||||
decision!(ignore_gdb(config, ln));
|
||||
decision!(ignore_lldb(config, ln));
|
||||
|
||||
if config.target == "wasm32-unknown-unknown" {
|
||||
if config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS) {
|
||||
decision!(IgnoreDecision::Ignore {
|
||||
reason: "ignored when checking the run results on WASM".into(),
|
||||
});
|
||||
iter_header_extra(
|
||||
config.mode,
|
||||
&config.suite,
|
||||
&mut local_poisoned,
|
||||
path,
|
||||
src,
|
||||
extra_directives,
|
||||
&mut |revision, og_ln, ln, line_number| {
|
||||
if revision.is_some() && revision != cfg {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
should_fail |= config.parse_name_directive(ln, "should-fail");
|
||||
});
|
||||
macro_rules! decision {
|
||||
($e:expr) => {
|
||||
match $e {
|
||||
IgnoreDecision::Ignore { reason } => {
|
||||
ignore = true;
|
||||
// The ignore reason must be a &'static str, so we have to leak memory to
|
||||
// create it. This is fine, as the header is parsed only at the start of
|
||||
// compiletest so it won't grow indefinitely.
|
||||
ignore_message = Some(&*Box::leak(Box::<str>::from(reason)));
|
||||
}
|
||||
IgnoreDecision::Error { message } => {
|
||||
eprintln!("error: {}:{line_number}: {message}", path.display());
|
||||
*poisoned = true;
|
||||
return;
|
||||
}
|
||||
IgnoreDecision::Continue => {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if let Some((_, post)) = og_ln.trim_start().split_once("//") {
|
||||
let post = post.trim_start();
|
||||
if post.starts_with("ignore-tidy")
|
||||
&& config.mode == Mode::Ui
|
||||
&& config.suite == "ui"
|
||||
{
|
||||
// not handled by compiletest under the ui test mode and ui test suite.
|
||||
} else {
|
||||
decision!(cfg::handle_ignore(config, ln));
|
||||
}
|
||||
} else {
|
||||
decision!(cfg::handle_ignore(config, ln));
|
||||
}
|
||||
|
||||
decision!(cfg::handle_only(config, ln));
|
||||
decision!(needs::handle_needs(&cache.needs, config, ln));
|
||||
decision!(ignore_llvm(config, ln));
|
||||
decision!(ignore_cdb(config, ln));
|
||||
decision!(ignore_gdb(config, ln));
|
||||
decision!(ignore_lldb(config, ln));
|
||||
|
||||
if config.target == "wasm32-unknown-unknown" {
|
||||
if config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS) {
|
||||
decision!(IgnoreDecision::Ignore {
|
||||
reason: "ignored when checking the run results on WASM".into(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
should_fail |= config.parse_name_directive(ln, "should-fail");
|
||||
},
|
||||
);
|
||||
|
||||
if local_poisoned {
|
||||
eprintln!("errors encountered when trying to make test description: {}", path.display());
|
||||
panic!("errors encountered when trying to make test description");
|
||||
}
|
||||
|
||||
// The `should-fail` annotation doesn't apply to pretty tests,
|
||||
// since we run the pretty printer across all tests by default.
|
||||
|
@ -210,7 +210,7 @@ fn 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);
|
||||
let d = make_test_description(&config, tn, p, std::io::Cursor::new("//@ should-fail"), None);
|
||||
assert_eq!(d.should_panic, test::ShouldPanic::Yes);
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ fn should_fail() {
|
||||
fn revisions() {
|
||||
let config: Config = cfg().build();
|
||||
|
||||
assert_eq!(parse_rs(&config, "// revisions: a b c").revisions, vec!["a", "b", "c"],);
|
||||
assert_eq!(parse_rs(&config, "//@ revisions: a b c").revisions, vec!["a", "b", "c"],);
|
||||
assert_eq!(
|
||||
parse_makefile(&config, "# revisions: hello there").revisions,
|
||||
vec!["hello", "there"],
|
||||
@ -233,8 +233,8 @@ fn aux_build() {
|
||||
parse_rs(
|
||||
&config,
|
||||
r"
|
||||
// aux-build: a.rs
|
||||
// aux-build: b.rs
|
||||
//@ aux-build: a.rs
|
||||
//@ aux-build: b.rs
|
||||
"
|
||||
)
|
||||
.aux,
|
||||
@ -245,128 +245,128 @@ fn aux_build() {
|
||||
#[test]
|
||||
fn llvm_version() {
|
||||
let config: Config = cfg().llvm_version("8.1.2").build();
|
||||
assert!(check_ignore(&config, "// min-llvm-version: 9.0"));
|
||||
assert!(check_ignore(&config, "//@ min-llvm-version: 9.0"));
|
||||
|
||||
let config: Config = cfg().llvm_version("9.0.1").build();
|
||||
assert!(check_ignore(&config, "// min-llvm-version: 9.2"));
|
||||
assert!(check_ignore(&config, "//@ min-llvm-version: 9.2"));
|
||||
|
||||
let config: Config = cfg().llvm_version("9.3.1").build();
|
||||
assert!(!check_ignore(&config, "// min-llvm-version: 9.2"));
|
||||
assert!(!check_ignore(&config, "//@ min-llvm-version: 9.2"));
|
||||
|
||||
let config: Config = cfg().llvm_version("10.0.0").build();
|
||||
assert!(!check_ignore(&config, "// min-llvm-version: 9.0"));
|
||||
assert!(!check_ignore(&config, "//@ min-llvm-version: 9.0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn system_llvm_version() {
|
||||
let config: Config = cfg().system_llvm(true).llvm_version("17.0.0").build();
|
||||
assert!(check_ignore(&config, "// min-system-llvm-version: 18.0"));
|
||||
assert!(check_ignore(&config, "//@ min-system-llvm-version: 18.0"));
|
||||
|
||||
let config: Config = cfg().system_llvm(true).llvm_version("18.0.0").build();
|
||||
assert!(!check_ignore(&config, "// min-system-llvm-version: 18.0"));
|
||||
assert!(!check_ignore(&config, "//@ min-system-llvm-version: 18.0"));
|
||||
|
||||
let config: Config = cfg().llvm_version("17.0.0").build();
|
||||
assert!(!check_ignore(&config, "// min-system-llvm-version: 18.0"));
|
||||
assert!(!check_ignore(&config, "//@ min-system-llvm-version: 18.0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_target() {
|
||||
let config: Config = cfg().target("x86_64-unknown-linux-gnu").build();
|
||||
|
||||
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!(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!(!check_ignore(&config, "// ignore-x86"));
|
||||
assert!(!check_ignore(&config, "// ignore-windows"));
|
||||
assert!(!check_ignore(&config, "// ignore-msvc"));
|
||||
assert!(!check_ignore(&config, "// ignore-32bit"));
|
||||
assert!(!check_ignore(&config, "//@ ignore-x86"));
|
||||
assert!(!check_ignore(&config, "//@ ignore-windows"));
|
||||
assert!(!check_ignore(&config, "//@ ignore-msvc"));
|
||||
assert!(!check_ignore(&config, "//@ ignore-32bit"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_target() {
|
||||
let config: Config = cfg().target("x86_64-pc-windows-gnu").build();
|
||||
|
||||
assert!(check_ignore(&config, "// only-x86"));
|
||||
assert!(check_ignore(&config, "// only-linux"));
|
||||
assert!(check_ignore(&config, "// only-msvc"));
|
||||
assert!(check_ignore(&config, "// only-32bit"));
|
||||
assert!(check_ignore(&config, "//@ only-x86"));
|
||||
assert!(check_ignore(&config, "//@ only-linux"));
|
||||
assert!(check_ignore(&config, "//@ only-msvc"));
|
||||
assert!(check_ignore(&config, "//@ only-32bit"));
|
||||
|
||||
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"));
|
||||
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]
|
||||
fn stage() {
|
||||
let config: Config = cfg().stage_id("stage1-x86_64-unknown-linux-gnu").build();
|
||||
|
||||
assert!(check_ignore(&config, "// ignore-stage1"));
|
||||
assert!(!check_ignore(&config, "// ignore-stage2"));
|
||||
assert!(check_ignore(&config, "//@ ignore-stage1"));
|
||||
assert!(!check_ignore(&config, "//@ ignore-stage2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cross_compile() {
|
||||
let config: Config = cfg().host("x86_64-apple-darwin").target("wasm32-unknown-unknown").build();
|
||||
assert!(check_ignore(&config, "// ignore-cross-compile"));
|
||||
assert!(check_ignore(&config, "//@ ignore-cross-compile"));
|
||||
|
||||
let config: Config = cfg().host("x86_64-apple-darwin").target("x86_64-apple-darwin").build();
|
||||
assert!(!check_ignore(&config, "// ignore-cross-compile"));
|
||||
assert!(!check_ignore(&config, "//@ ignore-cross-compile"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn debugger() {
|
||||
let mut config = cfg().build();
|
||||
config.debugger = None;
|
||||
assert!(!check_ignore(&config, "// ignore-cdb"));
|
||||
assert!(!check_ignore(&config, "//@ ignore-cdb"));
|
||||
|
||||
config.debugger = Some(Debugger::Cdb);
|
||||
assert!(check_ignore(&config, "// ignore-cdb"));
|
||||
assert!(check_ignore(&config, "//@ ignore-cdb"));
|
||||
|
||||
config.debugger = Some(Debugger::Gdb);
|
||||
assert!(check_ignore(&config, "// ignore-gdb"));
|
||||
assert!(check_ignore(&config, "//@ ignore-gdb"));
|
||||
|
||||
config.debugger = Some(Debugger::Lldb);
|
||||
assert!(check_ignore(&config, "// ignore-lldb"));
|
||||
assert!(check_ignore(&config, "//@ ignore-lldb"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn git_hash() {
|
||||
let config: Config = cfg().git_hash(false).build();
|
||||
assert!(check_ignore(&config, "// needs-git-hash"));
|
||||
assert!(check_ignore(&config, "//@ needs-git-hash"));
|
||||
|
||||
let config: Config = cfg().git_hash(true).build();
|
||||
assert!(!check_ignore(&config, "// needs-git-hash"));
|
||||
assert!(!check_ignore(&config, "//@ needs-git-hash"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanitizers() {
|
||||
// Target that supports all sanitizers:
|
||||
let config: Config = cfg().target("x86_64-unknown-linux-gnu").build();
|
||||
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"));
|
||||
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:
|
||||
let config: Config = cfg().target("wasm32-unknown-emscripten").build();
|
||||
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"));
|
||||
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]
|
||||
fn profiler_support() {
|
||||
let config: Config = cfg().profiler_support(false).build();
|
||||
assert!(check_ignore(&config, "// needs-profiler-support"));
|
||||
assert!(check_ignore(&config, "//@ needs-profiler-support"));
|
||||
|
||||
let config: Config = cfg().profiler_support(true).build();
|
||||
assert!(!check_ignore(&config, "// needs-profiler-support"));
|
||||
assert!(!check_ignore(&config, "//@ needs-profiler-support"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -382,7 +382,7 @@ fn asm_support() {
|
||||
for (target, has_asm) in asms {
|
||||
let config = cfg().target(target).build();
|
||||
assert_eq!(config.has_asm_support(), has_asm);
|
||||
assert_eq!(check_ignore(&config, "// needs-asm-support"), !has_asm)
|
||||
assert_eq!(check_ignore(&config, "//@ needs-asm-support"), !has_asm)
|
||||
}
|
||||
}
|
||||
|
||||
@ -390,13 +390,13 @@ fn asm_support() {
|
||||
fn channel() {
|
||||
let config: Config = cfg().channel("beta").build();
|
||||
|
||||
assert!(check_ignore(&config, "// ignore-beta"));
|
||||
assert!(check_ignore(&config, "// only-nightly"));
|
||||
assert!(check_ignore(&config, "// only-stable"));
|
||||
assert!(check_ignore(&config, "//@ ignore-beta"));
|
||||
assert!(check_ignore(&config, "//@ only-nightly"));
|
||||
assert!(check_ignore(&config, "//@ only-stable"));
|
||||
|
||||
assert!(!check_ignore(&config, "// only-beta"));
|
||||
assert!(!check_ignore(&config, "// ignore-nightly"));
|
||||
assert!(!check_ignore(&config, "// ignore-stable"));
|
||||
assert!(!check_ignore(&config, "//@ only-beta"));
|
||||
assert!(!check_ignore(&config, "//@ ignore-nightly"));
|
||||
assert!(!check_ignore(&config, "//@ ignore-stable"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -418,7 +418,7 @@ fn test_extract_version_range() {
|
||||
#[should_panic(expected = "Duplicate revision: `rpass1` in line ` rpass1 rpass1`")]
|
||||
fn test_duplicate_revisions() {
|
||||
let config: Config = cfg().build();
|
||||
parse_rs(&config, "// revisions: rpass1 rpass1");
|
||||
parse_rs(&config, "//@ revisions: rpass1 rpass1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -432,7 +432,7 @@ fn ignore_arch() {
|
||||
for (target, arch) in archs {
|
||||
let config: Config = cfg().target(target).build();
|
||||
assert!(config.matches_arch(arch), "{target} {arch}");
|
||||
assert!(check_ignore(&config, &format!("// ignore-{arch}")));
|
||||
assert!(check_ignore(&config, &format!("//@ ignore-{arch}")));
|
||||
}
|
||||
}
|
||||
|
||||
@ -447,7 +447,7 @@ fn matches_os() {
|
||||
for (target, os) in oss {
|
||||
let config = cfg().target(target).build();
|
||||
assert!(config.matches_os(os), "{target} {os}");
|
||||
assert!(check_ignore(&config, &format!("// ignore-{os}")));
|
||||
assert!(check_ignore(&config, &format!("//@ ignore-{os}")));
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,7 +461,7 @@ fn matches_env() {
|
||||
for (target, env) in envs {
|
||||
let config: Config = cfg().target(target).build();
|
||||
assert!(config.matches_env(env), "{target} {env}");
|
||||
assert!(check_ignore(&config, &format!("// ignore-{env}")));
|
||||
assert!(check_ignore(&config, &format!("//@ ignore-{env}")));
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,7 +475,7 @@ fn matches_abi() {
|
||||
for (target, abi) in abis {
|
||||
let config: Config = cfg().target(target).build();
|
||||
assert!(config.matches_abi(abi), "{target} {abi}");
|
||||
assert!(check_ignore(&config, &format!("// ignore-{abi}")));
|
||||
assert!(check_ignore(&config, &format!("//@ ignore-{abi}")));
|
||||
}
|
||||
}
|
||||
|
||||
@ -491,7 +491,7 @@ fn is_big_endian() {
|
||||
for (target, is_big) in endians {
|
||||
let config = cfg().target(target).build();
|
||||
assert_eq!(config.is_big_endian(), is_big, "{target} {is_big}");
|
||||
assert_eq!(check_ignore(&config, "// ignore-endian-big"), is_big);
|
||||
assert_eq!(check_ignore(&config, "//@ ignore-endian-big"), is_big);
|
||||
}
|
||||
}
|
||||
|
||||
@ -506,9 +506,9 @@ fn pointer_width() {
|
||||
for (target, width) in widths {
|
||||
let config: Config = cfg().target(target).build();
|
||||
assert_eq!(config.get_pointer_width(), width, "{target} {width}");
|
||||
assert_eq!(check_ignore(&config, "// ignore-16bit"), width == 16);
|
||||
assert_eq!(check_ignore(&config, "// ignore-32bit"), width == 32);
|
||||
assert_eq!(check_ignore(&config, "// ignore-64bit"), width == 64);
|
||||
assert_eq!(check_ignore(&config, "//@ ignore-16bit"), width == 16);
|
||||
assert_eq!(check_ignore(&config, "//@ ignore-32bit"), width == 32);
|
||||
assert_eq!(check_ignore(&config, "//@ ignore-64bit"), width == 64);
|
||||
}
|
||||
}
|
||||
|
||||
@ -534,7 +534,7 @@ fn wasm_special() {
|
||||
for (target, pattern, ignore) in ignores {
|
||||
let config: Config = cfg().target(target).build();
|
||||
assert_eq!(
|
||||
check_ignore(&config, &format!("// ignore-{pattern}")),
|
||||
check_ignore(&config, &format!("//@ ignore-{pattern}")),
|
||||
ignore,
|
||||
"{target} {pattern}"
|
||||
);
|
||||
@ -555,8 +555,8 @@ fn families() {
|
||||
assert!(config.matches_family(family));
|
||||
let other = if family == "windows" { "unix" } else { "windows" };
|
||||
assert!(!config.matches_family(other));
|
||||
assert!(check_ignore(&config, &format!("// ignore-{family}")));
|
||||
assert!(!check_ignore(&config, &format!("// ignore-{other}")));
|
||||
assert!(check_ignore(&config, &format!("//@ ignore-{family}")));
|
||||
assert!(!check_ignore(&config, &format!("//@ ignore-{other}")));
|
||||
}
|
||||
}
|
||||
|
||||
@ -566,10 +566,17 @@ fn ignore_mode() {
|
||||
// Indicate profiler support so that "coverage-run" tests aren't skipped.
|
||||
let config: Config = cfg().mode(mode).profiler_support(true).build();
|
||||
let other = if mode == "coverage-run" { "coverage-map" } else { "coverage-run" };
|
||||
|
||||
assert_ne!(mode, other);
|
||||
assert_eq!(config.mode, Mode::from_str(mode).unwrap());
|
||||
assert_ne!(config.mode, Mode::from_str(other).unwrap());
|
||||
assert!(check_ignore(&config, &format!("// ignore-mode-{mode}")));
|
||||
assert!(!check_ignore(&config, &format!("// ignore-mode-{other}")));
|
||||
|
||||
if mode == "ui" {
|
||||
assert!(check_ignore(&config, &format!("//@ ignore-mode-{mode}")));
|
||||
assert!(!check_ignore(&config, &format!("//@ ignore-mode-{other}")));
|
||||
} else {
|
||||
assert!(check_ignore(&config, &format!("// ignore-mode-{mode}")));
|
||||
assert!(!check_ignore(&config, &format!("// ignore-mode-{other}")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,11 +55,14 @@ const ANNOTATIONS_TO_IGNORE: &[&str] = &[
|
||||
"// CHECK",
|
||||
"// EMIT_MIR",
|
||||
"// compile-flags",
|
||||
"//@ compile-flags",
|
||||
"// error-pattern",
|
||||
"//@ error-pattern",
|
||||
"// gdb",
|
||||
"// lldb",
|
||||
"// cdb",
|
||||
"// normalize-stderr-test",
|
||||
"//@ normalize-stderr-test",
|
||||
];
|
||||
|
||||
// Intentionally written in decimal rather than hex
|
||||
@ -128,7 +131,15 @@ fn should_ignore(line: &str) -> bool {
|
||||
// This mirrors the regex in src/tools/compiletest/src/runtest.rs, please
|
||||
// update both if either are changed.
|
||||
let re = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap();
|
||||
re.is_match(line) || ANNOTATIONS_TO_IGNORE.iter().any(|a| line.contains(a))
|
||||
// For `ui_test`-style UI test directives, also ignore
|
||||
// - `//@[rev] compile-flags`
|
||||
// - `//@[rev] normalize-stderr-test`
|
||||
let ui_test_long_directives =
|
||||
Regex::new("\\s*//@(\\[.*\\]) (compile-flags|normalize-stderr-test|error-pattern).*")
|
||||
.unwrap();
|
||||
re.is_match(line)
|
||||
|| ANNOTATIONS_TO_IGNORE.iter().any(|a| line.contains(a))
|
||||
|| ui_test_long_directives.is_match(line)
|
||||
}
|
||||
|
||||
/// Returns `true` if `line` is allowed to be longer than the normal limit.
|
||||
|
@ -14,8 +14,9 @@ use std::path::{Path, PathBuf};
|
||||
// #73494.
|
||||
const ENTRY_LIMIT: usize = 900;
|
||||
// FIXME: The following limits should be reduced eventually.
|
||||
|
||||
const ISSUES_ENTRY_LIMIT: usize = 1781;
|
||||
const ROOT_ENTRY_LIMIT: usize = 870;
|
||||
const ROOT_ENTRY_LIMIT: usize = 871;
|
||||
|
||||
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||
"rs", // test source files
|
||||
|
35
tests/ui/README.md
Normal file
35
tests/ui/README.md
Normal file
@ -0,0 +1,35 @@
|
||||
# UI Tests
|
||||
|
||||
This folder contains `rustc`'s
|
||||
[UI tests](https://rustc-dev-guide.rust-lang.org/tests/ui.html).
|
||||
|
||||
## Test Directives (Headers)
|
||||
|
||||
Typically, a UI test will have some test directives / headers which are
|
||||
special comments that tell compiletest how to build and intepret a test.
|
||||
|
||||
As part of an on-going effort to rewrite compiletest
|
||||
(see <https://github.com/rust-lang/compiler-team/issues/536>), a major
|
||||
change proposal to change legacy compiletest-style headers `// <directive>`
|
||||
to [`ui_test`](https://github.com/oli-obk/ui_test)-style headers
|
||||
`//@ <directive>` was accepted (see
|
||||
<https://github.com/rust-lang/compiler-team/issues/512>.
|
||||
|
||||
An example directive is `ignore-test`. In legacy compiletest style, the header
|
||||
would be written as
|
||||
|
||||
```rs
|
||||
// ignore-test
|
||||
```
|
||||
|
||||
but in `ui_test` style, the header would be written as
|
||||
|
||||
```rs
|
||||
//@ ignore-test
|
||||
```
|
||||
|
||||
compiletest is changed to accept only `//@` directives for UI tests
|
||||
(currently), and will reject and report an error if it encounters any
|
||||
comments `// <content>` that may be parsed as an legacy compiletest-style
|
||||
test header. To fix this, you should migrate to the `ui_test`-style header
|
||||
`//@ <content>`.
|
@ -1,3 +1,4 @@
|
||||
// ignore-tidy-linelength
|
||||
// build-pass
|
||||
// only-x86
|
||||
// only-windows
|
||||
|
Loading…
Reference in New Issue
Block a user