[master] 48f1cba Add a program to compactly summarize gcov(1) results.
Poul-Henning Kamp
phk at FreeBSD.org
Sat Jan 7 11:39:05 CET 2017
commit 48f1cbac839f2a398d5a67512c7924b043e8d493
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Sat Jan 7 08:35:17 2017 +0000
Add a program to compactly summarize gcov(1) results.
diff --git a/tools/gcov_digest.py b/tools/gcov_digest.py
new file mode 100644
index 0000000..5fce2f5
--- /dev/null
+++ b/tools/gcov_digest.py
@@ -0,0 +1,194 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2017 Varnish Software AS
+# All rights reserved.
+#
+# Author: Poul-Henning Kamp <phk at 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)
More information about the varnish-commit
mailing list