Skip to content

Instantly share code, notes, and snippets.

@ribrdb
Last active April 27, 2017 21:25
Show Gist options
  • Save ribrdb/7969a336c333d0f62586e372cafec615 to your computer and use it in GitHub Desktop.
Save ribrdb/7969a336c333d0f62586e372cafec615 to your computer and use it in GitHub Desktop.
#!/usr/bin/python2.7
import cgi
import itertools
import json
import os
import sys
import urllib
combined_coverage = {}
def instrumented(hexstr):
while hexstr:
val = int(hexstr[:2], 16)
hexstr = hexstr[2:]
for i in xrange(8):
yield(bool(val & 1))
val >>= 1
def process_json(json):
for f, ins, ex in itertools.izip(json['fileNames'], json['instrumentedLines'], json['executedLines']):
if f.startswith("external/"):
continue
if f.endswith("_test.js"):
continue
covered = combined_coverage.setdefault(f, {})
for i, is_instrumented in enumerate(instrumented(ins)):
if is_instrumented:
covered[i] = ex[i] or covered.get(i, False)
def find_file(name):
for prefix in ('', 'bazel-genfiles', 'bazel-bin'):
p = os.path.join(prefix, name)
if os.path.isfile(p):
return p
def generate_html():
out = open("coverage.html", "w")
out.write("""<!doctype html>
<style>
.uncovered {
background:#faa
}
.covered {
background:#afa
}
div.line::before {
content: attr(data-lineno);
}
</style>
<h1><a id=top>Coverage</a></h1>
<ul>
""")
files = combined_coverage.keys()
files.sort()
total_lines = 0
total_covered = 0
for f in files:
coverage = combined_coverage[f]
lines = len(coverage)
covered = 0
for v in coverage.values():
if v:
covered += 1
total_covered += covered
total_lines += lines
out.write('<li><a href="#%s">%s</a> %.1f%% (%d/%d)\n' % (
urllib.quote_plus(f), f, covered*100.0/lines, covered, lines
))
out.write("""
</ul>
<p>Total: %.1f%% (%d/%d)
""" % (total_covered*100.0/total_lines, total_covered, total_lines))
for f in files:
p = find_file(f)
if p:
out.write('<h3><a id="%s">%s</a></h3>\n<p><a href="#top">Top</a>\n</p><pre>'%(urllib.quote_plus(f), f))
coverage = combined_coverage[f]
for i, line in enumerate(open(p, 'rU')):
klass = ""
covered = coverage.get(i, None)
if covered is True:
klass = " covered"
elif covered is False:
klass = " uncovered"
out.write('<div class="line%s" data-lineno="%d&nbsp;">%s</div>'%(
klass, i + 1, cgi.escape(line.rstrip('\n'))
))
out.write('</pre>')
out.close()
def main(args):
for arg in args[1:]:
d = json.load(open(arg))
process_json(d)
generate_html()
if __name__ == '__main__':
main(sys.argv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment