blob: 4532042ae79461cb34cd49054390403e3ff72135 [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
Vaclav Brozek8a8e2e202018-03-23 22:01:06109 def testNameMatch(self):
110 # Check that the detected histogram name is "Dummy" and not, e.g.,
111 # "Dummy\", true); // The \"correct"
112 diff_cc = ['UMA_HISTOGRAM_BOOL("Dummy", true); // The "correct" histogram']
113 diff_xml = ['<histogram name="Dummy"> </histogram>']
114 mock_input_api = MockInputApi()
115 mock_input_api.files = [
116 MockFile('some/path/foo.cc', diff_cc),
117 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
118 ]
119 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
120 MockOutputApi())
121 self.assertEqual(0, len(warnings))
122
123 def testSimilarMacroNames(self):
124 diff_cc = ['PUMA_HISTOGRAM_BOOL("Mountain Lion", 42)']
125 mock_input_api = MockInputApi()
126 mock_input_api.files = [
127 MockFile('some/path/foo.cc', diff_cc),
128 ]
129 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
130 MockOutputApi())
131 self.assertEqual(0, len(warnings))
132
[email protected]b8079ae4a2012-12-05 19:56:49133class BadExtensionsTest(unittest.TestCase):
134 def testBadRejFile(self):
135 mock_input_api = MockInputApi()
136 mock_input_api.files = [
137 MockFile('some/path/foo.cc', ''),
138 MockFile('some/path/foo.cc.rej', ''),
139 MockFile('some/path2/bar.h.rej', ''),
140 ]
141
142 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
143 self.assertEqual(1, len(results))
144 self.assertEqual(2, len(results[0].items))
145 self.assertTrue('foo.cc.rej' in results[0].items[0])
146 self.assertTrue('bar.h.rej' in results[0].items[1])
147
148 def testBadOrigFile(self):
149 mock_input_api = MockInputApi()
150 mock_input_api.files = [
151 MockFile('other/path/qux.h.orig', ''),
152 MockFile('other/path/qux.h', ''),
153 MockFile('other/path/qux.cc', ''),
154 ]
155
156 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
157 self.assertEqual(1, len(results))
158 self.assertEqual(1, len(results[0].items))
159 self.assertTrue('qux.h.orig' in results[0].items[0])
160
161 def testGoodFiles(self):
162 mock_input_api = MockInputApi()
163 mock_input_api.files = [
164 MockFile('other/path/qux.h', ''),
165 MockFile('other/path/qux.cc', ''),
166 ]
167 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
168 self.assertEqual(0, len(results))
169
170
glidere61efad2015-02-18 17:39:43171class CheckSingletonInHeadersTest(unittest.TestCase):
172 def testSingletonInArbitraryHeader(self):
173 diff_singleton_h = ['base::subtle::AtomicWord '
olli.raula36aa8be2015-09-10 11:14:22174 'base::Singleton<Type, Traits, DifferentiatingType>::']
175 diff_foo_h = ['// base::Singleton<Foo> in comment.',
176 'friend class base::Singleton<Foo>']
oysteinec430ad42015-10-22 20:55:24177 diff_foo2_h = [' //Foo* bar = base::Singleton<Foo>::get();']
olli.raula36aa8be2015-09-10 11:14:22178 diff_bad_h = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43179 mock_input_api = MockInputApi()
180 mock_input_api.files = [MockAffectedFile('base/memory/singleton.h',
181 diff_singleton_h),
182 MockAffectedFile('foo.h', diff_foo_h),
oysteinec430ad42015-10-22 20:55:24183 MockAffectedFile('foo2.h', diff_foo2_h),
glidere61efad2015-02-18 17:39:43184 MockAffectedFile('bad.h', diff_bad_h)]
185 warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api,
186 MockOutputApi())
187 self.assertEqual(1, len(warnings))
Sylvain Defresnea8b73d252018-02-28 15:45:54188 self.assertEqual(1, len(warnings[0].items))
glidere61efad2015-02-18 17:39:43189 self.assertEqual('error', warnings[0].type)
olli.raula36aa8be2015-09-10 11:14:22190 self.assertTrue('Found base::Singleton<T>' in warnings[0].message)
glidere61efad2015-02-18 17:39:43191
192 def testSingletonInCC(self):
olli.raula36aa8be2015-09-10 11:14:22193 diff_cc = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43194 mock_input_api = MockInputApi()
195 mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)]
196 warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api,
197 MockOutputApi())
198 self.assertEqual(0, len(warnings))
199
200
[email protected]b00342e7f2013-03-26 16:21:54201class InvalidOSMacroNamesTest(unittest.TestCase):
202 def testInvalidOSMacroNames(self):
203 lines = ['#if defined(OS_WINDOWS)',
204 ' #elif defined(OS_WINDOW)',
205 ' # if defined(OS_MACOSX) || defined(OS_CHROME)',
206 '# else // defined(OS_MAC)',
207 '#endif // defined(OS_MACOS)']
208 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
209 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
210 self.assertEqual(len(lines), len(errors))
211 self.assertTrue(':1 OS_WINDOWS' in errors[0])
212 self.assertTrue('(did you mean OS_WIN?)' in errors[0])
213
214 def testValidOSMacroNames(self):
215 lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS]
216 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
217 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
218 self.assertEqual(0, len(errors))
219
220
lliabraa35bab3932014-10-01 12:16:44221class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
222 def testInvalidIfDefinedMacroNames(self):
223 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
224 '#if !defined(TARGET_IPHONE_SIMULATOR)',
225 '#elif defined(TARGET_IPHONE_SIMULATOR)',
226 '#ifdef TARGET_IPHONE_SIMULATOR',
227 ' # ifdef TARGET_IPHONE_SIMULATOR',
228 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
229 '# else // defined(TARGET_IPHONE_SIMULATOR)',
230 '#endif // defined(TARGET_IPHONE_SIMULATOR)',]
231 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
232 MockInputApi(), MockFile('some/path/source.mm', lines))
233 self.assertEqual(len(lines), len(errors))
234
235 def testValidIfDefinedMacroNames(self):
236 lines = ['#if defined(FOO)',
237 '#ifdef BAR',]
238 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
239 MockInputApi(), MockFile('some/path/source.cc', lines))
240 self.assertEqual(0, len(errors))
241
242
[email protected]f32e2d1e2013-07-26 21:39:08243class CheckAddedDepsHaveTetsApprovalsTest(unittest.TestCase):
Daniel Cheng4dcdb6b2017-04-13 08:30:17244
245 def calculate(self, old_include_rules, old_specific_include_rules,
246 new_include_rules, new_specific_include_rules):
247 return PRESUBMIT._CalculateAddedDeps(
248 os.path, 'include_rules = %r\nspecific_include_rules = %r' % (
249 old_include_rules, old_specific_include_rules),
250 'include_rules = %r\nspecific_include_rules = %r' % (
251 new_include_rules, new_specific_include_rules))
252
253 def testCalculateAddedDeps(self):
254 old_include_rules = [
255 '+base',
256 '-chrome',
257 '+content',
258 '-grit',
259 '-grit/",',
260 '+jni/fooblat.h',
261 '!sandbox',
[email protected]f32e2d1e2013-07-26 21:39:08262 ]
Daniel Cheng4dcdb6b2017-04-13 08:30:17263 old_specific_include_rules = {
264 'compositor\.*': {
265 '+cc',
266 },
267 }
268
269 new_include_rules = [
270 '-ash',
271 '+base',
272 '+chrome',
273 '+components',
274 '+content',
275 '+grit',
276 '+grit/generated_resources.h",',
277 '+grit/",',
278 '+jni/fooblat.h',
279 '+policy',
manzagop85e629e2017-05-09 22:11:48280 '+' + os.path.join('third_party', 'WebKit'),
Daniel Cheng4dcdb6b2017-04-13 08:30:17281 ]
282 new_specific_include_rules = {
283 'compositor\.*': {
284 '+cc',
285 },
286 'widget\.*': {
287 '+gpu',
288 },
289 }
290
[email protected]f32e2d1e2013-07-26 21:39:08291 expected = set([
manzagop85e629e2017-05-09 22:11:48292 os.path.join('chrome', 'DEPS'),
293 os.path.join('gpu', 'DEPS'),
294 os.path.join('components', 'DEPS'),
295 os.path.join('policy', 'DEPS'),
296 os.path.join('third_party', 'WebKit', 'DEPS'),
[email protected]f32e2d1e2013-07-26 21:39:08297 ])
Daniel Cheng4dcdb6b2017-04-13 08:30:17298 self.assertEqual(
299 expected,
300 self.calculate(old_include_rules, old_specific_include_rules,
301 new_include_rules, new_specific_include_rules))
302
303 def testCalculateAddedDepsIgnoresPermutations(self):
304 old_include_rules = [
305 '+base',
306 '+chrome',
307 ]
308 new_include_rules = [
309 '+chrome',
310 '+base',
311 ]
312 self.assertEqual(set(),
313 self.calculate(old_include_rules, {}, new_include_rules,
314 {}))
[email protected]f32e2d1e2013-07-26 21:39:08315
316
[email protected]99171a92014-06-03 08:44:47317class JSONParsingTest(unittest.TestCase):
318 def testSuccess(self):
319 input_api = MockInputApi()
320 filename = 'valid_json.json'
321 contents = ['// This is a comment.',
322 '{',
323 ' "key1": ["value1", "value2"],',
324 ' "key2": 3 // This is an inline comment.',
325 '}'
326 ]
327 input_api.files = [MockFile(filename, contents)]
328 self.assertEqual(None,
329 PRESUBMIT._GetJSONParseError(input_api, filename))
330
331 def testFailure(self):
332 input_api = MockInputApi()
333 test_data = [
334 ('invalid_json_1.json',
335 ['{ x }'],
[email protected]a3343272014-06-17 11:41:53336 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47337 ('invalid_json_2.json',
338 ['// Hello world!',
339 '{ "hello": "world }'],
[email protected]a3343272014-06-17 11:41:53340 'Unterminated string starting at:'),
[email protected]99171a92014-06-03 08:44:47341 ('invalid_json_3.json',
342 ['{ "a": "b", "c": "d", }'],
[email protected]a3343272014-06-17 11:41:53343 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47344 ('invalid_json_4.json',
345 ['{ "a": "b" "c": "d" }'],
[email protected]a3343272014-06-17 11:41:53346 'Expecting , delimiter:'),
[email protected]99171a92014-06-03 08:44:47347 ]
348
349 input_api.files = [MockFile(filename, contents)
350 for (filename, contents, _) in test_data]
351
352 for (filename, _, expected_error) in test_data:
353 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
[email protected]a3343272014-06-17 11:41:53354 self.assertTrue(expected_error in str(actual_error),
355 "'%s' not found in '%s'" % (expected_error, actual_error))
[email protected]99171a92014-06-03 08:44:47356
357 def testNoEatComments(self):
358 input_api = MockInputApi()
359 file_with_comments = 'file_with_comments.json'
360 contents_with_comments = ['// This is a comment.',
361 '{',
362 ' "key1": ["value1", "value2"],',
363 ' "key2": 3 // This is an inline comment.',
364 '}'
365 ]
366 file_without_comments = 'file_without_comments.json'
367 contents_without_comments = ['{',
368 ' "key1": ["value1", "value2"],',
369 ' "key2": 3',
370 '}'
371 ]
372 input_api.files = [MockFile(file_with_comments, contents_with_comments),
373 MockFile(file_without_comments,
374 contents_without_comments)]
375
376 self.assertEqual('No JSON object could be decoded',
377 str(PRESUBMIT._GetJSONParseError(input_api,
378 file_with_comments,
379 eat_comments=False)))
380 self.assertEqual(None,
381 PRESUBMIT._GetJSONParseError(input_api,
382 file_without_comments,
383 eat_comments=False))
384
385
386class IDLParsingTest(unittest.TestCase):
387 def testSuccess(self):
388 input_api = MockInputApi()
389 filename = 'valid_idl_basics.idl'
390 contents = ['// Tests a valid IDL file.',
391 'namespace idl_basics {',
392 ' enum EnumType {',
393 ' name1,',
394 ' name2',
395 ' };',
396 '',
397 ' dictionary MyType1 {',
398 ' DOMString a;',
399 ' };',
400 '',
401 ' callback Callback1 = void();',
402 ' callback Callback2 = void(long x);',
403 ' callback Callback3 = void(MyType1 arg);',
404 ' callback Callback4 = void(EnumType type);',
405 '',
406 ' interface Functions {',
407 ' static void function1();',
408 ' static void function2(long x);',
409 ' static void function3(MyType1 arg);',
410 ' static void function4(Callback1 cb);',
411 ' static void function5(Callback2 cb);',
412 ' static void function6(Callback3 cb);',
413 ' static void function7(Callback4 cb);',
414 ' };',
415 '',
416 ' interface Events {',
417 ' static void onFoo1();',
418 ' static void onFoo2(long x);',
419 ' static void onFoo2(MyType1 arg);',
420 ' static void onFoo3(EnumType type);',
421 ' };',
422 '};'
423 ]
424 input_api.files = [MockFile(filename, contents)]
425 self.assertEqual(None,
426 PRESUBMIT._GetIDLParseError(input_api, filename))
427
428 def testFailure(self):
429 input_api = MockInputApi()
430 test_data = [
431 ('invalid_idl_1.idl',
432 ['//',
433 'namespace test {',
434 ' dictionary {',
435 ' DOMString s;',
436 ' };',
437 '};'],
438 'Unexpected "{" after keyword "dictionary".\n'),
439 # TODO(yoz): Disabled because it causes the IDL parser to hang.
440 # See crbug.com/363830.
441 # ('invalid_idl_2.idl',
442 # (['namespace test {',
443 # ' dictionary MissingSemicolon {',
444 # ' DOMString a',
445 # ' DOMString b;',
446 # ' };',
447 # '};'],
448 # 'Unexpected symbol DOMString after symbol a.'),
449 ('invalid_idl_3.idl',
450 ['//',
451 'namespace test {',
452 ' enum MissingComma {',
453 ' name1',
454 ' name2',
455 ' };',
456 '};'],
457 'Unexpected symbol name2 after symbol name1.'),
458 ('invalid_idl_4.idl',
459 ['//',
460 'namespace test {',
461 ' enum TrailingComma {',
462 ' name1,',
463 ' name2,',
464 ' };',
465 '};'],
466 'Trailing comma in block.'),
467 ('invalid_idl_5.idl',
468 ['//',
469 'namespace test {',
470 ' callback Callback1 = void(;',
471 '};'],
472 'Unexpected ";" after "(".'),
473 ('invalid_idl_6.idl',
474 ['//',
475 'namespace test {',
476 ' callback Callback1 = void(long );',
477 '};'],
478 'Unexpected ")" after symbol long.'),
479 ('invalid_idl_7.idl',
480 ['//',
481 'namespace test {',
482 ' interace Events {',
483 ' static void onFoo1();',
484 ' };',
485 '};'],
486 'Unexpected symbol Events after symbol interace.'),
487 ('invalid_idl_8.idl',
488 ['//',
489 'namespace test {',
490 ' interface NotEvent {',
491 ' static void onFoo1();',
492 ' };',
493 '};'],
494 'Did not process Interface Interface(NotEvent)'),
495 ('invalid_idl_9.idl',
496 ['//',
497 'namespace test {',
498 ' interface {',
499 ' static void function1();',
500 ' };',
501 '};'],
502 'Interface missing name.'),
503 ]
504
505 input_api.files = [MockFile(filename, contents)
506 for (filename, contents, _) in test_data]
507
508 for (filename, _, expected_error) in test_data:
509 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
510 self.assertTrue(expected_error in str(actual_error),
511 "'%s' not found in '%s'" % (expected_error, actual_error))
512
513
[email protected]0bb112362014-07-26 04:38:32514class TryServerMasterTest(unittest.TestCase):
515 def testTryServerMasters(self):
516 bots = {
tandriie5587792016-07-14 00:34:50517 'master.tryserver.chromium.android': [
jbudorick3ae7a772016-05-20 02:36:04518 'android_archive_rel_ng',
519 'android_arm64_dbg_recipe',
520 'android_blink_rel',
521 'android_chromium_variable',
522 'android_chromium_variable_archive',
523 'android_chromium_variable_arm64',
524 'android_chromium_variable_cast_shell',
525 'android_chromium_variable_clang',
526 'android_chromium_variable_gn',
527 'android_chromium_variable_nexus4',
528 'android_clang_dbg_recipe',
529 'android_compile_dbg',
530 'android_compile_mips_dbg',
jbudorick3ae7a772016-05-20 02:36:04531 'android_compile_x64_dbg',
532 'android_compile_x86_dbg',
533 'android_coverage',
534 'android_cronet_tester'
535 'android_swarming_rel',
536 'cast_shell_android',
537 'linux_android_dbg_ng',
538 'linux_android_rel_ng',
539 ],
tandriie5587792016-07-14 00:34:50540 'master.tryserver.chromium.mac': [
[email protected]0bb112362014-07-26 04:38:32541 'ios_dbg_simulator',
542 'ios_rel_device',
543 'ios_rel_device_ninja',
544 'mac_asan',
545 'mac_asan_64',
546 'mac_chromium_compile_dbg',
547 'mac_chromium_compile_rel',
548 'mac_chromium_dbg',
549 'mac_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32550 'mac_nacl_sdk',
551 'mac_nacl_sdk_build',
552 'mac_rel_naclmore',
[email protected]0bb112362014-07-26 04:38:32553 'mac_x64_rel',
554 'mac_xcodebuild',
555 ],
tandriie5587792016-07-14 00:34:50556 'master.tryserver.chromium.linux': [
[email protected]0bb112362014-07-26 04:38:32557 'chromium_presubmit',
558 'linux_arm_cross_compile',
559 'linux_arm_tester',
[email protected]0bb112362014-07-26 04:38:32560 'linux_chromeos_asan',
561 'linux_chromeos_browser_asan',
562 'linux_chromeos_valgrind',
[email protected]0bb112362014-07-26 04:38:32563 'linux_chromium_chromeos_dbg',
564 'linux_chromium_chromeos_rel',
[email protected]0bb112362014-07-26 04:38:32565 'linux_chromium_compile_dbg',
566 'linux_chromium_compile_rel',
567 'linux_chromium_dbg',
568 'linux_chromium_gn_dbg',
569 'linux_chromium_gn_rel',
570 'linux_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32571 'linux_chromium_trusty32_dbg',
572 'linux_chromium_trusty32_rel',
573 'linux_chromium_trusty_dbg',
574 'linux_chromium_trusty_rel',
575 'linux_clang_tsan',
576 'linux_ecs_ozone',
577 'linux_layout',
578 'linux_layout_asan',
579 'linux_layout_rel',
580 'linux_layout_rel_32',
581 'linux_nacl_sdk',
582 'linux_nacl_sdk_bionic',
583 'linux_nacl_sdk_bionic_build',
584 'linux_nacl_sdk_build',
585 'linux_redux',
586 'linux_rel_naclmore',
587 'linux_rel_precise32',
588 'linux_valgrind',
589 'tools_build_presubmit',
590 ],
tandriie5587792016-07-14 00:34:50591 'master.tryserver.chromium.win': [
[email protected]0bb112362014-07-26 04:38:32592 'win8_aura',
593 'win8_chromium_dbg',
594 'win8_chromium_rel',
595 'win_chromium_compile_dbg',
596 'win_chromium_compile_rel',
597 'win_chromium_dbg',
598 'win_chromium_rel',
599 'win_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32600 'win_chromium_x64_dbg',
601 'win_chromium_x64_rel',
[email protected]0bb112362014-07-26 04:38:32602 'win_nacl_sdk',
603 'win_nacl_sdk_build',
604 'win_rel_naclmore',
605 ],
606 }
607 for master, bots in bots.iteritems():
608 for bot in bots:
609 self.assertEqual(master, PRESUBMIT.GetTryServerMasterForBot(bot),
610 'bot=%s: expected %s, computed %s' % (
611 bot, master, PRESUBMIT.GetTryServerMasterForBot(bot)))
612
613
davileene0426252015-03-02 21:10:41614class UserMetricsActionTest(unittest.TestCase):
615 def testUserMetricsActionInActions(self):
616 input_api = MockInputApi()
617 file_with_user_action = 'file_with_user_action.cc'
618 contents_with_user_action = [
619 'base::UserMetricsAction("AboutChrome")'
620 ]
621
622 input_api.files = [MockFile(file_with_user_action,
623 contents_with_user_action)]
624
625 self.assertEqual(
626 [], PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi()))
627
628
629 def testUserMetricsActionNotAddedToActions(self):
630 input_api = MockInputApi()
631 file_with_user_action = 'file_with_user_action.cc'
632 contents_with_user_action = [
633 'base::UserMetricsAction("NotInActionsXml")'
634 ]
635
636 input_api.files = [MockFile(file_with_user_action,
637 contents_with_user_action)]
638
639 output = PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi())
640 self.assertEqual(
641 ('File %s line %d: %s is missing in '
642 'tools/metrics/actions/actions.xml. Please run '
643 'tools/metrics/actions/extract_actions.py to update.'
644 % (file_with_user_action, 1, 'NotInActionsXml')),
645 output[0].message)
646
647
agrievef32bcc72016-04-04 14:57:40648class PydepsNeedsUpdatingTest(unittest.TestCase):
649
650 class MockSubprocess(object):
651 CalledProcessError = subprocess.CalledProcessError
652
653 def setUp(self):
654 mock_all_pydeps = ['A.pydeps', 'B.pydeps']
655 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
656 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
657 self.mock_input_api = MockInputApi()
658 self.mock_output_api = MockOutputApi()
659 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
660 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
661 self.checker._file_cache = {
662 'A.pydeps': '# Generated by:\n# CMD A\nA.py\nC.py\n',
663 'B.pydeps': '# Generated by:\n# CMD B\nB.py\nC.py\n',
664 }
665
666 def tearDown(self):
667 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
668
669 def _RunCheck(self):
670 return PRESUBMIT._CheckPydepsNeedsUpdating(self.mock_input_api,
671 self.mock_output_api,
672 checker_for_tests=self.checker)
673
674 def testAddedPydep(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('new.pydeps', [], action='A'),
681 ]
682
Zhiling Huang45cabf32018-03-10 00:50:03683 self.mock_input_api.CreateMockFileInPath(
684 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
685 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40686 results = self._RunCheck()
687 self.assertEqual(1, len(results))
688 self.assertTrue('PYDEPS_FILES' in str(results[0]))
689
Zhiling Huang45cabf32018-03-10 00:50:03690 def testPydepNotInSrc(self):
691 self.mock_input_api.files = [
692 MockAffectedFile('new.pydeps', [], action='A'),
693 ]
694 self.mock_input_api.CreateMockFileInPath([])
695 results = self._RunCheck()
696 self.assertEqual(0, len(results))
697
agrievef32bcc72016-04-04 14:57:40698 def testRemovedPydep(self):
pastarmovj89f7ee12016-09-20 14:58:13699 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
700 if self.mock_input_api.platform != 'linux2':
701 return []
702
agrievef32bcc72016-04-04 14:57:40703 self.mock_input_api.files = [
704 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
705 ]
Zhiling Huang45cabf32018-03-10 00:50:03706 self.mock_input_api.CreateMockFileInPath(
707 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
708 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40709 results = self._RunCheck()
710 self.assertEqual(1, len(results))
711 self.assertTrue('PYDEPS_FILES' in str(results[0]))
712
713 def testRandomPyIgnored(self):
pastarmovj89f7ee12016-09-20 14:58:13714 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
715 if self.mock_input_api.platform != 'linux2':
716 return []
717
agrievef32bcc72016-04-04 14:57:40718 self.mock_input_api.files = [
719 MockAffectedFile('random.py', []),
720 ]
721
722 results = self._RunCheck()
723 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
724
725 def testRelevantPyNoChange(self):
pastarmovj89f7ee12016-09-20 14:58:13726 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
727 if self.mock_input_api.platform != 'linux2':
728 return []
729
agrievef32bcc72016-04-04 14:57:40730 self.mock_input_api.files = [
731 MockAffectedFile('A.py', []),
732 ]
733
John Budorickab2fa102017-10-06 16:59:49734 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40735 self.assertEqual('CMD A --output ""', cmd)
736 return self.checker._file_cache['A.pydeps']
737
738 self.mock_input_api.subprocess.check_output = mock_check_output
739
740 results = self._RunCheck()
741 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
742
743 def testRelevantPyOneChange(self):
pastarmovj89f7ee12016-09-20 14:58:13744 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
745 if self.mock_input_api.platform != 'linux2':
746 return []
747
agrievef32bcc72016-04-04 14:57:40748 self.mock_input_api.files = [
749 MockAffectedFile('A.py', []),
750 ]
751
John Budorickab2fa102017-10-06 16:59:49752 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40753 self.assertEqual('CMD A --output ""', cmd)
754 return 'changed data'
755
756 self.mock_input_api.subprocess.check_output = mock_check_output
757
758 results = self._RunCheck()
759 self.assertEqual(1, len(results))
760 self.assertTrue('File is stale' in str(results[0]))
761
762 def testRelevantPyTwoChanges(self):
pastarmovj89f7ee12016-09-20 14:58:13763 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
764 if self.mock_input_api.platform != 'linux2':
765 return []
766
agrievef32bcc72016-04-04 14:57:40767 self.mock_input_api.files = [
768 MockAffectedFile('C.py', []),
769 ]
770
John Budorickab2fa102017-10-06 16:59:49771 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40772 return 'changed data'
773
774 self.mock_input_api.subprocess.check_output = mock_check_output
775
776 results = self._RunCheck()
777 self.assertEqual(2, len(results))
778 self.assertTrue('File is stale' in str(results[0]))
779 self.assertTrue('File is stale' in str(results[1]))
780
Daniel Bratell8ba52722018-03-02 16:06:14781class IncludeGuardTest(unittest.TestCase):
782 def testIncludeGuardChecks(self):
783 mock_input_api = MockInputApi()
784 mock_output_api = MockOutputApi()
785 mock_input_api.files = [
786 MockAffectedFile('content/browser/thing/foo.h', [
787 '// Comment',
788 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
789 '#define CONTENT_BROWSER_THING_FOO_H_',
790 'struct McBoatFace;',
791 '#endif // CONTENT_BROWSER_THING_FOO_H_',
792 ]),
793 MockAffectedFile('content/browser/thing/bar.h', [
794 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
795 '#define CONTENT_BROWSER_THING_BAR_H_',
796 'namespace content {',
797 '#endif // CONTENT_BROWSER_THING_BAR_H_',
798 '} // namespace content',
799 ]),
800 MockAffectedFile('content/browser/test1.h', [
801 'namespace content {',
802 '} // namespace content',
803 ]),
804 MockAffectedFile('content\\browser\\win.h', [
805 '#ifndef CONTENT_BROWSER_WIN_H_',
806 '#define CONTENT_BROWSER_WIN_H_',
807 'struct McBoatFace;',
808 '#endif // CONTENT_BROWSER_WIN_H_',
809 ]),
810 MockAffectedFile('content/browser/test2.h', [
811 '// Comment',
812 '#ifndef CONTENT_BROWSER_TEST2_H_',
813 'struct McBoatFace;',
814 '#endif // CONTENT_BROWSER_TEST2_H_',
815 ]),
816 MockAffectedFile('content/browser/internal.h', [
817 '// Comment',
818 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
819 '#define CONTENT_BROWSER_INTERNAL_H_',
820 '// Comment',
821 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
822 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
823 'namespace internal {',
824 '} // namespace internal',
825 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
826 'namespace content {',
827 '} // namespace content',
828 '#endif // CONTENT_BROWSER_THING_BAR_H_',
829 ]),
830 MockAffectedFile('content/browser/thing/foo.cc', [
831 '// This is a non-header.',
832 ]),
833 MockAffectedFile('content/browser/disabled.h', [
834 '// no-include-guard-because-multiply-included',
835 'struct McBoatFace;',
836 ]),
837 # New files don't allow misspelled include guards.
838 MockAffectedFile('content/browser/spleling.h', [
839 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
840 '#define CONTENT_BROWSER_SPLLEING_H_',
841 'struct McBoatFace;',
842 '#endif // CONTENT_BROWSER_SPLLEING_H_',
843 ]),
844 # Old files allow misspelled include guards (for now).
845 MockAffectedFile('chrome/old.h', [
846 '// New contents',
847 '#ifndef CHROME_ODL_H_',
848 '#define CHROME_ODL_H_',
849 '#endif // CHROME_ODL_H_',
850 ], [
851 '// Old contents',
852 '#ifndef CHROME_ODL_H_',
853 '#define CHROME_ODL_H_',
854 '#endif // CHROME_ODL_H_',
855 ]),
856 # Using a Blink style include guard outside Blink is wrong.
857 MockAffectedFile('content/NotInBlink.h', [
858 '#ifndef NotInBlink_h',
859 '#define NotInBlink_h',
860 'struct McBoatFace;',
861 '#endif // NotInBlink_h',
862 ]),
863 # Using a Blink style include guard in Blink is ok for now.
864 MockAffectedFile('third_party/WebKit/InBlink.h', [
865 '#ifndef InBlink_h',
866 '#define InBlink_h',
867 'struct McBoatFace;',
868 '#endif // InBlink_h',
869 ]),
870 # Using a bad include guard in Blink is not ok.
871 MockAffectedFile('third_party/WebKit/AlsoInBlink.h', [
872 '#ifndef WrongInBlink_h',
873 '#define WrongInBlink_h',
874 'struct McBoatFace;',
875 '#endif // WrongInBlink_h',
876 ]),
877 # Using a bad include guard in Blink is accepted if it's an old file.
878 MockAffectedFile('third_party/WebKit/StillInBlink.h', [
879 '// New contents',
880 '#ifndef AcceptedInBlink_h',
881 '#define AcceptedInBlink_h',
882 'struct McBoatFace;',
883 '#endif // AcceptedInBlink_h',
884 ], [
885 '// Old contents',
886 '#ifndef AcceptedInBlink_h',
887 '#define AcceptedInBlink_h',
888 'struct McBoatFace;',
889 '#endif // AcceptedInBlink_h',
890 ]),
891 ]
892 msgs = PRESUBMIT._CheckForIncludeGuards(
893 mock_input_api, mock_output_api)
894 expected_fail_count = 6
895 self.assertEqual(expected_fail_count, len(msgs),
896 'Expected %d items, found %d: %s'
897 % (expected_fail_count, len(msgs), msgs))
898 self.assertEqual(msgs[0].items, [ 'content/browser/thing/bar.h' ])
899 self.assertEqual(msgs[0].message,
900 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
901 'not covering the whole file')
902
903 self.assertEqual(msgs[1].items, [ 'content/browser/test1.h' ])
904 self.assertEqual(msgs[1].message,
905 'Missing include guard CONTENT_BROWSER_TEST1_H_')
906
907 self.assertEqual(msgs[2].items, [ 'content/browser/test2.h:3' ])
908 self.assertEqual(msgs[2].message,
909 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
910 'include guard')
911
912 self.assertEqual(msgs[3].items, [ 'content/browser/spleling.h:1' ])
913 self.assertEqual(msgs[3].message,
914 'Header using the wrong include guard name '
915 'CONTENT_BROWSER_SPLLEING_H_')
916
917 self.assertEqual(msgs[4].items, [ 'content/NotInBlink.h:1' ])
918 self.assertEqual(msgs[4].message,
919 'Header using the wrong include guard name '
920 'NotInBlink_h')
921
922 self.assertEqual(msgs[5].items, [ 'third_party/WebKit/AlsoInBlink.h:1' ])
923 self.assertEqual(msgs[5].message,
924 'Header using the wrong include guard name '
925 'WrongInBlink_h')
926
yolandyan45001472016-12-21 21:12:42927class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
928 def testCheckAndroidTestAnnotationUsage(self):
929 mock_input_api = MockInputApi()
930 mock_output_api = MockOutputApi()
931
932 mock_input_api.files = [
933 MockAffectedFile('LalaLand.java', [
934 'random stuff'
935 ]),
936 MockAffectedFile('CorrectUsage.java', [
937 'import android.support.test.filters.LargeTest;',
938 'import android.support.test.filters.MediumTest;',
939 'import android.support.test.filters.SmallTest;',
940 ]),
941 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
942 'import android.test.suitebuilder.annotation.LargeTest;',
943 ]),
944 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
945 'import android.test.suitebuilder.annotation.MediumTest;',
946 ]),
947 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
948 'import android.test.suitebuilder.annotation.SmallTest;',
949 ]),
950 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
951 'import android.test.suitebuilder.annotation.Smoke;',
952 ])
953 ]
954 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
955 mock_input_api, mock_output_api)
956 self.assertEqual(1, len(msgs),
957 'Expected %d items, found %d: %s'
958 % (1, len(msgs), msgs))
959 self.assertEqual(4, len(msgs[0].items),
960 'Expected %d items, found %d: %s'
961 % (4, len(msgs[0].items), msgs[0].items))
962 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
963 'UsedDeprecatedLargeTestAnnotation not found in errors')
964 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
965 in msgs[0].items,
966 'UsedDeprecatedMediumTestAnnotation not found in errors')
967 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
968 'UsedDeprecatedSmallTestAnnotation not found in errors')
969 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
970 'UsedDeprecatedSmokeAnnotation not found in errors')
971
Yoland Yanb92fa522017-08-28 17:37:06972class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
973 def testCheckAndroidTestAnnotationUsage(self):
974 mock_input_api = MockInputApi()
975 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:42976
Yoland Yanb92fa522017-08-28 17:37:06977 mock_input_api.files = [
978 MockAffectedFile('LalaLand.java', [
979 'random stuff'
980 ]),
981 MockAffectedFile('CorrectUsage.java', [
982 'import org.junit.ABC',
983 'import org.junit.XYZ;',
984 ]),
985 MockAffectedFile('UsedDeprecatedJUnit.java', [
986 'import junit.framework.*;',
987 ]),
988 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
989 'import junit.framework.Assert;',
990 ]),
991 ]
992 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
993 mock_input_api, mock_output_api)
994 self.assertEqual(1, len(msgs),
995 'Expected %d items, found %d: %s'
996 % (1, len(msgs), msgs))
997 self.assertEqual(2, len(msgs[0].items),
998 'Expected %d items, found %d: %s'
999 % (2, len(msgs[0].items), msgs[0].items))
1000 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
1001 'UsedDeprecatedJUnit.java not found in errors')
1002 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
1003 in msgs[0].items,
1004 'UsedDeprecatedJUnitAssert not found in errors')
1005
1006class AndroidJUnitBaseClass(unittest.TestCase):
1007 def testCheckAndroidTestAnnotationUsage(self):
1008 mock_input_api = MockInputApi()
1009 mock_output_api = MockOutputApi()
1010
1011 mock_input_api.files = [
1012 MockAffectedFile('LalaLand.java', [
1013 'random stuff'
1014 ]),
1015 MockAffectedFile('CorrectTest.java', [
1016 '@RunWith(ABC.class);'
1017 'public class CorrectTest {',
1018 '}',
1019 ]),
1020 MockAffectedFile('HistoricallyIncorrectTest.java', [
1021 'public class Test extends BaseCaseA {',
1022 '}',
1023 ], old_contents=[
1024 'public class Test extends BaseCaseB {',
1025 '}',
1026 ]),
1027 MockAffectedFile('CorrectTestWithInterface.java', [
1028 '@RunWith(ABC.class);'
1029 'public class CorrectTest implement Interface {',
1030 '}',
1031 ]),
1032 MockAffectedFile('IncorrectTest.java', [
1033 'public class IncorrectTest extends TestCase {',
1034 '}',
1035 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241036 MockAffectedFile('IncorrectWithInterfaceTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061037 'public class Test implements X extends BaseClass {',
1038 '}',
1039 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241040 MockAffectedFile('IncorrectMultiLineTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061041 'public class Test implements X, Y, Z',
1042 ' extends TestBase {',
1043 '}',
1044 ]),
1045 ]
1046 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1047 mock_input_api, mock_output_api)
1048 self.assertEqual(1, len(msgs),
1049 'Expected %d items, found %d: %s'
1050 % (1, len(msgs), msgs))
1051 self.assertEqual(3, len(msgs[0].items),
1052 'Expected %d items, found %d: %s'
1053 % (3, len(msgs[0].items), msgs[0].items))
1054 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1055 'IncorrectTest not found in errors')
Vaclav Brozekf01ed502018-03-16 19:38:241056 self.assertTrue('IncorrectWithInterfaceTest.java:1'
Yoland Yanb92fa522017-08-28 17:37:061057 in msgs[0].items,
Vaclav Brozekf01ed502018-03-16 19:38:241058 'IncorrectWithInterfaceTest not found in errors')
1059 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1060 'IncorrectMultiLineTest not found in errors')
yolandyan45001472016-12-21 21:12:421061
dgn4401aa52015-04-29 16:26:171062class LogUsageTest(unittest.TestCase):
1063
dgnaa68d5e2015-06-10 10:08:221064 def testCheckAndroidCrLogUsage(self):
1065 mock_input_api = MockInputApi()
1066 mock_output_api = MockOutputApi()
1067
1068 mock_input_api.files = [
1069 MockAffectedFile('RandomStuff.java', [
1070 'random stuff'
1071 ]),
dgn87d9fb62015-06-12 09:15:121072 MockAffectedFile('HasAndroidLog.java', [
1073 'import android.util.Log;',
1074 'some random stuff',
1075 'Log.d("TAG", "foo");',
1076 ]),
1077 MockAffectedFile('HasExplicitUtilLog.java', [
1078 'some random stuff',
1079 'android.util.Log.d("TAG", "foo");',
1080 ]),
1081 MockAffectedFile('IsInBasePackage.java', [
1082 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511083 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121084 'Log.d(TAG, "foo");',
1085 ]),
1086 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1087 'package org.chromium.base;',
1088 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511089 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121090 'Log.d(TAG, "foo");',
1091 ]),
1092 MockAffectedFile('HasBothLog.java', [
1093 'import org.chromium.base.Log;',
1094 'some random stuff',
dgn38736db2015-09-18 19:20:511095 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121096 'Log.d(TAG, "foo");',
1097 'android.util.Log.d("TAG", "foo");',
1098 ]),
dgnaa68d5e2015-06-10 10:08:221099 MockAffectedFile('HasCorrectTag.java', [
1100 'import org.chromium.base.Log;',
1101 'some random stuff',
dgn38736db2015-09-18 19:20:511102 'private static final String TAG = "cr_Foo";',
1103 'Log.d(TAG, "foo");',
1104 ]),
1105 MockAffectedFile('HasOldTag.java', [
1106 'import org.chromium.base.Log;',
1107 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221108 'private static final String TAG = "cr.Foo";',
1109 'Log.d(TAG, "foo");',
1110 ]),
dgn38736db2015-09-18 19:20:511111 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221112 'import org.chromium.base.Log;',
1113 'some random stuff',
dgn38736db2015-09-18 19:20:511114 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221115 'Log.d(TAG, "foo");',
1116 ]),
1117 MockAffectedFile('HasNoTagDecl.java', [
1118 'import org.chromium.base.Log;',
1119 'some random stuff',
1120 'Log.d(TAG, "foo");',
1121 ]),
1122 MockAffectedFile('HasIncorrectTagDecl.java', [
1123 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511124 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221125 'some random stuff',
1126 'Log.d(TAG, "foo");',
1127 ]),
1128 MockAffectedFile('HasInlineTag.java', [
1129 'import org.chromium.base.Log;',
1130 'some random stuff',
dgn38736db2015-09-18 19:20:511131 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221132 'Log.d("TAG", "foo");',
1133 ]),
dgn38736db2015-09-18 19:20:511134 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221135 'import org.chromium.base.Log;',
1136 'some random stuff',
1137 'private static final String TAG = "rubbish";',
1138 'Log.d(TAG, "foo");',
1139 ]),
1140 MockAffectedFile('HasTooLongTag.java', [
1141 'import org.chromium.base.Log;',
1142 'some random stuff',
dgn38736db2015-09-18 19:20:511143 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:221144 'Log.d(TAG, "foo");',
1145 ]),
1146 ]
1147
1148 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1149 mock_input_api, mock_output_api)
1150
dgn38736db2015-09-18 19:20:511151 self.assertEqual(5, len(msgs),
1152 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221153
1154 # Declaration format
dgn38736db2015-09-18 19:20:511155 nb = len(msgs[0].items)
1156 self.assertEqual(2, nb,
1157 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221158 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1159 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221160
1161 # Tag length
dgn38736db2015-09-18 19:20:511162 nb = len(msgs[1].items)
1163 self.assertEqual(1, nb,
1164 'Expected %d items, found %d: %s' % (1, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:221165 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
1166
1167 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511168 nb = len(msgs[2].items)
1169 self.assertEqual(1, nb,
1170 'Expected %d items, found %d: %s' % (1, nb, msgs[2].items))
dgnaa68d5e2015-06-10 10:08:221171 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
1172
dgn87d9fb62015-06-12 09:15:121173 # Util Log usage
dgn38736db2015-09-18 19:20:511174 nb = len(msgs[3].items)
1175 self.assertEqual(2, nb,
1176 'Expected %d items, found %d: %s' % (2, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:121177 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
1178 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:221179
dgn38736db2015-09-18 19:20:511180 # Tag must not contain
1181 nb = len(msgs[4].items)
1182 self.assertEqual(2, nb,
1183 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1184 self.assertTrue('HasDottedTag.java' in msgs[4].items)
1185 self.assertTrue('HasOldTag.java' in msgs[4].items)
1186
estadee17314a02017-01-12 16:22:161187class GoogleAnswerUrlFormatTest(unittest.TestCase):
1188
1189 def testCatchAnswerUrlId(self):
1190 input_api = MockInputApi()
1191 input_api.files = [
1192 MockFile('somewhere/file.cc',
1193 ['char* host = '
1194 ' "https://support.google.com/chrome/answer/123456";']),
1195 MockFile('somewhere_else/file.cc',
1196 ['char* host = '
1197 ' "https://support.google.com/chrome/a/answer/123456";']),
1198 ]
1199
1200 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1201 input_api, MockOutputApi())
1202 self.assertEqual(1, len(warnings))
1203 self.assertEqual(2, len(warnings[0].items))
1204
1205 def testAllowAnswerUrlParam(self):
1206 input_api = MockInputApi()
1207 input_api.files = [
1208 MockFile('somewhere/file.cc',
1209 ['char* host = '
1210 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1211 ]
1212
1213 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1214 input_api, MockOutputApi())
1215 self.assertEqual(0, len(warnings))
1216
reillyi38965732015-11-16 18:27:331217class HardcodedGoogleHostsTest(unittest.TestCase):
1218
1219 def testWarnOnAssignedLiterals(self):
1220 input_api = MockInputApi()
1221 input_api.files = [
1222 MockFile('content/file.cc',
1223 ['char* host = "https://www.google.com";']),
1224 MockFile('content/file.cc',
1225 ['char* host = "https://www.googleapis.com";']),
1226 MockFile('content/file.cc',
1227 ['char* host = "https://clients1.google.com";']),
1228 ]
1229
1230 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1231 input_api, MockOutputApi())
1232 self.assertEqual(1, len(warnings))
1233 self.assertEqual(3, len(warnings[0].items))
1234
1235 def testAllowInComment(self):
1236 input_api = MockInputApi()
1237 input_api.files = [
1238 MockFile('content/file.cc',
1239 ['char* host = "https://www.aol.com"; // google.com'])
1240 ]
1241
1242 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1243 input_api, MockOutputApi())
1244 self.assertEqual(0, len(warnings))
1245
dgn4401aa52015-04-29 16:26:171246
jbriance9e12f162016-11-25 07:57:501247class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311248 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501249 mock_input_api = MockInputApi()
1250 mock_input_api.files = [
1251 MockAffectedFile('somewhere/file.cc', [
1252 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311253 ]),
1254 MockAffectedFile('third_party/header.h', [
1255 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501256 ])
1257 ]
1258 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1259 MockOutputApi())
1260 self.assertEqual(0, len(warnings))
1261
1262 def testNoNestedDeclaration(self):
1263 mock_input_api = MockInputApi()
1264 mock_input_api.files = [
1265 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311266 'class SomeClass {',
1267 ' protected:',
1268 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501269 '};'
1270 ])
1271 ]
1272 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1273 MockOutputApi())
1274 self.assertEqual(0, len(warnings))
1275
1276 def testSubStrings(self):
1277 mock_input_api = MockInputApi()
1278 mock_input_api.files = [
1279 MockAffectedFile('somewhere/header.h', [
1280 'class NotUsefulClass;',
1281 'struct SomeStruct;',
1282 'UsefulClass *p1;',
1283 'SomeStructPtr *p2;'
1284 ])
1285 ]
1286 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1287 MockOutputApi())
1288 self.assertEqual(2, len(warnings))
1289
1290 def testUselessForwardDeclaration(self):
1291 mock_input_api = MockInputApi()
1292 mock_input_api.files = [
1293 MockAffectedFile('somewhere/header.h', [
1294 'class DummyClass;',
1295 'struct DummyStruct;',
1296 'class UsefulClass;',
1297 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311298 ])
jbriance9e12f162016-11-25 07:57:501299 ]
1300 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1301 MockOutputApi())
1302 self.assertEqual(2, len(warnings))
1303
jbriance2c51e821a2016-12-12 08:24:311304 def testBlinkHeaders(self):
1305 mock_input_api = MockInputApi()
1306 mock_input_api.files = [
1307 MockAffectedFile('third_party/WebKit/header.h', [
1308 'class DummyClass;',
1309 'struct DummyStruct;',
1310 ]),
1311 MockAffectedFile('third_party\\WebKit\\header.h', [
1312 'class DummyClass;',
1313 'struct DummyStruct;',
1314 ])
1315 ]
1316 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1317 MockOutputApi())
1318 self.assertEqual(4, len(warnings))
1319
jbriance9e12f162016-11-25 07:57:501320
dbeam1ec68ac2016-12-15 05:22:241321class RiskyJsTest(unittest.TestCase):
1322 def testArrowWarnInIos9Code(self):
1323 mock_input_api = MockInputApi()
1324 mock_output_api = MockOutputApi()
1325
1326 mock_input_api.files = [
1327 MockAffectedFile('components/blah.js', ["shouldn't use => here"]),
1328 ]
1329 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1330 mock_input_api, mock_output_api)
1331 self.assertEqual(1, len(warnings))
1332
1333 mock_input_api.files = [
1334 MockAffectedFile('ios/blee.js', ['might => break folks']),
1335 ]
1336 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1337 mock_input_api, mock_output_api)
1338 self.assertEqual(1, len(warnings))
1339
1340 mock_input_api.files = [
1341 MockAffectedFile('ui/webui/resources/blarg.js', ['on => iOS9']),
1342 ]
1343 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1344 mock_input_api, mock_output_api)
1345 self.assertEqual(1, len(warnings))
1346
1347 def testArrowsAllowedInChromeCode(self):
1348 mock_input_api = MockInputApi()
1349 mock_input_api.files = [
1350 MockAffectedFile('chrome/browser/resources/blah.js', 'arrow => OK here'),
1351 ]
1352 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1353 mock_input_api, MockOutputApi())
1354 self.assertEqual(0, len(warnings))
1355
dpapadd651231d82017-07-21 02:44:471356 def testConstLetWarningIos9Code(self):
1357 mock_input_api = MockInputApi()
1358 mock_output_api = MockOutputApi()
1359
1360 mock_input_api.files = [
1361 MockAffectedFile('components/blah.js', [" const foo = 'bar';"]),
1362 MockAffectedFile('ui/webui/resources/blah.js', [" let foo = 3;"]),
1363 ]
1364 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1365 mock_input_api, mock_output_api)
1366 self.assertEqual(2, len(warnings))
1367
rlanday6802cf632017-05-30 17:48:361368class RelativeIncludesTest(unittest.TestCase):
1369 def testThirdPartyNotWebKitIgnored(self):
1370 mock_input_api = MockInputApi()
1371 mock_input_api.files = [
1372 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1373 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1374 ]
1375
1376 mock_output_api = MockOutputApi()
1377
1378 errors = PRESUBMIT._CheckForRelativeIncludes(
1379 mock_input_api, mock_output_api)
1380 self.assertEqual(0, len(errors))
1381
1382 def testNonCppFileIgnored(self):
1383 mock_input_api = MockInputApi()
1384 mock_input_api.files = [
1385 MockAffectedFile('test.py', '#include "../header.h"'),
1386 ]
1387
1388 mock_output_api = MockOutputApi()
1389
1390 errors = PRESUBMIT._CheckForRelativeIncludes(
1391 mock_input_api, mock_output_api)
1392 self.assertEqual(0, len(errors))
1393
1394 def testInnocuousChangesAllowed(self):
1395 mock_input_api = MockInputApi()
1396 mock_input_api.files = [
1397 MockAffectedFile('test.cpp', '#include "header.h"'),
1398 MockAffectedFile('test2.cpp', '../'),
1399 ]
1400
1401 mock_output_api = MockOutputApi()
1402
1403 errors = PRESUBMIT._CheckForRelativeIncludes(
1404 mock_input_api, mock_output_api)
1405 self.assertEqual(0, len(errors))
1406
1407 def testRelativeIncludeNonWebKitProducesError(self):
1408 mock_input_api = MockInputApi()
1409 mock_input_api.files = [
1410 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1411 ]
1412
1413 mock_output_api = MockOutputApi()
1414
1415 errors = PRESUBMIT._CheckForRelativeIncludes(
1416 mock_input_api, mock_output_api)
1417 self.assertEqual(1, len(errors))
1418
1419 def testRelativeIncludeWebKitProducesError(self):
1420 mock_input_api = MockInputApi()
1421 mock_input_api.files = [
1422 MockAffectedFile('third_party/WebKit/test.cpp',
1423 ['#include "../header.h']),
1424 ]
1425
1426 mock_output_api = MockOutputApi()
1427
1428 errors = PRESUBMIT._CheckForRelativeIncludes(
1429 mock_input_api, mock_output_api)
1430 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241431
Daniel Cheng13ca61a882017-08-25 15:11:251432
1433class MojoManifestOwnerTest(unittest.TestCase):
1434 def testMojoManifestChangeNeedsSecurityOwner(self):
1435 mock_input_api = MockInputApi()
1436 mock_input_api.files = [
1437 MockAffectedFile('services/goat/manifest.json',
1438 [
1439 '{',
1440 ' "name": "teleporter",',
1441 ' "display_name": "Goat Teleporter",'
1442 ' "interface_provider_specs": {',
1443 ' }',
1444 '}',
1445 ])
1446 ]
1447 mock_output_api = MockOutputApi()
1448 errors = PRESUBMIT._CheckIpcOwners(
1449 mock_input_api, mock_output_api)
1450 self.assertEqual(1, len(errors))
1451 self.assertEqual(
1452 'Found OWNERS files that need to be updated for IPC security review ' +
1453 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
1454
1455 # No warning if already covered by an OWNERS rule.
1456
1457 def testNonManifestChangesDoNotRequireSecurityOwner(self):
1458 mock_input_api = MockInputApi()
1459 mock_input_api.files = [
1460 MockAffectedFile('services/goat/species.json',
1461 [
1462 '[',
1463 ' "anglo-nubian",',
1464 ' "angora"',
1465 ']',
1466 ])
1467 ]
1468 mock_output_api = MockOutputApi()
1469 errors = PRESUBMIT._CheckIpcOwners(
1470 mock_input_api, mock_output_api)
1471 self.assertEqual([], errors)
1472
1473
Miguel Casas-Sancheze0d46d42017-12-14 15:52:191474class CrbugUrlFormatTest(unittest.TestCase):
1475
1476 def testCheckCrbugLinksHaveHttps(self):
1477 input_api = MockInputApi()
1478 input_api.files = [
1479 MockFile('somewhere/file.cc',
1480 ['// TODO(developer): crbug.com should be linkified',
1481 '// TODO(developer): (crbug.com) should be linkified',
1482 '// TODO(developer): crbug/123 should be well formed',
1483 '// TODO(developer): http://crbug.com it\'s OK',
Miguel Casas68bdb652017-12-19 16:29:091484 '// TODO(developer): https://crbug.com is just great',
1485 '// TODO(crbug.com/123456): this pattern it\'s also OK']),
Miguel Casas-Sancheze0d46d42017-12-14 15:52:191486 ]
1487
1488 warnings = PRESUBMIT._CheckCrbugLinksHaveHttps(input_api, MockOutputApi())
1489 self.assertEqual(1, len(warnings))
Miguel Casas68bdb652017-12-19 16:29:091490 self.assertEqual(3, warnings[0].message.count('\n'));
Miguel Casas-Sancheze0d46d42017-12-14 15:52:191491
1492
Sylvain Defresnea8b73d252018-02-28 15:45:541493class BannedFunctionCheckTest(unittest.TestCase):
1494
1495 def testBannedIosObcjFunctions(self):
1496 input_api = MockInputApi()
1497 input_api.files = [
1498 MockFile('some/ios/file.mm',
1499 ['TEST(SomeClassTest, SomeInteraction) {',
1500 '}']),
1501 MockFile('some/mac/file.mm',
1502 ['TEST(SomeClassTest, SomeInteraction) {',
1503 '}']),
1504 MockFile('another/ios_file.mm',
1505 ['class SomeTest : public testing::Test {};']),
1506 ]
1507
1508 errors = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi())
1509 self.assertEqual(1, len(errors))
1510 self.assertTrue('some/ios/file.mm' in errors[0].message)
1511 self.assertTrue('another/ios_file.mm' in errors[0].message)
1512 self.assertTrue('some/mac/file.mm' not in errors[0].message)
1513
1514
Vaclav Brozekf01ed502018-03-16 19:38:241515class NoProductionCodeUsingTestOnlyFunctions(unittest.TestCase):
1516 def testTruePositives(self):
1517 mock_input_api = MockInputApi()
1518 mock_input_api.files = [
1519 MockFile('some/path/foo.cc', ['foo_for_testing();']),
1520 MockFile('some/path/foo.mm', ['FooForTesting();']),
1521 MockFile('some/path/foo.cxx', ['FooForTests();']),
1522 MockFile('some/path/foo.cpp', ['foo_for_test();']),
1523 ]
1524
1525 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
1526 mock_input_api, MockOutputApi())
1527 self.assertEqual(1, len(results))
1528 self.assertEqual(4, len(results[0].items))
1529 self.assertTrue('foo.cc' in results[0].items[0])
1530 self.assertTrue('foo.mm' in results[0].items[1])
1531 self.assertTrue('foo.cxx' in results[0].items[2])
1532 self.assertTrue('foo.cpp' in results[0].items[3])
1533
1534 def testFalsePositives(self):
1535 mock_input_api = MockInputApi()
1536 mock_input_api.files = [
1537 MockFile('some/path/foo.h', ['foo_for_testing();']),
1538 MockFile('some/path/foo.mm', ['FooForTesting() {']),
1539 MockFile('some/path/foo.cc', ['::FooForTests();']),
1540 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
1541 ]
1542
1543 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
1544 mock_input_api, MockOutputApi())
1545 self.assertEqual(0, len(results))
1546
1547
[email protected]2299dcf2012-11-15 19:56:241548if __name__ == '__main__':
1549 unittest.main()