未验证 提交 0721364f 编写于 作者: M Mazdak Farrokhzad 提交者: GitHub

Rollup merge of #61755 - Centril:compiletest-force-check, r=petrochenkov

Add `--pass $mode` to compiletest through `./x.py`

Adds a flag `--pass $mode` to compiletest, which is exposed through `./x.py`.

When `--pass $mode` is passed, `{check,build,compile,run}-pass` tests will be forced to run under the given `$mode` unless the directive `// ignore-pass` exists in the test file.

The modes are explained in https://github.com/rust-lang/rust/pull/61778:
- `check` has the same effect as `cargo check`
- `build` or `compile` have the same effect as `cargo build`
- `run` has the same effect as `cargo run`

On my machine, `./x.py -i test src/test/run-pass --stage 1 --pass check` takes 38 seconds whereas it takes 2 min 7 seconds without `--pass check`.

cc https://github.com/rust-lang/rust/issues/61712

r? @petrochenkov
......@@ -598,6 +598,7 @@ fn test_with_no_doc_stage0() {
bless: false,
compare_mode: None,
rustfix_coverage: false,
pass: None,
};
let build = Build::new(config);
......@@ -640,6 +641,7 @@ fn test_exclude() {
bless: false,
compare_mode: None,
rustfix_coverage: false,
pass: None,
};
let build = Build::new(config);
......
......@@ -58,6 +58,7 @@ pub enum Subcommand {
/// Whether to automatically update stderr/stdout files
bless: bool,
compare_mode: Option<String>,
pass: Option<String>,
test_args: Vec<String>,
rustc_args: Vec<String>,
fail_fast: bool,
......@@ -199,6 +200,12 @@ pub fn parse(args: &[String]) -> Flags {
"mode describing what file the actual ui output will be compared to",
"COMPARE MODE",
);
opts.optopt(
"",
"pass",
"force {check,build,run}-pass tests to this mode.",
"check | build | run"
);
opts.optflag(
"",
"rustfix-coverage",
......@@ -401,6 +408,7 @@ pub fn parse(args: &[String]) -> Flags {
paths,
bless: matches.opt_present("bless"),
compare_mode: matches.opt_str("compare-mode"),
pass: matches.opt_str("pass"),
test_args: matches.opt_strs("test-args"),
rustc_args: matches.opt_strs("rustc-args"),
fail_fast: !matches.opt_present("no-fail-fast"),
......@@ -524,6 +532,15 @@ pub fn compare_mode(&self) -> Option<&str> {
_ => None,
}
}
pub fn pass(&self) -> Option<&str> {
match *self {
Subcommand::Test {
ref pass, ..
} => pass.as_ref().map(|s| &s[..]),
_ => None,
}
}
}
fn split(s: &[String]) -> Vec<String> {
......
......@@ -1065,6 +1065,11 @@ fn run(self, builder: &Builder<'_>) {
}
});
if let Some(ref pass) = builder.config.cmd.pass() {
cmd.arg("--pass");
cmd.arg(pass);
}
if let Some(ref nodejs) = builder.config.nodejs {
cmd.arg("--nodejs").arg(nodejs);
}
......
#![warn(const_err)]
// compile-pass
// compile-flags: -O
#![deny(const_err)]
fn main() {
println!("{}", 0u32 - 1);
let _x = 0u32 - 1;
//~^ WARN const_err
//~^ ERROR this expression will panic at runtime [const_err]
println!("{}", 1/(1-1));
//~^ WARN const_err
//~^ ERROR this expression will panic at runtime [const_err]
//~| ERROR attempt to divide by zero [const_err]
//~| ERROR reaching this expression at runtime will panic or abort [const_err]
let _x = 1/(1-1);
//~^ WARN const_err
//~| WARN const_err
//~^ ERROR const_err
//~| ERROR const_err
println!("{}", 1/(false as u32));
//~^ WARN const_err
//~^ ERROR this expression will panic at runtime [const_err]
//~| ERROR attempt to divide by zero [const_err]
//~| ERROR reaching this expression at runtime will panic or abort [const_err]
let _x = 1/(false as u32);
//~^ WARN const_err
//~| WARN const_err
//~^ ERROR const_err
//~| ERROR const_err
}
warning: this expression will panic at runtime
error: this expression will panic at runtime
--> $DIR/promoted_errors.rs:7:14
|
LL | let _x = 0u32 - 1;
| ^^^^^^^^ attempt to subtract with overflow
|
note: lint level defined here
--> $DIR/promoted_errors.rs:1:9
--> $DIR/promoted_errors.rs:3:9
|
LL | #![warn(const_err)]
LL | #![deny(const_err)]
| ^^^^^^^^^
warning: attempt to divide by zero
error: attempt to divide by zero
--> $DIR/promoted_errors.rs:9:20
|
LL | println!("{}", 1/(1-1));
| ^^^^^^^
warning: this expression will panic at runtime
error: this expression will panic at runtime
--> $DIR/promoted_errors.rs:9:20
|
LL | println!("{}", 1/(1-1));
| ^^^^^^^ attempt to divide by zero
warning: attempt to divide by zero
--> $DIR/promoted_errors.rs:11:14
error: attempt to divide by zero
--> $DIR/promoted_errors.rs:13:14
|
LL | let _x = 1/(1-1);
| ^^^^^^^
warning: this expression will panic at runtime
--> $DIR/promoted_errors.rs:11:14
error: this expression will panic at runtime
--> $DIR/promoted_errors.rs:13:14
|
LL | let _x = 1/(1-1);
| ^^^^^^^ attempt to divide by zero
warning: attempt to divide by zero
--> $DIR/promoted_errors.rs:14:20
error: attempt to divide by zero
--> $DIR/promoted_errors.rs:16:20
|
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^
warning: this expression will panic at runtime
--> $DIR/promoted_errors.rs:14:20
error: this expression will panic at runtime
--> $DIR/promoted_errors.rs:16:20
|
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^ attempt to divide by zero
warning: attempt to divide by zero
--> $DIR/promoted_errors.rs:16:14
error: attempt to divide by zero
--> $DIR/promoted_errors.rs:20:14
|
LL | let _x = 1/(false as u32);
| ^^^^^^^^^^^^^^^^
warning: this expression will panic at runtime
--> $DIR/promoted_errors.rs:16:14
error: this expression will panic at runtime
--> $DIR/promoted_errors.rs:20:14
|
LL | let _x = 1/(false as u32);
| ^^^^^^^^^^^^^^^^ attempt to divide by zero
warning: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:14:20
error: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:16:20
|
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^ attempt to divide by zero
warning: reaching this expression at runtime will panic or abort
error: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:9:20
|
LL | println!("{}", 1/(1-1));
| ^^^^^^^ attempt to divide by zero
error: aborting due to 11 previous errors
// compile-flags:--emit=metadata --error-format=json -Z emit-artifact-notifications
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// A very basic test for the emission of artifact notifications in JSON output.
......
// compile-flags: -O
#![warn(overflowing_literals)]
#![warn(const_err)]
// compile-pass
#[allow(unused_variables)]
#![deny(overflowing_literals)]
#![deny(const_err)]
fn main() {
let x2: i8 = --128; //~ warn: literal out of range for i8
let x2: i8 = --128; //~ ERROR literal out of range for `i8`
let x = -3.40282357e+38_f32; //~ warn: literal out of range for f32
let x = 3.40282357e+38_f32; //~ warn: literal out of range for f32
let x = -1.7976931348623159e+308_f64; //~ warn: literal out of range for f64
let x = 1.7976931348623159e+308_f64; //~ warn: literal out of range for f64
let x = -3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
let x = 3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
let x = -1.7976931348623159e+308_f64; //~ ERROR literal out of range for `f64`
let x = 1.7976931348623159e+308_f64; //~ ERROR literal out of range for `f64`
}
warning: literal out of range for `i8`
--> $DIR/lint-type-overflow2.rs:9:20
error: literal out of range for `i8`
--> $DIR/lint-type-overflow2.rs:7:20
|
LL | let x2: i8 = --128;
| ^^^
|
note: lint level defined here
--> $DIR/lint-type-overflow2.rs:2:9
--> $DIR/lint-type-overflow2.rs:3:9
|
LL | #![warn(overflowing_literals)]
LL | #![deny(overflowing_literals)]
| ^^^^^^^^^^^^^^^^^^^^
warning: literal out of range for `f32`
--> $DIR/lint-type-overflow2.rs:11:14
error: literal out of range for `f32`
--> $DIR/lint-type-overflow2.rs:9:14
|
LL | let x = -3.40282357e+38_f32;
| ^^^^^^^^^^^^^^^^^^
warning: literal out of range for `f32`
--> $DIR/lint-type-overflow2.rs:12:14
error: literal out of range for `f32`
--> $DIR/lint-type-overflow2.rs:10:14
|
LL | let x = 3.40282357e+38_f32;
| ^^^^^^^^^^^^^^^^^^
warning: literal out of range for `f64`
--> $DIR/lint-type-overflow2.rs:13:14
error: literal out of range for `f64`
--> $DIR/lint-type-overflow2.rs:11:14
|
LL | let x = -1.7976931348623159e+308_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: literal out of range for `f64`
--> $DIR/lint-type-overflow2.rs:14:14
error: literal out of range for `f64`
--> $DIR/lint-type-overflow2.rs:12:14
|
LL | let x = 1.7976931348623159e+308_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: this expression will panic at runtime
--> $DIR/lint-type-overflow2.rs:9:18
|
LL | let x2: i8 = --128;
| ^^^^^ attempt to negate with overflow
|
note: lint level defined here
--> $DIR/lint-type-overflow2.rs:3:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^
error: aborting due to 5 previous errors
// compile-flags: -Z print-type-sizes
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// This file illustrates how generics are handled: types have to be
// monomorphized, in the MIR of the original function in which they
......
// compile-flags: -Z print-type-sizes
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// This file illustrates how niche-filling enums are handled,
// modelled after cases like `Option<&u32>`, `Option<bool>` and such.
......
// compile-flags: -Z print-type-sizes
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// This file illustrates that when the same type occurs repeatedly
// (even if multiple functions), it is only printed once in the
......
// compile-flags: -Z print-type-sizes
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// This file illustrates how packing is handled; it should cause
// the elimination of padding that would normally be introduced
......
// compile-flags: -Z print-type-sizes
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// This file illustrates how padding is handled: alignment
// requirements can lead to the introduction of padding, either before
......
// compile-flags: -Z print-type-sizes
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
#![feature(never_type)]
#![feature(start)]
......
// run-pass
// force-host
// no-prefer-dynamic
// ignore-pass
#![crate_type = "proc-macro"]
......
// compile-pass
// compile-flags: -Zsave-analysis -Zemit-artifact-notifications
// compile-flags: --crate-type rlib --error-format=json
// ignore-pass
// ^-- needed because otherwise, the .stderr file changes with --pass check
pub fn foo() {}
......@@ -99,6 +99,36 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
#[derive(Clone, Copy, PartialEq, Debug, Hash)]
pub enum PassMode {
Check,
Build,
Run,
}
impl FromStr for PassMode {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
match s {
"check" => Ok(PassMode::Check),
"build" => Ok(PassMode::Build),
"run" => Ok(PassMode::Run),
_ => Err(()),
}
}
}
impl fmt::Display for PassMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match *self {
PassMode::Check => "check",
PassMode::Build => "build",
PassMode::Run => "run",
};
fmt::Display::fmt(s, f)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum CompareMode {
Nll,
......@@ -184,6 +214,9 @@ pub struct Config {
/// Exactly match the filter, rather than a substring
pub filter_exact: bool,
/// Force the pass mode of a check/build/run-pass test to this mode.
pub force_pass_mode: Option<PassMode>,
/// Write out a parseable log of tests that were run
pub logfile: Option<PathBuf>,
......
......@@ -6,7 +6,7 @@
use log::*;
use crate::common::{self, CompareMode, Config, Mode};
use crate::common::{self, CompareMode, Config, Mode, PassMode};
use crate::util;
use crate::extract_gdb_version;
......@@ -290,13 +290,6 @@ fn ignore_llvm(config: &Config, line: &str) -> bool {
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum PassMode {
Check,
Build,
Run,
}
#[derive(Clone, Debug)]
pub struct TestProps {
// Lines that should be expected, in order, on standard out
......@@ -357,7 +350,9 @@ pub struct TestProps {
// arguments. (In particular, it propagates to the aux-builds.)
pub incremental_dir: Option<PathBuf>,
// How far should the test proceed while still passing.
pub pass_mode: Option<PassMode>,
pass_mode: Option<PassMode>,
// Ignore `--pass` overrides from the command line for this test.
ignore_pass: bool,
// rustdoc will test the output of the `--test` option
pub check_test_line_numbers_match: bool,
// Do not pass `-Z ui-testing` to UI tests
......@@ -400,6 +395,7 @@ pub fn new() -> Self {
forbid_output: vec![],
incremental_dir: None,
pass_mode: None,
ignore_pass: false,
check_test_line_numbers_match: false,
disable_ui_testing_normalization: false,
normalize_stdout: vec![],
......@@ -528,6 +524,10 @@ fn load_from(&mut self, testfile: &Path, cfg: Option<&str>, config: &Config) {
self.update_pass_mode(ln, cfg, config);
if !self.ignore_pass {
self.ignore_pass = config.parse_ignore_pass(ln);
}
if !self.disable_ui_testing_normalization {
self.disable_ui_testing_normalization =
config.parse_disable_ui_testing_normalization(ln);
......@@ -608,6 +608,15 @@ fn update_pass_mode(&mut self, ln: &str, revision: Option<&str>, config: &Config
(_, None) => {}
}
}
pub fn pass_mode(&self, config: &Config) -> Option<PassMode> {
if !self.ignore_pass {
if let (mode @ Some(_), Some(_)) = (config.force_pass_mode, self.pass_mode) {
return mode;
}
}
self.pass_mode
}
}
fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut dyn FnMut(&str)) {
......@@ -743,6 +752,10 @@ fn parse_check_test_line_numbers_match(&self, line: &str) -> bool {
self.parse_name_directive(line, "check-test-line-numbers-match")
}
fn parse_ignore_pass(&self, line: &str) -> bool {
self.parse_name_directive(line, "ignore-pass")
}
fn parse_assembly_output(&self, line: &str) -> Option<String> {
self.parse_name_value_directive(line, "assembly-output")
.map(|r| r.trim().to_string())
......
......@@ -5,7 +5,7 @@
extern crate test;
use crate::common::CompareMode;
use crate::common::{CompareMode, PassMode};
use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
use crate::common::{Config, TestPaths};
use crate::common::{DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb, Mode, Pretty};
......@@ -128,6 +128,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
"(compile-fail|run-fail|run-pass|\
run-pass-valgrind|pretty|debug-info|incremental|mir-opt)",
)
.optopt(
"",
"pass",
"force {check,build,run}-pass tests to this mode.",
"check | build | run"
)
.optflag("", "ignored", "run tests marked as ignored")
.optflag("", "exact", "filters match exactly")
.optopt(
......@@ -320,6 +326,10 @@ fn make_absolute(path: PathBuf) -> PathBuf {
run_ignored,
filter: matches.free.first().cloned(),
filter_exact: matches.opt_present("exact"),
force_pass_mode: matches.opt_str("pass").map(|mode|
mode.parse::<PassMode>()
.unwrap_or_else(|_| panic!("unknown `--pass` option `{}` given", mode))
),
logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
runtool: matches.opt_str("runtool"),
host_rustcflags: matches.opt_str("host-rustcflags"),
......@@ -382,6 +392,10 @@ pub fn log_config(config: &Config) {
),
);
logv(c, format!("filter_exact: {}", config.filter_exact));
logv(c, format!(
"force_pass_mode: {}",
opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),
));
logv(c, format!("runtool: {}", opt_str(&config.runtool)));
logv(
c,
......
// ignore-tidy-filelength
use crate::common::CompareMode;
use crate::common::{CompareMode, PassMode};
use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT};
use crate::common::{output_base_dir, output_base_name, output_testname_unique};
use crate::common::{Codegen, CodegenUnits, Rustdoc};
......@@ -10,7 +10,7 @@
use crate::common::{Incremental, MirOpt, RunMake, Ui, JsDocTest, Assembly};
use diff;
use crate::errors::{self, Error, ErrorKind};
use crate::header::{TestProps, PassMode};
use crate::header::TestProps;
use crate::json;
use regex::{Captures, Regex};
use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
......@@ -260,6 +260,10 @@ pub fn compute_stamp_hash(config: &Config) -> String {
env::var_os("PYTHONPATH").hash(&mut hash);
}
if let Ui | RunPass | Incremental | Pretty = config.mode {
config.force_pass_mode.hash(&mut hash);
}
format!("{:x}", hash.finish())
}
......@@ -309,10 +313,13 @@ fn run_revision(&self) {
}
}
fn pass_mode(&self) -> Option<PassMode> {
self.props.pass_mode(self.config)
}
fn should_run_successfully(&self) -> bool {
match self.config.mode {
RunPass => true,
Ui => self.props.pass_mode == Some(PassMode::Run),
RunPass | Ui => self.pass_mode() == Some(PassMode::Run),
mode => panic!("unimplemented for mode {:?}", mode),
}
}
......@@ -322,7 +329,7 @@ fn should_compile_successfully(&self) -> bool {
CompileFail => false,
RunPass => true,
JsDocTest => true,
Ui => self.props.pass_mode.is_some(),
Ui => self.pass_mode().is_some(),
Incremental => {
let revision = self.revision
.expect("incremental tests require a list of revisions");
......@@ -330,7 +337,7 @@ fn should_compile_successfully(&self) -> bool {
true
} else if revision.starts_with("cfail") {
// FIXME: would be nice if incremental revs could start with "cpass"
self.props.pass_mode.is_some()
self.pass_mode().is_some()
} else {
panic!("revision name must begin with rpass, rfail, or cfail");
}
......@@ -1341,7 +1348,7 @@ fn check_single_line(line: &str, check_line: &str) -> bool {
fn check_error_patterns(&self, output_to_check: &str, proc_res: &ProcRes) {
debug!("check_error_patterns");
if self.props.error_patterns.is_empty() {
if self.props.pass_mode.is_some() {
if self.pass_mode().is_some() {
return;
} else {
self.fatal(&format!(
......@@ -1871,7 +1878,11 @@ fn compose_and_run(
result
}
fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command {
fn make_compile_args(
&self,
input_file: &Path,
output_file: TargetLocation,
) -> Command {
let is_rustdoc = self.config.src_base.ends_with("rustdoc-ui") ||
self.config.src_base.ends_with("rustdoc-js");
let mut rustc = if !is_rustdoc {
......@@ -1968,14 +1979,7 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C
}
}
if self.props.pass_mode == Some(PassMode::Check) {
assert!(
!self
.props
.compile_flags
.iter()
.any(|s| s.starts_with("--emit"))
);
if let Some(PassMode::Check) = self.pass_mode() {
rustc.args(&["--emit", "metadata"]);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册