xref: /aosp_15_r20/external/openscreen/build/code_coverage/merge_results.py (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
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