blob: 249d8ce2a58c98df5c2b669a6a018ff36ceba40b [file] [log] [blame]
Christoffer Jansson4e8a7732022-02-08 09:01:12 +01001#!/usr/bin/env vpython3
2
Artem Titarenko84d28272018-10-16 11:40:04 +02003# Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
4#
5# Use of this source code is governed by a BSD-style license
6# that can be found in the LICENSE file in the root of the source
7# tree. An additional intellectual property rights grant can be found
8# in the file PATENTS. All contributing project authors may
9# be found in the AUTHORS file in the root of the source tree.
Artem Titarenko84d28272018-10-16 11:40:04 +020010"""Generates command-line instructions to produce one-time iOS coverage using
11coverage.py.
12
13This script is usable for both real devices and simulator.
14But for real devices actual execution should be done manually from Xcode
15and coverage.profraw files should be also copied manually from the device.
16
17Additional prerequisites:
18
191. Xcode 10+ with iPhone Simulator SDK. Can be installed by command:
20 $ mac_toolchain install -kind ios -xcode-version 10l232m \
21 -output-dir build/mac_files/Xcode.app
22
232. For computing coverage on real device you probably also need to apply
24following patch to code_coverage/coverage.py script:
25
26========== BEGINNING OF PATCH ==========
27--- a/code_coverage/coverage.py
28+++ b/code_coverage/coverage.py
29@@ -693,8 +693,7 @@ def _AddArchArgumentForIOSIfNeeded(cmd_list, num_archs):
30 to use, and one architecture needs to be specified for each binary.
31 "" "
32if _IsIOS():
33- cmd_list.extend(['-arch=x86_64'] * num_archs)
34+ cmd_list.extend(['-arch=arm64'] * num_archs)
35
36
37def _GetBinaryPath(command):
38@@ -836,8 +835,8 @@ def _GetBinaryPathsFromTargets(targets, build_dir):
39 binary_path = os.path.join(build_dir, target)
40 if coverage_utils.GetHostPlatform() == 'win':
41 binary_path += '.exe'
42+ elif coverage_utils.GetHostPlatform() == 'mac':
43+ binary_path += '.app/%s' % target
44
45if os.path.exists(binary_path):
46 binary_paths.append(binary_path)
47========== ENDING OF PATCH ==========
48
49"""
Artem Titarenko84d28272018-10-16 11:40:04 +020050import sys
51
52DIRECTORY = 'out/coverage'
53
54TESTS = [
Mirko Bonadei8cc66952020-10-30 10:13:45 +010055 'audio_decoder_unittests',
56 'common_audio_unittests',
57 'common_video_unittests',
58 'modules_tests',
59 'modules_unittests',
60 'rtc_media_unittests',
61 'rtc_pc_unittests',
62 'rtc_stats_unittests',
63 'rtc_unittests',
Mirko Bonadei8cc66952020-10-30 10:13:45 +010064 'system_wrappers_unittests',
65 'test_support_unittests',
66 'tools_unittests',
67 'video_capture_tests',
68 'video_engine_tests',
69 'webrtc_nonparallel_tests',
Artem Titarenko84d28272018-10-16 11:40:04 +020070]
71
72XC_TESTS = [
Mirko Bonadei8cc66952020-10-30 10:13:45 +010073 'apprtcmobile_tests',
74 'sdk_framework_unittests',
75 'sdk_unittests',
Artem Titarenko84d28272018-10-16 11:40:04 +020076]
77
78
79def FormatIossimTest(test_name, is_xctest=False):
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010080 args = ['%s/%s.app' % (DIRECTORY, test_name)]
81 if is_xctest:
82 args += ['%s/%s_module.xctest' % (DIRECTORY, test_name)]
Artem Titarenko84d28272018-10-16 11:40:04 +020083
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010084 return '-c \'%s/iossim %s\'' % (DIRECTORY, ' '.join(args))
Artem Titarenko84d28272018-10-16 11:40:04 +020085
86
87def GetGNArgs(is_simulator):
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010088 target_cpu = 'x64' if is_simulator else 'arm64'
89 return ([] + ['target_os="ios"'] + ['target_cpu="%s"' % target_cpu] +
90 ['use_clang_coverage=true'] + ['is_component_build=false'] +
91 ['dcheck_always_on=true'])
Artem Titarenko84d28272018-10-16 11:40:04 +020092
93
94def GenerateIOSSimulatorCommand():
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010095 gn_args_string = ' '.join(GetGNArgs(is_simulator=True))
96 gn_cmd = ['gn', 'gen', DIRECTORY, '--args=\'%s\'' % gn_args_string]
Artem Titarenko84d28272018-10-16 11:40:04 +020097
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010098 coverage_cmd = ([sys.executable, 'tools/code_coverage/coverage.py'] +
99 ["%s.app" % t for t in XC_TESTS + TESTS] +
100 ['-b %s' % DIRECTORY, '-o out/report'] +
101 ['-i=\'.*/out/.*|.*/third_party/.*|.*test.*\''] +
102 [FormatIossimTest(t, is_xctest=True) for t in XC_TESTS] +
103 [FormatIossimTest(t, is_xctest=False) for t in TESTS])
Artem Titarenko84d28272018-10-16 11:40:04 +0200104
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100105 print('To get code coverage using iOS sim just run following commands:')
106 print('')
107 print(' '.join(gn_cmd))
108 print('')
109 print(' '.join(coverage_cmd))
110 return 0
Artem Titarenko84d28272018-10-16 11:40:04 +0200111
112
113def GenerateIOSDeviceCommand():
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100114 gn_args_string = ' '.join(GetGNArgs(is_simulator=False))
Artem Titarenko84d28272018-10-16 11:40:04 +0200115
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100116 coverage_report_cmd = ([sys.executable, 'tools/code_coverage/coverage.py'] +
117 ['%s.app' % t for t in TESTS] + ['-b %s' % DIRECTORY] +
118 ['-o out/report'] +
119 ['-p %s/merged.profdata' % DIRECTORY] +
120 ['-i=\'.*/out/.*|.*/third_party/.*|.*test.*\''])
Artem Titarenko84d28272018-10-16 11:40:04 +0200121
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100122 print('Computing code coverage for real iOS device is a little bit tedious.')
123 print('')
124 print('You will need:')
125 print('')
126 print('1. Generate xcode project and open it with Xcode 10+:')
127 print(' gn gen %s --ide=xcode --args=\'%s\'' % (DIRECTORY, gn_args_string))
128 print(' open %s/all.xcworkspace' % DIRECTORY)
129 print('')
130 print('2. Execute these Run targets manually with Xcode Run button and ')
131 print('manually save generated coverage.profraw file to %s:' % DIRECTORY)
132 print('\n'.join('- %s' % t for t in TESTS))
133 print('')
134 print('3. Execute these Test targets manually with Xcode Test button and ')
135 print('manually save generated coverage.profraw file to %s:' % DIRECTORY)
136 print('\n'.join('- %s' % t for t in XC_TESTS))
137 print('')
138 print('4. Merge *.profraw files to *.profdata using llvm-profdata tool:')
139 print((' build/mac_files/Xcode.app/Contents/Developer/Toolchains/' +
140 'XcodeDefault.xctoolchain/usr/bin/llvm-profdata merge ' +
141 '-o %s/merged.profdata ' % DIRECTORY +
142 '-sparse=true %s/*.profraw' % DIRECTORY))
143 print('')
144 print('5. Generate coverage report:')
145 print(' ' + ' '.join(coverage_report_cmd))
146 return 0
Artem Titarenko84d28272018-10-16 11:40:04 +0200147
148
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100149def main():
150 if len(sys.argv) < 2:
151 print('Please specify type of coverage:')
152 print(' %s simulator' % sys.argv[0])
153 print(' %s device' % sys.argv[0])
154 elif sys.argv[1] == 'simulator':
155 GenerateIOSSimulatorCommand()
156 elif sys.argv[1] == 'device':
157 GenerateIOSDeviceCommand()
158 else:
159 print('Unsupported type of coverage')
Artem Titarenko84d28272018-10-16 11:40:04 +0200160
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100161 return 0
Mirko Bonadei8cc66952020-10-30 10:13:45 +0100162
Artem Titarenko84d28272018-10-16 11:40:04 +0200163
164if __name__ == '__main__':
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100165 sys.exit(main())