Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2015 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 | |
| 7 """Run the given command through LLVM's coverage tools.""" | |
| 8 | |
| 9 | |
| 10 import argparse | |
| 11 import json | |
| 12 import os | |
| 13 import shlex | |
| 14 import subprocess | |
| 15 import sys | |
| 16 | |
| 17 | |
| 18 BUILDTYPE = 'Coverage' | |
| 19 OUT_DIR = os.path.realpath(os.path.join('out', BUILDTYPE)) | |
| 20 PROFILE_DATA = 'default.profraw' | |
| 21 PROFILE_DATA_MERGED = 'prof_merged' | |
| 22 | |
| 23 | |
| 24 def _fix_filename(filename): | |
| 25 """Return a filename which we can use to identify the file. | |
| 26 | |
| 27 The file paths printed by llvm-cov take the form: | |
| 28 | |
| 29 /path/to/repo/out/dir/../../src/filename.cpp | |
| 30 | |
| 31 And then they're truncated to 22 characters with leading ellipses: | |
| 32 | |
| 33 ...../../src/filename.cpp | |
| 34 | |
| 35 This makes it really tough to determine whether the file actually belongs in | |
| 36 the Skia repo. This function strips out the leading junk so that, if the file | |
| 37 exists in the repo, the returned string matches the end of some relative path | |
| 38 in the repo. This doesn't guarantee correctness, but it's about as close as | |
| 39 we can get. | |
| 40 """ | |
| 41 return filename.split('..')[-1].lstrip('./') | |
| 42 | |
| 43 | |
| 44 def _filter_results(results): | |
| 45 """Filter out any results for files not in the Skia repo. | |
| 46 | |
| 47 We run through the list of checked-in files and determine whether each file | |
| 48 belongs in the repo. Unfortunately, llvm-cov leaves us with fragments of the | |
| 49 file paths, so we can't guarantee accuracy. See the docstring for | |
| 50 _fix_filename for more details. | |
| 51 """ | |
| 52 all_files = subprocess.check_output(['git', 'ls-files']).splitlines() | |
| 53 filtered = [] | |
| 54 for percent, filename in results: | |
| 55 new_file = _fix_filename(filename) | |
| 56 matched = [] | |
| 57 for f in all_files: | |
| 58 if f.endswith(new_file): | |
| 59 matched.append(f) | |
| 60 if len(matched) == 1: | |
| 61 filtered.append((percent, matched[0])) | |
| 62 elif len(matched) > 1: | |
| 63 print >> sys.stderr, ('WARNING: multiple matches for %s; skipping:\n\t%s' | |
| 64 % (new_file, '\n\t'.join(matched))) | |
| 65 print 'Filtered out %d files.' % (len(results) - len(filtered)) | |
| 66 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
| |
| 67 | |
| 68 | |
| 69 def run_coverage(cmd): | |
| 70 """Run the given command and return per-file coverage data. | |
| 71 | |
| 72 Assumes that the binary has been built using llvm_coverage_build and that | |
| 73 LLVM 3.6 or newer is installed. | |
| 74 """ | |
| 75 binary_path = os.path.join(OUT_DIR, cmd[0]) | |
| 76 subprocess.call([binary_path] + cmd[1:]) | |
| 77 try: | |
| 78 subprocess.check_call( | |
| 79 ['llvm-profdata', 'merge', PROFILE_DATA, | |
| 80 '-output=%s' % PROFILE_DATA_MERGED]) | |
| 81 finally: | |
| 82 os.remove(PROFILE_DATA) | |
| 83 try: | |
| 84 report = subprocess.check_output( | |
| 85 ['llvm-cov', 'report', '-instr-profile', PROFILE_DATA_MERGED, | |
| 86 binary_path]) | |
| 87 finally: | |
| 88 os.remove(PROFILE_DATA_MERGED) | |
| 89 results = [] | |
| 90 for line in report.splitlines()[2:-2]: | |
| 91 filename, _, _, cover, _, _ = shlex.split(line) | |
| 92 percent = float(cover.split('%')[0]) | |
| 93 results.append((percent, filename)) | |
| 94 results = _filter_results(results) | |
| 95 results.sort() | |
| 96 return results | |
| 97 | |
| 98 | |
| 99 def main(): | |
| 100 res = run_coverage(sys.argv[1:]) | |
| 101 print '% Covered\tFilename' | |
| 102 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
| |
| 103 print '%f\t%s' % (percent, f) | |
| 104 | |
| 105 | |
| 106 if __name__ == '__main__': | |
| 107 main() | |
| OLD | NEW |