【C++】統計代碼覆蓋率(二)


嗷嗷嗷!!!好激動,我好蠢。不過最后還是解決了。嗚嗚嗚

有些都是東一塊西一塊查的,如果有侵權歡迎私信我,我注明出處。

一 gcov&CMake

昨天試了下測試代碼和被測代碼都是c++的情況,直接編譯生成gcno文件,再一運行,生成gcda文件。腳本統計,blingbling生成了報表,簡直漂亮!

不過我們的工程比較大= =。編譯時也需要很多依賴文件。

因此使用場景為:在機器A目錄編譯,拷貝純bin文件到B目錄上運行。編譯方式為CMake

1 修改編譯腳本

  • 找到CMakeList.txt文件,添加如下內容:
  • # coverage option
    OPTION (ENABLE_COVERAGE "Use gcov" OFF)
    MESSAGE(STATUS ENABLE_COVERAGE=${ENABLE_COVERAGE})
    IF(ENABLE_COVERAGE)
        SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
        SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
    # 其中
    -fprofile-arcs 用來生成 gcno 文件; -ftest-coverage 用來在統計時生成 gcda 文件
    # SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") ENDIF()
  • 編譯時使用命令如下:
    cmake -DENABLE_COVERAGE=ON ..
  • 編譯后查看文件目錄:build一路向下
  • ******/build/CMakeFiles/ad_server.dir/src
    $ll
    -rw-rw-r-- 1 mobdev mobdev 1431748 Jun 22 18:24 A.cpp.gcno
    -rw-rw-r-- 1 mobdev mobdev 2138256 Jun 22 18:24 A.cpp.o
    -rw-rw-r-- 1 mobdev mobdev  314180 Jun 22 18:25 B.cpp.gcno
    -rw-rw-r-- 1 mobdev mobdev  871944 Jun 22 18:25 B.cpp.o
    -rw-rw-r-- 1 mobdev mobdev 2053332 Jun 22 18:25 C.cpp.gcno
    -rw-rw-r-- 1 mobdev mobdev 3931584 Jun 22 18:25 C.cpp.o
    -rw-rw-r-- 1 mobdev mobdev 1063036 Jun 22 18:24 D.cpp.gcno
    -rw-rw-r-- 1 mobdev mobdev 3280472 Jun 22 18:24 D.cpp.o
  • 如上表示編譯成功

2 拷貝bin文件到目錄B,注意保持目錄B與目錄A的為同一次編譯結果(我是檢查md5文件)

   如果是從機器A到機器B,注意配置gcov_prefix交叉編譯。

3 啟動你的服務,按原方式執行測試用例。case執行完成后進入下一步

4 生成gcda文件。vim test.sh,內容如下:

  • #!/bin/sh
    SERVER_NAME=$1
    
    pid=`ps -ef | grep $SERVER_NAME | grep -v "grep" | awk '{print $2}'`
    echo $pid
    gdb -q attach $pid <<__EOF__
    p __gcov_flush()
    __EOF__

    執行命令:sh test.sh your_servername

5 檢查:因為這次我的編譯和測試在同台機器的不同目錄,因為gcda文件會生成到編譯時的gcno同目錄,檢查其中已有gcda文件。如下:

  • ******/build/CMakeFiles/ad_server.dir/src
    $ll
    -rw-rw-r-- 1 mobdev mobdev   71772 Jun 22 18:55 A.cpp.gcda
    -rw-rw-r-- 1 mobdev mobdev 1431748 Jun 22 18:24 A.cpp.gcno
    -rw-rw-r-- 1 mobdev mobdev 2138256 Jun 22 18:24 A.cpp.o
    -rw-rw-r-- 1 mobdev mobdev   18452 Jun 22 18:55 B.cpp.gcda
    -rw-rw-r-- 1 mobdev mobdev  314180 Jun 22 18:25 B.cpp.gcno
    -rw-rw-r-- 1 mobdev mobdev  871944 Jun 22 18:25 B.cpp.o   

二 生成html頁面 

進入gcda和gcno文件所在目錄,執行
lcov -c -o result.info  -b . -d .    //生成info文件
genhtml result.info -o Report   //生成html文件
tar cvf Report.tar.gz Report     //壓縮文件
sz Report.tar.gz                      //下載到windows系統
解壓打開其中的index.html即可看到測試代碼覆蓋率

