xref: /aosp_15_r20/external/webrtc/tools_webrtc/mb/mb_unittest.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"""Tests for mb.py."""
12
13import ast
14import os
15import re
16import sys
17import tempfile
18import unittest
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_webrtc.mb import mb
25
26
27class FakeMBW(mb.WebRTCMetaBuildWrapper):
28  def __init__(self, win32=False):
29    super().__init__()
30
31    # Override vars for test portability.
32    if win32:
33      self.chromium_src_dir = 'c:\\fake_src'
34      self.default_config = 'c:\\fake_src\\tools_webrtc\\mb\\mb_config.pyl'
35      self.default_isolate_map = ('c:\\fake_src\\testing\\buildbot\\'
36                                  'gn_isolate_map.pyl')
37      self.platform = 'win32'
38      self.executable = 'c:\\python\\vpython3.exe'
39      self.sep = '\\'
40      self.cwd = 'c:\\fake_src\\out\\Default'
41    else:
42      self.chromium_src_dir = '/fake_src'
43      self.default_config = '/fake_src/tools_webrtc/mb/mb_config.pyl'
44      self.default_isolate_map = '/fake_src/testing/buildbot/gn_isolate_map.pyl'
45      self.executable = '/usr/bin/vpython3'
46      self.platform = 'linux2'
47      self.sep = '/'
48      self.cwd = '/fake_src/out/Default'
49
50    self.files = {}
51    self.dirs = set()
52    self.calls = []
53    self.cmds = []
54    self.cross_compile = None
55    self.out = ''
56    self.err = ''
57    self.rmdirs = []
58
59  def ExpandUser(self, path):
60    # pylint: disable=no-self-use
61    return '$HOME/%s' % path
62
63  def Exists(self, path):
64    abs_path = self._AbsPath(path)
65    return self.files.get(abs_path) is not None or abs_path in self.dirs
66
67  def ListDir(self, path):
68    dir_contents = []
69    for f in list(self.files.keys()) + list(self.dirs):
70      head, _ = os.path.split(f)
71      if head == path:
72        dir_contents.append(f)
73    return dir_contents
74
75  def MaybeMakeDirectory(self, path):
76    abpath = self._AbsPath(path)
77    self.dirs.add(abpath)
78
79  def PathJoin(self, *comps):
80    return self.sep.join(comps)
81
82  def ReadFile(self, path):
83    try:
84      return self.files[self._AbsPath(path)]
85    except KeyError as e:
86      raise IOError('%s not found' % path) from e
87
88  def WriteFile(self, path, contents, force_verbose=False):
89    if self.args.dryrun or self.args.verbose or force_verbose:
90      self.Print('\nWriting """\\\n%s""" to %s.\n' % (contents, path))
91    abpath = self._AbsPath(path)
92    self.files[abpath] = contents
93
94  def Call(self, cmd, env=None, capture_output=True, input=None):
95    # pylint: disable=redefined-builtin
96    del env
97    del capture_output
98    del input
99    self.calls.append(cmd)
100    if self.cmds:
101      return self.cmds.pop(0)
102    return 0, '', ''
103
104  def Print(self, *args, **kwargs):
105    sep = kwargs.get('sep', ' ')
106    end = kwargs.get('end', '\n')
107    f = kwargs.get('file', sys.stdout)
108    if f == sys.stderr:
109      self.err += sep.join(args) + end
110    else:
111      self.out += sep.join(args) + end
112
113  def TempDir(self):
114    tmp_dir = os.path.join(tempfile.gettempdir(), 'mb_test')
115    self.dirs.add(tmp_dir)
116    return tmp_dir
117
118  def TempFile(self, mode='w'):
119    del mode
120    return FakeFile(self.files)
121
122  def RemoveFile(self, path):
123    abpath = self._AbsPath(path)
124    self.files[abpath] = None
125
126  def RemoveDirectory(self, abs_path):
127    # Normalize the passed-in path to handle different working directories
128    # used during unit testing.
129    abs_path = self._AbsPath(abs_path)
130    self.rmdirs.append(abs_path)
131    files_to_delete = [f for f in self.files if f.startswith(abs_path)]
132    for f in files_to_delete:
133      self.files[f] = None
134
135  def _AbsPath(self, path):
136    if not ((self.platform == 'win32' and path.startswith('c:')) or
137            (self.platform != 'win32' and path.startswith('/'))):
138      path = self.PathJoin(self.cwd, path)
139    if self.sep == '\\':
140      return re.sub(r'\\+', r'\\', path)
141    return re.sub('/+', '/', path)
142
143
144class FakeFile:
145  # pylint: disable=invalid-name
146  def __init__(self, files):
147    self.name = '/tmp/file'
148    self.buf = ''
149    self.files = files
150
151  def write(self, contents):
152    self.buf += contents
153
154  def close(self):
155    self.files[self.name] = self.buf
156
157
158TEST_CONFIG = """\
159{
160  'builder_groups': {
161    'chromium': {},
162    'fake_group': {
163      'fake_builder': 'rel_bot',
164      'fake_debug_builder': 'debug_goma',
165      'fake_args_bot': 'fake_args_bot',
166      'fake_multi_phase': { 'phase_1': 'phase_1', 'phase_2': 'phase_2'},
167      'fake_android_bot': 'android_bot',
168      'fake_args_file': 'args_file_goma',
169      'fake_ios_error': 'ios_error',
170    },
171  },
172  'configs': {
173    'args_file_goma': ['fake_args_bot', 'goma'],
174    'fake_args_bot': ['fake_args_bot'],
175    'rel_bot': ['rel', 'goma', 'fake_feature1'],
176    'debug_goma': ['debug', 'goma'],
177    'phase_1': ['rel', 'phase_1'],
178    'phase_2': ['rel', 'phase_2'],
179    'android_bot': ['android'],
180    'ios_error': ['error'],
181  },
182  'mixins': {
183    'error': {
184      'gn_args': 'error',
185    },
186    'fake_args_bot': {
187      'args_file': '//build/args/bots/fake_group/fake_args_bot.gn',
188    },
189    'fake_feature1': {
190      'gn_args': 'enable_doom_melon=true',
191    },
192    'goma': {
193      'gn_args': 'use_goma=true',
194    },
195    'phase_1': {
196      'gn_args': 'phase=1',
197    },
198    'phase_2': {
199      'gn_args': 'phase=2',
200    },
201    'rel': {
202      'gn_args': 'is_debug=false dcheck_always_on=false',
203    },
204    'debug': {
205      'gn_args': 'is_debug=true',
206    },
207    'android': {
208      'gn_args': 'target_os="android" dcheck_always_on=false',
209    }
210  },
211}
212"""
213
214
215def CreateFakeMBW(files=None, win32=False):
216  mbw = FakeMBW(win32=win32)
217  mbw.files.setdefault(mbw.default_config, TEST_CONFIG)
218  mbw.files.setdefault(
219      mbw.ToAbsPath('//testing/buildbot/gn_isolate_map.pyl'), '''{
220      "foo_unittests": {
221        "label": "//foo:foo_unittests",
222        "type": "console_test_launcher",
223        "args": [],
224      },
225    }''')
226  mbw.files.setdefault(
227      mbw.ToAbsPath('//build/args/bots/fake_group/fake_args_bot.gn'),
228      'is_debug = false\ndcheck_always_on=false\n')
229  mbw.files.setdefault(mbw.ToAbsPath('//tools/mb/rts_banned_suites.json'), '{}')
230  if files:
231    for path, contents in list(files.items()):
232      mbw.files[path] = contents
233      if path.endswith('.runtime_deps'):
234
235        def FakeCall(cmd, env=None, capture_output=True, stdin=None):
236          # pylint: disable=cell-var-from-loop
237          del cmd
238          del env
239          del capture_output
240          del stdin
241          mbw.files[path] = contents
242          return 0, '', ''
243
244        # pylint: disable=invalid-name
245        mbw.Call = FakeCall
246  return mbw
247
248
249class UnitTest(unittest.TestCase):
250  # pylint: disable=invalid-name
251  def check(self,
252            args,
253            mbw=None,
254            files=None,
255            out=None,
256            err=None,
257            ret=None,
258            env=None):
259    if not mbw:
260      mbw = CreateFakeMBW(files)
261
262    try:
263      prev_env = os.environ.copy()
264      os.environ = env if env else prev_env
265      actual_ret = mbw.Main(args)
266    finally:
267      os.environ = prev_env
268    self.assertEqual(
269        actual_ret, ret,
270        "ret: %s, out: %s, err: %s" % (actual_ret, mbw.out, mbw.err))
271    if out is not None:
272      self.assertEqual(mbw.out, out)
273    if err is not None:
274      self.assertEqual(mbw.err, err)
275    return mbw
276
277  def test_gen_swarming(self):
278    files = {
279        '/tmp/swarming_targets':
280        'foo_unittests\n',
281        '/fake_src/testing/buildbot/gn_isolate_map.pyl':
282        ("{'foo_unittests': {"
283         "  'label': '//foo:foo_unittests',"
284         "  'type': 'raw',"
285         "  'args': [],"
286         "}}\n"),
287        '/fake_src/out/Default/foo_unittests.runtime_deps': ("foo_unittests\n"),
288    }
289    mbw = CreateFakeMBW(files)
290    self.check([
291        'gen', '-c', 'debug_goma', '--swarming-targets-file',
292        '/tmp/swarming_targets', '//out/Default'
293    ],
294               mbw=mbw,
295               ret=0)
296    self.assertIn('/fake_src/out/Default/foo_unittests.isolate', mbw.files)
297    self.assertIn('/fake_src/out/Default/foo_unittests.isolated.gen.json',
298                  mbw.files)
299
300  def test_gen_swarming_android(self):
301    test_files = {
302        '/tmp/swarming_targets':
303        'foo_unittests\n',
304        '/fake_src/testing/buildbot/gn_isolate_map.pyl':
305        ("{'foo_unittests': {"
306         "  'label': '//foo:foo_unittests',"
307         "  'type': 'console_test_launcher',"
308         "}}\n"),
309        '/fake_src/out/Default/foo_unittests.runtime_deps': ("foo_unittests\n"),
310    }
311    mbw = self.check([
312        'gen', '-c', 'android_bot', '//out/Default', '--swarming-targets-file',
313        '/tmp/swarming_targets', '--isolate-map-file',
314        '/fake_src/testing/buildbot/gn_isolate_map.pyl'
315    ],
316                     files=test_files,
317                     ret=0)
318
319    isolate_file = mbw.files['/fake_src/out/Default/foo_unittests.isolate']
320    isolate_file_contents = ast.literal_eval(isolate_file)
321    files = isolate_file_contents['variables']['files']
322    command = isolate_file_contents['variables']['command']
323
324    self.assertEqual(
325        files,
326        ['../../.vpython3', '../../testing/test_env.py', 'foo_unittests'])
327    self.assertEqual(command, [
328        'luci-auth',
329        'context',
330        '--',
331        'vpython3',
332        '../../build/android/test_wrapper/logdog_wrapper.py',
333        '--target',
334        'foo_unittests',
335        '--logdog-bin-cmd',
336        '../../.task_template_packages/logdog_butler',
337        '--logcat-output-file',
338        '${ISOLATED_OUTDIR}/logcats',
339        '--store-tombstones',
340    ])
341
342  def test_gen_swarming_android_junit_test(self):
343    test_files = {
344        '/tmp/swarming_targets':
345        'foo_unittests\n',
346        '/fake_src/testing/buildbot/gn_isolate_map.pyl':
347        ("{'foo_unittests': {"
348         "  'label': '//foo:foo_unittests',"
349         "  'type': 'junit_test',"
350         "}}\n"),
351        '/fake_src/out/Default/foo_unittests.runtime_deps': ("foo_unittests\n"),
352    }
353    mbw = self.check([
354        'gen', '-c', 'android_bot', '//out/Default', '--swarming-targets-file',
355        '/tmp/swarming_targets', '--isolate-map-file',
356        '/fake_src/testing/buildbot/gn_isolate_map.pyl'
357    ],
358                     files=test_files,
359                     ret=0)
360
361    isolate_file = mbw.files['/fake_src/out/Default/foo_unittests.isolate']
362    isolate_file_contents = ast.literal_eval(isolate_file)
363    files = isolate_file_contents['variables']['files']
364    command = isolate_file_contents['variables']['command']
365
366    self.assertEqual(
367        files,
368        ['../../.vpython3', '../../testing/test_env.py', 'foo_unittests'])
369    self.assertEqual(command, [
370        'luci-auth',
371        'context',
372        '--',
373        'vpython3',
374        '../../build/android/test_wrapper/logdog_wrapper.py',
375        '--target',
376        'foo_unittests',
377        '--logdog-bin-cmd',
378        '../../.task_template_packages/logdog_butler',
379        '--logcat-output-file',
380        '${ISOLATED_OUTDIR}/logcats',
381        '--store-tombstones',
382    ])
383
384  def test_gen_timeout(self):
385    test_files = {
386        '/tmp/swarming_targets':
387        'foo_unittests\n',
388        '/fake_src/testing/buildbot/gn_isolate_map.pyl':
389        ("{'foo_unittests': {"
390         "  'label': '//foo:foo_unittests',"
391         "  'type': 'non_parallel_console_test_launcher',"
392         "  'timeout': 500,"
393         "}}\n"),
394        '/fake_src/out/Default/foo_unittests.runtime_deps': ("foo_unittests\n"),
395    }
396    mbw = self.check([
397        'gen', '-c', 'debug_goma', '//out/Default', '--swarming-targets-file',
398        '/tmp/swarming_targets', '--isolate-map-file',
399        '/fake_src/testing/buildbot/gn_isolate_map.pyl'
400    ],
401                     files=test_files,
402                     ret=0)
403
404    isolate_file = mbw.files['/fake_src/out/Default/foo_unittests.isolate']
405    isolate_file_contents = ast.literal_eval(isolate_file)
406    files = isolate_file_contents['variables']['files']
407    command = isolate_file_contents['variables']['command']
408
409    self.assertEqual(files, [
410        '../../.vpython3',
411        '../../testing/test_env.py',
412        '../../third_party/gtest-parallel/gtest-parallel',
413        '../../third_party/gtest-parallel/gtest_parallel.py',
414        '../../tools_webrtc/gtest-parallel-wrapper.py',
415        'foo_unittests',
416    ])
417    self.assertEqual(command, [
418        'vpython3',
419        '../../testing/test_env.py',
420        '../../tools_webrtc/gtest-parallel-wrapper.py',
421        '--output_dir=${ISOLATED_OUTDIR}/test_logs',
422        '--gtest_color=no',
423        '--timeout=500',
424        '--workers=1',
425        '--retry_failed=3',
426        './foo_unittests',
427        '--asan=0',
428        '--lsan=0',
429        '--msan=0',
430        '--tsan=0',
431    ])
432
433  def test_gen_script(self):
434    test_files = {
435        '/tmp/swarming_targets':
436        'foo_unittests_script\n',
437        '/fake_src/testing/buildbot/gn_isolate_map.pyl':
438        ("{'foo_unittests_script': {"
439         "  'label': '//foo:foo_unittests',"
440         "  'type': 'script',"
441         "  'script': '//foo/foo_unittests_script.py',"
442         "}}\n"),
443        '/fake_src/out/Default/foo_unittests_script.runtime_deps':
444        ("foo_unittests\n"
445         "foo_unittests_script.py\n"),
446    }
447    mbw = self.check([
448        'gen', '-c', 'debug_goma', '//out/Default', '--swarming-targets-file',
449        '/tmp/swarming_targets', '--isolate-map-file',
450        '/fake_src/testing/buildbot/gn_isolate_map.pyl'
451    ],
452                     files=test_files,
453                     ret=0)
454
455    isolate_file = (
456        mbw.files['/fake_src/out/Default/foo_unittests_script.isolate'])
457    isolate_file_contents = ast.literal_eval(isolate_file)
458    files = isolate_file_contents['variables']['files']
459    command = isolate_file_contents['variables']['command']
460
461    self.assertEqual(files, [
462        '../../.vpython3',
463        '../../testing/test_env.py',
464        'foo_unittests',
465        'foo_unittests_script.py',
466    ])
467    self.assertEqual(command, [
468        'vpython3',
469        '../../foo/foo_unittests_script.py',
470    ])
471
472  def test_gen_raw(self):
473    test_files = {
474        '/tmp/swarming_targets':
475        'foo_unittests\n',
476        '/fake_src/testing/buildbot/gn_isolate_map.pyl':
477        ("{'foo_unittests': {"
478         "  'label': '//foo:foo_unittests',"
479         "  'type': 'raw',"
480         "}}\n"),
481        '/fake_src/out/Default/foo_unittests.runtime_deps': ("foo_unittests\n"),
482    }
483    mbw = self.check([
484        'gen', '-c', 'debug_goma', '//out/Default', '--swarming-targets-file',
485        '/tmp/swarming_targets', '--isolate-map-file',
486        '/fake_src/testing/buildbot/gn_isolate_map.pyl'
487    ],
488                     files=test_files,
489                     ret=0)
490
491    isolate_file = mbw.files['/fake_src/out/Default/foo_unittests.isolate']
492    isolate_file_contents = ast.literal_eval(isolate_file)
493    files = isolate_file_contents['variables']['files']
494    command = isolate_file_contents['variables']['command']
495
496    self.assertEqual(files, [
497        '../../.vpython3',
498        '../../testing/test_env.py',
499        'foo_unittests',
500    ])
501    self.assertEqual(command, ['bin/run_foo_unittests'])
502
503  def test_gen_non_parallel_console_test_launcher(self):
504    test_files = {
505        '/tmp/swarming_targets':
506        'foo_unittests\n',
507        '/fake_src/testing/buildbot/gn_isolate_map.pyl':
508        ("{'foo_unittests': {"
509         "  'label': '//foo:foo_unittests',"
510         "  'type': 'non_parallel_console_test_launcher',"
511         "}}\n"),
512        '/fake_src/out/Default/foo_unittests.runtime_deps': ("foo_unittests\n"),
513    }
514    mbw = self.check([
515        'gen', '-c', 'debug_goma', '//out/Default', '--swarming-targets-file',
516        '/tmp/swarming_targets', '--isolate-map-file',
517        '/fake_src/testing/buildbot/gn_isolate_map.pyl'
518    ],
519                     files=test_files,
520                     ret=0)
521
522    isolate_file = mbw.files['/fake_src/out/Default/foo_unittests.isolate']
523    isolate_file_contents = ast.literal_eval(isolate_file)
524    files = isolate_file_contents['variables']['files']
525    command = isolate_file_contents['variables']['command']
526
527    self.assertEqual(files, [
528        '../../.vpython3',
529        '../../testing/test_env.py',
530        '../../third_party/gtest-parallel/gtest-parallel',
531        '../../third_party/gtest-parallel/gtest_parallel.py',
532        '../../tools_webrtc/gtest-parallel-wrapper.py',
533        'foo_unittests',
534    ])
535    self.assertEqual(command, [
536        'vpython3',
537        '../../testing/test_env.py',
538        '../../tools_webrtc/gtest-parallel-wrapper.py',
539        '--output_dir=${ISOLATED_OUTDIR}/test_logs',
540        '--gtest_color=no',
541        '--timeout=900',
542        '--workers=1',
543        '--retry_failed=3',
544        './foo_unittests',
545        '--asan=0',
546        '--lsan=0',
547        '--msan=0',
548        '--tsan=0',
549    ])
550
551  def test_isolate_windowed_test_launcher_linux(self):
552    test_files = {
553        '/tmp/swarming_targets':
554        'foo_unittests\n',
555        '/fake_src/testing/buildbot/gn_isolate_map.pyl':
556        ("{'foo_unittests': {"
557         "  'label': '//foo:foo_unittests',"
558         "  'type': 'windowed_test_launcher',"
559         "}}\n"),
560        '/fake_src/out/Default/foo_unittests.runtime_deps':
561        ("foo_unittests\n"
562         "some_resource_file\n"),
563    }
564    mbw = self.check([
565        'gen', '-c', 'debug_goma', '//out/Default', '--swarming-targets-file',
566        '/tmp/swarming_targets', '--isolate-map-file',
567        '/fake_src/testing/buildbot/gn_isolate_map.pyl'
568    ],
569                     files=test_files,
570                     ret=0)
571
572    isolate_file = mbw.files['/fake_src/out/Default/foo_unittests.isolate']
573    isolate_file_contents = ast.literal_eval(isolate_file)
574    files = isolate_file_contents['variables']['files']
575    command = isolate_file_contents['variables']['command']
576
577    self.assertEqual(files, [
578        '../../.vpython3',
579        '../../testing/test_env.py',
580        '../../testing/xvfb.py',
581        '../../third_party/gtest-parallel/gtest-parallel',
582        '../../third_party/gtest-parallel/gtest_parallel.py',
583        '../../tools_webrtc/gtest-parallel-wrapper.py',
584        'foo_unittests',
585        'some_resource_file',
586    ])
587    self.assertEqual(command, [
588        'vpython3',
589        '../../testing/xvfb.py',
590        '../../tools_webrtc/gtest-parallel-wrapper.py',
591        '--output_dir=${ISOLATED_OUTDIR}/test_logs',
592        '--gtest_color=no',
593        '--timeout=900',
594        '--retry_failed=3',
595        './foo_unittests',
596        '--asan=0',
597        '--lsan=0',
598        '--msan=0',
599        '--tsan=0',
600    ])
601
602  def test_gen_windowed_test_launcher_win(self):
603    files = {
604        'c:\\fake_src\\out\\Default\\tmp\\swarming_targets':
605        'unittests\n',
606        'c:\\fake_src\\testing\\buildbot\\gn_isolate_map.pyl':
607        ("{'unittests': {"
608         "  'label': '//somewhere:unittests',"
609         "  'type': 'windowed_test_launcher',"
610         "}}\n"),
611        r'c:\fake_src\out\Default\unittests.exe.runtime_deps':
612        ("unittests.exe\n"
613         "some_dependency\n"),
614    }
615    mbw = CreateFakeMBW(files=files, win32=True)
616    self.check([
617        'gen', '-c', 'debug_goma', '--swarming-targets-file',
618        'c:\\fake_src\\out\\Default\\tmp\\swarming_targets',
619        '--isolate-map-file',
620        'c:\\fake_src\\testing\\buildbot\\gn_isolate_map.pyl', '//out/Default'
621    ],
622               mbw=mbw,
623               ret=0)
624
625    isolate_file = mbw.files['c:\\fake_src\\out\\Default\\unittests.isolate']
626    isolate_file_contents = ast.literal_eval(isolate_file)
627    files = isolate_file_contents['variables']['files']
628    command = isolate_file_contents['variables']['command']
629
630    self.assertEqual(files, [
631        '../../.vpython3',
632        '../../testing/test_env.py',
633        '../../third_party/gtest-parallel/gtest-parallel',
634        '../../third_party/gtest-parallel/gtest_parallel.py',
635        '../../tools_webrtc/gtest-parallel-wrapper.py',
636        'some_dependency',
637        'unittests.exe',
638    ])
639    self.assertEqual(command, [
640        'vpython3',
641        '../../testing/test_env.py',
642        '../../tools_webrtc/gtest-parallel-wrapper.py',
643        '--output_dir=${ISOLATED_OUTDIR}/test_logs',
644        '--gtest_color=no',
645        '--timeout=900',
646        '--retry_failed=3',
647        r'.\unittests.exe',
648        '--asan=0',
649        '--lsan=0',
650        '--msan=0',
651        '--tsan=0',
652    ])
653
654  def test_gen_console_test_launcher(self):
655    test_files = {
656        '/tmp/swarming_targets':
657        'foo_unittests\n',
658        '/fake_src/testing/buildbot/gn_isolate_map.pyl':
659        ("{'foo_unittests': {"
660         "  'label': '//foo:foo_unittests',"
661         "  'type': 'console_test_launcher',"
662         "}}\n"),
663        '/fake_src/out/Default/foo_unittests.runtime_deps': ("foo_unittests\n"),
664    }
665    mbw = self.check([
666        'gen', '-c', 'debug_goma', '//out/Default', '--swarming-targets-file',
667        '/tmp/swarming_targets', '--isolate-map-file',
668        '/fake_src/testing/buildbot/gn_isolate_map.pyl'
669    ],
670                     files=test_files,
671                     ret=0)
672
673    isolate_file = mbw.files['/fake_src/out/Default/foo_unittests.isolate']
674    isolate_file_contents = ast.literal_eval(isolate_file)
675    files = isolate_file_contents['variables']['files']
676    command = isolate_file_contents['variables']['command']
677
678    self.assertEqual(files, [
679        '../../.vpython3',
680        '../../testing/test_env.py',
681        '../../third_party/gtest-parallel/gtest-parallel',
682        '../../third_party/gtest-parallel/gtest_parallel.py',
683        '../../tools_webrtc/gtest-parallel-wrapper.py',
684        'foo_unittests',
685    ])
686    self.assertEqual(command, [
687        'vpython3',
688        '../../testing/test_env.py',
689        '../../tools_webrtc/gtest-parallel-wrapper.py',
690        '--output_dir=${ISOLATED_OUTDIR}/test_logs',
691        '--gtest_color=no',
692        '--timeout=900',
693        '--retry_failed=3',
694        './foo_unittests',
695        '--asan=0',
696        '--lsan=0',
697        '--msan=0',
698        '--tsan=0',
699    ])
700
701  def test_isolate_test_launcher_with_webcam(self):
702    test_files = {
703        '/tmp/swarming_targets':
704        'foo_unittests\n',
705        '/fake_src/testing/buildbot/gn_isolate_map.pyl':
706        ("{'foo_unittests': {"
707         "  'label': '//foo:foo_unittests',"
708         "  'type': 'console_test_launcher',"
709         "  'use_webcam': True,"
710         "}}\n"),
711        '/fake_src/out/Default/foo_unittests.runtime_deps':
712        ("foo_unittests\n"
713         "some_resource_file\n"),
714    }
715    mbw = self.check([
716        'gen', '-c', 'debug_goma', '//out/Default', '--swarming-targets-file',
717        '/tmp/swarming_targets', '--isolate-map-file',
718        '/fake_src/testing/buildbot/gn_isolate_map.pyl'
719    ],
720                     files=test_files,
721                     ret=0)
722
723    isolate_file = mbw.files['/fake_src/out/Default/foo_unittests.isolate']
724    isolate_file_contents = ast.literal_eval(isolate_file)
725    files = isolate_file_contents['variables']['files']
726    command = isolate_file_contents['variables']['command']
727
728    self.assertEqual(files, [
729        '../../.vpython3',
730        '../../testing/test_env.py',
731        '../../third_party/gtest-parallel/gtest-parallel',
732        '../../third_party/gtest-parallel/gtest_parallel.py',
733        '../../tools_webrtc/ensure_webcam_is_running.py',
734        '../../tools_webrtc/gtest-parallel-wrapper.py',
735        'foo_unittests',
736        'some_resource_file',
737    ])
738    self.assertEqual(command, [
739        'vpython3',
740        '../../tools_webrtc/ensure_webcam_is_running.py',
741        'vpython3',
742        '../../testing/test_env.py',
743        '../../tools_webrtc/gtest-parallel-wrapper.py',
744        '--output_dir=${ISOLATED_OUTDIR}/test_logs',
745        '--gtest_color=no',
746        '--timeout=900',
747        '--retry_failed=3',
748        './foo_unittests',
749        '--asan=0',
750        '--lsan=0',
751        '--msan=0',
752        '--tsan=0',
753    ])
754
755  def test_isolate(self):
756    files = {
757        '/fake_src/out/Default/toolchain.ninja':
758        "",
759        '/fake_src/testing/buildbot/gn_isolate_map.pyl':
760        ("{'foo_unittests': {"
761         "  'label': '//foo:foo_unittests',"
762         "  'type': 'non_parallel_console_test_launcher',"
763         "}}\n"),
764        '/fake_src/out/Default/foo_unittests.runtime_deps': ("foo_unittests\n"),
765    }
766    self.check(
767        ['isolate', '-c', 'debug_goma', '//out/Default', 'foo_unittests'],
768        files=files,
769        ret=0)
770
771    # test running isolate on an existing build_dir
772    files['/fake_src/out/Default/args.gn'] = 'is_debug = true\n'
773    self.check(['isolate', '//out/Default', 'foo_unittests'],
774               files=files,
775               ret=0)
776    files['/fake_src/out/Default/mb_type'] = 'gn\n'
777    self.check(['isolate', '//out/Default', 'foo_unittests'],
778               files=files,
779               ret=0)
780
781if __name__ == '__main__':
782  unittest.main()
783