Skip to content
This repository has been archived by the owner on Apr 3, 2020. It is now read-only.

Commit

Permalink
[Coverage] Add coverage-data-split feature.
Browse files Browse the repository at this point in the history
This will allow to only load json data for the files under
review instead of the whole data set.

This will be called on the infra-side after all coverage
data has been merged.

Also fix a bunch of log lines.

BUG=chromium:568949
LOG=n
NOTRY=true

Review URL: https://codereview.chromium.org/1808663002

Cr-Commit-Position: refs/heads/master@{#34834}
  • Loading branch information
mi-ac authored and Commit bot committed Mar 16, 2016
1 parent 71ec6ec commit c44b02b
Showing 1 changed file with 61 additions and 12 deletions.
73 changes: 61 additions & 12 deletions tools/sanitizers/sancov_formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@

"""Script to transform and merge sancov files into human readable json-format.
The script supports two actions:
The script supports three actions:
all: Writes a json file with all instrumented lines of all executables.
merge: Merges sancov files with coverage output into an existing json file.
split: Split json file into separate files per covered source file.
The json data is structured as follows:
{
Expand All @@ -29,6 +30,9 @@
The line-number-bit_mask pairs are sorted by line number and don't contain
duplicates.
Split json data preserves the same format, but only contains one file per
json file.
The sancov tool is expected to be in the llvm compiler-rt third-party
directory. It's not checked out by default and must be added as a custom deps:
'v8/third_party/llvm/projects/compiler-rt':
Expand Down Expand Up @@ -213,7 +217,7 @@ def merge_files(x, y):
def write_instrumented(options):
"""Implements the 'all' action of this tool."""
exe_list = list(executables())
logging.info('Reading instrumented lines from %d executables.' %
logging.info('Reading instrumented lines from %d executables.',
len(exe_list))
pool = Pool(CPUS)
try:
Expand All @@ -224,9 +228,9 @@ def write_instrumented(options):
# Merge multiprocessing results and prepare output data.
data = merge_instrumented_line_results(exe_list, results)

logging.info('Read data from %d executables, which covers %d files.' %
(len(data['tests']), len(data['files'])))
logging.info('Writing results to %s' % options.json_output)
logging.info('Read data from %d executables, which covers %d files.',
len(data['tests']), len(data['files']))
logging.info('Writing results to %s', options.json_output)

# Write json output.
with open(options.json_output, 'w') as f:
Expand Down Expand Up @@ -342,8 +346,8 @@ def merge(options):
if match:
inputs.append((options.coverage_dir, match.group(1), f))

logging.info('Merging %d sancov files into %s' %
(len(inputs), options.json_input))
logging.info('Merging %d sancov files into %s',
len(inputs), options.json_input)

# Post-process covered lines in parallel.
pool = Pool(CPUS)
Expand All @@ -359,28 +363,62 @@ def merge(options):
# Merge muliprocessing results. Mutates data.
merge_covered_line_results(data, results)

logging.info('Merged data from %d executables, which covers %d files.' %
(len(data['tests']), len(data['files'])))
logging.info('Writing results to %s' % options.json_output)
logging.info('Merged data from %d executables, which covers %d files.',
len(data['tests']), len(data['files']))
logging.info('Writing results to %s', options.json_output)

# Write merged results to file.
with open(options.json_output, 'w') as f:
json.dump(data, f, sort_keys=True)


def split(options):
"""Implements the 'split' action of this tool."""
# Load existing json data file for splitting.
with open(options.json_input, 'r') as f:
data = json.load(f)

logging.info('Splitting off %d coverage files from %s',
len(data['files']), options.json_input)

for file_name, coverage in data['files'].iteritems():
# Preserve relative directories that are part of the file name.
file_path = os.path.join(options.output_dir, file_name + '.json')
try:
os.makedirs(os.path.dirname(file_path))
except OSError:
# Ignore existing directories.
pass

with open(file_path, 'w') as f:
# Flat-copy the old dict.
new_data = dict(data)

# Update current file.
new_data['files'] = {file_name: coverage}

# Write json data.
json.dump(new_data, f, sort_keys=True)


def main():
parser = argparse.ArgumentParser()
parser.add_argument('--coverage-dir',
help='Path to the sancov output files.')
parser.add_argument('--json-input',
help='Path to an existing json file with coverage data.')
parser.add_argument('--json-output', required=True,
parser.add_argument('--json-output',
help='Path to a file to write json output to.')
parser.add_argument('action', choices=['all', 'merge'],
parser.add_argument('--output-dir',
help='Directory where to put split output files to.')
parser.add_argument('action', choices=['all', 'merge', 'split'],
help='Action to perform.')

options = parser.parse_args()
if options.action.lower() == 'all':
if not options.json_output:
print '--json-output is required'
return 1
write_instrumented(options)
elif options.action.lower() == 'merge':
if not options.coverage_dir:
Expand All @@ -389,7 +427,18 @@ def main():
if not options.json_input:
print '--json-input is required'
return 1
if not options.json_output:
print '--json-output is required'
return 1
merge(options)
elif options.action.lower() == 'split':
if not options.json_input:
print '--json-input is required'
return 1
if not options.output_dir:
print '--output-dir is required'
return 1
split(options)
return 0


Expand Down

0 comments on commit c44b02b

Please sign in to comment.