117 lines
3.8 KiB
Python
Executable File
117 lines
3.8 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
#
|
|
# This script is executed by test-fwknop.pl in --enable-profile-coverage mode
|
|
# to show additions of code coverage in gcov/lcov output.
|
|
#
|
|
|
|
import re
|
|
import argparse
|
|
import os
|
|
|
|
def main():
|
|
|
|
args = parse_cmdline()
|
|
|
|
### the test suite writes final coverage info to this path
|
|
### in the output directory.
|
|
final_lcov_file = "lcov_coverage_final.info"
|
|
|
|
old_lcov_file = args.old_lcov_file
|
|
new_lcov_file = args.new_lcov_file
|
|
|
|
if args.old_lcov_dir:
|
|
old_lcov_file = args.old_lcov_dir + "/" + final_lcov_file
|
|
|
|
if args.new_lcov_dir:
|
|
new_lcov_file = args.new_lcov_dir + "/" + final_lcov_file
|
|
|
|
if not os.path.exists(old_lcov_file):
|
|
print "[*] old coverage file does not exist: %s" % old_lcov_file
|
|
return 1
|
|
|
|
if not os.path.exists(new_lcov_file):
|
|
print "[*] new coverage file does not exist: %s" % new_lcov_file
|
|
return 1
|
|
|
|
old_zero_coverage = extract_zero_coverage(old_lcov_file)
|
|
new_zero_coverage = extract_zero_coverage(new_lcov_file)
|
|
|
|
### diff the two dictionaries
|
|
print "[+] New coverage:"
|
|
for f in old_zero_coverage:
|
|
printed_file = 0
|
|
if f in new_zero_coverage:
|
|
for ctype in old_zero_coverage[f]:
|
|
for val in sorted(old_zero_coverage[f][ctype]):
|
|
if val not in new_zero_coverage[f][ctype]:
|
|
if not printed_file:
|
|
print "[+] Coverage: " + f
|
|
printed_file = 1
|
|
print "[+] new '" + ctype + "' coverage: " + val
|
|
|
|
print "\n[-] Missing coverage from the previous run:"
|
|
for f in new_zero_coverage:
|
|
printed_file = 0
|
|
if f in old_zero_coverage:
|
|
for ctype in new_zero_coverage[f]:
|
|
for val in sorted(new_zero_coverage[f][ctype]):
|
|
if val not in old_zero_coverage[f][ctype]:
|
|
if not printed_file:
|
|
print "[-] Coverage: " + f
|
|
printed_file = 1
|
|
print "[-] missing '" + ctype + "' coverage: " + val
|
|
|
|
def extract_zero_coverage(lcov_file):
|
|
|
|
zero_coverage = {}
|
|
|
|
### populate old lcov output for functions/lines that were called
|
|
### zero times
|
|
with open(lcov_file, 'r') as f:
|
|
current_file = ''
|
|
for line in f:
|
|
line = line.strip()
|
|
|
|
m = re.search('SF:(\S+)', line)
|
|
if m and m.group(1):
|
|
current_file = m.group(1)
|
|
zero_coverage[current_file] = {}
|
|
zero_coverage[current_file]['fcns'] = {}
|
|
zero_coverage[current_file]['lines'] = {}
|
|
continue
|
|
|
|
if current_file:
|
|
### look for functions that were never called
|
|
m = re.search('^FNDA:0,(\S+)', line)
|
|
if m and m.group(1):
|
|
zero_coverage[current_file]['fcns'][m.group(1) + '()'] = ''
|
|
continue
|
|
|
|
### look for lines that were never called
|
|
m = re.search('^DA:(\d+),0', line)
|
|
if m and m.group(1):
|
|
zero_coverage[current_file]['lines'][m.group(1)] = ''
|
|
|
|
return zero_coverage
|
|
|
|
def parse_cmdline():
|
|
|
|
### parse command line args
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument("-o", "--old-lcov-file", type=str, \
|
|
help="old lcov file", default="output.last/lcov_coverage_final.info")
|
|
parser.add_argument("-n", "--new-lcov-file", type=str, \
|
|
help="new lcov file", default="output/lcov_coverage_final.info")
|
|
parser.add_argument("-O", "--old-lcov-dir", type=str, \
|
|
help="old lcov file", default="")
|
|
parser.add_argument("-N", "--new-lcov-dir", type=str, \
|
|
help="new lcov file", default="")
|
|
|
|
args = parser.parse_args()
|
|
return args
|
|
|
|
if __name__ == "__main__":
|
|
main()
|