【问题标题】:Is it possible to check if code coverage has increased after a test是否可以在测试后检查代码覆盖率是否增加
【发布时间】:2014-11-06 04:31:14
【问题描述】:

我正在使用 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 文件并查看它们是否已更改。不幸的是,这不是一个可靠的解决方案,因为我正在并行运行随机测试,我希望“增加覆盖率”测试是原子的——项目很大,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

【问题讨论】:

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


    【解决方案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
    

    每次覆盖率提高时,此二进制文件都会打印“覆盖率增加”。

    【讨论】:

      【解决方案2】:

      可以在程序运行时/退出之前从正在运行的程序中读取 gcov 结构。如果您明天有兴趣,将在电话中添加详细信息。

      【讨论】:

      • 我不确定如何使用这些额外信息。我的用例是检测与前一批测试相比,程序的运行是否增加了覆盖率。我看不到仅通过查看当前程序的 gcov 数据来检测这一点的方法。如果这是可能的,我绝对感兴趣。
      • @DejanJovanović 您可以在每次运行时将 gcov 数据写入文件,然后使用单独的脚本计算代码覆盖率的“增量”。我对 gcov 本身一无所知,所以这只是一个概念性建议。
      • @Code-Apprentice 当我并行运行测试时,这个解决方案并不令人满意。当我检查 test1 的文件以计算增量时,其他一些 test2 可能会增加覆盖率,我会为 test1 计算它。这就是我在问题中所说的“原子”的意思。
      猜你喜欢
      • 1970-01-01
      • 2010-09-07
      • 2020-10-09
      • 2019-02-24
      • 2019-06-20
      • 1970-01-01
      • 2019-03-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多