blob: f8feb78f1815cae3ad31d87255002a248d82b060 [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
745
yolandyan45001472016-12-21 21:12:42746class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
747 def testCheckAndroidTestAnnotationUsage(self):
748 mock_input_api = MockInputApi()
749 mock_output_api = MockOutputApi()
750
751 mock_input_api.files = [
752 MockAffectedFile('LalaLand.java', [
753 'random stuff'
754 ]),
755 MockAffectedFile('CorrectUsage.java', [
756 'import android.support.test.filters.LargeTest;',
757 'import android.support.test.filters.MediumTest;',
758 'import android.support.test.filters.SmallTest;',
759 ]),
760 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
761 'import android.test.suitebuilder.annotation.LargeTest;',
762 ]),
763 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
764 'import android.test.suitebuilder.annotation.MediumTest;',
765 ]),
766 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
767 'import android.test.suitebuilder.annotation.SmallTest;',
768 ]),
769 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
770 'import android.test.suitebuilder.annotation.Smoke;',
771 ])
772 ]
773 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
774 mock_input_api, mock_output_api)
775 self.assertEqual(1, len(msgs),
776 'Expected %d items, found %d: %s'
777 % (1, len(msgs), msgs))
778 self.assertEqual(4, len(msgs[0].items),
779 'Expected %d items, found %d: %s'
780 % (4, len(msgs[0].items), msgs[0].items))
781 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
782 'UsedDeprecatedLargeTestAnnotation not found in errors')
783 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
784 in msgs[0].items,
785 'UsedDeprecatedMediumTestAnnotation not found in errors')
786 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
787 'UsedDeprecatedSmallTestAnnotation not found in errors')
788 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
789 'UsedDeprecatedSmokeAnnotation not found in errors')
790
791
792
dgn4401aa52015-04-29 16:26:17793class LogUsageTest(unittest.TestCase):
794
dgnaa68d5e2015-06-10 10:08:22795 def testCheckAndroidCrLogUsage(self):
796 mock_input_api = MockInputApi()
797 mock_output_api = MockOutputApi()
798
799 mock_input_api.files = [
800 MockAffectedFile('RandomStuff.java', [
801 'random stuff'
802 ]),
dgn87d9fb62015-06-12 09:15:12803 MockAffectedFile('HasAndroidLog.java', [
804 'import android.util.Log;',
805 'some random stuff',
806 'Log.d("TAG", "foo");',
807 ]),
808 MockAffectedFile('HasExplicitUtilLog.java', [
809 'some random stuff',
810 'android.util.Log.d("TAG", "foo");',
811 ]),
812 MockAffectedFile('IsInBasePackage.java', [
813 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:51814 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:12815 'Log.d(TAG, "foo");',
816 ]),
817 MockAffectedFile('IsInBasePackageButImportsLog.java', [
818 'package org.chromium.base;',
819 'import android.util.Log;',
dgn38736db2015-09-18 19:20:51820 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:12821 'Log.d(TAG, "foo");',
822 ]),
823 MockAffectedFile('HasBothLog.java', [
824 'import org.chromium.base.Log;',
825 'some random stuff',
dgn38736db2015-09-18 19:20:51826 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:12827 'Log.d(TAG, "foo");',
828 'android.util.Log.d("TAG", "foo");',
829 ]),
dgnaa68d5e2015-06-10 10:08:22830 MockAffectedFile('HasCorrectTag.java', [
831 'import org.chromium.base.Log;',
832 'some random stuff',
dgn38736db2015-09-18 19:20:51833 'private static final String TAG = "cr_Foo";',
834 'Log.d(TAG, "foo");',
835 ]),
836 MockAffectedFile('HasOldTag.java', [
837 'import org.chromium.base.Log;',
838 'some random stuff',
dgnaa68d5e2015-06-10 10:08:22839 'private static final String TAG = "cr.Foo";',
840 'Log.d(TAG, "foo");',
841 ]),
dgn38736db2015-09-18 19:20:51842 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:22843 'import org.chromium.base.Log;',
844 'some random stuff',
dgn38736db2015-09-18 19:20:51845 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:22846 'Log.d(TAG, "foo");',
847 ]),
848 MockAffectedFile('HasNoTagDecl.java', [
849 'import org.chromium.base.Log;',
850 'some random stuff',
851 'Log.d(TAG, "foo");',
852 ]),
853 MockAffectedFile('HasIncorrectTagDecl.java', [
854 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:51855 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:22856 'some random stuff',
857 'Log.d(TAG, "foo");',
858 ]),
859 MockAffectedFile('HasInlineTag.java', [
860 'import org.chromium.base.Log;',
861 'some random stuff',
dgn38736db2015-09-18 19:20:51862 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:22863 'Log.d("TAG", "foo");',
864 ]),
dgn38736db2015-09-18 19:20:51865 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:22866 'import org.chromium.base.Log;',
867 'some random stuff',
868 'private static final String TAG = "rubbish";',
869 'Log.d(TAG, "foo");',
870 ]),
871 MockAffectedFile('HasTooLongTag.java', [
872 'import org.chromium.base.Log;',
873 'some random stuff',
dgn38736db2015-09-18 19:20:51874 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:22875 'Log.d(TAG, "foo");',
876 ]),
877 ]
878
879 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
880 mock_input_api, mock_output_api)
881
dgn38736db2015-09-18 19:20:51882 self.assertEqual(5, len(msgs),
883 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:22884
885 # Declaration format
dgn38736db2015-09-18 19:20:51886 nb = len(msgs[0].items)
887 self.assertEqual(2, nb,
888 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:22889 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
890 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:22891
892 # Tag length
dgn38736db2015-09-18 19:20:51893 nb = len(msgs[1].items)
894 self.assertEqual(1, nb,
895 'Expected %d items, found %d: %s' % (1, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:22896 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
897
898 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:51899 nb = len(msgs[2].items)
900 self.assertEqual(1, nb,
901 'Expected %d items, found %d: %s' % (1, nb, msgs[2].items))
dgnaa68d5e2015-06-10 10:08:22902 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
903
dgn87d9fb62015-06-12 09:15:12904 # Util Log usage
dgn38736db2015-09-18 19:20:51905 nb = len(msgs[3].items)
906 self.assertEqual(2, nb,
907 'Expected %d items, found %d: %s' % (2, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:12908 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
909 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:22910
dgn38736db2015-09-18 19:20:51911 # Tag must not contain
912 nb = len(msgs[4].items)
913 self.assertEqual(2, nb,
914 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
915 self.assertTrue('HasDottedTag.java' in msgs[4].items)
916 self.assertTrue('HasOldTag.java' in msgs[4].items)
917
estadee17314a02017-01-12 16:22:16918class GoogleAnswerUrlFormatTest(unittest.TestCase):
919
920 def testCatchAnswerUrlId(self):
921 input_api = MockInputApi()
922 input_api.files = [
923 MockFile('somewhere/file.cc',
924 ['char* host = '
925 ' "https://support.google.com/chrome/answer/123456";']),
926 MockFile('somewhere_else/file.cc',
927 ['char* host = '
928 ' "https://support.google.com/chrome/a/answer/123456";']),
929 ]
930
931 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
932 input_api, MockOutputApi())
933 self.assertEqual(1, len(warnings))
934 self.assertEqual(2, len(warnings[0].items))
935
936 def testAllowAnswerUrlParam(self):
937 input_api = MockInputApi()
938 input_api.files = [
939 MockFile('somewhere/file.cc',
940 ['char* host = '
941 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
942 ]
943
944 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
945 input_api, MockOutputApi())
946 self.assertEqual(0, len(warnings))
947
reillyi38965732015-11-16 18:27:33948class HardcodedGoogleHostsTest(unittest.TestCase):
949
950 def testWarnOnAssignedLiterals(self):
951 input_api = MockInputApi()
952 input_api.files = [
953 MockFile('content/file.cc',
954 ['char* host = "https://www.google.com";']),
955 MockFile('content/file.cc',
956 ['char* host = "https://www.googleapis.com";']),
957 MockFile('content/file.cc',
958 ['char* host = "https://clients1.google.com";']),
959 ]
960
961 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
962 input_api, MockOutputApi())
963 self.assertEqual(1, len(warnings))
964 self.assertEqual(3, len(warnings[0].items))
965
966 def testAllowInComment(self):
967 input_api = MockInputApi()
968 input_api.files = [
969 MockFile('content/file.cc',
970 ['char* host = "https://www.aol.com"; // google.com'])
971 ]
972
973 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
974 input_api, MockOutputApi())
975 self.assertEqual(0, len(warnings))
976
dgn4401aa52015-04-29 16:26:17977
jbriance9e12f162016-11-25 07:57:50978class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:31979 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:50980 mock_input_api = MockInputApi()
981 mock_input_api.files = [
982 MockAffectedFile('somewhere/file.cc', [
983 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:31984 ]),
985 MockAffectedFile('third_party/header.h', [
986 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:50987 ])
988 ]
989 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
990 MockOutputApi())
991 self.assertEqual(0, len(warnings))
992
993 def testNoNestedDeclaration(self):
994 mock_input_api = MockInputApi()
995 mock_input_api.files = [
996 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:31997 'class SomeClass {',
998 ' protected:',
999 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501000 '};'
1001 ])
1002 ]
1003 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1004 MockOutputApi())
1005 self.assertEqual(0, len(warnings))
1006
1007 def testSubStrings(self):
1008 mock_input_api = MockInputApi()
1009 mock_input_api.files = [
1010 MockAffectedFile('somewhere/header.h', [
1011 'class NotUsefulClass;',
1012 'struct SomeStruct;',
1013 'UsefulClass *p1;',
1014 'SomeStructPtr *p2;'
1015 ])
1016 ]
1017 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1018 MockOutputApi())
1019 self.assertEqual(2, len(warnings))
1020
1021 def testUselessForwardDeclaration(self):
1022 mock_input_api = MockInputApi()
1023 mock_input_api.files = [
1024 MockAffectedFile('somewhere/header.h', [
1025 'class DummyClass;',
1026 'struct DummyStruct;',
1027 'class UsefulClass;',
1028 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311029 ])
jbriance9e12f162016-11-25 07:57:501030 ]
1031 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1032 MockOutputApi())
1033 self.assertEqual(2, len(warnings))
1034
jbriance2c51e821a2016-12-12 08:24:311035 def testBlinkHeaders(self):
1036 mock_input_api = MockInputApi()
1037 mock_input_api.files = [
1038 MockAffectedFile('third_party/WebKit/header.h', [
1039 'class DummyClass;',
1040 'struct DummyStruct;',
1041 ]),
1042 MockAffectedFile('third_party\\WebKit\\header.h', [
1043 'class DummyClass;',
1044 'struct DummyStruct;',
1045 ])
1046 ]
1047 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1048 MockOutputApi())
1049 self.assertEqual(4, len(warnings))
1050
jbriance9e12f162016-11-25 07:57:501051
dbeam1ec68ac2016-12-15 05:22:241052class RiskyJsTest(unittest.TestCase):
1053 def testArrowWarnInIos9Code(self):
1054 mock_input_api = MockInputApi()
1055 mock_output_api = MockOutputApi()
1056
1057 mock_input_api.files = [
1058 MockAffectedFile('components/blah.js', ["shouldn't use => here"]),
1059 ]
1060 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1061 mock_input_api, mock_output_api)
1062 self.assertEqual(1, len(warnings))
1063
1064 mock_input_api.files = [
1065 MockAffectedFile('ios/blee.js', ['might => break folks']),
1066 ]
1067 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1068 mock_input_api, mock_output_api)
1069 self.assertEqual(1, len(warnings))
1070
1071 mock_input_api.files = [
1072 MockAffectedFile('ui/webui/resources/blarg.js', ['on => iOS9']),
1073 ]
1074 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1075 mock_input_api, mock_output_api)
1076 self.assertEqual(1, len(warnings))
1077
1078 def testArrowsAllowedInChromeCode(self):
1079 mock_input_api = MockInputApi()
1080 mock_input_api.files = [
1081 MockAffectedFile('chrome/browser/resources/blah.js', 'arrow => OK here'),
1082 ]
1083 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1084 mock_input_api, MockOutputApi())
1085 self.assertEqual(0, len(warnings))
1086
dpapadd651231d82017-07-21 02:44:471087 def testConstLetWarningIos9Code(self):
1088 mock_input_api = MockInputApi()
1089 mock_output_api = MockOutputApi()
1090
1091 mock_input_api.files = [
1092 MockAffectedFile('components/blah.js', [" const foo = 'bar';"]),
1093 MockAffectedFile('ui/webui/resources/blah.js', [" let foo = 3;"]),
1094 ]
1095 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1096 mock_input_api, mock_output_api)
1097 self.assertEqual(2, len(warnings))
1098
rlanday6802cf632017-05-30 17:48:361099class RelativeIncludesTest(unittest.TestCase):
1100 def testThirdPartyNotWebKitIgnored(self):
1101 mock_input_api = MockInputApi()
1102 mock_input_api.files = [
1103 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1104 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1105 ]
1106
1107 mock_output_api = MockOutputApi()
1108
1109 errors = PRESUBMIT._CheckForRelativeIncludes(
1110 mock_input_api, mock_output_api)
1111 self.assertEqual(0, len(errors))
1112
1113 def testNonCppFileIgnored(self):
1114 mock_input_api = MockInputApi()
1115 mock_input_api.files = [
1116 MockAffectedFile('test.py', '#include "../header.h"'),
1117 ]
1118
1119 mock_output_api = MockOutputApi()
1120
1121 errors = PRESUBMIT._CheckForRelativeIncludes(
1122 mock_input_api, mock_output_api)
1123 self.assertEqual(0, len(errors))
1124
1125 def testInnocuousChangesAllowed(self):
1126 mock_input_api = MockInputApi()
1127 mock_input_api.files = [
1128 MockAffectedFile('test.cpp', '#include "header.h"'),
1129 MockAffectedFile('test2.cpp', '../'),
1130 ]
1131
1132 mock_output_api = MockOutputApi()
1133
1134 errors = PRESUBMIT._CheckForRelativeIncludes(
1135 mock_input_api, mock_output_api)
1136 self.assertEqual(0, len(errors))
1137
1138 def testRelativeIncludeNonWebKitProducesError(self):
1139 mock_input_api = MockInputApi()
1140 mock_input_api.files = [
1141 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1142 ]
1143
1144 mock_output_api = MockOutputApi()
1145
1146 errors = PRESUBMIT._CheckForRelativeIncludes(
1147 mock_input_api, mock_output_api)
1148 self.assertEqual(1, len(errors))
1149
1150 def testRelativeIncludeWebKitProducesError(self):
1151 mock_input_api = MockInputApi()
1152 mock_input_api.files = [
1153 MockAffectedFile('third_party/WebKit/test.cpp',
1154 ['#include "../header.h']),
1155 ]
1156
1157 mock_output_api = MockOutputApi()
1158
1159 errors = PRESUBMIT._CheckForRelativeIncludes(
1160 mock_input_api, mock_output_api)
1161 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241162
Daniel Cheng13ca61a882017-08-25 15:11:251163
1164class MojoManifestOwnerTest(unittest.TestCase):
1165 def testMojoManifestChangeNeedsSecurityOwner(self):
1166 mock_input_api = MockInputApi()
1167 mock_input_api.files = [
1168 MockAffectedFile('services/goat/manifest.json',
1169 [
1170 '{',
1171 ' "name": "teleporter",',
1172 ' "display_name": "Goat Teleporter",'
1173 ' "interface_provider_specs": {',
1174 ' }',
1175 '}',
1176 ])
1177 ]
1178 mock_output_api = MockOutputApi()
1179 errors = PRESUBMIT._CheckIpcOwners(
1180 mock_input_api, mock_output_api)
1181 self.assertEqual(1, len(errors))
1182 self.assertEqual(
1183 'Found OWNERS files that need to be updated for IPC security review ' +
1184 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
1185
1186 # No warning if already covered by an OWNERS rule.
1187
1188 def testNonManifestChangesDoNotRequireSecurityOwner(self):
1189 mock_input_api = MockInputApi()
1190 mock_input_api.files = [
1191 MockAffectedFile('services/goat/species.json',
1192 [
1193 '[',
1194 ' "anglo-nubian",',
1195 ' "angora"',
1196 ']',
1197 ])
1198 ]
1199 mock_output_api = MockOutputApi()
1200 errors = PRESUBMIT._CheckIpcOwners(
1201 mock_input_api, mock_output_api)
1202 self.assertEqual([], errors)
1203
1204
[email protected]2299dcf2012-11-15 19:56:241205if __name__ == '__main__':
1206 unittest.main()