Skip to content

Commit

Permalink
coverage: Copy all remaining run-coverage tests into coverage-map
Browse files Browse the repository at this point in the history
These multi-file tests were not copied over in rust-lang#114843 because they weren't
working, but it turns out that they just need the correct crate-type.
  • Loading branch information
Zalathar committed Nov 2, 2023
1 parent 0d2c5c5 commit bbe6d66
Show file tree
Hide file tree
Showing 13 changed files with 392 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2193,7 +2193,7 @@ impl<'test> TestCx<'test> {
|| self.is_vxworks_pure_static()
|| self.config.target.contains("bpf")
|| !self.config.target_cfg().dynamic_linking
|| self.config.mode == RunCoverage
|| matches!(self.config.mode, CoverageMap | RunCoverage)
{
// We primarily compile all auxiliary libraries as dynamic libraries
// to avoid code size bloat and large binaries as much as possible
Expand Down
22 changes: 22 additions & 0 deletions tests/coverage-map/auxiliary/inline_always_with_dead_code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0

#![allow(dead_code)]

mod foo {
#[inline(always)]
pub fn called() {}

fn uncalled() {}
}

pub mod bar {
pub fn call_me() {
super::foo::called();
}
}

pub mod baz {
pub fn call_me() {
super::foo::called();
}
}
4 changes: 4 additions & 0 deletions tests/coverage-map/auxiliary/unused_mod_helper.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#[allow(dead_code)]
pub fn never_called_function() {
println!("I am never called");
}
103 changes: 103 additions & 0 deletions tests/coverage-map/auxiliary/used_crate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#![allow(unused_assignments, unused_variables)]
// Verify that coverage works with optimizations:
// compile-flags: -C opt-level=3

use std::fmt::Debug;

pub fn used_function() {
// Initialize test constants in a way that cannot be determined at compile time, to ensure
// rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
// dependent conditions.
let is_true = std::env::args().len() == 1;
let mut countdown = 0;
if is_true {
countdown = 10;
}
use_this_lib_crate();
}

pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
println!("used_only_from_bin_crate_generic_function with {:?}", arg);
}
// Expect for above function: `Unexecuted instantiation` (see below)
pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
}

pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
}

pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
}

pub fn unused_generic_function<T: Debug>(arg: T) {
println!("unused_generic_function with {:?}", arg);
}

pub fn unused_function() {
let is_true = std::env::args().len() == 1;
let mut countdown = 2;
if !is_true {
countdown = 20;
}
}

#[allow(dead_code)]
fn unused_private_function() {
let is_true = std::env::args().len() == 1;
let mut countdown = 2;
if !is_true {
countdown = 20;
}
}

fn use_this_lib_crate() {
used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
"used from library used_crate.rs",
);
let some_vec = vec![5, 6, 7, 8];
used_only_from_this_lib_crate_generic_function(some_vec);
used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
}

// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results,
// for example:
//
// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
//
// These notices appear when `llvm-cov` shows instantiations. This may be a
// default option, but it can be suppressed with:
//
// ```shell
// $ `llvm-cov show --show-instantiations=0 ...`
// ```
//
// The notice is triggered because the function is unused by the library itself,
// and when the library is compiled, a synthetic function is generated, so
// unused function coverage can be reported. Coverage can be skipped for unused
// generic functions with:
//
// ```shell
// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...`
// ```
//
// Even though this function is used by `uses_crate.rs` (and
// counted), with substitutions for `T`, those instantiations are only generated
// when the generic function is actually used (from the binary, not from this
// library crate). So the test result shows coverage for all instantiated
// versions and their generic type substitutions, plus the `Unexecuted
// instantiation` message for the non-substituted version. This is valid, but
// unfortunately a little confusing.
//
// The library crate has its own coverage map, and the only way to show unused
// coverage of a generic function is to include the generic function in the
// coverage map, marked as an "unused function". If the library were used by
// another binary that never used this generic function, then it would be valid
// to show the unused generic, with unknown substitution (`_`).
//
// The alternative is to exclude all generics from being included in the "unused
// functions" list, which would then omit coverage results for
// `unused_generic_function<T>()`, below.
85 changes: 85 additions & 0 deletions tests/coverage-map/auxiliary/used_inline_crate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#![allow(unused_assignments, unused_variables)]
// Verify that coverage works with optimizations:
// compile-flags: -C opt-level=3

use std::fmt::Debug;