三 生成xml報告

1 安裝gcovr

cd /usr/local
wget https://github.com/gcovr/gcovr/archive/3.2.tar.gz
tar -xvf 3.2.tar.gz
cd gcovr-3.2/scripts
cp gcovr /usr/bin

2 在編譯路徑下執行 gcovr -r .即可查看覆蓋率情況

3 為了使其生成Cobertura可用的xml文件,可以使用命令

gcovr -r .  --output yourdir/coverage.xml  -xml-pretty
vim coverage.xml即可看到xml報告

四 問題

1 描述:無法生成gcda文件

  原因如下:

  • 用戶代碼調用 exit 正常結束時,gcov_exit 函數得到調用,其繼續調用 __gcov_flush 函數輸出統計數據到 *.gcda 文件中
  • 若用戶進程並非調用 exit 正常退出,覆蓋率統計數據就無法輸出,也就無從生成報告了。后台服務程序若非專門設計,一旦啟動就很少主動退出,用 kill 殺死進程強制退出時就不會調用 exit,因此沒有覆蓋率統計結果產生。

  解決:執行(一)4步驟即可。

2 描述:無法組合gcda和gcno文件:"stamp mismatch with notes file"

   原因如下:

  • 網上找了好多答案,說是編譯版本不一致,導致時間戳不一致,我一直沒有理解。
  • 確認自己這兒是因為生成gcno文件的編譯版本和生成gcda文件的版本不一致。
  • 我的操作:
    1 編譯二進制文件ad.server,生成了gcno文件
    2 拷貝ad.server進測試環境,測試生成了gcda
    3 中途又編譯了一次ad.server,生成了新的gcno文件.
    即gcno和gcda文件使用的ad.server並不是同一次編譯的結果。
    最后通過對比兩個地方的ad.server的md5發現了不同,我好蠢= =

    解決:解決很簡單,確保你的版本就ok了,可以對比二進制文件的md5.

    查看時間戳:hexdump -e '"%x\n"' -s8 -n4  A.cpp.gcno 可以看到時間戳。

                     hexdump -e '"%x\n"' -s8 -n4  A.cpp.gcda 可以看到時間戳

3 描述:想要讓gcda文件生成在指定目錄

   場景:有時候是在機器A編譯,機器B運行,這種情況就會不能生成gcda文件,提示找不到目錄

   解決:gcov的交叉編譯 

   操作如下:

  • vim /etc/profile 進行配置
  • export GCOV_PREFIX="/data/ad_server/ad_server.dir"  //gcda的目標路徑
    export GCOV_PREFIX_STRIP=9  //向上數你的路徑到需要配置的那個
    
    比如我的編譯路徑是/data/code/adserver/6/5/4/3/2/*.gcno,我就設置了9,應該也可以設置export GCOV_PREFIX_STRIP=999等很大然后配置全路徑,我沒試
  • source /etc/profile  使其生效
  • 重啟服務進程
  • 執行測試代碼,exit()退出,查看profile的設置路徑,已經有gcda文件
  • 拷貝gcno文件到gcda路徑,統計代碼覆蓋率
  • blingbling的就大功告成了!

我的問題:配置了n久該路徑一直不生效,最后要哭了。今天偶然發現需要重啟進程,憂傷極了

4 描述:無法使用gcovr生成覆蓋率--得到的覆蓋率為0%

$gcovr -r .
------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                       Lines    Exec  Cover   Missing
------------------------------------------------------------------------------
------------------------------------------------------------------------------
TOTAL                                          0       0    --%
------------------------------------------------------------------------------

  解決:執行gcovr -r .在編譯的大路徑下即可,或者在執行時指定source 路徑 如 gcovr -r /home/test/mytest/XXXX/

        目錄不對,只有gcda和gcno、cpp.o文件無法生成覆蓋率,需要源碼--猜測

5 描述:使用 --remove 后未在指定路徑看到 -o 后的新的 info 文件

  解決:實際生成了,使用命令 find / -name "new_file.info" 發現在根目錄下,不知道為什么會這樣,使用時更新為 指定絕對路徑 就 ok 了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM