PostgreSQL C代码覆盖率测试(gcov, lcov)

前端之家收集整理的这篇文章主要介绍了PostgreSQL C代码覆盖率测试(gcov, lcov)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
通常我们评判一个test case好坏的标准之一是代码的覆盖率,一个好的test case应该覆盖到所有的代码
那么问题来了,我们怎么知道这个test case有没有覆盖到所有的代码呢?
以C代码为例,我们看看如何检测代码覆盖率。

C代码覆盖率测试,需要用到gcc的配套工具gcov , 还有一个可视化公建lcov。
接下来以Postgresql为例,看看如何查看代码覆盖率。
首先需要打开Postgresql的一个编译选项。

--enable-coverage build with coverage testing instrumentation

这个编译项对应gcc的两个参数-fprofile-arcs -ftest-coverage

# enable code coverage if --enable-coverage
if test "$enable_coverage" = yes; then
if test "$GCC" = yes; then
CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage"
else
as_fn_error $? "--enable-coverage is supported only when using GCC" "$LINENO" 5
fi
fi

这两个参数的含义如下:

man gcc
fprofilearcs 用于产生.c文件对应的.gcda文件,.文件可以被用于profile驱动的优化,或者结合gcov 来做代码覆盖分析。
编译时尽量不要使用-O优化,这样代码覆盖数据.才能尽可能和代码接近。
代码调用时,.文件中对应的计数器会被修改,记录代码调用次数
Add code so that program flow arcs are instrumented. During execution the program records how many times each branch and call is executed how many times it taken or returnsWhen the compiled
program exits it saves this data to a file called auxnamegcda for each source fileThe data may be used profiledirected optimizations (-fbranchprobabilities), test coverage analysis
ftestcoverage).Eachobject files auxname generated from the name of the output file,136)">if explicitly specified it not the final executable otherwise it the basename of the source file.
In both cases any suffix removed (eg foo input file dir/foo dir output file specified aso diro).
coverage
This option used to compile link code instrumented coverage analysis a synonym coverage (when compiling)lgcov linkingSee the
documentation those options more details.
· Compile the source files arcs plus optimization code generation optionsFor test coverage analysisuse the additional coverage optionYoudo need to profile every
source file in a programLink your files lgcov the latter implies the formerRun the program on a representative workload to generate the arc profile information may be repeated any number of times can run concurrent instances of your program provided that
the file system supports locking the data files will be correctly updatedAlso "fork" calls are detected correctly handled double counting will happendirected optimizations compile the source files again the same optimization code generation options plus gcov to produce human readable information the gcno gcda filesRefer to the gcov documentation further informationWitharcs each function of your program GCC creates a program flow graphthen finds a spanning tree the graphOnly arcs that are on the spanning tree have to be instrumented:
the compiler adds code to count the number of times that these arcs are executed an arc the only exit only entrance to a block the instrumentation code can be added to the block;
otherwise a new basic block must be created to hold the instrumentation code.
这个选项用于产生.文件的.gcno文件。这个文件生成后不会被修改。结合.,可以分析测试代码覆盖率。
Produce a notes file that the gcov codecoverage utility can to show program coverage source files note file called auxname to the arcs option above a
description of auxname instructions on how to generate test coverage dataCoverage data will match the source files more closely you optimize.


首先需要安装依赖gcov和lcov
gcov在gcc包中已经包含了,locv是ltp的一个gcov扩展插件,用来产生HTML报告.
lcov用法参考:

# yum install -y http://downloads.sourceforge.net/ltp/lcov-1.11-1.noarch.rpm

编译Postgresql

./configure --prefix=/optpgsql9.4.4--withpgport=1921perl python tcl openssl pam ldap libxml libxslt threadsafety debug dtrace gmake world && gmake installworld

