주요 콘텐츠

Merge C/C++ Code Coverage Results from Build Variants

R2026b

In many projects, the same source code is compiled with different preprocessor macros to produce different build variants. For instance, a source file might use #if preprocessor directives to select between different code paths depending on the active variant. Each variant activates different branches in the code, so measuring code coverage for one variant alone does not reflect the actual test coverage of the entire source file.

To compute code coverage for a source file that supports multiple variants, you can collect code coverage results for each variant separately and then use the polyspace-code-profiler -merge -operation aggregate-variants command to combine the results into a single overview that accounts for all code paths across all variants.

Example Files

To follow this example, copy the folder <polyspaceroot>\polyspace\examples\doc_pstest\coverage_variants to a writable location. Here, <polyspaceroot> is the Polyspace® installation folder, for example, C:\Program Files\Polyspace\R2026b.

The folder contains these files:

  • source.c — Source file containing functions to test. The file uses #if preprocessor directives to select between two variant-specific code paths (Variant A and Variant B).

    The source file contains this pattern to define the variants:

    #if VARIANT_A
        /* Variant A: trim high values, nudge low values. */
        if (out > 50) {
            out = out - 5;
        } else {
            out = out + 1;
        }
    #elif VARIANT_B
        /* Variant B: bias away from zero. */
        if (out >= 0) {
            out = out + 3;
        } else {
            out = out - 3;
        }
    #endif

  • sut.h — Header file declaring the functions in source.c.

  • variantA/test.c — xUnit test file for Variant A. When building the test, set the macro VARIANT_A to 1.

  • variantB/test.c — xUnit test file for Variant B. When building the test, set the macro VARIANT_B to 1.

The tutorial uses <PSTEST_SOURCE>, <PSTEST_INCLUDE>, and <PSTEST_LIB> as shorthands for files and folders available with a Polyspace Test™ installation. For the full paths to these files and folders, see Set Up C/C++ Testing and Code Profiling Using Self-Managed Builds.

Collect Coverage for Each Variant

To collect coverage for each variant, instrument, compile, and run the tests for each variant separately. In this example, the GCC compiler (gcc command) is used as the toolchain.

Variant A

  1. Instrument the source file for Variant A and compile it:

    polyspace-code-profiler -instrument -instrum-dir instrums_variantA -- gcc -DVARIANT_A=1 -c source.c -I . -o source_variantA.o

  2. Compile the test file and the file pstest.c containing Polyspace Test xUnit API definitions (listed as <PSTEST_SOURCE> below):

    gcc -DVARIANT_A=1 -c variantA/test.c -I . -I <PSTEST_INCLUDE> -o test_variantA.o
    gcc -c -D PSTEST_RUNTIME_AS_STATIC_LIBRARY=1 <PSTEST_SOURCE> -I <PSTEST_INCLUDE> -o pstest.o

  3. Link the object files with the Polyspace Test precompiled library to create the test executable:

    gcc source_variantA.o test_variantA.o pstest.o <PSTEST_LIB> -o variantA

  4. Run the test executable and collect coverage data. In Windows®, enter:

    polyspace-code-profiler -run -instrum-dir instrums_variantA -results-dir results_variantA -- variantA.exe
    In Linux®, enter:
    polyspace-code-profiler -run -instrum-dir instrums_variantA -results-dir results_variantA -- ./variantA.out

Variant B

Repeat the same steps for Variant B, using -DVARIANT_B=1 instead of -DVARIANT_A=1:

  1. Instrument and compile the source file:

    polyspace-code-profiler -instrument -instrum-dir instrums_variantB -- gcc -DVARIANT_B=1 -c source.c -I . -o source_variantB.o

  2. Compile the test file:

    gcc -DVARIANT_B=1 -c variantB/test.c -I . -I <PSTEST_INCLUDE> -o test_variantB.o
    You have already compiled the file pstest.c containing Polyspace Test xUnit API definitions and do not need to compile this file again.

  3. Link the test executable:

    gcc source_variantB.o test_variantB.o pstest.o <PSTEST_LIB> -o variantB

  4. Run the test executable and collect coverage data. In Windows, enter:

    polyspace-code-profiler -run -instrum-dir instrums_variantB -results-dir results_variantB -- variantB.exe
    In Linux, enter:
    polyspace-code-profiler -run -instrum-dir instrums_variantB -results-dir results_variantB -- ./variantB.out

At this point, you have separate coverage results for each variant in results_variantA and results_variantB. Open each coverage result in the Polyspace Platform user interface and note the percentage coverage.

Aggregate Coverage Results from All Variants

Use the -merge command with the aggregate-variants operation to combine coverage results from the two variants into a single result:

polyspace-code-profiler -merge -operation aggregate-variants -results-dir mergedResult -results-name merged_variants results_variantA results_variantB

This command:

  • Reads the .psprof files from the two input folders results_variantA and results_variantB.

  • Aggregates the code coverage data from both variants, combining the coverage of variant-specific code paths.

  • Saves the aggregated result as merged_variants.psprof in the folder mergedResult.

Open the merged result, merged_variants.psprof, in the Polyspace Platform user interface. You see greater code coverage compared to either of the individual results.

To generate an HTML report from the aggregated results, enter:

polyspace-code-profiler -report -html -report-dir reports mergedResult

Open the HTML report to review the aggregated code coverage across all variants. The aggregated view shows coverage for code paths that are active in Variant A, code paths that are active in Variant B, and the shared code paths that are common to both variants.

See Also

Topics