blob: e01a75c049e0e9c1941d8c06eb5cfed7a07ff127 [file] [log] [blame]
Artem Titarenko84d28272018-10-16 09:40:041#!/usr/bin/env python
2# Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3#
4# Use of this source code is governed by a BSD-style license
5# that can be found in the LICENSE file in the root of the source
6# tree. An additional intellectual property rights grant can be found
7# in the file PATENTS. All contributing project authors may
8# be found in the AUTHORS file in the root of the source tree.
Artem Titarenko84d28272018-10-16 09:40:049"""Generates command-line instructions to produce one-time iOS coverage using
10coverage.py.
11
12This script is usable for both real devices and simulator.
13But for real devices actual execution should be done manually from Xcode
14and coverage.profraw files should be also copied manually from the device.
15
16Additional prerequisites:
17
181. Xcode 10+ with iPhone Simulator SDK. Can be installed by command:
19 $ mac_toolchain install -kind ios -xcode-version 10l232m \
20 -output-dir build/mac_files/Xcode.app
21
222. For computing coverage on real device you probably also need to apply
23following patch to code_coverage/coverage.py script:
24
25========== BEGINNING OF PATCH ==========
26--- a/code_coverage/coverage.py
27+++ b/code_coverage/coverage.py
28@@ -693,8 +693,7 @@ def _AddArchArgumentForIOSIfNeeded(cmd_list, num_archs):
29 to use, and one architecture needs to be specified for each binary.
30 "" "
31if _IsIOS():
32- cmd_list.extend(['-arch=x86_64'] * num_archs)
33+ cmd_list.extend(['-arch=arm64'] * num_archs)
34
35
36def _GetBinaryPath(command):
37@@ -836,8 +835,8 @@ def _GetBinaryPathsFromTargets(targets, build_dir):
38 binary_path = os.path.join(build_dir, target)
39 if coverage_utils.GetHostPlatform() == 'win':
40 binary_path += '.exe'
41+ elif coverage_utils.GetHostPlatform() == 'mac':
42+ binary_path += '.app/%s' % target
43
44if os.path.exists(binary_path):
45 binary_paths.append(binary_path)
46========== ENDING OF PATCH ==========
47
48"""
49
50import sys
51
52DIRECTORY = 'out/coverage'
53
54TESTS = [
Mirko Bonadei8cc66952020-10-30 09:13:4555 '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',
64 'slow_tests',
65 'system_wrappers_unittests',
66 'test_support_unittests',
67 'tools_unittests',
68 'video_capture_tests',
69 'video_engine_tests',
70 'webrtc_nonparallel_tests',
Artem Titarenko84d28272018-10-16 09:40:0471]
72
73XC_TESTS = [
Mirko Bonadei8cc66952020-10-30 09:13:4574 'apprtcmobile_tests',
75 'sdk_framework_unittests',
76 'sdk_unittests',
Artem Titarenko84d28272018-10-16 09:40:0477]
78
79
80def FormatIossimTest(test_name, is_xctest=False):
Mirko Bonadei8cc66952020-10-30 09:13:4581 args = ['%s/%s.app' % (DIRECTORY, test_name)]
82 if is_xctest:
83 args += ['%s/%s_module.xctest' % (DIRECTORY, test_name)]
Artem Titarenko84d28272018-10-16 09:40:0484
Mirko Bonadei8cc66952020-10-30 09:13:4585 return '-c \'%s/iossim %s\'' % (DIRECTORY, ' '.join(args))
Artem Titarenko84d28272018-10-16 09:40:0486
87
88def GetGNArgs(is_simulator):
Mirko Bonadei8cc66952020-10-30 09:13:4589 target_cpu = 'x64' if is_simulator else 'arm64'
90 return ([] + ['target_os="ios"'] + ['target_cpu="%s"' % target_cpu] +
91 ['use_clang_coverage=true'] + ['is_component_build=false'] +
92 ['dcheck_always_on=true'])
Artem Titarenko84d28272018-10-16 09:40:0493
94
95def GenerateIOSSimulatorCommand():
Mirko Bonadei8cc66952020-10-30 09:13:4596 gn_args_string = ' '.join(GetGNArgs(is_simulator=True))
97 gn_cmd = ['gn', 'gen', DIRECTORY, '--args=\'%s\'' % gn_args_string]
Artem Titarenko84d28272018-10-16 09:40:0498
Mirko Bonadei8cc66952020-10-30 09:13:4599 coverage_cmd = ([sys.executable, 'tools/code_coverage/coverage.py'] +
100 ["%s.app" % t for t in XC_TESTS + TESTS] +
101 ['-b %s' % DIRECTORY, '-o out/report'] +
102 ['-i=\'.*/out/.*|.*/third_party/.*|.*test.*\''] +
103 [FormatIossimTest(t, is_xctest=True) for t in XC_TESTS] +
104 [FormatIossimTest(t, is_xctest=False) for t in TESTS])
Artem Titarenko84d28272018-10-16 09:40:04105
Mirko Bonadei8cc66952020-10-30 09:13:45106 print 'To get code coverage using iOS simulator just run following commands:'
107 print ''
108 print ' '.join(gn_cmd)
109 print ''
110 print ' '.join(coverage_cmd)
111 return 0
Artem Titarenko84d28272018-10-16 09:40:04112
113
114def GenerateIOSDeviceCommand():
Mirko Bonadei8cc66952020-10-30 09:13:45115 gn_args_string = ' '.join(GetGNArgs(is_simulator=False))
Artem Titarenko84d28272018-10-16 09:40:04116
Mirko Bonadei8cc66952020-10-30 09:13:45117 coverage_report_cmd = (
118 [sys.executable, 'tools/code_coverage/coverage.py'] +
119 ['%s.app' % t for t in TESTS] + ['-b %s' % DIRECTORY] +
120 ['-o out/report'] + ['-p %s/merged.profdata' % DIRECTORY] +
121 ['-i=\'.*/out/.*|.*/third_party/.*|.*test.*\''])
Artem Titarenko84d28272018-10-16 09:40:04122
Mirko Bonadei8cc66952020-10-30 09:13:45123 print 'Computing code coverage for real iOS device is a little bit tedious.'
124 print ''
125 print 'You will need:'
126 print ''
127 print '1. Generate xcode project and open it with Xcode 10+:'
128 print ' gn gen %s --ide=xcode --args=\'%s\'' % (DIRECTORY, gn_args_string)
129 print ' open %s/all.xcworkspace' % DIRECTORY
130 print ''
131 print '2. Execute these Run targets manually with Xcode Run button and '
132 print 'manually save generated coverage.profraw file to %s:' % DIRECTORY
133 print '\n'.join('- %s' % t for t in TESTS)
134 print ''
135 print '3. Execute these Test targets manually with Xcode Test button and '
136 print 'manually save generated coverage.profraw file to %s:' % DIRECTORY
137 print '\n'.join('- %s' % t for t in XC_TESTS)
138 print ''
139 print '4. Merge *.profraw files to *.profdata using llvm-profdata tool:'
140 print(' build/mac_files/Xcode.app/Contents/Developer/Toolchains/' +
141 'XcodeDefault.xctoolchain/usr/bin/llvm-profdata merge ' +
142 '-o %s/merged.profdata ' % DIRECTORY +
143 '-sparse=true %s/*.profraw' % DIRECTORY)
144 print ''
145 print '5. Generate coverage report:'
146 print ' ' + ' '.join(coverage_report_cmd)
147 return 0
Artem Titarenko84d28272018-10-16 09:40:04148
149
150def Main():
Mirko Bonadei8cc66952020-10-30 09:13:45151 if len(sys.argv) < 2:
152 print 'Please specify type of coverage:'
153 print ' %s simulator' % sys.argv[0]
154 print ' %s device' % sys.argv[0]
155 elif sys.argv[1] == 'simulator':
156 GenerateIOSSimulatorCommand()
157 elif sys.argv[1] == 'device':
158 GenerateIOSDeviceCommand()
159 else:
160 print 'Unsupported type of coverage'
Artem Titarenko84d28272018-10-16 09:40:04161
Mirko Bonadei8cc66952020-10-30 09:13:45162 return 0
163
Artem Titarenko84d28272018-10-16 09:40:04164
165if __name__ == '__main__':
Mirko Bonadei8cc66952020-10-30 09:13:45166 sys.exit(Main())