覆盖率工具gcov,lcov实践记录

背景

本文记录的是gcov和lcov在统计一个分布式数据库的代码覆盖率过程中遇到的问题。

介绍

*gcov是一个测试代码覆盖率的工具,随着gcc一起发布,不需要进行特别安装;而lcov是配合gcov生成覆盖率文件的工具,需要单独安装。
*lcov是基于源码安装的,下载源码解压后make install即可安装。在安装完成后,使用lcov -v可以正确查询到安装的lcov版本。

使用流程

1.首先,在使用前配置各个子目录下的Makefile.am文件,加入编译开关:
if COVERAGE:
CXXFLAGS+=-fprofile-arcs -ftest-coverage
AM_LDFLAGS+=-lgcov
endif

2.之后,使用如下编译命令进行编译:

sh build.sh init
./configure --perfix=~/build --with-test-case=no --with-coverage=yes
make -j all -C src/
make install

注意:编译过程中,不能加入–with-release参数;若加入该参数可能会导致产生的覆盖率文件只统计构造函数,而忽略其他函数,原因暂时未知。

3.编译完成后,使用deploy跑测试程序,并统计测试覆盖率,命令大体如下:

lcov --rc lcov_branch_coverage=1 -c -o ~/info/xxx.info -d .

4.基于统计出的覆盖率info文件,我们准备对其进行汇总分析,获得代码覆盖率的完整信息。但是在后续统计中发现,一些必然会跑到的入口函数在覆盖率文件中并没有被统计到,所以展开这次调查。

遇到的问题

1.Can’t locate PerlIO/gzip.gm in @INC ,该错误是在使用lcov工具收集info文件时产生的,使用的命令为:

lcov --rc lcov_branch_coverage=1 -c -o ~/info/xxx.info -d .

这个错误是由于缺少PerlIO/gzip.gm和JSON.pm包导致的,找到对应的包安装即可。(本文是在离线环境下进行的,所以部分依赖没有一并安装)

2.覆盖率统计文件info中只统计了构造函数,其他函数都没有被统计
1)起初,发现部分必然会被覆盖到的函数在info文件的统计信息中值为0,代表该函数未被覆盖,所以基于这些函数入手,开始追踪这些函数的上层逻辑有无覆盖;
2)在追踪上层函数时发现,这几个函数都会进入一个名为xxx.so的动态链接库,于是猜想可能是gcov经过动态链接库后无法追踪到下层函数,于是写了一个简单的c程序进行验证,结论是gcov可以经过.so动态链接库追踪到下层函数,但是.so内的函数gcov并不进行统计。验证过程记录如下:
a.验证过程中使用了三个.cpp文件和一个头文件,分别为test.cpp,add.cpp,sub.cpp,head.h具体内容如下:
test.cpp:

#include <stdio.h>
#include "head.h"int main() {int a = 0;int b = add(a);printf("main is %d\n", b);return 0;

add.cpp:

#include <stdio.h>
#include "head.h"int add(int a) {a += 1;printf("add is %d\n", a);a = sub(a);return a;

sub.cpp:

#include <stdio.h>
#include "head.h"int add(int a) {a -= 1;printf("sub is %d\n", a);return a;

b.将add.c文件编译为add.so文件,编译指令如下:

gcc -fPIC -shared -o add.so add.c

c.将所有文件编译,并在编译时增加gcov相关的编译选项,编译命令如下:

gcc -fprofile -ftest-coverage -o test test.c sub.c head.h ./add.so

d.编译完成后运行可执行文件test,运行后会生成gcda文件,使用gcov指令运行gcda文件即可在后缀为.gcov文件中看到覆盖率信息。在生成gcda文件时可以看到,动态链接库对应的add.gcda文件并没有生成。整个过程的编译命令如下:

./test
gcov test.gcda

3)到此,自底向上追踪上层函数确定问题的方法已经不能再继续,因此,选择从上而下的方式,选择一个sql语句,追踪sql语句完整的执行流程,以便找到问题所在。在本次查找问题中选择的是insert语句,通过debug加看源码的方式,对insert语句进行追踪,从词法解析,语法解析,逻辑计划产生,物理计划产生以及物理计划的执行整个流程,在跟踪过程中发现即便是最外层的函数,在覆盖率统计时也不会覆盖到。基于此,我们不再细究代码层面的问题,而是将调查重心转到数据库源码编译的方式gcov工具的使用方法受否有错误等问题上。

