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