From f515af7e3b6070804e8cfc7e31c95e59bb663666 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 12 Jul 2022 11:19:52 +0200 Subject: [PATCH 1/2] Add regex-error-pattern flag in compiletest --- src/tools/compiletest/src/header.rs | 10 ++++ src/tools/compiletest/src/runtest.rs | 75 +++++++++++++++++++++------- 2 files changed, 66 insertions(+), 19 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 21d685861716d..17f2b77dab052 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -60,6 +60,8 @@ impl EarlyProps { pub struct TestProps { // Lines that should be expected, in order, on standard out pub error_patterns: Vec, + // Regexes that should be expected, in order, on standard out + pub regex_error_patterns: Vec, // Extra flags to pass to the compiler pub compile_flags: Vec, // Extra flags to pass when the compiled code is run (such as --bench) @@ -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"; @@ -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, @@ -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())); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index dd9e2a6687e7a..5517b5a12c393 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -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() { @@ -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 { @@ -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, ) { - 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; @@ -1243,13 +1243,8 @@ impl<'test> TestCx<'test> { let mut missing_patterns: Vec = 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; @@ -1268,6 +1263,44 @@ impl<'test> TestCx<'test> { } } + fn check_error_patterns(&self, output_to_check: &str, missing_patterns: &mut Vec) { + 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, + ) { + 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 => { @@ -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"]); } @@ -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); } } @@ -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 { From 349a3fc6a3c251088b58627d043c0cd1ca524640 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 12 Jul 2022 11:20:36 +0200 Subject: [PATCH 2/2] Update -zhelp and -chelp rustdoc-ui tests to use regex-error-pattern --- src/test/rustdoc-ui/c-help.rs | 2 ++ src/test/rustdoc-ui/z-help.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/test/rustdoc-ui/c-help.rs b/src/test/rustdoc-ui/c-help.rs index f63e8b08ecdad..e166edf8b619c 100644 --- a/src/test/rustdoc-ui/c-help.rs +++ b/src/test/rustdoc-ui/c-help.rs @@ -1,4 +1,6 @@ // check-pass // compile-flags: -Chelp +// check-stdout +// regex-error-pattern: -C\s+incremental pub struct Foo; diff --git a/src/test/rustdoc-ui/z-help.rs b/src/test/rustdoc-ui/z-help.rs index 036c68c272b82..c7cf841b93707 100644 --- a/src/test/rustdoc-ui/z-help.rs +++ b/src/test/rustdoc-ui/z-help.rs @@ -1,4 +1,6 @@ // check-pass // compile-flags: -Zhelp +// check-stdout +// regex-error-pattern: -Z\s+self-profile pub struct Foo;