4)初始的数据库源码编译方式如下:

./configure --perfix=~/build --with-test-case=no --with-coverage=yes --with-release=yes

我们尝试修改–with-release编译选项的值,将其分别设置为yes,no,结果没有发生变化;但是当我们把–with-release编译选项去掉后,在部分覆盖率文件中出现了除了构造函数以外的函数被覆盖到的情况(原因未知),这说明–with-release这个编译选项可能是覆盖率文件不完整的原因。修改后的编译源码的方式:

./configure --perfix=~/build --with-test-case=no --with-coverage=yes

5)经过多次验证,在去掉–with-release编译选项后,确实会产生部分正确的覆盖率文件,但是仍然有部分覆盖率文件时错误,其中只有构造函数才被统计到。

6)可以预见,还存在某些因素影响覆盖率文件的生成。在反复实验过程中,我们发现,杀死进程的方式会影响覆盖率文件的生成kill -9 杀死进程会导致****程序直接终止,没有将gcov守护进程所统计的信息添加到覆盖率文件中,所有导致覆盖率文件不生成在使用kill -15杀死进程后,在多数情况下会产生覆盖率文件,但是有时还是不产生覆盖率文件,于是对gcov刷新覆盖率文件的方式进行了了解。

7)在gcov中,守护进程之后在完全执行完成后,在返回结果进入用户代码 main 函数之前调用 gcov_init 内部函数初始化统计数据区,并将gcov_exit 内部函数注册为 exit handlers。用户代码调用 exit 正常结束时,gcov_exit 函数得到调用,其继续调用 __gcov_flush 函数输出统计数据到 *.gcda 文件中;

8)在gcov原理中,__gcov_flush函数是将数据写入.gcda覆盖率文件的核心,所以考虑在执行kill 进程时,主动调用__gcov_flush函数,将覆盖率信息写入文件中

9)本次实验所用的数据库源码只针对kill -15做了处理,因此在kill -15命令杀死进程过程中主动调用__gcov_flush函数,具体细节如下:
a) 数据库每次启停的服务包括rs,cs,ups,ms,通过跟踪kill -15 不同进程的流程发现,rs和ms时通过同一个方法启停服务,ups和cs是通过同一个方法启停服务,于是在两个启停服务的方法中加入了__gcov_flush函数。所加代码如下:

# 在对应的.c文件头部,加入引用
extern "C" void __gcov_flush(void);
# 在对应的方法体中加入__gcov_flush方法
__gcov_flush();

b)为了不影响原来程序的编译,在加入__gcov_flush函数的地方引入宏(宏已经在源码中定义过),判断是否需要编译相应的代码行,如下:

# 在对应的方法体中加入__gcov_flush方法
# ifdef COVERAGE
__gcov_flush();
# endif
  1. 至此,整个问题已解决。

