Skip to content

Commit 91fced8

Browse files
Add regex-error-pattern ui check
1 parent 415028d commit 91fced8

File tree

2 files changed

+67
-20
lines changed

2 files changed

+67
-20
lines changed

src/tools/compiletest/src/header.rs

+11
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ impl EarlyProps {
6060
pub struct TestProps {
6161
// Lines that should be expected, in order, on standard out
6262
pub error_patterns: Vec<String>,
63+
// Regexes that should be expected, in order, on standard out
64+
pub regex_error_patterns: Vec<String>,
6365
// Extra flags to pass to the compiler
6466
pub compile_flags: Vec<String>,
6567
// Extra flags to pass when the compiled code is run (such as --bench)
@@ -163,6 +165,7 @@ pub struct TestProps {
163165

164166
mod directives {
165167
pub const ERROR_PATTERN: &'static str = "error-pattern";
168+
pub const REGEX_ERROR_PATTERN: &'static str = "regex-error-pattern";
166169
pub const COMPILE_FLAGS: &'static str = "compile-flags";
167170
pub const RUN_FLAGS: &'static str = "run-flags";
168171
pub const SHOULD_ICE: &'static str = "should-ice";
@@ -200,6 +203,7 @@ impl TestProps {
200203
pub fn new() -> Self {
201204
TestProps {
202205
error_patterns: vec![],
206+
regex_error_patterns: vec![],
203207
compile_flags: vec![],
204208
run_flags: None,
205209
pp_exact: None,
@@ -286,6 +290,13 @@ impl TestProps {
286290
|r| r,
287291
);
288292

293+
config.push_name_value_directive(
294+
ln,
295+
REGEX_ERROR_PATTERN,
296+
&mut self.regex_error_patterns,
297+
|r| r,
298+
);
299+
289300
if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
290301
self.compile_flags.extend(flags.split_whitespace().map(|s| s.to_owned()));
291302
}

src/tools/compiletest/src/runtest.rs

+56-20
Original file line numberDiff line numberDiff line change
@@ -323,12 +323,13 @@ impl<'test> TestCx<'test> {
323323
let output_to_check = self.get_output(&proc_res);
324324
let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
325325
if !expected_errors.is_empty() {
326-
if !self.props.error_patterns.is_empty() {
326+
if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
327+
{
327328
self.fatal("both error pattern and expected errors specified");
328329
}
329330
self.check_expected_errors(expected_errors, &proc_res);
330331
} else {
331-
self.check_error_patterns(&output_to_check, &proc_res, pm);
332+
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
332333
}
333334
if self.props.should_ice {
334335
match proc_res.status.code() {
@@ -363,7 +364,7 @@ impl<'test> TestCx<'test> {
363364

364365
let output_to_check = self.get_output(&proc_res);
365366
self.check_correct_failure_status(&proc_res);
366-
self.check_error_patterns(&output_to_check, &proc_res, pm);
367+
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
367368
}
368369

369370
fn get_output(&self, proc_res: &ProcRes) -> String {
@@ -1222,14 +1223,13 @@ impl<'test> TestCx<'test> {
12221223
}
12231224
}
12241225

1225-
fn check_error_patterns(
1226+
fn check_all_error_patterns(
12261227
&self,
12271228
output_to_check: &str,
12281229
proc_res: &ProcRes,
12291230
pm: Option<PassMode>,
12301231
) {
1231-
debug!("check_error_patterns");
1232-
if self.props.error_patterns.is_empty() {
1232+
if self.props.error_patterns.is_empty() && self.props.regex_error_patterns.is_empty() {
12331233
if pm.is_some() {
12341234
// FIXME(#65865)
12351235
return;
@@ -1240,16 +1240,10 @@ impl<'test> TestCx<'test> {
12401240
));
12411241
}
12421242
}
1243-
12441243
let mut missing_patterns: Vec<String> = Vec::new();
12451244

1246-
for pattern in &self.props.error_patterns {
1247-
if output_to_check.contains(pattern.trim()) {
1248-
debug!("found error pattern {}", pattern);
1249-
} else {
1250-
missing_patterns.push(pattern.to_string());
1251-
}
1252-
}
1245+
self.check_error_patterns(output_to_check, &mut missing_patterns);
1246+
self.check_regex_error_patterns(output_to_check, proc_res, &mut missing_patterns);
12531247

12541248
if missing_patterns.is_empty() {
12551249
return;
@@ -1268,6 +1262,44 @@ impl<'test> TestCx<'test> {
12681262
}
12691263
}
12701264

1265+
fn check_error_patterns(&self, output_to_check: &str, missing_patterns: &mut Vec<String>) {
1266+
debug!("check_error_patterns");
1267+
for pattern in &self.props.error_patterns {
1268+
if output_to_check.contains(pattern.trim()) {
1269+
debug!("found error pattern {}", pattern);
1270+
} else {
1271+
missing_patterns.push(pattern.to_string());
1272+
}
1273+
}
1274+
}
1275+
1276+
fn check_regex_error_patterns(
1277+
&self,
1278+
output_to_check: &str,
1279+
proc_res: &ProcRes,
1280+
missing_patterns: &mut Vec<String>,
1281+
) {
1282+
debug!("check_regex_error_patterns");
1283+
1284+
for pattern in &self.props.regex_error_patterns {
1285+
let pattern = pattern.trim();
1286+
let re = match Regex::new(pattern) {
1287+
Ok(re) => re,
1288+
Err(err) => {
1289+
self.fatal_proc_rec(
1290+
&format!("invalid regex error pattern '{}': {:?}", pattern, err),
1291+
proc_res,
1292+
);
1293+
}
1294+
};
1295+
if re.is_match(output_to_check) {
1296+
debug!("found regex error pattern {}", pattern);
1297+
} else {
1298+
missing_patterns.push(pattern.to_string());
1299+
}
1300+
}
1301+
}
1302+
12711303
fn check_no_compiler_crash(&self, proc_res: &ProcRes, should_ice: bool) {
12721304
match proc_res.status.code() {
12731305
Some(101) if !should_ice => {
@@ -1892,7 +1924,9 @@ impl<'test> TestCx<'test> {
18921924
// If we are extracting and matching errors in the new
18931925
// fashion, then you want JSON mode. Old-skool error
18941926
// patterns still match the raw compiler output.
1895-
if self.props.error_patterns.is_empty() {
1927+
if self.props.error_patterns.is_empty()
1928+
&& self.props.regex_error_patterns.is_empty()
1929+
{
18961930
rustc.args(&["--error-format", "json"]);
18971931
rustc.args(&["--json", "future-incompat"]);
18981932
}
@@ -3268,10 +3302,11 @@ impl<'test> TestCx<'test> {
32683302
self.fatal_proc_rec("test run succeeded!", &proc_res);
32693303
}
32703304

3271-
if !self.props.error_patterns.is_empty() {
3305+
if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
3306+
{
32723307
// "// error-pattern" comments
32733308
let output_to_check = self.get_output(&proc_res);
3274-
self.check_error_patterns(&output_to_check, &proc_res, pm);
3309+
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
32753310
}
32763311
}
32773312

@@ -3285,15 +3320,16 @@ impl<'test> TestCx<'test> {
32853320
self.props.error_patterns
32863321
);
32873322
if !explicit && self.config.compare_mode.is_none() {
3288-
let check_patterns =
3289-
should_run == WillExecute::No && !self.props.error_patterns.is_empty();
3323+
let check_patterns = should_run == WillExecute::No
3324+
&& (!self.props.error_patterns.is_empty()
3325+
|| !self.props.regex_error_patterns.is_empty());
32903326

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

32933329
if check_patterns {
32943330
// "// error-pattern" comments
32953331
let output_to_check = self.get_output(&proc_res);
3296-
self.check_error_patterns(&output_to_check, &proc_res, pm);
3332+
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
32973333
}
32983334

32993335
if check_annotations {

0 commit comments

Comments
 (0)