blob: bb22f8c51af282470dfceb62ad3cb21c9d21a85c [file] [log] [blame]
[email protected]2299dcf2012-11-15 19:56:241#!/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
Daniel Cheng4dcdb6b2017-04-13 08:30:176import os.path
[email protected]2299dcf2012-11-15 19:56:247import re
[email protected]99171a92014-06-03 08:44:478import subprocess
[email protected]2299dcf2012-11-15 19:56:249import unittest
10
11import PRESUBMIT
glidere61efad2015-02-18 17:39:4312from PRESUBMIT_test_mocks import MockChange, MockFile, MockAffectedFile
gayane3dff8c22014-12-04 17:09:5113from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi
[email protected]2299dcf2012-11-15 19:56:2414
[email protected]99171a92014-06-03 08:44:4715_TEST_DATA_DIR = 'base/test/data/presubmit'
16
[email protected]b00342e7f2013-03-26 16:21:5417class VersionControlConflictsTest(unittest.TestCase):
[email protected]70ca77752012-11-20 03:45:0318 def testTypicalConflict(self):
19 lines = ['<<<<<<< HEAD',
20 ' base::ScopedTempDir temp_dir_;',
21 '=======',
22 ' ScopedTempDir temp_dir_;',
23 '>>>>>>> master']
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])
30
dbeam95c35a2f2015-06-02 01:40:2331 def testIgnoresReadmes(self):
32 lines = ['A First Level Header',
33 '====================',
34 '',
35 'A Second Level Header',
36 '---------------------']
37 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
38 MockInputApi(), MockFile('some/polymer/README.md', lines))
39 self.assertEqual(0, len(errors))
40
mcasasb7440c282015-02-04 14:52:1941class UmaHistogramChangeMatchedOrNotTest(unittest.TestCase):
42 def testTypicalCorrectlyMatchedChange(self):
43 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
44 diff_xml = ['<histogram name="Bla.Foo.Dummy"> </histogram>']
45 mock_input_api = MockInputApi()
46 mock_input_api.files = [
47 MockFile('some/path/foo.cc', diff_cc),
48 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
49 ]
50 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
51 MockOutputApi())
52 self.assertEqual(0, len(warnings))
53
54 def testTypicalNotMatchedChange(self):
55 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
56 mock_input_api = MockInputApi()
57 mock_input_api.files = [MockFile('some/path/foo.cc', diff_cc)]
58 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
59 MockOutputApi())
60 self.assertEqual(1, len(warnings))
61 self.assertEqual('warning', warnings[0].type)
62
63 def testTypicalNotMatchedChangeViaSuffixes(self):
64 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
65 diff_xml = ['<histogram_suffixes name="SuperHistogram">',
66 ' <suffix name="Dummy"/>',
67 ' <affected-histogram name="Snafu.Dummy"/>',
68 '</histogram>']
69 mock_input_api = MockInputApi()
70 mock_input_api.files = [
71 MockFile('some/path/foo.cc', diff_cc),
72 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
73 ]
74 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
75 MockOutputApi())
76 self.assertEqual(1, len(warnings))
77 self.assertEqual('warning', warnings[0].type)
78
79 def testTypicalCorrectlyMatchedChangeViaSuffixes(self):
80 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
81 diff_xml = ['<histogram_suffixes name="SuperHistogram">',
82 ' <suffix name="Dummy"/>',
83 ' <affected-histogram name="Bla.Foo"/>',
84 '</histogram>']
85 mock_input_api = MockInputApi()
86 mock_input_api.files = [
87 MockFile('some/path/foo.cc', diff_cc),
88 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
89 ]
90 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
91 MockOutputApi())
92 self.assertEqual(0, len(warnings))
93
94 def testTypicalCorrectlyMatchedChangeViaSuffixesWithSeparator(self):
95 diff_cc = ['UMA_HISTOGRAM_BOOL("Snafu_Dummy", true)']
96 diff_xml = ['<histogram_suffixes name="SuperHistogram" separator="_">',
97 ' <suffix name="Dummy"/>',
98 ' <affected-histogram name="Snafu"/>',
99 '</histogram>']
100 mock_input_api = MockInputApi()
101 mock_input_api.files = [
102 MockFile('some/path/foo.cc', diff_cc),
103 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
104 ]
105 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
106 MockOutputApi())
107 self.assertEqual(0, len(warnings))
[email protected]70ca77752012-11-20 03:45:03108
[email protected]b8079ae4a2012-12-05 19:56:49109class BadExtensionsTest(unittest.TestCase):
110 def testBadRejFile(self):
111 mock_input_api = MockInputApi()
112 mock_input_api.files = [
113 MockFile('some/path/foo.cc', ''),
114 MockFile('some/path/foo.cc.rej', ''),
115 MockFile('some/path2/bar.h.rej', ''),
116 ]
117
118 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
119 self.assertEqual(1, len(results))
120 self.assertEqual(2, len(results[0].items))
121 self.assertTrue('foo.cc.rej' in results[0].items[0])
122 self.assertTrue('bar.h.rej' in results[0].items[1])
123
124 def testBadOrigFile(self):
125 mock_input_api = MockInputApi()
126 mock_input_api.files = [
127 MockFile('other/path/qux.h.orig', ''),
128 MockFile('other/path/qux.h', ''),
129 MockFile('other/path/qux.cc', ''),
130 ]
131
132 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
133 self.assertEqual(1, len(results))
134 self.assertEqual(1, len(results[0].items))
135 self.assertTrue('qux.h.orig' in results[0].items[0])
136
137 def testGoodFiles(self):
138 mock_input_api = MockInputApi()
139 mock_input_api.files = [
140 MockFile('other/path/qux.h', ''),
141 MockFile('other/path/qux.cc', ''),
142 ]
143 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
144 self.assertEqual(0, len(results))
145
146
glidere61efad2015-02-18 17:39:43147class CheckSingletonInHeadersTest(unittest.TestCase):
148 def testSingletonInArbitraryHeader(self):
149 diff_singleton_h = ['base::subtle::AtomicWord '
olli.raula36aa8be2015-09-10 11:14:22150 'base::Singleton<Type, Traits, DifferentiatingType>::']
151 diff_foo_h = ['// base::Singleton<Foo> in comment.',
152 'friend class base::Singleton<Foo>']
oysteinec430ad42015-10-22 20:55:24153 diff_foo2_h = [' //Foo* bar = base::Singleton<Foo>::get();']
olli.raula36aa8be2015-09-10 11:14:22154 diff_bad_h = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43155 mock_input_api = MockInputApi()
156 mock_input_api.files = [MockAffectedFile('base/memory/singleton.h',
157 diff_singleton_h),
158 MockAffectedFile('foo.h', diff_foo_h),
oysteinec430ad42015-10-22 20:55:24159 MockAffectedFile('foo2.h', diff_foo2_h),
glidere61efad2015-02-18 17:39:43160 MockAffectedFile('bad.h', diff_bad_h)]
161 warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api,
162 MockOutputApi())
163 self.assertEqual(1, len(warnings))
oysteinec430ad42015-10-22 20:55:24164 self.assertEqual(2, len(warnings[0].items))
glidere61efad2015-02-18 17:39:43165 self.assertEqual('error', warnings[0].type)
olli.raula36aa8be2015-09-10 11:14:22166 self.assertTrue('Found base::Singleton<T>' in warnings[0].message)
glidere61efad2015-02-18 17:39:43167
168 def testSingletonInCC(self):
olli.raula36aa8be2015-09-10 11:14:22169 diff_cc = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43170 mock_input_api = MockInputApi()
171 mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)]
172 warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api,
173 MockOutputApi())
174 self.assertEqual(0, len(warnings))
175
176
[email protected]b00342e7f2013-03-26 16:21:54177class InvalidOSMacroNamesTest(unittest.TestCase):
178 def testInvalidOSMacroNames(self):
179 lines = ['#if defined(OS_WINDOWS)',
180 ' #elif defined(OS_WINDOW)',
181 ' # if defined(OS_MACOSX) || defined(OS_CHROME)',
182 '# else // defined(OS_MAC)',
183 '#endif // defined(OS_MACOS)']
184 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
185 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
186 self.assertEqual(len(lines), len(errors))
187 self.assertTrue(':1 OS_WINDOWS' in errors[0])
188 self.assertTrue('(did you mean OS_WIN?)' in errors[0])
189
190 def testValidOSMacroNames(self):
191 lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS]
192 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
193 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
194 self.assertEqual(0, len(errors))
195
196
lliabraa35bab3932014-10-01 12:16:44197class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
198 def testInvalidIfDefinedMacroNames(self):
199 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
200 '#if !defined(TARGET_IPHONE_SIMULATOR)',
201 '#elif defined(TARGET_IPHONE_SIMULATOR)',
202 '#ifdef TARGET_IPHONE_SIMULATOR',
203 ' # ifdef TARGET_IPHONE_SIMULATOR',
204 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
205 '# else // defined(TARGET_IPHONE_SIMULATOR)',
206 '#endif // defined(TARGET_IPHONE_SIMULATOR)',]
207 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
208 MockInputApi(), MockFile('some/path/source.mm', lines))
209 self.assertEqual(len(lines), len(errors))
210
211 def testValidIfDefinedMacroNames(self):
212 lines = ['#if defined(FOO)',
213 '#ifdef BAR',]
214 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
215 MockInputApi(), MockFile('some/path/source.cc', lines))
216 self.assertEqual(0, len(errors))
217
218
[email protected]f32e2d1e2013-07-26 21:39:08219class CheckAddedDepsHaveTetsApprovalsTest(unittest.TestCase):
Daniel Cheng4dcdb6b2017-04-13 08:30:17220
221 def calculate(self, old_include_rules, old_specific_include_rules,
222 new_include_rules, new_specific_include_rules):
223 return PRESUBMIT._CalculateAddedDeps(
224 os.path, 'include_rules = %r\nspecific_include_rules = %r' % (
225 old_include_rules, old_specific_include_rules),
226 'include_rules = %r\nspecific_include_rules = %r' % (
227 new_include_rules, new_specific_include_rules))
228
229 def testCalculateAddedDeps(self):
230 old_include_rules = [
231 '+base',
232 '-chrome',
233 '+content',
234 '-grit',
235 '-grit/",',
236 '+jni/fooblat.h',
237 '!sandbox',
[email protected]f32e2d1e2013-07-26 21:39:08238 ]
Daniel Cheng4dcdb6b2017-04-13 08:30:17239 old_specific_include_rules = {
240 'compositor\.*': {
241 '+cc',
242 },
243 }
244
245 new_include_rules = [
246 '-ash',
247 '+base',
248 '+chrome',
249 '+components',
250 '+content',
251 '+grit',
252 '+grit/generated_resources.h",',
253 '+grit/",',
254 '+jni/fooblat.h',
255 '+policy',
manzagop85e629e2017-05-09 22:11:48256 '+' + os.path.join('third_party', 'WebKit'),
Daniel Cheng4dcdb6b2017-04-13 08:30:17257 ]
258 new_specific_include_rules = {
259 'compositor\.*': {
260 '+cc',
261 },
262 'widget\.*': {
263 '+gpu',
264 },
265 }
266
[email protected]f32e2d1e2013-07-26 21:39:08267 expected = set([
manzagop85e629e2017-05-09 22:11:48268 os.path.join('chrome', 'DEPS'),
269 os.path.join('gpu', 'DEPS'),
270 os.path.join('components', 'DEPS'),
271 os.path.join('policy', 'DEPS'),
272 os.path.join('third_party', 'WebKit', 'DEPS'),
[email protected]f32e2d1e2013-07-26 21:39:08273 ])
Daniel Cheng4dcdb6b2017-04-13 08:30:17274 self.assertEqual(
275 expected,
276 self.calculate(old_include_rules, old_specific_include_rules,
277 new_include_rules, new_specific_include_rules))
278
279 def testCalculateAddedDepsIgnoresPermutations(self):
280 old_include_rules = [
281 '+base',
282 '+chrome',
283 ]
284 new_include_rules = [
285 '+chrome',
286 '+base',
287 ]
288 self.assertEqual(set(),
289 self.calculate(old_include_rules, {}, new_include_rules,
290 {}))
[email protected]f32e2d1e2013-07-26 21:39:08291
292
[email protected]99171a92014-06-03 08:44:47293class JSONParsingTest(unittest.TestCase):
294 def testSuccess(self):
295 input_api = MockInputApi()
296 filename = 'valid_json.json'
297 contents = ['// This is a comment.',
298 '{',
299 ' "key1": ["value1", "value2"],',
300 ' "key2": 3 // This is an inline comment.',
301 '}'
302 ]
303 input_api.files = [MockFile(filename, contents)]
304 self.assertEqual(None,
305 PRESUBMIT._GetJSONParseError(input_api, filename))
306
307 def testFailure(self):
308 input_api = MockInputApi()
309 test_data = [
310 ('invalid_json_1.json',
311 ['{ x }'],
[email protected]a3343272014-06-17 11:41:53312 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47313 ('invalid_json_2.json',
314 ['// Hello world!',
315 '{ "hello": "world }'],
[email protected]a3343272014-06-17 11:41:53316 'Unterminated string starting at:'),
[email protected]99171a92014-06-03 08:44:47317 ('invalid_json_3.json',
318 ['{ "a": "b", "c": "d", }'],
[email protected]a3343272014-06-17 11:41:53319 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47320 ('invalid_json_4.json',
321 ['{ "a": "b" "c": "d" }'],
[email protected]a3343272014-06-17 11:41:53322 'Expecting , delimiter:'),
[email protected]99171a92014-06-03 08:44:47323 ]
324
325 input_api.files = [MockFile(filename, contents)
326 for (filename, contents, _) in test_data]
327
328 for (filename, _, expected_error) in test_data:
329 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
[email protected]a3343272014-06-17 11:41:53330 self.assertTrue(expected_error in str(actual_error),
331 "'%s' not found in '%s'" % (expected_error, actual_error))
[email protected]99171a92014-06-03 08:44:47332
333 def testNoEatComments(self):
334 input_api = MockInputApi()
335 file_with_comments = 'file_with_comments.json'
336 contents_with_comments = ['// This is a comment.',
337 '{',
338 ' "key1": ["value1", "value2"],',
339 ' "key2": 3 // This is an inline comment.',
340 '}'
341 ]
342 file_without_comments = 'file_without_comments.json'
343 contents_without_comments = ['{',
344 ' "key1": ["value1", "value2"],',
345 ' "key2": 3',
346 '}'
347 ]
348 input_api.files = [MockFile(file_with_comments, contents_with_comments),
349 MockFile(file_without_comments,
350 contents_without_comments)]
351
352 self.assertEqual('No JSON object could be decoded',
353 str(PRESUBMIT._GetJSONParseError(input_api,
354 file_with_comments,
355 eat_comments=False)))
356 self.assertEqual(None,
357 PRESUBMIT._GetJSONParseError(input_api,
358 file_without_comments,
359 eat_comments=False))
360
361
362class IDLParsingTest(unittest.TestCase):
363 def testSuccess(self):
364 input_api = MockInputApi()
365 filename = 'valid_idl_basics.idl'
366 contents = ['// Tests a valid IDL file.',
367 'namespace idl_basics {',
368 ' enum EnumType {',
369 ' name1,',
370 ' name2',
371 ' };',
372 '',
373 ' dictionary MyType1 {',
374 ' DOMString a;',
375 ' };',
376 '',
377 ' callback Callback1 = void();',
378 ' callback Callback2 = void(long x);',
379 ' callback Callback3 = void(MyType1 arg);',
380 ' callback Callback4 = void(EnumType type);',
381 '',
382 ' interface Functions {',
383 ' static void function1();',
384 ' static void function2(long x);',
385 ' static void function3(MyType1 arg);',
386 ' static void function4(Callback1 cb);',
387 ' static void function5(Callback2 cb);',
388 ' static void function6(Callback3 cb);',
389 ' static void function7(Callback4 cb);',
390 ' };',
391 '',
392 ' interface Events {',
393 ' static void onFoo1();',
394 ' static void onFoo2(long x);',
395 ' static void onFoo2(MyType1 arg);',
396 ' static void onFoo3(EnumType type);',
397 ' };',
398 '};'
399 ]
400 input_api.files = [MockFile(filename, contents)]
401 self.assertEqual(None,
402 PRESUBMIT._GetIDLParseError(input_api, filename))
403
404 def testFailure(self):
405 input_api = MockInputApi()
406 test_data = [
407 ('invalid_idl_1.idl',
408 ['//',
409 'namespace test {',
410 ' dictionary {',
411 ' DOMString s;',
412 ' };',
413 '};'],
414 'Unexpected "{" after keyword "dictionary".\n'),
415 # TODO(yoz): Disabled because it causes the IDL parser to hang.
416 # See crbug.com/363830.
417 # ('invalid_idl_2.idl',
418 # (['namespace test {',
419 # ' dictionary MissingSemicolon {',
420 # ' DOMString a',
421 # ' DOMString b;',
422 # ' };',
423 # '};'],
424 # 'Unexpected symbol DOMString after symbol a.'),
425 ('invalid_idl_3.idl',
426 ['//',
427 'namespace test {',
428 ' enum MissingComma {',
429 ' name1',
430 ' name2',
431 ' };',
432 '};'],
433 'Unexpected symbol name2 after symbol name1.'),
434 ('invalid_idl_4.idl',
435 ['//',
436 'namespace test {',
437 ' enum TrailingComma {',
438 ' name1,',
439 ' name2,',
440 ' };',
441 '};'],
442 'Trailing comma in block.'),
443 ('invalid_idl_5.idl',
444 ['//',
445 'namespace test {',
446 ' callback Callback1 = void(;',
447 '};'],
448 'Unexpected ";" after "(".'),
449 ('invalid_idl_6.idl',
450 ['//',
451 'namespace test {',
452 ' callback Callback1 = void(long );',
453 '};'],
454 'Unexpected ")" after symbol long.'),
455 ('invalid_idl_7.idl',
456 ['//',
457 'namespace test {',
458 ' interace Events {',
459 ' static void onFoo1();',
460 ' };',
461 '};'],
462 'Unexpected symbol Events after symbol interace.'),
463 ('invalid_idl_8.idl',
464 ['//',
465 'namespace test {',
466 ' interface NotEvent {',
467 ' static void onFoo1();',
468 ' };',
469 '};'],
470 'Did not process Interface Interface(NotEvent)'),
471 ('invalid_idl_9.idl',
472 ['//',
473 'namespace test {',
474 ' interface {',
475 ' static void function1();',
476 ' };',
477 '};'],
478 'Interface missing name.'),
479 ]
480
481 input_api.files = [MockFile(filename, contents)
482 for (filename, contents, _) in test_data]
483
484 for (filename, _, expected_error) in test_data:
485 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
486 self.assertTrue(expected_error in str(actual_error),
487 "'%s' not found in '%s'" % (expected_error, actual_error))
488
489
[email protected]0bb112362014-07-26 04:38:32490class TryServerMasterTest(unittest.TestCase):
491 def testTryServerMasters(self):
492 bots = {
tandriie5587792016-07-14 00:34:50493 'master.tryserver.chromium.android': [
jbudorick3ae7a772016-05-20 02:36:04494 'android_archive_rel_ng',
495 'android_arm64_dbg_recipe',
496 'android_blink_rel',
497 'android_chromium_variable',
498 'android_chromium_variable_archive',
499 'android_chromium_variable_arm64',
500 'android_chromium_variable_cast_shell',
501 'android_chromium_variable_clang',
502 'android_chromium_variable_gn',
503 'android_chromium_variable_nexus4',
504 'android_clang_dbg_recipe',
505 'android_compile_dbg',
506 'android_compile_mips_dbg',
jbudorick3ae7a772016-05-20 02:36:04507 'android_compile_x64_dbg',
508 'android_compile_x86_dbg',
509 'android_coverage',
510 'android_cronet_tester'
511 'android_swarming_rel',
512 'cast_shell_android',
513 'linux_android_dbg_ng',
514 'linux_android_rel_ng',
515 ],
tandriie5587792016-07-14 00:34:50516 'master.tryserver.chromium.mac': [
[email protected]0bb112362014-07-26 04:38:32517 'ios_dbg_simulator',
518 'ios_rel_device',
519 'ios_rel_device_ninja',
520 'mac_asan',
521 'mac_asan_64',
522 'mac_chromium_compile_dbg',
523 'mac_chromium_compile_rel',
524 'mac_chromium_dbg',
525 'mac_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32526 'mac_nacl_sdk',
527 'mac_nacl_sdk_build',
528 'mac_rel_naclmore',
[email protected]0bb112362014-07-26 04:38:32529 'mac_x64_rel',
530 'mac_xcodebuild',
531 ],
tandriie5587792016-07-14 00:34:50532 'master.tryserver.chromium.linux': [
[email protected]0bb112362014-07-26 04:38:32533 'chromium_presubmit',
534 'linux_arm_cross_compile',
535 'linux_arm_tester',
[email protected]0bb112362014-07-26 04:38:32536 'linux_chromeos_asan',
537 'linux_chromeos_browser_asan',
538 'linux_chromeos_valgrind',
[email protected]0bb112362014-07-26 04:38:32539 'linux_chromium_chromeos_dbg',
540 'linux_chromium_chromeos_rel',
[email protected]0bb112362014-07-26 04:38:32541 'linux_chromium_compile_dbg',
542 'linux_chromium_compile_rel',
543 'linux_chromium_dbg',
544 'linux_chromium_gn_dbg',
545 'linux_chromium_gn_rel',
546 'linux_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32547 'linux_chromium_trusty32_dbg',
548 'linux_chromium_trusty32_rel',
549 'linux_chromium_trusty_dbg',
550 'linux_chromium_trusty_rel',
551 'linux_clang_tsan',
552 'linux_ecs_ozone',
553 'linux_layout',
554 'linux_layout_asan',
555 'linux_layout_rel',
556 'linux_layout_rel_32',
557 'linux_nacl_sdk',
558 'linux_nacl_sdk_bionic',
559 'linux_nacl_sdk_bionic_build',
560 'linux_nacl_sdk_build',
561 'linux_redux',
562 'linux_rel_naclmore',
563 'linux_rel_precise32',
564 'linux_valgrind',
565 'tools_build_presubmit',
566 ],
tandriie5587792016-07-14 00:34:50567 'master.tryserver.chromium.win': [
[email protected]0bb112362014-07-26 04:38:32568 'win8_aura',
569 'win8_chromium_dbg',
570 'win8_chromium_rel',
571 'win_chromium_compile_dbg',
572 'win_chromium_compile_rel',
573 'win_chromium_dbg',
574 'win_chromium_rel',
575 'win_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32576 'win_chromium_x64_dbg',
577 'win_chromium_x64_rel',
[email protected]0bb112362014-07-26 04:38:32578 'win_nacl_sdk',
579 'win_nacl_sdk_build',
580 'win_rel_naclmore',
581 ],
582 }
583 for master, bots in bots.iteritems():
584 for bot in bots:
585 self.assertEqual(master, PRESUBMIT.GetTryServerMasterForBot(bot),
586 'bot=%s: expected %s, computed %s' % (
587 bot, master, PRESUBMIT.GetTryServerMasterForBot(bot)))
588
589
davileene0426252015-03-02 21:10:41590class UserMetricsActionTest(unittest.TestCase):
591 def testUserMetricsActionInActions(self):
592 input_api = MockInputApi()
593 file_with_user_action = 'file_with_user_action.cc'
594 contents_with_user_action = [
595 'base::UserMetricsAction("AboutChrome")'
596 ]
597
598 input_api.files = [MockFile(file_with_user_action,
599 contents_with_user_action)]
600
601 self.assertEqual(
602 [], PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi()))
603
604
605 def testUserMetricsActionNotAddedToActions(self):
606 input_api = MockInputApi()
607 file_with_user_action = 'file_with_user_action.cc'
608 contents_with_user_action = [
609 'base::UserMetricsAction("NotInActionsXml")'
610 ]
611
612 input_api.files = [MockFile(file_with_user_action,
613 contents_with_user_action)]
614
615 output = PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi())
616 self.assertEqual(
617 ('File %s line %d: %s is missing in '
618 'tools/metrics/actions/actions.xml. Please run '
619 'tools/metrics/actions/extract_actions.py to update.'
620 % (file_with_user_action, 1, 'NotInActionsXml')),
621 output[0].message)
622
623
agrievef32bcc72016-04-04 14:57:40624class PydepsNeedsUpdatingTest(unittest.TestCase):
625
626 class MockSubprocess(object):
627 CalledProcessError = subprocess.CalledProcessError
628
629 def setUp(self):
630 mock_all_pydeps = ['A.pydeps', 'B.pydeps']
631 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
632 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
633 self.mock_input_api = MockInputApi()
634 self.mock_output_api = MockOutputApi()
635 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
636 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
637 self.checker._file_cache = {
638 'A.pydeps': '# Generated by:\n# CMD A\nA.py\nC.py\n',
639 'B.pydeps': '# Generated by:\n# CMD B\nB.py\nC.py\n',
640 }
641
642 def tearDown(self):
643 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
644
645 def _RunCheck(self):
646 return PRESUBMIT._CheckPydepsNeedsUpdating(self.mock_input_api,
647 self.mock_output_api,
648 checker_for_tests=self.checker)
649
650 def testAddedPydep(self):
pastarmovj89f7ee12016-09-20 14:58:13651 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
652 if self.mock_input_api.platform != 'linux2':
653 return []
654
agrievef32bcc72016-04-04 14:57:40655 self.mock_input_api.files = [
656 MockAffectedFile('new.pydeps', [], action='A'),
657 ]
658
659 results = self._RunCheck()
660 self.assertEqual(1, len(results))
661 self.assertTrue('PYDEPS_FILES' in str(results[0]))
662
663 def testRemovedPydep(self):
pastarmovj89f7ee12016-09-20 14:58:13664 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
665 if self.mock_input_api.platform != 'linux2':
666 return []
667
agrievef32bcc72016-04-04 14:57:40668 self.mock_input_api.files = [
669 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
670 ]
671
672 results = self._RunCheck()
673 self.assertEqual(1, len(results))
674 self.assertTrue('PYDEPS_FILES' in str(results[0]))
675
676 def testRandomPyIgnored(self):
pastarmovj89f7ee12016-09-20 14:58:13677 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
678 if self.mock_input_api.platform != 'linux2':
679 return []
680
agrievef32bcc72016-04-04 14:57:40681 self.mock_input_api.files = [
682 MockAffectedFile('random.py', []),
683 ]
684
685 results = self._RunCheck()
686 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
687
688 def testRelevantPyNoChange(self):
pastarmovj89f7ee12016-09-20 14:58:13689 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
690 if self.mock_input_api.platform != 'linux2':
691 return []
692
agrievef32bcc72016-04-04 14:57:40693 self.mock_input_api.files = [
694 MockAffectedFile('A.py', []),
695 ]
696
John Budorickab2fa102017-10-06 16:59:49697 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40698 self.assertEqual('CMD A --output ""', cmd)
699 return self.checker._file_cache['A.pydeps']
700
701 self.mock_input_api.subprocess.check_output = mock_check_output
702
703 results = self._RunCheck()
704 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
705
706 def testRelevantPyOneChange(self):
pastarmovj89f7ee12016-09-20 14:58:13707 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
708 if self.mock_input_api.platform != 'linux2':
709 return []
710
agrievef32bcc72016-04-04 14:57:40711 self.mock_input_api.files = [
712 MockAffectedFile('A.py', []),
713 ]
714
John Budorickab2fa102017-10-06 16:59:49715 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40716 self.assertEqual('CMD A --output ""', cmd)
717 return 'changed data'
718
719 self.mock_input_api.subprocess.check_output = mock_check_output
720
721 results = self._RunCheck()
722 self.assertEqual(1, len(results))
723 self.assertTrue('File is stale' in str(results[0]))
724
725 def testRelevantPyTwoChanges(self):
pastarmovj89f7ee12016-09-20 14:58:13726 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
727 if self.mock_input_api.platform != 'linux2':
728 return []
729
agrievef32bcc72016-04-04 14:57:40730 self.mock_input_api.files = [
731 MockAffectedFile('C.py', []),
732 ]
733
John Budorickab2fa102017-10-06 16:59:49734 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40735 return 'changed data'
736
737 self.mock_input_api.subprocess.check_output = mock_check_output
738
739 results = self._RunCheck()
740 self.assertEqual(2, len(results))
741 self.assertTrue('File is stale' in str(results[0]))
742 self.assertTrue('File is stale' in str(results[1]))
743
yolandyan45001472016-12-21 21:12:42744class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
745 def testCheckAndroidTestAnnotationUsage(self):
746 mock_input_api = MockInputApi()
747 mock_output_api = MockOutputApi()
748
749 mock_input_api.files = [
750 MockAffectedFile('LalaLand.java', [
751 'random stuff'
752 ]),
753 MockAffectedFile('CorrectUsage.java', [
754 'import android.support.test.filters.LargeTest;',
755 'import android.support.test.filters.MediumTest;',
756 'import android.support.test.filters.SmallTest;',
757 ]),
758 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
759 'import android.test.suitebuilder.annotation.LargeTest;',
760 ]),
761 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
762 'import android.test.suitebuilder.annotation.MediumTest;',
763 ]),
764 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
765 'import android.test.suitebuilder.annotation.SmallTest;',
766 ]),
767 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
768 'import android.test.suitebuilder.annotation.Smoke;',
769 ])
770 ]
771 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
772 mock_input_api, mock_output_api)
773 self.assertEqual(1, len(msgs),
774 'Expected %d items, found %d: %s'
775 % (1, len(msgs), msgs))
776 self.assertEqual(4, len(msgs[0].items),
777 'Expected %d items, found %d: %s'
778 % (4, len(msgs[0].items), msgs[0].items))
779 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
780 'UsedDeprecatedLargeTestAnnotation not found in errors')
781 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
782 in msgs[0].items,
783 'UsedDeprecatedMediumTestAnnotation not found in errors')
784 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
785 'UsedDeprecatedSmallTestAnnotation not found in errors')
786 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
787 'UsedDeprecatedSmokeAnnotation not found in errors')
788
Yoland Yanb92fa522017-08-28 17:37:06789class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
790 def testCheckAndroidTestAnnotationUsage(self):
791 mock_input_api = MockInputApi()
792 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:42793
Yoland Yanb92fa522017-08-28 17:37:06794 mock_input_api.files = [
795 MockAffectedFile('LalaLand.java', [
796 'random stuff'
797 ]),
798 MockAffectedFile('CorrectUsage.java', [
799 'import org.junit.ABC',
800 'import org.junit.XYZ;',
801 ]),
802 MockAffectedFile('UsedDeprecatedJUnit.java', [
803 'import junit.framework.*;',
804 ]),
805 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
806 'import junit.framework.Assert;',
807 ]),
808 ]
809 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
810 mock_input_api, mock_output_api)
811 self.assertEqual(1, len(msgs),
812 'Expected %d items, found %d: %s'
813 % (1, len(msgs), msgs))
814 self.assertEqual(2, len(msgs[0].items),
815 'Expected %d items, found %d: %s'
816 % (2, len(msgs[0].items), msgs[0].items))
817 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
818 'UsedDeprecatedJUnit.java not found in errors')
819 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
820 in msgs[0].items,
821 'UsedDeprecatedJUnitAssert not found in errors')
822
823class AndroidJUnitBaseClass(unittest.TestCase):
824 def testCheckAndroidTestAnnotationUsage(self):
825 mock_input_api = MockInputApi()
826 mock_output_api = MockOutputApi()
827
828 mock_input_api.files = [
829 MockAffectedFile('LalaLand.java', [
830 'random stuff'
831 ]),
832 MockAffectedFile('CorrectTest.java', [
833 '@RunWith(ABC.class);'
834 'public class CorrectTest {',
835 '}',
836 ]),
837 MockAffectedFile('HistoricallyIncorrectTest.java', [
838 'public class Test extends BaseCaseA {',
839 '}',
840 ], old_contents=[
841 'public class Test extends BaseCaseB {',
842 '}',
843 ]),
844 MockAffectedFile('CorrectTestWithInterface.java', [
845 '@RunWith(ABC.class);'
846 'public class CorrectTest implement Interface {',
847 '}',
848 ]),
849 MockAffectedFile('IncorrectTest.java', [
850 'public class IncorrectTest extends TestCase {',
851 '}',
852 ]),
853 MockAffectedFile('IncorrectTestWithInterface.java', [
854 'public class Test implements X extends BaseClass {',
855 '}',
856 ]),
857 MockAffectedFile('IncorrectTestMultiLine.java', [
858 'public class Test implements X, Y, Z',
859 ' extends TestBase {',
860 '}',
861 ]),
862 ]
863 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
864 mock_input_api, mock_output_api)
865 self.assertEqual(1, len(msgs),
866 'Expected %d items, found %d: %s'
867 % (1, len(msgs), msgs))
868 self.assertEqual(3, len(msgs[0].items),
869 'Expected %d items, found %d: %s'
870 % (3, len(msgs[0].items), msgs[0].items))
871 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
872 'IncorrectTest not found in errors')
873 self.assertTrue('IncorrectTestWithInterface.java:1'
874 in msgs[0].items,
875 'IncorrectTestWithInterface not found in errors')
876 self.assertTrue('IncorrectTestMultiLine.java:2' in msgs[0].items,
877 'IncorrectTestMultiLine not found in errors')
yolandyan45001472016-12-21 21:12:42878
dgn4401aa52015-04-29 16:26:17879class LogUsageTest(unittest.TestCase):
880
dgnaa68d5e2015-06-10 10:08:22881 def testCheckAndroidCrLogUsage(self):
882 mock_input_api = MockInputApi()
883 mock_output_api = MockOutputApi()
884
885 mock_input_api.files = [
886 MockAffectedFile('RandomStuff.java', [
887 'random stuff'
888 ]),
dgn87d9fb62015-06-12 09:15:12889 MockAffectedFile('HasAndroidLog.java', [
890 'import android.util.Log;',
891 'some random stuff',
892 'Log.d("TAG", "foo");',
893 ]),
894 MockAffectedFile('HasExplicitUtilLog.java', [
895 'some random stuff',
896 'android.util.Log.d("TAG", "foo");',
897 ]),
898 MockAffectedFile('IsInBasePackage.java', [
899 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:51900 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:12901 'Log.d(TAG, "foo");',
902 ]),
903 MockAffectedFile('IsInBasePackageButImportsLog.java', [
904 'package org.chromium.base;',
905 'import android.util.Log;',
dgn38736db2015-09-18 19:20:51906 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:12907 'Log.d(TAG, "foo");',
908 ]),
909 MockAffectedFile('HasBothLog.java', [
910 'import org.chromium.base.Log;',
911 'some random stuff',
dgn38736db2015-09-18 19:20:51912 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:12913 'Log.d(TAG, "foo");',
914 'android.util.Log.d("TAG", "foo");',
915 ]),
dgnaa68d5e2015-06-10 10:08:22916 MockAffectedFile('HasCorrectTag.java', [
917 'import org.chromium.base.Log;',
918 'some random stuff',
dgn38736db2015-09-18 19:20:51919 'private static final String TAG = "cr_Foo";',
920 'Log.d(TAG, "foo");',
921 ]),
922 MockAffectedFile('HasOldTag.java', [
923 'import org.chromium.base.Log;',
924 'some random stuff',
dgnaa68d5e2015-06-10 10:08:22925 'private static final String TAG = "cr.Foo";',
926 'Log.d(TAG, "foo");',
927 ]),
dgn38736db2015-09-18 19:20:51928 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:22929 'import org.chromium.base.Log;',
930 'some random stuff',
dgn38736db2015-09-18 19:20:51931 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:22932 'Log.d(TAG, "foo");',
933 ]),
934 MockAffectedFile('HasNoTagDecl.java', [
935 'import org.chromium.base.Log;',
936 'some random stuff',
937 'Log.d(TAG, "foo");',
938 ]),
939 MockAffectedFile('HasIncorrectTagDecl.java', [
940 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:51941 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:22942 'some random stuff',
943 'Log.d(TAG, "foo");',
944 ]),
945 MockAffectedFile('HasInlineTag.java', [
946 'import org.chromium.base.Log;',
947 'some random stuff',
dgn38736db2015-09-18 19:20:51948 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:22949 'Log.d("TAG", "foo");',
950 ]),
dgn38736db2015-09-18 19:20:51951 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:22952 'import org.chromium.base.Log;',
953 'some random stuff',
954 'private static final String TAG = "rubbish";',
955 'Log.d(TAG, "foo");',
956 ]),
957 MockAffectedFile('HasTooLongTag.java', [
958 'import org.chromium.base.Log;',
959 'some random stuff',
dgn38736db2015-09-18 19:20:51960 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:22961 'Log.d(TAG, "foo");',
962 ]),
963 ]
964
965 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
966 mock_input_api, mock_output_api)
967
dgn38736db2015-09-18 19:20:51968 self.assertEqual(5, len(msgs),
969 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:22970
971 # Declaration format
dgn38736db2015-09-18 19:20:51972 nb = len(msgs[0].items)
973 self.assertEqual(2, nb,
974 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:22975 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
976 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:22977
978 # Tag length
dgn38736db2015-09-18 19:20:51979 nb = len(msgs[1].items)
980 self.assertEqual(1, nb,
981 'Expected %d items, found %d: %s' % (1, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:22982 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
983
984 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:51985 nb = len(msgs[2].items)
986 self.assertEqual(1, nb,
987 'Expected %d items, found %d: %s' % (1, nb, msgs[2].items))
dgnaa68d5e2015-06-10 10:08:22988 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
989
dgn87d9fb62015-06-12 09:15:12990 # Util Log usage
dgn38736db2015-09-18 19:20:51991 nb = len(msgs[3].items)
992 self.assertEqual(2, nb,
993 'Expected %d items, found %d: %s' % (2, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:12994 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
995 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:22996
dgn38736db2015-09-18 19:20:51997 # Tag must not contain
998 nb = len(msgs[4].items)
999 self.assertEqual(2, nb,
1000 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1001 self.assertTrue('HasDottedTag.java' in msgs[4].items)
1002 self.assertTrue('HasOldTag.java' in msgs[4].items)
1003
estadee17314a02017-01-12 16:22:161004class GoogleAnswerUrlFormatTest(unittest.TestCase):
1005
1006 def testCatchAnswerUrlId(self):
1007 input_api = MockInputApi()
1008 input_api.files = [
1009 MockFile('somewhere/file.cc',
1010 ['char* host = '
1011 ' "https://support.google.com/chrome/answer/123456";']),
1012 MockFile('somewhere_else/file.cc',
1013 ['char* host = '
1014 ' "https://support.google.com/chrome/a/answer/123456";']),
1015 ]
1016
1017 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1018 input_api, MockOutputApi())
1019 self.assertEqual(1, len(warnings))
1020 self.assertEqual(2, len(warnings[0].items))
1021
1022 def testAllowAnswerUrlParam(self):
1023 input_api = MockInputApi()
1024 input_api.files = [
1025 MockFile('somewhere/file.cc',
1026 ['char* host = '
1027 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1028 ]
1029
1030 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1031 input_api, MockOutputApi())
1032 self.assertEqual(0, len(warnings))
1033
reillyi38965732015-11-16 18:27:331034class HardcodedGoogleHostsTest(unittest.TestCase):
1035
1036 def testWarnOnAssignedLiterals(self):
1037 input_api = MockInputApi()
1038 input_api.files = [
1039 MockFile('content/file.cc',
1040 ['char* host = "https://www.google.com";']),
1041 MockFile('content/file.cc',
1042 ['char* host = "https://www.googleapis.com";']),
1043 MockFile('content/file.cc',
1044 ['char* host = "https://clients1.google.com";']),
1045 ]
1046
1047 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1048 input_api, MockOutputApi())
1049 self.assertEqual(1, len(warnings))
1050 self.assertEqual(3, len(warnings[0].items))
1051
1052 def testAllowInComment(self):
1053 input_api = MockInputApi()
1054 input_api.files = [
1055 MockFile('content/file.cc',
1056 ['char* host = "https://www.aol.com"; // google.com'])
1057 ]
1058
1059 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1060 input_api, MockOutputApi())
1061 self.assertEqual(0, len(warnings))
1062
dgn4401aa52015-04-29 16:26:171063
jbriance9e12f162016-11-25 07:57:501064class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311065 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501066 mock_input_api = MockInputApi()
1067 mock_input_api.files = [
1068 MockAffectedFile('somewhere/file.cc', [
1069 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311070 ]),
1071 MockAffectedFile('third_party/header.h', [
1072 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501073 ])
1074 ]
1075 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1076 MockOutputApi())
1077 self.assertEqual(0, len(warnings))
1078
1079 def testNoNestedDeclaration(self):
1080 mock_input_api = MockInputApi()
1081 mock_input_api.files = [
1082 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311083 'class SomeClass {',
1084 ' protected:',
1085 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501086 '};'
1087 ])
1088 ]
1089 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1090 MockOutputApi())
1091 self.assertEqual(0, len(warnings))
1092
1093 def testSubStrings(self):
1094 mock_input_api = MockInputApi()
1095 mock_input_api.files = [
1096 MockAffectedFile('somewhere/header.h', [
1097 'class NotUsefulClass;',
1098 'struct SomeStruct;',
1099 'UsefulClass *p1;',
1100 'SomeStructPtr *p2;'
1101 ])
1102 ]
1103 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1104 MockOutputApi())
1105 self.assertEqual(2, len(warnings))
1106
1107 def testUselessForwardDeclaration(self):
1108 mock_input_api = MockInputApi()
1109 mock_input_api.files = [
1110 MockAffectedFile('somewhere/header.h', [
1111 'class DummyClass;',
1112 'struct DummyStruct;',
1113 'class UsefulClass;',
1114 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311115 ])
jbriance9e12f162016-11-25 07:57:501116 ]
1117 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1118 MockOutputApi())
1119 self.assertEqual(2, len(warnings))
1120
jbriance2c51e821a2016-12-12 08:24:311121 def testBlinkHeaders(self):
1122 mock_input_api = MockInputApi()
1123 mock_input_api.files = [
1124 MockAffectedFile('third_party/WebKit/header.h', [
1125 'class DummyClass;',
1126 'struct DummyStruct;',
1127 ]),
1128 MockAffectedFile('third_party\\WebKit\\header.h', [
1129 'class DummyClass;',
1130 'struct DummyStruct;',
1131 ])
1132 ]
1133 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1134 MockOutputApi())
1135 self.assertEqual(4, len(warnings))
1136
jbriance9e12f162016-11-25 07:57:501137
dbeam1ec68ac2016-12-15 05:22:241138class RiskyJsTest(unittest.TestCase):
1139 def testArrowWarnInIos9Code(self):
1140 mock_input_api = MockInputApi()
1141 mock_output_api = MockOutputApi()
1142
1143 mock_input_api.files = [
1144 MockAffectedFile('components/blah.js', ["shouldn't use => here"]),
1145 ]
1146 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1147 mock_input_api, mock_output_api)
1148 self.assertEqual(1, len(warnings))
1149
1150 mock_input_api.files = [
1151 MockAffectedFile('ios/blee.js', ['might => break folks']),
1152 ]
1153 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1154 mock_input_api, mock_output_api)
1155 self.assertEqual(1, len(warnings))
1156
1157 mock_input_api.files = [
1158 MockAffectedFile('ui/webui/resources/blarg.js', ['on => iOS9']),
1159 ]
1160 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1161 mock_input_api, mock_output_api)
1162 self.assertEqual(1, len(warnings))
1163
1164 def testArrowsAllowedInChromeCode(self):
1165 mock_input_api = MockInputApi()
1166 mock_input_api.files = [
1167 MockAffectedFile('chrome/browser/resources/blah.js', 'arrow => OK here'),
1168 ]
1169 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1170 mock_input_api, MockOutputApi())
1171 self.assertEqual(0, len(warnings))
1172
dpapadd651231d82017-07-21 02:44:471173 def testConstLetWarningIos9Code(self):
1174 mock_input_api = MockInputApi()
1175 mock_output_api = MockOutputApi()
1176
1177 mock_input_api.files = [
1178 MockAffectedFile('components/blah.js', [" const foo = 'bar';"]),
1179 MockAffectedFile('ui/webui/resources/blah.js', [" let foo = 3;"]),
1180 ]
1181 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1182 mock_input_api, mock_output_api)
1183 self.assertEqual(2, len(warnings))
1184
rlanday6802cf632017-05-30 17:48:361185class RelativeIncludesTest(unittest.TestCase):
1186 def testThirdPartyNotWebKitIgnored(self):
1187 mock_input_api = MockInputApi()
1188 mock_input_api.files = [
1189 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1190 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1191 ]
1192
1193 mock_output_api = MockOutputApi()
1194
1195 errors = PRESUBMIT._CheckForRelativeIncludes(
1196 mock_input_api, mock_output_api)
1197 self.assertEqual(0, len(errors))
1198
1199 def testNonCppFileIgnored(self):
1200 mock_input_api = MockInputApi()
1201 mock_input_api.files = [
1202 MockAffectedFile('test.py', '#include "../header.h"'),
1203 ]
1204
1205 mock_output_api = MockOutputApi()
1206
1207 errors = PRESUBMIT._CheckForRelativeIncludes(
1208 mock_input_api, mock_output_api)
1209 self.assertEqual(0, len(errors))
1210
1211 def testInnocuousChangesAllowed(self):
1212 mock_input_api = MockInputApi()
1213 mock_input_api.files = [
1214 MockAffectedFile('test.cpp', '#include "header.h"'),
1215 MockAffectedFile('test2.cpp', '../'),
1216 ]
1217
1218 mock_output_api = MockOutputApi()
1219
1220 errors = PRESUBMIT._CheckForRelativeIncludes(
1221 mock_input_api, mock_output_api)
1222 self.assertEqual(0, len(errors))
1223
1224 def testRelativeIncludeNonWebKitProducesError(self):
1225 mock_input_api = MockInputApi()
1226 mock_input_api.files = [
1227 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1228 ]
1229
1230 mock_output_api = MockOutputApi()
1231
1232 errors = PRESUBMIT._CheckForRelativeIncludes(
1233 mock_input_api, mock_output_api)
1234 self.assertEqual(1, len(errors))
1235
1236 def testRelativeIncludeWebKitProducesError(self):
1237 mock_input_api = MockInputApi()
1238 mock_input_api.files = [
1239 MockAffectedFile('third_party/WebKit/test.cpp',
1240 ['#include "../header.h']),
1241 ]
1242
1243 mock_output_api = MockOutputApi()
1244
1245 errors = PRESUBMIT._CheckForRelativeIncludes(
1246 mock_input_api, mock_output_api)
1247 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241248
Daniel Cheng13ca61a882017-08-25 15:11:251249
1250class MojoManifestOwnerTest(unittest.TestCase):
1251 def testMojoManifestChangeNeedsSecurityOwner(self):
1252 mock_input_api = MockInputApi()
1253 mock_input_api.files = [
1254 MockAffectedFile('services/goat/manifest.json',
1255 [
1256 '{',
1257 ' "name": "teleporter",',
1258 ' "display_name": "Goat Teleporter",'
1259 ' "interface_provider_specs": {',
1260 ' }',
1261 '}',
1262 ])
1263 ]
1264 mock_output_api = MockOutputApi()
1265 errors = PRESUBMIT._CheckIpcOwners(
1266 mock_input_api, mock_output_api)
1267 self.assertEqual(1, len(errors))
1268 self.assertEqual(
1269 'Found OWNERS files that need to be updated for IPC security review ' +
1270 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
1271
1272 # No warning if already covered by an OWNERS rule.
1273
1274 def testNonManifestChangesDoNotRequireSecurityOwner(self):
1275 mock_input_api = MockInputApi()
1276 mock_input_api.files = [
1277 MockAffectedFile('services/goat/species.json',
1278 [
1279 '[',
1280 ' "anglo-nubian",',
1281 ' "angora"',
1282 ']',
1283 ])
1284 ]
1285 mock_output_api = MockOutputApi()
1286 errors = PRESUBMIT._CheckIpcOwners(
1287 mock_input_api, mock_output_api)
1288 self.assertEqual([], errors)
1289
1290
Miguel Casas-Sancheze0d46d42017-12-14 15:52:191291class CrbugUrlFormatTest(unittest.TestCase):
1292
1293 def testCheckCrbugLinksHaveHttps(self):
1294 input_api = MockInputApi()
1295 input_api.files = [
1296 MockFile('somewhere/file.cc',
1297 ['// TODO(developer): crbug.com should be linkified',
1298 '// TODO(developer): (crbug.com) should be linkified',
1299 '// TODO(developer): crbug/123 should be well formed',
1300 '// TODO(developer): http://crbug.com it\'s OK',
1301 '// TODO(developer): https://crbug.com is just great']),
1302 ]
1303
1304 warnings = PRESUBMIT._CheckCrbugLinksHaveHttps(input_api, MockOutputApi())
1305 self.assertEqual(1, len(warnings))
1306
1307
[email protected]2299dcf2012-11-15 19:56:241308if __name__ == '__main__':
1309 unittest.main()