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