覆盖率工具gcov,lcov实践相关推荐

  1. 温故而知新:gtest单元测试工具和lcov覆盖率统计工具的结合使用

    一.简介   之所以叫温故而知新,是因为将这两个工具结合起来作为单元测试工具的想法在上一个项目中应用了,好像还没有人将这两种工具结合使用,或者没有写成博客供大家参考,现在重新温习下将想法写下来. gt ...

  2. Linux平台代码覆盖率测试工具GCOV的前端工具LCOV简介

    本博客 http://blog.csdn.net/livelylittlefish 贴出作者(三二一@小鱼)相关研究.学习内容所做的笔记,欢迎广大朋友指正! Content 1. Lcov是什么? 2 ...

  3. Android 增量代码测试覆盖率工具实践

    当业务快速发展,新业务不断出现,开发同学粗心的情况下,难免会出现少测漏测的情况,如何保证新增代码有足够的测试覆盖率?当一段正常的代码,开发却修改了,测试人员没有测试其功能,如果保证能够发现? 所以代码 ...

  4. iOS 覆盖率检测原理与增量代码测试覆盖率工具实现

    背景 对苹果开发者而言,由于平台审核周期较长,客户端代码导致的线上问题影响时间往往比较久.如果在开发.测试阶段能够提前暴露问题,就有助于避免线上事故的发生.代码覆盖率检测正是帮助开发.测试同学提前发现 ...

  5. C语言代码覆盖率测试软件,代码覆盖率检测工具GCOV

    一.关于gcov工具 gcov伴随gcc 发布.gcc编译加入-fprofile-arcs -ftest-coverage 参数生成二进制程序,执行测试用例生成代码覆盖率信息. 1.如何使用gcov ...

  6. ios 单元测试覆盖率怎么查看_iOS 覆盖率检测原理与增量代码测试覆盖率工具实现...

    背景 对苹果开发者而言,由于平台审核周期较长,客户端代码导致的线上问题影响时间往往比较久.如果在开发.测试阶段能够提前暴露问题,就有助于避免线上事故的发生.代码覆盖率检测正是帮助开发.测试同学提前发现 ...

  7. linux下测试qt程序代码覆盖率(gcov,lcov)

    代码覆盖率是指:在测试中,所执行的源代码占全部源代码的比例. 1.linux系统下可以用使用Qtcreator 自带的单元测试工具框架QTestlib进行测试. https://blog.csdn.n ...

  8. Java覆盖率工具jacoco,Cobertura

    最近研究Java覆盖率工具,了解到了jacoco,Cobertura这两款,但是Cobertura没有维护了,不支持新的java语法.下面简单介绍一下这两个工具的使用. 简介 市场上主要代码覆盖率工具 ...

  9. 《DevOps实战:VMware管理员运维方法、工具及最佳实践》——2.3 配置管理

    本节书摘来自华章计算机<DevOps实战:VMware管理员运维方法.工具及最佳实践>一书中的第2章,第2.3节,作者:小特雷弗 A. 罗伯茨(Trevor A. Roberts Jr.) ...

最新文章

  1. centos7下安装intel Media Server Studio记录
  2. FFmpeg将Jpeg 编码到视频中
  3. Leetcode 96. 不同的二叉搜索树 解题思路及C++实现
  4. 1139 First Contact (30 分)【难度: 一般 / 知识点: 模拟】
  5. Mysql报错130_mysql 突然报错,连接不上
  6. STM32H743+Cube-Keil上移植RTX5实时系统
  7. mysql 数据查询优化_优化MySQL数据库查询的三种方法
  8. 如何重新定义云数据中心的资源利用率
  9. 大数据分析平台由哪些部分组成
  10. 如何检索文献系列:检索文献窥秘
  11. python--django基础篇(创建项目,模型类,迁移,测试数据库操作)
  12. 2021CCF推荐国际学术会议A类及相关领域介绍
  13. 尔雅大学计算机基础知识点,超星尔雅_大学计算机基础_章节测试答案
  14. 优酷视频kux格式转mp4格式
  15. 获取QQ好友列表、QQ分组信息、QQ群成员数据接口实现
  16. 什么是初效过滤器_初效过滤器作用与原理
  17. SDCC 2017·深圳站八大不容错过的理由
  18. 2021年数学建模国赛C题思路
  19. 高效人士的七个好习惯
  20. cmmi3级认证有什么要求?参与人员都有哪些

热门文章

  1. Java 使用Redis实现秒杀功能
  2. hackerrank(python)
  3. Lyft抢跑Uber上市! 打响硅谷独角兽上市潮第一枪!
  4. JavaWeb开发框架——MyBatis
  5. 便签存储在哪个文件夹,Windows 7便笺保存位置
  6. 简单c语言程序求和,C语言程序设计100例之(23):数列求和
  7. 中值滤波算法的Verilog实现
  8. Java 代码实现一个标准输出的进度条,知识点你知道但并不一定会用
  9. WebRTC Native M96 SDK接口封装--enableLoopbackRecording启用声卡采集,声卡播放的声音合到本地音频流发送远端
  10. matlab实现谱质心算法