about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-01-09 00:19:35 +0100
committerGitHub <noreply@github.com>2024-01-09 00:19:35 +0100
commit867a87d3420324eb41ca88ce25f4e372b70672ed (patch)
treee60933e50cf81939617cc8bcbba558822834205c
parente6bc9f063782e54480907e6893b3097943343cdb (diff)
parent957a46fa69db5a67fad317305213b51d27e9df6e (diff)
downloadrust-867a87d3420324eb41ca88ce25f4e372b70672ed.tar.gz
rust-867a87d3420324eb41ca88ce25f4e372b70672ed.zip
Rollup merge of #119681 - Zalathar:anon-branch, r=clubby789
coverage: Anonymize line numbers in branch views

Extracted from #118305, as this is now the only part of that PR that needs to touch compiletest.

---

Coverage tests run the `llvm-cov` tool to generate a coverage report for a test program, and then compare the report against a known-good snapshot.

We use the `anonymize_coverage_line_numbers` function to replace line numbers in coverage reports with `LL`, so that they are less sensitive to lines being added or removed. This PR augments the existing code by making it also support the slightly different line number syntax used when reporting branch regions.

Currently the compiler never emits branch regions, so there is no way to write a coverage test that makes use of this new capability. Instead, I've added a unit test that checks against some sample reports taken from #118305. That unit test can be removed when some form of branch coverage support gets merged, and real branch coverage tests are added to the coverage test suite.

(I have also manually tested this change as part of my draft branch-coverage PR.)
-rw-r--r--src/tools/compiletest/src/runtest.rs24
-rw-r--r--src/tools/compiletest/src/runtest/tests.rs72
2 files changed, 93 insertions, 3 deletions
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 miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
 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 @@ impl<'test> TestCx<'test> {
 
     /// 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 @@ impl<'test> TestCx<'test> {
         //
         // 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<Regex> =
             Lazy::new(|| Regex::new(r"(?m:^)(?<prefix>(?:  \|)*) *[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<Regex> =
+            Lazy::new(|| Regex::new(r"(?m:^)(?<prefix>(?:  \|)+  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<T>() {
+    7|      3|    if std::mem::size_of::<T>() > 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<T>() {
+   LL|      3|    if std::mem::size_of::<T>() > 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<T>() {
+  |    7|      1|    if std::mem::size_of::<T>() > 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<T>() {
+  |   LL|      1|    if std::mem::size_of::<T>() > 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);
+}