安装好后,我们会发现在源码目录中多了一些.gcda和.gcno的文件,每个.c文件都会对应这两个文件
postgres@digoal-> ll
total 1.3M
rwr 1 postgres postgres 22KJun1003:29 gistbuildbuffersc
-------1.6KSep71442gcda
15K38gcno
70Ko
37K gistbuild2.2K20K92K43K gist3.1K29K16K gistget1.3K13K74K101K39K gistproc31K79K9.1K gistscan8486.7K60K24K gistsplit1.5K68K21K gistutil84K7.1K gistvacuum7847.3K56K14K gistxlog1.2K12K50K538Makefile
357 objfilestxt
README
postgres@digoal pwd
soft_bakpostgresql-9.44srcbackendaccessgist

注意,源码文件目录的权限需要改为数据库启动用户的权限,否则无法修改.gcda的值,也就无法获取代码调用次数了。
root@digoal chown R postgres:postgres 4

接下来我们看看文件的变化,以dbsize.c中的两个获取pg_database_size的C函数为例:
ls la|grep dbsize
19342 dbsize postgres postgres 266415012327289624o

调用一次
psql
psql ()
Type"help" helppostgres=# select pg_database_size(oid) from pg_database;
pg_database_size
------------------
6898180
6889988
24742560
(6 rows)
postgres=# \q

再次查看
12 dbsize.gcda文件修改时间发送了变化,说明刚才我们调用pg_database_size(oid)时,调用了dbsize.c中的代码。对应的行计数器会发生变化。
接下来我们生成html
$ mkdir html
$ cd html
$ lcov directory 4capture outputfile ./appinfo
// 如果你不需要所有的代码修改以上目录即可,譬如只看contrib下面的代码覆盖率。
$ genhtml ./app.info
postgres@digoal-> ll
total 3.7M
drwxrwxr-x 12 postgres postgres 4.0K Sep 7 15:02 access
-rw-rw-r-- 1 postgres postgres 141 Sep 7 15:02 amber.png
-rw-rw-r-- 1 postgres postgres 3.4M Sep 7 15:02 app.info
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 bootstrap
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 catalog
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 commands
-rw-rw-r-- 1 postgres postgres 141 Sep 7 15:02 emerald.png
drwxrwxr-x 2 postgres postgres 12K Sep 7 15:02 executor
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 foreign
-rw-rw-r-- 1 postgres postgres 9.7K Sep 7 15:02 gcov.css
-rw-rw-r-- 1 postgres postgres 167 Sep 7 15:02 glass.png
-rw-rw-r-- 1 postgres postgres 57K Sep 7 15:02 index.html
-rw-rw-r-- 1 postgres postgres 57K Sep 7 15:02 index-sort-f.html
-rw-rw-r-- 1 postgres postgres 57K Sep 7 15:02 index-sort-l.html
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 lib
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 libpq
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 main
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 nodes
drwxrwxr-x 3 postgres postgres 4.0K Sep 7 15:02 opt
drwxrwxr-x 7 postgres postgres 4.0K Sep 7 15:02 optimizer
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 parser
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 port
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 postmaster
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 regex
drwxrwxr-x 3 postgres postgres 4.0K Sep 7 15:02 replication
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 rewrite
-rw-rw-r-- 1 postgres postgres 141 Sep 7 15:02 ruby.png
drwxrwxr-x 3 postgres postgres 4.0K Sep 7 15:02 snowball
-rw-rw-r-- 1 postgres postgres 141 Sep 7 15:02 snow.png
drwxrwxr-x 10 postgres postgres 4.0K Sep 7 15:02 storage
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 tcop
drwxrwxr-x 2 postgres postgres 4.0K Sep 7 15:02 tsearch
-rw-rw-r-- 1 postgres postgres 117 Sep 7 15:02 updown.png
drwxrwxr-x 3 postgres postgres 4.0K Sep 7 15:02 usr
drwxrwxr-x 14 postgres postgres 4.0K Sep 7 15:02 utils

输出的HTML报告图例,
行数的覆盖率,函数的覆盖率。

每个目录下的覆盖率。

