Detect built-in varyings' invariant setting conflicts.
[chromium-blink-merge.git] / PRESUBMIT_test.py
blob02a10c624672e67cd9fb1a6ee906b42fe72a0f44
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.
6 import glob
7 import json
8 import os
9 import re
10 import subprocess
11 import sys
12 import unittest
14 import PRESUBMIT
17 _TEST_DATA_DIR = 'base/test/data/presubmit'
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
30 def AffectedFiles(self, file_filter=None):
31 return self.files
33 def PresubmitLocalPath(self):
34 return os.path.dirname(__file__)
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
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
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'
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'
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'
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'
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)]
78 def ChangedContents(self):
79 return self._changed_contents
81 def NewContents(self):
82 return self._new_contents
84 def LocalPath(self):
85 return self._local_path
88 class MockChange(object):
89 def __init__(self, changed_files):
90 self._changed_files = changed_files
92 def LocalPaths(self):
93 return self._changed_files
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))
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])
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])
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])
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])
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))
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))
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))
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])
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))
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))
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))
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])
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])
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))
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))
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))
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))
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)
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))
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))
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))
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))
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])
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', ''),
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])
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', ''),
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])
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', ''),
384 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
385 self.assertEqual(0, len(results))
387 def testOnlyOwnersFiles(self):
388 mock_change = MockChange([
389 'some/path/OWNERS',
390 'A\Windows\Path\OWNERS',
392 results = PRESUBMIT.GetPreferredTryMasters(None, mock_change)
393 self.assertEqual({}, results)
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])
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))
416 class InvalidOverideAndFinalTest(unittest.TestCase):
417 def testValidOverrideConstructs(self):
418 mock_input_api = MockInputApi()
419 lines = ['foo1() override;',
420 'foo2() final;',
421 '#DEFINE OVERRIDE_METHOD_OVERLOAD',
422 '#DEFINE FINAL_METHOD',
423 '#DEFINE OVERRIDE_OVERRIDE_SOMETHING',
424 '#DEFINE SOMETHING_OVERRIDE_SOMETHING',
425 '#DEFINE SOMETHING_SOMETHING_OVERRIDE',
426 '#DEFINE FINAL_OVERRIDE_FINAL',
427 '#DEFINE SOMETHING_OVERRIDE_FINAL',
428 '#DEFINE OVERRIDE_OVERRIDE_OVERRIDE',
429 '#endif // FINAL_METHOD',
430 '#endif // OVERRIDE_METHOD_OVERLOAD']
431 mock_file_h = MockFile('something.h', lines)
432 mock_input_api.files = [mock_file_h]
433 errors = PRESUBMIT._CheckForOverrideAndFinalRules(mock_input_api,
434 MockOutputApi())
435 self.assertEqual(0, len(errors))
437 def testInvalidOverrideConstructsInHeaders(self):
438 mock_input_api = MockInputApi()
439 lines_cpp = ['foo2() FINAL;']
440 lines_h = ['foo1() OVERRIDE;']
441 mock_file_cpp = MockFile('something.cpp', lines_cpp)
442 mock_file_h = MockFile('something.h', lines_h)
443 mock_input_api.files = [mock_file_cpp, mock_file_h]
444 errors = PRESUBMIT._CheckForOverrideAndFinalRules(mock_input_api,
445 MockOutputApi())
446 self.assertEqual(1, len(errors))
448 def testInvalidOverrideConstructsInCpp(self):
449 mock_input_api = MockInputApi()
450 lines_cpp = ['foo2() FINAL;']
451 mock_file_cpp = MockFile('something.cpp', lines_cpp)
452 mock_input_api.files = [mock_file_cpp]
453 errors = PRESUBMIT._CheckForOverrideAndFinalRules(mock_input_api,
454 MockOutputApi())
455 self.assertEqual(1, len(errors))
457 def testInvalidOverrideConstructsInCc(self):
458 mock_input_api = MockInputApi()
459 lines_cc = ['foo3() override FINAL;']
460 mock_file_cc = MockFile('something.cc', lines_cc)
461 mock_input_api.files = [mock_file_cc]
462 errors = PRESUBMIT._CheckForOverrideAndFinalRules(mock_input_api,
463 MockOutputApi())
464 self.assertEqual(1, len(errors))
466 def testInvalidOverrideConstructsInMm(self):
467 mock_input_api = MockInputApi()
468 lines_mm = ['foo4() OVERRIDE final;']
469 mock_file_mm = MockFile('something.mm', lines_mm)
470 mock_input_api.files = [mock_file_mm]
471 errors = PRESUBMIT._CheckForOverrideAndFinalRules(mock_input_api,
472 MockOutputApi())
473 self.assertEqual(1, len(errors))
476 class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
477 def testInvalidIfDefinedMacroNames(self):
478 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
479 '#if !defined(TARGET_IPHONE_SIMULATOR)',
480 '#elif defined(TARGET_IPHONE_SIMULATOR)',
481 '#ifdef TARGET_IPHONE_SIMULATOR',
482 ' # ifdef TARGET_IPHONE_SIMULATOR',
483 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
484 '# else // defined(TARGET_IPHONE_SIMULATOR)',
485 '#endif // defined(TARGET_IPHONE_SIMULATOR)',]
486 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
487 MockInputApi(), MockFile('some/path/source.mm', lines))
488 self.assertEqual(len(lines), len(errors))
490 def testValidIfDefinedMacroNames(self):
491 lines = ['#if defined(FOO)',
492 '#ifdef BAR',]
493 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
494 MockInputApi(), MockFile('some/path/source.cc', lines))
495 self.assertEqual(0, len(errors))
498 class CheckAddedDepsHaveTetsApprovalsTest(unittest.TestCase):
499 def testFilesToCheckForIncomingDeps(self):
500 changed_lines = [
501 '"+breakpad",',
502 '"+chrome/installer",',
503 '"+chrome/plugin/chrome_content_plugin_client.h",',
504 '"+chrome/utility/chrome_content_utility_client.h",',
505 '"+chromeos/chromeos_paths.h",',
506 '"+components/crash",',
507 '"+components/nacl/common",',
508 '"+content/public/browser/render_process_host.h",',
509 '"+jni/fooblat.h",',
510 '"+grit", # For generated headers',
511 '"+grit/generated_resources.h",',
512 '"+grit/",',
513 '"+policy", # For generated headers and source',
514 '"+sandbox",',
515 '"+tools/memory_watcher",',
516 '"+third_party/lss/linux_syscall_support.h",',
518 files_to_check = PRESUBMIT._FilesToCheckForIncomingDeps(re, changed_lines)
519 expected = set([
520 'breakpad/DEPS',
521 'chrome/installer/DEPS',
522 'chrome/plugin/chrome_content_plugin_client.h',
523 'chrome/utility/chrome_content_utility_client.h',
524 'chromeos/chromeos_paths.h',
525 'components/crash/DEPS',
526 'components/nacl/common/DEPS',
527 'content/public/browser/render_process_host.h',
528 'policy/DEPS',
529 'sandbox/DEPS',
530 'tools/memory_watcher/DEPS',
531 'third_party/lss/linux_syscall_support.h',
533 self.assertEqual(expected, files_to_check);
536 class JSONParsingTest(unittest.TestCase):
537 def testSuccess(self):
538 input_api = MockInputApi()
539 filename = 'valid_json.json'
540 contents = ['// This is a comment.',
541 '{',
542 ' "key1": ["value1", "value2"],',
543 ' "key2": 3 // This is an inline comment.',
546 input_api.files = [MockFile(filename, contents)]
547 self.assertEqual(None,
548 PRESUBMIT._GetJSONParseError(input_api, filename))
550 def testFailure(self):
551 input_api = MockInputApi()
552 test_data = [
553 ('invalid_json_1.json',
554 ['{ x }'],
555 'Expecting property name:'),
556 ('invalid_json_2.json',
557 ['// Hello world!',
558 '{ "hello": "world }'],
559 'Unterminated string starting at:'),
560 ('invalid_json_3.json',
561 ['{ "a": "b", "c": "d", }'],
562 'Expecting property name:'),
563 ('invalid_json_4.json',
564 ['{ "a": "b" "c": "d" }'],
565 'Expecting , delimiter:'),
568 input_api.files = [MockFile(filename, contents)
569 for (filename, contents, _) in test_data]
571 for (filename, _, expected_error) in test_data:
572 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
573 self.assertTrue(expected_error in str(actual_error),
574 "'%s' not found in '%s'" % (expected_error, actual_error))
576 def testNoEatComments(self):
577 input_api = MockInputApi()
578 file_with_comments = 'file_with_comments.json'
579 contents_with_comments = ['// This is a comment.',
580 '{',
581 ' "key1": ["value1", "value2"],',
582 ' "key2": 3 // This is an inline comment.',
585 file_without_comments = 'file_without_comments.json'
586 contents_without_comments = ['{',
587 ' "key1": ["value1", "value2"],',
588 ' "key2": 3',
591 input_api.files = [MockFile(file_with_comments, contents_with_comments),
592 MockFile(file_without_comments,
593 contents_without_comments)]
595 self.assertEqual('No JSON object could be decoded',
596 str(PRESUBMIT._GetJSONParseError(input_api,
597 file_with_comments,
598 eat_comments=False)))
599 self.assertEqual(None,
600 PRESUBMIT._GetJSONParseError(input_api,
601 file_without_comments,
602 eat_comments=False))
605 class IDLParsingTest(unittest.TestCase):
606 def testSuccess(self):
607 input_api = MockInputApi()
608 filename = 'valid_idl_basics.idl'
609 contents = ['// Tests a valid IDL file.',
610 'namespace idl_basics {',
611 ' enum EnumType {',
612 ' name1,',
613 ' name2',
614 ' };',
616 ' dictionary MyType1 {',
617 ' DOMString a;',
618 ' };',
620 ' callback Callback1 = void();',
621 ' callback Callback2 = void(long x);',
622 ' callback Callback3 = void(MyType1 arg);',
623 ' callback Callback4 = void(EnumType type);',
625 ' interface Functions {',
626 ' static void function1();',
627 ' static void function2(long x);',
628 ' static void function3(MyType1 arg);',
629 ' static void function4(Callback1 cb);',
630 ' static void function5(Callback2 cb);',
631 ' static void function6(Callback3 cb);',
632 ' static void function7(Callback4 cb);',
633 ' };',
635 ' interface Events {',
636 ' static void onFoo1();',
637 ' static void onFoo2(long x);',
638 ' static void onFoo2(MyType1 arg);',
639 ' static void onFoo3(EnumType type);',
640 ' };',
641 '};'
643 input_api.files = [MockFile(filename, contents)]
644 self.assertEqual(None,
645 PRESUBMIT._GetIDLParseError(input_api, filename))
647 def testFailure(self):
648 input_api = MockInputApi()
649 test_data = [
650 ('invalid_idl_1.idl',
651 ['//',
652 'namespace test {',
653 ' dictionary {',
654 ' DOMString s;',
655 ' };',
656 '};'],
657 'Unexpected "{" after keyword "dictionary".\n'),
658 # TODO(yoz): Disabled because it causes the IDL parser to hang.
659 # See crbug.com/363830.
660 # ('invalid_idl_2.idl',
661 # (['namespace test {',
662 # ' dictionary MissingSemicolon {',
663 # ' DOMString a',
664 # ' DOMString b;',
665 # ' };',
666 # '};'],
667 # 'Unexpected symbol DOMString after symbol a.'),
668 ('invalid_idl_3.idl',
669 ['//',
670 'namespace test {',
671 ' enum MissingComma {',
672 ' name1',
673 ' name2',
674 ' };',
675 '};'],
676 'Unexpected symbol name2 after symbol name1.'),
677 ('invalid_idl_4.idl',
678 ['//',
679 'namespace test {',
680 ' enum TrailingComma {',
681 ' name1,',
682 ' name2,',
683 ' };',
684 '};'],
685 'Trailing comma in block.'),
686 ('invalid_idl_5.idl',
687 ['//',
688 'namespace test {',
689 ' callback Callback1 = void(;',
690 '};'],
691 'Unexpected ";" after "(".'),
692 ('invalid_idl_6.idl',
693 ['//',
694 'namespace test {',
695 ' callback Callback1 = void(long );',
696 '};'],
697 'Unexpected ")" after symbol long.'),
698 ('invalid_idl_7.idl',
699 ['//',
700 'namespace test {',
701 ' interace Events {',
702 ' static void onFoo1();',
703 ' };',
704 '};'],
705 'Unexpected symbol Events after symbol interace.'),
706 ('invalid_idl_8.idl',
707 ['//',
708 'namespace test {',
709 ' interface NotEvent {',
710 ' static void onFoo1();',
711 ' };',
712 '};'],
713 'Did not process Interface Interface(NotEvent)'),
714 ('invalid_idl_9.idl',
715 ['//',
716 'namespace test {',
717 ' interface {',
718 ' static void function1();',
719 ' };',
720 '};'],
721 'Interface missing name.'),
724 input_api.files = [MockFile(filename, contents)
725 for (filename, contents, _) in test_data]
727 for (filename, _, expected_error) in test_data:
728 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
729 self.assertTrue(expected_error in str(actual_error),
730 "'%s' not found in '%s'" % (expected_error, actual_error))
733 class TryServerMasterTest(unittest.TestCase):
734 def testTryServerMasters(self):
735 bots = {
736 'tryserver.chromium.gpu': [
737 'mac_gpu',
738 'mac_gpu_triggered_tests',
739 'linux_gpu',
740 'linux_gpu_triggered_tests',
741 'win_gpu',
742 'win_gpu_triggered_tests',
744 'tryserver.chromium.mac': [
745 'ios_dbg_simulator',
746 'ios_rel_device',
747 'ios_rel_device_ninja',
748 'mac_asan',
749 'mac_asan_64',
750 'mac_chromium_compile_dbg',
751 'mac_chromium_compile_rel',
752 'mac_chromium_dbg',
753 'mac_chromium_rel',
754 'mac_chromium_rel_swarming',
755 'mac_nacl_sdk',
756 'mac_nacl_sdk_build',
757 'mac_rel_naclmore',
758 'mac_valgrind',
759 'mac_x64_rel',
760 'mac_xcodebuild',
762 'tryserver.chromium.linux': [
763 'android_aosp',
764 'android_chromium_gn_compile_dbg',
765 'android_chromium_gn_compile_rel',
766 'android_clang_dbg',
767 'android_dbg',
768 'android_dbg_recipe',
769 'android_dbg_triggered_tests',
770 'android_dbg_triggered_tests_recipe',
771 'android_fyi_dbg',
772 'android_fyi_dbg_triggered_tests',
773 'android_rel',
774 'android_rel_triggered_tests',
775 'android_x86_dbg',
776 'blink_android_compile_dbg',
777 'blink_android_compile_rel',
778 'blink_presubmit',
779 'chromium_presubmit',
780 'linux_arm_cross_compile',
781 'linux_arm_tester',
782 'linux_chromeos_asan',
783 'linux_chromeos_browser_asan',
784 'linux_chromeos_valgrind',
785 'linux_chromium_chromeos_clang_dbg',
786 'linux_chromium_chromeos_clang_rel',
787 'linux_chromium_chromeos_dbg',
788 'linux_chromium_chromeos_rel',
789 'linux_chromium_clang_dbg',
790 'linux_chromium_clang_rel',
791 'linux_chromium_compile_dbg',
792 'linux_chromium_compile_rel',
793 'linux_chromium_dbg',
794 'linux_chromium_gn_dbg',
795 'linux_chromium_gn_rel',
796 'linux_chromium_rel',
797 'linux_chromium_rel_swarming',
798 'linux_chromium_trusty32_dbg',
799 'linux_chromium_trusty32_rel',
800 'linux_chromium_trusty_dbg',
801 'linux_chromium_trusty_rel',
802 'linux_clang_tsan',
803 'linux_ecs_ozone',
804 'linux_layout',
805 'linux_layout_asan',
806 'linux_layout_rel',
807 'linux_layout_rel_32',
808 'linux_nacl_sdk',
809 'linux_nacl_sdk_bionic',
810 'linux_nacl_sdk_bionic_build',
811 'linux_nacl_sdk_build',
812 'linux_redux',
813 'linux_rel_naclmore',
814 'linux_rel_precise32',
815 'linux_valgrind',
816 'tools_build_presubmit',
818 'tryserver.chromium.win': [
819 'win8_aura',
820 'win8_chromium_dbg',
821 'win8_chromium_rel',
822 'win_chromium_compile_dbg',
823 'win_chromium_compile_rel',
824 'win_chromium_dbg',
825 'win_chromium_rel',
826 'win_chromium_rel',
827 'win_chromium_rel_swarming',
828 'win_chromium_rel_swarming',
829 'win_chromium_x64_dbg',
830 'win_chromium_x64_rel',
831 'win_drmemory',
832 'win_nacl_sdk',
833 'win_nacl_sdk_build',
834 'win_rel_naclmore',
837 for master, bots in bots.iteritems():
838 for bot in bots:
839 self.assertEqual(master, PRESUBMIT.GetTryServerMasterForBot(bot),
840 'bot=%s: expected %s, computed %s' % (
841 bot, master, PRESUBMIT.GetTryServerMasterForBot(bot)))
844 if __name__ == '__main__':
845 unittest.main()