blob: 5aa17a16e37184b865a182c0ad35e76da605135c [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))
Sylvain Defresnea8b73d252018-02-28 15:45:54164 self.assertEqual(1, 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
Zhiling Huang45cabf32018-03-10 00:50:03659 self.mock_input_api.CreateMockFileInPath(
660 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
661 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40662 results = self._RunCheck()
663 self.assertEqual(1, len(results))
664 self.assertTrue('PYDEPS_FILES' in str(results[0]))
665
Zhiling Huang45cabf32018-03-10 00:50:03666 def testPydepNotInSrc(self):
667 self.mock_input_api.files = [
668 MockAffectedFile('new.pydeps', [], action='A'),
669 ]
670 self.mock_input_api.CreateMockFileInPath([])
671 results = self._RunCheck()
672 self.assertEqual(0, len(results))
673
agrievef32bcc72016-04-04 14:57:40674 def testRemovedPydep(self):
pastarmovj89f7ee12016-09-20 14:58:13675 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
676 if self.mock_input_api.platform != 'linux2':
677 return []
678
agrievef32bcc72016-04-04 14:57:40679 self.mock_input_api.files = [
680 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
681 ]
Zhiling Huang45cabf32018-03-10 00:50:03682 self.mock_input_api.CreateMockFileInPath(
683 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
684 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40685 results = self._RunCheck()
686 self.assertEqual(1, len(results))
687 self.assertTrue('PYDEPS_FILES' in str(results[0]))
688
689 def testRandomPyIgnored(self):
pastarmovj89f7ee12016-09-20 14:58:13690 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
691 if self.mock_input_api.platform != 'linux2':
692 return []
693
agrievef32bcc72016-04-04 14:57:40694 self.mock_input_api.files = [
695 MockAffectedFile('random.py', []),
696 ]
697
698 results = self._RunCheck()
699 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
700
701 def testRelevantPyNoChange(self):
pastarmovj89f7ee12016-09-20 14:58:13702 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
703 if self.mock_input_api.platform != 'linux2':
704 return []
705
agrievef32bcc72016-04-04 14:57:40706 self.mock_input_api.files = [
707 MockAffectedFile('A.py', []),
708 ]
709
John Budorickab2fa102017-10-06 16:59:49710 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40711 self.assertEqual('CMD A --output ""', cmd)
712 return self.checker._file_cache['A.pydeps']
713
714 self.mock_input_api.subprocess.check_output = mock_check_output
715
716 results = self._RunCheck()
717 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
718
719 def testRelevantPyOneChange(self):
pastarmovj89f7ee12016-09-20 14:58:13720 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
721 if self.mock_input_api.platform != 'linux2':
722 return []
723
agrievef32bcc72016-04-04 14:57:40724 self.mock_input_api.files = [
725 MockAffectedFile('A.py', []),
726 ]
727
John Budorickab2fa102017-10-06 16:59:49728 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40729 self.assertEqual('CMD A --output ""', cmd)
730 return 'changed data'
731
732 self.mock_input_api.subprocess.check_output = mock_check_output
733
734 results = self._RunCheck()
735 self.assertEqual(1, len(results))
736 self.assertTrue('File is stale' in str(results[0]))
737
738 def testRelevantPyTwoChanges(self):
pastarmovj89f7ee12016-09-20 14:58:13739 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
740 if self.mock_input_api.platform != 'linux2':
741 return []
742
agrievef32bcc72016-04-04 14:57:40743 self.mock_input_api.files = [
744 MockAffectedFile('C.py', []),
745 ]
746
John Budorickab2fa102017-10-06 16:59:49747 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40748 return 'changed data'
749
750 self.mock_input_api.subprocess.check_output = mock_check_output
751
752 results = self._RunCheck()
753 self.assertEqual(2, len(results))
754 self.assertTrue('File is stale' in str(results[0]))
755 self.assertTrue('File is stale' in str(results[1]))
756
Daniel Bratell8ba52722018-03-02 16:06:14757class IncludeGuardTest(unittest.TestCase):
758 def testIncludeGuardChecks(self):
759 mock_input_api = MockInputApi()
760 mock_output_api = MockOutputApi()
761 mock_input_api.files = [
762 MockAffectedFile('content/browser/thing/foo.h', [
763 '// Comment',
764 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
765 '#define CONTENT_BROWSER_THING_FOO_H_',
766 'struct McBoatFace;',
767 '#endif // CONTENT_BROWSER_THING_FOO_H_',
768 ]),
769 MockAffectedFile('content/browser/thing/bar.h', [
770 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
771 '#define CONTENT_BROWSER_THING_BAR_H_',
772 'namespace content {',
773 '#endif // CONTENT_BROWSER_THING_BAR_H_',
774 '} // namespace content',
775 ]),
776 MockAffectedFile('content/browser/test1.h', [
777 'namespace content {',
778 '} // namespace content',
779 ]),
780 MockAffectedFile('content\\browser\\win.h', [
781 '#ifndef CONTENT_BROWSER_WIN_H_',
782 '#define CONTENT_BROWSER_WIN_H_',
783 'struct McBoatFace;',
784 '#endif // CONTENT_BROWSER_WIN_H_',
785 ]),
786 MockAffectedFile('content/browser/test2.h', [
787 '// Comment',
788 '#ifndef CONTENT_BROWSER_TEST2_H_',
789 'struct McBoatFace;',
790 '#endif // CONTENT_BROWSER_TEST2_H_',
791 ]),
792 MockAffectedFile('content/browser/internal.h', [
793 '// Comment',
794 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
795 '#define CONTENT_BROWSER_INTERNAL_H_',
796 '// Comment',
797 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
798 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
799 'namespace internal {',
800 '} // namespace internal',
801 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
802 'namespace content {',
803 '} // namespace content',
804 '#endif // CONTENT_BROWSER_THING_BAR_H_',
805 ]),
806 MockAffectedFile('content/browser/thing/foo.cc', [
807 '// This is a non-header.',
808 ]),
809 MockAffectedFile('content/browser/disabled.h', [
810 '// no-include-guard-because-multiply-included',
811 'struct McBoatFace;',
812 ]),
813 # New files don't allow misspelled include guards.
814 MockAffectedFile('content/browser/spleling.h', [
815 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
816 '#define CONTENT_BROWSER_SPLLEING_H_',
817 'struct McBoatFace;',
818 '#endif // CONTENT_BROWSER_SPLLEING_H_',
819 ]),
820 # Old files allow misspelled include guards (for now).
821 MockAffectedFile('chrome/old.h', [
822 '// New contents',
823 '#ifndef CHROME_ODL_H_',
824 '#define CHROME_ODL_H_',
825 '#endif // CHROME_ODL_H_',
826 ], [
827 '// Old contents',
828 '#ifndef CHROME_ODL_H_',
829 '#define CHROME_ODL_H_',
830 '#endif // CHROME_ODL_H_',
831 ]),
832 # Using a Blink style include guard outside Blink is wrong.
833 MockAffectedFile('content/NotInBlink.h', [
834 '#ifndef NotInBlink_h',
835 '#define NotInBlink_h',
836 'struct McBoatFace;',
837 '#endif // NotInBlink_h',
838 ]),
839 # Using a Blink style include guard in Blink is ok for now.
840 MockAffectedFile('third_party/WebKit/InBlink.h', [
841 '#ifndef InBlink_h',
842 '#define InBlink_h',
843 'struct McBoatFace;',
844 '#endif // InBlink_h',
845 ]),
846 # Using a bad include guard in Blink is not ok.
847 MockAffectedFile('third_party/WebKit/AlsoInBlink.h', [
848 '#ifndef WrongInBlink_h',
849 '#define WrongInBlink_h',
850 'struct McBoatFace;',
851 '#endif // WrongInBlink_h',
852 ]),
853 # Using a bad include guard in Blink is accepted if it's an old file.
854 MockAffectedFile('third_party/WebKit/StillInBlink.h', [
855 '// New contents',
856 '#ifndef AcceptedInBlink_h',
857 '#define AcceptedInBlink_h',
858 'struct McBoatFace;',
859 '#endif // AcceptedInBlink_h',
860 ], [
861 '// Old contents',
862 '#ifndef AcceptedInBlink_h',
863 '#define AcceptedInBlink_h',
864 'struct McBoatFace;',
865 '#endif // AcceptedInBlink_h',
866 ]),
867 ]
868 msgs = PRESUBMIT._CheckForIncludeGuards(
869 mock_input_api, mock_output_api)
870 expected_fail_count = 6
871 self.assertEqual(expected_fail_count, len(msgs),
872 'Expected %d items, found %d: %s'
873 % (expected_fail_count, len(msgs), msgs))
874 self.assertEqual(msgs[0].items, [ 'content/browser/thing/bar.h' ])
875 self.assertEqual(msgs[0].message,
876 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
877 'not covering the whole file')
878
879 self.assertEqual(msgs[1].items, [ 'content/browser/test1.h' ])
880 self.assertEqual(msgs[1].message,
881 'Missing include guard CONTENT_BROWSER_TEST1_H_')
882
883 self.assertEqual(msgs[2].items, [ 'content/browser/test2.h:3' ])
884 self.assertEqual(msgs[2].message,
885 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
886 'include guard')
887
888 self.assertEqual(msgs[3].items, [ 'content/browser/spleling.h:1' ])
889 self.assertEqual(msgs[3].message,
890 'Header using the wrong include guard name '
891 'CONTENT_BROWSER_SPLLEING_H_')
892
893 self.assertEqual(msgs[4].items, [ 'content/NotInBlink.h:1' ])
894 self.assertEqual(msgs[4].message,
895 'Header using the wrong include guard name '
896 'NotInBlink_h')
897
898 self.assertEqual(msgs[5].items, [ 'third_party/WebKit/AlsoInBlink.h:1' ])
899 self.assertEqual(msgs[5].message,
900 'Header using the wrong include guard name '
901 'WrongInBlink_h')
902
yolandyan45001472016-12-21 21:12:42903class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
904 def testCheckAndroidTestAnnotationUsage(self):
905 mock_input_api = MockInputApi()
906 mock_output_api = MockOutputApi()
907
908 mock_input_api.files = [
909 MockAffectedFile('LalaLand.java', [
910 'random stuff'
911 ]),
912 MockAffectedFile('CorrectUsage.java', [
913 'import android.support.test.filters.LargeTest;',
914 'import android.support.test.filters.MediumTest;',
915 'import android.support.test.filters.SmallTest;',
916 ]),
917 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
918 'import android.test.suitebuilder.annotation.LargeTest;',
919 ]),
920 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
921 'import android.test.suitebuilder.annotation.MediumTest;',
922 ]),
923 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
924 'import android.test.suitebuilder.annotation.SmallTest;',
925 ]),
926 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
927 'import android.test.suitebuilder.annotation.Smoke;',
928 ])
929 ]
930 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
931 mock_input_api, mock_output_api)
932 self.assertEqual(1, len(msgs),
933 'Expected %d items, found %d: %s'
934 % (1, len(msgs), msgs))
935 self.assertEqual(4, len(msgs[0].items),
936 'Expected %d items, found %d: %s'
937 % (4, len(msgs[0].items), msgs[0].items))
938 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
939 'UsedDeprecatedLargeTestAnnotation not found in errors')
940 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
941 in msgs[0].items,
942 'UsedDeprecatedMediumTestAnnotation not found in errors')
943 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
944 'UsedDeprecatedSmallTestAnnotation not found in errors')
945 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
946 'UsedDeprecatedSmokeAnnotation not found in errors')
947
Yoland Yanb92fa522017-08-28 17:37:06948class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
949 def testCheckAndroidTestAnnotationUsage(self):
950 mock_input_api = MockInputApi()
951 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:42952
Yoland Yanb92fa522017-08-28 17:37:06953 mock_input_api.files = [
954 MockAffectedFile('LalaLand.java', [
955 'random stuff'
956 ]),
957 MockAffectedFile('CorrectUsage.java', [
958 'import org.junit.ABC',
959 'import org.junit.XYZ;',
960 ]),
961 MockAffectedFile('UsedDeprecatedJUnit.java', [
962 'import junit.framework.*;',
963 ]),
964 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
965 'import junit.framework.Assert;',
966 ]),
967 ]
968 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
969 mock_input_api, mock_output_api)
970 self.assertEqual(1, len(msgs),
971 'Expected %d items, found %d: %s'
972 % (1, len(msgs), msgs))
973 self.assertEqual(2, len(msgs[0].items),
974 'Expected %d items, found %d: %s'
975 % (2, len(msgs[0].items), msgs[0].items))
976 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
977 'UsedDeprecatedJUnit.java not found in errors')
978 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
979 in msgs[0].items,
980 'UsedDeprecatedJUnitAssert not found in errors')
981
982class AndroidJUnitBaseClass(unittest.TestCase):
983 def testCheckAndroidTestAnnotationUsage(self):
984 mock_input_api = MockInputApi()
985 mock_output_api = MockOutputApi()
986
987 mock_input_api.files = [
988 MockAffectedFile('LalaLand.java', [
989 'random stuff'
990 ]),
991 MockAffectedFile('CorrectTest.java', [
992 '@RunWith(ABC.class);'
993 'public class CorrectTest {',
994 '}',
995 ]),
996 MockAffectedFile('HistoricallyIncorrectTest.java', [
997 'public class Test extends BaseCaseA {',
998 '}',
999 ], old_contents=[
1000 'public class Test extends BaseCaseB {',
1001 '}',
1002 ]),
1003 MockAffectedFile('CorrectTestWithInterface.java', [
1004 '@RunWith(ABC.class);'
1005 'public class CorrectTest implement Interface {',
1006 '}',
1007 ]),
1008 MockAffectedFile('IncorrectTest.java', [
1009 'public class IncorrectTest extends TestCase {',
1010 '}',
1011 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241012 MockAffectedFile('IncorrectWithInterfaceTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061013 'public class Test implements X extends BaseClass {',
1014 '}',
1015 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241016 MockAffectedFile('IncorrectMultiLineTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061017 'public class Test implements X, Y, Z',
1018 ' extends TestBase {',
1019 '}',
1020 ]),
1021 ]
1022 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1023 mock_input_api, mock_output_api)
1024 self.assertEqual(1, len(msgs),
1025 'Expected %d items, found %d: %s'
1026 % (1, len(msgs), msgs))
1027 self.assertEqual(3, len(msgs[0].items),
1028 'Expected %d items, found %d: %s'
1029 % (3, len(msgs[0].items), msgs[0].items))
1030 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1031 'IncorrectTest not found in errors')
Vaclav Brozekf01ed502018-03-16 19:38:241032 self.assertTrue('IncorrectWithInterfaceTest.java:1'
Yoland Yanb92fa522017-08-28 17:37:061033 in msgs[0].items,
Vaclav Brozekf01ed502018-03-16 19:38:241034 'IncorrectWithInterfaceTest not found in errors')
1035 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1036 'IncorrectMultiLineTest not found in errors')
yolandyan45001472016-12-21 21:12:421037
dgn4401aa52015-04-29 16:26:171038class LogUsageTest(unittest.TestCase):
1039
dgnaa68d5e2015-06-10 10:08:221040 def testCheckAndroidCrLogUsage(self):
1041 mock_input_api = MockInputApi()
1042 mock_output_api = MockOutputApi()
1043
1044 mock_input_api.files = [
1045 MockAffectedFile('RandomStuff.java', [
1046 'random stuff'
1047 ]),
dgn87d9fb62015-06-12 09:15:121048 MockAffectedFile('HasAndroidLog.java', [
1049 'import android.util.Log;',
1050 'some random stuff',
1051 'Log.d("TAG", "foo");',
1052 ]),
1053 MockAffectedFile('HasExplicitUtilLog.java', [
1054 'some random stuff',
1055 'android.util.Log.d("TAG", "foo");',
1056 ]),
1057 MockAffectedFile('IsInBasePackage.java', [
1058 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511059 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121060 'Log.d(TAG, "foo");',
1061 ]),
1062 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1063 'package org.chromium.base;',
1064 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511065 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121066 'Log.d(TAG, "foo");',
1067 ]),
1068 MockAffectedFile('HasBothLog.java', [
1069 'import org.chromium.base.Log;',
1070 'some random stuff',
dgn38736db2015-09-18 19:20:511071 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121072 'Log.d(TAG, "foo");',
1073 'android.util.Log.d("TAG", "foo");',
1074 ]),
dgnaa68d5e2015-06-10 10:08:221075 MockAffectedFile('HasCorrectTag.java', [
1076 'import org.chromium.base.Log;',
1077 'some random stuff',
dgn38736db2015-09-18 19:20:511078 'private static final String TAG = "cr_Foo";',
1079 'Log.d(TAG, "foo");',
1080 ]),
1081 MockAffectedFile('HasOldTag.java', [
1082 'import org.chromium.base.Log;',
1083 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221084 'private static final String TAG = "cr.Foo";',
1085 'Log.d(TAG, "foo");',
1086 ]),
dgn38736db2015-09-18 19:20:511087 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221088 'import org.chromium.base.Log;',
1089 'some random stuff',
dgn38736db2015-09-18 19:20:511090 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221091 'Log.d(TAG, "foo");',
1092 ]),
1093 MockAffectedFile('HasNoTagDecl.java', [
1094 'import org.chromium.base.Log;',
1095 'some random stuff',
1096 'Log.d(TAG, "foo");',
1097 ]),
1098 MockAffectedFile('HasIncorrectTagDecl.java', [
1099 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511100 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221101 'some random stuff',
1102 'Log.d(TAG, "foo");',
1103 ]),
1104 MockAffectedFile('HasInlineTag.java', [
1105 'import org.chromium.base.Log;',
1106 'some random stuff',
dgn38736db2015-09-18 19:20:511107 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221108 'Log.d("TAG", "foo");',
1109 ]),
dgn38736db2015-09-18 19:20:511110 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221111 'import org.chromium.base.Log;',
1112 'some random stuff',
1113 'private static final String TAG = "rubbish";',
1114 'Log.d(TAG, "foo");',
1115 ]),
1116 MockAffectedFile('HasTooLongTag.java', [
1117 'import org.chromium.base.Log;',
1118 'some random stuff',
dgn38736db2015-09-18 19:20:511119 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:221120 'Log.d(TAG, "foo");',
1121 ]),
1122 ]
1123
1124 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1125 mock_input_api, mock_output_api)
1126
dgn38736db2015-09-18 19:20:511127 self.assertEqual(5, len(msgs),
1128 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221129
1130 # Declaration format
dgn38736db2015-09-18 19:20:511131 nb = len(msgs[0].items)
1132 self.assertEqual(2, nb,
1133 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221134 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1135 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221136
1137 # Tag length
dgn38736db2015-09-18 19:20:511138 nb = len(msgs[1].items)
1139 self.assertEqual(1, nb,
1140 'Expected %d items, found %d: %s' % (1, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:221141 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
1142
1143 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511144 nb = len(msgs[2].items)
1145 self.assertEqual(1, nb,
1146 'Expected %d items, found %d: %s' % (1, nb, msgs[2].items))
dgnaa68d5e2015-06-10 10:08:221147 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
1148
dgn87d9fb62015-06-12 09:15:121149 # Util Log usage
dgn38736db2015-09-18 19:20:511150 nb = len(msgs[3].items)
1151 self.assertEqual(2, nb,
1152 'Expected %d items, found %d: %s' % (2, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:121153 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
1154 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:221155
dgn38736db2015-09-18 19:20:511156 # Tag must not contain
1157 nb = len(msgs[4].items)
1158 self.assertEqual(2, nb,
1159 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1160 self.assertTrue('HasDottedTag.java' in msgs[4].items)
1161 self.assertTrue('HasOldTag.java' in msgs[4].items)
1162
estadee17314a02017-01-12 16:22:161163class GoogleAnswerUrlFormatTest(unittest.TestCase):
1164
1165 def testCatchAnswerUrlId(self):
1166 input_api = MockInputApi()
1167 input_api.files = [
1168 MockFile('somewhere/file.cc',
1169 ['char* host = '
1170 ' "https://support.google.com/chrome/answer/123456";']),
1171 MockFile('somewhere_else/file.cc',
1172 ['char* host = '
1173 ' "https://support.google.com/chrome/a/answer/123456";']),
1174 ]
1175
1176 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1177 input_api, MockOutputApi())
1178 self.assertEqual(1, len(warnings))
1179 self.assertEqual(2, len(warnings[0].items))
1180
1181 def testAllowAnswerUrlParam(self):
1182 input_api = MockInputApi()
1183 input_api.files = [
1184 MockFile('somewhere/file.cc',
1185 ['char* host = '
1186 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1187 ]
1188
1189 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1190 input_api, MockOutputApi())
1191 self.assertEqual(0, len(warnings))
1192
reillyi38965732015-11-16 18:27:331193class HardcodedGoogleHostsTest(unittest.TestCase):
1194
1195 def testWarnOnAssignedLiterals(self):
1196 input_api = MockInputApi()
1197 input_api.files = [
1198 MockFile('content/file.cc',
1199 ['char* host = "https://www.google.com";']),
1200 MockFile('content/file.cc',
1201 ['char* host = "https://www.googleapis.com";']),
1202 MockFile('content/file.cc',
1203 ['char* host = "https://clients1.google.com";']),
1204 ]
1205
1206 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1207 input_api, MockOutputApi())
1208 self.assertEqual(1, len(warnings))
1209 self.assertEqual(3, len(warnings[0].items))
1210
1211 def testAllowInComment(self):
1212 input_api = MockInputApi()
1213 input_api.files = [
1214 MockFile('content/file.cc',
1215 ['char* host = "https://www.aol.com"; // google.com'])
1216 ]
1217
1218 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1219 input_api, MockOutputApi())
1220 self.assertEqual(0, len(warnings))
1221
dgn4401aa52015-04-29 16:26:171222
jbriance9e12f162016-11-25 07:57:501223class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311224 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501225 mock_input_api = MockInputApi()
1226 mock_input_api.files = [
1227 MockAffectedFile('somewhere/file.cc', [
1228 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311229 ]),
1230 MockAffectedFile('third_party/header.h', [
1231 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501232 ])
1233 ]
1234 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1235 MockOutputApi())
1236 self.assertEqual(0, len(warnings))
1237
1238 def testNoNestedDeclaration(self):
1239 mock_input_api = MockInputApi()
1240 mock_input_api.files = [
1241 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311242 'class SomeClass {',
1243 ' protected:',
1244 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501245 '};'
1246 ])
1247 ]
1248 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1249 MockOutputApi())
1250 self.assertEqual(0, len(warnings))
1251
1252 def testSubStrings(self):
1253 mock_input_api = MockInputApi()
1254 mock_input_api.files = [
1255 MockAffectedFile('somewhere/header.h', [
1256 'class NotUsefulClass;',
1257 'struct SomeStruct;',
1258 'UsefulClass *p1;',
1259 'SomeStructPtr *p2;'
1260 ])
1261 ]
1262 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1263 MockOutputApi())
1264 self.assertEqual(2, len(warnings))
1265
1266 def testUselessForwardDeclaration(self):
1267 mock_input_api = MockInputApi()
1268 mock_input_api.files = [
1269 MockAffectedFile('somewhere/header.h', [
1270 'class DummyClass;',
1271 'struct DummyStruct;',
1272 'class UsefulClass;',
1273 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311274 ])
jbriance9e12f162016-11-25 07:57:501275 ]
1276 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1277 MockOutputApi())
1278 self.assertEqual(2, len(warnings))
1279
jbriance2c51e821a2016-12-12 08:24:311280 def testBlinkHeaders(self):
1281 mock_input_api = MockInputApi()
1282 mock_input_api.files = [
1283 MockAffectedFile('third_party/WebKit/header.h', [
1284 'class DummyClass;',
1285 'struct DummyStruct;',
1286 ]),
1287 MockAffectedFile('third_party\\WebKit\\header.h', [
1288 'class DummyClass;',
1289 'struct DummyStruct;',
1290 ])
1291 ]
1292 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1293 MockOutputApi())
1294 self.assertEqual(4, len(warnings))
1295
jbriance9e12f162016-11-25 07:57:501296
dbeam1ec68ac2016-12-15 05:22:241297class RiskyJsTest(unittest.TestCase):
1298 def testArrowWarnInIos9Code(self):
1299 mock_input_api = MockInputApi()
1300 mock_output_api = MockOutputApi()
1301
1302 mock_input_api.files = [
1303 MockAffectedFile('components/blah.js', ["shouldn't use => here"]),
1304 ]
1305 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1306 mock_input_api, mock_output_api)
1307 self.assertEqual(1, len(warnings))
1308
1309 mock_input_api.files = [
1310 MockAffectedFile('ios/blee.js', ['might => break folks']),
1311 ]
1312 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1313 mock_input_api, mock_output_api)
1314 self.assertEqual(1, len(warnings))
1315
1316 mock_input_api.files = [
1317 MockAffectedFile('ui/webui/resources/blarg.js', ['on => iOS9']),
1318 ]
1319 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1320 mock_input_api, mock_output_api)
1321 self.assertEqual(1, len(warnings))
1322
1323 def testArrowsAllowedInChromeCode(self):
1324 mock_input_api = MockInputApi()
1325 mock_input_api.files = [
1326 MockAffectedFile('chrome/browser/resources/blah.js', 'arrow => OK here'),
1327 ]
1328 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1329 mock_input_api, MockOutputApi())
1330 self.assertEqual(0, len(warnings))
1331
dpapadd651231d82017-07-21 02:44:471332 def testConstLetWarningIos9Code(self):
1333 mock_input_api = MockInputApi()
1334 mock_output_api = MockOutputApi()
1335
1336 mock_input_api.files = [
1337 MockAffectedFile('components/blah.js', [" const foo = 'bar';"]),
1338 MockAffectedFile('ui/webui/resources/blah.js', [" let foo = 3;"]),
1339 ]
1340 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1341 mock_input_api, mock_output_api)
1342 self.assertEqual(2, len(warnings))
1343
rlanday6802cf632017-05-30 17:48:361344class RelativeIncludesTest(unittest.TestCase):
1345 def testThirdPartyNotWebKitIgnored(self):
1346 mock_input_api = MockInputApi()
1347 mock_input_api.files = [
1348 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1349 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1350 ]
1351
1352 mock_output_api = MockOutputApi()
1353
1354 errors = PRESUBMIT._CheckForRelativeIncludes(
1355 mock_input_api, mock_output_api)
1356 self.assertEqual(0, len(errors))
1357
1358 def testNonCppFileIgnored(self):
1359 mock_input_api = MockInputApi()
1360 mock_input_api.files = [
1361 MockAffectedFile('test.py', '#include "../header.h"'),
1362 ]
1363
1364 mock_output_api = MockOutputApi()
1365
1366 errors = PRESUBMIT._CheckForRelativeIncludes(
1367 mock_input_api, mock_output_api)
1368 self.assertEqual(0, len(errors))
1369
1370 def testInnocuousChangesAllowed(self):
1371 mock_input_api = MockInputApi()
1372 mock_input_api.files = [
1373 MockAffectedFile('test.cpp', '#include "header.h"'),
1374 MockAffectedFile('test2.cpp', '../'),
1375 ]
1376
1377 mock_output_api = MockOutputApi()
1378
1379 errors = PRESUBMIT._CheckForRelativeIncludes(
1380 mock_input_api, mock_output_api)
1381 self.assertEqual(0, len(errors))
1382
1383 def testRelativeIncludeNonWebKitProducesError(self):
1384 mock_input_api = MockInputApi()
1385 mock_input_api.files = [
1386 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1387 ]
1388
1389 mock_output_api = MockOutputApi()
1390
1391 errors = PRESUBMIT._CheckForRelativeIncludes(
1392 mock_input_api, mock_output_api)
1393 self.assertEqual(1, len(errors))
1394
1395 def testRelativeIncludeWebKitProducesError(self):
1396 mock_input_api = MockInputApi()
1397 mock_input_api.files = [
1398 MockAffectedFile('third_party/WebKit/test.cpp',
1399 ['#include "../header.h']),
1400 ]
1401
1402 mock_output_api = MockOutputApi()
1403
1404 errors = PRESUBMIT._CheckForRelativeIncludes(
1405 mock_input_api, mock_output_api)
1406 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241407
Daniel Cheng13ca61a882017-08-25 15:11:251408
1409class MojoManifestOwnerTest(unittest.TestCase):
1410 def testMojoManifestChangeNeedsSecurityOwner(self):
1411 mock_input_api = MockInputApi()
1412 mock_input_api.files = [
1413 MockAffectedFile('services/goat/manifest.json',
1414 [
1415 '{',
1416 ' "name": "teleporter",',
1417 ' "display_name": "Goat Teleporter",'
1418 ' "interface_provider_specs": {',
1419 ' }',
1420 '}',
1421 ])
1422 ]
1423 mock_output_api = MockOutputApi()
1424 errors = PRESUBMIT._CheckIpcOwners(
1425 mock_input_api, mock_output_api)
1426 self.assertEqual(1, len(errors))
1427 self.assertEqual(
1428 'Found OWNERS files that need to be updated for IPC security review ' +
1429 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
1430
1431 # No warning if already covered by an OWNERS rule.
1432
1433 def testNonManifestChangesDoNotRequireSecurityOwner(self):
1434 mock_input_api = MockInputApi()
1435 mock_input_api.files = [
1436 MockAffectedFile('services/goat/species.json',
1437 [
1438 '[',
1439 ' "anglo-nubian",',
1440 ' "angora"',
1441 ']',
1442 ])
1443 ]
1444 mock_output_api = MockOutputApi()
1445 errors = PRESUBMIT._CheckIpcOwners(
1446 mock_input_api, mock_output_api)
1447 self.assertEqual([], errors)
1448
1449
Miguel Casas-Sancheze0d46d42017-12-14 15:52:191450class CrbugUrlFormatTest(unittest.TestCase):
1451
1452 def testCheckCrbugLinksHaveHttps(self):
1453 input_api = MockInputApi()
1454 input_api.files = [
1455 MockFile('somewhere/file.cc',
1456 ['// TODO(developer): crbug.com should be linkified',
1457 '// TODO(developer): (crbug.com) should be linkified',
1458 '// TODO(developer): crbug/123 should be well formed',
1459 '// TODO(developer): http://crbug.com it\'s OK',
Miguel Casas68bdb652017-12-19 16:29:091460 '// TODO(developer): https://crbug.com is just great',
1461 '// TODO(crbug.com/123456): this pattern it\'s also OK']),
Miguel Casas-Sancheze0d46d42017-12-14 15:52:191462 ]
1463
1464 warnings = PRESUBMIT._CheckCrbugLinksHaveHttps(input_api, MockOutputApi())
1465 self.assertEqual(1, len(warnings))
Miguel Casas68bdb652017-12-19 16:29:091466 self.assertEqual(3, warnings[0].message.count('\n'));
Miguel Casas-Sancheze0d46d42017-12-14 15:52:191467
1468
Sylvain Defresnea8b73d252018-02-28 15:45:541469class BannedFunctionCheckTest(unittest.TestCase):
1470
1471 def testBannedIosObcjFunctions(self):
1472 input_api = MockInputApi()
1473 input_api.files = [
1474 MockFile('some/ios/file.mm',
1475 ['TEST(SomeClassTest, SomeInteraction) {',
1476 '}']),
1477 MockFile('some/mac/file.mm',
1478 ['TEST(SomeClassTest, SomeInteraction) {',
1479 '}']),
1480 MockFile('another/ios_file.mm',
1481 ['class SomeTest : public testing::Test {};']),
1482 ]
1483
1484 errors = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi())
1485 self.assertEqual(1, len(errors))
1486 self.assertTrue('some/ios/file.mm' in errors[0].message)
1487 self.assertTrue('another/ios_file.mm' in errors[0].message)
1488 self.assertTrue('some/mac/file.mm' not in errors[0].message)
1489
1490
Vaclav Brozekf01ed502018-03-16 19:38:241491class NoProductionCodeUsingTestOnlyFunctions(unittest.TestCase):
1492 def testTruePositives(self):
1493 mock_input_api = MockInputApi()
1494 mock_input_api.files = [
1495 MockFile('some/path/foo.cc', ['foo_for_testing();']),
1496 MockFile('some/path/foo.mm', ['FooForTesting();']),
1497 MockFile('some/path/foo.cxx', ['FooForTests();']),
1498 MockFile('some/path/foo.cpp', ['foo_for_test();']),
1499 ]
1500
1501 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
1502 mock_input_api, MockOutputApi())
1503 self.assertEqual(1, len(results))
1504 self.assertEqual(4, len(results[0].items))
1505 self.assertTrue('foo.cc' in results[0].items[0])
1506 self.assertTrue('foo.mm' in results[0].items[1])
1507 self.assertTrue('foo.cxx' in results[0].items[2])
1508 self.assertTrue('foo.cpp' in results[0].items[3])
1509
1510 def testFalsePositives(self):
1511 mock_input_api = MockInputApi()
1512 mock_input_api.files = [
1513 MockFile('some/path/foo.h', ['foo_for_testing();']),
1514 MockFile('some/path/foo.mm', ['FooForTesting() {']),
1515 MockFile('some/path/foo.cc', ['::FooForTests();']),
1516 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
1517 ]
1518
1519 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
1520 mock_input_api, MockOutputApi())
1521 self.assertEqual(0, len(results))
1522
1523
[email protected]2299dcf2012-11-15 19:56:241524if __name__ == '__main__':
1525 unittest.main()