8 Star 66 Fork 29

alibaba / PolarDB-for-PostgreSQL

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
delta_coverage.pl 20.18 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
#!/usr/bin/perl -w
use strict;
use FileHandle;
use Getopt::Std;
use IO::File;
use POSIX qw(strftime);
format HEADER =
cover_test.pl -f diff.log -d ./ -l output.log -p prev_commit
Syntax: cover_test.pl -option value
-f: the diff log file / Required
-d: the fundamental dir / optional
-l: the output / optional
-p: the prev commit id / optional
.
my $debug = 0;
my ($diff, $directory, $log, $prev_commit);
my $delta_path = "coverage";
&do_opt();
if(!defined $prev_commit)
{
$prev_commit=`git rev-parse HEAD~1`;
}
my $reg_line = '(.*)\n$';
my $current_commit=`git rev-parse HEAD~0`;
my $current_branch=`git rev-parse --abbrev-ref HEAD`;
$diff = "diff.log";
$prev_commit = &ppgrep($prev_commit, $reg_line, 1);
$current_commit = &ppgrep($current_commit, $reg_line, 1);
$prev_commit = $prev_commit->[0];
$current_commit = $current_commit->[0];
system("git config diff.renameLimit 10000;
git diff $prev_commit $current_commit > $diff");
if(!defined $diff)
{
&crit_record("pls input diff file");
}
if(!defined $directory)
{
$directory =".";
}
if(defined $log)
{
print "pls check the execute message in [$delta_path/$log]\n";
print "pls check the delta result in [$delta_path/delta_coverage.out]\n";
my $fd =POSIX::open( "$delta_path/$log", &POSIX::O_CREAT | &POSIX::O_WRONLY, 0640);
POSIX::dup2($fd, 1);
POSIX::dup2($fd, 2);
}
&record("directory=[$directory]; diff=[$diff];");
#interpret the diff file
my($hd_diff) = &getFileHandle($diff,"r"); #diff.org file
if (!defined $hd_diff)
{
&crit_record("diff [$diff] init fail, pls check it!");
}
&record("begin to interpret diff file!");
my $reg_diff = 'diff --git [ab]/(.+?)[\s\n]';
my $reg_add = '^\+(.*)';
my @reg_old = ('^-');
my @reg_del = ('^\+') ;
#my @reg_file = ('\.h$','\.cc$','\.c$','\.ic$');
my @reg_file = ('\.c$', '\.cpp$');
my $type_gcno = "gcno";
my $type_gcov = "gcov";
my $reg_cnt = '^@@.*?\d*,\d*.*?(\d*),(\d*) @@';
my $reg_gcov_1 = '^-:\s*(\d+):(.*)';
my $reg_gcov_2 = '^(#####|\d+):\s*(\d+):(.*)';
my $reg_gcov_3 = '^#####:\s*(\d+):(.*)';
my $reg_hgcov_file = '\.h\.gcov';
my $reg_file_prefix = '(.*)\..*';
my $line;
my %src_file = ();
my ($ref_raw_line, $raw_line, $key);
my ($bcnt, $ecnt) =(0,0);
my $delta =-1;
my $current =0;
my $in_block =0;
my $result_fd;
open($result_fd, ">$delta_path/delta_coverage.txt");
my $diff_line_num = 0;
my $no_test_line_num = 0;
while($line = $hd_diff->getline())
{
# find the file
$ref_raw_line = &ppgrep($line, $reg_diff, 1);
if(defined $ref_raw_line)
{
$in_block = 0;
$delta = -1;
$raw_line = $ref_raw_line->[0];
$raw_line = "$directory/$raw_line";
&debug_record("diff file has: $raw_line");
my @add_lines = ();
$key = $raw_line;
$src_file{$key} = \@add_lines;
$bcnt = 0;
$ecnt = 0;
next;
}
$ref_raw_line = &ppgrep($line, $reg_cnt, 2);
if(defined $ref_raw_line)
{
$in_block = 1;
$delta = -1;
my $c1 = $ref_raw_line->[0];
my $c2 = $ref_raw_line->[1];
$bcnt = $c1;
$ecnt = $c1+$c2-1;
$current = $c1-1;
print("\tdiff file has: $key: begin: $bcnt end: $ecnt\n");
next;
}
if ($in_block == 0)
{
next;
}
my $is_old = &filterLine(\@reg_old, $line);
if ($is_old == 0)
{
next;
}
$current = $current + 1;
#find the lines with head of '+'
$ref_raw_line = &ppgrep($line, $reg_add, 1);
if(defined $ref_raw_line)
{
my $new_ref_array = $src_file{$key};
&update_ecnt_by_bcnt($new_ref_array, $bcnt);
$raw_line = $ref_raw_line->[0];
$delta = $delta+1;
#del the backspace
$raw_line = &delbackspace($raw_line);
if (! defined $raw_line)
{
next;
}
&debug_record("diff file lines: $raw_line");
my $tmp_ref_array = $src_file{$key};
my @st_line = ($raw_line,$bcnt, $bcnt+$delta);
push(@$tmp_ref_array, \@st_line);
next;
}
elsif (!defined $ref_raw_line)
{
$bcnt = $current+1;
$delta = -1;
}
}
#-------------------------------print the currect line scope---------------------------------
my $value;
my $repeat = -1;
print "\n";
&record("begin to amend diff file[amend the bcnt, ecnt]!");
while(($key, $value) = each %src_file)
{
$repeat = -1;
foreach my $ref_correct(@$value)
{
my ($line_correct, $bcnt_correct, $ecnt_correct) =@$ref_correct;
&debug_record("\tline:$line_correct|bcnt=$bcnt_correct|ecnt=$ecnt_correct\n");
if ($repeat == $bcnt_correct)
{
next;
}
else
{
$repeat =$bcnt_correct;
print("\tdiff file has: $key: begin: $bcnt_correct end: $ecnt_correct\n");
}
}
}
print "\n";
#-------------------------------filter the not c/c++/h source file---------------------------------
my @filtered_file = ();
my @valid_file = ();
my $all_file_cnt = 0;
while(($key, $value) = each %src_file)
{
$all_file_cnt++;
# filter the file
my $ret = &filterLine(\@reg_file, $key);
if($ret == 0)
{
push(@valid_file, $key);
next;
}
else
{
push(@filtered_file, $key);
}
}
my $novalid_cnt = scalar(@filtered_file);
my $valid_cnt = $all_file_cnt - $novalid_cnt;
&record("The diff log include : [$all_file_cnt\t] files");
&record("The valid source file: [$valid_cnt\t]; listing as below:\n");
my $add_lines_cnt;
foreach my $file(@valid_file)
{
$value = $src_file{$file};
$add_lines_cnt =scalar(@$value);
print "\t\t\t lines:[$add_lines_cnt\t];file:[$file]\n";
}
&record("The filtered file: [$novalid_cnt\t]; listing as below:\n");
foreach my $file(@filtered_file)
{
$value = $src_file{$file};
$add_lines_cnt =scalar(@$value);
print "\t\t\t lines:[$add_lines_cnt\t];file:[$file]\n";
}
#---------------------------------begin to check-----------------------------------------------------
&record("begin to check files:");
my ($file_name, $file_gcno, $file_name_gcno, $file_gcov, $file_name_gcov, $file_path);
print $result_fd "==============Delta Code Coverage Start==============\n";
print $result_fd "current_branch = $current_branch\n";
print $result_fd "prev_commit = $prev_commit\ncurrent_commit = $current_commit\n\n";
my $total_test_line_num = 0;
my $total_diff_line_num = 0;
my $total_no_cover_line_num = 0;
my @no_compile_files = ();
my @no_test_files = ();
my $reg_no_test_directory = '^./src/test/';
my $no_test_directory;
foreach my $file(@valid_file)
{
print("\nfile: $file------------------------------------------\n");
if (-e $file) #diff file
{
print $result_fd "file [$file] begin--------------------\n";
$file_name = &getFileName($file);
#----------------debug
if( $debug and $file_name ne "mysqld.cc")
{
next;
}
#exclude files from "./src/test" directory
$no_test_directory = &isgrep($file, $reg_no_test_directory);
if($no_test_directory == 0)
{
print $result_fd " INFO: Test files are not included in delta coverage.\n";
print $result_fd "file [$file] end----------------------\n\n";
next;
}
$file_path = &getFilePath($file);
$file_name_gcno = &genTargetFileNameFor51($file_name, $type_gcno); #turn *.c.gcno to *.gcno
$file_gcno = "$file_path/$file_name_gcno";
&record("file = [$file]; gcno = [$file_gcno]");
if(!defined $file_gcno or ! -e $file_gcno)
{
&warn_record("file [$file_name_gcno] is not compiled.");
print $result_fd " WARNING: file [$file] is not compiled!\n";
push(@no_compile_files, $file);
}
else
{
#gen the gcov file
$file_name_gcov = &genTargetFileName($file_name, $type_gcov);
$file_gcov = "$directory/$delta_path/$file_name_gcov";
my $ret = &gengcov($file_name, $file_name_gcno, $file_name_gcov, $file_path, $directory);
if ($ret != 0)
{
&warn_record("file [$file_name_gcno] is not tested!");
print $result_fd " WARNING: file [$file] is not tested!\n";
push(@no_test_files, $file);
}
else
{
&record("......begin to scan gcov file [$file_gcov]......");
my $ref_diff_lines = $src_file{$file};
print $result_fd "Test Situation:\n";
&compare($ref_diff_lines, $file_gcov);
my $test_line_num = $diff_line_num - $no_test_line_num;
print $result_fd "Test Rate: $test_line_num / $diff_line_num\n";
$total_test_line_num = $total_test_line_num + $test_line_num;
$total_diff_line_num = $total_diff_line_num + $diff_line_num;
}
}
print $result_fd "file [$file] end----------------------\n\n";
}
else
{
&warn_record("file [$file] not exists!");
print $result_fd "file [$file] does not exist";
}
}
print $result_fd "\n---------------------------------------\n";
print $result_fd "Total Test Situation:\n";
print $result_fd "No Cover Lines: $total_no_cover_line_num\n";
my $no_compile_num = @no_compile_files;
my $no_test_num = @no_test_files;
print $result_fd "No Compile Files: $no_compile_num\n";
foreach my $file(@no_compile_files)
{
print $result_fd " $file\n";
}
print $result_fd "No Test Files: $no_test_num\n";
foreach my $file(@no_test_files)
{
print $result_fd " $file\n";
}
if ($total_diff_line_num == 0)
{
print $result_fd "No different line in .c file\n";
}
else
{
my $test_rate = ($total_test_line_num / $total_diff_line_num) * 100;
print $result_fd "Test Rate: $total_test_line_num / $total_diff_line_num = $test_rate%\n";
}
#------------------------------------------------------------
#correct the end line number
#------------------------------------------------------------
sub update_ecnt_by_bcnt()
{
my($ref_array, $bcnt) = @_;
if(defined $ref_array)
{
foreach my $ref(@$ref_array)
{
my($tmp_line, $tmp_bcnt, $tmp_ecnt) =@$ref;
if ($tmp_bcnt == $bcnt)
{
@$ref =($tmp_line, $tmp_bcnt, $tmp_ecnt+1);
}
}
}
}
#------------------------------------------------------------
#find the file
#------------------------------------------------------------
sub find_gcno(){
my($file_name_gcno, $dir) =@_;
my @result = `find $dir -name '$file_name_gcno'`;
if(defined $result[0]){
chomp($result[0]);
return $result[0];
}
else{
return undef;
}
}
#----------------------------------------------------
#append the file type
#----------------------------------------------------
sub genTargetFileName(){
my($file_name, $type) = @_;
my $type_file = "$file_name.$type";
return $type_file;
}
sub genTargetFileNameFor51(){
my($file_name, $type) = @_;
my $ref_file_prefix = &ppgrep($file_name, $reg_file_prefix, 1);
my $file_prefix = $ref_file_prefix->[0];
return "$file_prefix.$type";
}
#-----------------------------------------------------
#get the filename from string
#-----------------------------------------------------
sub getFileName(){
my($full_path) = @_;
my $file_name;
if($full_path =~ /.*\/(.*?)$/){
$file_name = $1;
}
else{
$file_name = $full_path;
}
return $file_name;
}
#-----------------------------------------------------
# POLAR: get the file path from string
#-----------------------------------------------------
sub getFilePath()
{
my($full_path) = @_;
my $file_path;
if($full_path =~ /(.*)\/(.*?)$/)
{
$file_path = $1;
}
else
{
$file_path = $full_path;
}
return $file_path;
}
#------------------------------------------------------------------------
#
#------------------------------------------------------------------------
sub compare()
{
my ($ref_diff_lines, $file_gcov) =@_;
my $hd_gcov = &getFileHandle($file_gcov, "r");
my $reg = "^#####:";
my $reg_no_cover = '\/\*no cover line\*\/$'; #"/*no cover line*/"
my $reg_no_cover_begin = '\/\*no cover begin\*\/$'; #"/*no cover begin*/"
my $reg_no_cover_end = '\/\*no cover end\*\/$'; #"/*no cover end*/"
my $no_cover_line_num = 0;
my $in_no_cover = 0;
my $after_no_cover_line = 0;
my $bcnt;
my $ecnt;
my $sr_cnt;
my $cov_ret;
my $temp_ret;
my $temp_line;
my $ret;
#print output to report.txt
$diff_line_num = 0;
$no_test_line_num = 0;
while(my $line = $hd_gcov->getline())
{
my $parse_line = $line;
#&debug_record("the gcno lines: $parse_line");
#step 1: del backspace
$parse_line = &delbackspace($parse_line);
if(!defined $parse_line)
{
next;
}
# "/*no cover line*/"
$cov_ret = &isgrep($parse_line, $reg_no_cover);
if($cov_ret == 0) #find "/*no cover line*/"
{
$after_no_cover_line = 1;
next;
}
# "/*no cover begin*/"
$cov_ret = &isgrep($parse_line, $reg_no_cover_begin);
if( $cov_ret == 0 and $in_no_cover == 0)
{
$in_no_cover = 1;
next;
}
# "/*no cover end*/"
$cov_ret = &isgrep($parse_line, $reg_no_cover_end);
if ($cov_ret == 0 and $in_no_cover == 1)
{
$in_no_cover = 0;
next;
}
#step 2: not grep -
$ret = &isgrep($parse_line, $reg_gcov_1); #return 0 if match '-'
if($ret == 0)
{
next;
}
if($in_no_cover == 1 or $after_no_cover_line == 1) #(between "/*no cover begin*/" and "/*no cover end*/") or (after "/*no cover line*/)"
{
$after_no_cover_line = 0;
$no_cover_line_num++;
next;
}
$temp_line = $parse_line;
$parse_line = &ppgrep($parse_line, $reg_gcov_2, 3);
if (!defined $parse_line)
{
next;
}
$sr_cnt = $parse_line->[1]; #line number
$parse_line = $parse_line->[2]; #statement
#step 3: del backspace
$parse_line = &delbackspace($parse_line);
if(!defined $parse_line)
{
next;
}
#step 4: del the no meaning line
$ret = &ismeaning($parse_line);
if($ret != 0)
{
next;
}
$temp_ret = &isgrep($temp_line, $reg_gcov_3); #retrun 0 if match #####
foreach my $diff_line(@$ref_diff_lines)
{
$ret = &isMatchStr($parse_line, $sr_cnt, $diff_line);
&debug_record("begin: $line end: $diff_line : result is $ret");
my $string;
if($ret == 0)
{
$diff_line_num = $diff_line_num + 1;
print "$line";
print $result_fd "$line";
if ($temp_ret == 0)
{
#print $result_fd "$line";
$no_test_line_num = $no_test_line_num + 1;
}
last;
}
}
}
if($no_cover_line_num > 0)
{
$total_no_cover_line_num = $total_no_cover_line_num + $no_cover_line_num;
my $str2;
my $str1 = "INFO: Filter the no cover lines: $no_cover_line_num";
if($in_no_cover == 1 or $after_no_cover_line == 1)
{
$str2 = "FATAL: Some 'no cover hint' don't match, pls check!!!";
}
else
{
$str2 = "INFO: All 'no cover hint' match correctly";
}
&sp_warn_record($str1, $str2);
if($in_no_cover == 1 or $after_no_cover_line == 1)
{
exit(1);
}
}
}
#------------------------------------------------------------------
#judge it is meaning line
#------------------------------------------------------------------
sub ismeaning(){
my($str) = @_;
if( $str =~ /[0-9]|[a-z]|[A-Z]/){
return 0;
}
else{
return 1;
}
}
#------------------------------------------------------------------
#
#------------------------------------------------------------------
sub isMatchStr(){
my($parse_line, $sr_cnt, $diff_line) = @_;
my ($bcnt, $ecnt);
($diff_line, $bcnt, $ecnt) = @$diff_line;
my $ret = &isfullstr($parse_line, $diff_line);
if ($ret == 0){
if($bcnt != 0 or $ecnt != 0){
if( $sr_cnt >= $bcnt and $sr_cnt <= $ecnt){
return 0;
}
else{
return 1;
}
}
else{
return 0;
}
}
return 1;
}
#------------------------------------------------------------------
#
#------------------------------------------------------------------
sub issubstr(){
my($full, $str) = @_;
my $pos = index($full, $str);
if( defined $pos and $pos >= 0){
return 0;
}
return 1;
}
#------------------------------------------------------------------
#
#------------------------------------------------------------------
sub isfullstr(){
my($full, $str) = @_;
if ($full eq $str){
return 0;
}
return 1;
}
#------------------------------------------------------------------
#generate the gcov file
#------------------------------------------------------------------
sub gengcov()
{
my ($file_name, $file_name_gcno, $file_name_gcov, $file_path, $directory) = @_;
my $file_gcno = "$file_path/$file_name_gcno";
if(!defined $file_gcno)
{
return 1;
}
# POLAR
my $ret1 = system("cd $file_path;
gcov $file_name -o $file_name_gcno >/dev/null"); #return 0 if success
my $ret2 = system("mv $file_path/$file_name_gcov $directory/$delta_path/$file_name_gcov");
$ret1 = $ret1 >> 8;
$ret2 = $ret2 >> 8;
if($ret1 == 0 && $ret2 == 0)
{
return 0;
}
else
{
return 1;
}
}
#-------------------------------------------------------
#replace the file type
#-------------------------------------------------------
sub replaceFileType(){
my ($str, $target) = @_;
my $newstr = $str;
if($str =~ /(.*)\..*?$/){
return "$1.$target";
}
return undef;
}
#-------------------------------------------------------
#truncate the backspace on the head and tail
#-------------------------------------------------------
sub delbackspace(){
my($str) =@_;
if( !defined $str or $str eq ""){
return undef;
}
$str =~s/^\s+//g;
$str =~s/\$\s+//g;
if ($str eq ""){
return undef;
}
return $str;
}
#------------------------------------------------------
#judge the str is in array
#------------------------------------------------------
sub isStrInArray(){
my (@array, $line) =@_;
foreach my $tmp(@array){
if($line eq $tmp){
return 0;
}
}
return 1;
}
#-------------------------------------------------------
#justify is success to grep the line according to regex
#-------------------------------------------------------
sub isgrep()
{
my ($line, $reg) =@_;
if($line =~ /$reg/)
{
return 0;
}
else
{
return 1;
}
}
#------------------------------------------------------
#grep the result
#------------------------------------------------------
sub ppgrep()
{
my($line, $reg, $cnt) = @_;
my @ret = ();
if($line =~ /$reg/i)
{
if ($cnt >=1){
push(@ret, $1);
}
if ($cnt >=2){
push(@ret, $2);
}
if ($cnt >=3){
push(@ret, $3);
}
if ($cnt >=4){
return undef;
}
return \@ret;
}
else
{
return undef;
}
}
#----------------------------------------------------------
#filter the lines according to reg array
#----------------------------------------------------------
sub filterLine(){
my($ref_reg, $line) = @_;
my @arr_filter = @$ref_reg;
foreach my $reg(@arr_filter){
my $ret =&isgrep($line,$reg);
if( $ret == 0){
return 0;
}
}
return 1;
}
#------------------------------------------
#record the information
#------------------------------------------
sub record(){
my($string) = @_;
my $current_time = strftime("%Y-%m-%d %H:%M:%S", localtime(time));
print("$current_time: info: $string\n");
}
#------------------------------------------
#record the crit
#------------------------------------------
sub crit_record(){
my($string) = @_;
my $current_time = strftime("%Y-%m-%d %H:%M:%S", localtime(time));
print("$current_time: crit: $string\n");
exit(1);
}
#------------------------------------------
#record the crit
#------------------------------------------
sub debug_record(){
my($string) = @_;
if( $debug ==1){
my $current_time = strftime("%Y-%m-%d %H:%M:%S", localtime(time));
print("$current_time: debug: $string\n");
}
}
#------------------------------------------
#record the warn
#------------------------------------------
sub warn_record(){
my($string) = @_;
my $current_time = strftime("%Y-%m-%d %H:%M:%S", localtime(time));
print("$current_time: warn: $string\n");
}
sub sp_warn_record(){
my($str1, $str2) = @_;
print $result_fd " $str1\n";
print $result_fd " $str2\n";
}
#---------------------------------------------------------------------
#init the file handle
#---------------------------------------------------------------------
sub getFileHandle{
my($file, $mode) = @_;
my ($hd);
$hd = new FileHandle($file,"$mode");
return $hd;
}
#---------------------------------------------------------------------------------
#split the input parameters
#---------------------------------------------------------------------------------
sub do_opt{
use vars '$opt_h','$opt_H','$opt_f','$opt_d','$opt_l','$opt_p';
my $returncode = getopts('hH:f:d:l:p:');
&do_help() if(defined $opt_h or defined $opt_H or $returncode!=1);
$diff = $opt_f if(defined $opt_f);
$directory = $opt_d if(defined $opt_d);
$log = $opt_l if(defined $opt_l);
$prev_commit = $opt_p if(defined $opt_p);
$prev_commit = "$prev_commit\n";
}
#----------------------------------------------------------------------------------
#give help information and exit;
#---------------------------------------------------------------------------------
sub do_help{
$~ = "HEADER";
write;
exit(1);
}
C++
1
https://gitee.com/mirrors_alibaba/PolarDB-for-PostgreSQL.git
git@gitee.com:mirrors_alibaba/PolarDB-for-PostgreSQL.git
mirrors_alibaba
PolarDB-for-PostgreSQL
PolarDB-for-PostgreSQL
POLARDB_11_STABLE

搜索帮助