[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