zoukankan      html  css  js  c++  java
  • 新增代码覆盖率解析

    大致原理步骤:

    1)编译阶段:加入编译选项 –fprofile-arcs –ftest-coverage。会在目标代码文件中加入对应的钩子,采集执行的统计来实现覆盖率的统计。

    2)编译后会生成gcno,执行后生成gcda文件。

    3)使用gcov,lcov可实现行覆盖、分支覆盖等计算,xx.info。

    4)结合git diff生成的diff文件,计算新增代码覆盖率。

    [UT/FT]

    1. clone

    |
    |---UTCA ===> dev_zxsdr_v2.17.00.03
    |
    |---utility/sdr_utft ===> dev_zxsdr_v2.17.00.03


    2. build & run

    [yangpeng@yangpeng sdr_utft]$./cmp_utft_BuildAndRun.sh


    3. add testcase

    相关文件介绍:
    (1)utility/sdr_utft/testcases/cmp/ut/testdata用于存放用例基线
    (2)utility/sdr_utft/testcases/cmp/ut/testsuite/include source用于存放用例头文件、源文件

    目前用例处理调试阶段,main工程不是包含source目录,如果新增用例源文件,需要在用例工程的CMakeList.txt对应增加。后期调试完毕,不需再加。

    debug
    utility/sdr_utft/build_tmp/lib# ./main --gtest_filter=*xxxxx* 可以执行制定用例,调试类似

    [COV]

    1. gcov gcov is a test coverage program.
    compile option: -fprofile-arcs -ftest-coverage
    || ||
    / /
    .gcda .gcno
    run compile

    xx.cpp.gcda yy.cpp.gcno

    2. lcov lcov - a graphical GCOV front-end

    ftcov.pl、NewCodeCoverData.ini

    pha_entry.py

    pha_dopatch.py

    WORKSPACE


    [PHA]

    Jenkins Server: http://xxx.xxx.xxx.xxx:xxxx/ 

       1 #!/usr/bin/perl -w
       2 #modify 11.03 by ywq
       3 #modify 2015.03.12 by zlb
       4 #modify 2018.06.12 by lyj
       5 use Cwd;
       6 use Encode;
       7 use Date::Calc qw(:all);
       8 
       9 ##### 调试信息开关 ######
      10 my $gDebugMsg;
      11 
      12 #####################全局变量#####################
      13 my $Config_File = "CodeCoverCfg.ini";
      14 my $gCoverFile = "";
      15 my $gCodePath = "";
      16 my $gBuildCodePath = "";
      17 my $gNodeBase = "";
      18 my $gKeyWordsStr = "";
      19 my $gUpdateDateMethod = "weekly";
      20 my $gTestcasesStat = "";
      21 #log文件
      22 my $RecodResultFile = "";
      23 my $ReportHtmlFile = "";
      24 
      25 my $gCiHomePath = "";
      26 my $gCmakeBuildPath = "";
      27 my $gProjectPath = "";
      28 my $gMyVersion = "";
      29 
      30 
      31 my $gCiVersionCfgFile = ReadValueCfg("$Config_File", "DIFF_CONFIG", "CiVersionCfg");
      32 my $gDifFile = ReadValueCfg("$Config_File", "DIFF_CONFIG", "DifFile");
      33 my $gLcovFile = ReadValueCfg("$Config_File", "DIFF_CONFIG", "LcovFile");
      34 my $gBranchVersion = ReadValueCfg("$Config_File","DIFF_CONFIG","BranchVersion");
      35 my $gCodeVersion = ReadValueCfg("$Config_File","DIFF_CONFIG","CodeVersion");
      36 
      37 my $gIgnoreFile = ReadValueCfg("$Config_File", "IGNORE_FILE_CONFIG", "IgnoreFile");
      38 if (defined $gIgnoreFile){
      39     print "Ignore File list  [G]: ".$gIgnoreFile."
    ";
      40 }
      41 my $gIgnorelinesection = ReadValueCfg("$Config_File", "IGNORE_FILE_CONFIG", "Ignorelinesection");
      42 if (defined $gIgnorelinesection){
      43     print "Ignore line sect  [G]: ".$gIgnorelinesection."
    ";
      44 }
      45 my $gIgnorelineno = ReadValueCfg("$Config_File", "IGNORE_FILE_CONFIG", "Ignorelineno");
      46 if (defined $gIgnorelineno){
      47     print "Ignore line no    [G]: ".$gIgnorelineno."
    ";
      48 }
      49 
      50 my @gIgnoreArr = ();
      51 my @gIgnoreLineSection = ();
      52 my @gKeyWordsArr = ();
      53 
      54 my $Root = getcwd;
      55 chdir($Root);
      56 
      57 
      58 @gArray = ();
      59 #@gSArray = ();
      60 my $gArrayCount = 0;
      61 #my $gSArrayCount = 0;
      62 
      63 %gDiffFileLineHash = ();
      64 %gIgnoreLineHash = ();
      65 my $Content = "";#新增代码详细内容
      66 
      67 #分支覆盖
      68 my $gDecisionCount = 0;
      69 my $gDecisionCoverCount = 0;
      70 
      71 #记录当前时间
      72 my $gDateTimeNow = GetDateTime();
      73 my $gCurrDate = GetDate();
      74 
      75 #新增覆盖率
      76 my $gNewOutofNum = 0;
      77 my $gNewCoverRage = 0;
      78 my $gProjectCoverage = 0;
      79 
      80 #更新状态文件信息
      81 my $gGitPrevDate = 0;
      82 
      83 my $proj_stats="";
      84 my $all_stats="";
      85 
      86 my (%gLcovHash);
      87 
      88 ###########################################
      89 
      90 main(@ARGV);
      91 
      92 ###########################################
      93 
      94 sub main {
      95     my (@ARGV) = @_;
      96     my $Endtime = "";
      97     my $html_begin="";
      98     my $html_end="";
      99     my $errorlogfile = "errorlog.txt";
     100     open($errorlogfile, "> $errorlogfile");
     101 
     102     if($ARGV[0] eq "") {
     103         print $errorlogfile("Usage: ftcov.pl INI_SECTION [project_path [build_debug_path [admin_home_path]]]
    ");
     104         print $errorlogfile("  INI_SECTION: $Config_File file section.
      project_path: project path, like .../dev_21703/
    build_debug_path: cmakek build path, like .../BRS_EM/cmake-debug-build/
    admin_home_path: CI config home path, like /home/brs/");
     105         close($errorlogfile);
     106         return;
     107     } else {
     108         $gTestProject = $ARGV[0];
     109         $gdiffId      = $ARGV[1];
     110         $gbaseBranch  = $ARGV[2];
     111         print $gTestProject;
     112         print $gbaseBranch;
     113         print $gdiffId;
     114         #$gProjectPath = $ARGV[1];    #.../dev_21703/
     115         #$gProjectPath = "./../../../";    #.../dev_21703/
     116         #$gCmakeBuildPath = $ARGV[2]; #.../BRS_EM/cmake-build-debug
     117         #$gCiHomePath = $ARGV[3];     #/home/brs/
     118     }
     119 
     120     if (defined $gProjectPath) {
     121         #$gDifFile = $gProjectPath.$gDifFile;
     122         #$gMyVersion = $gProjectPath."/myversion";
     123 
     124         # These TWO vars rebuild 
     125         #$gBranchVersion
     126         #$gCodeVersion
     127         # BRSCI have some version config
     128         # read from these file
     129         ReadProjectCfgFromCiCfg();
     130     }
     131 
     132 
     133     if (ChkIniSection($Config_File,$gTestProject) == 0) {
     134         print "--------
    ";
     135         print "Error $Config_File,$gTestProject  not exist!
    ";
     136         print "--------
    ";
     137         close($errorlogfile);
     138         return;
     139     }else{
     140         print "--------
    ";
     141         print "Starting $Config_File,$gTestProject ...
    ";
     142         print "--------
    ";
     143     }
     144 
     145     if (GetProjectParameter($Config_File,$gTestProject) == 0){
     146         close($errorlogfile);
     147         return;
     148     }
     149 
     150     if (defined $gIgnoreFile) {
     151         @gIgnoreArr = split /;+/, $gIgnoreFile;
     152     }
     153     if (defined $gIgnorelinesection) {
     154         @gIgnoreLineSection = split /;+/, $gIgnorelinesection;
     155     }
     156 
     157     #输出文件
     158     $RecodResultFile = "$gTestProject".".txt";
     159     open($RecodResultFile, "> $RecodResultFile") || die("Could not open $RecodResultFile");
     160 
     161 
     162     $html_begin = '<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <body>';
     163     $html_end = '</body> </html>';
     164     $ReportHtmlFile = "$gTestProject".".html";
     165     open($ReportHtmlFile, ">:encoding(utf-8)","$ReportHtmlFile") || die("Could not open $ReportHtmlFile");
     166     print $ReportHtmlFile decode('gbk',"$html_begin");
     167 
     168     print $RecodResultFile("***********************************Start:$gDateTimeNow**********************************
    ");
     169     print $RecodResultFile("模块号:$gTestProject。
    ");
     170 
     171     UpdateDiffFile();
     172 
     173     changecovfile();
     174 
     175     CalcCovs();
     176 
     177     $Endtime = GetDateTime();
     178     print $RecodResultFile("***********************************End:$Endtime**********************************
    ");
     179 
     180 
     181     print $ReportHtmlFile decode('utf-8',"$html_end");
     182     close($RecodResultFile);
     183     close($ReportHtmlFile);
     184     close($errorlogfile);
     185 }
     186 
     187 sub PickCoverLine {
     188     my $fileHandle;
     189 
     190     if(-e $gCoverFile) {
     191         open($fileHandle, "$gCoverFile");
     192     } else {
     193         print $RecodResultFile("PickCoverLine : open $gCoverFile fail.
    ");
     194         return;
     195     }
     196 
     197     my $CurFile;
     198     my $PreFile = "";
     199     my $IgnoreLine = 0;
     200     my $IgnoreFunc = 0;
     201 
     202     my $space = "&nbsp;&nbsp;&nbsp;&nbsp;";
     203     my $color = "<font color=0x99FF size=6.5>";
     204     my $colorsect = "<font color=0x44AA size=4.5>";
     205     my $nextline = "<br>";
     206     my $font = "</font>";
     207     my $red = "RED";
     208     my $gray ="BLUE";
     209     my $black = "GREEN";
     210     my $nocover = "<font color=$red size=4>New Uncovered</font>";
     211     my $colorTF = "";
     212     my $statistics = "";
     213     my $linesectionbegin = 1;
     214     my $linesection = "";
     215 
     216     my $note_fir = "<font color=$red size=3>NOTE:The first column: Line numbers</font>";
     217     my $note_sec = "<font color=$red size=3>The Second column: Coverage(true first: + be coveraged,- not coveraged)</font>";  
     218     $Content = $Content.$nextline.$note_fir.$nextline;
     219     $Content = $Content.$nextline.$note_sec.$nextline;
     220 
     221     while(<$fileHandle>) {
     222         #文件比较开始
     223         if($_ =~ /^.+/(.+?),(d+),(d+),(d+),(.*)$/) {
     224             #    $1 文件名        $2 行号        
     225             #    $3 行总分支数    $4 覆盖分支数
     226             #    $5 覆盖信息
     227             #分析完的文件从hash中删除
     228             if(lc($1) ne $PreFile && exists $gDiffFileLineHash{$PreFile}) {
     229                 delete $gDiffFileLineHash{$PreFile};
     230                 $CurFile = "";
     231                 #当hash为空时停止循环
     232                 my $length = keys %gDiffFileLineHash;
     233                 if($length eq 0) {
     234                     last;
     235                 }
     236             }
     237             #如果当前文件名与前一个文件名不同
     238             if(lc($1) ne $PreFile && exists $gDiffFileLineHash{lc($1)}) {
     239                 #第一次的时候$PreFile不在hash表里
     240                 $FileBeginFlag = 1;
     241             }
     242             $PreFile = lc($1);
     243 
     244             if(exists $gDiffFileLineHash{lc($1)}) {
     245                 $CurFile = lc($1);
     246             } else {#如果不是要分析的文件,继续查找
     247                 next;
     248             }
     249 
     250             #根据文件名从哈希表中找到新增代码的起始行&&末行
     251             my @LineNoArray = @{$gDiffFileLineHash{$CurFile}};
     252 
     253             my $LineNoBegin = $LineNoArray[0];
     254             my $LineNoEnd = $LineNoArray[-1];
     255 
     256             #如果找到行号小于修改行号最小值,继续查找
     257             if($2<$LineNoBegin) {
     258                 next;
     259             }
     260             #如果找到行号大于修改行号最大值,结束查找
     261             if($2>$LineNoEnd) {
     262                 next;
     263             }
     264             foreach $LineNo (@LineNoArray) {
     265                 #如果找到行号小于当前修改行号,结束查找
     266                 if($2<$LineNo) {
     267                     last;
     268                 }
     269                 #如果当前修改行号为0,继续查找
     270                 if($LineNo==0) {
     271                     next;
     272                 }
     273                 #如果找到行号大于当前修改行号,继续查找
     274                 if($2>$LineNo) {
     275                     next;
     276                 }
     277 
     278                 #如果覆盖未TF,tf,更新LineCoverCount,更新数组中当前修改行号为0,避免重复计算
     279                 {
     280                     $gDecisionCount = $gDecisionCount + $3;
     281                     $gDecisionCoverCount = $gDecisionCoverCount + $4;
     282                     if ($4 eq "0") {
     283                         $colorTF = "<font color=$red size=4>($5)</font>";
     284                     }elsif ($4 eq $3) {
     285                         $colorTF = "<font color=$black size=4>($5)</font>";
     286                     }else {
     287                         $colorTF = "<font color=$gray size=4>($5)</font>";
     288                     }
     289 
     290                     my $colorString = $colorTF;
     291 
     292                     for($i = 0; $i < $gArrayCount; $i++) {
     293                         if(lc($gArray[$i][0]) eq lc($CurFile) && $gArray[$i][1] == $2) {
     294                             if($FileBeginFlag == 1) {
     295                                 $Content = $Content.$nextline.$color.$CurFile.$font.$nextline;
     296                                 $FileBeginFlag = 0;
     297                             }
     298 
     299                             if($linesectionbegin == 1) {
     300                                 $linesection = $gArray[$i][3];
     301                                 $Content = $Content.$colorsect.$linesection.$font.$nextline;
     302                                 $linesectionbegin = 0;
     303                             }elsif($linesection ne $gArray[$i][3]) {
     304                                 $linesection = $gArray[$i][3];
     305                                 $Content = $Content.$colorsect.$linesection.$font.$nextline;
     306                             }
     307 
     308                             $Content = $Content.$space.$LineNo.$space.$colorString.$space.$gArray[$i][2].$nextline;
     309 
     310                             last;
     311                         }
     312                     }
     313                 }
     314 
     315             }
     316         } else {
     317             next;
     318         }
     319     }
     320 
     321     close($fileHandle);
     322 }
     323 
     324 
     325 sub GetDiffFileInfo {
     326     my $fp;
     327     my($filename, $arrayflag) = @_;
     328 
     329     print "-----------------------
    ";
     330     if(-e $filename) {
     331         open($fp, "$filename");
     332         print "open $filename ok!
    ";
     333     }else {
     334         print "open $filename error!
    ";
     335         return;
     336     }
     337 
     338     my $CurFile = "";
     339     my $FilePath = "";
     340     my $LineString;
     341     my $LineCount = 0;
     342     my $hashflag = 0;
     343     my $catchbegin = 0;
     344     my $beginline = 0;
     345     my $continueline = 0;
     346     my $linesection = "";
     347     my $strtmp = "BRS_SECURITY";
     348     my $strtmpnull = "NULL";
     349     my $strtmpprintf = "rintf";
     350 
     351     if($arrayflag eq 0) {
     352         $hashflag = 0;
     353     }else {
     354         $hashflag = 1;
     355     }
     356 
     357     @tmp = ();
     358 
     359     PutIgnorelinenoInHash();
     360 
     361     while(<$fp>) {
     362         #文件比较开始一行一行比较
     363         if($_ =~ /^diffs--gits.+/(.+?.cpp)s*$/) {
     364             $CurFile = $1;
     365             $FilePath = $_;
     366         } elsif($_ =~ /^diffs--gits.+/(.+?.h)s*$/) {
     367             $CurFile = $1;
     368             $FilePath = $_;
     369         } elsif($_ =~ /^diffs--gits.+/(.+?.c)s*$/) {
     370             $CurFile = $1;
     371             $FilePath = $_;
     372             #print "path:$FilePath,file:$CurFile
    "
     373         } elsif($_ =~ /^@@s.++(d+),(d+)s@@.*$/) {#增加或修改
     374             $LineCount = 0;
     375             $beginline = $1;
     376             $continueline = $1+$2;
     377             $linesection = "($beginline,$continueline)";
     378 
     379             #print "Diff file modify section: $linesection
    ";
     380         } elsif($_ =~ /^+s*$/) {#增加的空行。。。
     381             $LineCount++;
     382         } elsif($_ =~ /^s.*$/)  {#不变的任何行
     383             $LineCount++;
     384         } elsif($_ =~ /^---s(.+)$/) {#---行
     385             #print $1."
    ";
     386             next;
     387         } elsif($_ =~ /^+++s(.+)$/) {#+++行
     388             #print $1."
    ";
     389             next;
     390         } elsif($_ =~ /^+(.+)$/) {#增加修改的具体函数内容
     391             $tmp[0] = $CurFile;
     392             $tmp[1] = $beginline+$LineCount;
     393             $tmp[2] = $1;
     394             $tmp[3] = $linesection;
     395 
     396             $LineCount++;
     397 
     398             if (IsKeyWordsPath($FilePath) == 0) {
     399                 if (defined $gDebugMsg){
     400                     print "$CurFile : keywordpath ignored[$tmp[1],$tmp[3],$tmp[2]].
    ";
     401                 }
     402                 next;
     403             }elsif (IsIgnore($tmp[0],$tmp[3],$tmp[1]) == 1) {
     404                 if (defined $gDebugMsg){
     405                     print "$CurFile : ignore ignored[$tmp[1],$tmp[3],$tmp[2]].
    ";
     406                 }
     407                 next;
     408             }elsif ($1 =~ /$strtmp/) {
     409                 if (defined $gDebugMsg){
     410                     print "$CurFile : strtmp ignored[$tmp[1],$tmp[3],$tmp[2]].
    ";
     411                 }
     412                 next;
     413             }elsif ($1 =~ /$strtmpnull/) {
     414                 if (defined $gDebugMsg){
     415                     print "$CurFile : strtmpnull ignored[$tmp[1],$tmp[3],$tmp[2]].
    ";
     416                 }
     417                 next;
     418             }elsif ($1 =~ /$strtmpprintf/) {
     419                 if (defined $gDebugMsg){
     420                     print "$CurFile : strtmpprintf ignored[$tmp[1],$tmp[3],$tmp[2]].
    ";
     421                 }
     422                 next;
     423             }
     424 
     425             push @{$gDiffFileLineHash{$CurFile}}, $tmp[1];
     426 
     427             $gArray[$gArrayCount] = [$tmp[0], $tmp[1], $tmp[2],$tmp[3]];
     428             $gArrayCount++;
     429         } else {
     430             next;
     431         }
     432     }
     433 
     434     close($fp);
     435 }
     436 
     437 sub GetProjectParameter {
     438     my ($fileName,$Projectname) = @_;
     439 
     440     my $gSectionIgnoreFile;
     441 
     442     $gCoverFile = ReadValueCfg($fileName, $Projectname, "CoverFile");
     443     print "CoverResult file     : ".$gCoverFile."
    ";
     444 
     445     $gCodePath = ReadValueCfg($fileName, $Projectname, "CodePath");
     446     if (defined $gProjectPath){
     447         $gCodePath = $gProjectPath.$gCodePath;
     448     }
     449     print "Source code path     : ".$gCodePath."
    ";
     450 
     451     $gBuildCodePath = ReadValueCfg($fileName, $Projectname, "BuildCodePath");
     452     @gBuildCodePathArr = split /;+/, $gBuildCodePath;
     453     if (defined $gCmakeBuildPath){
     454         for ( $idx = 0; $idx < @gBuildCodePathArr; $idx ++){
     455             $gBuildCodePathArr[$idx] = $gCmakeBuildPath.$gBuildCodePathArr[$idx];
     456         }
     457     } elsif (defined $gProjectPath) {
     458         for ( $idx = 0; $idx < @gBuildCodePathArr; $idx ++){
     459             $gBuildCodePathArr[$idx] = $gProjectPath.$gBuildCodePathArr[$idx];
     460         }
     461     }
     462     print "Gcov parse code path : ".@gBuildCodePathArr."
    ";
     463 
     464     $gNodeBase = ReadValueCfg($fileName, $Projectname, "NodeBase");
     465     print $gNodeBase."
    ";
     466 
     467     $gUpdateDateMethod = ReadValueCfg($fileName, $Projectname, "UpdateDateMethod");
     468     print "FT update type       : ".$gUpdateDateMethod."
    ";
     469 
     470     $gSectionIgnoreFile = ReadValueCfg($fileName, $Projectname, "IgnoreFile");
     471     if (defined $gSectionIgnoreFile){
     472         $gIgnoreFile = $gIgnoreFile.";".$gSectionIgnoreFile;
     473         print "Ignore File list     : ".$gIgnoreFile."
    ";
     474     }
     475 
     476     $gKeyWordsStr = ReadValueCfg($fileName, $Projectname, "keywords");
     477     if (defined $gKeyWordsStr){
     478         print "FT Keyword list      : ".$gKeyWordsStr."
    ";
     479     }else {
     480         print "Error: not define keyswords!! You should add "keywords = all;".
    ";
     481         return 0;
     482     }
     483 
     484     $gTestcasesStat = ReadValueCfg($fileName, $Projectname, "TestcasesStat");
     485     if (defined $gTestcasesStat){
     486         print "TestCase stats path  : ".$gTestcasesStat."
    ";
     487     }
     488 
     489     if (defined $gKeyWordsStr){
     490         @gKeyWordsArr = split /;+/, $gKeyWordsStr;
     491     }
     492 
     493     return 1;
     494 }
     495 
     496 
     497 sub ChkIniSection {
     498     my($fileName, $labelName) = @_;
     499     my $value = 0;    
     500     my $fileHandle;
     501 
     502     if(-e $fileName) {
     503         open($fileHandle, "$fileName");
     504     }else {
     505         return;
     506     }
     507 
     508     while(defined($_ = <$fileHandle>)) {
     509         next if /^#/;   # 丢弃注释
     510         chomp;
     511         if(/^[.*]/){
     512             if(/[$labelName]/) {
     513                 $value = 1;    
     514                 last;
     515             }
     516         }
     517         next;
     518     }    
     519     close $fileHandle;
     520     return ($value);
     521 }
     522 
     523 
     524 #从配置文件中读取值类型的配置
     525 sub ReadValueCfg {
     526     my($fileName, $labelName, $keyName) = @_;
     527     my $isNeedLabel = 0;
     528     my $value;    
     529     my $fileHandle;
     530 
     531     if(-e $fileName) {
     532         open($fileHandle, "$fileName");
     533     }else {
     534         return;
     535     }
     536 
     537     while(defined($_ = <$fileHandle>)) {
     538         next if /^#/;   # 丢弃注释
     539         chomp;
     540 
     541         if ($isNeedLabel == 1){
     542             if(/^[.*]/){
     543                 # 进入另外一个段,退出
     544                 last;
     545             }
     546             if(!$isNeedLabel) {
     547                 next;
     548             }
     549             if(/$keyNames*=s*(.+);s*$/) {
     550                 $value = $1;    
     551                 last;
     552             }
     553         }else{
     554             if(/^[.*]/){
     555                 if(/[$labelName]/) {
     556                     $isNeedLabel = 1;
     557                 }
     558             }
     559             next;
     560         }
     561     }    
     562     close $fileHandle;
     563     return ($value);
     564 }
     565 
     566 
     567 sub GetDate {    
     568     ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
     569     $now = sprintf("%d-%02d-%02d",$year+1900,$mon+1,$mday);
     570     return $now;
     571 }
     572 
     573 sub GetDateTime {    
     574     ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
     575     $now = sprintf("%d-%02d-%02d %02d:%02d:%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec);
     576     return $now;
     577 }
     578 
     579 
     580 sub CalcCovs {
     581     my $flag = 0;
     582     my $red = "RED";
     583     my $blue = "BLUE";
     584     my $str = "";
     585     my $CurPreNodefile;
     586 
     587     ParseTestCasesStat();
     588 
     589     GetDiffFileInfo($gDifFile, $flag);
     590 
     591     PickCoverLine();
     592 
     593     my $sum = $gDecisionCount;
     594     $gNewOutofNum = $sum;
     595     my $covercount = $gDecisionCoverCount;
     596     my $nocovercount = $sum - $covercount;
     597 
     598     my $total_cases_stat = "<font color=$blue size=5>Total TestCases:$all_stats</font><br>";
     599     my $per_project_stat = "<font color=$blue size=5>Project TestCases:$proj_stats</font><br>";
     600 
     601     if($gDecisionCount == 0) {
     602         $gNewCoverRage = 60;
     603         $Content = "<font color=$red size=5>The Branch of Code No Change,So New Code Coverage:60%(项目达标线)</font>"."<br>";
     604 
     605         if(defined $gTestcasesStat){
     606             if(-e $gTestcasesStat) {
     607                 $Content .= $total_cases_stat;
     608                 $Content .= $per_project_stat;
     609             }
     610         }
     611         $str = $gNewCoverRage;
     612     } else {
     613         $gNewCoverRage = ($gDecisionCoverCount)*100/($gDecisionCount);
     614         $str = substr(lc($gNewCoverRage), 0, 6);
     615 
     616         my $web_new     = "<font color=$blue size=5>Sum Of New Branch:$sum</font><br>";
     617         my $web_cover   = "<font color=$blue size=5>Covered Branch:$covercount</font><br>";
     618         my $web_uncover = "<font color=$blue size=5>UnCovered Branch:$nocovercount</font><br>";   
     619         my $web_newcov  = "<font color=$blue size=5>New Code Coverage:$str%</font><br>";
     620 
     621         if(defined $gTestcasesStat){
     622             if(-e $gTestcasesStat) {
     623                 $Content = $per_project_stat.$Content;
     624                 $Content = $total_cases_stat.$Content;
     625             }
     626         }
     627 
     628         $Content = $web_new.$Content;
     629         $Content = $web_cover.$Content;
     630         $Content = $web_uncover.$Content;
     631         $Content = $web_newcov.$Content;
     632     }
     633 
     634     if($Content ne "") {
     635         print $ReportHtmlFile decode('gbk',"$Content");
     636     }
     637 
     638     if($gDecisionCount == 0) {
     639         print $RecodResultFile("两个节点间分支数未变化,新增覆盖率为 ---.
    ");
     640     } else {
     641         print $RecodResultFile("新增覆盖率:$gNewCoverRage% ---(新增代码被覆盖分支数/新增代码总分支数).
    ");
     642         print $RecodResultFile("总的新增分支数:$sum,新增代码被覆盖分支数:$covercount,新增代码未覆盖分支数:$nocovercount.
    ");
     643     }
     644     
     645     if($gNewCoverRage < 60){
     646         print $RecodResultFile("新增覆盖率:未达项目线.
    ");
     647     }
     648                      
     649     print "-----------------------
    ";
     650     print "Total CHANGED branch count:".$gDecisionCount."
    ";
     651     print "-----------------------
    ";
     652 }
     653 
     654 my $FoundSameFile = 0;
     655 my $FoundSameKey = 0;
     656 my $linecount=0;
     657 
     658 sub merge_calc{
     659     my ($fileLine)=@_;
     660     my (%zero_hash);
     661     my (%branchHash);
     662     my (@tmpArr);
     663     my $tmp = 0;
     664     my $tmpBranch= {};
     665     $linecount += 1;
     666     # 新增加一个文件的分支数据
     667     if($fileLine =~ /^SF:(.*/([^/]+[a-zA-Z]))[^a-zA-Z]*$/) {
     668         #print "found file key:".$1.",".$2.",".$linecount."
    ";
     669         # 清空
     670         $branchHash = {};
     671         # 置位
     672         $FoundSameKey = 0;
     673         $FoundSameFile = 0;
     674        
     675         if (exists $gLcovHash->{$2}){
     676             @tmpArr = @{$gLcovHash->{$2}};
     677             if ($#tmpArr >= 0){
     678                 $FoundSameKey = 1;
     679                 #print "found same key ($#tmpArr): $tmpArr[0]
    ";
     680                 $tmpBranch= {};
     681                 for $tmpBranch (@tmpArr){
     682                     if ($1 eq $tmpBranch->{SF} ){
     683                         # 文件完全一致,需要合并信息
     684                         $FoundSameFile = 1;
     685                         # 取出已存在的branch数据
     686                         $branchHash = $tmpBranch;
     687                         #print "found same file:".$branchHash->{SF}.",".$tmpBranch->{SF}.",".$linecount."
    ";
     688                         #last;
     689                         #}else{
     690                         #print "same key but file diffrent: $1 ** $tmpBranch->{SF}
    ";
     691                     }
     692                 }
     693                 #}else{
     694                 #print "array len invalid($#tmpArr), (".$2.")
    ";
     695             }
     696             #}else{
     697             #print "new key
    ";
     698         }
     699         $branchHash->{SF}=$1;
     700         $branchHash->{fn}=$2;
     701     }elsif($fileLine =~ /^(BRDA:d+,d+,d+),(.+?)
    *
    *$/) {
     702         # BRDA:line,mod,condition = "0/1/...."
     703         if (($2 eq "-")||($2 eq "0")) {
     704             $tmp = 0;
     705         }else{
     706             $tmp = $2;
     707         }
     708 
     709         if ($FoundSameFile) {
     710             if (defined $branchHash->{$1}){
     711                 #print "same file update BRDA:".$1.","".$branchHash->{$1};
     712                 $branchHash->{$1} += $tmp;
     713                 #print "<=".$tmp."=>".$branchHash->{$1}.""
    ";
     714                 return;
     715             }
     716         }
     717         $branchHash->{$1} = $tmp;
     718     }elsif($fileLine =~ /^BRF:(d+)$/) {
     719         # 一个文件的所有分支信息收集完成
     720         @tmpArr=();
     721         if ( $FoundSameKey ){
     722             if ($FoundSameFile){
     723                 @tmpArr = @{$gLcovHash->{$branchHash->{fn}}};
     724                 for ( $idx = 0; $idx <= $#tmpArr; $idx ++){
     725                     $tmp = $tmpArr[$idx];
     726                     if ($tmp->{SF} eq $branchHash->{SF} ){
     727                         #print "same file, node updated:$idx,$tmp
    ";
     728                         $gLcovHash->{$branchHash->{fn}}[$idx] = $branchHash;
     729                         last;
     730                         #}else{
     731                         #print "diff file: $tmp->{SF},$branchHash->{SF}
    ";
     732                     }
     733                 }
     734             }else{
     735                 @tmpArr = @{$gLcovHash->{$branchHash->{fn}}};
     736                 push (@tmpArr,$branchHash);
     737                 $gLcovHash->{$branchHash->{fn}} = [ @tmpArr ];
     738                 #print "same key, new node pushed:@tmpArr
    ";
     739             }
     740         }else{
     741             push (@tmpArr,$branchHash);
     742             $gLcovHash->{$branchHash->{fn}} = [ @tmpArr ];
     743 
     744             #print "new key pushed:@tmpArr,$branchHash->{fn},$branchHash->{SF}
    ";
     745         }
     746         #print "------------
    ";
     747     }
     748 }
     749 
     750 sub merge_lcov_info{
     751     my $fileHandle;
     752     my $mergedLcovFile;
     753     my $buildPath = "";
     754 
     755     for ( $cp_idx = 0; $cp_idx < @gBuildCodePathArr; $cp_idx ++){
     756         $linecount = 0;
     757         # 遍历lcov的文件
     758         $buildPath=$gBuildCodePathArr[$cp_idx];
     759         $lcovFile=$gLcovFile."_".$cp_idx;
     760         print "-----------------------
    ";
     761         print " lcov parse build path: $buildPath
    ";
     762         system("lcov -q -c -d $buildPath -o $lcovFile -t fttest --ignore-errors gcov,source,graph --rc lcov_branch_coverage=1");
     763 
     764         if(-e $lcovFile) {
     765             open($fileHandle, "$lcovFile");
     766         }else {
     767             print "open $lcovFile fail.
    ";
     768             return;
     769         }
     770 
     771         # 读取lcov文件,添加或者合并源文件的覆盖数据
     772         print "merge_calc ---
    ";
     773         while(<$fileHandle>) {
     774             merge_calc($_);
     775         }
     776         close($fileHandle);
     777     }
     778 
     779     # 合并后的数据,进行输出
     780     open($mergedLcovFile, "> $gLcovFile");
     781 
     782     print "-----------------------
    ";
     783     print "export merged gLcov:$gLcovFile
    ";
     784     for $fn (keys %{$gLcovHash}){
     785         for $tmp (@{$gLcovHash->{$fn}}){
     786             print $mergedLcovFile("SF:$tmp->{SF}
    ");
     787             for $brdaKey (sort keys %{$tmp}){
     788                 if ($brdaKey eq "SF" ){
     789                     next;
     790                 }
     791                 print $mergedLcovFile("$brdaKey,$tmp->{$brdaKey}
    ");
     792             }
     793         }
     794     }
     795 
     796     close($mergedLcovFile);
     797 }
     798 
     799 sub changecovfile {
     800     my $fileHandle;
     801     my $filename = "";
     802     my $currfilename = "";
     803     my $lineNum = 0;
     804     my $lineLastNum = 0;
     805     my $linebegin = 1;
     806     my $condition;
     807     my $covflag;
     808     my $covcontext="";
     809     my $resultfile;
     810     my $totalbranch = 0;
     811     my $covbranch = 0;
     812 
     813     merge_lcov_info();
     814 
     815     if(-e $gLcovFile) {
     816         open($fileHandle, "$gLcovFile");
     817     }else {
     818         print "open $gLcovFile fail.
    ";
     819         return;
     820     }
     821 
     822     open($resultfile, "> $gCoverFile");
     823 
     824     while(<$fileHandle>) {
     825         #文件比较开始
     826         if($_ =~ /^SF:*+/(.+?[a-zA-Z])[^a-zA-Z]*$/) {
     827             $filename = $1;
     828         }
     829         if($_ =~ /^BRDA:(d+),(d+),(d+),(.+?)$/) {
     830             $lineNum = $1;
     831             $condition = $3;
     832 
     833             if ($linebegin == 1) {
     834                 $linebegin = 0;
     835                 $lineLastNum = $lineNum;
     836             }
     837 
     838             if (($4 eq "-")||($4 eq "0")) {
     839                 $covflag = " -";
     840             }else {
     841                 $covflag = " +";
     842             }
     843 
     844             if ($lineNum eq $lineLastNum) {
     845                 $covcontext = $covcontext.$covflag;
     846                 $totalbranch++;
     847                 if ($covflag eq " +") {
     848                     $covbranch++;
     849                 }
     850                 $currfilename = $filename;
     851             }else {
     852                 $Content = $currfilename.",".$lineLastNum.",".$totalbranch.",".$covbranch.",".$covcontext."
    ";
     853                 print $resultfile("$Content");
     854 
     855                 $covcontext = $covflag;
     856                 $lineLastNum = $lineNum;
     857                 $totalbranch = 1;
     858                 if ($covflag eq " +") {
     859                     $covbranch = 1;
     860                 }else {
     861                     $covbranch = 0;
     862                 }
     863             }
     864         }
     865     }
     866 
     867     $Content = $filename.",".$lineLastNum.",".$totalbranch.",".$covbranch.",".$covcontext."
    ";
     868     print $resultfile("$Content");
     869 
     870     close($fileHandle);
     871 
     872     close($resultfile);
     873     $Content = "";
     874 }
     875 
     876 sub ParseTestCasesStat{
     877     my $readFile;
     878 
     879     print "-----------------------
    ";
     880     if(defined $gTestcasesStat){
     881         if(-e $gTestcasesStat) {
     882             open($readFile, "$gTestcasesStat");
     883         }else {
     884             print $RecodResultFile("open $gTestcasesStat fail.
    ");
     885             return;
     886         }
     887         while(<$readFile>) {
     888             if($_ =~ /^all_cases:(d+) *$/) {
     889                 $all_stats = $1;
     890             }elsif ($_ =~ /^project_cases:(.*) $/){
     891                 $proj_stats = $1;
     892             }
     893         }
     894         print "Got TestCaseStats info: $all_stats . $proj_stats
    ";
     895         close($readFile);
     896     } else {
     897         print "gTestcaseStat not defined, stop parse testcases stat.
    "
     898     }
     899 }
     900 
     901 
     902 sub GetYesterday(){
     903     my $ret= "";
     904     ($tmpY,$tmpM,$tmpD)=Add_Delta_Days(split("-",$gCurrDate),-1);
     905     $ret = $tmpY."-".$tmpM."-".$tmpD;
     906     print "Got Yestoday is ".$ret."
    ";
     907     return  $ret;
     908 }
     909 
     910 sub GetLastSunday(){
     911     my $delta=0;
     912     my $ret= "";
     913     #($tmpY,$tmpM,$tmpD) = split("-",$gCurrDate);
     914     $delta=Day_of_Week(split("-",$gCurrDate));
     915     ($tmpY,$tmpM,$tmpD)=Add_Delta_Days(split("-",$gCurrDate),-$delta);
     916     $ret = $tmpY."-".$tmpM."-".$tmpD;
     917     print "Got Last Sunday is ".$ret."
    ";
     918     return  $ret;
     919 }
     920 
     921 sub GetMonth1st(){
     922     my $ret= "";
     923     ($tmpY,$tmpM,$tmpD) = split("-",$gCurrDate);
     924     $ret = $tmpY."-".$tmpM."-1";
     925     print "Got MONTH first day is ".$ret."
    ";
     926     return  $ret;
     927 }
     928 
     929 sub GetYear1st(){
     930     my $ret= "";
     931     ($tmpY,$tmpM,$tmpD) = split("-",$gCurrDate);
     932     $ret = $tmpY."-1-1";
     933     print "Got YEAR first day is ".$ret."
    ";
     934     return  $ret;
     935 }
     936 
     937 sub GetDiffStartDate(){
     938     if ($gUpdateDateMethod eq "versionly") {
     939         return $gCurrDate; # no use return value
     940     }elsif ($gUpdateDateMethod eq "changely"){
     941         return $gCurrDate; # no use return value
     942     }elsif ($gUpdateDateMethod eq "daily"){
     943         return GetYesterday();
     944     }elsif ($gUpdateDateMethod eq "weekly"){
     945         return GetLastSunday();
     946     }elsif ($gUpdateDateMethod eq "monthly"){
     947         return GetMonth1st();
     948     }elsif ($gUpdateDateMethod eq "yearly"){
     949         return GetYear1st();
     950     }else{
     951         print "UpdateMethod is WRONG!!
    ";
     952         return 0;
     953     }
     954 }
     955 
     956 sub PrintDiffParams{
     957     my ($Param)=@_;
     958     print "-----------------------
    ";
     959     print "Projects: $gCodeVersion
    GitBegin: $Param
    GitTrunk: $gBranchVersion
    DiffText: $gDifFile
    CodePath: $gCodePath
    ";
     960     print "-----------------------
    ";
     961 }
     962 
     963 sub UpdateDiffFile {
     964     my $writefile;
     965 
     966     $gGitPrevDate = GetDiffStartDate();
     967 
     968     system("cd $gCodePath;git branch");
     969     
     970     if ($gUpdateDateMethod eq "versionly" ) {
     971         PrintDiffParams($gNodeBase);
     972         print "git diff $gNodeBase $gdiffId";
     973         system("cd $gCodePath;git diff -w -E $gNodeBase $gdiffId . > $gDifFile");
     974     }elsif ($gUpdateDateMethod eq "changely" ){
     975         system("cd $gCodePath;git diff -w -E origin/$gBranchVersion . > $gDifFile");
     976     }else{
     977         PrintDiffParams($gGitPrevDate);
     978         system("cd $gCodePath;git log --after="$gGitPrevDate" --pretty="%h" --date-order | tail -n1 | xargs -n1 -i git diff -w -E {} origin/$gBranchVersion . > $gDifFile");
     979     }
     980 
     981     #system("cd /home/brs/gitrepo/dev_21701/cov")
     982 }
     983 
     984 sub PutIgnorelinenoInHash {
     985     my $filename;
     986     if (defined $gIgnorelineno){
     987         my @IgnoreArr = split /;+/, $gIgnorelineno; 
     988 
     989         foreach(@IgnoreArr) {
     990             if ($_ =~ /^(.*)|(.*)$/) {
     991                 $filename = $1;
     992                 #print $filename."
    ";
     993                 my @LineArr = split /:+/, $2;
     994                 foreach (@LineArr) {
     995                     push @{$gIgnoreLineHash{$filename}},$_;
     996                 }
     997             }
     998         }
     999     }
    1000 }
    1001 
    1002 sub IsKeyWordsPath {
    1003     my ($filepath) = @_;
    1004     my $flag = 0;
    1005     my $keyword = "";
    1006 
    1007     foreach(@gKeyWordsArr) {
    1008         $keyword = $_;
    1009         if (($keyword eq "all")||($filepath =~ /$keyword/)) {
    1010             $flag = 1;
    1011             return $flag;
    1012         }
    1013     }
    1014     #返回0说明没有命中关键字,需要忽略
    1015     return $flag;
    1016 }
    1017 
    1018 sub IsIgnore {
    1019     my ($filename,$sectionname,$lineno) = @_;
    1020     my $flag = 0;
    1021 
    1022     foreach(@gIgnoreArr) {
    1023         if ($_ eq $filename) {
    1024             $flag = 1;
    1025             return $flag;
    1026         }
    1027     }
    1028 
    1029     foreach(@gIgnoreLineSection) {
    1030         if ($_ eq $sectionname) {
    1031             $flag = 1;
    1032             return $flag;
    1033         }
    1034     }
    1035 
    1036     if(exists $gIgnoreLineHash{$filename}) {
    1037         my @LineNoArray = @{$gIgnoreLineHash{$filename}};
    1038         foreach(@LineNoArray) {
    1039             if($lineno eq $_) {
    1040                 #print $funcname."
    ";
    1041                 $flag = 1;
    1042                 return $flag;
    1043             }
    1044         }
    1045     }
    1046 
    1047     return $flag;
    1048 }
    1049 
    1050 sub ReadProjectCfgFromCiCfg
    1051 {
    1052     my $myversionfile;
    1053     my $projectfilehandle; 
    1054     my $version=""; 
    1055 
    1056     if(-e $gMyVersion)
    1057     {
    1058         open($myversionfile, "$gMyVersion");
    1059     }else
    1060     {
    1061         print $RecodResultFile("open $gMyVersion fail.
    ");
    1062         return;
    1063     }
    1064 
    1065     while(<$myversionfile>)
    1066     {
    1067         if($_ =~ /^(.*)$/)
    1068         {
    1069             $version = $1;
    1070         }
    1071     }
    1072     close($myversionfile);
    1073 
    1074     $gCiVersionCfgFile=$gCiHomePath.$gCiVersionCfgFile;
    1075     if(-e $gCiVersionCfgFile)
    1076     {
    1077         open($projectfilehandle, "$gCiVersionCfgFile");
    1078     }else
    1079     {
    1080         print $RecodResultFile("open $gCiVersionCfgFile fail.
    ");
    1081         return;
    1082     }
    1083 
    1084     while(<$projectfilehandle>)
    1085     {
    1086         if($_ =~ /^(.*) (.*) (.*) (.*) (.*)$/)
    1087         {
    1088             if ($1 eq $version)
    1089             {
    1090                 $gBranchVersion = $2;
    1091                 $gCodeVersion = $4;
    1092                 print
    1093                 $1.
    1094                 "----".$2.
    1095                 "----".$3.
    1096                 "----".$4.
    1097                 "----".$5.
    1098                 "
    ";
    1099             }
    1100         }
    1101     }
    1102     close($projectfilehandle);
    1103 
    1104 }
    View Code
    https://blog.csdn.net/yyw794/article/details/77963310
    
    原因
    
    Lcov(1.10及往后)默认是关闭 分支覆盖率的。
    需要在参数中加入
    --rc lcov_branch_coverage=1
    才能使能。
    (即修改lcovrc的配置信息)
    解决措施
    
    ENABLE_BRANCH="--rc lcov_branch_coverage=1"
    lcov -c -d $TESTCASE_DIR -o $info_file  ${ENABLE_BRANCH} 1>/dev/null
    
    另外,genhtml中要添加上面的参数
    
    genhtml --branch-coverage  -o $COVERAGE_DIR $GENHTML_OPTIONS ${ENABLE_BRANCH} $info_file 1>/dev/null
    
    你看看jenkins的单元测试的html输出,是否新增了分支覆盖率统计。

    Executed 3 out of 3 tests: 3 tests pass.
    run test succ
    cp dbg succ
    find: `bazel-out/local-opt/bin/modules/': No such file or directory
    cp opt succ
    Capturing coverage data from data/cov/objs
    Found gcov version: 8.1.0
    Scanning data/cov/objs for .gcda files ...
    Found 150 data files in data/cov/objs
    Processing data/proto/static_info.pb.pic.gcda
    geninfo: ERROR: /apollo/data/cov/objs/modules/data/proto/static_info.pb.pic.gcno: reached unexpected end of file
    ============================
    [ERROR] lcov failed!
    (standard_in) 2: syntax error
    [INFO] Took  seconds
    ============================

    gcc -fprofile-arcs -ftest-coverage -o test test.c
    lcov --directory . --capture --output-file test.info
    genhtml -o results test.info

    https://github.com/linux-test-project/lcov
    lcov release version cannot resolve gcc 8. Use the github code and install 1.13.

    google test lcov genhtml 产生覆盖率xml文件,去除不需要的文件(include),或者包含需要的(source)

    https://blog.csdn.net/hanshuai584044490/article/details/83374617

    问题:在产生了.gcno 和 .gcda两个文件后,使用lcov -c -d Debug/source/ -o Debug/coverage.info 产生中间文件coverage.info文件,然后用genhtml -o output/  Debug/coverage.info产生html文件,发现产生的index.xml文件包含了include,甚至/usr/*下的公共头文件,怎么去除这些不需要统计覆盖率的文件?
    1。正向提取需要的文件:
    //比如希望把source相关的路径提取出来
    lcov --extract Debug/coverage.info '*source/*' -o Debug/finalresult.info
    //然后产生的xml就包含所有source相关的文件
    genhtml -o output/  Debug/finalresult.info
    2。反向去除不需要的文件:
    //比如希望去除UnitTest 和/usr/相关文件:
    lcov --remove Debug/coverage.info '*UnitTest/*' '/usr/*' -o Debug/finalresult.info
    //然后产生的xml就去除了UnitTest 和/usr/相关的文件
    genhtml -o output/  Debug/finalresult.info
    注意:lcov 不允许同时使用--extract  和  --remove

     
  • 相关阅读:
    Web CI/CD Continuous Integration / Continuous Delivery / Continuous Deployment
    hd + TP-Link Switch / wanzhaojiaohuanji / spf+ / TL-ST1008F / TL-ST5016F
    彻底理解js中this的指向,不必硬背(转)
    H5本地存储(转)
    jquery获得 当前页面url的变量
    js中实现base64加密、解密
    项目中easyui-tooltip提示消息运用
    Jquery生成二维码(微信中长按图片识别二维码功能)
    [hdu 3068] Manacher算法O(n)最长回文子串
    Hello world !
  • 原文地址:https://www.cnblogs.com/cjyp/p/9993667.html
Copyright © 2011-2022 走看看