LCOV/GCOV分支覆盖范围,C++生成分支机构

gha*_*ndi 19 c++ code-coverage gcov lcov

我们正在使用LCOV/GCOV来为我们的项目提供测试覆盖率.最近我们尝试另外启用分支覆盖.但看起来,这只是不会产生我们从高级开发人员视图中预期的结果.

在C++中使用branch-coverage可以在整个地方分支报表.我们怀疑(正如搜索问题所示)主要是异常处理代码创建这些"隐藏分支".GCOV/LCOV似乎没有跳过这些.

我创建了一个小测试项目来显示问题:https://github.com/ghandmann/lcov-branch-coverage-weirdness

目前我们使用的是Ubuntu 16.04.有:

  • gcc v5.4
  • lcov&genhtml v1.12

我们的生产代码是在启用c ++ 11的情况下构建的.最小的例子不是在启用c ++ 11的情况下构建的,但是当我们尝试使用所有不同的选项(c ++标准,优化-fno-exceptions)时,我们没有得到可通过的结果.

有人有想法吗?的窍门?我们使用的是错误的方式吗?这是否 - 如其他地方所述 - 真正预期的行为?

更新:

正如gcc-help邮件列表中指出的那样,这些"隐藏分支"由于异常处理而发生.因此,将-fno-exceptions开关添加到gcc会为"简单"程序产生100%的分支覆盖率.但是当禁用异常时,gcc拒绝编译实际使用异常的代码(例如try-catch,throw).因此,对于实际生产代码,这不是一种选择.看起来,在这种情况下,你必须简单地宣布约50%的覆盖率为新的100%.;)

max*_*zig 12

问题是GCC还记录了每一行的分支信息,其中由于某些抛出异常而导致范围退出(例如,在具有GCC 6.3.1和lcov 1.12的Fedora 25上).

此信息的价值有限.分支覆盖数据的主要用例是复杂的if语句,它具有如下所示的多分词逻辑表达式:

if (foo < 1 && (bar > x || y == 0))
Run Code Online (Sandbox Code Playgroud)

假设您有兴趣验证您的测试套件是否也涵盖了bar > x案例,或者您是否只有测试用例y == 0.

为此,分支覆盖数据收集和lcov的genhtml可视化非常有用.对于简单的if语句,如

if (p == nullptr) {
  return false;
}
return true;
Run Code Online (Sandbox Code Playgroud)

您不需要分支覆盖数据,因为您通过查看以下行的覆盖范围来查看分支是否被采用.

其输入genhtml是以lcov相对简单的文本格式生成的(参见geninfo(1)).因此,您可以对其进行后处理,以便BRDA:删除以if语句开头且不属于if语句的所有行.例如filterbr.py,参见哪个实现了这种方法.另请参阅gen-coverage.py其他lcov/genhtml处理步骤以及将生成的跟踪文件上载到codecov示例项目(codecov不使用genhtml但可以导入lcov跟踪文件并显示分支覆盖数据).

(非)替代

  • 当您的C++代码不使用任何异常时,禁用异常只是一个选项
  • 用类似的东西进行编译-O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls会减少记录的分支覆盖数据的数量,但不会太多
  • 锵支持gcov的风格覆盖集合,但也实现了不同的方法,被称为"基于源的代码覆盖率"(编译-fprofile-instr-generate -fcoverage-mapping和后处理同llvm-profdatallvm-cov).但该工具链不支持分支覆盖数据(截至2017-05-01).
  • 默认情况下,lcov + genhtml不生成分支覆盖数据 - 有时你并不真正需要它(见上文),因此,它是一个禁用它的选项(参见--rc lcov_branch_coverage=0--no-branch-coverage)


小智 8

GCC 将添加一堆异常处理的东西。特别是当你进行函数调用时。

您可以通过添加-fno-exceptions -fno-inline 到您的构建来解决此问题。

我应该补充一点,您可能只想打开这些标志进行测试。所以像这样:

g++ -O0 --coverage -fno-exceptions -fno-inline main.cpp -o test-coverage 
Run Code Online (Sandbox Code Playgroud)


Aru*_*run 6

有一个 PR 正在进行中,可以解决这些限制。https://github.com/linux-test-project/lcov/pull/86

本文解释了实施背后的理论。

结果