Skip to content

Put back UI test regex #99171

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/test/rustdoc-ui/c-help.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// check-pass
// compile-flags: -Chelp
// check-stdout
// regex-error-pattern: -C\s+incremental

pub struct Foo;
2 changes: 2 additions & 0 deletions src/test/rustdoc-ui/z-help.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// check-pass
// compile-flags: -Zhelp
// check-stdout
// regex-error-pattern: -Z\s+self-profile

pub struct Foo;
10 changes: 10 additions & 0 deletions src/tools/compiletest/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ impl EarlyProps {
pub struct TestProps {
// Lines that should be expected, in order, on standard out
pub error_patterns: Vec<String>,
// Regexes that should be expected, in order, on standard out
pub regex_error_patterns: Vec<String>,
// Extra flags to pass to the compiler
pub compile_flags: Vec<String>,
// Extra flags to pass when the compiled code is run (such as --bench)
Expand Down Expand Up @@ -163,6 +165,7 @@ pub struct TestProps {

mod directives {
pub const ERROR_PATTERN: &'static str = "error-pattern";
pub const REGEX_ERROR_PATTERN: &'static str = "regex-error-pattern";
pub const COMPILE_FLAGS: &'static str = "compile-flags";
pub const RUN_FLAGS: &'static str = "run-flags";
pub const SHOULD_ICE: &'static str = "should-ice";
Expand Down Expand Up @@ -200,6 +203,7 @@ impl TestProps {
pub fn new() -> Self {
TestProps {
error_patterns: vec![],
regex_error_patterns: vec![],
compile_flags: vec![],
run_flags: None,
pp_exact: None,
Expand Down Expand Up @@ -285,6 +289,12 @@ impl TestProps {
&mut self.error_patterns,
|r| r,
);
config.push_name_value_directive(
ln,
REGEX_ERROR_PATTERN,
&mut self.regex_error_patterns,
|r| r,
);

if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
self.compile_flags.extend(flags.split_whitespace().map(|s| s.to_owned()));
Expand Down
75 changes: 56 additions & 19 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,13 @@ impl<'test> TestCx<'test> {
let output_to_check = self.get_output(&proc_res);
let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
if !expected_errors.is_empty() {
if !self.props.error_patterns.is_empty() {
if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
{
self.fatal("both error pattern and expected errors specified");
}
self.check_expected_errors(expected_errors, &proc_res);
} else {
self.check_error_patterns(&output_to_check, &proc_res, pm);
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
}
if self.props.should_ice {
match proc_res.status.code() {
Expand Down Expand Up @@ -363,7 +364,7 @@ impl<'test> TestCx<'test> {

let output_to_check = self.get_output(&proc_res);
self.check_correct_failure_status(&proc_res);
self.check_error_patterns(&output_to_check, &proc_res, pm);
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
}

fn get_output(&self, proc_res: &ProcRes) -> String {
Expand Down Expand Up @@ -1222,14 +1223,13 @@ impl<'test> TestCx<'test> {
}
}

fn check_error_patterns(
fn check_all_error_patterns(
&self,
output_to_check: &str,
proc_res: &ProcRes,
pm: Option<PassMode>,
) {
debug!("check_error_patterns");
if self.props.error_patterns.is_empty() {
if self.props.error_patterns.is_empty() && self.props.regex_error_patterns.is_empty() {
if pm.is_some() {
// FIXME(#65865)
return;
Expand All @@ -1243,13 +1243,8 @@ impl<'test> TestCx<'test> {

let mut missing_patterns: Vec<String> = Vec::new();

for pattern in &self.props.error_patterns {
if output_to_check.contains(pattern.trim()) {
debug!("found error pattern {}", pattern);
} else {
missing_patterns.push(pattern.to_string());
}
}
self.check_error_patterns(output_to_check, &mut missing_patterns);
self.check_regex_error_patterns(output_to_check, proc_res, &mut missing_patterns);

if missing_patterns.is_empty() {
return;
Expand All @@ -1268,6 +1263,44 @@ impl<'test> TestCx<'test> {
}
}

fn check_error_patterns(&self, output_to_check: &str, missing_patterns: &mut Vec<String>) {
debug!("check_error_patterns");
for pattern in &self.props.error_patterns {
if output_to_check.contains(pattern.trim()) {
debug!("found error pattern {}", pattern);
} else {
missing_patterns.push(pattern.to_string());
}
}
}

fn check_regex_error_patterns(
&self,
output_to_check: &str,
proc_res: &ProcRes,
missing_patterns: &mut Vec<String>,
) {
debug!("check_regex_error_patterns");

for pattern in &self.props.regex_error_patterns {
let pattern = pattern.trim();
let re = match Regex::new(pattern) {
Ok(re) => re,
Err(err) => {
self.fatal_proc_rec(
&format!("invalid regex error pattern '{}': {:?}", pattern, err),
proc_res,
);
}
};
if re.is_match(output_to_check) {
debug!("found regex error pattern {}", pattern);
} else {
missing_patterns.push(pattern.to_string());
}
}
}

fn check_no_compiler_crash(&self, proc_res: &ProcRes, should_ice: bool) {
match proc_res.status.code() {
Some(101) if !should_ice => {
Expand Down Expand Up @@ -1892,7 +1925,9 @@ impl<'test> TestCx<'test> {
// 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.
if self.props.error_patterns.is_empty() {
if self.props.error_patterns.is_empty()
&& self.props.regex_error_patterns.is_empty()
{
rustc.args(&["--error-format", "json"]);
rustc.args(&["--json", "future-incompat"]);
}
Expand Down Expand Up @@ -3268,10 +3303,11 @@ impl<'test> TestCx<'test> {
self.fatal_proc_rec("test run succeeded!", &proc_res);
}

if !self.props.error_patterns.is_empty() {
if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
{
// "// error-pattern" comments
let output_to_check = self.get_output(&proc_res);
self.check_error_patterns(&output_to_check, &proc_res, pm);
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
}
}

Expand All @@ -3285,15 +3321,16 @@ impl<'test> TestCx<'test> {
self.props.error_patterns
);
if !explicit && self.config.compare_mode.is_none() {
let check_patterns =
should_run == WillExecute::No && !self.props.error_patterns.is_empty();
let check_patterns = should_run == WillExecute::No
&& (!self.props.error_patterns.is_empty()
|| !self.props.regex_error_patterns.is_empty());

let check_annotations = !check_patterns || !expected_errors.is_empty();

if check_patterns {
// "// error-pattern" comments
let output_to_check = self.get_output(&proc_res);
self.check_error_patterns(&output_to_check, &proc_res, pm);
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
}

if check_annotations {
Expand Down