是否可以检查测试后代码覆盖率是否增加

时间:2014-09-12 04:29:58

标签: c++ c gcc code-coverage gcov

我正在使用gcc中的gcov覆盖支持来分析大型项目的覆盖范围。我也在运行随机测试以尝试增加覆盖率。理想情况下,当我生成测试时,如果它增加任何覆盖率指标,我想保存它。

有什么可行的方法呢?

例如,假设我们有类似

的内容
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[]) {
  int x, y;
  x = atoi(argv[1]);
  y = atoi(argv[2]);
  if (x < 0 || y < 0) {
    x = -x;
    y = -y;
  } 
}

我用

编译
gcc -fprofile-arcs -ftest-coverage -o test test.c

有没有办法检测覆盖范围是否增加,并保存相应的输入? 例如使用

之类的东西
while [ 1 ];
do
  ./gen_test.sh > input.txt
  ./test < input.txt
  if [ COVERAGE_INCREASED ] then save input.txt fi
done;

运行gcov生成报告需要花费大量时间,所以我更愿意知道程序退出时覆盖率是否会增加。

我知道我可以查看.gcda文件并查看它们是否已更改。不幸的是,这并不是一个可靠的解决方案,因为我并行运行随机测试,我宁愿选择&#34;增加覆盖范围&#34; test是原子的 - 项目很大,gcda /源文件数量很大。

我假设如果这样的话可能,我需要在我的main中添加一些特定于gcc的代码,但我不知道在哪里看。

尝试1 :我从源代码(4.6.3)编译了gcc并查看了gcov代码。当覆盖测试程序退出时,它会运行一些合并功能来更新文件中已有的覆盖数据。我已经更新了其中一个合并函数(libgcov.c),只是在覆盖率已经积极更新的情况下打印出来,这似乎符合我的目的。

/* The profile merging function that just adds the counters.  It is given
   an array COUNTERS of N_COUNTERS old counters and it reads the same number
   of counters from the gcov file.  */
void
__gcov_merge_add (gcov_type *counters, unsigned n_counters)
{
  gcov_type prev;
  for (; n_counters; counters++, n_counters--) {
    prev = gcov_read_counter ();
    if (prev == 0 && *counters > 0) {
      fprintf(stdout, "Coverage increase by add");
    }
    *counters += prev;
  }
}

线路覆盖似乎正在做正确的事情,但它缺少分支覆盖范围。此外,它没有捕获初始运行,但这不是一个问题。

运行上面的示例,我得到了

./test 0 0
./test -1 0
Coverage increase by add
./test 0 -1

2 个答案:

答案 0 :(得分:1)

我通过在代码中重载gcc的add方法解决了这个问题。为了更好的做法,为了获得gcov_type,您可以安装gcc-4.6-plugin-dev包。

现在,上述程序可以改编为

#include <stdio.h> 
#include <stdlib.h>

#include <gcc-plugin.h>
#include <basic-block.h>

gcov_type __gcov_read_counter (void);

void
__gcov_merge_add (gcov_type *counters, unsigned n_counters)
{
  gcov_type prev;
  for (; n_counters; counters++, n_counters--) {
    prev = __gcov_read_counter ();
    if (prev == 0 && *counters > 0) {
      fprintf(stdout, "Coverage increased\n");
    }
    *counters += prev;
  }
}

int main(int argc, char* argv[]) {
  int x, y;
  x = atoi(argv[1]);
  y = atoi(argv[2]);
  if (x < 0 || y < 0) {
    x = -x;
    y = -y;
  } 
}

编译上面需要一些额外的包含

gcc -I/usr/lib/gcc/x86_64-linux-gnu/4.6/plugin/include \
    -fprofile-arcs -ftest-coverage \
    -o test test.c

这个二进制文件将打印打印件&#34;覆盖率增加&#34;每次覆盖都有所改善。

答案 1 :(得分:0)

可以在运行程序运行/退出之前从运行程序中读取gcov结构。如果您明天有兴趣,请立即通过手机添加详细信息。