Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / PRESUBMIT_test.py
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import glob
7 import json
8 import os
9 import re
10 import subprocess
11 import sys
12 import unittest
13
14 import PRESUBMIT
15
16
17 _TEST_DATA_DIR = 'base/test/data/presubmit'
18
19
20 class MockInputApi(object):
21   def __init__(self):
22     self.json = json
23     self.re = re
24     self.os_path = os.path
25     self.python_executable = sys.executable
26     self.subprocess = subprocess
27     self.files = []
28     self.is_committing = False
29
30   def AffectedFiles(self, file_filter=None):
31     return self.files
32
33   def PresubmitLocalPath(self):
34     return os.path.dirname(__file__)
35
36   def ReadFile(self, filename, mode='rU'):
37     for file_ in self.files:
38       if file_.LocalPath() == filename:
39         return '\n'.join(file_.NewContents())
40     # Otherwise, file is not in our mock API.
41     raise IOError, "No such file or directory: '%s'" % filename
42
43
44 class MockOutputApi(object):
45   class PresubmitResult(object):
46     def __init__(self, message, items=None, long_text=''):
47       self.message = message
48       self.items = items
49       self.long_text = long_text
50
51   class PresubmitError(PresubmitResult):
52     def __init__(self, message, items, long_text=''):
53       MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
54       self.type = 'error'
55
56   class PresubmitPromptWarning(PresubmitResult):
57     def __init__(self, message, items, long_text=''):
58       MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
59       self.type = 'warning'
60
61   class PresubmitNotifyResult(PresubmitResult):
62     def __init__(self, message, items, long_text=''):
63       MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
64       self.type = 'notify'
65
66   class PresubmitPromptOrNotify(PresubmitResult):
67     def __init__(self, message, items, long_text=''):
68       MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
69       self.type = 'promptOrNotify'
70
71
72 class MockFile(object):
73   def __init__(self, local_path, new_contents):
74     self._local_path = local_path
75     self._new_contents = new_contents
76     self._changed_contents = [(i + 1, l) for i, l in enumerate(new_contents)]
77
78   def ChangedContents(self):
79     return self._changed_contents
80
81   def NewContents(self):
82     return self._new_contents
83
84   def LocalPath(self):
85     return self._local_path
86
87
88 class MockChange(object):
89   def __init__(self, changed_files):
90     self._changed_files = changed_files
91
92   def LocalPaths(self):
93     return self._changed_files
94
95
96 class IncludeOrderTest(unittest.TestCase):
97   def testSystemHeaderOrder(self):
98     scope = [(1, '#include <csystem.h>'),
99              (2, '#include <cppsystem>'),
100              (3, '#include "acustom.h"')]
101     all_linenums = [linenum for (linenum, _) in scope]
102     mock_input_api = MockInputApi()
103     warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
104                                                     '', all_linenums)
105     self.assertEqual(0, len(warnings))
106
107   def testSystemHeaderOrderMismatch1(self):
108     scope = [(10, '#include <cppsystem>'),
109              (20, '#include <csystem.h>'),
110              (30, '#include "acustom.h"')]
111     all_linenums = [linenum for (linenum, _) in scope]
112     mock_input_api = MockInputApi()
113     warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
114                                                     '', all_linenums)
115     self.assertEqual(1, len(warnings))
116     self.assertTrue('20' in warnings[0])
117
118   def testSystemHeaderOrderMismatch2(self):
119     scope = [(10, '#include <cppsystem>'),
120              (20, '#include "acustom.h"'),
121              (30, '#include <csystem.h>')]
122     all_linenums = [linenum for (linenum, _) in scope]
123     mock_input_api = MockInputApi()
124     warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
125                                                     '', all_linenums)
126     self.assertEqual(1, len(warnings))
127     self.assertTrue('30' in warnings[0])
128
129   def testSystemHeaderOrderMismatch3(self):
130     scope = [(10, '#include "acustom.h"'),
131              (20, '#include <csystem.h>'),
132              (30, '#include <cppsystem>')]
133     all_linenums = [linenum for (linenum, _) in scope]
134     mock_input_api = MockInputApi()
135     warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
136                                                     '', all_linenums)
137     self.assertEqual(2, len(warnings))
138     self.assertTrue('20' in warnings[0])
139     self.assertTrue('30' in warnings[1])
140
141   def testAlphabeticalOrderMismatch(self):
142     scope = [(10, '#include <csystem.h>'),
143              (15, '#include <bsystem.h>'),
144              (20, '#include <cppsystem>'),
145              (25, '#include <bppsystem>'),
146              (30, '#include "bcustom.h"'),
147              (35, '#include "acustom.h"')]
148     all_linenums = [linenum for (linenum, _) in scope]
149     mock_input_api = MockInputApi()
150     warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
151                                                     '', all_linenums)
152     self.assertEqual(3, len(warnings))
153     self.assertTrue('15' in warnings[0])
154     self.assertTrue('25' in warnings[1])
155     self.assertTrue('35' in warnings[2])
156
157   def testSpecialFirstInclude1(self):
158     mock_input_api = MockInputApi()
159     contents = ['#include "some/path/foo.h"',
160                 '#include "a/header.h"']
161     mock_file = MockFile('some/path/foo.cc', contents)
162     warnings = PRESUBMIT._CheckIncludeOrderInFile(
163         mock_input_api, mock_file, range(1, len(contents) + 1))
164     self.assertEqual(0, len(warnings))
165
166   def testSpecialFirstInclude2(self):
167     mock_input_api = MockInputApi()
168     contents = ['#include "some/other/path/foo.h"',
169                 '#include "a/header.h"']
170     mock_file = MockFile('some/path/foo.cc', contents)
171     warnings = PRESUBMIT._CheckIncludeOrderInFile(
172         mock_input_api, mock_file, range(1, len(contents) + 1))
173     self.assertEqual(0, len(warnings))
174
175   def testSpecialFirstInclude3(self):
176     mock_input_api = MockInputApi()
177     contents = ['#include "some/path/foo.h"',
178                 '#include "a/header.h"']
179     mock_file = MockFile('some/path/foo_platform.cc', contents)
180     warnings = PRESUBMIT._CheckIncludeOrderInFile(
181         mock_input_api, mock_file, range(1, len(contents) + 1))
182     self.assertEqual(0, len(warnings))
183
184   def testSpecialFirstInclude4(self):
185     mock_input_api = MockInputApi()
186     contents = ['#include "some/path/bar.h"',
187                 '#include "a/header.h"']
188     mock_file = MockFile('some/path/foo_platform.cc', contents)
189     warnings = PRESUBMIT._CheckIncludeOrderInFile(
190         mock_input_api, mock_file, range(1, len(contents) + 1))
191     self.assertEqual(1, len(warnings))
192     self.assertTrue('2' in warnings[0])
193
194   def testSpecialFirstInclude5(self):
195     mock_input_api = MockInputApi()
196     contents = ['#include "some/other/path/foo.h"',
197                 '#include "a/header.h"']
198     mock_file = MockFile('some/path/foo-suffix.h', contents)
199     warnings = PRESUBMIT._CheckIncludeOrderInFile(
200         mock_input_api, mock_file, range(1, len(contents) + 1))
201     self.assertEqual(0, len(warnings))
202
203   def testSpecialFirstInclude6(self):
204     mock_input_api = MockInputApi()
205     contents = ['#include "some/other/path/foo_win.h"',
206                 '#include <set>',
207                 '#include "a/header.h"']
208     mock_file = MockFile('some/path/foo_unittest_win.h', contents)
209     warnings = PRESUBMIT._CheckIncludeOrderInFile(
210         mock_input_api, mock_file, range(1, len(contents) + 1))
211     self.assertEqual(0, len(warnings))
212
213   def testOrderAlreadyWrong(self):
214     scope = [(1, '#include "b.h"'),
215              (2, '#include "a.h"'),
216              (3, '#include "c.h"')]
217     mock_input_api = MockInputApi()
218     warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
219                                                     '', [3])
220     self.assertEqual(0, len(warnings))
221
222   def testConflictAdded1(self):
223     scope = [(1, '#include "a.h"'),
224              (2, '#include "c.h"'),
225              (3, '#include "b.h"')]
226     mock_input_api = MockInputApi()
227     warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
228                                                     '', [2])
229     self.assertEqual(1, len(warnings))
230     self.assertTrue('3' in warnings[0])
231
232   def testConflictAdded2(self):
233     scope = [(1, '#include "c.h"'),
234              (2, '#include "b.h"'),
235              (3, '#include "d.h"')]
236     mock_input_api = MockInputApi()
237     warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
238                                                     '', [2])
239     self.assertEqual(1, len(warnings))
240     self.assertTrue('2' in warnings[0])
241
242   def testIfElifElseEndif(self):
243     mock_input_api = MockInputApi()
244     contents = ['#include "e.h"',
245                 '#define foo',
246                 '#include "f.h"',
247                 '#undef foo',
248                 '#include "e.h"',
249                 '#if foo',
250                 '#include "d.h"',
251                 '#elif bar',
252                 '#include "c.h"',
253                 '#else',
254                 '#include "b.h"',
255                 '#endif',
256                 '#include "a.h"']
257     mock_file = MockFile('', contents)
258     warnings = PRESUBMIT._CheckIncludeOrderInFile(
259         mock_input_api, mock_file, range(1, len(contents) + 1))
260     self.assertEqual(0, len(warnings))
261
262   def testExcludedIncludes(self):
263     # #include <sys/...>'s can appear in any order.
264     mock_input_api = MockInputApi()
265     contents = ['#include <sys/b.h>',
266                 '#include <sys/a.h>']
267     mock_file = MockFile('', contents)
268     warnings = PRESUBMIT._CheckIncludeOrderInFile(
269         mock_input_api, mock_file, range(1, len(contents) + 1))
270     self.assertEqual(0, len(warnings))
271
272     contents = ['#include <atlbase.h>',
273                 '#include <aaa.h>']
274     mock_file = MockFile('', contents)
275     warnings = PRESUBMIT._CheckIncludeOrderInFile(
276         mock_input_api, mock_file, range(1, len(contents) + 1))
277     self.assertEqual(0, len(warnings))
278
279     contents = ['#include "build/build_config.h"',
280                 '#include "aaa.h"']
281     mock_file = MockFile('', contents)
282     warnings = PRESUBMIT._CheckIncludeOrderInFile(
283         mock_input_api, mock_file, range(1, len(contents) + 1))
284     self.assertEqual(0, len(warnings))
285
286   def testCheckOnlyCFiles(self):
287     mock_input_api = MockInputApi()
288     mock_output_api = MockOutputApi()
289     contents = ['#include <b.h>',
290                 '#include <a.h>']
291     mock_file_cc = MockFile('something.cc', contents)
292     mock_file_h = MockFile('something.h', contents)
293     mock_file_other = MockFile('something.py', contents)
294     mock_input_api.files = [mock_file_cc, mock_file_h, mock_file_other]
295     warnings = PRESUBMIT._CheckIncludeOrder(mock_input_api, mock_output_api)
296     self.assertEqual(1, len(warnings))
297     self.assertEqual(2, len(warnings[0].items))
298     self.assertEqual('promptOrNotify', warnings[0].type)
299
300   def testUncheckableIncludes(self):
301     mock_input_api = MockInputApi()
302     contents = ['#include <windows.h>',
303                 '#include "b.h"',
304                 '#include "a.h"']
305     mock_file = MockFile('', contents)
306     warnings = PRESUBMIT._CheckIncludeOrderInFile(
307         mock_input_api, mock_file, range(1, len(contents) + 1))
308     self.assertEqual(1, len(warnings))
309
310     contents = ['#include "gpu/command_buffer/gles_autogen.h"',
311                 '#include "b.h"',
312                 '#include "a.h"']
313     mock_file = MockFile('', contents)
314     warnings = PRESUBMIT._CheckIncludeOrderInFile(
315         mock_input_api, mock_file, range(1, len(contents) + 1))
316     self.assertEqual(1, len(warnings))
317
318     contents = ['#include "gl_mock_autogen.h"',
319                 '#include "b.h"',
320                 '#include "a.h"']
321     mock_file = MockFile('', contents)
322     warnings = PRESUBMIT._CheckIncludeOrderInFile(
323         mock_input_api, mock_file, range(1, len(contents) + 1))
324     self.assertEqual(1, len(warnings))
325
326     contents = ['#include "ipc/some_macros.h"',
327                 '#include "b.h"',
328                 '#include "a.h"']
329     mock_file = MockFile('', contents)
330     warnings = PRESUBMIT._CheckIncludeOrderInFile(
331         mock_input_api, mock_file, range(1, len(contents) + 1))
332     self.assertEqual(1, len(warnings))
333
334
335 class VersionControlConflictsTest(unittest.TestCase):
336   def testTypicalConflict(self):
337     lines = ['<<<<<<< HEAD',
338              '  base::ScopedTempDir temp_dir_;',
339              '=======',
340              '  ScopedTempDir temp_dir_;',
341              '>>>>>>> master']
342     errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
343         MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
344     self.assertEqual(3, len(errors))
345     self.assertTrue('1' in errors[0])
346     self.assertTrue('3' in errors[1])
347     self.assertTrue('5' in errors[2])
348
349
350 class BadExtensionsTest(unittest.TestCase):
351   def testBadRejFile(self):
352     mock_input_api = MockInputApi()
353     mock_input_api.files = [
354       MockFile('some/path/foo.cc', ''),
355       MockFile('some/path/foo.cc.rej', ''),
356       MockFile('some/path2/bar.h.rej', ''),
357     ]
358
359     results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
360     self.assertEqual(1, len(results))
361     self.assertEqual(2, len(results[0].items))
362     self.assertTrue('foo.cc.rej' in results[0].items[0])
363     self.assertTrue('bar.h.rej' in results[0].items[1])
364
365   def testBadOrigFile(self):
366     mock_input_api = MockInputApi()
367     mock_input_api.files = [
368       MockFile('other/path/qux.h.orig', ''),
369       MockFile('other/path/qux.h', ''),
370       MockFile('other/path/qux.cc', ''),
371     ]
372
373     results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
374     self.assertEqual(1, len(results))
375     self.assertEqual(1, len(results[0].items))
376     self.assertTrue('qux.h.orig' in results[0].items[0])
377
378   def testGoodFiles(self):
379     mock_input_api = MockInputApi()
380     mock_input_api.files = [
381       MockFile('other/path/qux.h', ''),
382       MockFile('other/path/qux.cc', ''),
383     ]
384     results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
385     self.assertEqual(0, len(results))
386
387   def testOnlyOwnersFiles(self):
388     mock_change = MockChange([
389       'some/path/OWNERS',
390       'A\Windows\Path\OWNERS',
391     ])
392     results = PRESUBMIT.GetPreferredTryMasters(None, mock_change)
393     self.assertEqual({}, results)
394
395
396 class InvalidOSMacroNamesTest(unittest.TestCase):
397   def testInvalidOSMacroNames(self):
398     lines = ['#if defined(OS_WINDOWS)',
399              ' #elif defined(OS_WINDOW)',
400              ' # if defined(OS_MACOSX) || defined(OS_CHROME)',
401              '# else  // defined(OS_MAC)',
402              '#endif  // defined(OS_MACOS)']
403     errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
404         MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
405     self.assertEqual(len(lines), len(errors))
406     self.assertTrue(':1 OS_WINDOWS' in errors[0])
407     self.assertTrue('(did you mean OS_WIN?)' in errors[0])
408
409   def testValidOSMacroNames(self):
410     lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS]
411     errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
412         MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
413     self.assertEqual(0, len(errors))
414
415
416 class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
417   def testInvalidIfDefinedMacroNames(self):
418     lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
419              '#if !defined(TARGET_IPHONE_SIMULATOR)',
420              '#elif defined(TARGET_IPHONE_SIMULATOR)',
421              '#ifdef TARGET_IPHONE_SIMULATOR',
422              ' # ifdef TARGET_IPHONE_SIMULATOR',
423              '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
424              '# else  // defined(TARGET_IPHONE_SIMULATOR)',
425              '#endif  // defined(TARGET_IPHONE_SIMULATOR)',]
426     errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
427         MockInputApi(), MockFile('some/path/source.mm', lines))
428     self.assertEqual(len(lines), len(errors))
429
430   def testValidIfDefinedMacroNames(self):
431     lines = ['#if defined(FOO)',
432              '#ifdef BAR',]
433     errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
434         MockInputApi(), MockFile('some/path/source.cc', lines))
435     self.assertEqual(0, len(errors))
436
437
438 class CheckAddedDepsHaveTetsApprovalsTest(unittest.TestCase):
439   def testFilesToCheckForIncomingDeps(self):
440     changed_lines = [
441       '"+breakpad",',
442       '"+chrome/installer",',
443       '"+chrome/plugin/chrome_content_plugin_client.h",',
444       '"+chrome/utility/chrome_content_utility_client.h",',
445       '"+chromeos/chromeos_paths.h",',
446       '"+components/crash",',
447       '"+components/nacl/common",',
448       '"+content/public/browser/render_process_host.h",',
449       '"+jni/fooblat.h",',
450       '"+grit",  # For generated headers',
451       '"+grit/generated_resources.h",',
452       '"+grit/",',
453       '"+policy",  # For generated headers and source',
454       '"+sandbox",',
455       '"+tools/memory_watcher",',
456       '"+third_party/lss/linux_syscall_support.h",',
457     ]
458     files_to_check = PRESUBMIT._FilesToCheckForIncomingDeps(re, changed_lines)
459     expected = set([
460       'breakpad/DEPS',
461       'chrome/installer/DEPS',
462       'chrome/plugin/chrome_content_plugin_client.h',
463       'chrome/utility/chrome_content_utility_client.h',
464       'chromeos/chromeos_paths.h',
465       'components/crash/DEPS',
466       'components/nacl/common/DEPS',
467       'content/public/browser/render_process_host.h',
468       'policy/DEPS',
469       'sandbox/DEPS',
470       'tools/memory_watcher/DEPS',
471       'third_party/lss/linux_syscall_support.h',
472     ])
473     self.assertEqual(expected, files_to_check);
474
475
476 class JSONParsingTest(unittest.TestCase):
477   def testSuccess(self):
478     input_api = MockInputApi()
479     filename = 'valid_json.json'
480     contents = ['// This is a comment.',
481                 '{',
482                 '  "key1": ["value1", "value2"],',
483                 '  "key2": 3  // This is an inline comment.',
484                 '}'
485                 ]
486     input_api.files = [MockFile(filename, contents)]
487     self.assertEqual(None,
488                      PRESUBMIT._GetJSONParseError(input_api, filename))
489
490   def testFailure(self):
491     input_api = MockInputApi()
492     test_data = [
493       ('invalid_json_1.json',
494        ['{ x }'],
495        'Expecting property name:'),
496       ('invalid_json_2.json',
497        ['// Hello world!',
498         '{ "hello": "world }'],
499        'Unterminated string starting at:'),
500       ('invalid_json_3.json',
501        ['{ "a": "b", "c": "d", }'],
502        'Expecting property name:'),
503       ('invalid_json_4.json',
504        ['{ "a": "b" "c": "d" }'],
505        'Expecting , delimiter:'),
506       ]
507
508     input_api.files = [MockFile(filename, contents)
509                        for (filename, contents, _) in test_data]
510
511     for (filename, _, expected_error) in test_data:
512       actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
513       self.assertTrue(expected_error in str(actual_error),
514                       "'%s' not found in '%s'" % (expected_error, actual_error))
515
516   def testNoEatComments(self):
517     input_api = MockInputApi()
518     file_with_comments = 'file_with_comments.json'
519     contents_with_comments = ['// This is a comment.',
520                               '{',
521                               '  "key1": ["value1", "value2"],',
522                               '  "key2": 3  // This is an inline comment.',
523                               '}'
524                               ]
525     file_without_comments = 'file_without_comments.json'
526     contents_without_comments = ['{',
527                                  '  "key1": ["value1", "value2"],',
528                                  '  "key2": 3',
529                                  '}'
530                                  ]
531     input_api.files = [MockFile(file_with_comments, contents_with_comments),
532                        MockFile(file_without_comments,
533                                 contents_without_comments)]
534
535     self.assertEqual('No JSON object could be decoded',
536                      str(PRESUBMIT._GetJSONParseError(input_api,
537                                                       file_with_comments,
538                                                       eat_comments=False)))
539     self.assertEqual(None,
540                      PRESUBMIT._GetJSONParseError(input_api,
541                                                   file_without_comments,
542                                                   eat_comments=False))
543
544
545 class IDLParsingTest(unittest.TestCase):
546   def testSuccess(self):
547     input_api = MockInputApi()
548     filename = 'valid_idl_basics.idl'
549     contents = ['// Tests a valid IDL file.',
550                 'namespace idl_basics {',
551                 '  enum EnumType {',
552                 '    name1,',
553                 '    name2',
554                 '  };',
555                 '',
556                 '  dictionary MyType1 {',
557                 '    DOMString a;',
558                 '  };',
559                 '',
560                 '  callback Callback1 = void();',
561                 '  callback Callback2 = void(long x);',
562                 '  callback Callback3 = void(MyType1 arg);',
563                 '  callback Callback4 = void(EnumType type);',
564                 '',
565                 '  interface Functions {',
566                 '    static void function1();',
567                 '    static void function2(long x);',
568                 '    static void function3(MyType1 arg);',
569                 '    static void function4(Callback1 cb);',
570                 '    static void function5(Callback2 cb);',
571                 '    static void function6(Callback3 cb);',
572                 '    static void function7(Callback4 cb);',
573                 '  };',
574                 '',
575                 '  interface Events {',
576                 '    static void onFoo1();',
577                 '    static void onFoo2(long x);',
578                 '    static void onFoo2(MyType1 arg);',
579                 '    static void onFoo3(EnumType type);',
580                 '  };',
581                 '};'
582                 ]
583     input_api.files = [MockFile(filename, contents)]
584     self.assertEqual(None,
585                      PRESUBMIT._GetIDLParseError(input_api, filename))
586
587   def testFailure(self):
588     input_api = MockInputApi()
589     test_data = [
590       ('invalid_idl_1.idl',
591        ['//',
592         'namespace test {',
593         '  dictionary {',
594         '    DOMString s;',
595         '  };',
596         '};'],
597        'Unexpected "{" after keyword "dictionary".\n'),
598       # TODO(yoz): Disabled because it causes the IDL parser to hang.
599       # See crbug.com/363830.
600       # ('invalid_idl_2.idl',
601       #  (['namespace test {',
602       #    '  dictionary MissingSemicolon {',
603       #    '    DOMString a',
604       #    '    DOMString b;',
605       #    '  };',
606       #    '};'],
607       #   'Unexpected symbol DOMString after symbol a.'),
608       ('invalid_idl_3.idl',
609        ['//',
610         'namespace test {',
611         '  enum MissingComma {',
612         '    name1',
613         '    name2',
614         '  };',
615         '};'],
616        'Unexpected symbol name2 after symbol name1.'),
617       ('invalid_idl_4.idl',
618        ['//',
619         'namespace test {',
620         '  enum TrailingComma {',
621         '    name1,',
622         '    name2,',
623         '  };',
624         '};'],
625        'Trailing comma in block.'),
626       ('invalid_idl_5.idl',
627        ['//',
628         'namespace test {',
629         '  callback Callback1 = void(;',
630         '};'],
631        'Unexpected ";" after "(".'),
632       ('invalid_idl_6.idl',
633        ['//',
634         'namespace test {',
635         '  callback Callback1 = void(long );',
636         '};'],
637        'Unexpected ")" after symbol long.'),
638       ('invalid_idl_7.idl',
639        ['//',
640         'namespace test {',
641         '  interace Events {',
642         '    static void onFoo1();',
643         '  };',
644         '};'],
645        'Unexpected symbol Events after symbol interace.'),
646       ('invalid_idl_8.idl',
647        ['//',
648         'namespace test {',
649         '  interface NotEvent {',
650         '    static void onFoo1();',
651         '  };',
652         '};'],
653        'Did not process Interface Interface(NotEvent)'),
654       ('invalid_idl_9.idl',
655        ['//',
656         'namespace test {',
657         '  interface {',
658         '    static void function1();',
659         '  };',
660         '};'],
661        'Interface missing name.'),
662       ]
663
664     input_api.files = [MockFile(filename, contents)
665                        for (filename, contents, _) in test_data]
666
667     for (filename, _, expected_error) in test_data:
668       actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
669       self.assertTrue(expected_error in str(actual_error),
670                       "'%s' not found in '%s'" % (expected_error, actual_error))
671
672
673 class TryServerMasterTest(unittest.TestCase):
674   def testTryServerMasters(self):
675     bots = {
676         'tryserver.chromium.gpu': [
677             'mac_gpu',
678             'mac_gpu_triggered_tests',
679             'linux_gpu',
680             'linux_gpu_triggered_tests',
681             'win_gpu',
682             'win_gpu_triggered_tests',
683         ],
684         'tryserver.chromium.mac': [
685             'ios_dbg_simulator',
686             'ios_rel_device',
687             'ios_rel_device_ninja',
688             'mac_asan',
689             'mac_asan_64',
690             'mac_chromium_compile_dbg',
691             'mac_chromium_compile_rel',
692             'mac_chromium_dbg',
693             'mac_chromium_rel',
694             'mac_nacl_sdk',
695             'mac_nacl_sdk_build',
696             'mac_rel_naclmore',
697             'mac_valgrind',
698             'mac_x64_rel',
699             'mac_xcodebuild',
700         ],
701         'tryserver.chromium.linux': [
702             'android_aosp',
703             'android_chromium_gn_compile_dbg',
704             'android_chromium_gn_compile_rel',
705             'android_clang_dbg',
706             'android_dbg',
707             'android_dbg_recipe',
708             'android_dbg_triggered_tests',
709             'android_dbg_triggered_tests_recipe',
710             'android_fyi_dbg',
711             'android_fyi_dbg_triggered_tests',
712             'android_rel',
713             'android_rel_triggered_tests',
714             'android_x86_dbg',
715             'blink_android_compile_dbg',
716             'blink_android_compile_rel',
717             'blink_presubmit',
718             'chromium_presubmit',
719             'linux_arm_cross_compile',
720             'linux_arm_tester',
721             'linux_chromeos_asan',
722             'linux_chromeos_browser_asan',
723             'linux_chromeos_valgrind',
724             'linux_chromium_chromeos_dbg',
725             'linux_chromium_chromeos_rel',
726             'linux_chromium_compile_dbg',
727             'linux_chromium_compile_rel',
728             'linux_chromium_dbg',
729             'linux_chromium_gn_dbg',
730             'linux_chromium_gn_rel',
731             'linux_chromium_rel',
732             'linux_chromium_trusty32_dbg',
733             'linux_chromium_trusty32_rel',
734             'linux_chromium_trusty_dbg',
735             'linux_chromium_trusty_rel',
736             'linux_clang_tsan',
737             'linux_ecs_ozone',
738             'linux_layout',
739             'linux_layout_asan',
740             'linux_layout_rel',
741             'linux_layout_rel_32',
742             'linux_nacl_sdk',
743             'linux_nacl_sdk_bionic',
744             'linux_nacl_sdk_bionic_build',
745             'linux_nacl_sdk_build',
746             'linux_redux',
747             'linux_rel_naclmore',
748             'linux_rel_precise32',
749             'linux_valgrind',
750             'tools_build_presubmit',
751         ],
752         'tryserver.chromium.win': [
753             'win8_aura',
754             'win8_chromium_dbg',
755             'win8_chromium_rel',
756             'win_chromium_compile_dbg',
757             'win_chromium_compile_rel',
758             'win_chromium_dbg',
759             'win_chromium_rel',
760             'win_chromium_rel',
761             'win_chromium_x64_dbg',
762             'win_chromium_x64_rel',
763             'win_drmemory',
764             'win_nacl_sdk',
765             'win_nacl_sdk_build',
766             'win_rel_naclmore',
767          ],
768     }
769     for master, bots in bots.iteritems():
770       for bot in bots:
771         self.assertEqual(master, PRESUBMIT.GetTryServerMasterForBot(bot),
772                          'bot=%s: expected %s, computed %s' % (
773             bot, master, PRESUBMIT.GetTryServerMasterForBot(bot)))
774
775
776 if __name__ == '__main__':
777   unittest.main()