BullseyeCoverage Up Contents Search

Introduction

BullseyeCoverage is a code coverage analyzer for the C and C++ languages. With BullseyeCoverage, you can:

The steps involved in using BullseyeCoverage are:

  1. Enable coverage build and build your program
  2. Run your program one or more times
  3. Generate and view coverage reports
  4. Repeat from step 2 until you are satisfied with testing

BullseyeCoverage cannot measure coverage of assembly code.

How it Works

When coverage build is enabled, BullseyeCoverage intercepts compiler invocations to perform instrumentation. Information about the code is written to a coverage file. The instrumented code is compiled using your compiler. At run-time, the coverage file is updated with coverage measurements. The COVFILE environment variable names the coverage file. You can view the coverage file using the Coverage Browser or the command line report programs.

Measurement Technique

Instrumentation Model

BullseyeCoverage measures condition/decision coverage and function coverage. The following specific events are monitored.

  1. BullseyeCoverage indicates whether the true and false outcomes of each decision occurred. A decision is the controlling expression in the if, if-else, while, do-while, and for statements. The first operand of the ?: operator is a decision if the ?: occurs outside a controlling expression. In the example code below, the decisions are marked by yellow boxes.
    if (v1 == v2 && (v3 || v4))
    
    v5 = v6 ? v7 : v8;
    
    if (v6 ? v7 : v8)
    
    v9 = (v10 || v11) ? v12 : v13;
    
    if ((v10 || v11) ? v12 : v13)
    
    v14 = v15 || v16;
    
  2. BullseyeCoverage indicates whether the true and false outcomes of each condition occurred. A condition is an operand of the logical operators && and || that does not contain logical operators. The ?: operator is also a logical operator. The first operand of the ?: operator is a condition if it does not contain logical operators and the ?: occurs in a decision. In the example code below, the conditions are marked by blue boxes.
    if (v1 == v2 && (v3 || v4))
    
    v5 = v6 ? v7 : v8;
    
    if (v6 ? v7 : v8)
    
    v9 = (v10 || v11) ? v12 : v13;
    
    if ((v10 || v11) ? v12 : v13)
    
    v14 = v15 || v16;
    
  3. BullseyeCoverage indicates whether each case and default label was selected. When the default label is omitted, the branch to the end of the switch statement is indicated. For example, BullseyeCoverage indicates whether control flowed to each of the pink boxed areas below.
    switch (a) {
    case 1:
    case 2:
        statements
        break;
    }	// Implicit default
    
  4. BullseyeCoverage indicates whether each try-block finished without exceptions and whether each exception handler was entered. Coverage of Microsoft structured exception handling (__try, __except) is indicated similarly. For example, BullseyeCoverage indicates whether control flowed to the pink boxed area below.
    try {
        statements
    }
    catch (exception-declaration) {
        statements
    }
    catch (...) {
        statements
    }
    
  5. BullseyeCoverage indicates whether each function was entered.
    void function()
    {
        statements
    }
    

  6. BullseyeCoverage indicates whether each lambda-expression was entered.
    [] { statements }
    

  7. BullseyeCoverage indicates whether each range-based for statement body was entered.
    for (for-range-declaration: expression) statement
    

Other Details

By default, BullseyeCoverage does not measure coverage of code produced by macros.

BullseyeCoverage does not measure coverage of variable initializers at file scope.

BullseyeCoverage does not measure coverage of static variable initializers in C. These initializers are evaluated at compile-time.

BullseyeCoverage does not measure coverage of functions declared consteval or constexpr. These functions might be evaluated at compile-time. Likewise, BullseyeCoverage does not measure coverage of initializers declared constexpr or constinit.

BullseyeCoverage measures coverage in template functions the same way as regular functions. Coverage is measured by instrumenting the source code. Coverage in all template instantiations is combined and reported together.

Best Practice Recommendations

These are general guidelines for usage of C++ features and tools that can have an impact on coverage measurement.

Performance

Instrumenting with BullseyeCoverage typically increases execution time to 1.2x, code size to 1.4x and compile time to 1.7x with most Microsoft C++ projects, 3-8x with other compilers. Your results may vary. Compiler optimization settings greatly affect performance of instrumented code.

BullseyeCoverage may modify compiler options and directives affecting performance. These changes may include, but are not limited to, the following.

object code

Updated: 29 Aug 2023