xref: /aosp_15_r20/external/webrtc/tools_webrtc/mb/mb.py (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1#!/usr/bin/env vpython3
2
3# Copyright (c) 2016 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.
10
11"""MB - the Meta-Build wrapper around GN.
12
13MB is a wrapper script for GN that can be used to generate build files
14for sets of canned configurations and analyze them.
15"""
16
17import os
18import sys
19
20_SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
21_SRC_DIR = os.path.dirname(os.path.dirname(_SCRIPT_DIR))
22sys.path.insert(0, _SRC_DIR)
23
24from tools.mb import mb
25
26
27def _GetExecutable(target, platform):
28  executable_prefix = '.\\' if platform == 'win32' else './'
29  executable_suffix = '.exe' if platform == 'win32' else ''
30  return executable_prefix + target + executable_suffix
31
32
33def main(args):
34  mbw = WebRTCMetaBuildWrapper()
35  return mbw.Main(args)
36
37
38class WebRTCMetaBuildWrapper(mb.MetaBuildWrapper):
39  def __init__(self):
40    super().__init__()
41    # Make sure default_config and default_isolate_map are attributes of the
42    # parent class before changing their values.
43    # pylint: disable=access-member-before-definition
44    assert self.default_config
45    assert self.default_isolate_map
46    self.default_config = os.path.join(_SCRIPT_DIR, 'mb_config.pyl')
47    self.default_isolate_map = os.path.join(_SRC_DIR, 'infra', 'specs',
48                                            'gn_isolate_map.pyl')
49
50  def GetSwarmingCommand(self, target, vals):
51    isolate_map = self.ReadIsolateMap()
52    test_type = isolate_map[target]['type']
53
54    is_android = 'target_os="android"' in vals['gn_args']
55    is_fuchsia = 'target_os="fuchsia"' in vals['gn_args']
56    is_ios = 'target_os="ios"' in vals['gn_args']
57    is_linux = self.platform.startswith('linux') and not is_android
58    is_win = self.platform.startswith('win')
59
60    if test_type == 'nontest':
61      self.WriteFailureAndRaise('We should not be isolating %s.' % target,
62                                output_path=None)
63    if test_type not in ('console_test_launcher', 'windowed_test_launcher',
64                         'non_parallel_console_test_launcher', 'raw',
65                         'additional_compile_target', 'junit_test', 'script'):
66      self.WriteFailureAndRaise('No command line for '
67                                '%s found (test type %s).' %
68                                (target, test_type),
69                                output_path=None)
70
71    cmdline = []
72    extra_files = [
73        '../../.vpython3',
74        '../../testing/test_env.py',
75    ]
76    vpython_exe = 'vpython3'
77
78    if isolate_map[target].get('script'):
79      cmdline += [
80          vpython_exe,
81          '../../' + self.ToSrcRelPath(isolate_map[target]['script'])
82      ]
83    elif is_android:
84      cmdline += [
85          'luci-auth', 'context', '--', vpython_exe,
86          '../../build/android/test_wrapper/logdog_wrapper.py', '--target',
87          target, '--logdog-bin-cmd',
88          '../../.task_template_packages/logdog_butler', '--logcat-output-file',
89          '${ISOLATED_OUTDIR}/logcats', '--store-tombstones'
90      ]
91    elif is_ios or is_fuchsia or test_type == 'raw':
92      if is_win:
93        cmdline += ['bin\\run_{}.bat'.format(target)]
94      else:
95        cmdline += ['bin/run_{}'.format(target)]
96    else:
97      if isolate_map[target].get('use_webcam', False):
98        cmdline += [
99            vpython_exe, '../../tools_webrtc/ensure_webcam_is_running.py'
100        ]
101        extra_files.append('../../tools_webrtc/ensure_webcam_is_running.py')
102      if isolate_map[target].get('use_pipewire', False):
103        cmdline += [vpython_exe, '../../tools_webrtc/configure_pipewire.py']
104        extra_files.append('../../tools_webrtc/configure_pipewire.py')
105
106      # is_linux uses use_ozone and x11 by default.
107      use_x11 = is_linux
108
109      xvfb = use_x11 and test_type == 'windowed_test_launcher'
110      if xvfb:
111        cmdline += [vpython_exe, '../../testing/xvfb.py']
112        extra_files.append('../../testing/xvfb.py')
113      else:
114        cmdline += [vpython_exe, '../../testing/test_env.py']
115
116      extra_files += [
117          '../../third_party/gtest-parallel/gtest-parallel',
118          '../../third_party/gtest-parallel/gtest_parallel.py',
119          '../../tools_webrtc/gtest-parallel-wrapper.py',
120      ]
121      output_dir = '${ISOLATED_OUTDIR}/test_logs'
122      timeout = isolate_map[target].get('timeout', 900)
123      cmdline += [
124          '../../tools_webrtc/gtest-parallel-wrapper.py',
125          '--output_dir=%s' % output_dir,
126          '--gtest_color=no',
127          # We tell gtest-parallel to interrupt the test after 900
128          # seconds, so it can exit cleanly and report results,
129          # instead of being interrupted by swarming and not
130          # reporting anything.
131          '--timeout=%s' % timeout,
132      ]
133      if test_type == 'non_parallel_console_test_launcher':
134        # Still use the gtest-parallel-wrapper.py script since we
135        # need it to run tests on swarming, but don't execute tests
136        # in parallel.
137        cmdline.append('--workers=1')
138
139      asan = 'is_asan=true' in vals['gn_args']
140      lsan = 'is_lsan=true' in vals['gn_args']
141      msan = 'is_msan=true' in vals['gn_args']
142      tsan = 'is_tsan=true' in vals['gn_args']
143      sanitizer = asan or lsan or msan or tsan
144      if not sanitizer:
145        # Retry would hide most sanitizers detections.
146        cmdline.append('--retry_failed=3')
147
148      cmdline.append(_GetExecutable(target, self.platform))
149
150      cmdline.extend([
151          '--asan=%d' % asan,
152          '--lsan=%d' % lsan,
153          '--msan=%d' % msan,
154          '--tsan=%d' % tsan,
155      ])
156
157    cmdline += isolate_map[target].get('args', [])
158
159    return cmdline, extra_files
160
161if __name__ == '__main__':
162  sys.exit(main(sys.argv[1:]))
163