mirror of
https://github.com/rust-lang/rust.git
synced 2025-10-02 10:18:25 +00:00
Rollup merge of #143823 - jieyouxu:compiletest-maintenance-5, r=Kobzol
[COMPILETEST-UNTANGLE 5/N] Test mode adjustments and other assorted cleanups This is part of a patch series to untangle `compiletest` to hopefully nudge it towards being more maintainable. This PR should contain no functional changes modulo the removed debugger version warning. - Commit 1: Removes a very outdated debugger version warning. - Commit 2: Moves `string_enum` out of `common` into `util` module. - Commit 3: Remove `#[derive(Default)` for `Mode` and `Config`. It is very important for correctness that we *don't* `#[derive(Default)]`, because there are no sensible defaults, so stop pretending there is. - Commit 4: Rename `Mode` -> `TestMode`, because I would like to introduce a `TestSuite` enum to stop using stringly-typed test suite names where test mode names can be the same as test suite names, and we also have a bunch of other "modes" in compiletest. Make this as unambiguous as possible. A corollary is that now it's more natural to reference via intra-doc links as ``[`TestMode`]``. - Commit 5: Ditto on `TestSuite`, stop glob-reexporting `TestMode::*` variants, and always use `EnumName::VariantName` form. - Commit 6: Apparently, `src/tools/rustdoc-gui-test/` depends on `compiletest` for `//@ {compile,run}-paths` directive parsing and extraction, which involves creating a dummy `compiletest` config (hence the existence of the default impls removed in Commit 3). Make this a specific associated function with a FIXME pointing to rust-lang/rust#143827 as I think this setup is quite questionable. Commits {4, 5} are also intended to help improve the self-consistency in nomenclature used within compiletest. Best reviewed commit-by-commit.
This commit is contained in:
commit
bb330bbc50
@ -1,63 +1,20 @@
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
use std::iter;
|
||||
use std::process::Command;
|
||||
use std::str::FromStr;
|
||||
use std::sync::OnceLock;
|
||||
use std::{fmt, iter};
|
||||
|
||||
use build_helper::git::GitConfig;
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use semver::Version;
|
||||
use serde::de::{Deserialize, Deserializer, Error as _};
|
||||
|
||||
pub use self::Mode::*;
|
||||
use crate::executor::{ColorConfig, OutputFormat};
|
||||
use crate::fatal;
|
||||
use crate::util::{Utf8PathBufExt, add_dylib_path};
|
||||
|
||||
macro_rules! string_enum {
|
||||
($(#[$meta:meta])* $vis:vis enum $name:ident { $($variant:ident => $repr:expr,)* }) => {
|
||||
$(#[$meta])*
|
||||
$vis enum $name {
|
||||
$($variant,)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
$vis const VARIANTS: &'static [Self] = &[$(Self::$variant,)*];
|
||||
$vis const STR_VARIANTS: &'static [&'static str] = &[$(Self::$variant.to_str(),)*];
|
||||
|
||||
$vis const fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
$(Self::$variant => $repr,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self.to_str(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for $name {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
$($repr => Ok(Self::$variant),)*
|
||||
_ => Err(format!(concat!("unknown `", stringify!($name), "` variant: `{}`"), s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make the macro visible outside of this module, for tests.
|
||||
#[cfg(test)]
|
||||
pub(crate) use string_enum;
|
||||
use crate::util::{Utf8PathBufExt, add_dylib_path, string_enum};
|
||||
|
||||
string_enum! {
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub enum Mode {
|
||||
pub enum TestMode {
|
||||
Pretty => "pretty",
|
||||
DebugInfo => "debuginfo",
|
||||
Codegen => "codegen",
|
||||
@ -76,18 +33,12 @@ string_enum! {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Mode {
|
||||
fn default() -> Self {
|
||||
Mode::Ui
|
||||
}
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
impl TestMode {
|
||||
pub fn aux_dir_disambiguator(self) -> &'static str {
|
||||
// Pretty-printing tests could run concurrently, and if they do,
|
||||
// they need to keep their output segregated.
|
||||
match self {
|
||||
Pretty => ".pretty",
|
||||
TestMode::Pretty => ".pretty",
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
@ -96,7 +47,7 @@ impl Mode {
|
||||
// Coverage tests use the same test files for multiple test modes,
|
||||
// so each mode should have a separate output directory.
|
||||
match self {
|
||||
CoverageMap | CoverageRun => self.to_str(),
|
||||
TestMode::CoverageMap | TestMode::CoverageRun => self.to_str(),
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
@ -193,9 +144,9 @@ pub enum Sanitizer {
|
||||
///
|
||||
/// FIXME: audit these options to make sure we are not hashing less than necessary for build stamp
|
||||
/// (for changed test detection).
|
||||
#[derive(Debug, Default, Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
/// Some test [`Mode`]s support [snapshot testing], where a *reference snapshot* of outputs (of
|
||||
/// Some [`TestMode`]s support [snapshot testing], where a *reference snapshot* of outputs (of
|
||||
/// `stdout`, `stderr`, or other form of artifacts) can be compared to the *actual output*.
|
||||
///
|
||||
/// This option can be set to `true` to update the *reference snapshots* in-place, otherwise
|
||||
@ -317,20 +268,20 @@ pub struct Config {
|
||||
/// FIXME: reconsider this string; this is hashed for test build stamp.
|
||||
pub stage_id: String,
|
||||
|
||||
/// The test [`Mode`]. E.g. [`Mode::Ui`]. Each test mode can correspond to one or more test
|
||||
/// The [`TestMode`]. E.g. [`TestMode::Ui`]. Each test mode can correspond to one or more test
|
||||
/// suites.
|
||||
///
|
||||
/// FIXME: stop using stringly-typed test suites!
|
||||
pub mode: Mode,
|
||||
pub mode: TestMode,
|
||||
|
||||
/// The test suite.
|
||||
///
|
||||
/// Example: `tests/ui/` is the "UI" test *suite*, which happens to also be of the [`Mode::Ui`]
|
||||
/// test *mode*.
|
||||
/// Example: `tests/ui/` is the "UI" test *suite*, which happens to also be of the
|
||||
/// [`TestMode::Ui`] test *mode*.
|
||||
///
|
||||
/// Note that the same test directory (e.g. `tests/coverage/`) may correspond to multiple test
|
||||
/// modes, e.g. `tests/coverage/` can be run under both [`Mode::CoverageRun`] and
|
||||
/// [`Mode::CoverageMap`].
|
||||
/// modes, e.g. `tests/coverage/` can be run under both [`TestMode::CoverageRun`] and
|
||||
/// [`TestMode::CoverageMap`].
|
||||
///
|
||||
/// FIXME: stop using stringly-typed test suites!
|
||||
pub suite: String,
|
||||
@ -586,8 +537,8 @@ pub struct Config {
|
||||
// Configuration for various run-make tests frobbing things like C compilers or querying about
|
||||
// various LLVM component information.
|
||||
//
|
||||
// FIXME: this really should be better packaged together.
|
||||
// FIXME: these need better docs, e.g. for *host*, or for *target*?
|
||||
// FIXME: this really should be better packaged together. FIXME: these need better docs, e.g.
|
||||
// for *host*, or for *target*?
|
||||
pub cc: String,
|
||||
pub cxx: String,
|
||||
pub cflags: String,
|
||||
@ -653,6 +604,107 @@ pub struct Config {
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Incomplete config intended for `src/tools/rustdoc-gui-test` **only** as
|
||||
/// `src/tools/rustdoc-gui-test` wants to reuse `compiletest`'s directive -> test property
|
||||
/// handling for `//@ {compile,run}-flags`, do not use for any other purpose.
|
||||
///
|
||||
/// FIXME(#143827): this setup feels very hacky. It so happens that `tests/rustdoc-gui/`
|
||||
/// **only** uses `//@ {compile,run}-flags` for now and not any directives that actually rely on
|
||||
/// info that is assumed available in a fully populated [`Config`].
|
||||
pub fn incomplete_for_rustdoc_gui_test() -> Config {
|
||||
// FIXME(#143827): spelling this out intentionally, because this is questionable.
|
||||
//
|
||||
// For instance, `//@ ignore-stage1` will not work at all.
|
||||
Config {
|
||||
mode: TestMode::Rustdoc,
|
||||
|
||||
// Dummy values.
|
||||
edition: Default::default(),
|
||||
bless: Default::default(),
|
||||
fail_fast: Default::default(),
|
||||
compile_lib_path: Utf8PathBuf::default(),
|
||||
run_lib_path: Utf8PathBuf::default(),
|
||||
rustc_path: Utf8PathBuf::default(),
|
||||
cargo_path: Default::default(),
|
||||
stage0_rustc_path: Default::default(),
|
||||
rustdoc_path: Default::default(),
|
||||
coverage_dump_path: Default::default(),
|
||||
python: Default::default(),
|
||||
jsondocck_path: Default::default(),
|
||||
jsondoclint_path: Default::default(),
|
||||
llvm_filecheck: Default::default(),
|
||||
llvm_bin_dir: Default::default(),
|
||||
run_clang_based_tests_with: Default::default(),
|
||||
src_root: Utf8PathBuf::default(),
|
||||
src_test_suite_root: Utf8PathBuf::default(),
|
||||
build_root: Utf8PathBuf::default(),
|
||||
build_test_suite_root: Utf8PathBuf::default(),
|
||||
sysroot_base: Utf8PathBuf::default(),
|
||||
stage: Default::default(),
|
||||
stage_id: String::default(),
|
||||
suite: Default::default(),
|
||||
debugger: Default::default(),
|
||||
run_ignored: Default::default(),
|
||||
with_rustc_debug_assertions: Default::default(),
|
||||
with_std_debug_assertions: Default::default(),
|
||||
filters: Default::default(),
|
||||
skip: Default::default(),
|
||||
filter_exact: Default::default(),
|
||||
force_pass_mode: Default::default(),
|
||||
run: Default::default(),
|
||||
runner: Default::default(),
|
||||
host_rustcflags: Default::default(),
|
||||
target_rustcflags: Default::default(),
|
||||
rust_randomized_layout: Default::default(),
|
||||
optimize_tests: Default::default(),
|
||||
target: Default::default(),
|
||||
host: Default::default(),
|
||||
cdb: Default::default(),
|
||||
cdb_version: Default::default(),
|
||||
gdb: Default::default(),
|
||||
gdb_version: Default::default(),
|
||||
lldb_version: Default::default(),
|
||||
llvm_version: Default::default(),
|
||||
system_llvm: Default::default(),
|
||||
android_cross_path: Default::default(),
|
||||
adb_path: Default::default(),
|
||||
adb_test_dir: Default::default(),
|
||||
adb_device_status: Default::default(),
|
||||
lldb_python_dir: Default::default(),
|
||||
verbose: Default::default(),
|
||||
format: Default::default(),
|
||||
color: Default::default(),
|
||||
remote_test_client: Default::default(),
|
||||
compare_mode: Default::default(),
|
||||
rustfix_coverage: Default::default(),
|
||||
has_html_tidy: Default::default(),
|
||||
has_enzyme: Default::default(),
|
||||
channel: Default::default(),
|
||||
git_hash: Default::default(),
|
||||
cc: Default::default(),
|
||||
cxx: Default::default(),
|
||||
cflags: Default::default(),
|
||||
cxxflags: Default::default(),
|
||||
ar: Default::default(),
|
||||
target_linker: Default::default(),
|
||||
host_linker: Default::default(),
|
||||
llvm_components: Default::default(),
|
||||
nodejs: Default::default(),
|
||||
npm: Default::default(),
|
||||
force_rerun: Default::default(),
|
||||
only_modified: Default::default(),
|
||||
target_cfgs: Default::default(),
|
||||
builtin_cfg_names: Default::default(),
|
||||
supported_crate_types: Default::default(),
|
||||
nocapture: Default::default(),
|
||||
nightly_branch: Default::default(),
|
||||
git_merge_commit_email: Default::default(),
|
||||
profiler_runtime: Default::default(),
|
||||
diff_command: Default::default(),
|
||||
minicore_path: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// FIXME: this run scheme is... confusing.
|
||||
pub fn run_enabled(&self) -> bool {
|
||||
self.run.unwrap_or_else(|| {
|
||||
|
@ -51,17 +51,6 @@ pub(crate) fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
|
||||
pub(crate) fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
|
||||
config.lldb_python_dir.as_ref()?;
|
||||
|
||||
// FIXME: this is super old
|
||||
if let Some(350) = config.lldb_version {
|
||||
println!(
|
||||
"WARNING: The used version of LLDB (350) has a \
|
||||
known issue that breaks debuginfo tests. See \
|
||||
issue #32520 for more information. Skipping all \
|
||||
LLDB-based tests!",
|
||||
);
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() }))
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ use camino::{Utf8Path, Utf8PathBuf};
|
||||
use semver::Version;
|
||||
use tracing::*;
|
||||
|
||||
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
|
||||
use crate::common::{Config, Debugger, FailMode, PassMode, TestMode};
|
||||
use crate::debuggers::{extract_cdb_version, extract_gdb_version};
|
||||
use crate::directives::auxiliary::{AuxProps, parse_and_update_aux};
|
||||
use crate::directives::needs::CachedNeedsConditions;
|
||||
@ -328,7 +328,7 @@ impl TestProps {
|
||||
props.exec_env.push(("RUSTC".to_string(), config.rustc_path.to_string()));
|
||||
|
||||
match (props.pass_mode, props.fail_mode) {
|
||||
(None, None) if config.mode == Mode::Ui => props.fail_mode = Some(FailMode::Check),
|
||||
(None, None) if config.mode == TestMode::Ui => props.fail_mode = Some(FailMode::Check),
|
||||
(Some(_), Some(_)) => panic!("cannot use a *-fail and *-pass mode together"),
|
||||
_ => {}
|
||||
}
|
||||
@ -609,11 +609,11 @@ impl TestProps {
|
||||
self.failure_status = Some(101);
|
||||
}
|
||||
|
||||
if config.mode == Mode::Incremental {
|
||||
if config.mode == TestMode::Incremental {
|
||||
self.incremental = true;
|
||||
}
|
||||
|
||||
if config.mode == Mode::Crashes {
|
||||
if config.mode == TestMode::Crashes {
|
||||
// we don't want to pollute anything with backtrace-files
|
||||
// also turn off backtraces in order to save some execution
|
||||
// time on the tests; we only need to know IF it crashes
|
||||
@ -641,11 +641,11 @@ impl TestProps {
|
||||
fn update_fail_mode(&mut self, ln: &str, config: &Config) {
|
||||
let check_ui = |mode: &str| {
|
||||
// Mode::Crashes may need build-fail in order to trigger llvm errors or stack overflows
|
||||
if config.mode != Mode::Ui && config.mode != Mode::Crashes {
|
||||
if config.mode != TestMode::Ui && config.mode != TestMode::Crashes {
|
||||
panic!("`{}-fail` directive is only supported in UI tests", mode);
|
||||
}
|
||||
};
|
||||
if config.mode == Mode::Ui && config.parse_name_directive(ln, "compile-fail") {
|
||||
if config.mode == TestMode::Ui && config.parse_name_directive(ln, "compile-fail") {
|
||||
panic!("`compile-fail` directive is useless in UI tests");
|
||||
}
|
||||
let fail_mode = if config.parse_name_directive(ln, "check-fail") {
|
||||
@ -669,10 +669,10 @@ impl TestProps {
|
||||
|
||||
fn update_pass_mode(&mut self, ln: &str, revision: Option<&str>, config: &Config) {
|
||||
let check_no_run = |s| match (config.mode, s) {
|
||||
(Mode::Ui, _) => (),
|
||||
(Mode::Crashes, _) => (),
|
||||
(Mode::Codegen, "build-pass") => (),
|
||||
(Mode::Incremental, _) => {
|
||||
(TestMode::Ui, _) => (),
|
||||
(TestMode::Crashes, _) => (),
|
||||
(TestMode::Codegen, "build-pass") => (),
|
||||
(TestMode::Incremental, _) => {
|
||||
if revision.is_some() && !self.revisions.iter().all(|r| r.starts_with("cfail")) {
|
||||
panic!("`{s}` directive is only supported in `cfail` incremental tests")
|
||||
}
|
||||
@ -715,7 +715,7 @@ impl TestProps {
|
||||
pub fn update_add_core_stubs(&mut self, ln: &str, config: &Config) {
|
||||
let add_core_stubs = config.parse_name_directive(ln, directives::ADD_CORE_STUBS);
|
||||
if add_core_stubs {
|
||||
if !matches!(config.mode, Mode::Ui | Mode::Codegen | Mode::Assembly) {
|
||||
if !matches!(config.mode, TestMode::Ui | TestMode::Codegen | TestMode::Assembly) {
|
||||
panic!(
|
||||
"`add-core-stubs` is currently only supported for ui, codegen and assembly test modes"
|
||||
);
|
||||
@ -833,7 +833,7 @@ pub(crate) struct CheckDirectiveResult<'ln> {
|
||||
|
||||
pub(crate) fn check_directive<'a>(
|
||||
directive_ln: &'a str,
|
||||
mode: Mode,
|
||||
mode: TestMode,
|
||||
original_line: &str,
|
||||
) -> CheckDirectiveResult<'a> {
|
||||
let (directive_name, post) = directive_ln.split_once([':', ' ']).unwrap_or((directive_ln, ""));
|
||||
@ -842,11 +842,11 @@ pub(crate) fn check_directive<'a>(
|
||||
let is_known = |s: &str| {
|
||||
KNOWN_DIRECTIVE_NAMES.contains(&s)
|
||||
|| match mode {
|
||||
Mode::Rustdoc | Mode::RustdocJson => {
|
||||
TestMode::Rustdoc | TestMode::RustdocJson => {
|
||||
original_line.starts_with("//@")
|
||||
&& match mode {
|
||||
Mode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,
|
||||
Mode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
|
||||
TestMode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,
|
||||
TestMode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
.contains(&s)
|
||||
@ -868,7 +868,7 @@ pub(crate) fn check_directive<'a>(
|
||||
const COMPILETEST_DIRECTIVE_PREFIX: &str = "//@";
|
||||
|
||||
fn iter_directives(
|
||||
mode: Mode,
|
||||
mode: TestMode,
|
||||
_suite: &str,
|
||||
poisoned: &mut bool,
|
||||
testfile: &Utf8Path,
|
||||
@ -883,7 +883,7 @@ fn iter_directives(
|
||||
// specify them manually in every test file.
|
||||
//
|
||||
// FIXME(jieyouxu): I feel like there's a better way to do this, leaving for later.
|
||||
if mode == Mode::CoverageRun {
|
||||
if mode == TestMode::CoverageRun {
|
||||
let extra_directives: &[&str] = &[
|
||||
"needs-profiler-runtime",
|
||||
// FIXME(pietroalbini): this test currently does not work on cross-compiled targets
|
||||
@ -964,7 +964,7 @@ impl Config {
|
||||
["CHECK", "COM", "NEXT", "SAME", "EMPTY", "NOT", "COUNT", "DAG", "LABEL"];
|
||||
|
||||
if let Some(raw) = self.parse_name_value_directive(line, "revisions") {
|
||||
if self.mode == Mode::RunMake {
|
||||
if self.mode == TestMode::RunMake {
|
||||
panic!("`run-make` tests do not support revisions: {}", testfile);
|
||||
}
|
||||
|
||||
@ -981,7 +981,7 @@ impl Config {
|
||||
);
|
||||
}
|
||||
|
||||
if matches!(self.mode, Mode::Assembly | Mode::Codegen | Mode::MirOpt)
|
||||
if matches!(self.mode, TestMode::Assembly | TestMode::Codegen | TestMode::MirOpt)
|
||||
&& FILECHECK_FORBIDDEN_REVISION_NAMES.contains(&revision)
|
||||
{
|
||||
panic!(
|
||||
@ -1443,7 +1443,7 @@ pub(crate) fn make_test_description<R: Read>(
|
||||
// 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 => ShouldPanic::No,
|
||||
TestMode::Pretty => ShouldPanic::No,
|
||||
_ if should_fail => ShouldPanic::Yes,
|
||||
_ => ShouldPanic::No,
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ use super::{
|
||||
DirectivesCache, EarlyProps, extract_llvm_version, extract_version_range, iter_directives,
|
||||
parse_normalize_rule,
|
||||
};
|
||||
use crate::common::{Config, Debugger, Mode};
|
||||
use crate::common::{Config, Debugger, TestMode};
|
||||
use crate::executor::{CollectedTestDesc, ShouldPanic};
|
||||
|
||||
fn make_test_description<R: Read>(
|
||||
@ -785,7 +785,7 @@ fn threads_support() {
|
||||
|
||||
fn run_path(poisoned: &mut bool, path: &Utf8Path, buf: &[u8]) {
|
||||
let rdr = std::io::Cursor::new(&buf);
|
||||
iter_directives(Mode::Ui, "ui", poisoned, path, rdr, &mut |_| {});
|
||||
iter_directives(TestMode::Ui, "ui", poisoned, path, rdr, &mut |_| {});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -39,8 +39,8 @@ use walkdir::WalkDir;
|
||||
|
||||
use self::directives::{EarlyProps, make_test_description};
|
||||
use crate::common::{
|
||||
CompareMode, Config, Debugger, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path,
|
||||
output_base_dir, output_relative_path,
|
||||
CompareMode, Config, Debugger, PassMode, TestMode, TestPaths, UI_EXTENSIONS,
|
||||
expected_output_path, output_base_dir, output_relative_path,
|
||||
};
|
||||
use crate::directives::DirectivesCache;
|
||||
use crate::executor::{CollectedTest, ColorConfig, OutputFormat};
|
||||
@ -268,7 +268,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||
let with_rustc_debug_assertions = matches.opt_present("with-rustc-debug-assertions");
|
||||
let with_std_debug_assertions = matches.opt_present("with-std-debug-assertions");
|
||||
let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode");
|
||||
let has_html_tidy = if mode == Mode::Rustdoc {
|
||||
let has_html_tidy = if mode == TestMode::Rustdoc {
|
||||
Command::new("tidy")
|
||||
.arg("--version")
|
||||
.stdout(Stdio::null())
|
||||
@ -279,7 +279,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||
false
|
||||
};
|
||||
let has_enzyme = matches.opt_present("has-enzyme");
|
||||
let filters = if mode == Mode::RunMake {
|
||||
let filters = if mode == TestMode::RunMake {
|
||||
matches
|
||||
.free
|
||||
.iter()
|
||||
@ -545,7 +545,7 @@ pub fn run_tests(config: Arc<Config>) {
|
||||
unsafe { env::set_var("TARGET", &config.target) };
|
||||
|
||||
let mut configs = Vec::new();
|
||||
if let Mode::DebugInfo = config.mode {
|
||||
if let TestMode::DebugInfo = config.mode {
|
||||
// Debugging emscripten code doesn't make sense today
|
||||
if !config.target.contains("emscripten") {
|
||||
match config.debugger {
|
||||
@ -783,7 +783,7 @@ fn collect_tests_from_dir(
|
||||
}
|
||||
|
||||
// For run-make tests, a "test file" is actually a directory that contains an `rmake.rs`.
|
||||
if cx.config.mode == Mode::RunMake {
|
||||
if cx.config.mode == TestMode::RunMake {
|
||||
let mut collector = TestCollector::new();
|
||||
if dir.join("rmake.rs").exists() {
|
||||
let paths = TestPaths {
|
||||
@ -869,7 +869,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
|
||||
// For run-make tests, each "test file" is actually a _directory_ containing an `rmake.rs`. But
|
||||
// for the purposes of directive parsing, we want to look at that recipe file, not the directory
|
||||
// itself.
|
||||
let test_path = if cx.config.mode == Mode::RunMake {
|
||||
let test_path = if cx.config.mode == TestMode::RunMake {
|
||||
testpaths.file.join("rmake.rs")
|
||||
} else {
|
||||
testpaths.file.clone()
|
||||
@ -884,7 +884,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
|
||||
// - Incremental tests inherently can't run their revisions in parallel, so
|
||||
// we treat them like non-revisioned tests here. Incremental revisions are
|
||||
// handled internally by `runtest::run` instead.
|
||||
let revisions = if early_props.revisions.is_empty() || cx.config.mode == Mode::Incremental {
|
||||
let revisions = if early_props.revisions.is_empty() || cx.config.mode == TestMode::Incremental {
|
||||
vec![None]
|
||||
} else {
|
||||
early_props.revisions.iter().map(|r| Some(r.as_str())).collect()
|
||||
@ -1116,11 +1116,11 @@ fn check_for_overlapping_test_paths(found_path_stems: &HashSet<Utf8PathBuf>) {
|
||||
}
|
||||
|
||||
pub fn early_config_check(config: &Config) {
|
||||
if !config.has_html_tidy && config.mode == Mode::Rustdoc {
|
||||
if !config.has_html_tidy && config.mode == TestMode::Rustdoc {
|
||||
warning!("`tidy` (html-tidy.org) is not installed; diffs will not be generated");
|
||||
}
|
||||
|
||||
if !config.profiler_runtime && config.mode == Mode::CoverageRun {
|
||||
if !config.profiler_runtime && config.mode == TestMode::CoverageRun {
|
||||
let actioned = if config.bless { "blessed" } else { "checked" };
|
||||
warning!("profiler runtime is not available, so `.coverage` files won't be {actioned}");
|
||||
help!("try setting `profiler = true` in the `[build]` section of `bootstrap.toml`");
|
||||
|
@ -16,11 +16,10 @@ use regex::{Captures, Regex};
|
||||
use tracing::*;
|
||||
|
||||
use crate::common::{
|
||||
Assembly, Codegen, CodegenUnits, CompareMode, Config, CoverageMap, CoverageRun, Crashes,
|
||||
DebugInfo, Debugger, FailMode, Incremental, MirOpt, PassMode, Pretty, RunMake, Rustdoc,
|
||||
RustdocJs, RustdocJson, TestPaths, UI_EXTENSIONS, UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT,
|
||||
UI_STDERR, UI_STDOUT, UI_SVG, UI_WINDOWS_SVG, Ui, expected_output_path, incremental_dir,
|
||||
output_base_dir, output_base_name, output_testname_unique,
|
||||
CompareMode, Config, Debugger, FailMode, PassMode, TestMode, TestPaths, UI_EXTENSIONS,
|
||||
UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT, UI_STDERR, UI_STDOUT, UI_SVG, UI_WINDOWS_SVG,
|
||||
expected_output_path, incremental_dir, output_base_dir, output_base_name,
|
||||
output_testname_unique,
|
||||
};
|
||||
use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
|
||||
use crate::directives::TestProps;
|
||||
@ -154,7 +153,7 @@ pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
|
||||
cx.init_incremental_test();
|
||||
}
|
||||
|
||||
if config.mode == Incremental {
|
||||
if config.mode == TestMode::Incremental {
|
||||
// Incremental tests are special because they cannot be run in
|
||||
// parallel.
|
||||
assert!(!props.revisions.is_empty(), "Incremental tests require revisions.");
|
||||
@ -203,7 +202,7 @@ pub fn compute_stamp_hash(config: &Config) -> String {
|
||||
None => {}
|
||||
}
|
||||
|
||||
if let Ui = config.mode {
|
||||
if config.mode == TestMode::Ui {
|
||||
config.force_pass_mode.hash(&mut hash);
|
||||
}
|
||||
|
||||
@ -251,25 +250,28 @@ impl<'test> TestCx<'test> {
|
||||
/// Code executed for each revision in turn (or, if there are no
|
||||
/// revisions, exactly once, with revision == None).
|
||||
fn run_revision(&self) {
|
||||
if self.props.should_ice && self.config.mode != Incremental && self.config.mode != Crashes {
|
||||
if self.props.should_ice
|
||||
&& self.config.mode != TestMode::Incremental
|
||||
&& self.config.mode != TestMode::Crashes
|
||||
{
|
||||
self.fatal("cannot use should-ice in a test that is not cfail");
|
||||
}
|
||||
match self.config.mode {
|
||||
Pretty => self.run_pretty_test(),
|
||||
DebugInfo => self.run_debuginfo_test(),
|
||||
Codegen => self.run_codegen_test(),
|
||||
Rustdoc => self.run_rustdoc_test(),
|
||||
RustdocJson => self.run_rustdoc_json_test(),
|
||||
CodegenUnits => self.run_codegen_units_test(),
|
||||
Incremental => self.run_incremental_test(),
|
||||
RunMake => self.run_rmake_test(),
|
||||
Ui => self.run_ui_test(),
|
||||
MirOpt => self.run_mir_opt_test(),
|
||||
Assembly => self.run_assembly_test(),
|
||||
RustdocJs => self.run_rustdoc_js_test(),
|
||||
CoverageMap => self.run_coverage_map_test(), // see self::coverage
|
||||
CoverageRun => self.run_coverage_run_test(), // see self::coverage
|
||||
Crashes => self.run_crash_test(),
|
||||
TestMode::Pretty => self.run_pretty_test(),
|
||||
TestMode::DebugInfo => self.run_debuginfo_test(),
|
||||
TestMode::Codegen => self.run_codegen_test(),
|
||||
TestMode::Rustdoc => self.run_rustdoc_test(),
|
||||
TestMode::RustdocJson => self.run_rustdoc_json_test(),
|
||||
TestMode::CodegenUnits => self.run_codegen_units_test(),
|
||||
TestMode::Incremental => self.run_incremental_test(),
|
||||
TestMode::RunMake => self.run_rmake_test(),
|
||||
TestMode::Ui => self.run_ui_test(),
|
||||
TestMode::MirOpt => self.run_mir_opt_test(),
|
||||
TestMode::Assembly => self.run_assembly_test(),
|
||||
TestMode::RustdocJs => self.run_rustdoc_js_test(),
|
||||
TestMode::CoverageMap => self.run_coverage_map_test(), // see self::coverage
|
||||
TestMode::CoverageRun => self.run_coverage_run_test(), // see self::coverage
|
||||
TestMode::Crashes => self.run_crash_test(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,9 +281,13 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
fn should_run(&self, pm: Option<PassMode>) -> WillExecute {
|
||||
let test_should_run = match self.config.mode {
|
||||
Ui if pm == Some(PassMode::Run) || self.props.fail_mode == Some(FailMode::Run) => true,
|
||||
MirOpt if pm == Some(PassMode::Run) => true,
|
||||
Ui | MirOpt => false,
|
||||
TestMode::Ui
|
||||
if pm == Some(PassMode::Run) || self.props.fail_mode == Some(FailMode::Run) =>
|
||||
{
|
||||
true
|
||||
}
|
||||
TestMode::MirOpt if pm == Some(PassMode::Run) => true,
|
||||
TestMode::Ui | TestMode::MirOpt => false,
|
||||
mode => panic!("unimplemented for mode {:?}", mode),
|
||||
};
|
||||
if test_should_run { self.run_if_enabled() } else { WillExecute::No }
|
||||
@ -293,17 +299,17 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
fn should_run_successfully(&self, pm: Option<PassMode>) -> bool {
|
||||
match self.config.mode {
|
||||
Ui | MirOpt => pm == Some(PassMode::Run),
|
||||
TestMode::Ui | TestMode::MirOpt => pm == Some(PassMode::Run),
|
||||
mode => panic!("unimplemented for mode {:?}", mode),
|
||||
}
|
||||
}
|
||||
|
||||
fn should_compile_successfully(&self, pm: Option<PassMode>) -> bool {
|
||||
match self.config.mode {
|
||||
RustdocJs => true,
|
||||
Ui => pm.is_some() || self.props.fail_mode > Some(FailMode::Build),
|
||||
Crashes => false,
|
||||
Incremental => {
|
||||
TestMode::RustdocJs => true,
|
||||
TestMode::Ui => pm.is_some() || self.props.fail_mode > Some(FailMode::Build),
|
||||
TestMode::Crashes => false,
|
||||
TestMode::Incremental => {
|
||||
let revision =
|
||||
self.revision.expect("incremental tests require a list of revisions");
|
||||
if revision.starts_with("cpass")
|
||||
@ -349,7 +355,7 @@ impl<'test> TestCx<'test> {
|
||||
if proc_res.status.success() {
|
||||
{
|
||||
self.error(&format!("{} test did not emit an error", self.config.mode));
|
||||
if self.config.mode == crate::common::Mode::Ui {
|
||||
if self.config.mode == crate::common::TestMode::Ui {
|
||||
println!("note: by default, ui tests are expected not to compile");
|
||||
}
|
||||
proc_res.fatal(None, || ());
|
||||
@ -892,7 +898,9 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
fn should_emit_metadata(&self, pm: Option<PassMode>) -> Emit {
|
||||
match (pm, self.props.fail_mode, self.config.mode) {
|
||||
(Some(PassMode::Check), ..) | (_, Some(FailMode::Check), Ui) => Emit::Metadata,
|
||||
(Some(PassMode::Check), ..) | (_, Some(FailMode::Check), TestMode::Ui) => {
|
||||
Emit::Metadata
|
||||
}
|
||||
_ => Emit::None,
|
||||
}
|
||||
}
|
||||
@ -926,7 +934,7 @@ impl<'test> TestCx<'test> {
|
||||
};
|
||||
|
||||
let allow_unused = match self.config.mode {
|
||||
Ui => {
|
||||
TestMode::Ui => {
|
||||
// UI tests tend to have tons of unused code as
|
||||
// it's just testing various pieces of the compile, but we don't
|
||||
// want to actually assert warnings about all this code. Instead
|
||||
@ -1021,7 +1029,7 @@ impl<'test> TestCx<'test> {
|
||||
.args(&self.props.compile_flags)
|
||||
.args(&self.props.doc_flags);
|
||||
|
||||
if self.config.mode == RustdocJson {
|
||||
if self.config.mode == TestMode::RustdocJson {
|
||||
rustdoc.arg("--output-format").arg("json").arg("-Zunstable-options");
|
||||
}
|
||||
|
||||
@ -1372,7 +1380,7 @@ impl<'test> TestCx<'test> {
|
||||
|| self.is_vxworks_pure_static()
|
||||
|| self.config.target.contains("bpf")
|
||||
|| !self.config.target_cfg().dynamic_linking
|
||||
|| matches!(self.config.mode, CoverageMap | CoverageRun)
|
||||
|| matches!(self.config.mode, TestMode::CoverageMap | TestMode::CoverageRun)
|
||||
{
|
||||
// We primarily compile all auxiliary libraries as dynamic libraries
|
||||
// to avoid code size bloat and large binaries as much as possible
|
||||
@ -1562,14 +1570,14 @@ impl<'test> TestCx<'test> {
|
||||
rustc.args(&["-Z", "incremental-verify-ich"]);
|
||||
}
|
||||
|
||||
if self.config.mode == CodegenUnits {
|
||||
if self.config.mode == TestMode::CodegenUnits {
|
||||
rustc.args(&["-Z", "human_readable_cgu_names"]);
|
||||
}
|
||||
}
|
||||
|
||||
if self.config.optimize_tests && !is_rustdoc {
|
||||
match self.config.mode {
|
||||
Ui => {
|
||||
TestMode::Ui => {
|
||||
// If optimize-tests is true we still only want to optimize tests that actually get
|
||||
// executed and that don't specify their own optimization levels.
|
||||
// Note: aux libs don't have a pass-mode, so they won't get optimized
|
||||
@ -1585,8 +1593,8 @@ impl<'test> TestCx<'test> {
|
||||
rustc.arg("-O");
|
||||
}
|
||||
}
|
||||
DebugInfo => { /* debuginfo tests must be unoptimized */ }
|
||||
CoverageMap | CoverageRun => {
|
||||
TestMode::DebugInfo => { /* debuginfo tests must be unoptimized */ }
|
||||
TestMode::CoverageMap | TestMode::CoverageRun => {
|
||||
// Coverage mappings and coverage reports are affected by
|
||||
// optimization level, so they ignore the optimize-tests
|
||||
// setting and set an optimization level in their mode's
|
||||
@ -1607,7 +1615,7 @@ impl<'test> TestCx<'test> {
|
||||
};
|
||||
|
||||
match self.config.mode {
|
||||
Incremental => {
|
||||
TestMode::Incremental => {
|
||||
// If we are extracting and matching errors in the new
|
||||
// fashion, then you want JSON mode. Old-skool error
|
||||
// patterns still match the raw compiler output.
|
||||
@ -1620,7 +1628,7 @@ impl<'test> TestCx<'test> {
|
||||
rustc.arg("-Zui-testing");
|
||||
rustc.arg("-Zdeduplicate-diagnostics=no");
|
||||
}
|
||||
Ui => {
|
||||
TestMode::Ui => {
|
||||
if !self.props.compile_flags.iter().any(|s| s.starts_with("--error-format")) {
|
||||
rustc.args(&["--error-format", "json"]);
|
||||
rustc.args(&["--json", "future-incompat"]);
|
||||
@ -1633,7 +1641,7 @@ impl<'test> TestCx<'test> {
|
||||
// FIXME: use this for other modes too, for perf?
|
||||
rustc.arg("-Cstrip=debuginfo");
|
||||
}
|
||||
MirOpt => {
|
||||
TestMode::MirOpt => {
|
||||
// We check passes under test to minimize the mir-opt test dump
|
||||
// if files_for_miropt_test parses the passes, we dump only those passes
|
||||
// otherwise we conservatively pass -Zdump-mir=all
|
||||
@ -1663,7 +1671,7 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
set_mir_dump_dir(&mut rustc);
|
||||
}
|
||||
CoverageMap => {
|
||||
TestMode::CoverageMap => {
|
||||
rustc.arg("-Cinstrument-coverage");
|
||||
// These tests only compile to LLVM IR, so they don't need the
|
||||
// profiler runtime to be present.
|
||||
@ -1673,23 +1681,28 @@ impl<'test> TestCx<'test> {
|
||||
// by `compile-flags`.
|
||||
rustc.arg("-Copt-level=2");
|
||||
}
|
||||
CoverageRun => {
|
||||
TestMode::CoverageRun => {
|
||||
rustc.arg("-Cinstrument-coverage");
|
||||
// Coverage reports are sometimes sensitive to optimizations,
|
||||
// and the current snapshots assume `opt-level=2` unless
|
||||
// overridden by `compile-flags`.
|
||||
rustc.arg("-Copt-level=2");
|
||||
}
|
||||
Assembly | Codegen => {
|
||||
TestMode::Assembly | TestMode::Codegen => {
|
||||
rustc.arg("-Cdebug-assertions=no");
|
||||
}
|
||||
Crashes => {
|
||||
TestMode::Crashes => {
|
||||
set_mir_dump_dir(&mut rustc);
|
||||
}
|
||||
CodegenUnits => {
|
||||
TestMode::CodegenUnits => {
|
||||
rustc.arg("-Zprint-mono-items");
|
||||
}
|
||||
Pretty | DebugInfo | Rustdoc | RustdocJson | RunMake | RustdocJs => {
|
||||
TestMode::Pretty
|
||||
| TestMode::DebugInfo
|
||||
| TestMode::Rustdoc
|
||||
| TestMode::RustdocJson
|
||||
| TestMode::RunMake
|
||||
| TestMode::RustdocJs => {
|
||||
// do not use JSON output
|
||||
}
|
||||
}
|
||||
@ -1962,7 +1975,7 @@ impl<'test> TestCx<'test> {
|
||||
/// The revision, ignored for incremental compilation since it wants all revisions in
|
||||
/// the same directory.
|
||||
fn safe_revision(&self) -> Option<&str> {
|
||||
if self.config.mode == Incremental { None } else { self.revision }
|
||||
if self.config.mode == TestMode::Incremental { None } else { self.revision }
|
||||
}
|
||||
|
||||
/// Gets the absolute path to the directory where all output for the given
|
||||
|
@ -67,11 +67,7 @@ fn is_test_test() {
|
||||
|
||||
#[test]
|
||||
fn string_enums() {
|
||||
// These imports are needed for the macro-generated code
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
crate::common::string_enum! {
|
||||
crate::util::string_enum! {
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
enum Animal {
|
||||
Cat => "meow",
|
||||
|
@ -104,3 +104,42 @@ macro_rules! static_regex {
|
||||
}};
|
||||
}
|
||||
pub(crate) use static_regex;
|
||||
|
||||
macro_rules! string_enum {
|
||||
($(#[$meta:meta])* $vis:vis enum $name:ident { $($variant:ident => $repr:expr,)* }) => {
|
||||
$(#[$meta])*
|
||||
$vis enum $name {
|
||||
$($variant,)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
$vis const VARIANTS: &'static [Self] = &[$(Self::$variant,)*];
|
||||
$vis const STR_VARIANTS: &'static [&'static str] = &[$(Self::$variant.to_str(),)*];
|
||||
|
||||
$vis const fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
$(Self::$variant => $repr,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
::std::fmt::Display::fmt(self.to_str(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::str::FromStr for $name {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
$($repr => Ok(Self::$variant),)*
|
||||
_ => Err(format!(concat!("unknown `", stringify!($name), "` variant: `{}`"), s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) use string_enum;
|
||||
|
@ -112,11 +112,7 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse
|
||||
.current_dir(path);
|
||||
|
||||
if let Some(librs) = find_librs(entry.path()) {
|
||||
let compiletest_c = compiletest::common::Config {
|
||||
edition: None,
|
||||
mode: compiletest::common::Mode::Rustdoc,
|
||||
..Default::default()
|
||||
};
|
||||
let compiletest_c = compiletest::common::Config::incomplete_for_rustdoc_gui_test();
|
||||
|
||||
let test_props = TestProps::from_file(
|
||||
&camino::Utf8PathBuf::try_from(librs).unwrap(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user