Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(555)

Unified Diff: tools/llvm_coverage_run.py

Issue 1213063009: Add scripts for running LLVM coverage (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: remove accidentally-include script Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« tools/llvm_coverage_build ('K') | « tools/llvm_coverage_build ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/llvm_coverage_run.py
diff --git a/tools/llvm_coverage_run.py b/tools/llvm_coverage_run.py
new file mode 100755
index 0000000000000000000000000000000000000000..902b1c6b04f1833dc3b6d48c5bfa919f3311bb16
--- /dev/null
+++ b/tools/llvm_coverage_run.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""Run the given command through LLVM's coverage tools."""
+
+
+import argparse
+import json
+import os
+import shlex
+import subprocess
+import sys
+
+
+BUILDTYPE = 'Coverage'
+OUT_DIR = os.path.realpath(os.path.join('out', BUILDTYPE))
+PROFILE_DATA = 'default.profraw'
+PROFILE_DATA_MERGED = 'prof_merged'
+
+
+def _fix_filename(filename):
+ """Return a filename which we can use to identify the file.
+
+ The file paths printed by llvm-cov take the form:
+
+ /path/to/repo/out/dir/../../src/filename.cpp
+
+ And then they're truncated to 22 characters with leading ellipses:
+
+ ...../../src/filename.cpp
+
+ This makes it really tough to determine whether the file actually belongs in
+ the Skia repo. This function strips out the leading junk so that, if the file
+ exists in the repo, the returned string matches the end of some relative path
+ in the repo. This doesn't guarantee correctness, but it's about as close as
+ we can get.
+ """
+ return filename.split('..')[-1].lstrip('./')
+
+
+def _filter_results(results):
+ """Filter out any results for files not in the Skia repo.
+
+ We run through the list of checked-in files and determine whether each file
+ belongs in the repo. Unfortunately, llvm-cov leaves us with fragments of the
+ file paths, so we can't guarantee accuracy. See the docstring for
+ _fix_filename for more details.
+ """
+ all_files = subprocess.check_output(['git', 'ls-files']).splitlines()
+ filtered = []
+ for percent, filename in results:
+ new_file = _fix_filename(filename)
+ matched = []
+ for f in all_files:
+ if f.endswith(new_file):
+ matched.append(f)
+ if len(matched) == 1:
+ filtered.append((percent, matched[0]))
+ elif len(matched) > 1:
+ print >> sys.stderr, ('WARNING: multiple matches for %s; skipping:\n\t%s'
+ % (new_file, '\n\t'.join(matched)))
+ print 'Filtered out %d files.' % (len(results) - len(filtered))
+ return filtered
borenet 2015/07/01 20:06:51 The right solution here is to submit a change to L
mtklein 2015/07/01 20:17:37 I wonder how basename.startswith('Sk') works as ou
borenet 2015/07/06 12:06:35 Maybe. The biggest problem with that is we'll mis
+
+
+def run_coverage(cmd):
+ """Run the given command and return per-file coverage data.
+
+ Assumes that the binary has been built using llvm_coverage_build and that
+ LLVM 3.6 or newer is installed.
+ """
+ binary_path = os.path.join(OUT_DIR, cmd[0])
+ subprocess.call([binary_path] + cmd[1:])
+ try:
+ subprocess.check_call(
+ ['llvm-profdata', 'merge', PROFILE_DATA,
+ '-output=%s' % PROFILE_DATA_MERGED])
+ finally:
+ os.remove(PROFILE_DATA)
+ try:
+ report = subprocess.check_output(
+ ['llvm-cov', 'report', '-instr-profile', PROFILE_DATA_MERGED,
+ binary_path])
+ finally:
+ os.remove(PROFILE_DATA_MERGED)
+ results = []
+ for line in report.splitlines()[2:-2]:
+ filename, _, _, cover, _, _ = shlex.split(line)
+ percent = float(cover.split('%')[0])
+ results.append((percent, filename))
+ results = _filter_results(results)
+ results.sort()
+ return results
+
+
+def main():
+ res = run_coverage(sys.argv[1:])
+ print '% Covered\tFilename'
+ for percent, f in res:
mtklein 2015/07/01 20:17:37 Can we get a line-by-line breakdown or some sort o
borenet 2015/07/06 12:06:35 `llvm-cov show` generates a giant file which shows
+ print '%f\t%s' % (percent, f)
+
+
+if __name__ == '__main__':
+ main()
« tools/llvm_coverage_build ('K') | « tools/llvm_coverage_build ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698