使用gcov和lcov统计代码覆盖率

gcov简介

gcov是gcc的内置工具,是进行代码运行的覆盖率统计的工具,可以分析程序中运行过的代码和未经运行的代码。测试人员可以借助这个工具对整个测试过程的充分性进行评估。俗话说:覆盖率很充分不能说明绝对没有漏测,但是覆盖率不充分就肯定存在漏测。该工具可以通过覆盖率分析,从而进行更精准的测试。

原理

Gcc中指定-ftest-coverage 等覆盖率测试选项后,gcc会:在输出目标文件中留出一段存储区保存统计数据,在源代码中每行可执行语句生成的代码之后附加一段更新覆盖率统计结果的代码,在最终可执行文件中进入用户代码 main函数之前调用 gcovinit内部函数初始化统计数据区,并将gcovexit内部函数注册为 exit handlers,用户代码调用exit 正常结束时,gcovexit函数得到调用,其继续调用 gcovflush函数输出统计数据到 .gcda 文件中。所以gcov统计覆盖率,需要应用程序是正常退出的,如果是kill掉的。则搜集不到覆盖率统计文件。

gcov统计kernel覆盖率

安装内核源代码:

sudo apt-get source linux-source-4.16.12
cd /usr/src/linux-4.16.12
sudo cp /boot/config-4.16.0-1-amd64 /usr/src/linux-4.16.12/.config

修改.config文件

打开.config中以下配置选项,在.config文件中加入下面的几行即可。

CONFIG_GCOV_KERNEL=y
CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
CONFIG_GCOV_PROFILE_ALL=y
CONFIG_GCOV_FORMAT_AUTODETECT=y

编译安装内核

sudo make oldconfig
sudo make deb-pkg  #编译内核为deb包,存放在上层目录
cd ../
sudo dpkg -i linux-image-4.16.12_4.16.12-2_amd64.deb linux-libc-dev_4.16.12-2_amd64.deb linux-headers-4.16.12_4.16.12-2_amd64.deb #安装内核

使用lcov工具,生成可视化html文件

lcov简介

lcov是什么:
* 是GCOV图形化的前端工具
* 是Linux Test Project维护的开放源代码工具,最初被设计用来支持Linux内核覆盖率的度量
* 基于Html输出,并生成一棵完整的HTML树
* 输出包括概述、覆盖率百分比、图表,能快速浏览覆盖率数据
* 支持大项目,提供三个级别的视图:目录视图、文件视图、源码视图
* 仓库中存在lcov的包,可以直接安装。

安装完成所编译的内核之后,重启系统,进入新编的内核。在本地目录执行下面命令:

sudo lcov --zerocounters #清零计数器
sudo lcov --capture --output-file kernel.info  #捕获当前覆盖状态到文件
genhtml kernel.info #获取HTML输出 

执行完成之后,在当前目录下面打开index.html文件,就可以看到kernel的代码运行覆盖率详细信息了。

gcov统计dde-calendar的运行覆盖率

以统计dde-calendar运行代码覆盖率为例进行探索。
安装dde-calendar源码,需要确保/etc/apt/sources.list中存在src的源:

deb-src http://packages.deepin.com/enterprise camel main contrib non-free

apt-get source dde-calendar
cd dde-calendar
mkdir build
cd build
qmake ../     #在build目录生成Makefile文件。

用户需要修改Makefile文件,在Makefile中添加gcov支持的编译和链接参数。添加参数可以直接手工修改Makefile文件,也可以修改项目自带的.pro文件,让qmake生成的makefile文件就具有相关的参数。
修改.pro文件,添加下面两行,然后在执行上面的qmake ../ 命令。

QMAKE_CXXFLAGS+= -fprofile-arcs -ftest-coverage
LIBS += -fprofile-arcs

使用lcov工具,生成可视化html文件

编译完成之后,在build目录执行生成的可执行文件dde-calendar,在日历界面进行简单的操作。然后退出深度日历。在当前目录执行命令:

  lcov --directory . --zerocounters   # 清零执行计数器
  lcov --directory . --capture --output-file dde-calendar.info 
  genhtml -o results dde-calendar.info   #生成html格式文件在目录results中

使用浏览器打开results目录中的index.html文件。

gcov统计dde-control-center的运行覆盖率

下载dde-control-center的源码,直接从github上拉取。

git clone https://github.com/linuxdeepin/dde-control-center.git
cd dde-control-center

按照README中安装所需要的所有依赖包。
修改目录dde-control-center/src/frame中的CMakeList.txt,添加gcov支持的参数,如下:

set(CMAKE_CXX_FLAGS "-g -Wall  -fprofile-arcs -ftest-coverage")
set(CMAKE_EXE_LINKER_FLAGS "-lcrypt -fprofile-arcs")

然后目录dde-control-center中创建build目录,进入build目录执行命令:

cmake ../ 
make 
cp /src/frame dde-control-center CMakeFiles/dde-control-center.dir/
cd src/frame/CMakeFiles/dde-control-center.dir
./dde-control-center show

打开控制中心之后,在控制中心界面简单操作一段时间,然后再开个终端,在当前目录运行二进制文件dde-control-center (这是因为dde-control-center没有退出函数,再次运行dde-control-center才可以生成.gcda文件)

使用lcov工具,生成可视化html文件

  lcov --directory . --zerocounters   # 清零执行计数器
  lcov --directory . --capture --output-file dde-control-center.info 
  genhtml -o results dde-control-center.info   #生成html格式文见在目录results中

进入目录results,使用浏览器 打开index.html文件。

界面如下:
dde-control-center-gcov
从上面的页面可以看到,代码行数覆盖率是3.0%。函数覆盖率是4.4%。需要关注应用程序的源代码的覆盖率,其依赖库的代码覆盖率不是重点。
点击相关源码目录,可以看到每个代码文件的具体的行覆盖率和行数覆盖率。
dde-control-center-gcov-2

为了方便体验,我把kernel,dde-calendar,dde-control-center的示例代码覆盖率结果都放在了10.0.12.150上面了,可以直接点击下面的链接访问:
kernel:kernel 代码覆盖率
dde-calendar:dde-calendar代码覆盖率
dde-control-center:dde-control-center代码覆盖率

总结

在系统测试阶段或者开发自测阶段,配合gcov和lcov的使用,在测试结束时,可以很清晰的看出哪些代码块跑到了,哪些代码块没有跑到。虽然说覆盖率100%不能证明系统就没有问题了,但是当测试完成时,覆盖率结果依然很低,那肯定有漏测无疑了。

参考资料:
linux kernel 指南
gcov—a Test Coverage Program
gcov代码覆盖率测试-原理和实践总结

发表评论

电子邮件地址不会被公开。 必填项已用*标注