覆蓋率測試工具gcov的前端工具_LCOV_簡介

一、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

參考資料
一、http://ltp.sourceforge.net/coverage/

*******************

Gcov做爲gnu/gcc工做組件之一,是一款的免費的代碼覆蓋率測試工具,並且能夠結合lcov生成美觀的html的測試報表。本文介紹一些gcov的使用方法,基本原理,一些實際中可能會遇到的問題以及解決思路。

  1. 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以下:

gcov

第一列是覆蓋狀況,第二列是行號加源程序,其中第一列中數字開頭的是執行的次數,####開頭的是沒有執行到的語句。

2. Gcov的實現原理簡介

Gcc中指定-ftest-coverage 等覆蓋率測試選項後,gcc 會:

  • 在輸出目標文件中留出一段存儲區保存統計數據
  • 在源代碼中每行可執行語句生成的代碼以後附加一段更新覆蓋率統計結果的代碼
  • 在最終可執行文件中進入用戶代碼 main 函數以前調用 gcov_init 內部函數初始化統計數據區,並將gcov_exit 內部函數註冊爲 exit handlers
  • 用戶代碼調用 exit 正常結束時,gcov_exit 函數獲得調用,其繼續調用 __gcov_flush 函數輸出統計數據到 *.gcda 文件中

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

http://www.linezing.com/blog/?p=234

相關文章
相關標籤/搜索