From aeb91e892b3af7b8a47b7a78e734cc41d1ef5738 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 31 May 2022 08:37:45 +0000 Subject: [PATCH] Make sure we don't allow the same message to be matched twice --- ui_test/src/lib.rs | 78 +++++++++++++++++++++++++------------------- ui_test/src/tests.rs | 46 ++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 34 deletions(-) diff --git a/ui_test/src/lib.rs b/ui_test/src/lib.rs index 507b0a8f29..569c99aa67 100644 --- a/ui_test/src/lib.rs +++ b/ui_test/src/lib.rs @@ -299,7 +299,7 @@ fn check_test_result( } fn check_annotations( - diagnostics: Diagnostics, + mut diagnostics: Diagnostics, errors: &mut Errors, config: &Config, revision: &str, @@ -307,13 +307,33 @@ fn check_annotations( ) { let mut found_annotation = false; if let Some((ref error_pattern, definition_line)) = comments.error_pattern { - if !diagnostics - .messages + let mut found = false; + + // first check the diagnostics messages outside of our file. We check this first, so that + // you can mix in-file annotations with // error-pattern annotations, even if there is overlap + // in the messages. + if let Some(i) = diagnostics + .messages_from_unknown_file_or_line .iter() - .flatten() - .chain(&diagnostics.messages_from_unknown_file_or_line) - .any(|msg| msg.message.contains(error_pattern)) + .position(|msg| msg.message.contains(error_pattern)) { + diagnostics.messages_from_unknown_file_or_line.remove(i); + found = true; + } + + // if nothing was found, check the ones inside our file. We permit this because some tests may have + // flaky line numbers for their messages. + if !found { + for line in &mut diagnostics.messages { + if let Some(i) = line.iter().position(|msg| msg.message.contains(error_pattern)) { + line.remove(i); + found = true; + break; + } + } + } + + if !found { errors.push(Error::PatternNotFound { stderr: diagnostics.rendered.to_string(), pattern: error_pattern.to_string(), @@ -322,13 +342,8 @@ fn check_annotations( } found_annotation = true; } - 'pattern: for &ErrorMatch { - ref matched, - revision: ref rev, - definition_line, - line, - ref level, - } in &comments.error_matches + for &ErrorMatch { ref matched, revision: ref rev, definition_line, line, ref level } in + &comments.error_matches { if let Some(rev) = rev { if rev != revision { @@ -338,27 +353,22 @@ fn check_annotations( found_annotation = true; - if let Some(msgs) = diagnostics.messages.get(line) { - for msg in msgs { - if !msg.message.contains(matched) { - continue; - } - if let Some(level) = &level { - match &msg.level.to_uppercase()[..] { - // Special case: `warning` level in json can be matched by - // `WARN` annotation. - "WARNING" => - if level != "WARN" { - continue; - }, - lvl => - if lvl != level { - continue; - }, - } - } - // Actually a match for the expression we looked for, go to the next pattern - continue 'pattern; + if let Some(msgs) = diagnostics.messages.get_mut(line) { + let found = msgs.iter().position(|msg| { + msg.message.contains(matched) + // in case there is no level on the annotation, match any level. + && level.as_ref().map_or(true, |level| { + match &msg.level.to_uppercase()[..] { + // Special case: `warning` level in json can be matched by + // `WARN` annotation. + "WARNING" => level == "WARN", + lvl => level == lvl, + } + }) + }); + if let Some(found) = found { + msgs.remove(found); + continue; } } diff --git a/ui_test/src/tests.rs b/ui_test/src/tests.rs index 522e02e7b6..4518412a06 100644 --- a/ui_test/src/tests.rs +++ b/ui_test/src/tests.rs @@ -148,3 +148,49 @@ error: aborting due to previous error } } } + +#[test] +fn duplicate_pattern() { + let s = r" +use std::mem; + +fn main() { + let _x: &i32 = unsafe { mem::transmute(16usize) }; //~ ERROR encountered a dangling reference (address 0x10 is unallocated) + //~^ ERROR encountered a dangling reference (address 0x10 is unallocated) +} + "; + let comments = Comments::parse(Path::new(""), s); + let config = config(); + let unnormalized_stderr = r" +error: Undefined Behavior: type validation failed: encountered a dangling reference (address 0x10 is unallocated) + --> tests/compile-fail/validity/dangling_ref1.rs:6:29 + | +LL | let _x: &i32 = unsafe { mem::transmute(16usize) }; //~ ERROR encountered a dangling reference (address 0x10 is unallocated) + | ^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (address 0x10 is unallocated) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + + = note: inside `main` at tests/compile-fail/validity/dangling_ref1.rs:6:29 +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace +error: aborting due to previous error + "; + { + let diagnostics = Diagnostics { + rendered: unnormalized_stderr.to_string(), + messages_from_unknown_file_or_line: vec![], + messages: vec![vec![], vec![], vec![], vec![], vec![], vec![ + Message { + message: "Undefined Behavior: type validation failed: encountered a dangling reference (address 0x10 is unallocated)".to_string(), + level: "ERROR".to_string(), + } + ]] + }; + let mut errors = vec![]; + check_annotations(diagnostics, &mut errors, &config, "", &comments); + match &errors[..] { + [Error::PatternNotFound { definition_line: 6, .. }] => {} + _ => panic!("{:#?}", errors), + } + } +}