[master] 552f5c1ff Renovate the gcov_digest script.
Poul-Henning Kamp
phk at FreeBSD.org
Mon Jun 16 14:00:05 UTC 2025
commit 552f5c1ff8453ac45e5aca2775ca0ff728f0fd29
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Mon Jun 16 13:58:33 2025 +0000
Renovate the gcov_digest script.
diff --git a/tools/gcov_digest.py b/tools/gcov_digest.py
index eb6fa58c3..309958fba 100644
--- a/tools/gcov_digest.py
+++ b/tools/gcov_digest.py
@@ -55,39 +55,92 @@ import sys
import getopt
import subprocess
-counts = {}
-lengths = {}
+source_files = {}
+
+class SourceFile():
+ ''' GCOV counts for a single source file '''
+
+ def __init__(self, path):
+ self.path = path
+ self.counts = {}
+ self.length = 0
+ source_files[path] = self
+
+ def __lt__(self, other):
+ return self.path < other.path
+
+ def ingest(self, fd):
+ ''' Ingest a gcov file '''
+ for line in fd:
+ flds = line.split(':', maxsplit=2)
+ cnt = flds[0].strip()
+ if cnt == "-":
+ continue
+ if cnt == "#####":
+ cnt = 0
+ else:
+ cnt = int(cnt)
+ lno = int(flds[1])
+ if lno not in self.counts:
+ self.counts[lno] = cnt
+ else:
+ self.counts[lno] += cnt
+ self.length = lno
+
+ def summary(self):
+ """
+ Produce compact output file
+
+ Format:
+ linefm [lineto] count
+
+ "+" in linefm means "previous line + 1"
+ "." in count means "same as previous count"
+ """
+ yield "/" + self.path + " " + str(self.length)
+ lnos = list(sorted(self.counts.items()))
+ pln = -1
+ pcn = -1
+ while lnos:
+ ln, cn = lnos.pop(0)
+ lnl = ln
+ while lnos:
+ 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
+ yield s
exclude = [".git", ".deps",]
-def process_gcov(fn, sn):
+def process_gcov(fn, root):
""" Sum .gcov file into counts, then delete it """
- dd = counts.get(sn)
- if dd is None:
- dd = {}
- for ln in open(fn, encoding="UTF-8"):
- 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
+
+ with open(fn, encoding="UTF-8") as gfile:
+ sline = gfile.readline().split(':')
+ assert sline[2] == "Source"
+ sname = os.path.normpath(os.path.join(root, sline[3].strip()))
+ sfile = source_files.get(sname)
+ if not sfile:
+ sfile = SourceFile(sname)
+ sfile.ingest(gfile)
os.remove(fn)
def run_gcov(prog, subdir):
@@ -109,18 +162,31 @@ def run_gcov(prog, subdir):
subdir = root.split("/")[-1]
cmd = ["cd " + root + "/.. && " + "exec " + prog + " " + subdir + "/" + fn]
rpath = "/../"
+ elif "vtest2" in root:
+ cmd = ["cd " + root + "/../.. && " + "exec " + prog + " vtest2/src/" + fn]
+ rpath = "/../../"
+ #print("VT2")
elif root[-6:] == "/.libs":
cmd = ["cd " + root + "/.. && " + "exec " + prog + " .libs/" + fn]
rpath = "/../"
else:
+ #print("R", root, "FN", fn)
cmd = ["cd " + root + " && " + "exec " + prog + " " + fn]
rpath = "/"
- x = subprocess.check_output(
+ sp = subprocess.run(
cmd,
- stderr=subprocess.STDOUT, shell=True,
- universal_newlines=True)
- pf = ""
+ shell=True,
+ universal_newlines=True,
+ capture_output=True,
+ )
+
+ if sp.returncode != 0 or sp.stderr:
+ print("CMD", cmd, "EXIT", sp.returncode)
+ print("SERR", len(sp.stderr), sp.stderr)
+ print("SOUT", sp.stdout)
+ sys.exit(2)
+ x = sp.stdout
for ln in x.split("\n"):
if "such file" in ln:
@@ -129,59 +195,15 @@ def run_gcov(prog, subdir):
ln = ln.split()
if not ln:
continue
- if ln[0].find("reating") != -1:
+ if "reating" in ln[0]:
gn = root + rpath + ln[1].strip("'")
gn = os.path.normpath(gn)
assert gn[-5:] == ".gcov"
- sn = gn[:-5]
- process_gcov(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.items():
- fdo.write("/" + sn + " " + str(lengths[sn]) + "\n")
- lnos = list(cnt.items())
- lnos.sort()
- pln = -1
- pcn = -1
- while lnos:
- ln, cn = lnos.pop(0)
- lnl = ln
- while lnos:
- 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__":
+ #print("GS", gn)
+ process_gcov(gn, root)
+def main():
+ ''' ... '''
optlist, args = getopt.getopt(sys.argv[1:], "g:o:x:")
fo = sys.stdout
@@ -193,7 +215,7 @@ if __name__ == "__main__":
if f == '-o' and v == '-':
fo = sys.stdout
elif f == '-o':
- fo = open(v, "w")
+ fo = open(v, "w", encoding="utf8")
elif f == '-g':
gcovprog = v
elif f == '-x':
@@ -205,4 +227,9 @@ if __name__ == "__main__":
for dn in args:
run_gcov(gcovprog, dn)
- produce_output(fo)
+ for sf in sorted(source_files.values()):
+ for i in sf.summary():
+ fo.write(i + "\n")
+
+if __name__ == "__main__":
+ main()
More information about the varnish-commit
mailing list