章节目录:

前言

C/C++test 的多指标覆盖率分析允许在执行 C/C++test 外部的独立应用程序或库时监控代码覆盖率。

C/C++test 附带一个独立的覆盖率包,包含以下组件:

  • <INSTALL_DIR>/bin/cpptestcc - 一个集成到您的构建流程中的覆盖率工具,用于应用程序插桩以收集原始覆盖率数据。
  • <INSTALL_DIR>/bin/engine/coverage/runtime - 需要与插桩的应用程序集成的覆盖率运行时库。
使用 cpptestcc 收集覆盖率分为三个阶段:

  1. 通过将 cpptestcc 工具集成到构建中来进行应用程序插桩。
  2. 执行插桩的代码并收集原始覆盖率数据。
  3. 使用内建测试配置将原始覆盖率数据导入 C/C++test 可在 C/C++test 中查看覆盖率。

cpptestcc 快速入门

  1. 将路径添加到 <INSTALL_DIR>/bin  PATH 系统变量,使 cpptestcc 工具能够执行。

  2. 更新编译命令,使之包含 cpptestcc 可执行文件作为编译器命令的前缀,通过 -- 进行分隔。 例如:

    原始编译命令行

    cc -I app/includes -D defines -c source.cpp

    更新后的编译命令行

    cpptestcc -compiler gcc_9-64 -line-coverage -- cc -I app/includes -D defines -c source.cpp
    cpptestcc 工具至少要求在命令行配置以下参数:

    - 编译器标识符: -compiler <COMPILER_ID>

    - 覆盖率指标(例如,-decision-coverage

    有关其他选项的信息,请参阅 cpptestcc 命令行参考

  3. 使用 C/C++test 附带的预建覆盖率运行时库的路径更新链接器命令,将该库添加到您的应用程序中。例如:

    原始命令行

    lxx -L app/lib app/source.o somelib.lib -o app.exe

    更新后的命令行

    lxx -L app/lib app/source.o somelib.lib [INSTALL_DIR]/bin/engine/coverage/runtime/lib/cpptest.lib -o app.exe

    重要提示

    如果覆盖率运行时库作为共享(动态加载)库链接,则必须确保在启动插桩的应用程序时可以加载该库。这通常需要将 <INSTALL_DIR>/bin/engine/coverage/runtime/bin 添加到 PATH 环境变量(Windows)或 <INSTALL_DIR>/bin/engine/coverage/runtime/lib  LD_LIBRARY_PATH 环境变量中(Linux)。

    C/C++test 为原生 Windows 和 Linux 应用程序提供了预建的覆盖率运行时库。对于跨平台和嵌入式测试,该运行时库需要从 <INSTALL_DIR>/bin/engine/coverage/runtime 的源文件中构建。 详细信息请参阅覆盖率运行时库

  4. 构建应用程序。进行代码插桩时,cpptestcc 会创建 .cpptest/cpptestcc 文件夹,存储重要的覆盖率相关数据(“覆盖率映射”)。默认情况下,该文件夹位于当前编译的工作目录中。可以使用 -workspace <path> 选项更改默认位置;详细信息请参阅 cpptestcc 命令行参考 
  5. 运行应用程序。覆盖率数据(“覆盖率日志”)将存储在 cpptest_results.clog 文件中。
  6. 在安装了 C/C++test 的 IDE 中,创建一个包含应用程序所有源文件的新项目。
    (info)确保这些文件和所有路径都保持不变。
  7. 选中项目,从 IDE 菜单选择 Parasoft> 测试配置> Utilitie> Load Application Coverage 导入覆盖率数据(详细信息请参阅导入覆盖率数据)。
  8. 查看覆盖率信息(请参阅查看覆盖率信息)。

导入覆盖率数据

Load Application Coverage 测试配置假设 .cpptest/cpptestcc 文件夹和 cpptest_results.clog 文件存储在默认位置。要自定义该位置,需在测试配置中配置以下执行细节(执行> 常规> 执行细节):
Coverage map files root location - default: ${project_loc}/.cpptest/cpptestcc
Coverage log files - default: ${project_loc}/*.clog

默认情况下,Load Application Coverage 测试配置会尝试加载有关支持的所有覆盖率指标的信息。要自定义支持的覆盖率指标列表,可前往执行> 常规> 执行细节> 插桩模式> 插桩功能> C/C++ 代码覆盖率指标,然后选择需要报告的指标。

我们建议与编译命令行中为 cpptestcc 工具启用的指标保持一致。

收集 CMake 项目的应用程序覆盖率

C/C++test 附带一个 CMake 扩展,允许将 C/C++test 的代码覆盖率分析直接集成到您的 CMake 项目中。该扩展会自动修改编译器/链接器命令行,在构建项目时使用 cpptestcc 覆盖率工具。因此,在运行插桩的应用程序或执行功能测试或单元测试后,会创建一个 C/C++test·覆盖率日志文件(.clog)。该覆盖率日志文件之后可用于生成完整的代码覆盖率报告。

CMake 集成支持包含:

  • <CPPTEST_INSTALL_DIR>/integration/cmake/cpptest-coverage.cmake 扩展 - 需要添加到您的 CMakeFiles.txt 构建文件中的 CMake C/C++test 扩展文件。
  • <CPPTEST_INSTALL_DIR>/integration/cmake/cpptest.templates/* 中的模板 - 用于生成 C/C++test(Eclipse)项目的 C/C++test 一套模板。
  • CPPTEST_COVERAGE=ONCPPTEST_HOME=<CPPTEST_INSTALL_DIR> 选项 - 该扩展提供的选项,可在使用 CMake 构建应用程序时激活扩展。
  • cpptest_coverage_report 目标 - 该扩展提供的目标,使用 .clog 文件作为输入来生成覆盖率报告。

此外,<CPPTEST_INSTALL_DIR>/examples/Timer 目录包含一个演示 CMake 项目代码覆盖率收集的示例项目。

要求

  • 带有 Unix Makefiles 或 Ninja 生成器的 CMake 3.10 或更高版本

附加前提条件:

  • 必须执行应用程序的完整构建才能收集 CMake 项目的代码覆盖率。不支持增量构建。
  • 在 Windows 中,您的 CMake 项目和工具链需要配置为使用带正斜杠或反斜杠的 Windows 路径(例如,c:/folder/source.cpp  c:\folder\source.cpp)。Windows 不支持 Unix 风格的路径(例如,/c/folder/source.cpp)。

工作流程概要

  1. <CPPTEST_INSTALL_DIR>/integration/cmake/cpptest-coverage.cmake<CPPTEST_INSTALL_DIR>/integration/cmake/cpptest.templates/* 复制到 CMake 项目中。
  2. cpptest-coverage.cmake 文件中查看覆盖率配置详细信息并根据需要更新选项。  至少需要确保使用 CPPTEST_COMPILER_ID 选项指定的编译器配置与您的编译器匹配。有关可用选项的信息,请参阅自定义 CMake 的覆盖率扩展

  3. cpptest-coverage.cmake 扩展添加到您的 CMakeLists.txt 主构建文件中。概扩展必须放在所有构建目标定义之前,以确保自动修改编译器/链接器命令行。
  4. 在配置和构建 CMake 项目时,使用 CPPTEST_COVERAGE and CPPTEST_HOME 选项激活扩展:

    > cmake -DCPPTEST_COVERAGE=ON -DCPPTEST_HOME=<CPPTEST_INSTALL_DIR> ..

    默认情况下,C/C++test 的覆盖率数据文件将在 <CMAKE_SOURCE_DIR>/../cpptest-coverage/<CMAKE_PROJECT_NAME>/.cpptest 中创建。

  5. 运行应用程序或执行功能或单元测试。
    默认情况下,C/C++test 覆盖率日志文件(.clog)将在 <CMAKE_SOURCE_DIR>/../cpptest-coverage/<CMAKE_PROJECT_NAME>/<CMAKE_PROJECT_NAME>.clog 中创建。
  6. 运行 cpptest_coverage_report 辅助目标以生成覆盖率报告:

    > make cpptest_coverage_report

    C/C++test 目标将创建:
    - 一个可以直接在 IDE 中打开的工作空间:<CMAKE_SOURCE_DIR>/../cpptest-coverage
    - 一个位于该工作空间中的 C/C++test(Eclipse)项目:<CMAKE_SOURCE_DIR>/../cpptest-coverage/<CMAKE_PROJECT_NAME>
    - 位于 reports 目录的覆盖率报: <CMAKE_SOURCE_DIR>/../cpptest-coverage/<CMAKE_PROJECT_NAME>/reports

    我们建议使用 cpptest_coverage_report 目标生成覆盖率报告。或者,也可以用 C/C++test 的 Load Application Coverage 测试配置,根据从 <CMAKE_SOURCE_DIR>/../cpptest-coverage/<CMAKE_PROJECT_NAME> 中收集的覆盖率数据生成报告。详细信息请参阅导入覆盖率数据

自定义 CMake 的覆盖率扩展

要自定义该 C/C++test 扩展的覆盖率收集功能,应打开复制到您的 CMake 项目中的 cpptest-coverage.cmake 文件并修改 C/C++test 选项。 

选项名称说明默认值
CPPTEST_COMPILER_ID

指定与您的编译器匹配的编译器配置。

gcc_9-64
 CPPTEST_COVERAGE_TYPE_FLAGS 指定覆盖率类型。有关可用选项的信息,请参阅cpptestcc 命令行参考-optimized-line-coverage
CPPTEST_COVERAGE_WORKSPACE指定覆盖率工具的工作空间路径,默认存储 C/C++test 的覆盖率数据文件。<CMAKE_SOURCE_DIR>/../cpptest-coverage/<CMAKE_PROJECT_NAME>
CPPTEST_COVERAGE_LOG_FILE

指定 C/C++test 覆盖率日志文件的名称和位置(.clog)。

重要提示:在运行插桩的应用程序之前,必须确保覆盖率日志目录存在。

<CPPTEST_COVERAGE_WORKSPACE>/<CMAKE_PROJECT_NAME>.clog
CPPTEST_CPPTESTCC_OPTS指定 cpptestcc 覆盖率工具的选项。

此外,您可能需要查看:

  • cpptest_coverage_report 目标的定义,该目标指定用于生成覆盖率报告的 cpptestcli 的参数。
  • # Build C/C++test coverage runtime library 部分,其中包含配置 C/C++test 的运行时库(该库由覆盖率扩展自动构建)的配置。
  • CPPTEST_LINKER_FLAGS 选项,该选项定义了如何链接 C/C++test·覆盖率运行时。

覆盖率扩展与 CMake 的集成示例

该部分演示如何使用 C/C++test 的 CMake 覆盖率扩展收集 <CPPTEST_INSTALL_DIR>/examples/Timer 目录中示例项目的覆盖率数据。Timer 项目经配置使用 <CPPTEST_INSTALL_DIR>/integration/cmake 中提供的 cpptest-coverage.cmake 扩展。

收集示例项目覆盖率的步骤:

  1. 如果您使用的编译器不是默认的 GNU GCC 9 (x64),应在 <CPPTEST_INSTALL_DIR>/integration/cmake/cpptest-coverage.cmake 中修改CPPTEST_COMPILER_ID 以匹配您的编译器。
  2. 构建示例项目:

    > cd <CPPTEST_INSTALL_DIR>/examples/Timer
    > mkdir build
    > cd build
    > cmake -DCPPTEST_COVERAGE=ON -DCPPTEST_HOME=<CPPTEST_INSTALL_DIR> ..
    > make
  3. 运行应用程序:

    > ./timer
  4. 生成覆盖率报告:

    > make cpptest_coverage_report

    报告将在 <CPPTEST_INSTALL_DIR>/examples/cpptest-coverage/Timer/reports 中生成。

  5. (可选)启动 C/C++test GUI,打开<CPPTEST_INSTALL_DIR>/examples/cpptest-coverage 工作空间,在 IDE 中查看覆盖率详细信息。

收集 MSBuild 项目的应用程序覆盖率

您可以使用 C/C++test 附带的脚本快速配置 MSBuild 项目以集成覆盖率分析。此脚本支持 Visual Studio 和 Cmake 生成的 MSBuild 项目。该脚本创建目标 .vcxproj 文件的备份并修改,从而在所有构建目标上启用所需的 Parasoft 功能。

C/C++test 有一个 Python 脚本启动器,用于运行包含的工具,可以在以下位置找到:

<CPPTEST_INSTALL_DIR>/bin/engine/bin/cpptestpy.exe
MSBuild 集成脚本位于以下位置:

<CPPTEST_INSTALL_DIR>/integration/msbuild/msbuild_cpptest.py

收集 MSBuild 项目覆盖率的步骤:

  1. 设置环境变量。

请确保未在 = 后面使用双引号,否则会导致不正确的字符串解释。 

    1. 设置 CPPTEST_INSTALL_DIR 变量。

      set CPPTEST_HOME=<CPPTEST_INSTALL_DIR>
    2. 设置 PATH 变量。

      set PATH=%PATH%;%CPPTEST_HOME\bin\engine\coverage\runtime\bin

  1. (仅限 Cmake)使用 Cmake 生成 MSBuild 文件。 

    cd <PROJECT_DIR>
    mkdir build
    cd build
    cmake ..
  2. 运行集成脚本。 

    <cpptestpy.exe> <msbuild_cpptest.py> -c -f project.vcxproj
  3. 使用 MSBuild 构建项目。

    msbuild -t:Rebuild project.sln
  4.  要收集覆盖率,需进入构建目录并运行该项目。

    cd x64\Debug
    project.exe

    包含覆盖率信息的 .clog 文件将在您当前的工作目录中生成。
    文件默认命名为 cpptest_results.clog

  5. 生成覆盖率报告。

    cpptestcli.exe \
    -data ../workspace \
    -bdf cpptestscan.bdf \
    -property bdf.import.location=BDF_LOC \
    -config "builtin://Load Application Coverage"

cpptestcc 命令行参考

(info) 您可以运行以下命令将可用选项打印到控制台中: cpptestcc -help

可使用以下选项:

-compiler <name|path>

指定要用于代码分析和插桩的编译器配置的名称。有关支持的编译器列表,请参阅编译器,或使用 -list-compilers 命令行选项将支持的编译器列表打印到控制台中。

示例:

cpptestcc -compiler gcc_9-64 

cpptestcc -compiler vc_11_0

配置文件格式(请参阅 -psrc):cpptestcc.compiler <name>

-list-compilers

打印支持的所有编译器配置的名称。

配置文件格式(请参阅 -psrc):cpptestcc.listCompilers

-include <file|pattern> and -exclude <file|pattern>

在插桩范围中包含或从插桩范围中排除所有匹配指定模式的文件。

最终的过滤结果只有在按顺序指定所有包含/排除条目后才能确定。

支持以下通配符:

  • ? - 任意字符
  • * - 任意字符序列

为防止 shell 将 * 通配符扩展为文件或目录列表,可以使用 regex: 前缀来指定值。

(info) 这些选项可以指定多次。

配置文件格式(请参阅 -psrc):cpptestcc.include <path|pattern>

示例 1:

示例项目结构:

<project root>
 + external_libs
 + src
 + include

如果您的项目具有以上结构,则以下命令将从插桩范围中排除 external_libs 目录中的所有文件:

cpptestcc -include regex:*/<project root>/* -exclude regex:*/<project root>/external_libs <other command line options>

示例 2:

示例项目结构:

<project root> 
<sourcefiles>.cpp 
<headerfiles>.hpp

如果您的项目具有以上结构,则以下命令将仅对头文件插桩(不会对源文件插桩):

cpptestcc -include regex:* -exclude regex:*.cpp <remaining part of cmd>

-ignore <pattern>

指定在处理过程中将忽略的源文件。将编译匹配指定模式的文件,但不会进行解析或插桩。

-ignore 与 -exclude

-ignore 选项从处理过程中彻底删除指定的文件,使其不被覆盖率引擎解析。

-include/-exclude 过滤器在解析源代码后应用,允许选择插桩或不插桩的头文件。

您可以使用 -ignore 选项,通过忽略对某些代码部分(如外部库)进行覆盖率分析或忽略在处理过程中暴露解析错误或其他问题的特定文件来减少构建时间开销。

支持以下通配符:

  • ? - 任意字符
  • * - 任意字符序列

为防止 shell 将 * 通配符扩展为文件或目录列表,可以使用 regex: 前缀来指定值。

(info) 此选项可以多次指定。

配置文件格式(请参阅 -psrc):cpptestcc.ignore <path|pattern>

示例:

cpptestcc -ignore "*/Lib/*" <remaining part of cmd>
cpptestcc -ignore regex:*/file.c <remaining part of cmd>
cpptestcc -ignore c:/proj/file.c <remaining part of cmd>
cpptestcc -ignore "*/MyLib/*.cpp" -ignore file.cpp <remaining part of cmd>

-line-coverage

启用行覆盖率收集。

执行代码时,运行时覆盖率结果将写入结果日志。这会为被测代码执行时间带来了一些开销,但是能够确保即使应用程序崩溃也能收集到覆盖率数据。

配置文件格式(请参阅 -psrc):cpptestcc.lineCoverage [true|false]

-optimized-line-coverage

启用行覆盖率优化收集。

运行时覆盖率结果存储在内存中,然后在应用程序完成后或根据用户请求写入结果日志。这种方式的性能更佳,但如果应用程序崩溃可能会丢失结果。

配置文件格式(请参阅 -psrc):cpptestcc.optimizedLineCoverage [true|false]

-function-coverage

启用函数覆盖率收集。

配置文件格式(请参阅 -psrc):cpptestcc.functionCoverage [true|false]

-optimized-function-coverage

启用函数覆盖率优化收集。配置文件格式(请参阅 -psrc):

cpptestcc.optimizedFunctionCoverage [true|false]

-statement-coverage

启用语句覆盖率收集。配置文件格式(请参阅 -psrc):

cpptestcc.statementCoverage [true|false]

-optimized-statement-coverage

启用语句覆盖率优化收集。

配置文件格式(请参阅 -psrc):cpptestcc.optimizedStatementCoverage [true|false]

-block-coverage

启用基础块覆盖率收集。

配置文件格式(请参阅 -psrc):cpptestcc.blockCoverage [true|false]

-optimized-block-coverage

启用基础块覆盖率优化收集。

配置文件格式(请参阅 -psrc):cpptestcc.optimizedBlockCoverage [true|false]

-path-coverage

启用路径覆盖率收集。

配置文件格式(请参阅 -psrc):cpptestcc.pathCoverage [true|false]

-decision-coverage

启用判定覆盖率收集。

配置文件格式(请参阅 -psrc):cpptestcc.decisionCoverage [true|false]

-optimized-decision-coverage

启用判定覆盖率优化收集。

配置文件格式(请参阅 -psrc):cpptestcc.optimizedDecisionCoverage [true|false]

-simple-condition-coverage

启用简单条件覆盖率收集。

配置文件格式(请参阅 -psrc):cpptestcc.simpleConditionCoverage [true|false]

-optimized-simple-condition-coverage

启用简单条件覆盖率优化收集。

配置文件格式(请参阅 -psrc):cpptestcc.optimizedSimpleConditionCoverage [true|false]

-mcdc-coverage

启用 MC/DC 覆盖率收集。

配置文件格式(请参阅 -psrc):cpptestcc.mcdcCoverage [true|false]

-call-coverage

启用调用覆盖率收集。

配置文件格式(请参阅 -psrc):cpptestcc.callCoverage [true|false]

-optimized-call-coverage

启用调用覆盖率优化收集。

配置文件格式(请参阅 -psrc):cpptestcc.optimizedCallCoverage [true|false]

-coverage-early-init

启用在应用程序入口点开头初始化覆盖率模块。

配置文件格式(请参阅 -psrc):cpptestcc.coverageEarlyInit [true|false]

-coverage-auto-finalization

启用后,覆盖率收集将在应用程序退出时自动完成。默认情况下启用此选项。

配置文件格式(请参阅 -psrc):cpptestcc.coverageAutoFinalization [true|false]

-optimized-coverage-corruption-detection

启用优化覆盖率指标的损坏检测算法。

配置文件格式(请参阅 -psrc):cpptestcc.optimizedCoverageCorruptionDetection [true|false]

-template-coverage

启用模板类和函数的覆盖率收集。

配置文件格式(请参阅 -psrc):cpptestcc.templateCoverage [true|false]

-constexpr-coverage

启用 constexpr 函数的覆盖率收集。

注意:此功能仅适用于选定的编译器。详细信息请参阅 C++ 常量表达式支持

配置文件格式(请参阅 -psrc):cpptestcc.constexprCoverage [true|false]

-ignore-const-decisions

启用在编译时已知判定结果时忽略判定/分支点

示例:

while(1) {} // no decision / branch
if(false) {} // no decision / branch

详细信息,请参阅在编译时已知判定结果时忽略判定/分支点

此设置将影响判定(分支)覆盖率和路径覆盖率。该选项默认禁用。

配置文件格式(请参阅 -psrc):cpptestcc.ignoreConstDecisions [true|false]

 -coverage-data-variants

启用为同一源文件的不同编译存储覆盖率数据的多个变体。

默认情况下,cpptestcc 每次构建会收集每个源文件的覆盖率数据一次。在极少数情况下,当源文件在构建期间被多次编译时,您可以使用此选项为同一个源文件存储覆盖率数据的多个变体——每次编译一个变体。

此选项不支持通过多次编译同一源文件而引入冲突代码的方案。

-disable-auto-recovery-mode

禁用覆盖率插桩的自动恢复模式。

默认情况下,当无法成功进行文件插桩时,将在构建中使用该文件的原始(未插桩)版本。指定此选项后,如果出现插桩问题,构建将失败并出现错误。

-workspace <path>

指定一个自定义目录,在代码分析和插桩期间,有关代码结构的信息将存储在该目录中。cpptestcli 工具将使用该信息生成最终的覆盖率报告。

默认情况下,该信息存储在当前编译的工作目录中。如果编译使用多个工作目录,我们建议您指定一个自定义目录来确保所有覆盖率数据都存储在同一位置。

配置文件格式(请参阅 -psrc):cpptestcc.workspace <path>

-techsupport

 使用从工作空间(请参阅 -workspace)收集的诊断文件创建压缩包。压缩包将存储在当前的工作目录中。

示例:

cpptestcc -techsupport

cpptestcc -techsupport -workspace path/to/workspace-dir

-psrc <file>

指定可以配置其他 cpptestcc 选项的配置文件的路径。

默认情况下,cpptestcc 会尝试读取当前工作目录或用户 HOME 目录中的 .psrc 文件。使用该选项可以指定配置文件的自定义位置。

(info) 如果在命令行和配置文件中都配置了选项,cpptestcc 将使用命令行中指定的值。

-status

-status-verbose

显示从工作空间(请参阅 -workspace)中收集的诊断数据,包括错误和警告信息、文件数量等。

使用 -status-verbose 以显示更详细的信息。

示例:

cpptestcc -status

cpptestcc -status -workspace path/to/workspace-dir

cpptestcc -status-verbose

cpptestcc -status-verbose -workspace path/to/workspace-dir

-version

打印有关版本的信息

-help

打印帮助消息并退出。

覆盖率运行时库

覆盖率运行时库是源代码插桩用来在应用程序运行时发出覆盖率信息的辅助函数和服务的集合。没有该库就无法链接已插桩的应用程序。根据被测项目的类型,运行时库可以通过多种方式链接到最终的可测试二进制文件。

除了为插桩的代码提供基本服务外,该库还用于使代码覆盖率解决方案适应特定的开发环境,例如支持被测嵌入式设备和开发主机之间覆盖率结果的非标准传输。

预建版本和自定义构建

C/C++test 配备了运行时库的预建版本,适合在安装了 C/C++test 的平台上使用。在大多数情况下,从原生开发的应用中收集代码覆盖率信息可以使用预建版本的运行时库。

所有开发跨平台应用程序的用户都需要使用合适的交叉编译器和链接器准备覆盖率运行时库的自定义构建。代码覆盖率运行时库的源代码与 C/C++test 一起提供。

覆盖率运行时库自定义构建的准备过程通常受限于覆盖率运行时库源代码的编译。在某些情况下,您可能需要安装一些源代码片段,以使代码覆盖率适应特定的开发平台。该过程在以下部分说明。

使用预建的运行时库

C/C++test 包含以下二进制文件:

Windows(x86 和 x86-64) 

文件说明
<INSTALL_DIR>/bin/engine/coverage/runtime/lib/cpptest.a用于 Cygwin GNU GCC 编译器的 32 位导入库。添加到链接命令行。
<INSTALL_DIR>/bin/engine/coverage/runtime/lib/cpptest64.a用于 Cygwin GNU GCC 编译器的 64 位导入库。添加到链接命令行。
<INSTALL_DIR>/bin/engine/coverage/runtime/lib/cpptest.lib用于 Microsoft Visual C++ 编译器的 32 位导入库。添加到链接命令行。
<INSTALL_DIR>/bin/engine/coverage/runtime/lib/cpptest64.lib用于 Microsoft Visual C++ 编译器的 64 位导入库。添加到链接命令行。
<INSTALL_DIR>/bin/engine/coverage/runtime/bin/cpptest.dll32 位动态链接库。<INSTALL_DIR>/bin/engine/coverage/runtime/bin 应添加到 PATH 环境变量。
<INSTALL_DIR>/bin/engine/coverage/runtime/bin/cpptest64.dll64 位动态链接库。<INSTALL_DIR>/bin/engine/coverage/runtime/bin 应添加到 PATH 环境变量。
Linux(x86 和 x86-64)
文件说明
<INSTALL_DIR>/bin/engine/coverage/runtime/lib/libcpptest.so32 位共享库。添加到链接命令行。<INSTALL_DIR>/bin/engine/coverage/runtime/lib 应添加到 LD_LIBRARY_PATH
<INSTALL_DIR>/bin/engine/coverage/runtime/lib/libcpptest64.so64 位共享库。添加到链接命令行。<INSTALL_DIR>/bin/engine/coverage/runtime/lib 应添加到 LD_LIBRARY_PATH

如果您需要以非现成解决方案的形式使用运行时库,则可以准备一个符合特定开发环境要求的覆盖率运行时库的自定义构建。更多详细信息,请参阅自定义运行时库

与链接器命令行集成

将覆盖率运行时库与被测应用程序链接过程集成通常需要修改链接器命令行,在某些情况下,还需要修改执行环境。该部分介绍如何在使用 C/C++test 提供的预建版本时修改链接过程。

Windows Cygwin GNU GCC 编译器的静态库:

  1. 在构建脚本中找到链接器命令行
  2. 修改构建脚本,从而在链接器命令行中某处指定覆盖率运行时库——最好在所有目标文件之后。

Microsoft Visual C++ 编译器的动态链接库:

  1. 在构建脚本中找到链接器命令行
  2. 修改构建脚本,从而在链接器命令行中某处指定覆盖率运行时库——最好在所有目标文件之后。例如:

    $(LXX) $(PRODUCT_OBJ) $(OFLAG_EXE)$(PROJ_EXECUTABLE) $(LXXFLAGS) $(SYSLIB) $(EXECUTABLE_LIB_LXX_OPTS) <INSTALL_DIR>/bin/engine/coverage/runtime/lib/cpptest.lib

  3. 确保将 lib 目录的路径添加到 PATH 环境变量,以便在启动被测程序时能够定位该库。也可以考虑将 cpptest.dll(或 cpptest64.dll)文件复制到与可执行文件所在的目录,或者复制到在被测应用程序启动期间为动态链接库扫描的其他位置。

Linux GNU GCC 编译器的共享库:

  1. 在构建脚本中找到链接器命令行
  2. 修改构建脚本,从而在链接器命令行中某处指定覆盖率运行时库——最好在所有目标文件之后。例如:

    $(LXX) $(PRODUCT_OBJ) $(OFLAG_EXE)$(PROJ_EXECUTABLE) $(LXXFLAGS) $(SYSLIB) $(EXECUTABLE_LIB_LXX_OPTS) -L <INSTALL_DIR>/bin/engine/coverage/runtime/lib -lcpptest
    请注意是否已添加 -L-lcpptest 选项。

  3. 确保将 lib 目录的路径添加到 LD_LIBRARY_PATH 环境变量中,允许被测可执行文件找到共享库的路径。

自定义运行时库

出现以下情况时,可能需要自定义运行时库:

  • 需要不同形式的二进制文件
  • 启用用于结果传输的非默认通信通道
  • 安装用于结果传输的通信通道的自定义实现
  • 启用多线程应用程序的非默认支持
  • 安装多线程应用程序支持的自定义实现
  • 多个插桩的二进制文件写入同一个覆盖率日志文件

库源代码结构

运行时库源代码随 C/C++test 一起提供,位于 [INSTALL_DIR]/bin/engine/coverage/runtime 目录中。下表提供了该结构的描述: 

Component说明
include

包含库头文件的目录。
include/cpptest.h - 库公共接口
include/cpptest/* - 库私有接口
include 目录的内容不是为环境特定的修改而设计的。

src

包含库源代码的目录。
src/cpptest.c - 运行时库的主要和唯一源文件
该文件是为修改和自定义而设计的。

Makefile为构建运行时库提供的基本 Makefile。
target包含一组 Makefile 包含文件的目录,这些文件具有编译器特定的选项,用于为主流的开发环境准备运行时库构建。
channel包含一组 Makefile 包含文件的目录,这些文件具有支持的通信通道的配置。

切换通信通道支持

运行时库支持通过各种通信通道收集数据。使用的通信通道取决于开发环境。在大多数情况下,可以将结果存储在一个或多个文件中,但在其他情况下则可能需要使用 TCP/IP 套接字或 RS232 传输。在 cpptest.c 库源文件编译过程中,可以设置专用的宏值来启用特定的通信通道。将 -D<MACRO> 添加到编译命令行中设置该值。下表提供了通信通道控制宏的完整列表:  

通道说明
CPPTEST_NULL_COMMUNICATION空实现。启用后,将不会发送任何结果。适用于初始测试构建和调试。
CPPTEST_FILE_COMMUNICATION

基于文件的实现。使用 ANSI C 文件 I/O 接口。启用后,结果将会写入本地驱动器文件。

还提供了以下附加配置宏:

CPPTEST_LOG_FILE_NAME:结果文件的名称;默认 cpptest_results.clog

CPPTEST_LOG_FILE_APPEND:创建新的结果文件或追加到现有的结果文件。默认值为 1 -> append,也可选择 0 -> create new

CPPTEST_SPLIT_FILE_COMMUNICATION

基于文件的实现。使用 ANSI C 文件 I/O 接口。启用后,结果将会写入一系列本地驱动器文件。

可以使用以下宏配置此通道:

CPPTEST_LOG_FILE_NAME:文件系列中第一个结果文件的名称;默认值为 cpptest_results.clog。其他文件将按顺序命名,例如,cpptest_results.clog.0001

系列中的所有文件都放在同一个目录中。

CPPTEST_MAX_ALLOWED_NUMBER_OF_BYTES_PER_FILE:指定系列中一个文件的最大大小;默认值为 20 亿字节(2 GB)。

CPPTEST_UNIX_SOCKET_COMMUNICATION

基于 TCP/IP 套接字的实现。使用 POSIX API。启用后,结果将发送到指定的 TCP/IP 端口。提供以下附加配置宏:

CPPTEST_LOG_SOCKET_HOST:指定主机 IP 地址字符串

CPPTEST_LOG_SOCKET_PORT:指定端口号

CPPTEST_GETHOSTBYNAME_ENABLED:如果设置为 1,则可以通过域名指定主机(要求有 gethostbyname 函数)

CPPTEST_WIN_SOCKET_COMMUNICATION同上,使用 Windows API。
CPPTEST_UNIX_SOCKET_UDP_COMMUNICATION同上,基于 UDP 的实现。
CPPTEST_RS232_UNIX_COMMUNICATION

基于 RS232 的实现。使用 POSIX API。启用后,通过指定的 RS232 系统设备发送结果。提供以下附加配置宏:

CPPTEST_RS232_DEVICE_NAME: 系统设备名称

CPPTEST_RS232_BAUD_RATE:传输波特率

CPPTEST_RS232_BYTE_SIZE:字节大小

CPPTEST_RS232_PARITY:奇偶校验控制

CPPTEST_RS232_STOP_BIT:停止位使用

CPPTEST_RS232_TIMEOUT:传输超时值

CPPTEST_RS232_WIN_COMMUNICATION同上。使用 Windows API。
CPPTEST_RS232_STM32F103ZE_COMMUNICATION基于 STM32F103x USART 的实现。使用 STM Cortex 库接口(需要 ST/STM32F10x/stm32f10x.h 头文件)
CPPTEST_HEW_SIMIO_COMMUNICATIONRenesas HEW 模拟器具体实现。
CPPTEST_LAUTERBACH_FDX_COMMUNICATION基于 Lauterbach TRACE32 的实现(使用 FDX)
CPPTEST_ITM_COMMUNICATION基于 ARM CoreSight ITM 单元的通信。需要 CMSIS 头文件。
CPPTEST_CUSTOM_COMMUNICATION启用用于自定义实现的空模板

如果使用提供的 Makefile 构建覆盖率运行时库,则可以使用 [INSTALL_DIR]/bin/engine/coverage/runtime/channel 目录中提供的其中一个 make 配置文件。

安装自定义通信通道的支持

如果没有适合您的开发环境的通信通道实现,则可以提供自定义实现。以下说明描述了如何自定义运行时库,使其使用通信通道的自定义实现: 

  1. 复制 [INSTALL_DIR]/bin/engine/coverage/runtime/src/cpptest.c 并打开文件进行编辑。

  2. 找到 1.14“Custom Communication Implementation”部分。
    Custom Communication Implementation 部分包含四种不同方法的空模板:

    函数说明
    void cpptestInitializeStream(void)该函数负责初始化通信通道,例如创建并连接套接字或初始化 UART 设备。
    void cpptestFinalizeStream(void)该函数负责终止通信通道。例如,它可能负责关闭 TCP/IP 套接字。

    int cpptestSendData(const char *data, unsigned size)

    该函数负责从数据缓冲区发送大小字节。
    void cpptestFlushData(void)该函数负责清除数据。它的含义取决于特定的传输类型。该函数在一些实现中的应用可能受限,在这种情况下,该函数应该留空。
  3. 为符合您的环境要求的方法提供实现。
  4. 编译 cpptest.c 时,将以下宏定义添加到编译命令行:
    -DCPPTEST_CUSTOM_COMMUNICATION
  5. 如果生成的目标文件无法满足要求,您可以根据需要进一步处理该文件(例如,创建共享库)。

切换多线程 API 支持

运行时库包含对多线程应用程序的支持。支持 POSIX、Windows 和 VxWorks API。您可以在 cpptest.c 编译时通过将 -D<MACRO> 添加到编译命令行来启用对特定多线程 API 的支持。下表提供了多线程 API 支持控制宏的完整列表:

说明
CPPTEST_NO_THREADS空实现。覆盖率运行时不与多线程应用程序一起使用
CPPTEST_WINDOWS_THREADSWindows 多线程 API 实现
CPPTEST_UNIX_THREADSPOSIX 多线程 API 实现
CPPTEST_VXWORKS_THREADSVxWorks 多线程 API 实现

安装自定义线程 API 的支持

如果将 C/C++test 的覆盖率引擎与不使用支持的多线程 API 的多线程应用程序使用,您可以自定义运行时库,从而与您的多线程 API 一起使用。需要完成以下步骤:

  1. 复制 [INSTALL_DIR]/bin/engine/coverage/runtime/src/cpptest.c 并打开文件进行编辑。

  2. 找到 2.5“Custom Multithreading Implementation”部分。
    Custom Multithreading Implementation 部分包含两种不同方法的空模板:

    函数说明
    static int cpptestLock(void)该函数确保覆盖率工具运行时库内部的同步操作。如果一个线程锁定了对运行时库服务的访问,这意味着一个原子操作正在进行,其他线程不可以使用运行时库服务。锁定释放后,其他线程才可以使用运行时库服务
    static int cpptestUnlock(void)解除对运行时库服务的锁定。
  3. 为符合您的环境需求的方法提供实现。

  4. 编译 cpptest.c 时,将以下宏添加到编译命令行:
    -DCPPTEST_CUSTOM_THREADS

  5. 如果生成的目标文件无法满足要求,您可以根据需要进一步处理该文件(例如,创建共享库)。

多个插桩的二进制文件写入同一个覆盖率日志文件

当同一个覆盖率日志文件(.clog)被并行运行的多个插桩的二进制文件使用时,需要在运行时库中启用多进程支持。

要启用多进程支持,编译 cpptest.c 时将以下宏添加到编译命令行:
"-DCPPTEST_MULTI_PROCESSES_LOG=1"

构建运行时库

C/C++test 附带了一个简单的 Makefile(请参阅库源代码结构),可简化构建运行时库的过程。然而,在多数情况下不需要提供的 make 文件,因为源代码已经针对构建过程进行了优化。唯一一个始终需要执行的步骤是编译主要的 cpptest.c 源文件。对所产生的目标文件的任何额外处理都取决于特定的开发环境及要求,例如将运行时库作为共享库提供。

使用提供的 Makefile 构建运行时库

  1. 复制 <INSTALL_DIR>/bin/engine/coverage/runtime 到本地目录

  2. 如果需要修改编译标志(例如,添加交叉编译器或定义来执行运行时库重新配置),应在目标子目录中提供一个新的 make 配置文件。为了方便起见,您可以复制一个现有的目标配置文件,然后修改其内容以满足您的需要。
  3. 调用以下命令行创建包含单个对象 cpptest.<OBJ_EXT>build 子目录,可用于链接插桩的应用程序。

    make TARGET_CFG=<target config file name> CHANNEL_FILE=<channel config file name>

    您的命令行可能类似于:

    make TARGET_CFG=gcc-static.mk CHANNEL_FILE=channel/unix-socket.mk

    或者,您可以提供通道类型:

    make TARGET_CFG=gcc-static.mk CHANNEL_TYPE=unix-socket
  4. 如果需要通过共享库、动态链接库或任何其他类型的二进制文件链接覆盖率运行时库,则需要自定义 Makefile 或设置自定义构建。

运行时库用户构建

要设置覆盖率运行时库的用户构建,请执行以下步骤:

  1. 将 <INSTALL_DIR>/bin/engine/coverage/runtime/src/cpptest.c 中的 cpptest.c 文件复制到您的首选位置

  2. 根据自定义运行时库中的说明引入所需自定义设置。
  3. 设置您需要的构建系统(例如, IAR Embedded Workbench 项目或任何其他类型的源代码构建器)。
  4. 修改编译标志以包含编译器的 include 标志(通常使用 -I),并使用以下值:-I <INSTALL_DIR>/bin/engine/coverage/runtime/include

  5. 添加所需的配置定义(通常使用 -D)例如:
    -DCPPTEST_FILE_COMMUNICATION -DCPPTEST_NO_THREADS
  6. 调用命令运行构建器(例如,在 IDE 中选择构建命令)。
  7. 找到生成的目标文件,并使用该文件链接插桩的应用程序。

代码覆盖率故障排查

如何显示包括错误和警告信息的覆盖率工作空间诊断数据?

覆盖率工作空间保留了插桩代码和相应的静态覆盖率数据,以及进行代码插桩时生成的一些日志和配置文件。使用 -status 选项可以显示从覆盖率工作空间收集的诊断数据,包括错误和警告信息、文件数量等。或者,还可以用 -status-verbose 显示更详细的信息。

默认情况下,将扫描位于当前目录中的覆盖率工作空间以获取诊断数据。您可以使用 -workspace 选项配置不同的工作空间位置。

示例

cpptestcc -status
cpptestcc -status -workspace /path/to/workspace

cpptestcc -status-verbose
cpptestcc -status-verbose -workspace /path/to/workspace

如何将覆盖率工作空间的诊断数据发送给 Parasoft 支持?

您可以使用 -techsupport 选项为覆盖率工作空间创建一个技术支持包。这会创建一个包含所有诊断数据的 .zip 文件,其中包括日志文件和无法成功插桩的文件的预处理源代码。

默认情况下,将扫描位于当前目录中的覆盖率工作空间以获取诊断数据。您可以通过 -workspace 选项配置其他工作空间位置。

示例

cpptestcc -techsupport
cpptestcc -techsupport -workspace /path/to/workspace

如果在为应用程序覆盖率生成报告时找不到某个或多个源文件怎么办?

生成覆盖率报告时,C/C++test 要求为代码覆盖率插桩的所有文件都能在原始位置找到。如果 C/C++test 在原始位置找不到文件,覆盖率报告就会不完整。在该情况下,C/C++test 会显示一条警告消息,包含缺少的文件列表。

若想要生成的覆盖率报告中包含已移动到其他位置的文件的覆盖率数据,则可以使用 CPPTEST_COVERAGE_SRC_ROOT 环境变量将原始路径映射到本地(当前)路径:

CPPTEST_COVERAGE_SRC_ROOT=/original/path1=/local/path1;/original/path2=/local/path2;...

可以在原始路径中使用允许的通配符“*”。例如:

CPPTEST_COVERAGE_SRC_ROOT=/*/path=/local/path

还可以在列表文件(*.lst)中指定路径映射列表,并将其位置设置为值。例如:

CPPTEST_COVERAGE_SRC_ROOT=/path/mapping.lst

*.lst 文件中的每一项都被视为一个单独的条目。

示例

在下面的示例中,对 foo.cpp 文件进行覆盖率插桩并移动到其他位置。

  • 插桩文件的原始位置: /home/server/project-123/foo.cpp
  • 插桩文件的当前位置(生成报告时的位置): /home/devel/project/foo.cpp

生成包含 foo.cpp 文件覆盖率数据的覆盖率报告:

  1. 使用 CPPTEST_COVERAGE_SRC_ROOT 环境变量定义路径映射,例如:
    > export CPPTEST_COVERAGE_SRC_ROOT=/home/server/project-123=/home/devel/project
  2. 生成覆盖率报告。

如果代码不能进行代码覆盖率插桩,如何使构建失败?

默认情况下,当无法成功进行文件插桩时,将在构建中使用该文件的原始(未插桩)版本并显示警告。若要在某个或多个源文件无法进行覆盖率插桩时使构建失败,可使用 -disable-auto-recovery-mode 选项。

示例

cpptestcc -disable-auto-recovery-mode [. . .]

如何收集构建期间经过多次编译的文件的覆盖率?

默认情况下,C/C++test 会在一次构建中为每个源文件的一次编译存储覆盖率数据。因此,当出现一次构建中多次编译源文件的罕见情况时,C/C++test 仅存储该源文件最后一次编译的覆盖率数据。这可能会导致覆盖率报告不完整,并在生成报告时发出警告:“由于当前工作空间中缺少有关代码结构的某些信息,因此覆盖率报告可能不完整。”要为同一源文件存储覆盖率数据的多个变体(构建期间每次编译一个变体),可使用 -coverage-data-variants 选项。

确保同一源文件的不同编译不会引入冲突代码(例如,同一函数的不同变体)——这种情况下无法支持。

示例

cpptestcc -coverage-data-variants [. ..]
  • No labels