Commit 48f1cbac authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Add a program to compactly summarize gcov(1) results.

parent 6b4c4955
#!/usr/bin/env python
#
# Copyright (c) 2017 Varnish Software AS
# All rights reserved.
#
# Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
"""
This program produces a compact summ of gcov run on all .o files
found in a subdirectory tree.
Options:
-g gcov-program
default:gcov49
-o output-filename
default: stdout
-x exclude-subdir
default ".git" and ".deps"
Arguments:
directories to process
"""
from __future__ import print_function
import os
import sys
import getopt
import subprocess
counts = {}
lengths = {}
exclude = [".git", ".deps",]
def process_gcov(fn, sn):
""" Sum .gcov file into counts, then delete it """
dd = counts.get(sn)
if dd is None:
dd = {}
for ln in open(fn):
d = ln.split(":")
cnt = d[0].strip()
ll = d[1]
if cnt == "-":
continue
if cnt == "#####":
cnt = 0
else:
cnt = int(cnt)
lno = int(d[1])
if lno not in dd:
dd[lno] = 0
dd[lno] += cnt
counts[sn] = dd
pl = lengths.get(sn)
ll = ll.strip()
if d[2] == "/*EOF*/\n":
ll = pl
elif pl != ll and not pl is None:
print("CONFLICT", fn, ll, pl)
ll = "-1"
lengths[sn] = ll
os.remove(fn)
def run_gcov(prog, subdir):
""" Walk tree, run gcov, process output """
for root, dirs, files in os.walk(subdir):
for i in exclude:
if i in dirs:
dirs.remove(i)
for fn in files:
if fn[-2:] != ".o":
continue
# if we find the .o file in a .../.libs the sources
# must be found relative to the parent directory
if root[-6:] == "/.libs":
x = subprocess.check_output(
["cd " + root + "/.. && " +
"exec " + prog + " -r .libs/" + fn],
stderr=subprocess.STDOUT, shell=True)
pf = ".."
else:
x = subprocess.check_output(
["cd " + root + " && " +
"exec " + prog + " -r " + fn],
stderr=subprocess.STDOUT, shell=True)
pf = ""
for ln in x.split("\n"):
ln = ln.split()
if len(ln) == 0:
continue
if ln[0] == "Creating":
gn = ln[1].strip("'")
assert gn[-5:] == ".gcov"
sn = gn[:-5]
process_gcov(
os.path.join(root, pf, gn), sn)
def produce_output(fdo):
"""
Produce compact output file
Format:
linefm [lineto] count
"+" in linefm means "previous line + 1"
"." in count means "same as previous count"
"""
for sn, cnt in counts.iteritems():
fdo.write("/" + sn + " " + str(lengths[sn]) + "\n")
lnos = list(cnt.iteritems())
lnos.sort()
pln = -1
pcn = -1
while len(lnos) > 0:
ln, cn = lnos.pop(0)
lnl = ln
while len(lnos) > 0:
lnn, cnn = lnos[0]
if lnl + 1 != lnn or cnn != cn:
break
lnos.pop(0)
lnl = lnn
if ln == pln + 1:
s = "+ "
else:
s = "%d " % ln
if ln != lnl:
s += "%d " % lnl
pln = lnl
else:
pln = ln
if cn == pcn:
s += "."
else:
s += "%d" % cn
pcn = cn
fdo.write(s + "\n")
if __name__ == "__main__":
optlist, args = getopt.getopt(sys.argv[1:], "g:o:x:")
fo = sys.stdout
gcovprog = "gcov49"
for f, v in optlist:
if f == '-o' and v == '-':
fo = sys.stdout
elif f == '-o':
fo = open(v, "w")
elif f == '-g':
gcovprog = v
elif f == '-x':
exclude.append(v)
else:
assert False
for dn in args:
run_gcov(gcovprog, dn)
produce_output(fo)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment