一、Gcov是進行代碼運行的覆蓋率統計的工具,它隨着gcc的發佈一塊兒發佈的,它的使用也很簡單,須要在編譯和連接的時候加上-fprofile-arcs -ftest-coverage生成二進制文件,gcov主要使用.gcno和.gcda兩個文件,.gcno是由-ftest-coverage產生的,它包含了重建基本塊圖和相應的塊的源碼的行號的信息。.gcda是由加了-fprofile-arcs編譯參數的編譯後的文件運行所產生的,它包含了弧跳變的次數和其餘的概要信息。gcda文件的生成須要先執行可執行文件才能生成。生成gcda文件以後執行命令gcov *.cpp就會在屏幕上打印出測試的覆蓋率,並同時生成文件「*cpp.gcov」,而後用vi打開就能夠看見哪行被覆蓋掉了。php
二、lcov的安裝很簡單,下載源碼執行make install就能夠了,在生成的「*.cpp.gcov"文件中執行lcov --directory . --capture --output-file app.info生成info文件,再執行genhtml -o results app.info就會生成result目錄,生成的html文件就在result目錄下。css
___________________________html
http://www.linuxidc.com/Linux/2011-05/36544.htm前端
Contentlinux
1. Lcov是什麼?shell
2. 如何在Linux平臺安裝Lcov?ruby
3. 如何使用Lcov?app
(1) 使用lcov收集覆蓋率數據並寫入文件函數
(2) 使用genhtml生成基於HTML的輸出工具
(3) 該例子的圖形顯示
4. 編譯lcov自帶例子
5. 其餘相關工具
(1) gcov-dump
(2) ggcov
1. Lcov是什麼?
是GCOV圖形化的前端工具
是Linux Test Project維護的開放源代碼工具,最初被設計用來支持Linux內核覆蓋率的度量
基於Html輸出,並生成一棵完整的HTML樹
輸出包括概述、覆蓋率百分比、圖表,能快速瀏覽覆蓋率數據
支持大項目,提供三個級別的視圖:目錄視圖、文件視圖、源碼視圖
Use lcov to collect coverage data and genhtml to create HTML pages. Coverage data can either be collected from the currently running Linux kernel or from a user space application. To do this, you have to complete the following preparation steps:
For Linux kernel coverage:
Follow the setup instructions for the gcov-kernel infrastructure:
http://ltp.sourceforge.net/coverage/gcov.php
For user space application coverage:
Compile the application with GCC using the options "-fprofile-arcs" and "-ftest-coverage".
2. 如何在Linux平臺安裝Lcov?
# wget http://downloads.sourceforge.net/ltp/lcov-1.9.tar.gz
# tar -zxvf lcov-1.9.tar.gz
# cd lcov-1.9
# ls
bin contrib descriptions.tests lcovrc man rpm
CHANGES COPYING example Makefile README
# make install
不須要編譯,直接安裝便可,lcov, gendesc, genhtml, geninfo, genpng將被安裝到/usr/bin目錄。
3. 如何使用Lcov?
以Linux平臺代碼覆蓋率測試工具GCOV簡介一文的例子爲例。
(1) 使用lcov收集覆蓋率數據並寫入文件
# lcov --capture --directory . --output-file test.info --test-name test
Capturing coverage data from .
Found gcov version: 4.1.2
Scanning . for .gcda files ...
Found 1 data files in .
Processing test.gcda
Finished .info-file creation
.表示當前目錄,收集coverage data,即.gcda文件中的信息,並寫入test.info文件,且取名爲test。其餘選項請參考lcov的manual頁。
test.info文件內容以下。
TN:test
SF:/home/zubo/gcc/2011-04-10.sample/test.c
FN:4,main
FNDA:1,main
FNF:1
FNH:1
BRDA:9,2,0,10
BRDA:9,2,1,1
BRDA:12,0,0,0
BRDA:12,0,1,1
BRF:4
BRH:3
DA:4,1
DA:7,1
DA:9,11
DA:10,10
DA:12,1
DA:13,0
DA:15,1
DA:16,1
LF:8
LH:7
end_of_record
(2) 使用genhtml生成基於HTML的輸出
# genhtml test.info --output-directory output --title "a simple test" --show-details --legend
Reading data file test.info
Found 1 entries.
Found common filename prefix "/home/zubo"
Writing .css and .png files.
Generating output.
Processing file gcc/2011-04-10.sample/test.c
Writing directory view page.
Overall coverage rate:
lines......: 87.5% (7 of 8 lines)
functions..: 100.0% (1 of 1 function)
branches...: 75.0% (3 of 4 branches)
選項解釋請參考genhtml的manual頁。cd到output目錄,能夠看到,生成了不少相關文件,以下。
# cd output
# ls
amber.png gcov.css index-sort-b.html ruby.png
emerald.png glass.png index-sort-f.html snow.png
gcc index.html index-sort-l.html updown.png
(3) 該例子的圖形顯示
(3.1) top level的視圖
(3.2) 文件或函數的視圖
4. 編譯lcov自帶例子
# cd /usr/src/lcov-1.9/example
# make
編譯、運行自帶例子並查看結果是快速學習某個工具最好的方法。從example的makefile文件和編譯輸出,均可以學習相關概念和命令的使用方法。Html輸出能夠由/usr/src/lcov-1.9/example/output/index.html查看。讀者可自行實驗。
5. 其餘相關工具
(1) gcov-dump
或許,咱們還能夠使用gcov-dump命令輸出gcov的相關數據,但gcc默認不編譯gcov-dump,所以,要使用它,可能須要從新編譯gcc。
(2) ggcov
Ggcov is a Graphical tool for displaying gcov test coverage data. 詳細信息可參考http://ggcov.sourceforge.net。
Reference
lcov的manual頁
genhtml的manual頁
geninfo的manual頁
lcov的readme文件,本文/usr/src/lcov-1.9/README
lcov的makefile文件,本文爲/usr/src/lcov-1.9/Makefile
本篇文章來源於 Linux公社網站(www.linuxidc.com) 原文連接:http://www.linuxidc.com/Linux/2011-05/36544.htm
*************************
代碼覆蓋率——gcov lcov的使用
1、關於gcov工具
gcov伴隨gcc 發佈。gcc編譯加入-fprofile-arcs -ftest-coverage 參數生成二進制程序,執行測試用例生成代碼覆蓋率信息。
一、如何使用gcov
用GCC編譯的時候加上-fprofile-arcs -ftest-coverage選項,連接的時候也加上。
fprofile-arcs參數使gcc建立一個程序的流圖,以後找到適合圖的生成樹。只有不在生成樹中的弧被操縱(instrumented):gcc添加了代碼來清點這
些弧執行的次數。當這段弧是一個塊的惟一出口或入口時,操縱工具代碼(instrumentation code)將會添加到塊中,不然建立一個基礎塊來包含操縱
工具代碼。gcov主要使用.gcno和.gcda兩個文件。
.gcno是由-ftest-coverage產生的,它包含了重建基本塊圖和相應的塊的源碼的行號的信息。
.gcda是由加了-fprofile-arcs編譯參數的編譯後的文件運行所產生的,它包含了弧跳變的次數和其餘的概要信息。
Gcov執行函數覆蓋、語句覆蓋和分支覆蓋。
舉個例子,程序代碼由main.c和tmp.c兩個文件組成,編譯、連接、運行程序
編譯:gcc -fprofile-arcs -ftest-coverage -o myapp main.c tmp.c
運行:./myapp
而後 輸入
命令: gcov main.c,gcov tmp.c
這個時候當前目錄下有了新的文檔main.c.gcov,和tmp.c.gcov
若想保存覆蓋率文件,上述命令修改成:
命令:
gcov main.c >>yourfilename,
gcov tmp.c >>yourfilename
查看結果:
-: 65:/***************************************************************************************
-: 66: * name : main
-: 67: * return : 0 OK
-: 68: * other ERROR
-: 69: * history : 2006-06-13
-: 70:****************************************************************************************/
-: 71:int main( int argc, char *argv[] ) /* the entrance for program
*/
function main called 4 returned 100% blocks executed 81%
4: 72:{
4: 73: int loop = 0 ;
4: 74: int ret = OK ;
4: 75: int empty_line = 0 ;
4: 76: int code_line = 0 ;
4: 77: int annotation_line = 0 ;
4: 78: struct stat file_stat ; /* use for file state */
4: 79: char recu_name[256] ;
4: 80: char *pwd = NULL ;
4: 81: char *tmp = NULL ;
-: 82:
4: 83: if( argc = MAX_FILE ){ /* file size larger than max size */
#####: 98: printf( "file [%s] size is over 64K! \ncontinue....\n", argv[loop] ) ;
#####: 99: continue ;
-: 100: }
##### 這就是表示沒跑到的
各個參數使用以下:
gcov [-b] [-c] [-v] [-n] [-l] [-f] [-o directory] sourcefile
-b
Write branch frequencies to the output file, and write branch summary info to the standard output. This option allows you to
see how often each branch in your program was taken.
//b(ranch),分支測試
-c
Write branch frequencies as the number of branches taken, rather than the percentage of branches taken.
-v
Display the gcov version number (on the standard error stream).
//太簡單了吧,我上面用了
-n
Do not create the gcov output file.
-l
Create long file names for included source files. For example, if the header file `x.h' contains code, and was included in the
file `a.c', then running gcov on the file `a.c' will produce an output file called `a.c.x.h.gcov' instead of `x.h.gcov'. This can
be useful if `x.h' is included in multiple source files.
-f
Output summaries for each function in addition to the file level summary.
-o
The directory where the object files live. Gcov will search for `.bb', `.bbg', and `.da' files in this directory.
新版的是這麼說的
-o directory│file
--object-directory directory
--object-file file
Specify either the directory containing the gcov data files, or the
object path name. The .gcno, and .gcda data files are searched for
using this option. If a directory is specified, the data files are
in that directory and named after the source file name, without its
extension. If a file is specified here, the data files are named
after that file, without its extension. If this option is not sup-
plied, it defaults to the current directory.
其餘的更有新版的-u,
-u
--unconditional-branches
When branch counts are given, include those of unconditional
branches. Unconditional branches are normally not interesting.
-p
--preserve-paths
Preserve complete path information in the names of generated .gcov
files. Without this option, just the filename component is used.
With this option, all directories are used, with ’/’ characters
translated to ’#’ characters, ’.’ directory components removed and
’..’ components renamed to ’^’. This is useful if sourcefiles are
in several different directories. It also affects the -l option.
2、關於lcov
Lcov則是上的gcov 結果展示的一個前端,能夠將覆蓋率信息轉換成html展示。
一、如何使用lcov
Makefile 在編譯和link環節都加入 -fprofile-arcs -ftest-coverage 選項
收集覆蓋率數據生成app.info文件
命令:cov --directory . --capture --output-file myapp.info
Capturing coverage data from .
Found gcov version: 3.4.6
Scanning . for .gcda files ...
Found 1 data files in .
Processing ./TestQuery.gcda
Finished .info-file creation
轉換成html格式
命令:genhtml -o results app.info
Reading data file app.info
Found 18 entries.
Found common filename prefix "/home/search/isearch_yb/src"
Writing .css and .png files.
Generating output.
Processing file cpp/core/basis/GlobalDef.h
Processing file cpp/core/search/QueryCache.h
...
Writing directory view page.
Overall coverage rate: 117 of 514 lines (22.8%)
二、查看html文件
html包含代碼覆蓋的詳細信息
更多命令選項
http://ltp.sourceforge.net/coverage/lcov/lcov.1.php?PHPSESSID=26d7173d1f492f5f691715ef8b7d0b40
*******************
Gcov做爲gnu/gcc工做組件之一,是一款的免費的代碼覆蓋率測試工具,並且能夠結合lcov生成美觀的html的測試報表。本文介紹一些gcov的使用方法,基本原理,一些實際中可能會遇到的問題以及解決思路。
1.1 編譯
Gcov的使用方法很簡單,首先須要給gcc編譯的時候打開覆蓋測試的開關
例如要對srcfile.c單個文件生成的程序進行代碼覆蓋測試,在gcc編譯的時候:
1
2
|
gcc -fprofile-arcs -ftest-coverage srcfile.c -o srcfile
|
或者簡化成:
1
2
|
gcc --coverage srcfile.c -o srcfile
|
若是源文件不少,須要編譯,連接的時候,在gcc編譯的時候:
編譯:
1
2
|
gcc -fprofile-arcs -ftest-coverage -c srcfile.c
|
連接:
1
2
|
gcc srcfile.o -o srcfile -lgcov
|
或者
1
2
|
gcc srcfile.o –o srcfile -fprofile-arcs
|
看出來了沒有,gcov能夠只針對大項目中的某幾個單獨的文件進行代碼覆蓋測試,只要在這幾個文件編譯的時候,加上-ftest-coverage,其餘的文件不變就好了,爽吧。
1.2 生成報表
編譯完成後會同時生成 *.gcno 文件(gcov notes),gcov生成覆蓋率報告時須要參考該文件。
運行生成的可執行文件,給予正常的工做負載,待其正常退出後會生成覆蓋率統計數據 *.gcda 文件(gcov data)
經過以下命令行之一查看覆蓋率報告:
gcov 生成文本統計結果和帶 line-count 標註的源代碼:gcov srcfile
lcov 生成較正式的 HTML 報告:
1
2
|
lcov -c -d srcfile_dir -o srcfile.info
genhtml -o report_dir srcfile.info
|
注意:另外,編譯選項中最好加入 -g3 -O0,前者是爲了增長調試信息,後者是爲了禁用優化,省得覆蓋率測試不許確。
1.3 一個單文件的例子
一個例子程序以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#include <stdio.h>
#include <stdlib.h>
int
main(
int
argc,
char
* argv[]) {
int
i = 0;
printf
(
"Begin Test...\n"
);
if
(1 == argc) {
printf
(
"argc == 1\n"
);
}
else
{
printf
(
"argc != 1\n"
);
for
(i = 0; i < argc; i++)
printf
(
"%d\tof\t%d\n"
, i+1, argc);
}
printf
(
"End Test!\n"
);
}
|
編譯:
1
|
gcc
test
.c -fprofile-arcs -ftest-coverage -o
test
|
生成文件以下:
1
|
test
test
.c
test
.gcno
|
運行:
1
|
. /test
1 2 3 4
|
生成文件以下:
1
|
test
test
.c
test
.gcda
test
.gcno
|
生成覆蓋測試報告:
1
|
gcov
test
|
生成的test.gcov以下:
第一列是覆蓋狀況,第二列是行號加源程序,其中第一列中數字開頭的是執行的次數,####開頭的是沒有執行到的語句。
2. Gcov的實現原理簡介
Gcc中指定-ftest-coverage 等覆蓋率測試選項後,gcc 會:
2 對後臺服務程序進行覆蓋率測
從 gcc coverage test 實現原理可知,若用戶進程並不是調用 exit 正常退出,覆蓋率統計數據就沒法輸出,也就無從生成報告了。後臺服務程序若非專門設計,一旦啓動就不多主動退出,用 kill 殺死進程強制退出時就不會調用 exit,所以沒有覆蓋率統計結果產生。
爲了解決這個問題,咱們能夠給待測程序增長一個 signal handler,攔截 SIGHUP、SIGINT、SIGQUIT、SIGTERM 等常見強制退出信號,並在 signal handler 中主動調用 exit 或 __gcov_flush 函數輸出統計結果便可。如何使用gcov完成對後臺駐守程序的測試
該方案仍然須要修改待測程序代碼,不過借用動態庫預加載技術和 gcc 擴展的 constructor 屬性,咱們能夠將 signalhandler 和其註冊過程都封裝到一個獨立的動態庫中,並在預加載動態庫時實現信號攔截註冊。這樣,就能夠簡單地經過以下命令行來實現異常退出時的統計結果輸出了:
1
|
LD_PRELOAD=. /gcov_out .so . /daemon
|
測試完畢後可直接 kill 掉 daemon 進程,並得到正常的統計結果文件 *.gcda。
用來預加載的動態庫gcov_out.so的代碼以下,其中__attribute__ ((constructor))
是gcc的符號,它修飾的函數會在main函數執行以前調用,咱們利用它把異常信號攔截到咱們本身的函數中,而後調用__gcov_flush()輸出錯誤信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#define SIMPLE_WAY
void
sighandler(
int
signo)
{
#ifdef SIMPLE_WAY
exit
(signo);
#else
extern
void
__gcov_flush();
// flush out gcov stats data
__gcov_flush();
// raise the signal again to crash process
raise
(signo);
#endif
}
__attribute__ ((constructor))
void
ctor()
{
int
sigs[] = {
SIGILL, SIGFPE, SIGABRT, SIGBUS,
SIGSEGV, SIGHUP, SIGINT, SIGQUIT,
SIGTERM
};
int
i;
struct
sigaction sa;
sa.sa_handler = sighandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESETHAND;
for
(i = 0; i <
sizeof
(sigs)/
sizeof
(sigs[0]); ++i) {
if
(sigaction(sigs[i], &sa, NULL) == -1) {
perror
(
"Could not set signal handler"
);
}
}
}
|
編譯:
1
|
gcc -shared -fPIC gcov_out.c -o gcov_out.so
|
4. 參考資料
man gcc
man gcov
lcov – http://ltp.sourceforge.net/coverage/lcov.php
注意,lcov 最好使用 1.9 及以上版本,不然可能遇到以下錯誤:
geninfo: ERROR: …: reached unexpected end of file