zeek/testing/scripts/coverage-calc

60 lines
2.3 KiB
Python
Executable file

#! /usr/bin/env python3
# This script aggregates many files containing Zeek script coverage information
# into a single file and reports the overall coverage information. Usage:
#
# coverage-calc <quoted glob of filenames> <output file> <script dir>
#
# The last argument is used to point to a root directory containing all
# the Zeek distribution's scripts. It's used to cull out test scripts
# that are not part of the distribution and which should not count towards
# the coverage calculation.
import glob
import os
import sys
stats = {}
inputglob = sys.argv[1]
outputfile = sys.argv[2]
scriptdir = os.path.abspath(sys.argv[3])
for filename in glob.glob(inputglob):
with open(filename) as f:
for line in f.read().splitlines():
parts = line.split("\t")
exec_count = int(parts[0])
# grab file path and line numbers separately
filepath, srclines = parts[1].rsplit(",", 1)
filepath = os.path.normpath(filepath)
# ignore scripts that don't appear to be part of Zeek distribution
if not filepath.startswith(scriptdir):
continue
# keep only the line number (or line number range)
srclines = srclines.split()[1]
# For sorting purposes (so that line numbers get sorted correctly),
# construct a specially-formatted key string.
sortkey = filepath + ", line " + ("{:<6s}".format(srclines.split("-")[0]))
location = filepath + ", line " + srclines
desc = parts[2]
# Keying by location + desc may result in duplicate data
# as some descs change as a result of differing configurations
# producing record (re)definitions
key = location
if key in stats:
stats[key][0] += exec_count
else:
stats[key] = [exec_count, location, desc, sortkey]
with open(outputfile, "w") as f:
for k in sorted(stats, key=lambda i: stats[i][3]):
f.write(f"{stats[k][0]}\t{stats[k][1]}\t{stats[k][2]}\n")
num_covered = 0
for k in stats:
if stats[k][0] > 0:
num_covered += 1
if len(stats) > 0:
pct = float(num_covered) / len(stats) * 100
print(f"{num_covered}/{len(stats)} ({pct:.1f}%) Zeek script statements covered.")