1#!/usr/bin/env/python 2# Copyright 2020 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"""Merges .profraw files generated by unit tests into .profdata files 6to be processed by the chromium code_coverage module. 7 8This script based on the following chromium script. It performs the 9same merging steps, but code related to json parsing has been removed, 10as openscreen does not generate these json files as chromium does: 11https://source.chromium.org/chromium/chromium/src/+/master:testing/merge_scripts/code_coverage/merge_steps.py 12""" 13 14import argparse 15import json 16import logging 17import os 18import subprocess 19import sys 20 21import merge_lib as coverage_merger 22 23 24def _MergeAPIArgumentParser(*args, **kwargs): 25 parser = argparse.ArgumentParser(*args, **kwargs) 26 parser.add_argument( 27 '--task-output-dir', required=True, help=argparse.SUPPRESS) 28 parser.add_argument( 29 '--profdata-dir', required=True, help='where to store the merged data') 30 parser.add_argument( 31 '--llvm-profdata', 32 required=True, 33 help='path to llvm-profdata executable') 34 parser.add_argument( 35 '--per-cl-coverage', 36 action='store_true', 37 help='set to indicate that this is a per-CL coverage build') 38 # TODO(crbug.com/1077304) - migrate this to sparse=False as default, and have 39 # --sparse to set sparse 40 parser.add_argument( 41 '--no-sparse', 42 action='store_false', 43 dest='sparse', 44 help='run llvm-profdata without the sparse flag.') 45 # TODO(crbug.com/1077304) - The intended behaviour is to default sparse to 46 # false. --no-sparse above was added as a workaround, and will be removed. 47 # This is being introduced now in support of the migration to intended 48 # behavior. Ordering of args matters here, as the default is set by the former 49 # (sparse defaults to False because of ordering. See unit tests for details) 50 parser.add_argument( 51 '--sparse', 52 action='store_true', 53 dest='sparse', 54 help='run llvm-profdata with the sparse flag.') 55 # (crbug.com/1091310) - IR PGO is incompatible with the initial conversion 56 # of .profraw -> .profdata that's run to detect validation errors. 57 # Introducing a bypass flag that'll merge all .profraw directly to .profdata 58 parser.add_argument( 59 '--skip-validation', 60 action='store_true', 61 help='skip validation for good raw profile data. this will pass all ' 62 'raw profiles found to llvm-profdata to be merged. only applicable ' 63 'when input extension is .profraw.') 64 return parser 65 66 67def main(): 68 desc = "Merge profraw files in <--task-output-dir> into a single profdata." 69 parser = _MergeAPIArgumentParser(description=desc) 70 params = parser.parse_args() 71 72 output_prodata_filename = 'default.profdata' 73 invalid_profiles, counter_overflows = coverage_merger.merge_profiles( 74 params.task_output_dir, 75 os.path.join(params.profdata_dir, output_prodata_filename), '.profraw', 76 params.llvm_profdata, 77 sparse=params.sparse, 78 skip_validation=params.skip_validation) 79 80 # At the moment counter overflows overlap with invalid profiles, but this is 81 # not guaranteed to remain the case indefinitely. To avoid future conflicts 82 # treat these separately. 83 if counter_overflows: 84 with open( 85 os.path.join(params.profdata_dir, 'profiles_with_overflows.json'), 86 'w') as f: 87 json.dump(counter_overflows, f) 88 89 if invalid_profiles: 90 with open(os.path.join(params.profdata_dir, 'invalid_profiles.json'), 91 'w') as f: 92 json.dump(invalid_profiles, f) 93 94 return 1 if bool(invalid_profiles) else 0 95 96 97if __name__ == '__main__': 98 logging.basicConfig( 99 format='[%(asctime)s %(levelname)s] %(message)s', level=logging.INFO) 100 sys.exit(main()) 101