diff --git a/coverage/check_coverage.sh b/coverage/check_coverage.sh new file mode 100755 index 0000000000..5dcc1fe0d4 --- /dev/null +++ b/coverage/check_coverage.sh @@ -0,0 +1,118 @@ +#!/bin/bash + +line_cover_base=75 +mds_branch_base=70 +snapshot_branch_base=70 +client_branch_base=78 +other_branch_base=65 +line_cover_all=`cat coverage/index.html | grep -A 5 "Lines" | grep % | awk -F "%" '{print $1}' | awk -F '>' '{print $2}' | awk -F '.' '{print $1}'` + +if(("$line_cover_all" < "$line_cover_base")) +then + echo "line cover not ok!."; + echo $line_cover_all; + exit -1 +else + echo "line cover ok!."; + echo $line_cover_all; +fi + +for i in `find coverage -type d | grep mds`;do for j in $i;do find $j -name index.html | xargs cat | grep -A 5 "Branches" | grep % | awk -F '>' '{print $2}' | awk '{print $1}' | awk -F '.' '{print $1}' | grep -v tr;done;done > mds.all +if [ -s mds.all ]; then + mds_branch=`cat mds.all | awk '{sum+=$1} END {print sum/NR}' | awk -F '.' '{print $1}'` +else + mds_branch=0 +fi +if(("$mds_branch" < "$mds_branch_base")) +then + echo "mds_branch cover not ok!."; + echo $mds_branch; + exit -1 +else + echo "mds_branch cover ok!."; + echo $mds_branch; +fi + +for i in `find coverage -type d | grep tools`;do for j in $i;do find $j -name index.html | xargs cat | grep -A 5 "Branches" | grep % | awk -F '>' '{print $2}' | awk '{print $1}' | awk -F '.' '{print $1}' | grep -v tr;done;done > tools.all +if [ -s tools.all ]; then + tools_branch=`cat tools.all | awk '{sum+=$1} END {print sum/NR}' | awk -F '.' '{print $1}'` +else + tools_branch=0 +fi + +if(("$tools_branch" < "$other_branch_base")) +then + echo "tools_branch cover not ok!."; + echo $tools_branch; + #exit -1 +else + echo "tools_branch cover ok!."; + echo $tools_branch; +fi + +for i in `find coverage -type d | grep common`;do for j in $i;do find $j -name index.html | xargs cat | grep -A 5 "Branches" | grep % | awk -F '>' '{print $2}' | awk '{print $1}' | awk -F '.' '{print $1}' | grep -v tr;done;done > common.all +if [ -s common.all ]; then + common_branch=`cat common.all | awk '{sum+=$1} END {print sum/NR}' | awk -F '.' '{print $1}'` +else + common_branch=0 +fi +if(("$common_branch" < "$other_branch_base")) +then + echo "common_branch cover not ok!."; + echo $common_branch; + exit -1 +else + echo "common_branch cover ok!."; + echo $common_branch; +fi + + +for i in `find coverage -type d | grep chunkserver`;do for j in $i;do find $j -name index.html | xargs cat | grep -A 5 "Branches" | grep % | awk -F '>' '{print $2}' | awk '{print $1}' | awk -F '.' '{print $1}' | grep -v tr;done;done > chunkserver.all +if [ -s chunkserver.all ]; then + chunkserver_branch=`cat chunkserver.all | awk '{sum+=$1} END {print sum/NR}' | awk -F '.' '{print $1}'` +else + chunkserver_branch=0 +fi +if(("$chunkserver_branch" < "$other_branch_base")) +then + echo "chunkserver_branch cover not ok!."; + echo $chunkserver_branch; + exit -1 +else + echo "chunkserver_branch cover ok!."; + echo $chunkserver_branch; +fi + + +for i in `find coverage/client -type d | grep client`;do for j in $i;do find $j -name index.html | xargs cat | grep -A 5 "Branches" | grep % | awk -F '>' '{print $2}' | awk '{print $1}' | awk -F '.' '{print $1}' | grep -v tr;done;done > client.all +if [ -s chunkserver.all ]; then + client_branch=`cat client.all | awk '{sum+=$1} END {print sum/NR}' | awk -F '.' '{print $1}'` +else + client_branch=0 +fi +if(("$client_branch" < "$client_branch_base")) +then + echo "client_branch cover not ok!."; + echo $client_branch; + exit -1 +else + echo "client_branch cover ok!."; + echo $client_branch; +fi + +for i in `find coverage -type d | grep fs`;do for j in $i;do find $j -name index.html | xargs cat | grep -A 5 "Branches" | grep % | awk -F '>' '{print $2}' | awk '{print $1}' | awk -F '.' '{print $1}' | grep -v tr;done;done > sfs.all +if [ -s sfs.all ]; then + sfs_branch=`cat sfs.all | awk '{sum+=$1} END {print sum/NR}' | awk -F '.' '{print $1}'` +else + sfs_branch=0 +fi +if(("$sfs_branch" < "$other_branch_base")) +then + echo "sfs_branch cover not ok!."; + echo $sfs_branch; + #exit -1 +else + echo "sfs_branch cover ok!."; + echo $sfs_branch; +fi + diff --git a/coverage/filterbr.py b/coverage/filterbr.py new file mode 100755 index 0000000000..64ee2da06f --- /dev/null +++ b/coverage/filterbr.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 + +# 2017, Georg Sauthoff , GPLv3 + +import sys + +def skip_comments(lines): + state = 0 + for line in lines: + n = len(line) + l = '' + p = 0 + while p < n: + if state == 0: + a = line.find('//', p) + b = line.find('/*', p) + if a > -1 and (a < b or b == -1): + l += line[p:a] + p = n + elif b > -1 and (b < a or a == -1): + l += line[p:b] + p = b+2 + state = 1 + else: + l += line[p:] + p = n + elif state == 1: + a = line.rfind('*/', p) + if a == -1: + p = n + else: + p = a + 2 + state = 0 + yield l + +def cond_lines(lines): + state = 0 + pcnt = 0 + for nr, line in enumerate(lines, 1): + if not line: + continue + n = len(line) + p = 0 + do_yield = False + while p < n: + if state == 0: +# p = line.strip().startswith('if', p) + p = line.find('if', p) + if p == -1: + p = n + continue + if (p == 0 or not line[p-1].isalpha()) \ + and (p+2 == len(line) or not line[p+2].isalpha()): + do_yield = True + state = 1 + p += 2 + elif state == 1: + do_yield = True + p = line.find('(', p) + if p == -1: + p = n + else: + p += 1 + state = 2 + pcnt = 1 + elif state == 2: + do_yield = True + for p in range(p, n): + if line[p] == '(': + pcnt += 1 + elif line[p] == ')': + pcnt -= 1 + if not pcnt: + state = 0 + break + p += 1 + if do_yield: + yield nr + +def cond_lines_from_file(filename): + with open(filename) as f: + yield from cond_lines(skip_comments(f)) + +def filter_lcov_trace(lines): + nrs = set() + for line in lines: + if line.startswith('SF:'): + nrs = set(cond_lines_from_file(line[3:-1])) + elif line.startswith('BRDA:'): + xs = line[5:].split(',') + nr = int(xs[0]) if xs else 0 + if nr not in nrs: + continue + yield line + +def filter_lcov_trace_file(s_filename, d_file): + with open(s_filename) as f: + for l in filter_lcov_trace(f): + print(l, end='', file=d_file) + +if __name__ == '__main__': + #for l in cond_lines_from_file(sys.argv[1]): + # print(l) + + filter_lcov_trace_file(sys.argv[1], sys.stdout) + + #with open(sys.argv[1]) as f: + # for l in skip_comments(f): + # print(l) + + diff --git a/coverage/gen-coverage-nebd.py b/coverage/gen-coverage-nebd.py new file mode 100755 index 0000000000..5ce58890a5 --- /dev/null +++ b/coverage/gen-coverage-nebd.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 + +# 2017, Georg Sauthoff , GPLv3 + +import argparse +import logging +import os +import subprocess +import shutil +import sys + +sys.path.insert(0, os.path.dirname(__file__)) +import filterbr + +log = logging.getLogger(__name__) + +#ex_path = [ '/usr/include/*', 'unittest/*', 'lib*/*', '*@exe/*', 'example/*' ] +ex_path = [ '/usr/include/*', '/usr/local/include/*', '/usr/lib/*', '*/bazel_out/*', '*/k8-dbg/*', 'test/*', '*/test/*', '*/external/*' , '*/include/*' , '*/thirdparties/*' , '*/client_proto/*' ] + +brflag = ['--rc', 'lcov_branch_coverage=1'] + +lcov = 'lcov' +base = os.path.abspath('.') + +cov_init_raw = 'coverage_init_raw.info' +cov_post_raw = 'coverage_post_raw.info' +cov_init = 'coverage_init.info' +cov_post = 'coverage_post.info' +cov_br = 'coverage.info' +cov = 'coverage.info' +report_dir = 'coverage' + +def setup_logging(): + log_format = '{rel_secs:6.1f} {lvl} {message}' + log_date_format = '%Y-%m-%d %H:%M:%S' + + class Relative_Formatter(logging.Formatter): + level_dict = { 10 : 'DBG', 20 : 'INF', 30 : 'WRN', 40 : 'ERR', + 50 : 'CRI' } + def format(self, rec): + rec.rel_secs = rec.relativeCreated/1000.0 + rec.lvl = self.level_dict[rec.levelno] + return super(Relative_Formatter, self).format(rec) + + log = logging.getLogger() # root logger + log.setLevel(logging.DEBUG) + ch = logging.StreamHandler() + ch.setLevel(logging.INFO) + ch.setFormatter(Relative_Formatter(log_format, log_date_format, style='{')) + log.addHandler(ch) + +def mk_arg_parser(): + p = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description='Do some stuff', + epilog='...') + p.add_argument('--html', action='store_true', default=True, + help='generate HTML report (default: on)') + p.add_argument('--no-html', dest='html', action='store_false', + help='disable html report generation') + p.add_argument('--filter-br', action='store_true', default=True, + help='filter branch coverage data (default: on)') + p.add_argument('--no-filter-br', dest='filter_br', action='store_false', + help='disable branch filtering') + return p + +def parse_args(*a): + arg_parser = mk_arg_parser() + args = arg_parser.parse_args(*a) + global cov_br + if args.filter_br: + cov_br = 'coverage_br.info' + return args + +def run(*args, **kw): + log.info('Executing: ' + ' '.join(map(lambda s:"'"+s+"'", args[0]))) + return subprocess.run(*args, **kw, check=True) + + +def main(args): + run([lcov, '--directory', 'src', '--capture', '-o', cov_post_raw] + brflag ) + run([lcov, '--directory', 'src', '--capture', '--initial', '-o', cov_init_raw]) + + for i, o in [ (cov_init_raw, cov_init), (cov_post_raw, cov_post) ]: + run([lcov, '--remove', i] + ex_path + [ '-o', o] + brflag) + + run([lcov, '-a', cov_init, '-a', cov_post, '-o', cov_br] + brflag) + + if args.filter_br: + log.info('Filtering branch coverage data ({} -> {})'.format(cov_br, cov)) + with open(cov, 'w') as f: + filterbr.filter_lcov_trace_file(cov_br, f) + + if args.html: + shutil.rmtree(report_dir, ignore_errors=True) + run(['genhtml', cov, '--branch-coverage', '--ignore-errors', 'source', '-o', report_dir]) + + return 0 + +if __name__ == '__main__': + setup_logging() + args = parse_args() + sys.exit(main(args)) + + + diff --git a/coverage/gen-coverage.py b/coverage/gen-coverage.py new file mode 100755 index 0000000000..6a6926a99f --- /dev/null +++ b/coverage/gen-coverage.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 + +# 2017, Georg Sauthoff , GPLv3 + +import argparse +import logging +import os +import subprocess +import shutil +import sys + +sys.path.insert(0, os.path.dirname(__file__)) +import filterbr + +log = logging.getLogger(__name__) + +#ex_path = [ '/usr/include/*', 'unittest/*', 'lib*/*', '*@exe/*', 'example/*' ] +ex_path = [ '/usr/include/*', '/usr/local/include/*', '/usr/lib/*', '*/bazel_out/*', '*/k8-dbg/*', 'test/*', '*/test/*', '*/external/*' , '*/include/*' , '*/thirdparties/*' ] + +brflag = ['--rc', 'lcov_branch_coverage=1'] + +lcov = 'lcov' +base = os.path.abspath('.') + +cov_init_raw = 'coverage_init_raw.info' +cov_post_raw = 'coverage_post_raw.info' +cov_init = 'coverage_init.info' +cov_post = 'coverage_post.info' +cov_br = 'coverage.info' +cov = 'coverage.info' +report_dir = 'coverage' + +def setup_logging(): + log_format = '{rel_secs:6.1f} {lvl} {message}' + log_date_format = '%Y-%m-%d %H:%M:%S' + + class Relative_Formatter(logging.Formatter): + level_dict = { 10 : 'DBG', 20 : 'INF', 30 : 'WRN', 40 : 'ERR', + 50 : 'CRI' } + def format(self, rec): + rec.rel_secs = rec.relativeCreated/1000.0 + rec.lvl = self.level_dict[rec.levelno] + return super(Relative_Formatter, self).format(rec) + + log = logging.getLogger() # root logger + log.setLevel(logging.DEBUG) + ch = logging.StreamHandler() + ch.setLevel(logging.INFO) + ch.setFormatter(Relative_Formatter(log_format, log_date_format, style='{')) + log.addHandler(ch) + +def mk_arg_parser(): + p = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description='Do some stuff', + epilog='...') + p.add_argument('--html', action='store_true', default=True, + help='generate HTML report (default: on)') + p.add_argument('--no-html', dest='html', action='store_false', + help='disable html report generation') + p.add_argument('--filter-br', action='store_true', default=True, + help='filter branch coverage data (default: on)') + p.add_argument('--no-filter-br', dest='filter_br', action='store_false', + help='disable branch filtering') + return p + +def parse_args(*a): + arg_parser = mk_arg_parser() + args = arg_parser.parse_args(*a) + global cov_br + if args.filter_br: + cov_br = 'coverage_br.info' + return args + +def run(*args, **kw): + log.info('Executing: ' + ' '.join(map(lambda s:"'"+s+"'", args[0]))) + return subprocess.run(*args, **kw, check=True) + + +def main(args): + run([lcov, '--directory', 'src', '--capture', '-o', cov_post_raw] + brflag ) + run([lcov, '--directory', 'src', '--capture', '--initial', '-o', cov_init_raw]) + + for i, o in [ (cov_init_raw, cov_init), (cov_post_raw, cov_post) ]: + run([lcov, '--remove', i] + ex_path + [ '-o', o] + brflag) + + run([lcov, '-a', cov_init, '-a', cov_post, '-o', cov_br] + brflag) + + if args.filter_br: + log.info('Filtering branch coverage data ({} -> {})'.format(cov_br, cov)) + with open(cov, 'w') as f: + filterbr.filter_lcov_trace_file(cov_br, f) + + if args.html: + shutil.rmtree(report_dir, ignore_errors=True) + run(['genhtml', cov, '--branch-coverage', '--ignore-errors', 'source', '-o', report_dir]) + + return 0 + +if __name__ == '__main__': + setup_logging() + args = parse_args() + sys.exit(main(args)) + + + diff --git a/coverage/gen-coverage2.py b/coverage/gen-coverage2.py new file mode 100755 index 0000000000..43b9ccde78 --- /dev/null +++ b/coverage/gen-coverage2.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 + +# 2017, Georg Sauthoff , GPLv3 + +import argparse +import logging +import os +import subprocess +import shutil +import sys + +sys.path.insert(0, os.path.dirname(__file__)) +import filterbr + +log = logging.getLogger(__name__) + +#ex_path = [ '/usr/include/*', 'unittest/*', 'lib*/*', '*@exe/*', 'example/*' ] +ex_path = [ '/usr/include/*', '/usr/local/include/*', '/usr/lib/*', '*/bazel_out/*', '*/k8-dbg/*', 'test/*', '*/test/*', '*/external/*' , '*/include/*' , '*/thirdparties/*' , '*/snapshotcloneserver/*' ] + +brflag = ['--rc', 'lcov_branch_coverage=1'] + +lcov = 'lcov' +base = os.path.abspath('.') + +cov_init_raw = 'coverage_init_raw.info' +cov_post_raw = 'coverage_post_raw.info' +cov_init = 'coverage_init.info' +cov_post = 'coverage_post.info' +cov_br = 'coverage.info' +cov = 'coverage.info' +report_dir = 'coverage' + +def setup_logging(): + log_format = '{rel_secs:6.1f} {lvl} {message}' + log_date_format = '%Y-%m-%d %H:%M:%S' + + class Relative_Formatter(logging.Formatter): + level_dict = { 10 : 'DBG', 20 : 'INF', 30 : 'WRN', 40 : 'ERR', + 50 : 'CRI' } + def format(self, rec): + rec.rel_secs = rec.relativeCreated/1000.0 + rec.lvl = self.level_dict[rec.levelno] + return super(Relative_Formatter, self).format(rec) + + log = logging.getLogger() # root logger + log.setLevel(logging.DEBUG) + ch = logging.StreamHandler() + ch.setLevel(logging.INFO) + ch.setFormatter(Relative_Formatter(log_format, log_date_format, style='{')) + log.addHandler(ch) + +def mk_arg_parser(): + p = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description='Do some stuff', + epilog='...') + p.add_argument('--html', action='store_true', default=True, + help='generate HTML report (default: on)') + p.add_argument('--no-html', dest='html', action='store_false', + help='disable html report generation') + p.add_argument('--filter-br', action='store_true', default=True, + help='filter branch coverage data (default: on)') + p.add_argument('--no-filter-br', dest='filter_br', action='store_false', + help='disable branch filtering') + return p + +def parse_args(*a): + arg_parser = mk_arg_parser() + args = arg_parser.parse_args(*a) + global cov_br + if args.filter_br: + cov_br = 'coverage_br.info' + return args + +def run(*args, **kw): + log.info('Executing: ' + ' '.join(map(lambda s:"'"+s+"'", args[0]))) + return subprocess.run(*args, **kw, check=True) + + +def main(args): + run([lcov, '--directory', 'src', '--capture', '-o', cov_post_raw] + brflag ) + run([lcov, '--directory', 'src', '--capture', '--initial', '-o', cov_init_raw]) + + for i, o in [ (cov_init_raw, cov_init), (cov_post_raw, cov_post) ]: + run([lcov, '--remove', i] + ex_path + [ '-o', o] + brflag) + + run([lcov, '-a', cov_init, '-a', cov_post, '-o', cov_br] + brflag) + + if args.filter_br: + log.info('Filtering branch coverage data ({} -> {})'.format(cov_br, cov)) + with open(cov, 'w') as f: + filterbr.filter_lcov_trace_file(cov_br, f) + + if args.html: + shutil.rmtree(report_dir, ignore_errors=True) + run(['genhtml', cov, '--branch-coverage', '--ignore-errors', 'source', '-o', report_dir]) + + return 0 + +if __name__ == '__main__': + setup_logging() + args = parse_args() + sys.exit(main(args)) + + + diff --git a/coverage/test.py b/coverage/test.py new file mode 100755 index 0000000000..7c457e795f --- /dev/null +++ b/coverage/test.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +def lls(s): + d = {} + start = 0 + ans = 0 + for i,c in enumerate(s): + print "i,c %s %s" %(i,c) + if c in d: + print "c=%s" %c + start = max(start, d[c] + 1) + print "start=%s" %start + d[c] = i + print "d = %s" %d + ans = max(ans, i - start + 1) + print "ans=%s" %ans + print d + print ans + +lls("afal") diff --git a/coverage/tmp.py b/coverage/tmp.py new file mode 100755 index 0000000000..78bfda2a3b --- /dev/null +++ b/coverage/tmp.py @@ -0,0 +1,9 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +a = ['src/chunkserver/datastore/chunkfile_pool.cpp', 'src/fs/ext4_filesystem_impl.cpp', 'src/fs/wrap_posix.cpp'] + +a = [c.split('/', 1)[1] for c in a] +print a + + diff --git a/coverage/ut_incremental_check.py b/coverage/ut_incremental_check.py new file mode 100755 index 0000000000..2f757123a0 --- /dev/null +++ b/coverage/ut_incremental_check.py @@ -0,0 +1,226 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +###################################################################### +# Purpose: calculate UT coverage of git commits' new code +# Useage: ./ut_incremental_check.py +# Version: Initial Version by wahaha02 +###################################################################### + +__version__ = 'V1.0' +__author__ = 'wahaha02' +__date__ = '2016-7-25' +__doc__ = ''' +PURPOSE: +calculate UT coverage of git commits' new code + +USAGE: +./ut_incremental_check.py .. +example: +./ut_incremental_check.py "227b032..79196ba" '["source/soda/sp/lssp/i2c-v2/ksource"]' "coverage" 0.6 + +WORK PROCESS: +get changed file list between and , filter by options; +get changed lines per changed file; +based on , search .gcov.html per file, and get uncover lines; +create report file:ut_incremental_check_report.html and check (cover lines/new lines). + +UT: +./ut_incremental_check.py ut +''' + +__todo__ = ''' +TODO LIST: + 1. support svn + 2. refactory html report by django web template + 3. add commit info in html report + 4. prompt user/commit/date info when mouse point to uncovered line + 5. ... +''' + +import sys, os, re +import json +import commands +from HTMLParser import HTMLParser +from pprint import * + +DEBUG = 0 + +class GcovHTMLParser(HTMLParser): + def __init__(self): + HTMLParser.__init__(self) + self.uncovers = [] + self.covers = [] + self.islineNum = False + self.lineNum = 0 + + def handle_starttag(self, tag, attrs): + if tag == "span": + for a in attrs: + if a == ('class', 'lineNum'): + self.islineNum = True + if a == ('class', 'lineNoCov'): + self.uncovers.append(self.lineNum) + if a == ('class', 'lineCov'): + self.covers.append(self.lineNum) + + def handle_data(self, data): + if self.islineNum: + try: + self.lineNum = int(data) + except: + self.lineNum = -1 + + def handle_endtag(self, tag): + if tag == "span": + self.islineNum = False + +class UTCover(object) : + def __init__(self, since_until, monitor, lcov_dir, thresh) : + self.since, self.until = since_until.split('..') + self.monitor = json.loads(monitor) + self.lcov_dir = lcov_dir + self.thresh = float(thresh) + + def get_src(self): + # self.since, self.until, self.monitor + satus, output = commands.getstatusoutput("git diff --name-only %s %s" %(self.since, self.until)) + src_files = [f for f in output.split('\n') + for m in self.monitor if m in f + if os.path.splitext(f)[1][1:] in ['c', 'cpp']] + if DEBUG: pprint(src_files) + for i in src_files: + if i.find("main") > 0: + src_files.remove(i) + return src_files + + def get_change(self, src_files): + # self.since, self.until + changes = {} + for f in src_files: + satus, output = commands.getstatusoutput("git log --oneline %s..%s %s | awk '{print $1}'" %(self.since, self.until, f)) + commits = output.split('\n') + cmd = "git blame %s | grep -E '(%s)' | awk -F' *|)' '{print $6}'" %(f, '|'.join(commits)) + satus, lines = commands.getstatusoutput(cmd) + changes[f] = [ int(i) for i in lines.split('\n') if i.isdigit() ] + + + if DEBUG: pprint(changes) + return changes + + def get_ghp(self, f): + gcovfile = os.path.join(self.lcov_dir, f + '.gcov.html') + if not os.path.exists(gcovfile): + return None + + ghp = GcovHTMLParser() + ghp.feed(open(gcovfile, 'r').read()) + + return ghp + + def get_lcov_data(self, changes): + # self.lcov_dir + uncovers = {} + lcov_changes = {} + + for f, lines in changes.items(): + #print f + f = f.split('/', 1)[1] + #f = [c.split('/', 1)[1] for c in f] + ghp = self.get_ghp(f) + if not ghp: + uncovers[f] = lines + lcov_changes[f] = lines + continue + + if DEBUG: print f, ghp.uncovers, ghp.covers, lines + lcov_changes[f] = sorted(list(set(ghp.uncovers + ghp.covers) & set(lines))) + uncov_lines = list(set(ghp.uncovers) & set(lines)) + if len(uncov_lines) != 0: + uncovers[f] = sorted(uncov_lines) + ghp.close() + + return lcov_changes, uncovers + + def create_uncover_trs(self, uncovers): + tr_format = ''' + + %(file)s + %(uncov_lines)s + + + ''' + trs = '' + for f,v in uncovers.items(): + gcovfile = os.path.join(self.lcov_dir, f + '.gcov.html') + if os.path.exists(gcovfile): + s = '' + p = re.compile(r'^\s*(?P\d+)\s*') + for line in open(gcovfile, 'r').readlines(): + ps = p.search(line) + if ps: + s += '' %ps.group('num') + line + '' + else: + s += line + open(gcovfile, 'w').write(s) + + data = {'file':f, 'uncov_lines': + ", ".join(['%d' %(f, i, i) for i in v])} + trs += tr_format %data + + return trs + + def create_report(self, changes, uncovers): + change_linenum, uncov_linenum = 0, 0 + for k,v in changes.items(): + change_linenum += len(v) + for k,v in uncovers.items(): + uncov_linenum += len(v) + + cov_linenum = change_linenum - uncov_linenum + coverage = round(cov_linenum * 1.0 / change_linenum + if change_linenum > 0 else 1, 4) + + template = open('ut_incremental_coverage_report.template', 'r').read() + data = { 'cov_lines':cov_linenum, + 'change_linenum':change_linenum, + 'coverage': coverage * 100, + 'uncover_trs': self.create_uncover_trs(uncovers)} + open(os.path.join(self.lcov_dir, 'ut_incremental_coverage_report.html'), + 'w').write(template %data) + + return coverage + + def check(self): + # main function + src_files = self.get_src() + changes = self.get_change(src_files) + lcov_changes, uncovers = self.get_lcov_data(changes) + return 0 if self.create_report(lcov_changes, uncovers) > self.thresh else -1 + +if len(sys.argv) == 1: + print __doc__ + sys.exit(0) +if sys.argv[1] == 'ut': + monitor, lcov_dir, threshold = ['["src/"]', "/root/.cache/bazel/_bazel_root/6f45ce5b16fddc736efcfa6b0a4c96a2/execroot/curve/bazel-out/k8-dbg/bin/coverage", 0.95] + test1 = ["960fc84f..9a928260", monitor, lcov_dir, threshold] + if DEBUG: print "test1: ", test1 + ut = UTCover(*test1) + src_files = ut.get_src() + print src_files + print "=====================" + changes = ut.get_change(src_files) + print "=====================" + lcov_changes, uncovers = ut.get_lcov_data(changes) + print "=====================" + print uncovers + print "=====================" + rate = ut.create_report(changes, uncovers) + print rate + print "====================" + + + sys.exit(0) + +ret = UTCover(*sys.argv[1:]).check() +sys.exit(ret) + diff --git a/coverage/ut_incremental_check_nebd.py b/coverage/ut_incremental_check_nebd.py new file mode 100644 index 0000000000..9b0baca20b --- /dev/null +++ b/coverage/ut_incremental_check_nebd.py @@ -0,0 +1,252 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +###################################################################### +# Purpose: calculate UT coverage of git commits' new code +# Useage: ./ut_incremental_check.py +# Version: Initial Version by wahaha02 +###################################################################### + +__version__ = 'V1.0' +__author__ = 'wahaha02' +__date__ = '2016-7-25' +__doc__ = ''' +PURPOSE: +calculate UT coverage of git commits' new code + +USAGE: +./ut_incremental_check.py .. +example: +./ut_incremental_check.py "227b032..79196ba" '["source/soda/sp/lssp/i2c-v2/ksource"]' "coverage" 0.6 + +WORK PROCESS: +get changed file list between and , filter by options; +get changed lines per changed file; +based on , search .gcov.html per file, and get uncover lines; +create report file:ut_incremental_check_report.html and check (cover lines/new lines). + +UT: +./ut_incremental_check.py ut +''' + +__todo__ = ''' +TODO LIST: + 1. support svn + 2. refactory html report by django web template + 3. add commit info in html report + 4. prompt user/commit/date info when mouse point to uncovered line + 5. ... +''' + +import sys, os, re +import json +import commands +from HTMLParser import HTMLParser +from pprint import * + +DEBUG = 0 + +class GcovHTMLParser(HTMLParser): + def __init__(self): + HTMLParser.__init__(self) + self.uncovers = [] + self.covers = [] + self.islineNum = False + self.lineNum = 0 + + def handle_starttag(self, tag, attrs): + if tag == "span": + for a in attrs: + if a == ('class', 'lineNum'): + self.islineNum = True + if a == ('class', 'lineNoCov'): + self.uncovers.append(self.lineNum) + if a == ('class', 'lineCov'): + self.covers.append(self.lineNum) + + def handle_data(self, data): + if self.islineNum: + try: + self.lineNum = int(data) + except: + self.lineNum = -1 + + def handle_endtag(self, tag): + if tag == "span": + self.islineNum = False + +class UTCover(object) : + def __init__(self, since_until, monitor, lcov_dir, thresh) : + self.since, self.until = since_until.split('..') + self.monitor = json.loads(monitor) + self.lcov_dir = lcov_dir + self.thresh = float(thresh) + + def get_src(self): + # self.since, self.until, self.monitor + satus, output = commands.getstatusoutput("git diff --name-only %s %s" %(self.since, self.until)) + src_files = [f for f in output.split('\n') + for m in self.monitor if m in f + if os.path.splitext(f)[1][1:] in ['c', 'cpp', 'cc']] + exclude = ['src/test'] + src_files_clean = [] + for f in src_files: + need_excluded = False + for e in exclude: + if e in f: + need_excluded = True + break + if not need_excluded: + src_files_clean.append(f) + print src_files_clean + if DEBUG: pprint(src_files) + return src_files_clean + + def get_change(self, src_files): + # self.since, self.until + changes = {} + for f in src_files: + satus, output = commands.getstatusoutput("git log --oneline %s..%s %s | awk '{print $1}'" %(self.since, self.until, f)) + commits = output.split('\n') + cmd = "git blame %s | grep -E '(%s)' | cut -d\) -f1 | awk '{print $NF}'" %(f, '|'.join(commits)) + print cmd + satus, lines = commands.getstatusoutput(cmd) + changes[f.split("src/")[1]] = [ int(i) for i in lines.split('\n') if i.isdigit() ] + + + if DEBUG: pprint(changes) + print changes + return changes + + def get_ghp(self, f): + gcovfile = os.path.join(self.lcov_dir, f + '.gcov.html') + if not os.path.exists(gcovfile): + print "%s does not exist" % gcovfile + return None + + ghp = GcovHTMLParser() + ghp.feed(open(gcovfile, 'r').read()) + + return ghp + + def get_lcov_data(self, changes): + # self.lcov_dir + uncovers = {} + lcov_changes = {} + + for f, lines in changes.items(): + ghp = self.get_ghp(f) + if not ghp: + uncovers[f] = lines + lcov_changes[f] = lines + continue + + if DEBUG: print f, ghp.uncovers, ghp.covers, lines + lcov_changes[f] = sorted(list(set(ghp.uncovers + ghp.covers) & set(lines))) + uncov_lines = list(set(ghp.uncovers) & set(lines)) + if len(uncov_lines) != 0: + uncovers[f] = sorted(uncov_lines) + ghp.close() + + return lcov_changes, uncovers + + def create_uncover_trs(self, uncovers): + tr_format = ''' + + %(file)s + %(uncov_lines)s + + + ''' + trs = '' + for f,v in uncovers.items(): + gcovfile = os.path.join(self.lcov_dir, f + '.gcov.html') + if os.path.exists(gcovfile): + s = '' + p = re.compile(r'^\s*(?P\d+)\s*') + for line in open(gcovfile, 'r').readlines(): + ps = p.search(line) + if ps: + s += '' %ps.group('num') + line + '' + else: + s += line + open(gcovfile, 'w').write(s) + + data = {'file':f, 'uncov_lines': + ", ".join(['%d' %(f, i, i) for i in v])} + trs += tr_format %data + + return trs + + def create_report(self, changes, uncovers): + change_linenum, uncov_linenum = 0, 0 + for k,v in changes.items(): + change_linenum += len(v) + for k,v in uncovers.items(): + uncov_linenum += len(v) + + cov_linenum = change_linenum - uncov_linenum + coverage = round(cov_linenum * 1.0 / change_linenum + if change_linenum > 0 else 1, 4) + + template = open('ut_incremental_coverage_report.template', 'r').read() + data = { 'cov_lines':cov_linenum, + 'change_linenum':change_linenum, + 'coverage': coverage * 100, + 'uncover_trs': self.create_uncover_trs(uncovers)} + open(os.path.join(self.lcov_dir, 'ut_incremental_coverage_report.html'), + 'w').write(template %data) + + return coverage + + def check(self): + # main function + src_files = self.get_src() + changes = self.get_change(src_files) + lcov_changes, uncovers = self.get_lcov_data(changes) + return 0 if self.create_report(lcov_changes, uncovers) > self.thresh else 1 + +if len(sys.argv) == 1: + print __doc__ + sys.exit(0) +if sys.argv[1] == 'ut': + monitor, lcov_dir, threshold = ['["source/soda/sp/lssp/i2c-v2/ksource"]', "coverage", 0.8] + test1 = ["b2016fdb..11440652", monitor, lcov_dir, threshold] + if DEBUG: print "test1: ", test1 + ut = UTCover(*test1) + src_files = ut.get_src() + assert(src_files == []) + changes = ut.get_change(src_files) + assert(changes == {}) + lcov_changes, uncovers = ut.get_lcov_data(changes) + assert(uncovers == {}) + rate = ut.create_report(changes, uncovers) + assert(rate == 1) + assert(ut.check() == 0) + + test2 = [ + "227b03259b33360e2309274f3927c38457d84dd3..79196baabed99661bd31a201ead6764f23a2884c", + monitor, lcov_dir, threshold] + if DEBUG: print "test2: ", test2 + ut = UTCover(*test2) + src_files = ut.get_src() + assert(src_files == ['source/soda/sp/lssp/i2c-v2/ksource/bsp_i2c_dev.c', 'source/soda/sp/lssp/i2c-v2/ksource/chips/bsp_i2c_cfcuctrl.c', 'source/soda/sp/lssp/i2c-v2/ksource/chips/bsp_i2c_opt.c', 'source/soda/sp/lssp/i2c-v2/ksource/chips/bsp_i2c_pcie.c']) + changes = ut.get_change(src_files) + assert(changes == {'source/soda/sp/lssp/i2c-v2/ksource/chips/bsp_i2c_pcie.c': [78], 'source/soda/sp/lssp/i2c-v2/ksource/chips/bsp_i2c_cfcuctrl.c': [56, 57, 58, 59, 60, 130, 131, 132], 'source/soda/sp/lssp/i2c-v2/ksource/chips/bsp_i2c_opt.c': [68, 69, 115, 118, 124, 125, 126, 454, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 471, 721], 'source/soda/sp/lssp/i2c-v2/ksource/bsp_i2c_dev.c': [494, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652]}) + lcov_changes, uncovers = ut.get_lcov_data(changes) + assert( lcov_changes == {'source/soda/sp/lssp/i2c-v2/ksource/chips/bsp_i2c_pcie.c': [78], 'source/soda/sp/lssp/i2c-v2/ksource/chips/bsp_i2c_cfcuctrl.c': [56, 57, 58, 59, 60, 130, 131, 132], 'source/soda/sp/lssp/i2c-v2/ksource/chips/bsp_i2c_opt.c': [125, 459, 461, 462, 471], 'source/soda/sp/lssp/i2c-v2/ksource/bsp_i2c_dev.c': [496, 498, 502, 503, 504, 625, 629, 630, 631, 633, 634, 636, 638, 639, 643, 644, 649, 650]}) + assert(uncovers == {'source/soda/sp/lssp/i2c-v2/ksource/chips/bsp_i2c_pcie.c': [78], 'source/soda/sp/lssp/i2c-v2/ksource/chips/bsp_i2c_cfcuctrl.c': [56, 57, 58, 59, 60, 130, 131, 132], 'source/soda/sp/lssp/i2c-v2/ksource/chips/bsp_i2c_opt.c': [125, 471], 'source/soda/sp/lssp/i2c-v2/ksource/bsp_i2c_dev.c': [502, 503, 504, 643, 644]}) + rate = ut.create_report(changes, uncovers) + assert(0.8 > rate > 0.6) + assert(ut.check() == 1) + + test3 = ['d98b93e705a227389e7cdc4b43252f4194a6cb7a..e8876ff5fe8ee0e61865315a67bd395f5d7f63f7 ', + monitor, lcov_dir, threshold] + if DEBUG: print "test3: ", test3 + ut = UTCover(*test3) + assert(ut.check() == 0) + + sys.exit(0) + +ret = UTCover(*sys.argv[1:]).check() +sys.exit(ret) + diff --git a/curve-ansible/roles/install_package/tasks/include/copy_file_to_remote.yml b/curve-ansible/roles/install_package/tasks/include/copy_file_to_remote.yml index 216de4b63f..3adc88dcc2 100644 --- a/curve-ansible/roles/install_package/tasks/include/copy_file_to_remote.yml +++ b/curve-ansible/roles/install_package/tasks/include/copy_file_to_remote.yml @@ -29,8 +29,8 @@ - name: copy file with sudo block: - name: clear tmp dir - become: false - shell: rm -rf {{ tmp_dir }} + become: true + shell: sudo rm -rf {{ tmp_dir }} - name: create tmp dir become: false shell: mkdir -p {{ tmp_dir }} diff --git a/localut.sh b/localut.sh new file mode 100644 index 0000000000..925be0a8ca --- /dev/null +++ b/localut.sh @@ -0,0 +1,84 @@ +#!/bin/bash +bash replace-curve-repo.sh +WORKSPACE=`pwd` +rm -fr ${WORKSPACE}/curve/unittest +rm -fr ${WORKSPACE}/runlog +mkdir ${WORKSPACE}/curve_unittest/ +set -e +ulimit -a +ulimit -c unlimited +ulimit -a +ps -ef | grep chunkserver | grep -v grep | awk '{print $2}' | xargs kill -9 || true +ps -ef | grep mds | grep -v grep | awk '{print $2}' | xargs kill -9 || true +ps -ef | grep etcd | grep -v grep | awk '{print $2}' | xargs kill -9 || true +ps -ef | grep test | grep -v grep | awk '{print $2}' | xargs kill -9 || true + +cd ${WORKSPACE}/thirdparties/etcdclient && make clean && make all + +export LD_LIBRARY_PATH=${WORKSPACE}thirdparties/etcdclient:${LD_LIBRARY_PATH} +cd ${WORKSPACE} +mkdir runlog +bazel clean --async +sleep 5 + +bazel build tools/... --compilation_mode=dbg --collect_code_coverage --jobs=64 --copt -DHAVE_ZLIB=1 --define=with_glog=true --define=libunwind=true --copt -DGFLAGS_NS=google --copt -Wno-error=format-security --copt -DUSE_BTHREAD_MUTEX +bazel build src/... --compilation_mode=dbg --collect_code_coverage --jobs=64 --copt -DHAVE_ZLIB=1 --define=with_glog=true --define=libunwind=true --copt -DGFLAGS_NS=google --copt -Wno-error=format-security --copt -DUSE_BTHREAD_MUTEX +bazel build test/... --compilation_mode=dbg --collect_code_coverage --jobs=64 --copt -DHAVE_ZLIB=1 --define=with_glog=true --define=libunwind=true --copt -DGFLAGS_NS=google --copt -Wno-error=format-security --copt -DUSE_BTHREAD_MUTEX +for i in 0 1 2 3; do mkdir -p $i/{copysets,recycler}; done +for i in `find bazel-bin/test/ -type f -executable -exec file -i '{}' \; | grep -E 'x-executable|x-sharedlib' | grep "charset=binary" | grep -v ".so"|grep test | grep -Ev 'snapshot-server|snapshot_dummy_server|client-test|server-test|multi|topology_dummy|curve_client_workflow|curve_fake_mds' | awk -F":" '{print $1'}`;do $i 2>&1 | tee $i.log & done + +count=2 +check=0 +while [ $count -gt 1 ] +do + sleep 60 + count=`ps -ef | grep test | wc -l` + echo "===========================================================================================================================================" + + process=`ps -ef | grep test` + echo $process + echo ${count} + echo "===========================================================================================================================================" + + #for i in `find bazel-bin/test/ -type f -executable -exec file -i '{}' \; | grep -E 'x-executable|x-sharedlib' | grep "charset=binary" | grep -v ".so"|grep test | grep -Ev 'snapshot-server|snapshot_dummy_server|client-test|server-test|multi|topology_dummy|curve_client_workflow|curve_client_workflow|curve_fake_mds' | awk -F":" '{print $1'}`;do cat $i.log;done + + echo "===========================================================================================================================================" + f1="" + f2="" + f1_file="" + f2_file="" + now_test=`ps -ef | grep '\-test' | grep -v grep | awk '{print $8}'` + echo "now_test case is "$now_test + for i in `find bazel-bin/test/ -type f -executable -exec file -i '{}' \; | grep -E 'x-executable|x-sharedlib' | grep "charset=binary" | grep -v ".so"|grep test | grep -Ev 'snapshot-server|snapshot_dummy_server|client-test|server-test|multi|topology_dummy|curve_client_workflow|curve_client_workflow|curve_fake_mds' | awk -F":" '{print $1'}`;do a=`cat $i.log | grep "FAILED ]" | wc -l`;if [ $a -gt 0 ];then f1=`cat $i.log | grep "FAILED ]"`;f1_file="${i}.log"; echo "fail test is $i"; check=1; fi;done + for i in `find bazel-bin/test/ -type f -executable -exec file -i '{}' \; | grep -E 'x-executable|x-sharedlib' | grep "charset=binary" | grep -v ".so"|grep test | grep -Ev 'snapshot-server|snapshot_dummy_server|client-test|server-test|multi|topology_dummy|curve_client_workflow|curve_client_workflow|curve_fake_mds' | awk -F":" '{print $1'}`;do b=`cat $i.log | grep "Failure" | wc -l`;if [ $b -gt 0 ];then f2=`cat $i.log | grep "Failure"`; f2_file="${i}.log";echo "fail test is $i"; check=1; fi;done + if [ $check -eq 1 ];then + echo "=========================test fail,Here is the logs of failed use cases=========================" + echo "=========================test fail,Here is the logs of failed use cases=========================" + echo "=========================test fail,Here is the logs of failed use cases=========================" + echo $f1 + echo $f2 + if [ "$f1" != "" ];then + echo "test ${f1_file} log is --------------------------------------------->>>>>>>>" + cat ${f1_file} + fi + if [ "$f2" != "" ];then + echo "test ${f2_file} log is --------------------------------------------->>>>>>>>" + cat ${f2_file} + fi + exit -1 + fi +done + + +#echo "===========================================================================================================================================" + +#for i in `find bazel-bin/test/ -type f -executable -exec file -i '{}' \; | grep -E 'x-executable|x-sharedlib' | grep "charset=binary" | grep -v ".so"|grep test | grep -Ev 'snapshot-server|snapshot_dummy_server|client-test|server-test|multi|topology_dummy|curve_client_workflow|curve_client_workflow|curve_fake_mds' | awk -F":" '{print $1'}`;do cat $i.log;done + +sleep 30 + +cd bazel-bin +./../coverage/gen-coverage.py +./../coverage/check_coverage.sh +cp -r coverage ${WORKSPACE} +gcovr -x -r src -e ".*test/.*" -e ".*\.h" -e ".*usr/include/.*" -e ".*/thirdparties/*" -e "/usr/lib/*" -e ".*/external/*" -e ".*/bazel_out/*" -e "/usr/local/include/*" -e "test/*" -e ".*main\.cpp" -e ".*/_objs/snapshotcloneserver/*" -e ".*/_objs/mds/*" --output coverage.xml +cp coverage.xml ${WORKSPACE}