blob: 649872cb9d5a59dd83d5c9bb6055130737d4d176 [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',
507 'android_compile_rel',
508 'android_compile_x64_dbg',
509 'android_compile_x86_dbg',
510 'android_coverage',
511 'android_cronet_tester'
512 'android_swarming_rel',
513 'cast_shell_android',
514 'linux_android_dbg_ng',
515 'linux_android_rel_ng',
516 ],
tandriie5587792016-07-14 00:34:50517 'master.tryserver.chromium.mac': [
[email protected]0bb112362014-07-26 04:38:32518 'ios_dbg_simulator',
519 'ios_rel_device',
520 'ios_rel_device_ninja',
521 'mac_asan',
522 'mac_asan_64',
523 'mac_chromium_compile_dbg',
524 'mac_chromium_compile_rel',
525 'mac_chromium_dbg',
526 'mac_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32527 'mac_nacl_sdk',
528 'mac_nacl_sdk_build',
529 'mac_rel_naclmore',
[email protected]0bb112362014-07-26 04:38:32530 'mac_x64_rel',
531 'mac_xcodebuild',
532 ],
tandriie5587792016-07-14 00:34:50533 'master.tryserver.chromium.linux': [
[email protected]0bb112362014-07-26 04:38:32534 'chromium_presubmit',
535 'linux_arm_cross_compile',
536 'linux_arm_tester',
[email protected]0bb112362014-07-26 04:38:32537 'linux_chromeos_asan',
538 'linux_chromeos_browser_asan',
539 'linux_chromeos_valgrind',
[email protected]0bb112362014-07-26 04:38:32540 'linux_chromium_chromeos_dbg',
541 'linux_chromium_chromeos_rel',
[email protected]0bb112362014-07-26 04:38:32542 'linux_chromium_compile_dbg',
543 'linux_chromium_compile_rel',
544 'linux_chromium_dbg',
545 'linux_chromium_gn_dbg',
546 'linux_chromium_gn_rel',
547 'linux_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32548 'linux_chromium_trusty32_dbg',
549 'linux_chromium_trusty32_rel',
550 'linux_chromium_trusty_dbg',
551 'linux_chromium_trusty_rel',
552 'linux_clang_tsan',
553 'linux_ecs_ozone',
554 'linux_layout',
555 'linux_layout_asan',
556 'linux_layout_rel',
557 'linux_layout_rel_32',
558 'linux_nacl_sdk',
559 'linux_nacl_sdk_bionic',
560 'linux_nacl_sdk_bionic_build',
561 'linux_nacl_sdk_build',
562 'linux_redux',
563 'linux_rel_naclmore',
564 'linux_rel_precise32',
565 'linux_valgrind',
566 'tools_build_presubmit',
567 ],
tandriie5587792016-07-14 00:34:50568 'master.tryserver.chromium.win': [
[email protected]0bb112362014-07-26 04:38:32569 'win8_aura',
570 'win8_chromium_dbg',
571 'win8_chromium_rel',
572 'win_chromium_compile_dbg',
573 'win_chromium_compile_rel',
574 'win_chromium_dbg',
575 'win_chromium_rel',
576 'win_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32577 'win_chromium_x64_dbg',
578 'win_chromium_x64_rel',
[email protected]0bb112362014-07-26 04:38:32579 'win_nacl_sdk',
580 'win_nacl_sdk_build',
581 'win_rel_naclmore',
582 ],
583 }
584 for master, bots in bots.iteritems():
585 for bot in bots:
586 self.assertEqual(master, PRESUBMIT.GetTryServerMasterForBot(bot),
587 'bot=%s: expected %s, computed %s' % (
588 bot, master, PRESUBMIT.GetTryServerMasterForBot(bot)))
589
590
davileene0426252015-03-02 21:10:41591class UserMetricsActionTest(unittest.TestCase):
592 def testUserMetricsActionInActions(self):
593 input_api = MockInputApi()
594 file_with_user_action = 'file_with_user_action.cc'
595 contents_with_user_action = [
596 'base::UserMetricsAction("AboutChrome")'
597 ]
598
599 input_api.files = [MockFile(file_with_user_action,
600 contents_with_user_action)]
601
602 self.assertEqual(
603 [], PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi()))
604
605
606 def testUserMetricsActionNotAddedToActions(self):
607 input_api = MockInputApi()
608 file_with_user_action = 'file_with_user_action.cc'
609 contents_with_user_action = [
610 'base::UserMetricsAction("NotInActionsXml")'
611 ]
612
613 input_api.files = [MockFile(file_with_user_action,
614 contents_with_user_action)]
615
616 output = PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi())
617 self.assertEqual(
618 ('File %s line %d: %s is missing in '
619 'tools/metrics/actions/actions.xml. Please run '
620 'tools/metrics/actions/extract_actions.py to update.'
621 % (file_with_user_action, 1, 'NotInActionsXml')),
622 output[0].message)
623
624
agrievef32bcc72016-04-04 14:57:40625class PydepsNeedsUpdatingTest(unittest.TestCase):
626
627 class MockSubprocess(object):
628 CalledProcessError = subprocess.CalledProcessError
629
630 def setUp(self):
631 mock_all_pydeps = ['A.pydeps', 'B.pydeps']
632 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
633 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
634 self.mock_input_api = MockInputApi()
635 self.mock_output_api = MockOutputApi()
636 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
637 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
638 self.checker._file_cache = {
639 'A.pydeps': '# Generated by:\n# CMD A\nA.py\nC.py\n',
640 'B.pydeps': '# Generated by:\n# CMD B\nB.py\nC.py\n',
641 }
642
643 def tearDown(self):
644 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
645
646 def _RunCheck(self):
647 return PRESUBMIT._CheckPydepsNeedsUpdating(self.mock_input_api,
648 self.mock_output_api,
649 checker_for_tests=self.checker)
650
651 def testAddedPydep(self):
pastarmovj89f7ee12016-09-20 14:58:13652 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
653 if self.mock_input_api.platform != 'linux2':
654 return []
655
agrievef32bcc72016-04-04 14:57:40656 self.mock_input_api.files = [
657 MockAffectedFile('new.pydeps', [], action='A'),
658 ]
659
660 results = self._RunCheck()
661 self.assertEqual(1, len(results))
662 self.assertTrue('PYDEPS_FILES' in str(results[0]))
663
664 def testRemovedPydep(self):
pastarmovj89f7ee12016-09-20 14:58:13665 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
666 if self.mock_input_api.platform != 'linux2':
667 return []
668
agrievef32bcc72016-04-04 14:57:40669 self.mock_input_api.files = [
670 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
671 ]
672
673 results = self._RunCheck()
674 self.assertEqual(1, len(results))
675 self.assertTrue('PYDEPS_FILES' in str(results[0]))
676
677 def testRandomPyIgnored(self):
pastarmovj89f7ee12016-09-20 14:58:13678 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
679 if self.mock_input_api.platform != 'linux2':
680 return []
681
agrievef32bcc72016-04-04 14:57:40682 self.mock_input_api.files = [
683 MockAffectedFile('random.py', []),
684 ]
685
686 results = self._RunCheck()
687 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
688
689 def testRelevantPyNoChange(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('A.py', []),
696 ]
697
698 def mock_check_output(cmd, shell=False):
699 self.assertEqual('CMD A --output ""', cmd)
700 return self.checker._file_cache['A.pydeps']
701
702 self.mock_input_api.subprocess.check_output = mock_check_output
703
704 results = self._RunCheck()
705 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
706
707 def testRelevantPyOneChange(self):
pastarmovj89f7ee12016-09-20 14:58:13708 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
709 if self.mock_input_api.platform != 'linux2':
710 return []
711
agrievef32bcc72016-04-04 14:57:40712 self.mock_input_api.files = [
713 MockAffectedFile('A.py', []),
714 ]
715
716 def mock_check_output(cmd, shell=False):
717 self.assertEqual('CMD A --output ""', cmd)
718 return 'changed data'
719
720 self.mock_input_api.subprocess.check_output = mock_check_output
721
722 results = self._RunCheck()
723 self.assertEqual(1, len(results))
724 self.assertTrue('File is stale' in str(results[0]))
725
726 def testRelevantPyTwoChanges(self):
pastarmovj89f7ee12016-09-20 14:58:13727 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
728 if self.mock_input_api.platform != 'linux2':
729 return []
730
agrievef32bcc72016-04-04 14:57:40731 self.mock_input_api.files = [
732 MockAffectedFile('C.py', []),
733 ]
734
735 def mock_check_output(cmd, shell=False):
736 return 'changed data'
737
738 self.mock_input_api.subprocess.check_output = mock_check_output
739
740 results = self._RunCheck()
741 self.assertEqual(2, len(results))
742 self.assertTrue('File is stale' in str(results[0]))
743 self.assertTrue('File is stale' in str(results[1]))
744
yolandyan45001472016-12-21 21:12:42745class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
746 def testCheckAndroidTestAnnotationUsage(self):
747 mock_input_api = MockInputApi()
748 mock_output_api = MockOutputApi()
749
750 mock_input_api.files = [
751 MockAffectedFile('LalaLand.java', [
752 'random stuff'
753 ]),
754 MockAffectedFile('CorrectUsage.java', [
755 'import android.support.test.filters.LargeTest;',
756 'import android.support.test.filters.MediumTest;',
757 'import android.support.test.filters.SmallTest;',
758 ]),
759 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
760 'import android.test.suitebuilder.annotation.LargeTest;',
761 ]),
762 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
763 'import android.test.suitebuilder.annotation.MediumTest;',
764 ]),
765 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
766 'import android.test.suitebuilder.annotation.SmallTest;',
767 ]),
768 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
769 'import android.test.suitebuilder.annotation.Smoke;',
770 ])
771 ]
772 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
773 mock_input_api, mock_output_api)
774 self.assertEqual(1, len(msgs),
775 'Expected %d items, found %d: %s'
776 % (1, len(msgs), msgs))
777 self.assertEqual(4, len(msgs[0].items),
778 'Expected %d items, found %d: %s'
779 % (4, len(msgs[0].items), msgs[0].items))
780 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
781 'UsedDeprecatedLargeTestAnnotation not found in errors')
782 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
783 in msgs[0].items,
784 'UsedDeprecatedMediumTestAnnotation not found in errors')
785 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
786 'UsedDeprecatedSmallTestAnnotation not found in errors')
787 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
788 'UsedDeprecatedSmokeAnnotation not found in errors')
789
Yoland Yanb92fa522017-08-28 17:37:06790class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
791 def testCheckAndroidTestAnnotationUsage(self):
792 mock_input_api = MockInputApi()
793 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:42794
Yoland Yanb92fa522017-08-28 17:37:06795 mock_input_api.files = [
796 MockAffectedFile('LalaLand.java', [
797 'random stuff'
798 ]),
799 MockAffectedFile('CorrectUsage.java', [
800 'import org.junit.ABC',
801 'import org.junit.XYZ;',
802 ]),
803 MockAffectedFile('UsedDeprecatedJUnit.java', [
804 'import junit.framework.*;',
805 ]),
806 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
807 'import junit.framework.Assert;',
808 ]),
809 ]
810 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
811 mock_input_api, mock_output_api)
812 self.assertEqual(1, len(msgs),
813 'Expected %d items, found %d: %s'
814 % (1, len(msgs), msgs))
815 self.assertEqual(2, len(msgs[0].items),
816 'Expected %d items, found %d: %s'
817 % (2, len(msgs[0].items), msgs[0].items))
818 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
819 'UsedDeprecatedJUnit.java not found in errors')
820 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
821 in msgs[0].items,
822 'UsedDeprecatedJUnitAssert not found in errors')
823
824class AndroidJUnitBaseClass(unittest.TestCase):
825 def testCheckAndroidTestAnnotationUsage(self):
826 mock_input_api = MockInputApi()
827 mock_output_api = MockOutputApi()
828
829 mock_input_api.files = [
830 MockAffectedFile('LalaLand.java', [
831 'random stuff'
832 ]),
833 MockAffectedFile('CorrectTest.java', [
834 '@RunWith(ABC.class);'
835 'public class CorrectTest {',
836 '}',
837 ]),
838 MockAffectedFile('HistoricallyIncorrectTest.java', [
839 'public class Test extends BaseCaseA {',
840 '}',
841 ], old_contents=[
842 'public class Test extends BaseCaseB {',
843 '}',
844 ]),
845 MockAffectedFile('CorrectTestWithInterface.java', [
846 '@RunWith(ABC.class);'
847 'public class CorrectTest implement Interface {',
848 '}',
849 ]),
850 MockAffectedFile('IncorrectTest.java', [
851 'public class IncorrectTest extends TestCase {',
852 '}',
853 ]),
854 MockAffectedFile('IncorrectTestWithInterface.java', [
855 'public class Test implements X extends BaseClass {',
856 '}',
857 ]),
858 MockAffectedFile('IncorrectTestMultiLine.java', [
859 'public class Test implements X, Y, Z',
860 ' extends TestBase {',
861 '}',
862 ]),
863 ]
864 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
865 mock_input_api, mock_output_api)
866 self.assertEqual(1, len(msgs),
867 'Expected %d items, found %d: %s'
868 % (1, len(msgs), msgs))
869 self.assertEqual(3, len(msgs[0].items),
870 'Expected %d items, found %d: %s'
871 % (3, len(msgs[0].items), msgs[0].items))
872 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
873 'IncorrectTest not found in errors')
874 self.assertTrue('IncorrectTestWithInterface.java:1'
875 in msgs[0].items,
876 'IncorrectTestWithInterface not found in errors')
877 self.assertTrue('IncorrectTestMultiLine.java:2' in msgs[0].items,
878 'IncorrectTestMultiLine not found in errors')
yolandyan45001472016-12-21 21:12:42879
dgn4401aa52015-04-29 16:26:17880class LogUsageTest(unittest.TestCase):
881
dgnaa68d5e2015-06-10 10:08:22882 def testCheckAndroidCrLogUsage(self):
883 mock_input_api = MockInputApi()
884 mock_output_api = MockOutputApi()
885
886 mock_input_api.files = [
887 MockAffectedFile('RandomStuff.java', [
888 'random stuff'
889 ]),
dgn87d9fb62015-06-12 09:15:12890 MockAffectedFile('HasAndroidLog.java', [
891 'import android.util.Log;',
892 'some random stuff',
893 'Log.d("TAG", "foo");',
894 ]),
895 MockAffectedFile('HasExplicitUtilLog.java', [
896 'some random stuff',
897 'android.util.Log.d("TAG", "foo");',
898 ]),
899 MockAffectedFile('IsInBasePackage.java', [
900 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:51901 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:12902 'Log.d(TAG, "foo");',
903 ]),
904 MockAffectedFile('IsInBasePackageButImportsLog.java', [
905 'package org.chromium.base;',
906 'import android.util.Log;',
dgn38736db2015-09-18 19:20:51907 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:12908 'Log.d(TAG, "foo");',
909 ]),
910 MockAffectedFile('HasBothLog.java', [
911 'import org.chromium.base.Log;',
912 'some random stuff',
dgn38736db2015-09-18 19:20:51913 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:12914 'Log.d(TAG, "foo");',
915 'android.util.Log.d("TAG", "foo");',
916 ]),
dgnaa68d5e2015-06-10 10:08:22917 MockAffectedFile('HasCorrectTag.java', [
918 'import org.chromium.base.Log;',
919 'some random stuff',
dgn38736db2015-09-18 19:20:51920 'private static final String TAG = "cr_Foo";',
921 'Log.d(TAG, "foo");',
922 ]),
923 MockAffectedFile('HasOldTag.java', [
924 'import org.chromium.base.Log;',
925 'some random stuff',
dgnaa68d5e2015-06-10 10:08:22926 'private static final String TAG = "cr.Foo";',
927 'Log.d(TAG, "foo");',
928 ]),
dgn38736db2015-09-18 19:20:51929 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:22930 'import org.chromium.base.Log;',
931 'some random stuff',
dgn38736db2015-09-18 19:20:51932 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:22933 'Log.d(TAG, "foo");',
934 ]),
935 MockAffectedFile('HasNoTagDecl.java', [
936 'import org.chromium.base.Log;',
937 'some random stuff',
938 'Log.d(TAG, "foo");',
939 ]),
940 MockAffectedFile('HasIncorrectTagDecl.java', [
941 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:51942 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:22943 'some random stuff',
944 'Log.d(TAG, "foo");',
945 ]),
946 MockAffectedFile('HasInlineTag.java', [
947 'import org.chromium.base.Log;',
948 'some random stuff',
dgn38736db2015-09-18 19:20:51949 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:22950 'Log.d("TAG", "foo");',
951 ]),
dgn38736db2015-09-18 19:20:51952 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:22953 'import org.chromium.base.Log;',
954 'some random stuff',
955 'private static final String TAG = "rubbish";',
956 'Log.d(TAG, "foo");',
957 ]),
958 MockAffectedFile('HasTooLongTag.java', [
959 'import org.chromium.base.Log;',
960 'some random stuff',
dgn38736db2015-09-18 19:20:51961 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:22962 'Log.d(TAG, "foo");',
963 ]),
964 ]
965
966 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
967 mock_input_api, mock_output_api)
968
dgn38736db2015-09-18 19:20:51969 self.assertEqual(5, len(msgs),
970 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:22971
972 # Declaration format
dgn38736db2015-09-18 19:20:51973 nb = len(msgs[0].items)
974 self.assertEqual(2, nb,
975 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:22976 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
977 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:22978
979 # Tag length
dgn38736db2015-09-18 19:20:51980 nb = len(msgs[1].items)
981 self.assertEqual(1, nb,
982 'Expected %d items, found %d: %s' % (1, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:22983 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
984
985 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:51986 nb = len(msgs[2].items)
987 self.assertEqual(1, nb,
988 'Expected %d items, found %d: %s' % (1, nb, msgs[2].items))
dgnaa68d5e2015-06-10 10:08:22989 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
990
dgn87d9fb62015-06-12 09:15:12991 # Util Log usage
dgn38736db2015-09-18 19:20:51992 nb = len(msgs[3].items)
993 self.assertEqual(2, nb,
994 'Expected %d items, found %d: %s' % (2, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:12995 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
996 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:22997
dgn38736db2015-09-18 19:20:51998 # Tag must not contain
999 nb = len(msgs[4].items)
1000 self.assertEqual(2, nb,
1001 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1002 self.assertTrue('HasDottedTag.java' in msgs[4].items)
1003 self.assertTrue('HasOldTag.java' in msgs[4].items)
1004
estadee17314a02017-01-12 16:22:161005class GoogleAnswerUrlFormatTest(unittest.TestCase):
1006
1007 def testCatchAnswerUrlId(self):
1008 input_api = MockInputApi()
1009 input_api.files = [
1010 MockFile('somewhere/file.cc',
1011 ['char* host = '
1012 ' "https://support.google.com/chrome/answer/123456";']),
1013 MockFile('somewhere_else/file.cc',
1014 ['char* host = '
1015 ' "https://support.google.com/chrome/a/answer/123456";']),
1016 ]
1017
1018 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1019 input_api, MockOutputApi())
1020 self.assertEqual(1, len(warnings))
1021 self.assertEqual(2, len(warnings[0].items))
1022
1023 def testAllowAnswerUrlParam(self):
1024 input_api = MockInputApi()
1025 input_api.files = [
1026 MockFile('somewhere/file.cc',
1027 ['char* host = '
1028 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1029 ]
1030
1031 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1032 input_api, MockOutputApi())
1033 self.assertEqual(0, len(warnings))
1034
reillyi38965732015-11-16 18:27:331035class HardcodedGoogleHostsTest(unittest.TestCase):
1036
1037 def testWarnOnAssignedLiterals(self):
1038 input_api = MockInputApi()
1039 input_api.files = [
1040 MockFile('content/file.cc',
1041 ['char* host = "https://www.google.com";']),
1042 MockFile('content/file.cc',
1043 ['char* host = "https://www.googleapis.com";']),
1044 MockFile('content/file.cc',
1045 ['char* host = "https://clients1.google.com";']),
1046 ]
1047
1048 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1049 input_api, MockOutputApi())
1050 self.assertEqual(1, len(warnings))
1051 self.assertEqual(3, len(warnings[0].items))
1052
1053 def testAllowInComment(self):
1054 input_api = MockInputApi()
1055 input_api.files = [
1056 MockFile('content/file.cc',
1057 ['char* host = "https://www.aol.com"; // google.com'])
1058 ]
1059
1060 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1061 input_api, MockOutputApi())
1062 self.assertEqual(0, len(warnings))
1063
dgn4401aa52015-04-29 16:26:171064
jbriance9e12f162016-11-25 07:57:501065class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311066 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501067 mock_input_api = MockInputApi()
1068 mock_input_api.files = [
1069 MockAffectedFile('somewhere/file.cc', [
1070 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311071 ]),
1072 MockAffectedFile('third_party/header.h', [
1073 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501074 ])
1075 ]
1076 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1077 MockOutputApi())
1078 self.assertEqual(0, len(warnings))
1079
1080 def testNoNestedDeclaration(self):
1081 mock_input_api = MockInputApi()
1082 mock_input_api.files = [
1083 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311084 'class SomeClass {',
1085 ' protected:',
1086 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501087 '};'
1088 ])
1089 ]
1090 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1091 MockOutputApi())
1092 self.assertEqual(0, len(warnings))
1093
1094 def testSubStrings(self):
1095 mock_input_api = MockInputApi()
1096 mock_input_api.files = [
1097 MockAffectedFile('somewhere/header.h', [
1098 'class NotUsefulClass;',
1099 'struct SomeStruct;',
1100 'UsefulClass *p1;',
1101 'SomeStructPtr *p2;'
1102 ])
1103 ]
1104 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1105 MockOutputApi())
1106 self.assertEqual(2, len(warnings))
1107
1108 def testUselessForwardDeclaration(self):
1109 mock_input_api = MockInputApi()
1110 mock_input_api.files = [
1111 MockAffectedFile('somewhere/header.h', [
1112 'class DummyClass;',
1113 'struct DummyStruct;',
1114 'class UsefulClass;',
1115 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311116 ])
jbriance9e12f162016-11-25 07:57:501117 ]
1118 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1119 MockOutputApi())
1120 self.assertEqual(2, len(warnings))
1121
jbriance2c51e821a2016-12-12 08:24:311122 def testBlinkHeaders(self):
1123 mock_input_api = MockInputApi()
1124 mock_input_api.files = [
1125 MockAffectedFile('third_party/WebKit/header.h', [
1126 'class DummyClass;',
1127 'struct DummyStruct;',
1128 ]),
1129 MockAffectedFile('third_party\\WebKit\\header.h', [
1130 'class DummyClass;',
1131 'struct DummyStruct;',
1132 ])
1133 ]
1134 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1135 MockOutputApi())
1136 self.assertEqual(4, len(warnings))
1137
jbriance9e12f162016-11-25 07:57:501138
dbeam1ec68ac2016-12-15 05:22:241139class RiskyJsTest(unittest.TestCase):
1140 def testArrowWarnInIos9Code(self):
1141 mock_input_api = MockInputApi()
1142 mock_output_api = MockOutputApi()
1143
1144 mock_input_api.files = [
1145 MockAffectedFile('components/blah.js', ["shouldn't use => here"]),
1146 ]
1147 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1148 mock_input_api, mock_output_api)
1149 self.assertEqual(1, len(warnings))
1150
1151 mock_input_api.files = [
1152 MockAffectedFile('ios/blee.js', ['might => break folks']),
1153 ]
1154 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1155 mock_input_api, mock_output_api)
1156 self.assertEqual(1, len(warnings))
1157
1158 mock_input_api.files = [
1159 MockAffectedFile('ui/webui/resources/blarg.js', ['on => iOS9']),
1160 ]
1161 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1162 mock_input_api, mock_output_api)
1163 self.assertEqual(1, len(warnings))
1164
1165 def testArrowsAllowedInChromeCode(self):
1166 mock_input_api = MockInputApi()
1167 mock_input_api.files = [
1168 MockAffectedFile('chrome/browser/resources/blah.js', 'arrow => OK here'),
1169 ]
1170 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1171 mock_input_api, MockOutputApi())
1172 self.assertEqual(0, len(warnings))
1173
dpapadd651231d82017-07-21 02:44:471174 def testConstLetWarningIos9Code(self):
1175 mock_input_api = MockInputApi()
1176 mock_output_api = MockOutputApi()
1177
1178 mock_input_api.files = [
1179 MockAffectedFile('components/blah.js', [" const foo = 'bar';"]),
1180 MockAffectedFile('ui/webui/resources/blah.js', [" let foo = 3;"]),
1181 ]
1182 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1183 mock_input_api, mock_output_api)
1184 self.assertEqual(2, len(warnings))
1185
rlanday6802cf632017-05-30 17:48:361186class RelativeIncludesTest(unittest.TestCase):
1187 def testThirdPartyNotWebKitIgnored(self):
1188 mock_input_api = MockInputApi()
1189 mock_input_api.files = [
1190 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1191 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1192 ]
1193
1194 mock_output_api = MockOutputApi()
1195
1196 errors = PRESUBMIT._CheckForRelativeIncludes(
1197 mock_input_api, mock_output_api)
1198 self.assertEqual(0, len(errors))
1199
1200 def testNonCppFileIgnored(self):
1201 mock_input_api = MockInputApi()
1202 mock_input_api.files = [
1203 MockAffectedFile('test.py', '#include "../header.h"'),
1204 ]
1205
1206 mock_output_api = MockOutputApi()
1207
1208 errors = PRESUBMIT._CheckForRelativeIncludes(
1209 mock_input_api, mock_output_api)
1210 self.assertEqual(0, len(errors))
1211
1212 def testInnocuousChangesAllowed(self):
1213 mock_input_api = MockInputApi()
1214 mock_input_api.files = [
1215 MockAffectedFile('test.cpp', '#include "header.h"'),
1216 MockAffectedFile('test2.cpp', '../'),
1217 ]
1218
1219 mock_output_api = MockOutputApi()
1220
1221 errors = PRESUBMIT._CheckForRelativeIncludes(
1222 mock_input_api, mock_output_api)
1223 self.assertEqual(0, len(errors))
1224
1225 def testRelativeIncludeNonWebKitProducesError(self):
1226 mock_input_api = MockInputApi()
1227 mock_input_api.files = [
1228 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1229 ]
1230
1231 mock_output_api = MockOutputApi()
1232
1233 errors = PRESUBMIT._CheckForRelativeIncludes(
1234 mock_input_api, mock_output_api)
1235 self.assertEqual(1, len(errors))
1236
1237 def testRelativeIncludeWebKitProducesError(self):
1238 mock_input_api = MockInputApi()
1239 mock_input_api.files = [
1240 MockAffectedFile('third_party/WebKit/test.cpp',
1241 ['#include "../header.h']),
1242 ]
1243
1244 mock_output_api = MockOutputApi()
1245
1246 errors = PRESUBMIT._CheckForRelativeIncludes(
1247 mock_input_api, mock_output_api)
1248 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241249
Daniel Cheng13ca61a882017-08-25 15:11:251250
1251class MojoManifestOwnerTest(unittest.TestCase):
1252 def testMojoManifestChangeNeedsSecurityOwner(self):
1253 mock_input_api = MockInputApi()
1254 mock_input_api.files = [
1255 MockAffectedFile('services/goat/manifest.json',
1256 [
1257 '{',
1258 ' "name": "teleporter",',
1259 ' "display_name": "Goat Teleporter",'
1260 ' "interface_provider_specs": {',
1261 ' }',
1262 '}',
1263 ])
1264 ]
1265 mock_output_api = MockOutputApi()
1266 errors = PRESUBMIT._CheckIpcOwners(
1267 mock_input_api, mock_output_api)
1268 self.assertEqual(1, len(errors))
1269 self.assertEqual(
1270 'Found OWNERS files that need to be updated for IPC security review ' +
1271 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
1272
1273 # No warning if already covered by an OWNERS rule.
1274
1275 def testNonManifestChangesDoNotRequireSecurityOwner(self):
1276 mock_input_api = MockInputApi()
1277 mock_input_api.files = [
1278 MockAffectedFile('services/goat/species.json',
1279 [
1280 '[',
1281 ' "anglo-nubian",',
1282 ' "angora"',
1283 ']',
1284 ])
1285 ]
1286 mock_output_api = MockOutputApi()
1287 errors = PRESUBMIT._CheckIpcOwners(
1288 mock_input_api, mock_output_api)
1289 self.assertEqual([], errors)
1290
1291
[email protected]2299dcf2012-11-15 19:56:241292if __name__ == '__main__':
1293 unittest.main()