调用pg_database_size前,你会发现这两个函数没有被覆盖到,说明PG自己的回归测试可能没有覆盖这两个函数,或者我们在安装PG时没有使用make check来进行回归测试。

在我们调用pg_database_size(oid)和(name)后,重新生成app.info文件和html。
这两个函数调用到了。第二列是调用次数,说明pg_database_size_oid被调用了6次。pg_database_size_name被调用了一次,我们前面的测试省略了一些sql没有列出。

最后,Postgresql其实已经在Makefile提供了生成代码覆盖HTML的target。

[root@digoal postgresql]# make coverage-html

产生的html目录如下:
# cd coverage
[root@digoal coverage]# ll
total 224
-rw-r--r-- 1 root root 141 Sep 7 19:17 amber.png
-rw-r--r-- 1 root root 141 Sep 7 19:17 emerald.png
-rw-r--r-- 1 root root 9893 Sep 7 19:17 gcov.css
-rw-r--r-- 1 root root 167 Sep 7 19:17 glass.png
-rw-r--r-- 1 root root 58737 Sep 7 19:18 index.html
-rw-r--r-- 1 root root 58730 Sep 7 19:18 index-sort-f.html
-rw-r--r-- 1 root root 58730 Sep 7 19:18 index-sort-l.html
-rw-r--r-- 1 root root 141 Sep 7 19:17 ruby.png
-rw-r--r-- 1 root root 141 Sep 7 19:17 snow.png
drwxr-xr-x 11 root root 4096 Sep 7 19:18 src
-rw-r--r-- 1 root root 117 Sep 7 19:17 updown.png
drwxr-xr-x 3 root root 4096 Sep 7 19:18 usr

target见makefile:
/Makefile.global
########################################################################## # # Coverage # Explanation of involved files: # foo.c source file # foo.o object file # foo.gcno gcov graph (a.k.a. "notes") file,created at compile time # (by gcc -ftest-coverage) # foo.gcda gcov data file,created when the program is run (for # programs compiled with gcc -fprofile-arcs) # foo.c.gcov gcov output file with coverage information,created by # gcov from foo.gcda (by "make coverage") # foo.c.gcov.out stdout captured when foo.c.gcov is created,mildly # interesting # lcov.info lcov tracefile,built from gcda files in one directory, # later collected by "make coverage-html" ifeq $enable_coverage yes) # There is a strange interaction between lcov and existing .gcov # output files. Hence the rm command and the ordering dependency. gcda_files := $wildcard *.) lcovinfogcda_files rm f gcov ^,0)">LCOVd c o $@ $LCOVFLAGSgcovtool $GCOV)) %.gcda lcovinfo b p o GCOVFLAGS>out :.=.info PHONY coveragehtml html coverage rf coverage mkdir coverage GENHTMLshowdetails legend directory=title=Postgresqlnumspacesprefixabs_top_srcdir`find . -name lcov.info -print` # hook for clean-up clean distclean maintainerclean cleancoverage coverage : gcno lcovinfo out # User-callable target to reset counts between test runs f `find . -name '*.gcda' -print` endif # enable_coverage

所以每次对代码改动后,执行完make check或其他回归测试手段后,就可以执行make coverage-html了。
[参考]
1. http://magustest.com/blog/whiteboxtesting/using-gcov-lcov/
2. http://ltp.sourceforge.net/coverage/lcov.php
3. http://ltp.sourceforge.net/coverage/lcov/readme.php
4. http://blog.163.com/digoal@126/blog/static/16387704020158792814297/
5. http://www.jb51.cc/article/p-wqvazeuq-tz.html
6. https://github.com/linux-test-project/ltp
7. https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
8. https://wiki.postgresql.org/wiki/CodeCoverage
9. http://www.postgresql.org/docs/devel/static/regress-coverage.html
原文地址: http://blog.163.com/digoal@126/blog/static/1638770402015875295989/
原文链接:https://www.f2er.com/postgresql/194611.html

猜你在找的Postgre SQL相关文章