Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

coverage: Anonymize line numbers in branch views #119681

Merged
merged 1 commit into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -725,17 +724,36 @@ 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`.)
// A pipe character `|` appears immediately after the final digit.
//
// 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
Expand Down
72 changes: 72 additions & 0 deletions src/tools/compiletest/src/runtest/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Loading