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.
12 from PRESUBMIT_test_mocks import MockChange, MockFile, MockAffectedFile
13 from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi
15 _TEST_DATA_DIR = 'base/test/data/presubmit'
17 class VersionControlConflictsTest(unittest.TestCase):
18 def testTypicalConflict(self):
19 lines = ['<<<<<<< HEAD',
20 ' base::ScopedTempDir temp_dir_;',
22 ' ScopedTempDir temp_dir_;',
24 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
25 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
26 self.assertEqual(3, len(errors))
27 self.assertTrue('1' in errors[0])
28 self.assertTrue('3' in errors[1])
29 self.assertTrue('5' in errors[2])
31 def testIgnoresReadmes(self):
32 lines = ['A First Level Header',
33 '====================',
35 'A Second Level Header',
36 '---------------------']
37 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
38 MockInputApi(), MockFile('some/polymer/README.md', lines))
39 self.assertEqual(0, len(errors))
41 class UmaHistogramChangeMatchedOrNotTest(unittest.TestCase):
42 def testTypicalCorrectlyMatchedChange(self):
43 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
45 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
46 diff_xml = ['<histogram name="Bla.Foo.Dummy"> </histogram>']
47 mock_input_api = MockInputApi()
48 mock_input_api.files = [
49 MockFile('some/path/foo.cc', diff_cc),
50 MockFile('some/path/foo.java', diff_java),
51 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
53 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
55 self.assertEqual(0, len(warnings))
57 def testTypicalNotMatchedChange(self):
58 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
60 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
61 mock_input_api = MockInputApi()
62 mock_input_api.files = [
63 MockFile('some/path/foo.cc', diff_cc),
64 MockFile('some/path/foo.java', diff_java),
66 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
68 self.assertEqual(1, len(warnings))
69 self.assertEqual('warning', warnings[0].type)
70 self.assertTrue('foo.cc' in warnings[0].items[0])
71 self.assertTrue('foo.java' in warnings[0].items[1])
73 def testTypicalNotMatchedChangeViaSuffixes(self):
74 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
76 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
77 diff_xml = ['<histogram_suffixes name="SuperHistogram">',
78 ' <suffix name="Dummy"/>',
79 ' <affected-histogram name="Snafu.Dummy"/>',
81 mock_input_api = MockInputApi()
82 mock_input_api.files = [
83 MockFile('some/path/foo.cc', diff_cc),
84 MockFile('some/path/foo.java', diff_java),
85 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
87 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
89 self.assertEqual(1, len(warnings))
90 self.assertEqual('warning', warnings[0].type)
91 self.assertTrue('foo.cc' in warnings[0].items[0])
92 self.assertTrue('foo.java' in warnings[0].items[1])
94 def testTypicalCorrectlyMatchedChangeViaSuffixes(self):
95 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
97 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
98 diff_xml = ['<histogram_suffixes name="SuperHistogram">',
99 ' <suffix name="Dummy"/>',
100 ' <affected-histogram name="Bla.Foo"/>',
102 mock_input_api = MockInputApi()
103 mock_input_api.files = [
104 MockFile('some/path/foo.cc', diff_cc),
105 MockFile('some/path/foo.java', diff_java),
106 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
108 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
110 self.assertEqual(0, len(warnings))
112 def testTypicalCorrectlyMatchedChangeViaSuffixesWithSeparator(self):
113 diff_cc = ['UMA_HISTOGRAM_BOOL("Snafu_Dummy", true)']
114 diff_java = ['RecordHistogram.recordBooleanHistogram("Snafu_Dummy", true)']
115 diff_xml = ['<histogram_suffixes name="SuperHistogram" separator="_">',
116 ' <suffix name="Dummy"/>',
117 ' <affected-histogram name="Snafu"/>',
119 mock_input_api = MockInputApi()
120 mock_input_api.files = [
121 MockFile('some/path/foo.cc', diff_cc),
122 MockFile('some/path/foo.java', diff_java),
123 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
125 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
127 self.assertEqual(0, len(warnings))
129 def testNameMatch(self):
130 # Check that the detected histogram name is "Dummy" and not, e.g.,
131 # "Dummy\", true); // The \"correct"
132 diff_cc = ['UMA_HISTOGRAM_BOOL("Dummy", true); // The "correct" histogram']
134 'RecordHistogram.recordBooleanHistogram("Dummy", true);'
135 + ' // The "correct" histogram']
136 diff_xml = ['<histogram name="Dummy"> </histogram>']
137 mock_input_api = MockInputApi()
138 mock_input_api.files = [
139 MockFile('some/path/foo.cc', diff_cc),
140 MockFile('some/path/foo.java', diff_java),
141 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
143 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
145 self.assertEqual(0, len(warnings))
147 def testSimilarMacroNames(self):
148 diff_cc = ['PUMA_HISTOGRAM_COOL("Mountain Lion", 42)']
150 'FakeRecordHistogram.recordFakeHistogram("Mountain Lion", 42)']
151 mock_input_api = MockInputApi()
152 mock_input_api.files = [
153 MockFile('some/path/foo.cc', diff_cc),
154 MockFile('some/path/foo.java', diff_java),
156 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
158 self.assertEqual(0, len(warnings))
160 def testMultiLine(self):
161 diff_cc = ['UMA_HISTOGRAM_BOOLEAN(', ' "Multi.Line", true)']
162 diff_cc2 = ['UMA_HISTOGRAM_BOOLEAN(', ' "Multi.Line"', ' , true)']
164 'RecordHistogram.recordBooleanHistogram(',
165 ' "Multi.Line", true);',
167 mock_input_api = MockInputApi()
168 mock_input_api.files = [
169 MockFile('some/path/foo.cc', diff_cc),
170 MockFile('some/path/foo2.cc', diff_cc2),
171 MockFile('some/path/foo.java', diff_java),
173 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
175 self.assertEqual(1, len(warnings))
176 self.assertEqual('warning', warnings[0].type)
177 self.assertTrue('foo.cc' in warnings[0].items[0])
178 self.assertTrue('foo2.cc' in warnings[0].items[1])
180 class BadExtensionsTest(unittest.TestCase):
181 def testBadRejFile(self):
182 mock_input_api = MockInputApi()
183 mock_input_api.files = [
184 MockFile('some/path/foo.cc', ''),
185 MockFile('some/path/foo.cc.rej', ''),
186 MockFile('some/path2/bar.h.rej', ''),
189 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
190 self.assertEqual(1, len(results))
191 self.assertEqual(2, len(results[0].items))
192 self.assertTrue('foo.cc.rej' in results[0].items[0])
193 self.assertTrue('bar.h.rej' in results[0].items[1])
195 def testBadOrigFile(self):
196 mock_input_api = MockInputApi()
197 mock_input_api.files = [
198 MockFile('other/path/qux.h.orig', ''),
199 MockFile('other/path/qux.h', ''),
200 MockFile('other/path/qux.cc', ''),
203 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
204 self.assertEqual(1, len(results))
205 self.assertEqual(1, len(results[0].items))
206 self.assertTrue('qux.h.orig' in results[0].items[0])
208 def testGoodFiles(self):
209 mock_input_api = MockInputApi()
210 mock_input_api.files = [
211 MockFile('other/path/qux.h', ''),
212 MockFile('other/path/qux.cc', ''),
214 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
215 self.assertEqual(0, len(results))
218 class CheckSingletonInHeadersTest(unittest.TestCase):
219 def testSingletonInArbitraryHeader(self):
220 diff_singleton_h = ['base::subtle::AtomicWord '
221 'base::Singleton<Type, Traits, DifferentiatingType>::']
222 diff_foo_h = ['// base::Singleton<Foo> in comment.',
223 'friend class base::Singleton<Foo>']
224 diff_foo2_h = [' //Foo* bar = base::Singleton<Foo>::get();']
225 diff_bad_h = ['Foo* foo = base::Singleton<Foo>::get();']
226 mock_input_api = MockInputApi()
227 mock_input_api.files = [MockAffectedFile('base/memory/singleton.h',
229 MockAffectedFile('foo.h', diff_foo_h),
230 MockAffectedFile('foo2.h', diff_foo2_h),
231 MockAffectedFile('bad.h', diff_bad_h)]
232 warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api,
234 self.assertEqual(1, len(warnings))
235 self.assertEqual(1, len(warnings[0].items))
236 self.assertEqual('error', warnings[0].type)
237 self.assertTrue('Found base::Singleton<T>' in warnings[0].message)
239 def testSingletonInCC(self):
240 diff_cc = ['Foo* foo = base::Singleton<Foo>::get();']
241 mock_input_api = MockInputApi()
242 mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)]
243 warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api,
245 self.assertEqual(0, len(warnings))
248 class InvalidOSMacroNamesTest(unittest.TestCase):
249 def testInvalidOSMacroNames(self):
250 lines = ['#if defined(OS_WINDOWS)',
251 ' #elif defined(OS_WINDOW)',
252 ' # if defined(OS_MACOSX) || defined(OS_CHROME)',
253 '# else // defined(OS_MAC)',
254 '#endif // defined(OS_MACOS)']
255 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
256 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
257 self.assertEqual(len(lines), len(errors))
258 self.assertTrue(':1 OS_WINDOWS' in errors[0])
259 self.assertTrue('(did you mean OS_WIN?)' in errors[0])
261 def testValidOSMacroNames(self):
262 lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS]
263 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
264 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
265 self.assertEqual(0, len(errors))
268 class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
269 def testInvalidIfDefinedMacroNames(self):
270 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
271 '#if !defined(TARGET_IPHONE_SIMULATOR)',
272 '#elif defined(TARGET_IPHONE_SIMULATOR)',
273 '#ifdef TARGET_IPHONE_SIMULATOR',
274 ' # ifdef TARGET_IPHONE_SIMULATOR',
275 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
276 '# else // defined(TARGET_IPHONE_SIMULATOR)',
277 '#endif // defined(TARGET_IPHONE_SIMULATOR)',]
278 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
279 MockInputApi(), MockFile('some/path/source.mm', lines))
280 self.assertEqual(len(lines), len(errors))
282 def testValidIfDefinedMacroNames(self):
283 lines = ['#if defined(FOO)',
285 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
286 MockInputApi(), MockFile('some/path/source.cc', lines))
287 self.assertEqual(0, len(errors))
290 class CheckAddedDepsHaveTetsApprovalsTest(unittest.TestCase):
292 def calculate(self, old_include_rules, old_specific_include_rules,
293 new_include_rules, new_specific_include_rules):
294 return PRESUBMIT._CalculateAddedDeps(
295 os.path, 'include_rules = %r\nspecific_include_rules = %r' % (
296 old_include_rules, old_specific_include_rules),
297 'include_rules = %r\nspecific_include_rules = %r' % (
298 new_include_rules, new_specific_include_rules))
300 def testCalculateAddedDeps(self):
301 old_include_rules = [
310 old_specific_include_rules = {
316 new_include_rules = [
323 '+grit/generated_resources.h",',
327 '+' + os.path.join('third_party', 'WebKit'),
329 new_specific_include_rules = {
339 os.path.join('chrome', 'DEPS'),
340 os.path.join('gpu', 'DEPS'),
341 os.path.join('components', 'DEPS'),
342 os.path.join('policy', 'DEPS'),
343 os.path.join('third_party', 'WebKit', 'DEPS'),
347 self.calculate(old_include_rules, old_specific_include_rules,
348 new_include_rules, new_specific_include_rules))
350 def testCalculateAddedDepsIgnoresPermutations(self):
351 old_include_rules = [
355 new_include_rules = [
359 self.assertEqual(set(),
360 self.calculate(old_include_rules, {}, new_include_rules,
364 class JSONParsingTest(unittest.TestCase):
365 def testSuccess(self):
366 input_api = MockInputApi()
367 filename = 'valid_json.json'
368 contents = ['// This is a comment.',
370 ' "key1": ["value1", "value2"],',
371 ' "key2": 3 // This is an inline comment.',
374 input_api.files = [MockFile(filename, contents)]
375 self.assertEqual(None,
376 PRESUBMIT._GetJSONParseError(input_api, filename))
378 def testFailure(self):
379 input_api = MockInputApi()
381 ('invalid_json_1.json',
383 'Expecting property name:'),
384 ('invalid_json_2.json',
386 '{ "hello": "world }'],
387 'Unterminated string starting at:'),
388 ('invalid_json_3.json',
389 ['{ "a": "b", "c": "d", }'],
390 'Expecting property name:'),
391 ('invalid_json_4.json',
392 ['{ "a": "b" "c": "d" }'],
393 'Expecting , delimiter:'),
396 input_api.files = [MockFile(filename, contents)
397 for (filename, contents, _) in test_data]
399 for (filename, _, expected_error) in test_data:
400 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
401 self.assertTrue(expected_error in str(actual_error),
402 "'%s' not found in '%s'" % (expected_error, actual_error))
404 def testNoEatComments(self):
405 input_api = MockInputApi()
406 file_with_comments = 'file_with_comments.json'
407 contents_with_comments = ['// This is a comment.',
409 ' "key1": ["value1", "value2"],',
410 ' "key2": 3 // This is an inline comment.',
413 file_without_comments = 'file_without_comments.json'
414 contents_without_comments = ['{',
415 ' "key1": ["value1", "value2"],',
419 input_api.files = [MockFile(file_with_comments, contents_with_comments),
420 MockFile(file_without_comments,
421 contents_without_comments)]
423 self.assertEqual('No JSON object could be decoded',
424 str(PRESUBMIT._GetJSONParseError(input_api,
426 eat_comments=False)))
427 self.assertEqual(None,
428 PRESUBMIT._GetJSONParseError(input_api,
429 file_without_comments,
433 class IDLParsingTest(unittest.TestCase):
434 def testSuccess(self):
435 input_api = MockInputApi()
436 filename = 'valid_idl_basics.idl'
437 contents = ['// Tests a valid IDL file.',
438 'namespace idl_basics {',
444 ' dictionary MyType1 {',
448 ' callback Callback1 = void();',
449 ' callback Callback2 = void(long x);',
450 ' callback Callback3 = void(MyType1 arg);',
451 ' callback Callback4 = void(EnumType type);',
453 ' interface Functions {',
454 ' static void function1();',
455 ' static void function2(long x);',
456 ' static void function3(MyType1 arg);',
457 ' static void function4(Callback1 cb);',
458 ' static void function5(Callback2 cb);',
459 ' static void function6(Callback3 cb);',
460 ' static void function7(Callback4 cb);',
463 ' interface Events {',
464 ' static void onFoo1();',
465 ' static void onFoo2(long x);',
466 ' static void onFoo2(MyType1 arg);',
467 ' static void onFoo3(EnumType type);',
471 input_api.files = [MockFile(filename, contents)]
472 self.assertEqual(None,
473 PRESUBMIT._GetIDLParseError(input_api, filename))
475 def testFailure(self):
476 input_api = MockInputApi()
478 ('invalid_idl_1.idl',
485 'Unexpected "{" after keyword "dictionary".\n'),
486 # TODO(yoz): Disabled because it causes the IDL parser to hang.
487 # See crbug.com/363830.
488 # ('invalid_idl_2.idl',
489 # (['namespace test {',
490 # ' dictionary MissingSemicolon {',
495 # 'Unexpected symbol DOMString after symbol a.'),
496 ('invalid_idl_3.idl',
499 ' enum MissingComma {',
504 'Unexpected symbol name2 after symbol name1.'),
505 ('invalid_idl_4.idl',
508 ' enum TrailingComma {',
513 'Trailing comma in block.'),
514 ('invalid_idl_5.idl',
517 ' callback Callback1 = void(;',
519 'Unexpected ";" after "(".'),
520 ('invalid_idl_6.idl',
523 ' callback Callback1 = void(long );',
525 'Unexpected ")" after symbol long.'),
526 ('invalid_idl_7.idl',
529 ' interace Events {',
530 ' static void onFoo1();',
533 'Unexpected symbol Events after symbol interace.'),
534 ('invalid_idl_8.idl',
537 ' interface NotEvent {',
538 ' static void onFoo1();',
541 'Did not process Interface Interface(NotEvent)'),
542 ('invalid_idl_9.idl',
546 ' static void function1();',
549 'Interface missing name.'),
552 input_api.files = [MockFile(filename, contents)
553 for (filename, contents, _) in test_data]
555 for (filename, _, expected_error) in test_data:
556 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
557 self.assertTrue(expected_error in str(actual_error),
558 "'%s' not found in '%s'" % (expected_error, actual_error))
561 class TryServerMasterTest(unittest.TestCase):
562 def testTryServerMasters(self):
564 'master.tryserver.chromium.android': [
565 'android_archive_rel_ng',
566 'android_arm64_dbg_recipe',
568 'android_chromium_variable',
569 'android_chromium_variable_archive',
570 'android_chromium_variable_arm64',
571 'android_chromium_variable_cast_shell',
572 'android_chromium_variable_clang',
573 'android_chromium_variable_gn',
574 'android_chromium_variable_nexus4',
575 'android_clang_dbg_recipe',
576 'android_compile_dbg',
577 'android_compile_x64_dbg',
578 'android_compile_x86_dbg',
580 'android_cronet_tester'
581 'android_swarming_rel',
582 'cast_shell_android',
583 'linux_android_dbg_ng',
584 'linux_android_rel_ng',
586 'master.tryserver.chromium.mac': [
589 'ios_rel_device_ninja',
592 'mac_chromium_compile_dbg',
593 'mac_chromium_compile_rel',
597 'mac_nacl_sdk_build',
602 'master.tryserver.chromium.linux': [
603 'chromium_presubmit',
604 'linux_arm_cross_compile',
606 'linux_chromeos_asan',
607 'linux_chromeos_browser_asan',
608 'linux_chromeos_valgrind',
609 'linux_chromium_chromeos_dbg',
610 'linux_chromium_chromeos_rel',
611 'linux_chromium_compile_dbg',
612 'linux_chromium_compile_rel',
613 'linux_chromium_dbg',
614 'linux_chromium_gn_dbg',
615 'linux_chromium_gn_rel',
616 'linux_chromium_rel',
617 'linux_chromium_trusty32_dbg',
618 'linux_chromium_trusty32_rel',
619 'linux_chromium_trusty_dbg',
620 'linux_chromium_trusty_rel',
626 'linux_layout_rel_32',
628 'linux_nacl_sdk_bionic',
629 'linux_nacl_sdk_bionic_build',
630 'linux_nacl_sdk_build',
632 'linux_rel_naclmore',
633 'linux_rel_precise32',
635 'tools_build_presubmit',
637 'master.tryserver.chromium.win': [
641 'win_chromium_compile_dbg',
642 'win_chromium_compile_rel',
646 'win_chromium_x64_dbg',
647 'win_chromium_x64_rel',
649 'win_nacl_sdk_build',
653 for master, bots in bots.iteritems():
655 self.assertEqual(master, PRESUBMIT.GetTryServerMasterForBot(bot),
656 'bot=%s: expected %s, computed %s' % (
657 bot, master, PRESUBMIT.GetTryServerMasterForBot(bot)))
660 class UserMetricsActionTest(unittest.TestCase):
661 def testUserMetricsActionInActions(self):
662 input_api = MockInputApi()
663 file_with_user_action = 'file_with_user_action.cc'
664 contents_with_user_action = [
665 'base::UserMetricsAction("AboutChrome")'
668 input_api.files = [MockFile(file_with_user_action,
669 contents_with_user_action)]
672 [], PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi()))
675 def testUserMetricsActionNotAddedToActions(self):
676 input_api = MockInputApi()
677 file_with_user_action = 'file_with_user_action.cc'
678 contents_with_user_action = [
679 'base::UserMetricsAction("NotInActionsXml")'
682 input_api.files = [MockFile(file_with_user_action,
683 contents_with_user_action)]
685 output = PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi())
687 ('File %s line %d: %s is missing in '
688 'tools/metrics/actions/actions.xml. Please run '
689 'tools/metrics/actions/extract_actions.py to update.'
690 % (file_with_user_action, 1, 'NotInActionsXml')),
694 class PydepsNeedsUpdatingTest(unittest.TestCase):
696 class MockSubprocess(object):
697 CalledProcessError = subprocess.CalledProcessError
700 mock_all_pydeps = ['A.pydeps', 'B.pydeps']
701 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
702 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
703 self.mock_input_api = MockInputApi()
704 self.mock_output_api = MockOutputApi()
705 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
706 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
707 self.checker._file_cache = {
708 'A.pydeps': '# Generated by:\n# CMD A\nA.py\nC.py\n',
709 'B.pydeps': '# Generated by:\n# CMD B\nB.py\nC.py\n',
713 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
716 return PRESUBMIT._CheckPydepsNeedsUpdating(self.mock_input_api,
717 self.mock_output_api,
718 checker_for_tests=self.checker)
720 def testAddedPydep(self):
721 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
722 if self.mock_input_api.platform != 'linux2':
725 self.mock_input_api.files = [
726 MockAffectedFile('new.pydeps', [], action='A'),
729 self.mock_input_api.CreateMockFileInPath(
730 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
731 include_deletes=True)])
732 results = self._RunCheck()
733 self.assertEqual(1, len(results))
734 self.assertTrue('PYDEPS_FILES' in str(results[0]))
736 def testPydepNotInSrc(self):
737 self.mock_input_api.files = [
738 MockAffectedFile('new.pydeps', [], action='A'),
740 self.mock_input_api.CreateMockFileInPath([])
741 results = self._RunCheck()
742 self.assertEqual(0, len(results))
744 def testRemovedPydep(self):
745 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
746 if self.mock_input_api.platform != 'linux2':
749 self.mock_input_api.files = [
750 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
752 self.mock_input_api.CreateMockFileInPath(
753 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
754 include_deletes=True)])
755 results = self._RunCheck()
756 self.assertEqual(1, len(results))
757 self.assertTrue('PYDEPS_FILES' in str(results[0]))
759 def testRandomPyIgnored(self):
760 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
761 if self.mock_input_api.platform != 'linux2':
764 self.mock_input_api.files = [
765 MockAffectedFile('random.py', []),
768 results = self._RunCheck()
769 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
771 def testRelevantPyNoChange(self):
772 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
773 if self.mock_input_api.platform != 'linux2':
776 self.mock_input_api.files = [
777 MockAffectedFile('A.py', []),
780 def mock_check_output(cmd, shell=False, env=None):
781 self.assertEqual('CMD A --output ""', cmd)
782 return self.checker._file_cache['A.pydeps']
784 self.mock_input_api.subprocess.check_output = mock_check_output
786 results = self._RunCheck()
787 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
789 def testRelevantPyOneChange(self):
790 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
791 if self.mock_input_api.platform != 'linux2':
794 self.mock_input_api.files = [
795 MockAffectedFile('A.py', []),
798 def mock_check_output(cmd, shell=False, env=None):
799 self.assertEqual('CMD A --output ""', cmd)
800 return 'changed data'
802 self.mock_input_api.subprocess.check_output = mock_check_output
804 results = self._RunCheck()
805 self.assertEqual(1, len(results))
806 self.assertTrue('File is stale' in str(results[0]))
808 def testRelevantPyTwoChanges(self):
809 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
810 if self.mock_input_api.platform != 'linux2':
813 self.mock_input_api.files = [
814 MockAffectedFile('C.py', []),
817 def mock_check_output(cmd, shell=False, env=None):
818 return 'changed data'
820 self.mock_input_api.subprocess.check_output = mock_check_output
822 results = self._RunCheck()
823 self.assertEqual(2, len(results))
824 self.assertTrue('File is stale' in str(results[0]))
825 self.assertTrue('File is stale' in str(results[1]))
827 class IncludeGuardTest(unittest.TestCase):
828 def testIncludeGuardChecks(self):
829 mock_input_api = MockInputApi()
830 mock_output_api = MockOutputApi()
831 mock_input_api.files = [
832 MockAffectedFile('content/browser/thing/foo.h', [
834 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
835 '#define CONTENT_BROWSER_THING_FOO_H_',
836 'struct McBoatFace;',
837 '#endif // CONTENT_BROWSER_THING_FOO_H_',
839 MockAffectedFile('content/browser/thing/bar.h', [
840 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
841 '#define CONTENT_BROWSER_THING_BAR_H_',
842 'namespace content {',
843 '#endif // CONTENT_BROWSER_THING_BAR_H_',
844 '} // namespace content',
846 MockAffectedFile('content/browser/test1.h', [
847 'namespace content {',
848 '} // namespace content',
850 MockAffectedFile('content\\browser\\win.h', [
851 '#ifndef CONTENT_BROWSER_WIN_H_',
852 '#define CONTENT_BROWSER_WIN_H_',
853 'struct McBoatFace;',
854 '#endif // CONTENT_BROWSER_WIN_H_',
856 MockAffectedFile('content/browser/test2.h', [
858 '#ifndef CONTENT_BROWSER_TEST2_H_',
859 'struct McBoatFace;',
860 '#endif // CONTENT_BROWSER_TEST2_H_',
862 MockAffectedFile('content/browser/internal.h', [
864 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
865 '#define CONTENT_BROWSER_INTERNAL_H_',
867 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
868 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
869 'namespace internal {',
870 '} // namespace internal',
871 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
872 'namespace content {',
873 '} // namespace content',
874 '#endif // CONTENT_BROWSER_THING_BAR_H_',
876 MockAffectedFile('content/browser/thing/foo.cc', [
877 '// This is a non-header.',
879 MockAffectedFile('content/browser/disabled.h', [
880 '// no-include-guard-because-multiply-included',
881 'struct McBoatFace;',
883 # New files don't allow misspelled include guards.
884 MockAffectedFile('content/browser/spleling.h', [
885 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
886 '#define CONTENT_BROWSER_SPLLEING_H_',
887 'struct McBoatFace;',
888 '#endif // CONTENT_BROWSER_SPLLEING_H_',
890 # Old files allow misspelled include guards (for now).
891 MockAffectedFile('chrome/old.h', [
893 '#ifndef CHROME_ODL_H_',
894 '#define CHROME_ODL_H_',
895 '#endif // CHROME_ODL_H_',
898 '#ifndef CHROME_ODL_H_',
899 '#define CHROME_ODL_H_',
900 '#endif // CHROME_ODL_H_',
902 # Using a Blink style include guard outside Blink is wrong.
903 MockAffectedFile('content/NotInBlink.h', [
904 '#ifndef NotInBlink_h',
905 '#define NotInBlink_h',
906 'struct McBoatFace;',
907 '#endif // NotInBlink_h',
909 # Using a Blink style include guard in Blink is ok for now.
910 MockAffectedFile('third_party/WebKit/InBlink.h', [
913 'struct McBoatFace;',
914 '#endif // InBlink_h',
916 # Using a bad include guard in Blink is not ok.
917 MockAffectedFile('third_party/WebKit/AlsoInBlink.h', [
918 '#ifndef WrongInBlink_h',
919 '#define WrongInBlink_h',
920 'struct McBoatFace;',
921 '#endif // WrongInBlink_h',
923 # Using a bad include guard in Blink is accepted if it's an old file.
924 MockAffectedFile('third_party/WebKit/StillInBlink.h', [
926 '#ifndef AcceptedInBlink_h',
927 '#define AcceptedInBlink_h',
928 'struct McBoatFace;',
929 '#endif // AcceptedInBlink_h',
932 '#ifndef AcceptedInBlink_h',
933 '#define AcceptedInBlink_h',
934 'struct McBoatFace;',
935 '#endif // AcceptedInBlink_h',
938 msgs = PRESUBMIT._CheckForIncludeGuards(
939 mock_input_api, mock_output_api)
940 expected_fail_count = 6
941 self.assertEqual(expected_fail_count, len(msgs),
942 'Expected %d items, found %d: %s'
943 % (expected_fail_count, len(msgs), msgs))
944 self.assertEqual(msgs[0].items, [ 'content/browser/thing/bar.h' ])
945 self.assertEqual(msgs[0].message,
946 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
947 'not covering the whole file')
949 self.assertEqual(msgs[1].items, [ 'content/browser/test1.h' ])
950 self.assertEqual(msgs[1].message,
951 'Missing include guard CONTENT_BROWSER_TEST1_H_')
953 self.assertEqual(msgs[2].items, [ 'content/browser/test2.h:3' ])
954 self.assertEqual(msgs[2].message,
955 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
958 self.assertEqual(msgs[3].items, [ 'content/browser/spleling.h:1' ])
959 self.assertEqual(msgs[3].message,
960 'Header using the wrong include guard name '
961 'CONTENT_BROWSER_SPLLEING_H_')
963 self.assertEqual(msgs[4].items, [ 'content/NotInBlink.h:1' ])
964 self.assertEqual(msgs[4].message,
965 'Header using the wrong include guard name '
968 self.assertEqual(msgs[5].items, [ 'third_party/WebKit/AlsoInBlink.h:1' ])
969 self.assertEqual(msgs[5].message,
970 'Header using the wrong include guard name '
973 class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
974 def testCheckAndroidTestAnnotationUsage(self):
975 mock_input_api = MockInputApi()
976 mock_output_api = MockOutputApi()
978 mock_input_api.files = [
979 MockAffectedFile('LalaLand.java', [
982 MockAffectedFile('CorrectUsage.java', [
983 'import android.support.test.filters.LargeTest;',
984 'import android.support.test.filters.MediumTest;',
985 'import android.support.test.filters.SmallTest;',
987 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
988 'import android.test.suitebuilder.annotation.LargeTest;',
990 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
991 'import android.test.suitebuilder.annotation.MediumTest;',
993 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
994 'import android.test.suitebuilder.annotation.SmallTest;',
996 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
997 'import android.test.suitebuilder.annotation.Smoke;',
1000 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
1001 mock_input_api, mock_output_api)
1002 self.assertEqual(1, len(msgs),
1003 'Expected %d items, found %d: %s'
1004 % (1, len(msgs), msgs))
1005 self.assertEqual(4, len(msgs[0].items),
1006 'Expected %d items, found %d: %s'
1007 % (4, len(msgs[0].items), msgs[0].items))
1008 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
1009 'UsedDeprecatedLargeTestAnnotation not found in errors')
1010 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
1012 'UsedDeprecatedMediumTestAnnotation not found in errors')
1013 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
1014 'UsedDeprecatedSmallTestAnnotation not found in errors')
1015 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
1016 'UsedDeprecatedSmokeAnnotation not found in errors')
1018 class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
1019 def testCheckAndroidTestAnnotationUsage(self):
1020 mock_input_api = MockInputApi()
1021 mock_output_api = MockOutputApi()
1023 mock_input_api.files = [
1024 MockAffectedFile('LalaLand.java', [
1027 MockAffectedFile('CorrectUsage.java', [
1028 'import org.junit.ABC',
1029 'import org.junit.XYZ;',
1031 MockAffectedFile('UsedDeprecatedJUnit.java', [
1032 'import junit.framework.*;',
1034 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
1035 'import junit.framework.Assert;',
1038 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
1039 mock_input_api, mock_output_api)
1040 self.assertEqual(1, len(msgs),
1041 'Expected %d items, found %d: %s'
1042 % (1, len(msgs), msgs))
1043 self.assertEqual(2, len(msgs[0].items),
1044 'Expected %d items, found %d: %s'
1045 % (2, len(msgs[0].items), msgs[0].items))
1046 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
1047 'UsedDeprecatedJUnit.java not found in errors')
1048 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
1050 'UsedDeprecatedJUnitAssert not found in errors')
1052 class AndroidJUnitBaseClass(unittest.TestCase):
1053 def testCheckAndroidTestAnnotationUsage(self):
1054 mock_input_api = MockInputApi()
1055 mock_output_api = MockOutputApi()
1057 mock_input_api.files = [
1058 MockAffectedFile('LalaLand.java', [
1061 MockAffectedFile('CorrectTest.java', [
1062 '@RunWith(ABC.class);'
1063 'public class CorrectTest {',
1066 MockAffectedFile('HistoricallyIncorrectTest.java', [
1067 'public class Test extends BaseCaseA {',
1070 'public class Test extends BaseCaseB {',
1073 MockAffectedFile('CorrectTestWithInterface.java', [
1074 '@RunWith(ABC.class);'
1075 'public class CorrectTest implement Interface {',
1078 MockAffectedFile('IncorrectTest.java', [
1079 'public class IncorrectTest extends TestCase {',
1082 MockAffectedFile('IncorrectWithInterfaceTest.java', [
1083 'public class Test implements X extends BaseClass {',
1086 MockAffectedFile('IncorrectMultiLineTest.java', [
1087 'public class Test implements X, Y, Z',
1088 ' extends TestBase {',
1092 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1093 mock_input_api, mock_output_api)
1094 self.assertEqual(1, len(msgs),
1095 'Expected %d items, found %d: %s'
1096 % (1, len(msgs), msgs))
1097 self.assertEqual(3, len(msgs[0].items),
1098 'Expected %d items, found %d: %s'
1099 % (3, len(msgs[0].items), msgs[0].items))
1100 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1101 'IncorrectTest not found in errors')
1102 self.assertTrue('IncorrectWithInterfaceTest.java:1'
1104 'IncorrectWithInterfaceTest not found in errors')
1105 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1106 'IncorrectMultiLineTest not found in errors')
1108 class LogUsageTest(unittest.TestCase):
1110 def testCheckAndroidCrLogUsage(self):
1111 mock_input_api = MockInputApi()
1112 mock_output_api = MockOutputApi()
1114 mock_input_api.files = [
1115 MockAffectedFile('RandomStuff.java', [
1118 MockAffectedFile('HasAndroidLog.java', [
1119 'import android.util.Log;',
1120 'some random stuff',
1121 'Log.d("TAG", "foo");',
1123 MockAffectedFile('HasExplicitUtilLog.java', [
1124 'some random stuff',
1125 'android.util.Log.d("TAG", "foo");',
1127 MockAffectedFile('IsInBasePackage.java', [
1128 'package org.chromium.base;',
1129 'private static final String TAG = "cr_Foo";',
1130 'Log.d(TAG, "foo");',
1132 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1133 'package org.chromium.base;',
1134 'import android.util.Log;',
1135 'private static final String TAG = "cr_Foo";',
1136 'Log.d(TAG, "foo");',
1138 MockAffectedFile('HasBothLog.java', [
1139 'import org.chromium.base.Log;',
1140 'some random stuff',
1141 'private static final String TAG = "cr_Foo";',
1142 'Log.d(TAG, "foo");',
1143 'android.util.Log.d("TAG", "foo");',
1145 MockAffectedFile('HasCorrectTag.java', [
1146 'import org.chromium.base.Log;',
1147 'some random stuff',
1148 'private static final String TAG = "cr_Foo";',
1149 'Log.d(TAG, "foo");',
1151 MockAffectedFile('HasOldTag.java', [
1152 'import org.chromium.base.Log;',
1153 'some random stuff',
1154 'private static final String TAG = "cr.Foo";',
1155 'Log.d(TAG, "foo");',
1157 MockAffectedFile('HasDottedTag.java', [
1158 'import org.chromium.base.Log;',
1159 'some random stuff',
1160 'private static final String TAG = "cr_foo.bar";',
1161 'Log.d(TAG, "foo");',
1163 MockAffectedFile('HasNoTagDecl.java', [
1164 'import org.chromium.base.Log;',
1165 'some random stuff',
1166 'Log.d(TAG, "foo");',
1168 MockAffectedFile('HasIncorrectTagDecl.java', [
1169 'import org.chromium.base.Log;',
1170 'private static final String TAHG = "cr_Foo";',
1171 'some random stuff',
1172 'Log.d(TAG, "foo");',
1174 MockAffectedFile('HasInlineTag.java', [
1175 'import org.chromium.base.Log;',
1176 'some random stuff',
1177 'private static final String TAG = "cr_Foo";',
1178 'Log.d("TAG", "foo");',
1180 MockAffectedFile('HasUnprefixedTag.java', [
1181 'import org.chromium.base.Log;',
1182 'some random stuff',
1183 'private static final String TAG = "rubbish";',
1184 'Log.d(TAG, "foo");',
1186 MockAffectedFile('HasTooLongTag.java', [
1187 'import org.chromium.base.Log;',
1188 'some random stuff',
1189 'private static final String TAG = "21_charachers_long___";',
1190 'Log.d(TAG, "foo");',
1194 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1195 mock_input_api, mock_output_api)
1197 self.assertEqual(5, len(msgs),
1198 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
1200 # Declaration format
1201 nb = len(msgs[0].items)
1202 self.assertEqual(2, nb,
1203 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
1204 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1205 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
1208 nb = len(msgs[1].items)
1209 self.assertEqual(1, nb,
1210 'Expected %d items, found %d: %s' % (1, nb, msgs[1].items))
1211 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
1213 # Tag must be a variable named TAG
1214 nb = len(msgs[2].items)
1215 self.assertEqual(1, nb,
1216 'Expected %d items, found %d: %s' % (1, nb, msgs[2].items))
1217 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
1220 nb = len(msgs[3].items)
1221 self.assertEqual(2, nb,
1222 'Expected %d items, found %d: %s' % (2, nb, msgs[3].items))
1223 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
1224 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
1226 # Tag must not contain
1227 nb = len(msgs[4].items)
1228 self.assertEqual(2, nb,
1229 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1230 self.assertTrue('HasDottedTag.java' in msgs[4].items)
1231 self.assertTrue('HasOldTag.java' in msgs[4].items)
1233 class GoogleAnswerUrlFormatTest(unittest.TestCase):
1235 def testCatchAnswerUrlId(self):
1236 input_api = MockInputApi()
1238 MockFile('somewhere/file.cc',
1240 ' "https://support.google.com/chrome/answer/123456";']),
1241 MockFile('somewhere_else/file.cc',
1243 ' "https://support.google.com/chrome/a/answer/123456";']),
1246 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1247 input_api, MockOutputApi())
1248 self.assertEqual(1, len(warnings))
1249 self.assertEqual(2, len(warnings[0].items))
1251 def testAllowAnswerUrlParam(self):
1252 input_api = MockInputApi()
1254 MockFile('somewhere/file.cc',
1256 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1259 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1260 input_api, MockOutputApi())
1261 self.assertEqual(0, len(warnings))
1263 class HardcodedGoogleHostsTest(unittest.TestCase):
1265 def testWarnOnAssignedLiterals(self):
1266 input_api = MockInputApi()
1268 MockFile('content/file.cc',
1269 ['char* host = "https://www.google.com";']),
1270 MockFile('content/file.cc',
1271 ['char* host = "https://www.googleapis.com";']),
1272 MockFile('content/file.cc',
1273 ['char* host = "https://clients1.google.com";']),
1276 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1277 input_api, MockOutputApi())
1278 self.assertEqual(1, len(warnings))
1279 self.assertEqual(3, len(warnings[0].items))
1281 def testAllowInComment(self):
1282 input_api = MockInputApi()
1284 MockFile('content/file.cc',
1285 ['char* host = "https://www.aol.com"; // google.com'])
1288 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1289 input_api, MockOutputApi())
1290 self.assertEqual(0, len(warnings))
1293 class ForwardDeclarationTest(unittest.TestCase):
1294 def testCheckHeadersOnlyOutsideThirdParty(self):
1295 mock_input_api = MockInputApi()
1296 mock_input_api.files = [
1297 MockAffectedFile('somewhere/file.cc', [
1300 MockAffectedFile('third_party/header.h', [
1304 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1306 self.assertEqual(0, len(warnings))
1308 def testNoNestedDeclaration(self):
1309 mock_input_api = MockInputApi()
1310 mock_input_api.files = [
1311 MockAffectedFile('somewhere/header.h', [
1312 'class SomeClass {',
1314 ' class NotAMatch;',
1318 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1320 self.assertEqual(0, len(warnings))
1322 def testSubStrings(self):
1323 mock_input_api = MockInputApi()
1324 mock_input_api.files = [
1325 MockAffectedFile('somewhere/header.h', [
1326 'class NotUsefulClass;',
1327 'struct SomeStruct;',
1329 'SomeStructPtr *p2;'
1332 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1334 self.assertEqual(2, len(warnings))
1336 def testUselessForwardDeclaration(self):
1337 mock_input_api = MockInputApi()
1338 mock_input_api.files = [
1339 MockAffectedFile('somewhere/header.h', [
1340 'class DummyClass;',
1341 'struct DummyStruct;',
1342 'class UsefulClass;',
1343 'std::unique_ptr<UsefulClass> p;'
1346 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1348 self.assertEqual(2, len(warnings))
1350 def testBlinkHeaders(self):
1351 mock_input_api = MockInputApi()
1352 mock_input_api.files = [
1353 MockAffectedFile('third_party/WebKit/header.h', [
1354 'class DummyClass;',
1355 'struct DummyStruct;',
1357 MockAffectedFile('third_party\\WebKit\\header.h', [
1358 'class DummyClass;',
1359 'struct DummyStruct;',
1362 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1364 self.assertEqual(4, len(warnings))
1367 class RiskyJsTest(unittest.TestCase):
1368 def testArrowWarnInIos9Code(self):
1369 mock_input_api = MockInputApi()
1370 mock_output_api = MockOutputApi()
1372 mock_input_api.files = [
1373 MockAffectedFile('components/blah.js', ["shouldn't use => here"]),
1375 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1376 mock_input_api, mock_output_api)
1377 self.assertEqual(1, len(warnings))
1379 mock_input_api.files = [
1380 MockAffectedFile('ios/blee.js', ['might => break folks']),
1382 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1383 mock_input_api, mock_output_api)
1384 self.assertEqual(1, len(warnings))
1386 mock_input_api.files = [
1387 MockAffectedFile('ui/webui/resources/blarg.js', ['on => iOS9']),
1389 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1390 mock_input_api, mock_output_api)
1391 self.assertEqual(1, len(warnings))
1393 def testArrowsAllowedInChromeCode(self):
1394 mock_input_api = MockInputApi()
1395 mock_input_api.files = [
1396 MockAffectedFile('chrome/browser/resources/blah.js', 'arrow => OK here'),
1398 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1399 mock_input_api, MockOutputApi())
1400 self.assertEqual(0, len(warnings))
1402 def testConstLetWarningIos9Code(self):
1403 mock_input_api = MockInputApi()
1404 mock_output_api = MockOutputApi()
1406 mock_input_api.files = [
1407 MockAffectedFile('components/blah.js', [" const foo = 'bar';"]),
1408 MockAffectedFile('ui/webui/resources/blah.js', [" let foo = 3;"]),
1410 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1411 mock_input_api, mock_output_api)
1412 self.assertEqual(2, len(warnings))
1414 class RelativeIncludesTest(unittest.TestCase):
1415 def testThirdPartyNotWebKitIgnored(self):
1416 mock_input_api = MockInputApi()
1417 mock_input_api.files = [
1418 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1419 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1422 mock_output_api = MockOutputApi()
1424 errors = PRESUBMIT._CheckForRelativeIncludes(
1425 mock_input_api, mock_output_api)
1426 self.assertEqual(0, len(errors))
1428 def testNonCppFileIgnored(self):
1429 mock_input_api = MockInputApi()
1430 mock_input_api.files = [
1431 MockAffectedFile('test.py', '#include "../header.h"'),
1434 mock_output_api = MockOutputApi()
1436 errors = PRESUBMIT._CheckForRelativeIncludes(
1437 mock_input_api, mock_output_api)
1438 self.assertEqual(0, len(errors))
1440 def testInnocuousChangesAllowed(self):
1441 mock_input_api = MockInputApi()
1442 mock_input_api.files = [
1443 MockAffectedFile('test.cpp', '#include "header.h"'),
1444 MockAffectedFile('test2.cpp', '../'),
1447 mock_output_api = MockOutputApi()
1449 errors = PRESUBMIT._CheckForRelativeIncludes(
1450 mock_input_api, mock_output_api)
1451 self.assertEqual(0, len(errors))
1453 def testRelativeIncludeNonWebKitProducesError(self):
1454 mock_input_api = MockInputApi()
1455 mock_input_api.files = [
1456 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1459 mock_output_api = MockOutputApi()
1461 errors = PRESUBMIT._CheckForRelativeIncludes(
1462 mock_input_api, mock_output_api)
1463 self.assertEqual(1, len(errors))
1465 def testRelativeIncludeWebKitProducesError(self):
1466 mock_input_api = MockInputApi()
1467 mock_input_api.files = [
1468 MockAffectedFile('third_party/WebKit/test.cpp',
1469 ['#include "../header.h']),
1472 mock_output_api = MockOutputApi()
1474 errors = PRESUBMIT._CheckForRelativeIncludes(
1475 mock_input_api, mock_output_api)
1476 self.assertEqual(1, len(errors))
1479 class MojoManifestOwnerTest(unittest.TestCase):
1480 def testMojoManifestChangeNeedsSecurityOwner(self):
1481 mock_input_api = MockInputApi()
1482 mock_input_api.files = [
1483 MockAffectedFile('services/goat/manifest.json',
1486 ' "name": "teleporter",',
1487 ' "display_name": "Goat Teleporter",'
1488 ' "interface_provider_specs": {',
1493 mock_output_api = MockOutputApi()
1494 errors = PRESUBMIT._CheckIpcOwners(
1495 mock_input_api, mock_output_api)
1496 self.assertEqual(1, len(errors))
1498 'Found OWNERS files that need to be updated for IPC security review ' +
1499 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
1501 # No warning if already covered by an OWNERS rule.
1503 def testNonManifestChangesDoNotRequireSecurityOwner(self):
1504 mock_input_api = MockInputApi()
1505 mock_input_api.files = [
1506 MockAffectedFile('services/goat/species.json',
1514 mock_output_api = MockOutputApi()
1515 errors = PRESUBMIT._CheckIpcOwners(
1516 mock_input_api, mock_output_api)
1517 self.assertEqual([], errors)
1520 class CrbugUrlFormatTest(unittest.TestCase):
1522 def testCheckCrbugLinksHaveHttps(self):
1523 input_api = MockInputApi()
1525 MockFile('somewhere/file.cc',
1526 ['// TODO(developer): crbug.com should be linkified',
1527 '// TODO(developer): (crbug.com) should be linkified',
1528 '// TODO(developer): crbug/123 should be well formed',
1529 '// TODO(developer): http://crbug.com it\'s OK',
1530 '// TODO(developer): https://crbug.com is just great',
1531 '// TODO(crbug.com/123456): this pattern it\'s also OK']),
1534 warnings = PRESUBMIT._CheckCrbugLinksHaveHttps(input_api, MockOutputApi())
1535 self.assertEqual(1, len(warnings))
1536 self.assertEqual(3, warnings[0].message.count('\n'));
1539 class BannedFunctionCheckTest(unittest.TestCase):
1541 def testBannedIosObcjFunctions(self):
1542 input_api = MockInputApi()
1544 MockFile('some/ios/file.mm',
1545 ['TEST(SomeClassTest, SomeInteraction) {',
1547 MockFile('some/mac/file.mm',
1548 ['TEST(SomeClassTest, SomeInteraction) {',
1550 MockFile('another/ios_file.mm',
1551 ['class SomeTest : public testing::Test {};']),
1554 errors = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi())
1555 self.assertEqual(1, len(errors))
1556 self.assertTrue('some/ios/file.mm' in errors[0].message)
1557 self.assertTrue('another/ios_file.mm' in errors[0].message)
1558 self.assertTrue('some/mac/file.mm' not in errors[0].message)
1561 class NoProductionCodeUsingTestOnlyFunctions(unittest.TestCase):
1562 def testTruePositives(self):
1563 mock_input_api = MockInputApi()
1564 mock_input_api.files = [
1565 MockFile('some/path/foo.cc', ['foo_for_testing();']),
1566 MockFile('some/path/foo.mm', ['FooForTesting();']),
1567 MockFile('some/path/foo.cxx', ['FooForTests();']),
1568 MockFile('some/path/foo.cpp', ['foo_for_test();']),
1571 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
1572 mock_input_api, MockOutputApi())
1573 self.assertEqual(1, len(results))
1574 self.assertEqual(4, len(results[0].items))
1575 self.assertTrue('foo.cc' in results[0].items[0])
1576 self.assertTrue('foo.mm' in results[0].items[1])
1577 self.assertTrue('foo.cxx' in results[0].items[2])
1578 self.assertTrue('foo.cpp' in results[0].items[3])
1580 def testFalsePositives(self):
1581 mock_input_api = MockInputApi()
1582 mock_input_api.files = [
1583 MockFile('some/path/foo.h', ['foo_for_testing();']),
1584 MockFile('some/path/foo.mm', ['FooForTesting() {']),
1585 MockFile('some/path/foo.cc', ['::FooForTests();']),
1586 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
1589 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
1590 mock_input_api, MockOutputApi())
1591 self.assertEqual(0, len(results))
1594 class NoProductionJavaCodeUsingTestOnlyFunctions(unittest.TestCase):
1595 def testTruePositives(self):
1596 mock_input_api = MockInputApi()
1597 mock_input_api.files = [
1598 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
1599 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
1600 MockFile('dir/java/src/baz.java', ['FooForTest(','y',');']),
1601 MockFile('dir/java/src/mult.java', [
1602 'int x = SomethingLongHere()',
1603 ' * SomethingLongHereForTesting();'
1607 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctionsJava(
1608 mock_input_api, MockOutputApi())
1609 self.assertEqual(1, len(results))
1610 self.assertEqual(4, len(results[0].items))
1611 self.assertTrue('foo.java' in results[0].items[0])
1612 self.assertTrue('bar.java' in results[0].items[1])
1613 self.assertTrue('baz.java' in results[0].items[2])
1614 self.assertTrue('mult.java' in results[0].items[3])
1616 def testFalsePositives(self):
1617 mock_input_api = MockInputApi()
1618 mock_input_api.files = [
1619 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
1620 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
1621 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
1622 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
1623 MockFile('dir/javatests/src/baz.java', ['FooForTest(','y',');']),
1624 MockFile('dir/junit/src/baz.java', ['FooForTest(','y',');']),
1625 MockFile('dir/junit/src/javadoc.java', [
1626 '/** Use FooForTest(); to obtain foo in tests.'
1629 MockFile('dir/junit/src/javadoc2.java', [
1631 ' * Use FooForTest(); to obtain foo in tests.'
1636 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctionsJava(
1637 mock_input_api, MockOutputApi())
1638 self.assertEqual(0, len(results))
1641 class CheckUniquePtr(unittest.TestCase):
1642 def testTruePositivesNullptr(self):
1643 mock_input_api = MockInputApi()
1644 mock_input_api.files = [
1645 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
1646 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
1649 results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi())
1650 self.assertEqual(1, len(results))
1651 self.assertTrue('nullptr' in results[0].message)
1652 self.assertEqual(2, len(results[0].items))
1653 self.assertTrue('baz.cc' in results[0].items[0])
1654 self.assertTrue('baz-p.cc' in results[0].items[1])
1656 def testTruePositivesConstructor(self):
1657 mock_input_api = MockInputApi()
1658 mock_input_api.files = [
1659 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
1660 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
1661 MockFile('dir/mult.cc', [
1663 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
1665 MockFile('dir/mult2.cc', [
1666 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
1667 ' std::unique_ptr<T>(foo);'
1669 MockFile('dir/mult3.cc', [
1670 'bar = std::unique_ptr<T>(',
1671 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
1675 results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi())
1676 self.assertEqual(1, len(results))
1677 self.assertTrue('std::make_unique' in results[0].message)
1678 self.assertEqual(5, len(results[0].items))
1679 self.assertTrue('foo.cc' in results[0].items[0])
1680 self.assertTrue('bar.mm' in results[0].items[1])
1681 self.assertTrue('mult.cc' in results[0].items[2])
1682 self.assertTrue('mult2.cc' in results[0].items[3])
1683 self.assertTrue('mult3.cc' in results[0].items[4])
1685 def testFalsePositives(self):
1686 mock_input_api = MockInputApi()
1687 mock_input_api.files = [
1688 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
1689 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
1690 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
1691 MockFile('dir/baz.cc', [
1692 'std::unique_ptr<T> result = std::make_unique<T>();'
1694 MockFile('dir/baz2.cc', [
1695 'std::unique_ptr<T> result = std::make_unique<T>('
1697 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
1698 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
1701 results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi())
1702 self.assertEqual(0, len(results))
1705 if __name__ == '__main__':