diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index b258b748ca8..8be4def15de 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -19,7 +19,6 @@ use regex::{Captures, Regex}; use rustfix::{apply_suggestions, get_suggestions_from_json, Filter}; -use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::env; use std::ffi::{OsStr, OsString}; @@ -725,7 +724,7 @@ fn normalize_coverage_output(&self, coverage: &str) -> Result { /// Replace line numbers in coverage reports with the placeholder `LL`, /// so that the tests are less sensitive to lines being added/removed. - fn anonymize_coverage_line_numbers(coverage: &str) -> Cow<'_, str> { + fn anonymize_coverage_line_numbers(coverage: &str) -> String { // The coverage reporter prints line numbers at the start of a line. // They are truncated or left-padded to occupy exactly 5 columns. // (`LineNumberColumnWidth` in `SourceCoverageViewText.cpp`.) @@ -733,9 +732,28 @@ fn anonymize_coverage_line_numbers(coverage: &str) -> Cow<'_, str> { // // Line numbers that appear inside expansion/instantiation subviews // have an additional prefix of ` |` for each nesting level. + // + // Branch views also include the relevant line number, so we want to + // redact those too. (These line numbers don't have padding.) + // + // Note: The pattern `(?m:^)` matches the start of a line. + + // ` 1|` => ` LL|` + // ` 10|` => ` LL|` + // ` 100|` => ` LL|` + // ` | 1000|` => ` | LL|` + // ` | | 1000|` => ` | | LL|` static LINE_NUMBER_RE: Lazy = Lazy::new(|| Regex::new(r"(?m:^)(?(?: \|)*) *[0-9]+\|").unwrap()); - LINE_NUMBER_RE.replace_all(coverage, "$prefix LL|") + let coverage = LINE_NUMBER_RE.replace_all(&coverage, "${prefix} LL|"); + + // ` | Branch (1:` => ` | Branch (LL:` + // ` | | Branch (10:` => ` | | Branch (LL:` + static BRANCH_LINE_NUMBER_RE: Lazy = + Lazy::new(|| Regex::new(r"(?m:^)(?(?: \|)+ Branch \()[0-9]+:").unwrap()); + let coverage = BRANCH_LINE_NUMBER_RE.replace_all(&coverage, "${prefix}LL:"); + + coverage.into_owned() } /// Coverage reports can describe multiple source files, separated by diff --git a/src/tools/compiletest/src/runtest/tests.rs b/src/tools/compiletest/src/runtest/tests.rs index fb3dd326a4c..ee42243e83d 100644 --- a/src/tools/compiletest/src/runtest/tests.rs +++ b/src/tools/compiletest/src/runtest/tests.rs @@ -48,3 +48,75 @@ fn normalize_platform_differences() { r#"println!("test\ntest")"#, ); } + +/// Test for anonymizing line numbers in coverage reports, especially for +/// branch regions. +/// +/// FIXME(#119681): This test can be removed when we have examples of branch +/// coverage in the actual coverage test suite. +#[test] +fn anonymize_coverage_line_numbers() { + let anon = |coverage| TestCx::anonymize_coverage_line_numbers(coverage); + + let input = r#" + 6| 3|fn print_size() { + 7| 3| if std::mem::size_of::() > 4 { + ------------------ + | Branch (7:8): [True: 0, False: 1] + | Branch (7:8): [True: 0, False: 1] + | Branch (7:8): [True: 1, False: 0] + ------------------ + 8| 1| println!("size > 4"); +"#; + + let expected = r#" + LL| 3|fn print_size() { + LL| 3| if std::mem::size_of::() > 4 { + ------------------ + | Branch (LL:8): [True: 0, False: 1] + | Branch (LL:8): [True: 0, False: 1] + | Branch (LL:8): [True: 1, False: 0] + ------------------ + LL| 1| println!("size > 4"); +"#; + + assert_eq!(anon(input), expected); + + ////////// + + let input = r#" + 12| 3|} + ------------------ + | branch_generics::print_size::<()>: + | 6| 1|fn print_size() { + | 7| 1| if std::mem::size_of::() > 4 { + | ------------------ + | | Branch (7:8): [True: 0, False: 1] + | ------------------ + | 8| 0| println!("size > 4"); + | 9| 1| } else { + | 10| 1| println!("size <= 4"); + | 11| 1| } + | 12| 1|} + ------------------ +"#; + + let expected = r#" + LL| 3|} + ------------------ + | branch_generics::print_size::<()>: + | LL| 1|fn print_size() { + | LL| 1| if std::mem::size_of::() > 4 { + | ------------------ + | | Branch (LL:8): [True: 0, False: 1] + | ------------------ + | LL| 0| println!("size > 4"); + | LL| 1| } else { + | LL| 1| println!("size <= 4"); + | LL| 1| } + | LL| 1|} + ------------------ +"#; + + assert_eq!(anon(input), expected); +}