pub fn used_function() {
// Initialize test constants in a way that cannot be determined at compile time, to ensure
// rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
// dependent conditions.
let is_true = std::env::args().len() == 1;
let mut countdown = 0;
if is_true {
countdown = 10;
}
use_this_lib_crate();
}

#[inline(always)]
pub fn used_inline_function() {
// Initialize test constants in a way that cannot be determined at compile time, to ensure
// rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
// dependent conditions.
let is_true = std::env::args().len() == 1;
let mut countdown = 0;
if is_true {
countdown = 10;
}
use_this_lib_crate();
}

#[inline(always)]
pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
println!("used_only_from_bin_crate_generic_function with {:?}", arg);
}
// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)

#[inline(always)]
pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
}

#[inline(always)]
pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
}

#[inline(always)]
pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
}

#[inline(always)]
pub fn unused_generic_function<T: Debug>(arg: T) {
println!("unused_generic_function with {:?}", arg);
}

#[inline(always)]
pub fn unused_function() {
let is_true = std::env::args().len() == 1;
let mut countdown = 2;
if !is_true {
countdown = 20;
}
}

#[inline(always)]
#[allow(dead_code)]
fn unused_private_function() {
let is_true = std::env::args().len() == 1;
let mut countdown = 2;
if !is_true {
countdown = 20;
}
}

fn use_this_lib_crate() {
used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
"used from library used_crate.rs",
);
let some_vec = vec![5, 6, 7, 8];
used_only_from_this_lib_crate_generic_function(some_vec);
used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
}
8 changes: 8 additions & 0 deletions tests/coverage-map/issue-85461.cov-map
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Function name: issue_85461::main
Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 03, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 2)

11 changes: 11 additions & 0 deletions tests/coverage-map/issue-85461.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]

// aux-build:inline_always_with_dead_code.rs
extern crate inline_always_with_dead_code;

use inline_always_with_dead_code::{bar, baz};

fn main() {
bar::call_me();
baz::call_me();
}
16 changes: 16 additions & 0 deletions tests/coverage-map/unused_mod.cov-map
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Function name: unused_mod::main
Raw bytes (9): 0x[01, 02, 00, 01, 01, 04, 01, 02, 02]
Number of files: 1
- file 0 => global file 2
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 4, 1) to (start + 2, 2)

Function name: unused_mod::unused_module::never_called_function (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 02, 01, 02, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 2, 1) to (start + 2, 2)

6 changes: 6 additions & 0 deletions tests/coverage-map/unused_mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#[path = "auxiliary/unused_mod_helper.rs"]
mod unused_module;

fn main() {
println!("hello world!");
}
40 changes: 40 additions & 0 deletions tests/coverage-map/uses_crate.cov-map
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
Function name: used_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>
Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 02, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 27, 1) to (start + 2, 2)

Function name: used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>
Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2)

Function name: used_crate::used_only_from_bin_crate_generic_function::<&str>
Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2)

Function name: used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>
Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 02, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 2)

Function name: uses_crate::main
Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 07, 02]
Number of files: 1
- file 0 => global file 2
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 12, 1) to (start + 7, 2)

19 changes: 19 additions & 0 deletions tests/coverage-map/uses_crate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// This test was failing on Linux for a while due to #110393 somehow making
// the unused functions not instrumented, but it seems to be fine now.

// Validates coverage now works with optimizations
// compile-flags: -C opt-level=3

#![allow(unused_assignments, unused_variables)]

// aux-build:used_crate.rs
extern crate used_crate;

fn main() {
used_crate::used_function();
let some_vec = vec![1, 2, 3, 4];
used_crate::used_only_from_bin_crate_generic_function(&some_vec);
used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?");
}
55 changes: 55 additions & 0 deletions tests/coverage-map/uses_inline_crate.cov-map
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Function name: used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>
Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 01, 02, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 44, 1) to (start + 2, 2)

Function name: used_inline_crate::used_inline_function
Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 14, 01, 06, 0f, 05, 06, 10, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 2
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
Number of file 0 mappings: 4
- Code(Counter(0)) at (prev + 20, 1) to (start + 6, 15)
- Code(Counter(1)) at (prev + 6, 16) to (start + 2, 6)
- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7)
= (c0 - c1)
- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 1, 2)
= (c1 + (c0 - c1))

Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>
Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2)

Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&str>
Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2)

Function name: used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>
Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 02, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 49, 1) to (start + 2, 2)

Function name: uses_inline_crate::main
Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 0a, 02]
Number of files: 1
- file 0 => global file 2
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 12, 1) to (start + 10, 2)

Loading

0 comments on commit bbe6d66

Please sign in to comment.