blob: 85c5eb2ea8ebaec3e2f3ccdd738c5f04a0f26a20 [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]99171a92014-06-03 08:44:477import subprocess
[email protected]2299dcf2012-11-15 19:56:248import unittest
9
10import PRESUBMIT
Saagar Sanghavifceeaae2020-08-12 16:40:3611
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3912from PRESUBMIT_test_mocks import MockFile, MockAffectedFile
gayane3dff8c22014-12-04 17:09:5113from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi
[email protected]2299dcf2012-11-15 19:56:2414
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3915
[email protected]99171a92014-06-03 08:44:4716_TEST_DATA_DIR = 'base/test/data/presubmit'
17
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3918
[email protected]b00342e7f2013-03-26 16:21:5419class VersionControlConflictsTest(unittest.TestCase):
[email protected]70ca77752012-11-20 03:45:0320 def testTypicalConflict(self):
21 lines = ['<<<<<<< HEAD',
22 ' base::ScopedTempDir temp_dir_;',
23 '=======',
24 ' ScopedTempDir temp_dir_;',
25 '>>>>>>> master']
26 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
27 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
28 self.assertEqual(3, len(errors))
29 self.assertTrue('1' in errors[0])
30 self.assertTrue('3' in errors[1])
31 self.assertTrue('5' in errors[2])
32
dbeam95c35a2f2015-06-02 01:40:2333 def testIgnoresReadmes(self):
34 lines = ['A First Level Header',
35 '====================',
36 '',
37 'A Second Level Header',
38 '---------------------']
39 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
40 MockInputApi(), MockFile('some/polymer/README.md', lines))
41 self.assertEqual(0, len(errors))
42
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3943
[email protected]b8079ae4a2012-12-05 19:56:4944class BadExtensionsTest(unittest.TestCase):
45 def testBadRejFile(self):
46 mock_input_api = MockInputApi()
47 mock_input_api.files = [
48 MockFile('some/path/foo.cc', ''),
49 MockFile('some/path/foo.cc.rej', ''),
50 MockFile('some/path2/bar.h.rej', ''),
51 ]
52
Saagar Sanghavifceeaae2020-08-12 16:40:3653 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:4954 self.assertEqual(1, len(results))
55 self.assertEqual(2, len(results[0].items))
56 self.assertTrue('foo.cc.rej' in results[0].items[0])
57 self.assertTrue('bar.h.rej' in results[0].items[1])
58
59 def testBadOrigFile(self):
60 mock_input_api = MockInputApi()
61 mock_input_api.files = [
62 MockFile('other/path/qux.h.orig', ''),
63 MockFile('other/path/qux.h', ''),
64 MockFile('other/path/qux.cc', ''),
65 ]
66
Saagar Sanghavifceeaae2020-08-12 16:40:3667 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:4968 self.assertEqual(1, len(results))
69 self.assertEqual(1, len(results[0].items))
70 self.assertTrue('qux.h.orig' in results[0].items[0])
71
72 def testGoodFiles(self):
73 mock_input_api = MockInputApi()
74 mock_input_api.files = [
75 MockFile('other/path/qux.h', ''),
76 MockFile('other/path/qux.cc', ''),
77 ]
Saagar Sanghavifceeaae2020-08-12 16:40:3678 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:4979 self.assertEqual(0, len(results))
80
81
glidere61efad2015-02-18 17:39:4382class CheckSingletonInHeadersTest(unittest.TestCase):
83 def testSingletonInArbitraryHeader(self):
84 diff_singleton_h = ['base::subtle::AtomicWord '
olli.raula36aa8be2015-09-10 11:14:2285 'base::Singleton<Type, Traits, DifferentiatingType>::']
86 diff_foo_h = ['// base::Singleton<Foo> in comment.',
87 'friend class base::Singleton<Foo>']
oysteinec430ad42015-10-22 20:55:2488 diff_foo2_h = [' //Foo* bar = base::Singleton<Foo>::get();']
olli.raula36aa8be2015-09-10 11:14:2289 diff_bad_h = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:4390 mock_input_api = MockInputApi()
91 mock_input_api.files = [MockAffectedFile('base/memory/singleton.h',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3992 diff_singleton_h),
glidere61efad2015-02-18 17:39:4393 MockAffectedFile('foo.h', diff_foo_h),
oysteinec430ad42015-10-22 20:55:2494 MockAffectedFile('foo2.h', diff_foo2_h),
glidere61efad2015-02-18 17:39:4395 MockAffectedFile('bad.h', diff_bad_h)]
Saagar Sanghavifceeaae2020-08-12 16:40:3696 warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
glidere61efad2015-02-18 17:39:4397 MockOutputApi())
98 self.assertEqual(1, len(warnings))
Sylvain Defresnea8b73d252018-02-28 15:45:5499 self.assertEqual(1, len(warnings[0].items))
glidere61efad2015-02-18 17:39:43100 self.assertEqual('error', warnings[0].type)
olli.raula36aa8be2015-09-10 11:14:22101 self.assertTrue('Found base::Singleton<T>' in warnings[0].message)
glidere61efad2015-02-18 17:39:43102
103 def testSingletonInCC(self):
olli.raula36aa8be2015-09-10 11:14:22104 diff_cc = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43105 mock_input_api = MockInputApi()
106 mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)]
Saagar Sanghavifceeaae2020-08-12 16:40:36107 warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
glidere61efad2015-02-18 17:39:43108 MockOutputApi())
109 self.assertEqual(0, len(warnings))
110
111
[email protected]b00342e7f2013-03-26 16:21:54112class InvalidOSMacroNamesTest(unittest.TestCase):
113 def testInvalidOSMacroNames(self):
114 lines = ['#if defined(OS_WINDOWS)',
115 ' #elif defined(OS_WINDOW)',
Avi Drissman34594e902020-07-25 05:35:44116 ' # if defined(OS_MAC) || defined(OS_CHROME)',
Avi Drissman32967a9e2020-07-30 04:10:32117 '# else // defined(OS_MACOSX)',
[email protected]b00342e7f2013-03-26 16:21:54118 '#endif // defined(OS_MACOS)']
119 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
120 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
121 self.assertEqual(len(lines), len(errors))
122 self.assertTrue(':1 OS_WINDOWS' in errors[0])
123 self.assertTrue('(did you mean OS_WIN?)' in errors[0])
124
125 def testValidOSMacroNames(self):
126 lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS]
127 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
128 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
129 self.assertEqual(0, len(errors))
130
131
lliabraa35bab3932014-10-01 12:16:44132class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
133 def testInvalidIfDefinedMacroNames(self):
134 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
135 '#if !defined(TARGET_IPHONE_SIMULATOR)',
136 '#elif defined(TARGET_IPHONE_SIMULATOR)',
137 '#ifdef TARGET_IPHONE_SIMULATOR',
138 ' # ifdef TARGET_IPHONE_SIMULATOR',
139 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
140 '# else // defined(TARGET_IPHONE_SIMULATOR)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39141 '#endif // defined(TARGET_IPHONE_SIMULATOR)']
lliabraa35bab3932014-10-01 12:16:44142 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
143 MockInputApi(), MockFile('some/path/source.mm', lines))
144 self.assertEqual(len(lines), len(errors))
145
146 def testValidIfDefinedMacroNames(self):
147 lines = ['#if defined(FOO)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39148 '#ifdef BAR']
lliabraa35bab3932014-10-01 12:16:44149 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
150 MockInputApi(), MockFile('some/path/source.cc', lines))
151 self.assertEqual(0, len(errors))
152
153
Samuel Huang0db2ea22019-12-09 16:42:47154class CheckAddedDepsHaveTestApprovalsTest(unittest.TestCase):
Daniel Cheng4dcdb6b2017-04-13 08:30:17155
156 def calculate(self, old_include_rules, old_specific_include_rules,
157 new_include_rules, new_specific_include_rules):
158 return PRESUBMIT._CalculateAddedDeps(
159 os.path, 'include_rules = %r\nspecific_include_rules = %r' % (
160 old_include_rules, old_specific_include_rules),
161 'include_rules = %r\nspecific_include_rules = %r' % (
162 new_include_rules, new_specific_include_rules))
163
164 def testCalculateAddedDeps(self):
165 old_include_rules = [
166 '+base',
167 '-chrome',
168 '+content',
169 '-grit',
170 '-grit/",',
171 '+jni/fooblat.h',
172 '!sandbox',
[email protected]f32e2d1e2013-07-26 21:39:08173 ]
Daniel Cheng4dcdb6b2017-04-13 08:30:17174 old_specific_include_rules = {
175 'compositor\.*': {
176 '+cc',
177 },
178 }
179
180 new_include_rules = [
181 '-ash',
182 '+base',
183 '+chrome',
184 '+components',
185 '+content',
186 '+grit',
187 '+grit/generated_resources.h",',
188 '+grit/",',
189 '+jni/fooblat.h',
190 '+policy',
manzagop85e629e2017-05-09 22:11:48191 '+' + os.path.join('third_party', 'WebKit'),
Daniel Cheng4dcdb6b2017-04-13 08:30:17192 ]
193 new_specific_include_rules = {
194 'compositor\.*': {
195 '+cc',
196 },
197 'widget\.*': {
198 '+gpu',
199 },
200 }
201
[email protected]f32e2d1e2013-07-26 21:39:08202 expected = set([
manzagop85e629e2017-05-09 22:11:48203 os.path.join('chrome', 'DEPS'),
204 os.path.join('gpu', 'DEPS'),
205 os.path.join('components', 'DEPS'),
206 os.path.join('policy', 'DEPS'),
207 os.path.join('third_party', 'WebKit', 'DEPS'),
[email protected]f32e2d1e2013-07-26 21:39:08208 ])
Daniel Cheng4dcdb6b2017-04-13 08:30:17209 self.assertEqual(
210 expected,
211 self.calculate(old_include_rules, old_specific_include_rules,
212 new_include_rules, new_specific_include_rules))
213
214 def testCalculateAddedDepsIgnoresPermutations(self):
215 old_include_rules = [
216 '+base',
217 '+chrome',
218 ]
219 new_include_rules = [
220 '+chrome',
221 '+base',
222 ]
223 self.assertEqual(set(),
224 self.calculate(old_include_rules, {}, new_include_rules,
225 {}))
[email protected]f32e2d1e2013-07-26 21:39:08226
227
[email protected]99171a92014-06-03 08:44:47228class JSONParsingTest(unittest.TestCase):
229 def testSuccess(self):
230 input_api = MockInputApi()
231 filename = 'valid_json.json'
232 contents = ['// This is a comment.',
233 '{',
234 ' "key1": ["value1", "value2"],',
235 ' "key2": 3 // This is an inline comment.',
236 '}'
237 ]
238 input_api.files = [MockFile(filename, contents)]
239 self.assertEqual(None,
240 PRESUBMIT._GetJSONParseError(input_api, filename))
241
242 def testFailure(self):
243 input_api = MockInputApi()
244 test_data = [
245 ('invalid_json_1.json',
246 ['{ x }'],
[email protected]a3343272014-06-17 11:41:53247 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47248 ('invalid_json_2.json',
249 ['// Hello world!',
250 '{ "hello": "world }'],
[email protected]a3343272014-06-17 11:41:53251 'Unterminated string starting at:'),
[email protected]99171a92014-06-03 08:44:47252 ('invalid_json_3.json',
253 ['{ "a": "b", "c": "d", }'],
[email protected]a3343272014-06-17 11:41:53254 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47255 ('invalid_json_4.json',
256 ['{ "a": "b" "c": "d" }'],
[email protected]a3343272014-06-17 11:41:53257 'Expecting , delimiter:'),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39258 ]
[email protected]99171a92014-06-03 08:44:47259
260 input_api.files = [MockFile(filename, contents)
261 for (filename, contents, _) in test_data]
262
263 for (filename, _, expected_error) in test_data:
264 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
[email protected]a3343272014-06-17 11:41:53265 self.assertTrue(expected_error in str(actual_error),
266 "'%s' not found in '%s'" % (expected_error, actual_error))
[email protected]99171a92014-06-03 08:44:47267
268 def testNoEatComments(self):
269 input_api = MockInputApi()
270 file_with_comments = 'file_with_comments.json'
271 contents_with_comments = ['// This is a comment.',
272 '{',
273 ' "key1": ["value1", "value2"],',
274 ' "key2": 3 // This is an inline comment.',
275 '}'
276 ]
277 file_without_comments = 'file_without_comments.json'
278 contents_without_comments = ['{',
279 ' "key1": ["value1", "value2"],',
280 ' "key2": 3',
281 '}'
282 ]
283 input_api.files = [MockFile(file_with_comments, contents_with_comments),
284 MockFile(file_without_comments,
285 contents_without_comments)]
286
287 self.assertEqual('No JSON object could be decoded',
288 str(PRESUBMIT._GetJSONParseError(input_api,
289 file_with_comments,
290 eat_comments=False)))
291 self.assertEqual(None,
292 PRESUBMIT._GetJSONParseError(input_api,
293 file_without_comments,
294 eat_comments=False))
295
296
297class IDLParsingTest(unittest.TestCase):
298 def testSuccess(self):
299 input_api = MockInputApi()
300 filename = 'valid_idl_basics.idl'
301 contents = ['// Tests a valid IDL file.',
302 'namespace idl_basics {',
303 ' enum EnumType {',
304 ' name1,',
305 ' name2',
306 ' };',
307 '',
308 ' dictionary MyType1 {',
309 ' DOMString a;',
310 ' };',
311 '',
312 ' callback Callback1 = void();',
313 ' callback Callback2 = void(long x);',
314 ' callback Callback3 = void(MyType1 arg);',
315 ' callback Callback4 = void(EnumType type);',
316 '',
317 ' interface Functions {',
318 ' static void function1();',
319 ' static void function2(long x);',
320 ' static void function3(MyType1 arg);',
321 ' static void function4(Callback1 cb);',
322 ' static void function5(Callback2 cb);',
323 ' static void function6(Callback3 cb);',
324 ' static void function7(Callback4 cb);',
325 ' };',
326 '',
327 ' interface Events {',
328 ' static void onFoo1();',
329 ' static void onFoo2(long x);',
330 ' static void onFoo2(MyType1 arg);',
331 ' static void onFoo3(EnumType type);',
332 ' };',
333 '};'
334 ]
335 input_api.files = [MockFile(filename, contents)]
336 self.assertEqual(None,
337 PRESUBMIT._GetIDLParseError(input_api, filename))
338
339 def testFailure(self):
340 input_api = MockInputApi()
341 test_data = [
342 ('invalid_idl_1.idl',
343 ['//',
344 'namespace test {',
345 ' dictionary {',
346 ' DOMString s;',
347 ' };',
348 '};'],
349 'Unexpected "{" after keyword "dictionary".\n'),
350 # TODO(yoz): Disabled because it causes the IDL parser to hang.
351 # See crbug.com/363830.
352 # ('invalid_idl_2.idl',
353 # (['namespace test {',
354 # ' dictionary MissingSemicolon {',
355 # ' DOMString a',
356 # ' DOMString b;',
357 # ' };',
358 # '};'],
359 # 'Unexpected symbol DOMString after symbol a.'),
360 ('invalid_idl_3.idl',
361 ['//',
362 'namespace test {',
363 ' enum MissingComma {',
364 ' name1',
365 ' name2',
366 ' };',
367 '};'],
368 'Unexpected symbol name2 after symbol name1.'),
369 ('invalid_idl_4.idl',
370 ['//',
371 'namespace test {',
372 ' enum TrailingComma {',
373 ' name1,',
374 ' name2,',
375 ' };',
376 '};'],
377 'Trailing comma in block.'),
378 ('invalid_idl_5.idl',
379 ['//',
380 'namespace test {',
381 ' callback Callback1 = void(;',
382 '};'],
383 'Unexpected ";" after "(".'),
384 ('invalid_idl_6.idl',
385 ['//',
386 'namespace test {',
387 ' callback Callback1 = void(long );',
388 '};'],
389 'Unexpected ")" after symbol long.'),
390 ('invalid_idl_7.idl',
391 ['//',
392 'namespace test {',
393 ' interace Events {',
394 ' static void onFoo1();',
395 ' };',
396 '};'],
397 'Unexpected symbol Events after symbol interace.'),
398 ('invalid_idl_8.idl',
399 ['//',
400 'namespace test {',
401 ' interface NotEvent {',
402 ' static void onFoo1();',
403 ' };',
404 '};'],
405 'Did not process Interface Interface(NotEvent)'),
406 ('invalid_idl_9.idl',
407 ['//',
408 'namespace test {',
409 ' interface {',
410 ' static void function1();',
411 ' };',
412 '};'],
413 'Interface missing name.'),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39414 ]
[email protected]99171a92014-06-03 08:44:47415
416 input_api.files = [MockFile(filename, contents)
417 for (filename, contents, _) in test_data]
418
419 for (filename, _, expected_error) in test_data:
420 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
421 self.assertTrue(expected_error in str(actual_error),
422 "'%s' not found in '%s'" % (expected_error, actual_error))
423
424
[email protected]0bb112362014-07-26 04:38:32425class TryServerMasterTest(unittest.TestCase):
426 def testTryServerMasters(self):
427 bots = {
tandriie5587792016-07-14 00:34:50428 'master.tryserver.chromium.android': [
jbudorick3ae7a772016-05-20 02:36:04429 'android_archive_rel_ng',
430 'android_arm64_dbg_recipe',
431 'android_blink_rel',
jbudorick3ae7a772016-05-20 02:36:04432 'android_clang_dbg_recipe',
433 'android_compile_dbg',
jbudorick3ae7a772016-05-20 02:36:04434 'android_compile_x64_dbg',
435 'android_compile_x86_dbg',
436 'android_coverage',
437 'android_cronet_tester'
438 'android_swarming_rel',
439 'cast_shell_android',
440 'linux_android_dbg_ng',
441 'linux_android_rel_ng',
442 ],
tandriie5587792016-07-14 00:34:50443 'master.tryserver.chromium.mac': [
[email protected]0bb112362014-07-26 04:38:32444 'ios_dbg_simulator',
445 'ios_rel_device',
446 'ios_rel_device_ninja',
447 'mac_asan',
448 'mac_asan_64',
449 'mac_chromium_compile_dbg',
450 'mac_chromium_compile_rel',
451 'mac_chromium_dbg',
452 'mac_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32453 'mac_nacl_sdk',
454 'mac_nacl_sdk_build',
455 'mac_rel_naclmore',
[email protected]0bb112362014-07-26 04:38:32456 'mac_x64_rel',
457 'mac_xcodebuild',
458 ],
tandriie5587792016-07-14 00:34:50459 'master.tryserver.chromium.linux': [
[email protected]0bb112362014-07-26 04:38:32460 'chromium_presubmit',
461 'linux_arm_cross_compile',
462 'linux_arm_tester',
[email protected]0bb112362014-07-26 04:38:32463 'linux_chromeos_asan',
464 'linux_chromeos_browser_asan',
465 'linux_chromeos_valgrind',
[email protected]0bb112362014-07-26 04:38:32466 'linux_chromium_chromeos_dbg',
467 'linux_chromium_chromeos_rel',
[email protected]0bb112362014-07-26 04:38:32468 'linux_chromium_compile_dbg',
469 'linux_chromium_compile_rel',
470 'linux_chromium_dbg',
471 'linux_chromium_gn_dbg',
472 'linux_chromium_gn_rel',
473 'linux_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32474 'linux_chromium_trusty32_dbg',
475 'linux_chromium_trusty32_rel',
476 'linux_chromium_trusty_dbg',
477 'linux_chromium_trusty_rel',
478 'linux_clang_tsan',
479 'linux_ecs_ozone',
480 'linux_layout',
481 'linux_layout_asan',
482 'linux_layout_rel',
483 'linux_layout_rel_32',
484 'linux_nacl_sdk',
485 'linux_nacl_sdk_bionic',
486 'linux_nacl_sdk_bionic_build',
487 'linux_nacl_sdk_build',
488 'linux_redux',
489 'linux_rel_naclmore',
490 'linux_rel_precise32',
491 'linux_valgrind',
492 'tools_build_presubmit',
493 ],
tandriie5587792016-07-14 00:34:50494 'master.tryserver.chromium.win': [
[email protected]0bb112362014-07-26 04:38:32495 'win8_aura',
496 'win8_chromium_dbg',
497 'win8_chromium_rel',
498 'win_chromium_compile_dbg',
499 'win_chromium_compile_rel',
500 'win_chromium_dbg',
501 'win_chromium_rel',
502 'win_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32503 'win_chromium_x64_dbg',
504 'win_chromium_x64_rel',
[email protected]0bb112362014-07-26 04:38:32505 'win_nacl_sdk',
506 'win_nacl_sdk_build',
507 'win_rel_naclmore',
508 ],
509 }
510 for master, bots in bots.iteritems():
511 for bot in bots:
512 self.assertEqual(master, PRESUBMIT.GetTryServerMasterForBot(bot),
513 'bot=%s: expected %s, computed %s' % (
514 bot, master, PRESUBMIT.GetTryServerMasterForBot(bot)))
515
516
davileene0426252015-03-02 21:10:41517class UserMetricsActionTest(unittest.TestCase):
518 def testUserMetricsActionInActions(self):
519 input_api = MockInputApi()
520 file_with_user_action = 'file_with_user_action.cc'
521 contents_with_user_action = [
522 'base::UserMetricsAction("AboutChrome")'
523 ]
524
525 input_api.files = [MockFile(file_with_user_action,
526 contents_with_user_action)]
527
528 self.assertEqual(
Saagar Sanghavifceeaae2020-08-12 16:40:36529 [], PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi()))
davileene0426252015-03-02 21:10:41530
davileene0426252015-03-02 21:10:41531 def testUserMetricsActionNotAddedToActions(self):
532 input_api = MockInputApi()
533 file_with_user_action = 'file_with_user_action.cc'
534 contents_with_user_action = [
535 'base::UserMetricsAction("NotInActionsXml")'
536 ]
537
538 input_api.files = [MockFile(file_with_user_action,
539 contents_with_user_action)]
540
Saagar Sanghavifceeaae2020-08-12 16:40:36541 output = PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi())
davileene0426252015-03-02 21:10:41542 self.assertEqual(
543 ('File %s line %d: %s is missing in '
544 'tools/metrics/actions/actions.xml. Please run '
545 'tools/metrics/actions/extract_actions.py to update.'
546 % (file_with_user_action, 1, 'NotInActionsXml')),
547 output[0].message)
548
549
agrievef32bcc72016-04-04 14:57:40550class PydepsNeedsUpdatingTest(unittest.TestCase):
551
552 class MockSubprocess(object):
553 CalledProcessError = subprocess.CalledProcessError
554
Mohamed Heikal7cd4d8312020-06-16 16:49:40555 def _MockParseGclientArgs(self, is_android=True):
556 return lambda: {'checkout_android': 'true' if is_android else 'false' }
557
agrievef32bcc72016-04-04 14:57:40558 def setUp(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40559 mock_all_pydeps = ['A.pydeps', 'B.pydeps', 'D.pydeps']
agrievef32bcc72016-04-04 14:57:40560 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
561 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
Mohamed Heikal7cd4d8312020-06-16 16:49:40562 mock_android_pydeps = ['D.pydeps']
563 self.old_ANDROID_SPECIFIC_PYDEPS_FILES = (
564 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES)
565 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = mock_android_pydeps
566 self.old_ParseGclientArgs = PRESUBMIT._ParseGclientArgs
567 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs()
agrievef32bcc72016-04-04 14:57:40568 self.mock_input_api = MockInputApi()
569 self.mock_output_api = MockOutputApi()
570 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
571 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
572 self.checker._file_cache = {
Andrew Grieve5bb4cf702020-10-22 20:21:39573 'A.pydeps': '# Generated by:\n# CMD --output A.pydeps A\nA.py\nC.py\n',
574 'B.pydeps': '# Generated by:\n# CMD --output B.pydeps B\nB.py\nC.py\n',
575 'D.pydeps': '# Generated by:\n# CMD --output D.pydeps D\nD.py\n',
agrievef32bcc72016-04-04 14:57:40576 }
577
578 def tearDown(self):
579 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
Mohamed Heikal7cd4d8312020-06-16 16:49:40580 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = (
581 self.old_ANDROID_SPECIFIC_PYDEPS_FILES)
582 PRESUBMIT._ParseGclientArgs = self.old_ParseGclientArgs
agrievef32bcc72016-04-04 14:57:40583
584 def _RunCheck(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36585 return PRESUBMIT.CheckPydepsNeedsUpdating(self.mock_input_api,
agrievef32bcc72016-04-04 14:57:40586 self.mock_output_api,
587 checker_for_tests=self.checker)
588
589 def testAddedPydep(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36590 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13591 if self.mock_input_api.platform != 'linux2':
592 return []
593
agrievef32bcc72016-04-04 14:57:40594 self.mock_input_api.files = [
595 MockAffectedFile('new.pydeps', [], action='A'),
596 ]
597
Zhiling Huang45cabf32018-03-10 00:50:03598 self.mock_input_api.CreateMockFileInPath(
599 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
600 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40601 results = self._RunCheck()
602 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39603 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40604
Zhiling Huang45cabf32018-03-10 00:50:03605 def testPydepNotInSrc(self):
606 self.mock_input_api.files = [
607 MockAffectedFile('new.pydeps', [], action='A'),
608 ]
609 self.mock_input_api.CreateMockFileInPath([])
610 results = self._RunCheck()
611 self.assertEqual(0, len(results))
612
agrievef32bcc72016-04-04 14:57:40613 def testRemovedPydep(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36614 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13615 if self.mock_input_api.platform != 'linux2':
616 return []
617
agrievef32bcc72016-04-04 14:57:40618 self.mock_input_api.files = [
619 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
620 ]
Zhiling Huang45cabf32018-03-10 00:50:03621 self.mock_input_api.CreateMockFileInPath(
622 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
623 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40624 results = self._RunCheck()
625 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39626 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40627
628 def testRandomPyIgnored(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36629 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13630 if self.mock_input_api.platform != 'linux2':
631 return []
632
agrievef32bcc72016-04-04 14:57:40633 self.mock_input_api.files = [
634 MockAffectedFile('random.py', []),
635 ]
636
637 results = self._RunCheck()
638 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
639
640 def testRelevantPyNoChange(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36641 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13642 if self.mock_input_api.platform != 'linux2':
643 return []
644
agrievef32bcc72016-04-04 14:57:40645 self.mock_input_api.files = [
646 MockAffectedFile('A.py', []),
647 ]
648
John Budorickab2fa102017-10-06 16:59:49649 def mock_check_output(cmd, shell=False, env=None):
Andrew Grieve5bb4cf702020-10-22 20:21:39650 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
agrievef32bcc72016-04-04 14:57:40651 return self.checker._file_cache['A.pydeps']
652
653 self.mock_input_api.subprocess.check_output = mock_check_output
654
655 results = self._RunCheck()
656 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
657
658 def testRelevantPyOneChange(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36659 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13660 if self.mock_input_api.platform != 'linux2':
661 return []
662
agrievef32bcc72016-04-04 14:57:40663 self.mock_input_api.files = [
664 MockAffectedFile('A.py', []),
665 ]
666
John Budorickab2fa102017-10-06 16:59:49667 def mock_check_output(cmd, shell=False, env=None):
Andrew Grieve5bb4cf702020-10-22 20:21:39668 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
agrievef32bcc72016-04-04 14:57:40669 return 'changed data'
670
671 self.mock_input_api.subprocess.check_output = mock_check_output
672
673 results = self._RunCheck()
674 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39675 self.assertIn('File is stale', str(results[0]))
agrievef32bcc72016-04-04 14:57:40676
677 def testRelevantPyTwoChanges(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36678 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13679 if self.mock_input_api.platform != 'linux2':
680 return []
681
agrievef32bcc72016-04-04 14:57:40682 self.mock_input_api.files = [
683 MockAffectedFile('C.py', []),
684 ]
685
John Budorickab2fa102017-10-06 16:59:49686 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40687 return 'changed data'
688
689 self.mock_input_api.subprocess.check_output = mock_check_output
690
691 results = self._RunCheck()
692 self.assertEqual(2, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39693 self.assertIn('File is stale', str(results[0]))
694 self.assertIn('File is stale', str(results[1]))
agrievef32bcc72016-04-04 14:57:40695
Mohamed Heikal7cd4d8312020-06-16 16:49:40696 def testRelevantAndroidPyInNonAndroidCheckout(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36697 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Mohamed Heikal7cd4d8312020-06-16 16:49:40698 if self.mock_input_api.platform != 'linux2':
699 return []
700
701 self.mock_input_api.files = [
702 MockAffectedFile('D.py', []),
703 ]
704
705 def mock_check_output(cmd, shell=False, env=None):
Andrew Grieve5bb4cf702020-10-22 20:21:39706 self.assertEqual('CMD --output D.pydeps D --output ""', cmd)
Mohamed Heikal7cd4d8312020-06-16 16:49:40707 return 'changed data'
708
709 self.mock_input_api.subprocess.check_output = mock_check_output
710 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs(is_android=False)
711
712 results = self._RunCheck()
713 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39714 self.assertIn('Android', str(results[0]))
715 self.assertIn('D.pydeps', str(results[0]))
716
717 def testGnPathsAndMissingOutputFlag(self):
718 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
719 if self.mock_input_api.platform != 'linux2':
720 return []
721
722 self.checker._file_cache = {
723 'A.pydeps': '# Generated by:\n# CMD --gn-paths A\n//A.py\n//C.py\n',
724 'B.pydeps': '# Generated by:\n# CMD --gn-paths B\n//B.py\n//C.py\n',
725 'D.pydeps': '# Generated by:\n# CMD --gn-paths D\n//D.py\n',
726 }
727
728 self.mock_input_api.files = [
729 MockAffectedFile('A.py', []),
730 ]
731
732 def mock_check_output(cmd, shell=False, env=None):
733 self.assertEqual('CMD --gn-paths A --output A.pydeps --output ""', cmd)
734 return 'changed data'
735
736 self.mock_input_api.subprocess.check_output = mock_check_output
737
738 results = self._RunCheck()
739 self.assertEqual(1, len(results))
740 self.assertIn('File is stale', str(results[0]))
Mohamed Heikal7cd4d8312020-06-16 16:49:40741
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39742
Daniel Bratell8ba52722018-03-02 16:06:14743class IncludeGuardTest(unittest.TestCase):
744 def testIncludeGuardChecks(self):
745 mock_input_api = MockInputApi()
746 mock_output_api = MockOutputApi()
747 mock_input_api.files = [
748 MockAffectedFile('content/browser/thing/foo.h', [
749 '// Comment',
750 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
751 '#define CONTENT_BROWSER_THING_FOO_H_',
752 'struct McBoatFace;',
753 '#endif // CONTENT_BROWSER_THING_FOO_H_',
754 ]),
755 MockAffectedFile('content/browser/thing/bar.h', [
756 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
757 '#define CONTENT_BROWSER_THING_BAR_H_',
758 'namespace content {',
759 '#endif // CONTENT_BROWSER_THING_BAR_H_',
760 '} // namespace content',
761 ]),
762 MockAffectedFile('content/browser/test1.h', [
763 'namespace content {',
764 '} // namespace content',
765 ]),
766 MockAffectedFile('content\\browser\\win.h', [
767 '#ifndef CONTENT_BROWSER_WIN_H_',
768 '#define CONTENT_BROWSER_WIN_H_',
769 'struct McBoatFace;',
770 '#endif // CONTENT_BROWSER_WIN_H_',
771 ]),
772 MockAffectedFile('content/browser/test2.h', [
773 '// Comment',
774 '#ifndef CONTENT_BROWSER_TEST2_H_',
775 'struct McBoatFace;',
776 '#endif // CONTENT_BROWSER_TEST2_H_',
777 ]),
778 MockAffectedFile('content/browser/internal.h', [
779 '// Comment',
780 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
781 '#define CONTENT_BROWSER_INTERNAL_H_',
782 '// Comment',
783 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
784 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
785 'namespace internal {',
786 '} // namespace internal',
787 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
788 'namespace content {',
789 '} // namespace content',
790 '#endif // CONTENT_BROWSER_THING_BAR_H_',
791 ]),
792 MockAffectedFile('content/browser/thing/foo.cc', [
793 '// This is a non-header.',
794 ]),
795 MockAffectedFile('content/browser/disabled.h', [
796 '// no-include-guard-because-multiply-included',
797 'struct McBoatFace;',
798 ]),
799 # New files don't allow misspelled include guards.
800 MockAffectedFile('content/browser/spleling.h', [
801 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
802 '#define CONTENT_BROWSER_SPLLEING_H_',
803 'struct McBoatFace;',
804 '#endif // CONTENT_BROWSER_SPLLEING_H_',
805 ]),
Olivier Robinbba137492018-07-30 11:31:34806 # New files don't allow + in include guards.
807 MockAffectedFile('content/browser/foo+bar.h', [
808 '#ifndef CONTENT_BROWSER_FOO+BAR_H_',
809 '#define CONTENT_BROWSER_FOO+BAR_H_',
810 'struct McBoatFace;',
811 '#endif // CONTENT_BROWSER_FOO+BAR_H_',
812 ]),
Daniel Bratell8ba52722018-03-02 16:06:14813 # Old files allow misspelled include guards (for now).
814 MockAffectedFile('chrome/old.h', [
815 '// New contents',
816 '#ifndef CHROME_ODL_H_',
817 '#define CHROME_ODL_H_',
818 '#endif // CHROME_ODL_H_',
819 ], [
820 '// Old contents',
821 '#ifndef CHROME_ODL_H_',
822 '#define CHROME_ODL_H_',
823 '#endif // CHROME_ODL_H_',
824 ]),
825 # Using a Blink style include guard outside Blink is wrong.
826 MockAffectedFile('content/NotInBlink.h', [
827 '#ifndef NotInBlink_h',
828 '#define NotInBlink_h',
829 'struct McBoatFace;',
830 '#endif // NotInBlink_h',
831 ]),
Daniel Bratell39b5b062018-05-16 18:09:57832 # Using a Blink style include guard in Blink is no longer ok.
833 MockAffectedFile('third_party/blink/InBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14834 '#ifndef InBlink_h',
835 '#define InBlink_h',
836 'struct McBoatFace;',
837 '#endif // InBlink_h',
838 ]),
839 # Using a bad include guard in Blink is not ok.
Daniel Bratell39b5b062018-05-16 18:09:57840 MockAffectedFile('third_party/blink/AlsoInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14841 '#ifndef WrongInBlink_h',
842 '#define WrongInBlink_h',
843 'struct McBoatFace;',
844 '#endif // WrongInBlink_h',
845 ]),
Daniel Bratell39b5b062018-05-16 18:09:57846 # Using a bad include guard in Blink is not accepted even if
847 # it's an old file.
848 MockAffectedFile('third_party/blink/StillInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14849 '// New contents',
850 '#ifndef AcceptedInBlink_h',
851 '#define AcceptedInBlink_h',
852 'struct McBoatFace;',
853 '#endif // AcceptedInBlink_h',
854 ], [
855 '// Old contents',
856 '#ifndef AcceptedInBlink_h',
857 '#define AcceptedInBlink_h',
858 'struct McBoatFace;',
859 '#endif // AcceptedInBlink_h',
860 ]),
Daniel Bratell39b5b062018-05-16 18:09:57861 # Using a non-Chromium include guard in third_party
862 # (outside blink) is accepted.
863 MockAffectedFile('third_party/foo/some_file.h', [
864 '#ifndef REQUIRED_RPCNDR_H_',
865 '#define REQUIRED_RPCNDR_H_',
866 'struct SomeFileFoo;',
867 '#endif // REQUIRED_RPCNDR_H_',
868 ]),
Kinuko Yasuda0cdb3da2019-07-31 21:50:32869 # Not having proper include guard in *_message_generator.h
870 # for old IPC messages is allowed.
871 MockAffectedFile('content/common/content_message_generator.h', [
872 '#undef CONTENT_COMMON_FOO_MESSAGES_H_',
873 '#include "content/common/foo_messages.h"',
874 '#ifndef CONTENT_COMMON_FOO_MESSAGES_H_',
875 '#error "Failed to include content/common/foo_messages.h"',
876 '#endif',
877 ]),
Daniel Bratell8ba52722018-03-02 16:06:14878 ]
Saagar Sanghavifceeaae2020-08-12 16:40:36879 msgs = PRESUBMIT.CheckForIncludeGuards(
Daniel Bratell8ba52722018-03-02 16:06:14880 mock_input_api, mock_output_api)
Olivier Robinbba137492018-07-30 11:31:34881 expected_fail_count = 8
Daniel Bratell8ba52722018-03-02 16:06:14882 self.assertEqual(expected_fail_count, len(msgs),
883 'Expected %d items, found %d: %s'
884 % (expected_fail_count, len(msgs), msgs))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39885 self.assertEqual(msgs[0].items, ['content/browser/thing/bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:14886 self.assertEqual(msgs[0].message,
887 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
888 'not covering the whole file')
889
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39890 self.assertEqual(msgs[1].items, ['content/browser/test1.h'])
Daniel Bratell8ba52722018-03-02 16:06:14891 self.assertEqual(msgs[1].message,
892 'Missing include guard CONTENT_BROWSER_TEST1_H_')
893
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39894 self.assertEqual(msgs[2].items, ['content/browser/test2.h:3'])
Daniel Bratell8ba52722018-03-02 16:06:14895 self.assertEqual(msgs[2].message,
896 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
897 'include guard')
898
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39899 self.assertEqual(msgs[3].items, ['content/browser/spleling.h:1'])
Daniel Bratell8ba52722018-03-02 16:06:14900 self.assertEqual(msgs[3].message,
901 'Header using the wrong include guard name '
902 'CONTENT_BROWSER_SPLLEING_H_')
903
Olivier Robinbba137492018-07-30 11:31:34904 self.assertEqual(msgs[4].items, ['content/browser/foo+bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:14905 self.assertEqual(msgs[4].message,
Olivier Robinbba137492018-07-30 11:31:34906 'Missing include guard CONTENT_BROWSER_FOO_BAR_H_')
907
908 self.assertEqual(msgs[5].items, ['content/NotInBlink.h:1'])
909 self.assertEqual(msgs[5].message,
Daniel Bratell8ba52722018-03-02 16:06:14910 'Header using the wrong include guard name '
911 'NotInBlink_h')
912
Olivier Robinbba137492018-07-30 11:31:34913 self.assertEqual(msgs[6].items, ['third_party/blink/InBlink.h:1'])
914 self.assertEqual(msgs[6].message,
Daniel Bratell8ba52722018-03-02 16:06:14915 'Header using the wrong include guard name '
Daniel Bratell39b5b062018-05-16 18:09:57916 'InBlink_h')
917
Olivier Robinbba137492018-07-30 11:31:34918 self.assertEqual(msgs[7].items, ['third_party/blink/AlsoInBlink.h:1'])
919 self.assertEqual(msgs[7].message,
Daniel Bratell39b5b062018-05-16 18:09:57920 'Header using the wrong include guard name '
Daniel Bratell8ba52722018-03-02 16:06:14921 'WrongInBlink_h')
922
Chris Hall59f8d0c72020-05-01 07:31:19923class AccessibilityRelnotesFieldTest(unittest.TestCase):
924 def testRelnotesPresent(self):
925 mock_input_api = MockInputApi()
926 mock_output_api = MockOutputApi()
927
928 mock_input_api.files = [MockAffectedFile('ui/accessibility/foo.bar', [''])]
Akihiro Ota08108e542020-05-20 15:30:53929 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19930 mock_input_api.change.footers['AX-Relnotes'] = [
931 'Important user facing change']
932
Saagar Sanghavifceeaae2020-08-12 16:40:36933 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19934 mock_input_api, mock_output_api)
935 self.assertEqual(0, len(msgs),
936 'Expected %d messages, found %d: %s'
937 % (0, len(msgs), msgs))
938
939 def testRelnotesMissingFromAccessibilityChange(self):
940 mock_input_api = MockInputApi()
941 mock_output_api = MockOutputApi()
942
943 mock_input_api.files = [
944 MockAffectedFile('some/file', ['']),
945 MockAffectedFile('ui/accessibility/foo.bar', ['']),
946 MockAffectedFile('some/other/file', [''])
947 ]
Akihiro Ota08108e542020-05-20 15:30:53948 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19949
Saagar Sanghavifceeaae2020-08-12 16:40:36950 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19951 mock_input_api, mock_output_api)
952 self.assertEqual(1, len(msgs),
953 'Expected %d messages, found %d: %s'
954 % (1, len(msgs), msgs))
955 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
956 'Missing AX-Relnotes field message not found in errors')
957
958 # The relnotes footer is not required for changes which do not touch any
959 # accessibility directories.
960 def testIgnoresNonAccesssibilityCode(self):
961 mock_input_api = MockInputApi()
962 mock_output_api = MockOutputApi()
963
964 mock_input_api.files = [
965 MockAffectedFile('some/file', ['']),
966 MockAffectedFile('some/other/file', [''])
967 ]
Akihiro Ota08108e542020-05-20 15:30:53968 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19969
Saagar Sanghavifceeaae2020-08-12 16:40:36970 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19971 mock_input_api, mock_output_api)
972 self.assertEqual(0, len(msgs),
973 'Expected %d messages, found %d: %s'
974 % (0, len(msgs), msgs))
975
976 # Test that our presubmit correctly raises an error for a set of known paths.
977 def testExpectedPaths(self):
978 filesToTest = [
979 "chrome/browser/accessibility/foo.py",
980 "chrome/browser/chromeos/arc/accessibility/foo.cc",
981 "chrome/browser/ui/views/accessibility/foo.h",
982 "chrome/browser/extensions/api/automation/foo.h",
983 "chrome/browser/extensions/api/automation_internal/foo.cc",
984 "chrome/renderer/extensions/accessibility_foo.h",
985 "chrome/tests/data/accessibility/foo.html",
986 "content/browser/accessibility/foo.cc",
987 "content/renderer/accessibility/foo.h",
988 "content/tests/data/accessibility/foo.cc",
989 "extensions/renderer/api/automation/foo.h",
990 "ui/accessibility/foo/bar/baz.cc",
991 "ui/views/accessibility/foo/bar/baz.h",
992 ]
993
994 for testFile in filesToTest:
995 mock_input_api = MockInputApi()
996 mock_output_api = MockOutputApi()
997
998 mock_input_api.files = [
999 MockAffectedFile(testFile, [''])
1000 ]
Akihiro Ota08108e542020-05-20 15:30:531001 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191002
Saagar Sanghavifceeaae2020-08-12 16:40:361003 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:191004 mock_input_api, mock_output_api)
1005 self.assertEqual(1, len(msgs),
1006 'Expected %d messages, found %d: %s, for file %s'
1007 % (1, len(msgs), msgs, testFile))
1008 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1009 ('Missing AX-Relnotes field message not found in errors '
1010 ' for file %s' % (testFile)))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391011
Akihiro Ota08108e542020-05-20 15:30:531012 # Test that AX-Relnotes field can appear in the commit description (as long
1013 # as it appears at the beginning of a line).
1014 def testRelnotesInCommitDescription(self):
1015 mock_input_api = MockInputApi()
1016 mock_output_api = MockOutputApi()
1017
1018 mock_input_api.files = [
1019 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1020 ]
1021 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1022 'AX-Relnotes: solves all accessibility issues forever')
1023
Saagar Sanghavifceeaae2020-08-12 16:40:361024 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531025 mock_input_api, mock_output_api)
1026 self.assertEqual(0, len(msgs),
1027 'Expected %d messages, found %d: %s'
1028 % (0, len(msgs), msgs))
1029
1030 # Test that we don't match AX-Relnotes if it appears in the middle of a line.
1031 def testRelnotesMustAppearAtBeginningOfLine(self):
1032 mock_input_api = MockInputApi()
1033 mock_output_api = MockOutputApi()
1034
1035 mock_input_api.files = [
1036 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1037 ]
1038 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1039 'This change has no AX-Relnotes: we should print a warning')
1040
Saagar Sanghavifceeaae2020-08-12 16:40:361041 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531042 mock_input_api, mock_output_api)
1043 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1044 'Missing AX-Relnotes field message not found in errors')
1045
1046 # Tests that the AX-Relnotes field can be lowercase and use a '=' in place
1047 # of a ':'.
1048 def testRelnotesLowercaseWithEqualSign(self):
1049 mock_input_api = MockInputApi()
1050 mock_output_api = MockOutputApi()
1051
1052 mock_input_api.files = [
1053 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1054 ]
1055 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1056 'ax-relnotes= this is a valid format for accessibiliy relnotes')
1057
Saagar Sanghavifceeaae2020-08-12 16:40:361058 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531059 mock_input_api, mock_output_api)
1060 self.assertEqual(0, len(msgs),
1061 'Expected %d messages, found %d: %s'
1062 % (0, len(msgs), msgs))
1063
yolandyan45001472016-12-21 21:12:421064class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
1065 def testCheckAndroidTestAnnotationUsage(self):
1066 mock_input_api = MockInputApi()
1067 mock_output_api = MockOutputApi()
1068
1069 mock_input_api.files = [
1070 MockAffectedFile('LalaLand.java', [
1071 'random stuff'
1072 ]),
1073 MockAffectedFile('CorrectUsage.java', [
1074 'import android.support.test.filters.LargeTest;',
1075 'import android.support.test.filters.MediumTest;',
1076 'import android.support.test.filters.SmallTest;',
1077 ]),
1078 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
1079 'import android.test.suitebuilder.annotation.LargeTest;',
1080 ]),
1081 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
1082 'import android.test.suitebuilder.annotation.MediumTest;',
1083 ]),
1084 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
1085 'import android.test.suitebuilder.annotation.SmallTest;',
1086 ]),
1087 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
1088 'import android.test.suitebuilder.annotation.Smoke;',
1089 ])
1090 ]
1091 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
1092 mock_input_api, mock_output_api)
1093 self.assertEqual(1, len(msgs),
1094 'Expected %d items, found %d: %s'
1095 % (1, len(msgs), msgs))
1096 self.assertEqual(4, len(msgs[0].items),
1097 'Expected %d items, found %d: %s'
1098 % (4, len(msgs[0].items), msgs[0].items))
1099 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
1100 'UsedDeprecatedLargeTestAnnotation not found in errors')
1101 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
1102 in msgs[0].items,
1103 'UsedDeprecatedMediumTestAnnotation not found in errors')
1104 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
1105 'UsedDeprecatedSmallTestAnnotation not found in errors')
1106 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
1107 'UsedDeprecatedSmokeAnnotation not found in errors')
1108
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391109
Mohamed Heikal5e5b7922020-10-29 18:57:591110class CheckNoDownstreamDepsTest(unittest.TestCase):
1111 def testInvalidDepFromUpstream(self):
1112 mock_input_api = MockInputApi()
1113 mock_output_api = MockOutputApi()
1114
1115 mock_input_api.files = [
1116 MockAffectedFile('BUILD.gn', [
1117 'deps = [',
1118 ' "//clank/target:test",',
1119 ']'
1120 ]),
1121 MockAffectedFile('chrome/android/BUILD.gn', [
1122 'deps = [ "//clank/target:test" ]'
1123 ]),
1124 MockAffectedFile('chrome/chrome_java_deps.gni', [
1125 'java_deps = [',
1126 ' "//clank/target:test",',
1127 ']'
1128 ]),
1129 ]
1130 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1131 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1132 mock_input_api, mock_output_api)
1133 self.assertEqual(1, len(msgs),
1134 'Expected %d items, found %d: %s'
1135 % (1, len(msgs), msgs))
1136 self.assertEqual(3, len(msgs[0].items),
1137 'Expected %d items, found %d: %s'
1138 % (3, len(msgs[0].items), msgs[0].items))
1139 self.assertTrue(any('BUILD.gn:2' in item for item in msgs[0].items),
1140 'BUILD.gn not found in errors')
1141 self.assertTrue(
1142 any('chrome/android/BUILD.gn:1' in item for item in msgs[0].items),
1143 'chrome/android/BUILD.gn:1 not found in errors')
1144 self.assertTrue(
1145 any('chrome/chrome_java_deps.gni:2' in item for item in msgs[0].items),
1146 'chrome/chrome_java_deps.gni:2 not found in errors')
1147
1148 def testAllowsComments(self):
1149 mock_input_api = MockInputApi()
1150 mock_output_api = MockOutputApi()
1151
1152 mock_input_api.files = [
1153 MockAffectedFile('BUILD.gn', [
1154 '# real implementation in //clank/target:test',
1155 ]),
1156 ]
1157 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1158 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1159 mock_input_api, mock_output_api)
1160 self.assertEqual(0, len(msgs),
1161 'Expected %d items, found %d: %s'
1162 % (0, len(msgs), msgs))
1163
1164 def testOnlyChecksBuildFiles(self):
1165 mock_input_api = MockInputApi()
1166 mock_output_api = MockOutputApi()
1167
1168 mock_input_api.files = [
1169 MockAffectedFile('README.md', [
1170 'DEPS = [ "//clank/target:test" ]'
1171 ]),
1172 MockAffectedFile('chrome/android/java/file.java', [
1173 '//clank/ only function'
1174 ]),
1175 ]
1176 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1177 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1178 mock_input_api, mock_output_api)
1179 self.assertEqual(0, len(msgs),
1180 'Expected %d items, found %d: %s'
1181 % (0, len(msgs), msgs))
1182
1183 def testValidDepFromDownstream(self):
1184 mock_input_api = MockInputApi()
1185 mock_output_api = MockOutputApi()
1186
1187 mock_input_api.files = [
1188 MockAffectedFile('BUILD.gn', [
1189 'DEPS = [',
1190 ' "//clank/target:test",',
1191 ']'
1192 ]),
1193 MockAffectedFile('java/BUILD.gn', [
1194 'DEPS = [ "//clank/target:test" ]'
1195 ]),
1196 ]
1197 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src/clank'
1198 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1199 mock_input_api, mock_output_api)
1200 self.assertEqual(0, len(msgs),
1201 'Expected %d items, found %d: %s'
1202 % (0, len(msgs), msgs))
1203
Yoland Yanb92fa522017-08-28 17:37:061204class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271205 def testCheckAndroidTestJUnitFramework(self):
Yoland Yanb92fa522017-08-28 17:37:061206 mock_input_api = MockInputApi()
1207 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:421208
Yoland Yanb92fa522017-08-28 17:37:061209 mock_input_api.files = [
1210 MockAffectedFile('LalaLand.java', [
1211 'random stuff'
1212 ]),
1213 MockAffectedFile('CorrectUsage.java', [
1214 'import org.junit.ABC',
1215 'import org.junit.XYZ;',
1216 ]),
1217 MockAffectedFile('UsedDeprecatedJUnit.java', [
1218 'import junit.framework.*;',
1219 ]),
1220 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
1221 'import junit.framework.Assert;',
1222 ]),
1223 ]
1224 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
1225 mock_input_api, mock_output_api)
1226 self.assertEqual(1, len(msgs),
1227 'Expected %d items, found %d: %s'
1228 % (1, len(msgs), msgs))
1229 self.assertEqual(2, len(msgs[0].items),
1230 'Expected %d items, found %d: %s'
1231 % (2, len(msgs[0].items), msgs[0].items))
1232 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
1233 'UsedDeprecatedJUnit.java not found in errors')
1234 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
1235 in msgs[0].items,
1236 'UsedDeprecatedJUnitAssert not found in errors')
1237
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391238
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271239class AndroidJUnitBaseClassTest(unittest.TestCase):
1240 def testCheckAndroidTestJUnitBaseClass(self):
Yoland Yanb92fa522017-08-28 17:37:061241 mock_input_api = MockInputApi()
1242 mock_output_api = MockOutputApi()
1243
1244 mock_input_api.files = [
1245 MockAffectedFile('LalaLand.java', [
1246 'random stuff'
1247 ]),
1248 MockAffectedFile('CorrectTest.java', [
1249 '@RunWith(ABC.class);'
1250 'public class CorrectTest {',
1251 '}',
1252 ]),
1253 MockAffectedFile('HistoricallyIncorrectTest.java', [
1254 'public class Test extends BaseCaseA {',
1255 '}',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391256 ], old_contents=[
Yoland Yanb92fa522017-08-28 17:37:061257 'public class Test extends BaseCaseB {',
1258 '}',
1259 ]),
1260 MockAffectedFile('CorrectTestWithInterface.java', [
1261 '@RunWith(ABC.class);'
1262 'public class CorrectTest implement Interface {',
1263 '}',
1264 ]),
1265 MockAffectedFile('IncorrectTest.java', [
1266 'public class IncorrectTest extends TestCase {',
1267 '}',
1268 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241269 MockAffectedFile('IncorrectWithInterfaceTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061270 'public class Test implements X extends BaseClass {',
1271 '}',
1272 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241273 MockAffectedFile('IncorrectMultiLineTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061274 'public class Test implements X, Y, Z',
1275 ' extends TestBase {',
1276 '}',
1277 ]),
1278 ]
1279 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1280 mock_input_api, mock_output_api)
1281 self.assertEqual(1, len(msgs),
1282 'Expected %d items, found %d: %s'
1283 % (1, len(msgs), msgs))
1284 self.assertEqual(3, len(msgs[0].items),
1285 'Expected %d items, found %d: %s'
1286 % (3, len(msgs[0].items), msgs[0].items))
1287 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1288 'IncorrectTest not found in errors')
Vaclav Brozekf01ed502018-03-16 19:38:241289 self.assertTrue('IncorrectWithInterfaceTest.java:1'
Yoland Yanb92fa522017-08-28 17:37:061290 in msgs[0].items,
Vaclav Brozekf01ed502018-03-16 19:38:241291 'IncorrectWithInterfaceTest not found in errors')
1292 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1293 'IncorrectMultiLineTest not found in errors')
yolandyan45001472016-12-21 21:12:421294
Jinsong Fan91ebbbd2019-04-16 14:57:171295class AndroidDebuggableBuildTest(unittest.TestCase):
1296
1297 def testCheckAndroidDebuggableBuild(self):
1298 mock_input_api = MockInputApi()
1299 mock_output_api = MockOutputApi()
1300
1301 mock_input_api.files = [
1302 MockAffectedFile('RandomStuff.java', [
1303 'random stuff'
1304 ]),
1305 MockAffectedFile('CorrectUsage.java', [
1306 'import org.chromium.base.BuildInfo;',
1307 'some random stuff',
1308 'boolean isOsDebuggable = BuildInfo.isDebugAndroid();',
1309 ]),
1310 MockAffectedFile('JustCheckUserdebugBuild.java', [
1311 'import android.os.Build;',
1312 'some random stuff',
1313 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")',
1314 ]),
1315 MockAffectedFile('JustCheckEngineeringBuild.java', [
1316 'import android.os.Build;',
1317 'some random stuff',
1318 'boolean isOsDebuggable = "eng".equals(Build.TYPE)',
1319 ]),
1320 MockAffectedFile('UsedBuildType.java', [
1321 'import android.os.Build;',
1322 'some random stuff',
1323 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")'
1324 '|| "eng".equals(Build.TYPE)',
1325 ]),
1326 MockAffectedFile('UsedExplicitBuildType.java', [
1327 'some random stuff',
1328 'boolean isOsDebuggable = android.os.Build.TYPE.equals("userdebug")'
1329 '|| "eng".equals(android.os.Build.TYPE)',
1330 ]),
1331 ]
1332
1333 msgs = PRESUBMIT._CheckAndroidDebuggableBuild(
1334 mock_input_api, mock_output_api)
1335 self.assertEqual(1, len(msgs),
1336 'Expected %d items, found %d: %s'
1337 % (1, len(msgs), msgs))
1338 self.assertEqual(4, len(msgs[0].items),
1339 'Expected %d items, found %d: %s'
1340 % (4, len(msgs[0].items), msgs[0].items))
1341 self.assertTrue('JustCheckUserdebugBuild.java:3' in msgs[0].items)
1342 self.assertTrue('JustCheckEngineeringBuild.java:3' in msgs[0].items)
1343 self.assertTrue('UsedBuildType.java:3' in msgs[0].items)
1344 self.assertTrue('UsedExplicitBuildType.java:2' in msgs[0].items)
1345
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391346
dgn4401aa52015-04-29 16:26:171347class LogUsageTest(unittest.TestCase):
1348
dgnaa68d5e2015-06-10 10:08:221349 def testCheckAndroidCrLogUsage(self):
1350 mock_input_api = MockInputApi()
1351 mock_output_api = MockOutputApi()
1352
1353 mock_input_api.files = [
1354 MockAffectedFile('RandomStuff.java', [
1355 'random stuff'
1356 ]),
dgn87d9fb62015-06-12 09:15:121357 MockAffectedFile('HasAndroidLog.java', [
1358 'import android.util.Log;',
1359 'some random stuff',
1360 'Log.d("TAG", "foo");',
1361 ]),
1362 MockAffectedFile('HasExplicitUtilLog.java', [
1363 'some random stuff',
1364 'android.util.Log.d("TAG", "foo");',
1365 ]),
1366 MockAffectedFile('IsInBasePackage.java', [
1367 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511368 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121369 'Log.d(TAG, "foo");',
1370 ]),
1371 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1372 'package org.chromium.base;',
1373 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511374 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121375 'Log.d(TAG, "foo");',
1376 ]),
1377 MockAffectedFile('HasBothLog.java', [
1378 'import org.chromium.base.Log;',
1379 'some random stuff',
dgn38736db2015-09-18 19:20:511380 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121381 'Log.d(TAG, "foo");',
1382 'android.util.Log.d("TAG", "foo");',
1383 ]),
dgnaa68d5e2015-06-10 10:08:221384 MockAffectedFile('HasCorrectTag.java', [
1385 'import org.chromium.base.Log;',
1386 'some random stuff',
dgn38736db2015-09-18 19:20:511387 'private static final String TAG = "cr_Foo";',
1388 'Log.d(TAG, "foo");',
1389 ]),
1390 MockAffectedFile('HasOldTag.java', [
1391 'import org.chromium.base.Log;',
1392 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221393 'private static final String TAG = "cr.Foo";',
1394 'Log.d(TAG, "foo");',
1395 ]),
dgn38736db2015-09-18 19:20:511396 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221397 'import org.chromium.base.Log;',
1398 'some random stuff',
dgn38736db2015-09-18 19:20:511399 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221400 'Log.d(TAG, "foo");',
1401 ]),
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461402 MockAffectedFile('HasDottedTagPublic.java', [
1403 'import org.chromium.base.Log;',
1404 'some random stuff',
1405 'public static final String TAG = "cr_foo.bar";',
1406 'Log.d(TAG, "foo");',
1407 ]),
dgnaa68d5e2015-06-10 10:08:221408 MockAffectedFile('HasNoTagDecl.java', [
1409 'import org.chromium.base.Log;',
1410 'some random stuff',
1411 'Log.d(TAG, "foo");',
1412 ]),
1413 MockAffectedFile('HasIncorrectTagDecl.java', [
1414 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511415 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221416 'some random stuff',
1417 'Log.d(TAG, "foo");',
1418 ]),
1419 MockAffectedFile('HasInlineTag.java', [
1420 'import org.chromium.base.Log;',
1421 'some random stuff',
dgn38736db2015-09-18 19:20:511422 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221423 'Log.d("TAG", "foo");',
1424 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551425 MockAffectedFile('HasInlineTagWithSpace.java', [
1426 'import org.chromium.base.Log;',
1427 'some random stuff',
1428 'private static final String TAG = "cr_Foo";',
1429 'Log.d("log message", "foo");',
1430 ]),
dgn38736db2015-09-18 19:20:511431 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221432 'import org.chromium.base.Log;',
1433 'some random stuff',
1434 'private static final String TAG = "rubbish";',
1435 'Log.d(TAG, "foo");',
1436 ]),
1437 MockAffectedFile('HasTooLongTag.java', [
1438 'import org.chromium.base.Log;',
1439 'some random stuff',
dgn38736db2015-09-18 19:20:511440 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:221441 'Log.d(TAG, "foo");',
1442 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551443 MockAffectedFile('HasTooLongTagWithNoLogCallsInDiff.java', [
1444 'import org.chromium.base.Log;',
1445 'some random stuff',
1446 'private static final String TAG = "21_charachers_long___";',
1447 ]),
dgnaa68d5e2015-06-10 10:08:221448 ]
1449
1450 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1451 mock_input_api, mock_output_api)
1452
dgn38736db2015-09-18 19:20:511453 self.assertEqual(5, len(msgs),
1454 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221455
1456 # Declaration format
dgn38736db2015-09-18 19:20:511457 nb = len(msgs[0].items)
1458 self.assertEqual(2, nb,
1459 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221460 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1461 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221462
1463 # Tag length
dgn38736db2015-09-18 19:20:511464 nb = len(msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551465 self.assertEqual(2, nb,
1466 'Expected %d items, found %d: %s' % (2, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:221467 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551468 self.assertTrue('HasTooLongTagWithNoLogCallsInDiff.java' in msgs[1].items)
dgnaa68d5e2015-06-10 10:08:221469
1470 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511471 nb = len(msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551472 self.assertEqual(3, nb,
1473 'Expected %d items, found %d: %s' % (3, nb, msgs[2].items))
1474 self.assertTrue('HasBothLog.java:5' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221475 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551476 self.assertTrue('HasInlineTagWithSpace.java:4' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221477
dgn87d9fb62015-06-12 09:15:121478 # Util Log usage
dgn38736db2015-09-18 19:20:511479 nb = len(msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551480 self.assertEqual(3, nb,
1481 'Expected %d items, found %d: %s' % (3, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:121482 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551483 self.assertTrue('HasExplicitUtilLog.java:2' in msgs[3].items)
dgn87d9fb62015-06-12 09:15:121484 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:221485
dgn38736db2015-09-18 19:20:511486 # Tag must not contain
1487 nb = len(msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461488 self.assertEqual(3, nb,
dgn38736db2015-09-18 19:20:511489 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1490 self.assertTrue('HasDottedTag.java' in msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461491 self.assertTrue('HasDottedTagPublic.java' in msgs[4].items)
dgn38736db2015-09-18 19:20:511492 self.assertTrue('HasOldTag.java' in msgs[4].items)
1493
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391494
estadee17314a02017-01-12 16:22:161495class GoogleAnswerUrlFormatTest(unittest.TestCase):
1496
1497 def testCatchAnswerUrlId(self):
1498 input_api = MockInputApi()
1499 input_api.files = [
1500 MockFile('somewhere/file.cc',
1501 ['char* host = '
1502 ' "https://support.google.com/chrome/answer/123456";']),
1503 MockFile('somewhere_else/file.cc',
1504 ['char* host = '
1505 ' "https://support.google.com/chrome/a/answer/123456";']),
1506 ]
1507
Saagar Sanghavifceeaae2020-08-12 16:40:361508 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161509 input_api, MockOutputApi())
1510 self.assertEqual(1, len(warnings))
1511 self.assertEqual(2, len(warnings[0].items))
1512
1513 def testAllowAnswerUrlParam(self):
1514 input_api = MockInputApi()
1515 input_api.files = [
1516 MockFile('somewhere/file.cc',
1517 ['char* host = '
1518 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1519 ]
1520
Saagar Sanghavifceeaae2020-08-12 16:40:361521 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161522 input_api, MockOutputApi())
1523 self.assertEqual(0, len(warnings))
1524
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391525
reillyi38965732015-11-16 18:27:331526class HardcodedGoogleHostsTest(unittest.TestCase):
1527
1528 def testWarnOnAssignedLiterals(self):
1529 input_api = MockInputApi()
1530 input_api.files = [
1531 MockFile('content/file.cc',
1532 ['char* host = "https://www.google.com";']),
1533 MockFile('content/file.cc',
1534 ['char* host = "https://www.googleapis.com";']),
1535 MockFile('content/file.cc',
1536 ['char* host = "https://clients1.google.com";']),
1537 ]
1538
Saagar Sanghavifceeaae2020-08-12 16:40:361539 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331540 input_api, MockOutputApi())
1541 self.assertEqual(1, len(warnings))
1542 self.assertEqual(3, len(warnings[0].items))
1543
1544 def testAllowInComment(self):
1545 input_api = MockInputApi()
1546 input_api.files = [
1547 MockFile('content/file.cc',
1548 ['char* host = "https://www.aol.com"; // google.com'])
1549 ]
1550
Saagar Sanghavifceeaae2020-08-12 16:40:361551 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331552 input_api, MockOutputApi())
1553 self.assertEqual(0, len(warnings))
1554
dgn4401aa52015-04-29 16:26:171555
James Cook6b6597c2019-11-06 22:05:291556class ChromeOsSyncedPrefRegistrationTest(unittest.TestCase):
1557
1558 def testWarnsOnChromeOsDirectories(self):
1559 input_api = MockInputApi()
1560 input_api.files = [
1561 MockFile('ash/file.cc',
1562 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1563 MockFile('chrome/browser/chromeos/file.cc',
1564 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1565 MockFile('chromeos/file.cc',
1566 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1567 MockFile('components/arc/file.cc',
1568 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1569 MockFile('components/exo/file.cc',
1570 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1571 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361572 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291573 input_api, MockOutputApi())
1574 self.assertEqual(1, len(warnings))
1575
1576 def testDoesNotWarnOnSyncOsPref(self):
1577 input_api = MockInputApi()
1578 input_api.files = [
1579 MockFile('chromeos/file.cc',
1580 ['PrefRegistrySyncable::SYNCABLE_OS_PREF']),
1581 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361582 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291583 input_api, MockOutputApi())
1584 self.assertEqual(0, len(warnings))
1585
1586 def testDoesNotWarnOnCrossPlatformDirectories(self):
1587 input_api = MockInputApi()
1588 input_api.files = [
1589 MockFile('chrome/browser/ui/file.cc',
1590 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1591 MockFile('components/sync/file.cc',
1592 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1593 MockFile('content/browser/file.cc',
1594 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1595 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361596 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291597 input_api, MockOutputApi())
1598 self.assertEqual(0, len(warnings))
1599
1600 def testSeparateWarningForPriorityPrefs(self):
1601 input_api = MockInputApi()
1602 input_api.files = [
1603 MockFile('chromeos/file.cc',
1604 ['PrefRegistrySyncable::SYNCABLE_PREF',
1605 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']),
1606 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361607 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291608 input_api, MockOutputApi())
1609 self.assertEqual(2, len(warnings))
1610
1611
jbriance9e12f162016-11-25 07:57:501612class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311613 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501614 mock_input_api = MockInputApi()
1615 mock_input_api.files = [
1616 MockAffectedFile('somewhere/file.cc', [
1617 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311618 ]),
1619 MockAffectedFile('third_party/header.h', [
1620 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501621 ])
1622 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361623 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391624 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501625 self.assertEqual(0, len(warnings))
1626
1627 def testNoNestedDeclaration(self):
1628 mock_input_api = MockInputApi()
1629 mock_input_api.files = [
1630 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311631 'class SomeClass {',
1632 ' protected:',
1633 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501634 '};'
1635 ])
1636 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361637 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391638 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501639 self.assertEqual(0, len(warnings))
1640
1641 def testSubStrings(self):
1642 mock_input_api = MockInputApi()
1643 mock_input_api.files = [
1644 MockAffectedFile('somewhere/header.h', [
1645 'class NotUsefulClass;',
1646 'struct SomeStruct;',
1647 'UsefulClass *p1;',
1648 'SomeStructPtr *p2;'
1649 ])
1650 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361651 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391652 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501653 self.assertEqual(2, len(warnings))
1654
1655 def testUselessForwardDeclaration(self):
1656 mock_input_api = MockInputApi()
1657 mock_input_api.files = [
1658 MockAffectedFile('somewhere/header.h', [
1659 'class DummyClass;',
1660 'struct DummyStruct;',
1661 'class UsefulClass;',
1662 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311663 ])
jbriance9e12f162016-11-25 07:57:501664 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361665 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391666 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501667 self.assertEqual(2, len(warnings))
1668
jbriance2c51e821a2016-12-12 08:24:311669 def testBlinkHeaders(self):
1670 mock_input_api = MockInputApi()
1671 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491672 MockAffectedFile('third_party/blink/header.h', [
jbriance2c51e821a2016-12-12 08:24:311673 'class DummyClass;',
1674 'struct DummyStruct;',
1675 ]),
Kent Tamura32dbbcb2018-11-30 12:28:491676 MockAffectedFile('third_party\\blink\\header.h', [
jbriance2c51e821a2016-12-12 08:24:311677 'class DummyClass;',
1678 'struct DummyStruct;',
1679 ])
1680 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361681 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391682 MockOutputApi())
jbriance2c51e821a2016-12-12 08:24:311683 self.assertEqual(4, len(warnings))
1684
jbriance9e12f162016-11-25 07:57:501685
rlanday6802cf632017-05-30 17:48:361686class RelativeIncludesTest(unittest.TestCase):
1687 def testThirdPartyNotWebKitIgnored(self):
1688 mock_input_api = MockInputApi()
1689 mock_input_api.files = [
1690 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1691 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1692 ]
1693
1694 mock_output_api = MockOutputApi()
1695
Saagar Sanghavifceeaae2020-08-12 16:40:361696 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361697 mock_input_api, mock_output_api)
1698 self.assertEqual(0, len(errors))
1699
1700 def testNonCppFileIgnored(self):
1701 mock_input_api = MockInputApi()
1702 mock_input_api.files = [
1703 MockAffectedFile('test.py', '#include "../header.h"'),
1704 ]
1705
1706 mock_output_api = MockOutputApi()
1707
Saagar Sanghavifceeaae2020-08-12 16:40:361708 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361709 mock_input_api, mock_output_api)
1710 self.assertEqual(0, len(errors))
1711
1712 def testInnocuousChangesAllowed(self):
1713 mock_input_api = MockInputApi()
1714 mock_input_api.files = [
1715 MockAffectedFile('test.cpp', '#include "header.h"'),
1716 MockAffectedFile('test2.cpp', '../'),
1717 ]
1718
1719 mock_output_api = MockOutputApi()
1720
Saagar Sanghavifceeaae2020-08-12 16:40:361721 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361722 mock_input_api, mock_output_api)
1723 self.assertEqual(0, len(errors))
1724
1725 def testRelativeIncludeNonWebKitProducesError(self):
1726 mock_input_api = MockInputApi()
1727 mock_input_api.files = [
1728 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1729 ]
1730
1731 mock_output_api = MockOutputApi()
1732
Saagar Sanghavifceeaae2020-08-12 16:40:361733 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361734 mock_input_api, mock_output_api)
1735 self.assertEqual(1, len(errors))
1736
1737 def testRelativeIncludeWebKitProducesError(self):
1738 mock_input_api = MockInputApi()
1739 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491740 MockAffectedFile('third_party/blink/test.cpp',
rlanday6802cf632017-05-30 17:48:361741 ['#include "../header.h']),
1742 ]
1743
1744 mock_output_api = MockOutputApi()
1745
Saagar Sanghavifceeaae2020-08-12 16:40:361746 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361747 mock_input_api, mock_output_api)
1748 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241749
Daniel Cheng13ca61a882017-08-25 15:11:251750
Daniel Bratell65b033262019-04-23 08:17:061751class CCIncludeTest(unittest.TestCase):
1752 def testThirdPartyNotBlinkIgnored(self):
1753 mock_input_api = MockInputApi()
1754 mock_input_api.files = [
1755 MockAffectedFile('third_party/test.cpp', '#include "file.cc"'),
1756 ]
1757
1758 mock_output_api = MockOutputApi()
1759
Saagar Sanghavifceeaae2020-08-12 16:40:361760 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061761 mock_input_api, mock_output_api)
1762 self.assertEqual(0, len(errors))
1763
1764 def testPythonFileIgnored(self):
1765 mock_input_api = MockInputApi()
1766 mock_input_api.files = [
1767 MockAffectedFile('test.py', '#include "file.cc"'),
1768 ]
1769
1770 mock_output_api = MockOutputApi()
1771
Saagar Sanghavifceeaae2020-08-12 16:40:361772 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061773 mock_input_api, mock_output_api)
1774 self.assertEqual(0, len(errors))
1775
1776 def testIncFilesAccepted(self):
1777 mock_input_api = MockInputApi()
1778 mock_input_api.files = [
1779 MockAffectedFile('test.py', '#include "file.inc"'),
1780 ]
1781
1782 mock_output_api = MockOutputApi()
1783
Saagar Sanghavifceeaae2020-08-12 16:40:361784 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061785 mock_input_api, mock_output_api)
1786 self.assertEqual(0, len(errors))
1787
1788 def testInnocuousChangesAllowed(self):
1789 mock_input_api = MockInputApi()
1790 mock_input_api.files = [
1791 MockAffectedFile('test.cpp', '#include "header.h"'),
1792 MockAffectedFile('test2.cpp', 'Something "file.cc"'),
1793 ]
1794
1795 mock_output_api = MockOutputApi()
1796
Saagar Sanghavifceeaae2020-08-12 16:40:361797 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061798 mock_input_api, mock_output_api)
1799 self.assertEqual(0, len(errors))
1800
1801 def testCcIncludeNonBlinkProducesError(self):
1802 mock_input_api = MockInputApi()
1803 mock_input_api.files = [
1804 MockAffectedFile('test.cpp', ['#include "file.cc"']),
1805 ]
1806
1807 mock_output_api = MockOutputApi()
1808
Saagar Sanghavifceeaae2020-08-12 16:40:361809 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061810 mock_input_api, mock_output_api)
1811 self.assertEqual(1, len(errors))
1812
1813 def testCppIncludeBlinkProducesError(self):
1814 mock_input_api = MockInputApi()
1815 mock_input_api.files = [
1816 MockAffectedFile('third_party/blink/test.cpp',
1817 ['#include "foo/file.cpp"']),
1818 ]
1819
1820 mock_output_api = MockOutputApi()
1821
Saagar Sanghavifceeaae2020-08-12 16:40:361822 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061823 mock_input_api, mock_output_api)
1824 self.assertEqual(1, len(errors))
1825
1826
Andrew Grieve1b290e4a22020-11-24 20:07:011827class GnGlobForwardTest(unittest.TestCase):
1828 def testAddBareGlobs(self):
1829 mock_input_api = MockInputApi()
1830 mock_input_api.files = [
1831 MockAffectedFile('base/stuff.gni', [
1832 'forward_variables_from(invoker, "*")']),
1833 MockAffectedFile('base/BUILD.gn', [
1834 'forward_variables_from(invoker, "*")']),
1835 ]
1836 warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
1837 self.assertEqual(1, len(warnings))
1838 msg = '\n'.join(warnings[0].items)
1839 self.assertIn('base/stuff.gni', msg)
1840 # Should not check .gn files. Local templates don't need to care about
1841 # visibility / testonly.
1842 self.assertNotIn('base/BUILD.gn', msg)
1843
1844 def testValidUses(self):
1845 mock_input_api = MockInputApi()
1846 mock_input_api.files = [
1847 MockAffectedFile('base/stuff.gni', [
1848 'forward_variables_from(invoker, "*", [])']),
1849 MockAffectedFile('base/stuff2.gni', [
1850 'forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)']),
1851 MockAffectedFile('base/stuff3.gni', [
1852 'forward_variables_from(invoker, [ "testonly" ])']),
1853 ]
1854 warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
1855 self.assertEqual([], warnings)
1856
1857
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191858class NewHeaderWithoutGnChangeTest(unittest.TestCase):
1859 def testAddHeaderWithoutGn(self):
1860 mock_input_api = MockInputApi()
1861 mock_input_api.files = [
1862 MockAffectedFile('base/stuff.h', ''),
1863 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361864 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191865 mock_input_api, MockOutputApi())
1866 self.assertEqual(1, len(warnings))
1867 self.assertTrue('base/stuff.h' in warnings[0].items)
1868
1869 def testModifyHeader(self):
1870 mock_input_api = MockInputApi()
1871 mock_input_api.files = [
1872 MockAffectedFile('base/stuff.h', '', action='M'),
1873 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361874 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191875 mock_input_api, MockOutputApi())
1876 self.assertEqual(0, len(warnings))
1877
1878 def testDeleteHeader(self):
1879 mock_input_api = MockInputApi()
1880 mock_input_api.files = [
1881 MockAffectedFile('base/stuff.h', '', action='D'),
1882 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361883 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191884 mock_input_api, MockOutputApi())
1885 self.assertEqual(0, len(warnings))
1886
1887 def testAddHeaderWithGn(self):
1888 mock_input_api = MockInputApi()
1889 mock_input_api.files = [
1890 MockAffectedFile('base/stuff.h', ''),
1891 MockAffectedFile('base/BUILD.gn', 'stuff.h'),
1892 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361893 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191894 mock_input_api, MockOutputApi())
1895 self.assertEqual(0, len(warnings))
1896
1897 def testAddHeaderWithGni(self):
1898 mock_input_api = MockInputApi()
1899 mock_input_api.files = [
1900 MockAffectedFile('base/stuff.h', ''),
1901 MockAffectedFile('base/files.gni', 'stuff.h'),
1902 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361903 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191904 mock_input_api, MockOutputApi())
1905 self.assertEqual(0, len(warnings))
1906
1907 def testAddHeaderWithOther(self):
1908 mock_input_api = MockInputApi()
1909 mock_input_api.files = [
1910 MockAffectedFile('base/stuff.h', ''),
1911 MockAffectedFile('base/stuff.cc', 'stuff.h'),
1912 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361913 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191914 mock_input_api, MockOutputApi())
1915 self.assertEqual(1, len(warnings))
1916
1917 def testAddHeaderWithWrongGn(self):
1918 mock_input_api = MockInputApi()
1919 mock_input_api.files = [
1920 MockAffectedFile('base/stuff.h', ''),
1921 MockAffectedFile('base/BUILD.gn', 'stuff_h'),
1922 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361923 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191924 mock_input_api, MockOutputApi())
1925 self.assertEqual(1, len(warnings))
1926
1927 def testAddHeadersWithGn(self):
1928 mock_input_api = MockInputApi()
1929 mock_input_api.files = [
1930 MockAffectedFile('base/stuff.h', ''),
1931 MockAffectedFile('base/another.h', ''),
1932 MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'),
1933 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361934 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191935 mock_input_api, MockOutputApi())
1936 self.assertEqual(0, len(warnings))
1937
1938 def testAddHeadersWithWrongGn(self):
1939 mock_input_api = MockInputApi()
1940 mock_input_api.files = [
1941 MockAffectedFile('base/stuff.h', ''),
1942 MockAffectedFile('base/another.h', ''),
1943 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'),
1944 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361945 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191946 mock_input_api, MockOutputApi())
1947 self.assertEqual(1, len(warnings))
1948 self.assertFalse('base/stuff.h' in warnings[0].items)
1949 self.assertTrue('base/another.h' in warnings[0].items)
1950
1951 def testAddHeadersWithWrongGn2(self):
1952 mock_input_api = MockInputApi()
1953 mock_input_api.files = [
1954 MockAffectedFile('base/stuff.h', ''),
1955 MockAffectedFile('base/another.h', ''),
1956 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'),
1957 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361958 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191959 mock_input_api, MockOutputApi())
1960 self.assertEqual(1, len(warnings))
1961 self.assertTrue('base/stuff.h' in warnings[0].items)
1962 self.assertTrue('base/another.h' in warnings[0].items)
1963
1964
Michael Giuffridad3bc8672018-10-25 22:48:021965class CorrectProductNameInMessagesTest(unittest.TestCase):
1966 def testProductNameInDesc(self):
1967 mock_input_api = MockInputApi()
1968 mock_input_api.files = [
1969 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1970 '<message name="Foo" desc="Welcome to Chrome">',
1971 ' Welcome to Chrome!',
1972 '</message>',
1973 ]),
1974 MockAffectedFile('chrome/app/chromium_strings.grd', [
1975 '<message name="Bar" desc="Welcome to Chrome">',
1976 ' Welcome to Chromium!',
1977 '</message>',
1978 ]),
1979 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361980 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021981 mock_input_api, MockOutputApi())
1982 self.assertEqual(0, len(warnings))
1983
1984 def testChromeInChromium(self):
1985 mock_input_api = MockInputApi()
1986 mock_input_api.files = [
1987 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1988 '<message name="Foo" desc="Welcome to Chrome">',
1989 ' Welcome to Chrome!',
1990 '</message>',
1991 ]),
1992 MockAffectedFile('chrome/app/chromium_strings.grd', [
1993 '<message name="Bar" desc="Welcome to Chrome">',
1994 ' Welcome to Chrome!',
1995 '</message>',
1996 ]),
1997 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361998 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021999 mock_input_api, MockOutputApi())
2000 self.assertEqual(1, len(warnings))
2001 self.assertTrue('chrome/app/chromium_strings.grd' in warnings[0].items[0])
2002
2003 def testChromiumInChrome(self):
2004 mock_input_api = MockInputApi()
2005 mock_input_api.files = [
2006 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2007 '<message name="Foo" desc="Welcome to Chrome">',
2008 ' Welcome to Chromium!',
2009 '</message>',
2010 ]),
2011 MockAffectedFile('chrome/app/chromium_strings.grd', [
2012 '<message name="Bar" desc="Welcome to Chrome">',
2013 ' Welcome to Chromium!',
2014 '</message>',
2015 ]),
2016 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362017 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022018 mock_input_api, MockOutputApi())
2019 self.assertEqual(1, len(warnings))
2020 self.assertTrue(
2021 'chrome/app/google_chrome_strings.grd:2' in warnings[0].items[0])
2022
2023 def testMultipleInstances(self):
2024 mock_input_api = MockInputApi()
2025 mock_input_api.files = [
2026 MockAffectedFile('chrome/app/chromium_strings.grd', [
2027 '<message name="Bar" desc="Welcome to Chrome">',
2028 ' Welcome to Chrome!',
2029 '</message>',
2030 '<message name="Baz" desc="A correct message">',
2031 ' Chromium is the software you are using.',
2032 '</message>',
2033 '<message name="Bat" desc="An incorrect message">',
2034 ' Google Chrome is the software you are using.',
2035 '</message>',
2036 ]),
2037 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362038 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022039 mock_input_api, MockOutputApi())
2040 self.assertEqual(1, len(warnings))
2041 self.assertTrue(
2042 'chrome/app/chromium_strings.grd:2' in warnings[0].items[0])
2043 self.assertTrue(
2044 'chrome/app/chromium_strings.grd:8' in warnings[0].items[1])
2045
2046 def testMultipleWarnings(self):
2047 mock_input_api = MockInputApi()
2048 mock_input_api.files = [
2049 MockAffectedFile('chrome/app/chromium_strings.grd', [
2050 '<message name="Bar" desc="Welcome to Chrome">',
2051 ' Welcome to Chrome!',
2052 '</message>',
2053 '<message name="Baz" desc="A correct message">',
2054 ' Chromium is the software you are using.',
2055 '</message>',
2056 '<message name="Bat" desc="An incorrect message">',
2057 ' Google Chrome is the software you are using.',
2058 '</message>',
2059 ]),
2060 MockAffectedFile('components/components_google_chrome_strings.grd', [
2061 '<message name="Bar" desc="Welcome to Chrome">',
2062 ' Welcome to Chrome!',
2063 '</message>',
2064 '<message name="Baz" desc="A correct message">',
2065 ' Chromium is the software you are using.',
2066 '</message>',
2067 '<message name="Bat" desc="An incorrect message">',
2068 ' Google Chrome is the software you are using.',
2069 '</message>',
2070 ]),
2071 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362072 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022073 mock_input_api, MockOutputApi())
2074 self.assertEqual(2, len(warnings))
2075 self.assertTrue(
2076 'components/components_google_chrome_strings.grd:5'
2077 in warnings[0].items[0])
2078 self.assertTrue(
2079 'chrome/app/chromium_strings.grd:2' in warnings[1].items[0])
2080 self.assertTrue(
2081 'chrome/app/chromium_strings.grd:8' in warnings[1].items[1])
2082
2083
Ken Rockot9f668262018-12-21 18:56:362084class ServiceManifestOwnerTest(unittest.TestCase):
Ken Rockot9f668262018-12-21 18:56:362085 def testServiceManifestChangeNeedsSecurityOwner(self):
2086 mock_input_api = MockInputApi()
2087 mock_input_api.files = [
2088 MockAffectedFile('services/goat/public/cpp/manifest.cc',
2089 [
2090 '#include "services/goat/public/cpp/manifest.h"',
2091 'const service_manager::Manifest& GetManifest() {}',
2092 ])]
2093 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362094 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362095 mock_input_api, mock_output_api)
2096 self.assertEqual(1, len(errors))
2097 self.assertEqual(
2098 'Found OWNERS files that need to be updated for IPC security review ' +
2099 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2100
2101 def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
2102 mock_input_api = MockInputApi()
2103 mock_input_api.files = [
2104 MockAffectedFile('some/non/service/thing/foo_manifest.cc',
2105 [
2106 'const char kNoEnforcement[] = "not a manifest!";',
2107 ])]
2108 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362109 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032110 mock_input_api, mock_output_api)
2111 self.assertEqual([], errors)
2112
2113
2114class FuchsiaSecurityOwnerTest(unittest.TestCase):
2115 def testFidlChangeNeedsSecurityOwner(self):
2116 mock_input_api = MockInputApi()
2117 mock_input_api.files = [
2118 MockAffectedFile('potentially/scary/ipc.fidl',
2119 [
2120 'library test.fidl'
2121 ])]
2122 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362123 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032124 mock_input_api, mock_output_api)
2125 self.assertEqual(1, len(errors))
2126 self.assertEqual(
2127 'Found OWNERS files that need to be updated for IPC security review ' +
2128 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2129
2130 def testComponentManifestV1ChangeNeedsSecurityOwner(self):
2131 mock_input_api = MockInputApi()
2132 mock_input_api.files = [
2133 MockAffectedFile('potentially/scary/v2_manifest.cmx',
2134 [
2135 '{ "that is no": "manifest!" }'
2136 ])]
2137 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362138 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032139 mock_input_api, mock_output_api)
2140 self.assertEqual(1, len(errors))
2141 self.assertEqual(
2142 'Found OWNERS files that need to be updated for IPC security review ' +
2143 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2144
2145 def testComponentManifestV2NeedsSecurityOwner(self):
2146 mock_input_api = MockInputApi()
2147 mock_input_api.files = [
2148 MockAffectedFile('potentially/scary/v2_manifest.cml',
2149 [
2150 '{ "that is no": "manifest!" }'
2151 ])]
2152 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362153 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032154 mock_input_api, mock_output_api)
2155 self.assertEqual(1, len(errors))
2156 self.assertEqual(
2157 'Found OWNERS files that need to be updated for IPC security review ' +
2158 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2159
Joshua Peraza1ca6d392020-12-08 00:14:092160 def testThirdPartyTestsDoNotRequireSecurityOwner(self):
2161 mock_input_api = MockInputApi()
2162 mock_input_api.files = [
2163 MockAffectedFile('third_party/crashpad/test/tests.cmx',
2164 [
2165 'const char kNoEnforcement[] = "Security?!? Pah!";',
2166 ])]
2167 mock_output_api = MockOutputApi()
2168 errors = PRESUBMIT.CheckSecurityOwners(
2169 mock_input_api, mock_output_api)
2170 self.assertEqual([], errors)
2171
Wez17c66962020-04-29 15:26:032172 def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2173 mock_input_api = MockInputApi()
2174 mock_input_api.files = [
2175 MockAffectedFile('some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',
2176 [
2177 'const char kNoEnforcement[] = "Security?!? Pah!";',
2178 ])]
2179 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362180 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362181 mock_input_api, mock_output_api)
2182 self.assertEqual([], errors)
2183
Daniel Cheng13ca61a882017-08-25 15:11:252184
Robert Sesek2c905332020-05-06 23:17:132185class SecurityChangeTest(unittest.TestCase):
2186 class _MockOwnersDB(object):
2187 def __init__(self):
2188 self.email_regexp = '.*'
2189
2190 def owners_rooted_at_file(self, f):
2191 return ['[email protected]', '[email protected]']
2192
2193 def _mockChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2194 def __MockOwnerAndReviewers(input_api, email_regexp, approval_needed=False):
2195 return [owner, reviewers]
2196 input_api.canned_checks.GetCodereviewOwnerAndReviewers = \
2197 __MockOwnerAndReviewers
2198
Alex Goughbc964dd2020-06-15 17:52:372199 def testDiffGetServiceSandboxType(self):
Robert Sesek2c905332020-05-06 23:17:132200 mock_input_api = MockInputApi()
2201 mock_input_api.files = [
2202 MockAffectedFile(
2203 'services/goat/teleporter_host.cc',
2204 [
Alex Goughbc964dd2020-06-15 17:52:372205 'template <>',
2206 'inline content::SandboxType',
2207 'content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {',
2208 '#if defined(OS_WIN)',
2209 ' return SandboxType::kGoaty;',
2210 '#else',
2211 ' return SandboxType::kNoSandbox;',
2212 '#endif // !defined(OS_WIN)',
2213 '}'
Robert Sesek2c905332020-05-06 23:17:132214 ]
2215 ),
2216 ]
2217 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2218 mock_input_api)
2219 self.assertEqual({
2220 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372221 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132222 ])},
2223 files_to_functions)
2224
2225 def testDiffRemovingLine(self):
2226 mock_input_api = MockInputApi()
2227 mock_file = MockAffectedFile('services/goat/teleporter_host.cc', '')
2228 mock_file._scm_diff = """--- old 2020-05-04 14:08:25.000000000 -0400
2229+++ new 2020-05-04 14:08:32.000000000 -0400
2230@@ -1,5 +1,4 @@
Alex Goughbc964dd2020-06-15 17:52:372231 template <>
2232 inline content::SandboxType
2233-content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {
2234 #if defined(OS_WIN)
2235 return SandboxType::kGoaty;
Robert Sesek2c905332020-05-06 23:17:132236"""
2237 mock_input_api.files = [mock_file]
2238 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2239 mock_input_api)
2240 self.assertEqual({
2241 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372242 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132243 ])},
2244 files_to_functions)
2245
2246 def testChangeOwnersMissing(self):
2247 mock_input_api = MockInputApi()
2248 mock_input_api.owners_db = self._MockOwnersDB()
2249 mock_input_api.is_committing = False
2250 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372251 MockAffectedFile('file.cc', ['GetServiceSandboxType<Goat>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132252 ]
2253 mock_output_api = MockOutputApi()
2254 self._mockChangeOwnerAndReviewers(
2255 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362256 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132257 self.assertEquals(1, len(result))
2258 self.assertEquals(result[0].type, 'notify')
2259 self.assertEquals(result[0].message,
2260 'The following files change calls to security-sensive functions\n' \
2261 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2262 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372263 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132264
2265 def testChangeOwnersMissingAtCommit(self):
2266 mock_input_api = MockInputApi()
2267 mock_input_api.owners_db = self._MockOwnersDB()
2268 mock_input_api.is_committing = True
2269 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372270 MockAffectedFile('file.cc', ['GetServiceSandboxType<mojom::Goat>()'])
Robert Sesek2c905332020-05-06 23:17:132271 ]
2272 mock_output_api = MockOutputApi()
2273 self._mockChangeOwnerAndReviewers(
2274 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362275 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132276 self.assertEquals(1, len(result))
2277 self.assertEquals(result[0].type, 'error')
2278 self.assertEquals(result[0].message,
2279 'The following files change calls to security-sensive functions\n' \
2280 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2281 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372282 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132283
2284 def testChangeOwnersPresent(self):
2285 mock_input_api = MockInputApi()
2286 mock_input_api.owners_db = self._MockOwnersDB()
2287 mock_input_api.files = [
2288 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2289 ]
2290 mock_output_api = MockOutputApi()
2291 self._mockChangeOwnerAndReviewers(
2292 mock_input_api, '[email protected]',
2293 ['[email protected]', '[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362294 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132295 self.assertEquals(0, len(result))
2296
2297 def testChangeOwnerIsSecurityOwner(self):
2298 mock_input_api = MockInputApi()
2299 mock_input_api.owners_db = self._MockOwnersDB()
2300 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372301 MockAffectedFile('file.cc', ['GetServiceSandboxType<T>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132302 ]
2303 mock_output_api = MockOutputApi()
2304 self._mockChangeOwnerAndReviewers(
2305 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362306 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132307 self.assertEquals(1, len(result))
2308
2309
Mario Sanchez Prada2472cab2019-09-18 10:58:312310class BannedTypeCheckTest(unittest.TestCase):
Sylvain Defresnea8b73d252018-02-28 15:45:542311
Peter Kasting94a56c42019-10-25 21:54:042312 def testBannedCppFunctions(self):
2313 input_api = MockInputApi()
2314 input_api.files = [
2315 MockFile('some/cpp/problematic/file.cc',
2316 ['using namespace std;']),
Oksana Zhuravlovac8222d22019-12-19 19:21:162317 MockFile('third_party/blink/problematic/file.cc',
2318 ['GetInterfaceProvider()']),
Peter Kasting94a56c42019-10-25 21:54:042319 MockFile('some/cpp/ok/file.cc',
2320 ['using std::string;']),
Allen Bauer53b43fb12020-03-12 17:21:472321 MockFile('some/cpp/problematic/file2.cc',
2322 ['set_owned_by_client()']),
Peter Kasting94a56c42019-10-25 21:54:042323 ]
2324
Saagar Sanghavifceeaae2020-08-12 16:40:362325 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlovac8222d22019-12-19 19:21:162326
2327 # warnings are results[0], errors are results[1]
2328 self.assertEqual(2, len(results))
2329 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2330 self.assertTrue(
2331 'third_party/blink/problematic/file.cc' in results[0].message)
2332 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
Allen Bauer53b43fb12020-03-12 17:21:472333 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
Peter Kasting94a56c42019-10-25 21:54:042334
Abhijeet Kandalkar1e7c2502019-10-29 15:05:452335 def testBannedBlinkDowncastHelpers(self):
2336 input_api = MockInputApi()
2337 input_api.files = [
2338 MockFile('some/cpp/problematic/file1.cc',
2339 ['DEFINE_TYPE_CASTS(ToType, FromType, from_argument,'
2340 'PointerPredicate(), ReferencePredicate());']),
2341 MockFile('some/cpp/problematic/file2.cc',
2342 ['bool is_test_ele = IsHTMLTestElement(n);']),
2343 MockFile('some/cpp/problematic/file3.cc',
2344 ['auto* html_test_ele = ToHTMLTestElement(n);']),
2345 MockFile('some/cpp/problematic/file4.cc',
2346 ['auto* html_test_ele_or_null = ToHTMLTestElementOrNull(n);']),
2347 MockFile('some/cpp/ok/file1.cc',
2348 ['bool is_test_ele = IsA<HTMLTestElement>(n);']),
2349 MockFile('some/cpp/ok/file2.cc',
2350 ['auto* html_test_ele = To<HTMLTestElement>(n);']),
2351 MockFile('some/cpp/ok/file3.cc',
2352 ['auto* html_test_ele_or_null = ',
2353 'DynamicTo<HTMLTestElement>(n);']),
2354 ]
2355
2356 # warnings are errors[0], errors are errors[1]
Saagar Sanghavifceeaae2020-08-12 16:40:362357 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Abhijeet Kandalkar1e7c2502019-10-29 15:05:452358 self.assertEqual(2, len(errors))
2359 self.assertTrue('some/cpp/problematic/file1.cc' in errors[1].message)
2360 self.assertTrue('some/cpp/problematic/file2.cc' in errors[0].message)
2361 self.assertTrue('some/cpp/problematic/file3.cc' in errors[0].message)
2362 self.assertTrue('some/cpp/problematic/file4.cc' in errors[0].message)
2363 self.assertTrue('some/cpp/ok/file1.cc' not in errors[0].message)
2364 self.assertTrue('some/cpp/ok/file2.cc' not in errors[0].message)
2365 self.assertTrue('some/cpp/ok/file3.cc' not in errors[0].message)
2366
Peter K. Lee6c03ccff2019-07-15 14:40:052367 def testBannedIosObjcFunctions(self):
Sylvain Defresnea8b73d252018-02-28 15:45:542368 input_api = MockInputApi()
2369 input_api.files = [
2370 MockFile('some/ios/file.mm',
2371 ['TEST(SomeClassTest, SomeInteraction) {',
2372 '}']),
2373 MockFile('some/mac/file.mm',
2374 ['TEST(SomeClassTest, SomeInteraction) {',
2375 '}']),
2376 MockFile('another/ios_file.mm',
2377 ['class SomeTest : public testing::Test {};']),
Peter K. Lee6c03ccff2019-07-15 14:40:052378 MockFile('some/ios/file_egtest.mm',
2379 ['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
2380 MockFile('some/ios/file_unittest.mm',
2381 ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']),
Sylvain Defresnea8b73d252018-02-28 15:45:542382 ]
2383
Saagar Sanghavifceeaae2020-08-12 16:40:362384 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Sylvain Defresnea8b73d252018-02-28 15:45:542385 self.assertEqual(1, len(errors))
2386 self.assertTrue('some/ios/file.mm' in errors[0].message)
2387 self.assertTrue('another/ios_file.mm' in errors[0].message)
2388 self.assertTrue('some/mac/file.mm' not in errors[0].message)
Peter K. Lee6c03ccff2019-07-15 14:40:052389 self.assertTrue('some/ios/file_egtest.mm' in errors[0].message)
2390 self.assertTrue('some/ios/file_unittest.mm' not in errors[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542391
Carlos Knippschildab192b8c2019-04-08 20:02:382392 def testBannedMojoFunctions(self):
2393 input_api = MockInputApi()
2394 input_api.files = [
2395 MockFile('some/cpp/problematic/file.cc',
2396 ['mojo::DataPipe();']),
Oksana Zhuravlovafd247772019-05-16 16:57:292397 MockFile('some/cpp/problematic/file2.cc',
2398 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382399 MockFile('some/cpp/ok/file.cc',
2400 ['CreateDataPipe();']),
Kinuko Yasuda376c2ce12019-04-16 01:20:372401 MockFile('some/cpp/ok/file2.cc',
2402 ['mojo::DataPipeDrainer();']),
Oksana Zhuravlovafd247772019-05-16 16:57:292403 MockFile('third_party/blink/ok/file3.cc',
2404 ['mojo::ConvertTo<>']),
2405 MockFile('content/renderer/ok/file3.cc',
2406 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382407 ]
2408
Saagar Sanghavifceeaae2020-08-12 16:40:362409 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222410
2411 # warnings are results[0], errors are results[1]
2412 self.assertEqual(2, len(results))
2413 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2414 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
2415 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
2416 self.assertTrue('some/cpp/ok/file2.cc' not in results[1].message)
2417 self.assertTrue('third_party/blink/ok/file3.cc' not in results[0].message)
2418 self.assertTrue('content/renderer/ok/file3.cc' not in results[0].message)
Carlos Knippschildab192b8c2019-04-08 20:02:382419
Mario Sanchez Prada2472cab2019-09-18 10:58:312420 def testDeprecatedMojoTypes(self):
Mario Sanchez Pradacec9cef2019-12-15 11:54:572421 ok_paths = ['components/arc']
2422 warning_paths = ['some/cpp']
Mario Sanchez Pradaaab91382019-12-19 08:57:092423 error_paths = ['third_party/blink', 'content']
Mario Sanchez Prada2472cab2019-09-18 10:58:312424 test_cases = [
2425 {
2426 'type': 'mojo::AssociatedBinding<>;',
2427 'file': 'file1.c'
2428 },
2429 {
2430 'type': 'mojo::AssociatedBindingSet<>;',
2431 'file': 'file2.c'
2432 },
2433 {
2434 'type': 'mojo::AssociatedInterfacePtr<>',
2435 'file': 'file3.cc'
2436 },
2437 {
2438 'type': 'mojo::AssociatedInterfacePtrInfo<>',
2439 'file': 'file4.cc'
2440 },
2441 {
2442 'type': 'mojo::AssociatedInterfaceRequest<>',
2443 'file': 'file5.cc'
2444 },
2445 {
2446 'type': 'mojo::Binding<>',
2447 'file': 'file6.cc'
2448 },
2449 {
2450 'type': 'mojo::BindingSet<>',
2451 'file': 'file7.cc'
2452 },
2453 {
2454 'type': 'mojo::InterfacePtr<>',
2455 'file': 'file8.cc'
2456 },
2457 {
2458 'type': 'mojo::InterfacePtrInfo<>',
2459 'file': 'file9.cc'
2460 },
2461 {
2462 'type': 'mojo::InterfaceRequest<>',
2463 'file': 'file10.cc'
2464 },
2465 {
2466 'type': 'mojo::MakeRequest()',
2467 'file': 'file11.cc'
2468 },
2469 {
2470 'type': 'mojo::MakeRequestAssociatedWithDedicatedPipe()',
2471 'file': 'file12.cc'
2472 },
2473 {
2474 'type': 'mojo::MakeStrongBinding()<>',
2475 'file': 'file13.cc'
2476 },
2477 {
2478 'type': 'mojo::MakeStrongAssociatedBinding()<>',
2479 'file': 'file14.cc'
2480 },
2481 {
Gyuyoung Kim4952ba62020-07-07 07:33:442482 'type': 'mojo::StrongAssociatedBinding<>',
Mario Sanchez Prada2472cab2019-09-18 10:58:312483 'file': 'file15.cc'
2484 },
2485 {
Gyuyoung Kim4952ba62020-07-07 07:33:442486 'type': 'mojo::StrongBinding<>',
Mario Sanchez Prada2472cab2019-09-18 10:58:312487 'file': 'file16.cc'
2488 },
Gyuyoung Kim4952ba62020-07-07 07:33:442489 {
2490 'type': 'mojo::StrongAssociatedBindingSet<>',
2491 'file': 'file17.cc'
2492 },
2493 {
2494 'type': 'mojo::StrongBindingSet<>',
2495 'file': 'file18.cc'
2496 },
Mario Sanchez Prada2472cab2019-09-18 10:58:312497 ]
2498
2499 # Build the list of MockFiles considering paths that should trigger warnings
Mario Sanchez Pradacec9cef2019-12-15 11:54:572500 # as well as paths that should trigger errors.
Mario Sanchez Prada2472cab2019-09-18 10:58:312501 input_api = MockInputApi()
2502 input_api.files = []
2503 for test_case in test_cases:
2504 for path in ok_paths:
2505 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2506 [test_case['type']]))
2507 for path in warning_paths:
2508 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2509 [test_case['type']]))
Mario Sanchez Pradacec9cef2019-12-15 11:54:572510 for path in error_paths:
2511 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2512 [test_case['type']]))
Mario Sanchez Prada2472cab2019-09-18 10:58:312513
Saagar Sanghavifceeaae2020-08-12 16:40:362514 results = PRESUBMIT.CheckNoDeprecatedMojoTypes(input_api, MockOutputApi())
Mario Sanchez Prada2472cab2019-09-18 10:58:312515
Mario Sanchez Pradacec9cef2019-12-15 11:54:572516 # warnings are results[0], errors are results[1]
2517 self.assertEqual(2, len(results))
Mario Sanchez Prada2472cab2019-09-18 10:58:312518
2519 for test_case in test_cases:
Mario Sanchez Pradacec9cef2019-12-15 11:54:572520 # Check that no warnings nor errors have been triggered for these paths.
Mario Sanchez Prada2472cab2019-09-18 10:58:312521 for path in ok_paths:
2522 self.assertFalse(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572523 self.assertFalse(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312524
2525 # Check warnings have been triggered for these paths.
2526 for path in warning_paths:
2527 self.assertTrue(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572528 self.assertFalse(path in results[1].message)
2529
2530 # Check errors have been triggered for these paths.
2531 for path in error_paths:
2532 self.assertFalse(path in results[0].message)
2533 self.assertTrue(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312534
Sylvain Defresnea8b73d252018-02-28 15:45:542535
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272536class NoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:242537 def testTruePositives(self):
2538 mock_input_api = MockInputApi()
2539 mock_input_api.files = [
2540 MockFile('some/path/foo.cc', ['foo_for_testing();']),
2541 MockFile('some/path/foo.mm', ['FooForTesting();']),
2542 MockFile('some/path/foo.cxx', ['FooForTests();']),
2543 MockFile('some/path/foo.cpp', ['foo_for_test();']),
2544 ]
2545
Saagar Sanghavifceeaae2020-08-12 16:40:362546 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242547 mock_input_api, MockOutputApi())
2548 self.assertEqual(1, len(results))
2549 self.assertEqual(4, len(results[0].items))
2550 self.assertTrue('foo.cc' in results[0].items[0])
2551 self.assertTrue('foo.mm' in results[0].items[1])
2552 self.assertTrue('foo.cxx' in results[0].items[2])
2553 self.assertTrue('foo.cpp' in results[0].items[3])
2554
2555 def testFalsePositives(self):
2556 mock_input_api = MockInputApi()
2557 mock_input_api.files = [
2558 MockFile('some/path/foo.h', ['foo_for_testing();']),
2559 MockFile('some/path/foo.mm', ['FooForTesting() {']),
2560 MockFile('some/path/foo.cc', ['::FooForTests();']),
2561 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
2562 ]
2563
Saagar Sanghavifceeaae2020-08-12 16:40:362564 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242565 mock_input_api, MockOutputApi())
2566 self.assertEqual(0, len(results))
2567
2568
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272569class NoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:232570 def testTruePositives(self):
2571 mock_input_api = MockInputApi()
2572 mock_input_api.files = [
2573 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
2574 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392575 MockFile('dir/java/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232576 MockFile('dir/java/src/mult.java', [
2577 'int x = SomethingLongHere()',
2578 ' * SomethingLongHereForTesting();'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392579 ])
Vaclav Brozek7dbc28c2018-03-27 08:35:232580 ]
2581
Saagar Sanghavifceeaae2020-08-12 16:40:362582 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232583 mock_input_api, MockOutputApi())
2584 self.assertEqual(1, len(results))
2585 self.assertEqual(4, len(results[0].items))
2586 self.assertTrue('foo.java' in results[0].items[0])
2587 self.assertTrue('bar.java' in results[0].items[1])
2588 self.assertTrue('baz.java' in results[0].items[2])
2589 self.assertTrue('mult.java' in results[0].items[3])
2590
2591 def testFalsePositives(self):
2592 mock_input_api = MockInputApi()
2593 mock_input_api.files = [
2594 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
2595 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
2596 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
2597 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
Sky Malice9e6d6032020-10-15 22:49:552598 MockFile('dir/java/src/bar3.java', ['@VisibleForTesting']),
2599 MockFile('dir/java/src/bar4.java', ['@VisibleForTesting()']),
2600 MockFile('dir/java/src/bar5.java', [
2601 '@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)'
2602 ]),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392603 MockFile('dir/javatests/src/baz.java', ['FooForTest(', 'y', ');']),
2604 MockFile('dir/junit/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232605 MockFile('dir/junit/src/javadoc.java', [
2606 '/** Use FooForTest(); to obtain foo in tests.'
2607 ' */'
2608 ]),
2609 MockFile('dir/junit/src/javadoc2.java', [
2610 '/** ',
2611 ' * Use FooForTest(); to obtain foo in tests.'
2612 ' */'
2613 ]),
2614 ]
2615
Saagar Sanghavifceeaae2020-08-12 16:40:362616 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232617 mock_input_api, MockOutputApi())
2618 self.assertEqual(0, len(results))
2619
2620
Mohamed Heikald048240a2019-11-12 16:57:372621class NewImagesWarningTest(unittest.TestCase):
2622 def testTruePositives(self):
2623 mock_input_api = MockInputApi()
2624 mock_input_api.files = [
2625 MockFile('dir/android/res/drawable/foo.png', []),
2626 MockFile('dir/android/res/drawable-v21/bar.svg', []),
2627 MockFile('dir/android/res/mipmap-v21-en/baz.webp', []),
2628 MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png', []),
2629 ]
2630
2631 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2632 self.assertEqual(1, len(results))
2633 self.assertEqual(4, len(results[0].items))
2634 self.assertTrue('foo.png' in results[0].items[0].LocalPath())
2635 self.assertTrue('bar.svg' in results[0].items[1].LocalPath())
2636 self.assertTrue('baz.webp' in results[0].items[2].LocalPath())
2637 self.assertTrue('foobar.png' in results[0].items[3].LocalPath())
2638
2639 def testFalsePositives(self):
2640 mock_input_api = MockInputApi()
2641 mock_input_api.files = [
2642 MockFile('dir/pngs/README.md', []),
2643 MockFile('java/test/res/drawable/foo.png', []),
2644 MockFile('third_party/blink/foo.png', []),
2645 MockFile('dir/third_party/libpng/src/foo.cc', ['foobar']),
2646 MockFile('dir/resources.webp/.gitignore', ['foo.png']),
2647 ]
2648
2649 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2650 self.assertEqual(0, len(results))
2651
2652
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272653class CheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:052654 def testTruePositivesNullptr(self):
2655 mock_input_api = MockInputApi()
2656 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162657 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
2658 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
Vaclav Brozek851d9602018-04-04 16:13:052659 ]
2660
Saagar Sanghavifceeaae2020-08-12 16:40:362661 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052662 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162663 self.assertTrue('nullptr' in results[0].message)
Vaclav Brozek851d9602018-04-04 16:13:052664 self.assertEqual(2, len(results[0].items))
2665 self.assertTrue('baz.cc' in results[0].items[0])
2666 self.assertTrue('baz-p.cc' in results[0].items[1])
2667
2668 def testTruePositivesConstructor(self):
Vaclav Brozek52e18bf2018-04-03 07:05:242669 mock_input_api = MockInputApi()
2670 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162671 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
2672 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
2673 MockFile('dir/mult.cc', [
Vaclav Brozek95face62018-04-04 14:15:112674 'return',
2675 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
2676 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162677 MockFile('dir/mult2.cc', [
Vaclav Brozek95face62018-04-04 14:15:112678 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
2679 ' std::unique_ptr<T>(foo);'
2680 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162681 MockFile('dir/mult3.cc', [
Vaclav Brozek95face62018-04-04 14:15:112682 'bar = std::unique_ptr<T>(',
2683 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
2684 ]),
Vaclav Brozekb7fadb692018-08-30 06:39:532685 MockFile('dir/multi_arg.cc', [
2686 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']),
Vaclav Brozek52e18bf2018-04-03 07:05:242687 ]
2688
Saagar Sanghavifceeaae2020-08-12 16:40:362689 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052690 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162691 self.assertTrue('std::make_unique' in results[0].message)
Vaclav Brozekb7fadb692018-08-30 06:39:532692 self.assertEqual(6, len(results[0].items))
Vaclav Brozek851d9602018-04-04 16:13:052693 self.assertTrue('foo.cc' in results[0].items[0])
2694 self.assertTrue('bar.mm' in results[0].items[1])
2695 self.assertTrue('mult.cc' in results[0].items[2])
2696 self.assertTrue('mult2.cc' in results[0].items[3])
2697 self.assertTrue('mult3.cc' in results[0].items[4])
Vaclav Brozekb7fadb692018-08-30 06:39:532698 self.assertTrue('multi_arg.cc' in results[0].items[5])
Vaclav Brozek52e18bf2018-04-03 07:05:242699
2700 def testFalsePositives(self):
2701 mock_input_api = MockInputApi()
2702 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162703 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
2704 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
2705 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
2706 MockFile('dir/baz.cc', [
Vaclav Brozek52e18bf2018-04-03 07:05:242707 'std::unique_ptr<T> result = std::make_unique<T>();'
2708 ]),
Vaclav Brozeka54c528b2018-04-06 19:23:552709 MockFile('dir/baz2.cc', [
2710 'std::unique_ptr<T> result = std::make_unique<T>('
2711 ]),
2712 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
2713 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
Vaclav Brozekb7fadb692018-08-30 06:39:532714
2715 # Two-argument invocation of std::unique_ptr is exempt because there is
2716 # no equivalent using std::make_unique.
2717 MockFile('dir/multi_arg.cc', [
2718 'auto p = std::unique_ptr<T, D>(new T(), D());']),
Vaclav Brozek52e18bf2018-04-03 07:05:242719 ]
2720
Saagar Sanghavifceeaae2020-08-12 16:40:362721 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek52e18bf2018-04-03 07:05:242722 self.assertEqual(0, len(results))
2723
Danil Chapovalov3518f362018-08-11 16:13:432724class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
2725 def testBlocksDirectIncludes(self):
2726 mock_input_api = MockInputApi()
2727 mock_input_api.files = [
2728 MockFile('dir/foo_win.cc', ['#include "shlwapi.h"']),
2729 MockFile('dir/bar.h', ['#include <propvarutil.h>']),
2730 MockFile('dir/baz.h', ['#include <atlbase.h>']),
2731 MockFile('dir/jumbo.h', ['#include "sphelper.h"']),
2732 ]
2733 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2734 self.assertEquals(1, len(results))
2735 self.assertEquals(4, len(results[0].items))
2736 self.assertTrue('StrCat' in results[0].message)
2737 self.assertTrue('foo_win.cc' in results[0].items[0])
2738 self.assertTrue('bar.h' in results[0].items[1])
2739 self.assertTrue('baz.h' in results[0].items[2])
2740 self.assertTrue('jumbo.h' in results[0].items[3])
2741
2742 def testAllowsToIncludeWrapper(self):
2743 mock_input_api = MockInputApi()
2744 mock_input_api.files = [
2745 MockFile('dir/baz_win.cc', ['#include "base/win/shlwapi.h"']),
2746 MockFile('dir/baz-win.h', ['#include "base/win/atl.h"']),
2747 ]
2748 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2749 self.assertEquals(0, len(results))
2750
2751 def testAllowsToCreateWrapper(self):
2752 mock_input_api = MockInputApi()
2753 mock_input_api.files = [
2754 MockFile('base/win/shlwapi.h', [
2755 '#include <shlwapi.h>',
2756 '#include "base/win/windows_defines.inc"']),
2757 ]
2758 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2759 self.assertEquals(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:242760
Mustafa Emre Acer51f2f742020-03-09 19:41:122761
Rainhard Findlingfc31844c52020-05-15 09:58:262762class StringTest(unittest.TestCase):
2763 """Tests ICU syntax check and translation screenshots check."""
2764
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142765 # An empty grd file.
2766 OLD_GRD_CONTENTS = """<?xml version="1.0" encoding="UTF-8"?>
2767 <grit latest_public_release="1" current_release="1">
2768 <release seq="1">
2769 <messages></messages>
2770 </release>
2771 </grit>
2772 """.splitlines()
2773 # A grd file with a single message.
2774 NEW_GRD_CONTENTS1 = """<?xml version="1.0" encoding="UTF-8"?>
2775 <grit latest_public_release="1" current_release="1">
2776 <release seq="1">
2777 <messages>
2778 <message name="IDS_TEST1">
2779 Test string 1
2780 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482781 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE1"
2782 translateable="false">
2783 Non translateable message 1, should be ignored
2784 </message>
Mustafa Emre Acered1a48962020-06-30 19:15:392785 <message name="IDS_TEST_STRING_ACCESSIBILITY"
Mustafa Emre Acerd3ca8be2020-07-07 22:35:342786 is_accessibility_with_no_ui="true">
Mustafa Emre Acered1a48962020-06-30 19:15:392787 Accessibility label 1, should be ignored
2788 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142789 </messages>
2790 </release>
2791 </grit>
2792 """.splitlines()
2793 # A grd file with two messages.
2794 NEW_GRD_CONTENTS2 = """<?xml version="1.0" encoding="UTF-8"?>
2795 <grit latest_public_release="1" current_release="1">
2796 <release seq="1">
2797 <messages>
2798 <message name="IDS_TEST1">
2799 Test string 1
2800 </message>
2801 <message name="IDS_TEST2">
2802 Test string 2
2803 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482804 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE2"
2805 translateable="false">
2806 Non translateable message 2, should be ignored
2807 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142808 </messages>
2809 </release>
2810 </grit>
2811 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:262812 # A grd file with one ICU syntax message without syntax errors.
2813 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1 = """<?xml version="1.0" encoding="UTF-8"?>
2814 <grit latest_public_release="1" current_release="1">
2815 <release seq="1">
2816 <messages>
2817 <message name="IDS_TEST1">
2818 {NUM, plural,
2819 =1 {Test text for numeric one}
2820 other {Test text for plural with {NUM} as number}}
2821 </message>
2822 </messages>
2823 </release>
2824 </grit>
2825 """.splitlines()
2826 # A grd file with one ICU syntax message without syntax errors.
2827 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2 = """<?xml version="1.0" encoding="UTF-8"?>
2828 <grit latest_public_release="1" current_release="1">
2829 <release seq="1">
2830 <messages>
2831 <message name="IDS_TEST1">
2832 {NUM, plural,
2833 =1 {Different test text for numeric one}
2834 other {Different test text for plural with {NUM} as number}}
2835 </message>
2836 </messages>
2837 </release>
2838 </grit>
2839 """.splitlines()
2840 # A grd file with one ICU syntax message with syntax errors (misses a comma).
2841 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
2842 <grit latest_public_release="1" current_release="1">
2843 <release seq="1">
2844 <messages>
2845 <message name="IDS_TEST1">
2846 {NUM, plural
2847 =1 {Test text for numeric one}
2848 other {Test text for plural with {NUM} as number}}
2849 </message>
2850 </messages>
2851 </release>
2852 </grit>
2853 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142854
meacerff8a9b62019-12-10 19:43:582855 OLD_GRDP_CONTENTS = (
2856 '<?xml version="1.0" encoding="utf-8"?>',
2857 '<grit-part>',
2858 '</grit-part>'
2859 )
2860
2861 NEW_GRDP_CONTENTS1 = (
2862 '<?xml version="1.0" encoding="utf-8"?>',
2863 '<grit-part>',
2864 '<message name="IDS_PART_TEST1">',
2865 'Part string 1',
2866 '</message>',
2867 '</grit-part>')
2868
2869 NEW_GRDP_CONTENTS2 = (
2870 '<?xml version="1.0" encoding="utf-8"?>',
2871 '<grit-part>',
2872 '<message name="IDS_PART_TEST1">',
2873 'Part string 1',
2874 '</message>',
2875 '<message name="IDS_PART_TEST2">',
2876 'Part string 2',
2877 '</message>',
2878 '</grit-part>')
2879
Rainhard Findlingd8d04372020-08-13 13:30:092880 NEW_GRDP_CONTENTS3 = (
2881 '<?xml version="1.0" encoding="utf-8"?>',
2882 '<grit-part>',
2883 '<message name="IDS_PART_TEST1" desc="Description with typo.">',
2884 'Part string 1',
2885 '</message>',
2886 '</grit-part>')
2887
2888 NEW_GRDP_CONTENTS4 = (
2889 '<?xml version="1.0" encoding="utf-8"?>',
2890 '<grit-part>',
2891 '<message name="IDS_PART_TEST1" desc="Description with typo fixed.">',
2892 'Part string 1',
2893 '</message>',
2894 '</grit-part>')
2895
Rainhard Findling1a3e71e2020-09-21 07:33:352896 NEW_GRDP_CONTENTS5 = (
2897 '<?xml version="1.0" encoding="utf-8"?>',
2898 '<grit-part>',
2899 '<message name="IDS_PART_TEST1" meaning="Meaning with typo.">',
2900 'Part string 1',
2901 '</message>',
2902 '</grit-part>')
2903
2904 NEW_GRDP_CONTENTS6 = (
2905 '<?xml version="1.0" encoding="utf-8"?>',
2906 '<grit-part>',
2907 '<message name="IDS_PART_TEST1" meaning="Meaning with typo fixed.">',
2908 'Part string 1',
2909 '</message>',
2910 '</grit-part>')
2911
Rainhard Findlingfc31844c52020-05-15 09:58:262912 # A grdp file with one ICU syntax message without syntax errors.
2913 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = (
2914 '<?xml version="1.0" encoding="utf-8"?>',
2915 '<grit-part>',
2916 '<message name="IDS_PART_TEST1">',
2917 '{NUM, plural,',
2918 '=1 {Test text for numeric one}',
2919 'other {Test text for plural with {NUM} as number}}',
2920 '</message>',
2921 '</grit-part>')
2922 # A grdp file with one ICU syntax message without syntax errors.
2923 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2 = (
2924 '<?xml version="1.0" encoding="utf-8"?>',
2925 '<grit-part>',
2926 '<message name="IDS_PART_TEST1">',
2927 '{NUM, plural,',
2928 '=1 {Different test text for numeric one}',
2929 'other {Different test text for plural with {NUM} as number}}',
2930 '</message>',
2931 '</grit-part>')
2932
2933 # A grdp file with one ICU syntax message with syntax errors (superfluent
2934 # whitespace).
2935 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR = (
2936 '<?xml version="1.0" encoding="utf-8"?>',
2937 '<grit-part>',
2938 '<message name="IDS_PART_TEST1">',
2939 '{NUM, plural,',
2940 '= 1 {Test text for numeric one}',
2941 'other {Test text for plural with {NUM} as number}}',
2942 '</message>',
2943 '</grit-part>')
2944
Mustafa Emre Acerc8a012d2018-07-31 00:00:392945 DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
2946 'changelist. Run '
2947 'tools/translate/upload_screenshots.py to '
2948 'upload them instead:')
2949 GENERATE_SIGNATURES_MESSAGE = ('You are adding or modifying UI strings.\n'
2950 'To ensure the best translations, take '
2951 'screenshots of the relevant UI '
2952 '(https://g.co/chrome/translation) and add '
2953 'these files to your changelist:')
2954 REMOVE_SIGNATURES_MESSAGE = ('You removed strings associated with these '
2955 'files. Remove:')
Rainhard Findlingfc31844c52020-05-15 09:58:262956 ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
2957 'strings (problems or feedback? Contact '
2958 '[email protected]):')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142959
2960 def makeInputApi(self, files):
2961 input_api = MockInputApi()
2962 input_api.files = files
meacere7be7532019-10-02 17:41:032963 # Override os_path.exists because the presubmit uses the actual
2964 # os.path.exists.
2965 input_api.CreateMockFileInPath(
2966 [x.LocalPath() for x in input_api.AffectedFiles(include_deletes=True)])
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142967 return input_api
2968
meacerff8a9b62019-12-10 19:43:582969 """ CL modified and added messages, but didn't add any screenshots."""
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142970 def testNoScreenshots(self):
meacerff8a9b62019-12-10 19:43:582971 # No new strings (file contents same). Should not warn.
2972 input_api = self.makeInputApi([
2973 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
2974 self.NEW_GRD_CONTENTS1, action='M'),
2975 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1,
2976 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362977 warnings = PRESUBMIT.CheckStrings(input_api,
meacerff8a9b62019-12-10 19:43:582978 MockOutputApi())
2979 self.assertEqual(0, len(warnings))
2980
2981 # Add two new strings. Should have two warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142982 input_api = self.makeInputApi([
2983 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582984 self.NEW_GRD_CONTENTS1, action='M'),
2985 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2986 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362987 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142988 MockOutputApi())
2989 self.assertEqual(1, len(warnings))
2990 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerc6ed2682020-07-07 07:24:002991 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012992 self.assertEqual([
meacerff8a9b62019-12-10 19:43:582993 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2994 os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
2995 warnings[0].items)
Mustafa Emre Acer36eaad52019-11-12 23:03:342996
meacerff8a9b62019-12-10 19:43:582997 # Add four new strings. Should have four warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:212998 input_api = self.makeInputApi([
2999 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:583000 self.OLD_GRD_CONTENTS, action='M'),
3001 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
3002 self.OLD_GRDP_CONTENTS, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363003 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213004 MockOutputApi())
3005 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003006 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213007 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583008 self.assertEqual([
3009 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3010 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3011 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3012 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3013 ], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213014
Rainhard Findlingd8d04372020-08-13 13:30:093015 def testModifiedMessageDescription(self):
3016 # CL modified a message description for a message that does not yet have a
Rainhard Findling1a3e71e2020-09-21 07:33:353017 # screenshot. Should not warn.
Rainhard Findlingd8d04372020-08-13 13:30:093018 input_api = self.makeInputApi([
3019 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
3020 self.NEW_GRDP_CONTENTS4, action='M')])
3021 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findling1a3e71e2020-09-21 07:33:353022 self.assertEqual(0, len(warnings))
Rainhard Findlingd8d04372020-08-13 13:30:093023
3024 # CL modified a message description for a message that already has a
3025 # screenshot. Should not warn.
3026 input_api = self.makeInputApi([
3027 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
3028 self.NEW_GRDP_CONTENTS4, action='M'),
3029 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3030 'binary', action='A')])
3031 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3032 self.assertEqual(0, len(warnings))
3033
Rainhard Findling1a3e71e2020-09-21 07:33:353034 def testModifiedMessageMeaning(self):
3035 # CL modified a message meaning for a message that does not yet have a
3036 # screenshot. Should warn.
3037 input_api = self.makeInputApi([
3038 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3039 self.NEW_GRDP_CONTENTS6, action='M')])
3040 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3041 self.assertEqual(1, len(warnings))
3042
3043 # CL modified a message meaning for a message that already has a
3044 # screenshot. Should not warn.
3045 input_api = self.makeInputApi([
3046 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3047 self.NEW_GRDP_CONTENTS6, action='M'),
3048 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3049 'binary', action='A')])
3050 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3051 self.assertEqual(0, len(warnings))
3052
meacerff8a9b62019-12-10 19:43:583053 def testPngAddedSha1NotAdded(self):
3054 # CL added one new message in a grd file and added the png file associated
3055 # with it, but did not add the corresponding sha1 file. This should warn
3056 # twice:
3057 # - Once for the added png file (because we don't want developers to upload
3058 # actual images)
3059 # - Once for the missing .sha1 file
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143060 input_api = self.makeInputApi([
Mustafa Emre Acerea3e57a2018-12-17 23:51:013061 MockAffectedFile(
3062 'test.grd',
3063 self.NEW_GRD_CONTENTS1,
3064 self.OLD_GRD_CONTENTS,
3065 action='M'),
3066 MockAffectedFile(
3067 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
3068 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363069 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143070 MockOutputApi())
3071 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003072 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143073 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013074 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
3075 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003076 self.assertEqual('error', warnings[1].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143077 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013078 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3079 warnings[1].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143080
meacerff8a9b62019-12-10 19:43:583081 # CL added two messages (one in grd, one in grdp) and added the png files
3082 # associated with the messages, but did not add the corresponding sha1
3083 # files. This should warn twice:
3084 # - Once for the added png files (because we don't want developers to upload
3085 # actual images)
3086 # - Once for the missing .sha1 files
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143087 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583088 # Modified files:
Mustafa Emre Acer36eaad52019-11-12 23:03:343089 MockAffectedFile(
3090 'test.grd',
meacerff8a9b62019-12-10 19:43:583091 self.NEW_GRD_CONTENTS1,
Mustafa Emre Acer36eaad52019-11-12 23:03:343092 self.OLD_GRD_CONTENTS,
meacer2308d0742019-11-12 18:15:423093 action='M'),
Mustafa Emre Acer12e7fee2019-11-18 18:49:553094 MockAffectedFile(
meacerff8a9b62019-12-10 19:43:583095 'part.grdp',
3096 self.NEW_GRDP_CONTENTS1,
3097 self.OLD_GRDP_CONTENTS,
3098 action='M'),
3099 # Added files:
3100 MockAffectedFile(
3101 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A'),
3102 MockAffectedFile(
3103 os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary',
3104 action='A')
Mustafa Emre Acerad8fb082019-11-19 04:24:213105 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363106 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213107 MockOutputApi())
3108 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003109 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213110 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583111 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png'),
3112 os.path.join('test_grd', 'IDS_TEST1.png')],
Mustafa Emre Acerad8fb082019-11-19 04:24:213113 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003114 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213115 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
meacerff8a9b62019-12-10 19:43:583116 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3117 os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3118 warnings[1].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213119
3120 def testScreenshotsWithSha1(self):
meacerff8a9b62019-12-10 19:43:583121 # CL added four messages (two each in a grd and grdp) and their
3122 # corresponding .sha1 files. No warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213123 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583124 # Modified files:
Mustafa Emre Acerad8fb082019-11-19 04:24:213125 MockAffectedFile(
3126 'test.grd',
3127 self.NEW_GRD_CONTENTS2,
3128 self.OLD_GRD_CONTENTS,
Mustafa Emre Acer12e7fee2019-11-18 18:49:553129 action='M'),
meacerff8a9b62019-12-10 19:43:583130 MockAffectedFile(
3131 'part.grdp',
3132 self.NEW_GRDP_CONTENTS2,
3133 self.OLD_GRDP_CONTENTS,
3134 action='M'),
3135 # Added files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013136 MockFile(
3137 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3138 'binary',
3139 action='A'),
3140 MockFile(
3141 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3142 'binary',
meacerff8a9b62019-12-10 19:43:583143 action='A'),
3144 MockFile(
3145 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3146 'binary',
3147 action='A'),
3148 MockFile(
3149 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3150 'binary',
3151 action='A'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013152 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363153 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143154 MockOutputApi())
3155 self.assertEqual([], warnings)
3156
3157 def testScreenshotsRemovedWithSha1(self):
meacerff8a9b62019-12-10 19:43:583158 # Replace new contents with old contents in grd and grp files, removing
3159 # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3160 # Should warn to remove the sha1 files associated with these strings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143161 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583162 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013163 MockAffectedFile(
3164 'test.grd',
meacerff8a9b62019-12-10 19:43:583165 self.OLD_GRD_CONTENTS, # new_contents
3166 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013167 action='M'),
meacerff8a9b62019-12-10 19:43:583168 MockAffectedFile(
3169 'part.grdp',
3170 self.OLD_GRDP_CONTENTS, # new_contents
3171 self.NEW_GRDP_CONTENTS2, # old_contents
3172 action='M'),
3173 # Unmodified files:
3174 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
3175 MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', ''),
3176 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3177 'binary', ''),
3178 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3179 'binary', '')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013180 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363181 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143182 MockOutputApi())
3183 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003184 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143185 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013186 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583187 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3188 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013189 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3190 os.path.join('test_grd', 'IDS_TEST2.png.sha1')
3191 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143192
meacerff8a9b62019-12-10 19:43:583193 # Same as above, but this time one of the .sha1 files is also removed.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143194 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583195 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013196 MockAffectedFile(
3197 'test.grd',
meacerff8a9b62019-12-10 19:43:583198 self.OLD_GRD_CONTENTS, # new_contents
3199 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013200 action='M'),
meacerff8a9b62019-12-10 19:43:583201 MockAffectedFile(
3202 'part.grdp',
3203 self.OLD_GRDP_CONTENTS, # new_contents
3204 self.NEW_GRDP_CONTENTS2, # old_contents
3205 action='M'),
3206 # Unmodified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013207 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
meacerff8a9b62019-12-10 19:43:583208 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3209 'binary', ''),
3210 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013211 MockAffectedFile(
3212 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3213 '',
3214 'old_contents',
meacerff8a9b62019-12-10 19:43:583215 action='D'),
3216 MockAffectedFile(
3217 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3218 '',
3219 'old_contents',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013220 action='D')
3221 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363222 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143223 MockOutputApi())
3224 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003225 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143226 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583227 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3228 os.path.join('test_grd', 'IDS_TEST1.png.sha1')
3229 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143230
meacerff8a9b62019-12-10 19:43:583231 # Remove all sha1 files. There should be no warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143232 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583233 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013234 MockAffectedFile(
3235 'test.grd',
3236 self.OLD_GRD_CONTENTS,
3237 self.NEW_GRD_CONTENTS2,
3238 action='M'),
meacerff8a9b62019-12-10 19:43:583239 MockAffectedFile(
3240 'part.grdp',
3241 self.OLD_GRDP_CONTENTS,
3242 self.NEW_GRDP_CONTENTS2,
3243 action='M'),
3244 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013245 MockFile(
3246 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3247 'binary',
3248 action='D'),
3249 MockFile(
3250 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3251 'binary',
meacerff8a9b62019-12-10 19:43:583252 action='D'),
3253 MockFile(
3254 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3255 'binary',
3256 action='D'),
3257 MockFile(
3258 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3259 'binary',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013260 action='D')
3261 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363262 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143263 MockOutputApi())
3264 self.assertEqual([], warnings)
3265
Rainhard Findlingfc31844c52020-05-15 09:58:263266 def testIcuSyntax(self):
3267 # Add valid ICU syntax string. Should not raise an error.
3268 input_api = self.makeInputApi([
3269 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3270 self.NEW_GRD_CONTENTS1, action='M'),
3271 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3272 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363273 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263274 # We expect no ICU syntax errors.
3275 icu_errors = [e for e in results
3276 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3277 self.assertEqual(0, len(icu_errors))
3278
3279 # Valid changes in ICU syntax. Should not raise an error.
3280 input_api = self.makeInputApi([
3281 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3282 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3283 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3284 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363285 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263286 # We expect no ICU syntax errors.
3287 icu_errors = [e for e in results
3288 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3289 self.assertEqual(0, len(icu_errors))
3290
3291 # Add invalid ICU syntax strings. Should raise two errors.
3292 input_api = self.makeInputApi([
3293 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3294 self.NEW_GRD_CONTENTS1, action='M'),
3295 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3296 self.NEW_GRD_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363297 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263298 # We expect 2 ICU syntax errors.
3299 icu_errors = [e for e in results
3300 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3301 self.assertEqual(1, len(icu_errors))
3302 self.assertEqual([
3303 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3304 'ICU syntax.',
3305 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3306 ], icu_errors[0].items)
3307
3308 # Change two strings to have ICU syntax errors. Should raise two errors.
3309 input_api = self.makeInputApi([
3310 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3311 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3312 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3313 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363314 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263315 # We expect 2 ICU syntax errors.
3316 icu_errors = [e for e in results
3317 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3318 self.assertEqual(1, len(icu_errors))
3319 self.assertEqual([
3320 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3321 'ICU syntax.',
3322 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3323 ], icu_errors[0].items)
3324
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143325
Mustafa Emre Acer51f2f742020-03-09 19:41:123326class TranslationExpectationsTest(unittest.TestCase):
3327 ERROR_MESSAGE_FORMAT = (
3328 "Failed to get a list of translatable grd files. "
3329 "This happens when:\n"
3330 " - One of the modified grd or grdp files cannot be parsed or\n"
3331 " - %s is not updated.\n"
3332 "Stack:\n"
3333 )
3334 REPO_ROOT = os.path.join('tools', 'translation', 'testdata')
3335 # This lists all .grd files under REPO_ROOT.
3336 EXPECTATIONS = os.path.join(REPO_ROOT,
3337 "translation_expectations.pyl")
3338 # This lists all .grd files under REPO_ROOT except unlisted.grd.
3339 EXPECTATIONS_WITHOUT_UNLISTED_FILE = os.path.join(
3340 REPO_ROOT, "translation_expectations_without_unlisted_file.pyl")
3341
3342 # Tests that the presubmit doesn't return when no grd or grdp files are
3343 # modified.
3344 def testExpectationsNoModifiedGrd(self):
3345 input_api = MockInputApi()
3346 input_api.files = [
3347 MockAffectedFile('not_used.txt', 'not used', 'not used', action='M')
3348 ]
3349 # Fake list of all grd files in the repo. This list is missing all grd/grdps
3350 # under tools/translation/testdata. This is OK because the presubmit won't
3351 # run in the first place since there are no modified grd/grps in input_api.
3352 grd_files = ['doesnt_exist_doesnt_matter.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363353 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123354 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3355 grd_files)
3356 self.assertEqual(0, len(warnings))
3357
3358
3359 # Tests that the list of files passed to the presubmit matches the list of
3360 # files in the expectations.
3361 def testExpectationsSuccess(self):
3362 # Mock input file list needs a grd or grdp file in order to run the
3363 # presubmit. The file itself doesn't matter.
3364 input_api = MockInputApi()
3365 input_api.files = [
3366 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3367 ]
3368 # List of all grd files in the repo.
3369 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3370 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363371 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123372 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3373 grd_files)
3374 self.assertEqual(0, len(warnings))
3375
3376 # Tests that the presubmit warns when a file is listed in expectations, but
3377 # does not actually exist.
3378 def testExpectationsMissingFile(self):
3379 # Mock input file list needs a grd or grdp file in order to run the
3380 # presubmit.
3381 input_api = MockInputApi()
3382 input_api.files = [
3383 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3384 ]
3385 # unlisted.grd is listed under tools/translation/testdata but is not
3386 # included in translation expectations.
3387 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363388 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123389 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3390 grd_files)
3391 self.assertEqual(1, len(warnings))
3392 self.assertTrue(warnings[0].message.startswith(
3393 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS))
3394 self.assertTrue(
3395 ("test.grd is listed in the translation expectations, "
3396 "but this grd file does not exist")
3397 in warnings[0].message)
3398
3399 # Tests that the presubmit warns when a file is not listed in expectations but
3400 # does actually exist.
3401 def testExpectationsUnlistedFile(self):
3402 # Mock input file list needs a grd or grdp file in order to run the
3403 # presubmit.
3404 input_api = MockInputApi()
3405 input_api.files = [
3406 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3407 ]
3408 # unlisted.grd is listed under tools/translation/testdata but is not
3409 # included in translation expectations.
3410 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3411 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363412 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123413 input_api, MockOutputApi(), self.REPO_ROOT,
3414 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3415 self.assertEqual(1, len(warnings))
3416 self.assertTrue(warnings[0].message.startswith(
3417 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3418 self.assertTrue(
3419 ("unlisted.grd appears to be translatable "
3420 "(because it contains <file> or <message> elements), "
3421 "but is not listed in the translation expectations.")
3422 in warnings[0].message)
3423
3424 # Tests that the presubmit warns twice:
3425 # - for a non-existing file listed in expectations
3426 # - for an existing file not listed in expectations
3427 def testMultipleWarnings(self):
3428 # Mock input file list needs a grd or grdp file in order to run the
3429 # presubmit.
3430 input_api = MockInputApi()
3431 input_api.files = [
3432 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3433 ]
3434 # unlisted.grd is listed under tools/translation/testdata but is not
3435 # included in translation expectations.
3436 # test.grd is not listed under tools/translation/testdata but is included
3437 # in translation expectations.
3438 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363439 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123440 input_api, MockOutputApi(), self.REPO_ROOT,
3441 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3442 self.assertEqual(1, len(warnings))
3443 self.assertTrue(warnings[0].message.startswith(
3444 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3445 self.assertTrue(
3446 ("unlisted.grd appears to be translatable "
3447 "(because it contains <file> or <message> elements), "
3448 "but is not listed in the translation expectations.")
3449 in warnings[0].message)
3450 self.assertTrue(
3451 ("test.grd is listed in the translation expectations, "
3452 "but this grd file does not exist")
3453 in warnings[0].message)
3454
3455
Dominic Battre033531052018-09-24 15:45:343456class DISABLETypoInTest(unittest.TestCase):
3457
3458 def testPositive(self):
3459 # Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
3460 # where the desire is to disable a test.
3461 tests = [
3462 # Disabled on one platform:
3463 '#if defined(OS_WIN)\n'
3464 '#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
3465 '#else\n'
3466 '#define MAYBE_FoobarTest FoobarTest\n'
3467 '#endif\n',
3468 # Disabled on one platform spread cross lines:
3469 '#if defined(OS_WIN)\n'
3470 '#define MAYBE_FoobarTest \\\n'
3471 ' DISABLE_FoobarTest\n'
3472 '#else\n'
3473 '#define MAYBE_FoobarTest FoobarTest\n'
3474 '#endif\n',
3475 # Disabled on all platforms:
3476 ' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
3477 # Disabled on all platforms but multiple lines
3478 ' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
3479 ]
3480
3481 for test in tests:
3482 mock_input_api = MockInputApi()
3483 mock_input_api.files = [
3484 MockFile('some/path/foo_unittest.cc', test.splitlines()),
3485 ]
3486
Saagar Sanghavifceeaae2020-08-12 16:40:363487 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343488 MockOutputApi())
3489 self.assertEqual(
3490 1,
3491 len(results),
3492 msg=('expected len(results) == 1 but got %d in test: %s' %
3493 (len(results), test)))
3494 self.assertTrue(
3495 'foo_unittest.cc' in results[0].message,
3496 msg=('expected foo_unittest.cc in message but got %s in test %s' %
3497 (results[0].message, test)))
3498
3499 def testIngoreNotTestFiles(self):
3500 mock_input_api = MockInputApi()
3501 mock_input_api.files = [
3502 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'),
3503 ]
3504
Saagar Sanghavifceeaae2020-08-12 16:40:363505 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343506 MockOutputApi())
3507 self.assertEqual(0, len(results))
3508
Katie Df13948e2018-09-25 07:33:443509 def testIngoreDeletedFiles(self):
3510 mock_input_api = MockInputApi()
3511 mock_input_api.files = [
3512 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'),
3513 ]
3514
Saagar Sanghavifceeaae2020-08-12 16:40:363515 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Katie Df13948e2018-09-25 07:33:443516 MockOutputApi())
3517 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:343518
Dirk Pranke3c18a382019-03-15 01:07:513519
3520class BuildtoolsRevisionsAreInSyncTest(unittest.TestCase):
3521 # TODO(crbug.com/941824): We need to make sure the entries in
3522 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3523 # so that users of //buildtools in other projects get the same tooling
3524 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3525 # support to gclient, we can eliminate the duplication and delete
3526 # these tests for the corresponding presubmit check.
3527
3528 def _check(self, files):
3529 mock_input_api = MockInputApi()
3530 mock_input_api.files = []
3531 for fname, contents in files.items():
3532 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363533 return PRESUBMIT.CheckBuildtoolsRevisionsAreInSync(mock_input_api,
Dirk Pranke3c18a382019-03-15 01:07:513534 MockOutputApi())
3535
3536 def testOneFileChangedButNotTheOther(self):
3537 results = self._check({
3538 "DEPS": "'libunwind_revision': 'onerev'",
3539 })
3540 self.assertNotEqual(results, [])
3541
3542 def testNeitherFileChanged(self):
3543 results = self._check({
3544 "OWNERS": "[email protected]",
3545 })
3546 self.assertEqual(results, [])
3547
3548 def testBothFilesChangedAndMatch(self):
3549 results = self._check({
3550 "DEPS": "'libunwind_revision': 'onerev'",
3551 "buildtools/DEPS": "'libunwind_revision': 'onerev'",
3552 })
3553 self.assertEqual(results, [])
3554
3555 def testBothFilesWereChangedAndDontMatch(self):
3556 results = self._check({
3557 "DEPS": "'libunwind_revision': 'onerev'",
3558 "buildtools/DEPS": "'libunwind_revision': 'anotherrev'",
3559 })
3560 self.assertNotEqual(results, [])
3561
3562
Max Morozb47503b2019-08-08 21:03:273563class CheckFuzzTargetsTest(unittest.TestCase):
3564
3565 def _check(self, files):
3566 mock_input_api = MockInputApi()
3567 mock_input_api.files = []
3568 for fname, contents in files.items():
3569 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363570 return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api, MockOutputApi())
Max Morozb47503b2019-08-08 21:03:273571
3572 def testLibFuzzerSourcesIgnored(self):
3573 results = self._check({
3574 "third_party/lib/Fuzzer/FuzzerDriver.cpp": "LLVMFuzzerInitialize",
3575 })
3576 self.assertEqual(results, [])
3577
3578 def testNonCodeFilesIgnored(self):
3579 results = self._check({
3580 "README.md": "LLVMFuzzerInitialize",
3581 })
3582 self.assertEqual(results, [])
3583
3584 def testNoErrorHeaderPresent(self):
3585 results = self._check({
3586 "fuzzer.cc": (
3587 "#include \"testing/libfuzzer/libfuzzer_exports.h\"\n" +
3588 "LLVMFuzzerInitialize"
3589 )
3590 })
3591 self.assertEqual(results, [])
3592
3593 def testErrorMissingHeader(self):
3594 results = self._check({
3595 "fuzzer.cc": "LLVMFuzzerInitialize"
3596 })
3597 self.assertEqual(len(results), 1)
3598 self.assertEqual(results[0].items, ['fuzzer.cc'])
3599
3600
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263601class SetNoParentTest(unittest.TestCase):
3602 def testSetNoParentMissing(self):
3603 mock_input_api = MockInputApi()
3604 mock_input_api.files = [
3605 MockAffectedFile('goat/OWNERS',
3606 [
3607 'set noparent',
3608 '[email protected]',
3609 'per-file *.json=set noparent',
3610 'per-file *[email protected]',
3611 ])
3612 ]
3613 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363614 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263615 self.assertEqual(1, len(errors))
3616 self.assertTrue('goat/OWNERS:1' in errors[0].long_text)
3617 self.assertTrue('goat/OWNERS:3' in errors[0].long_text)
3618
3619
3620 def testSetNoParentWithCorrectRule(self):
3621 mock_input_api = MockInputApi()
3622 mock_input_api.files = [
3623 MockAffectedFile('goat/OWNERS',
3624 [
3625 'set noparent',
3626 'file://ipc/SECURITY_OWNERS',
3627 'per-file *.json=set noparent',
3628 'per-file *.json=file://ipc/SECURITY_OWNERS',
3629 ])
3630 ]
3631 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363632 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263633 self.assertEqual([], errors)
3634
3635
Ken Rockotc31f4832020-05-29 18:58:513636class MojomStabilityCheckTest(unittest.TestCase):
3637 def runTestWithAffectedFiles(self, affected_files):
3638 mock_input_api = MockInputApi()
3639 mock_input_api.files = affected_files
3640 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363641 return PRESUBMIT.CheckStableMojomChanges(
Ken Rockotc31f4832020-05-29 18:58:513642 mock_input_api, mock_output_api)
3643
3644 def testSafeChangePasses(self):
3645 errors = self.runTestWithAffectedFiles([
3646 MockAffectedFile('foo/foo.mojom',
3647 ['[Stable] struct S { [MinVersion=1] int32 x; };'],
3648 old_contents=['[Stable] struct S {};'])
3649 ])
3650 self.assertEqual([], errors)
3651
3652 def testBadChangeFails(self):
3653 errors = self.runTestWithAffectedFiles([
3654 MockAffectedFile('foo/foo.mojom',
3655 ['[Stable] struct S { int32 x; };'],
3656 old_contents=['[Stable] struct S {};'])
3657 ])
3658 self.assertEqual(1, len(errors))
3659 self.assertTrue('not backward-compatible' in errors[0].message)
3660
Ken Rockotad7901f942020-06-04 20:17:093661 def testDeletedFile(self):
3662 """Regression test for https://crbug.com/1091407."""
3663 errors = self.runTestWithAffectedFiles([
3664 MockAffectedFile('a.mojom', [], old_contents=['struct S {};'],
3665 action='D'),
3666 MockAffectedFile('b.mojom',
3667 ['struct S {}; struct T { S s; };'],
3668 old_contents=['import "a.mojom"; struct T { S s; };'])
3669 ])
3670 self.assertEqual([], errors)
3671
Ken Rockotc31f4832020-05-29 18:58:513672
Dominic Battre645d42342020-12-04 16:14:103673class CheckDeprecationOfPreferencesTest(unittest.TestCase):
3674 # Test that a warning is generated if a preference registration is removed
3675 # from a random file.
3676 def testWarning(self):
3677 mock_input_api = MockInputApi()
3678 mock_input_api.files = [
3679 MockAffectedFile(
3680 'foo.cc',
3681 ['A', 'B'],
3682 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
3683 scm_diff='\n'.join([
3684 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
3685 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
3686 '@@ -1,3 +1,2 @@',
3687 ' A',
3688 '-prefs->RegisterStringPref("foo", "default");',
3689 ' B']),
3690 action='M')
3691 ]
3692 mock_output_api = MockOutputApi()
3693 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3694 mock_output_api)
3695 self.assertEqual(1, len(errors))
3696 self.assertTrue(
3697 'Discovered possible removal of preference registrations' in
3698 errors[0].message)
3699
3700 # Test that a warning is inhibited if the preference registration was moved
3701 # to the deprecation functions in browser prefs.
3702 def testNoWarningForMigration(self):
3703 mock_input_api = MockInputApi()
3704 mock_input_api.files = [
3705 # RegisterStringPref was removed from foo.cc.
3706 MockAffectedFile(
3707 'foo.cc',
3708 ['A', 'B'],
3709 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
3710 scm_diff='\n'.join([
3711 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
3712 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
3713 '@@ -1,3 +1,2 @@',
3714 ' A',
3715 '-prefs->RegisterStringPref("foo", "default");',
3716 ' B']),
3717 action='M'),
3718 # But the preference was properly migrated.
3719 MockAffectedFile(
3720 'chrome/browser/prefs/browser_prefs.cc',
3721 [
3722 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3723 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3724 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3725 'prefs->RegisterStringPref("foo", "default");',
3726 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3727 ],
3728 [
3729 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3730 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3731 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3732 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3733 ],
3734 scm_diff='\n'.join([
3735 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
3736 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
3737 '@@ -2,3 +2,4 @@',
3738 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3739 ' // BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3740 '+prefs->RegisterStringPref("foo", "default");',
3741 ' // END_MIGRATE_OBSOLETE_PROFILE_PREFS']),
3742 action='M'),
3743 ]
3744 mock_output_api = MockOutputApi()
3745 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3746 mock_output_api)
3747 self.assertEqual(0, len(errors))
3748
3749 # Test that a warning is NOT inhibited if the preference registration was
3750 # moved to a place outside of the migration functions in browser_prefs.cc
3751 def testWarningForImproperMigration(self):
3752 mock_input_api = MockInputApi()
3753 mock_input_api.files = [
3754 # RegisterStringPref was removed from foo.cc.
3755 MockAffectedFile(
3756 'foo.cc',
3757 ['A', 'B'],
3758 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
3759 scm_diff='\n'.join([
3760 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
3761 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
3762 '@@ -1,3 +1,2 @@',
3763 ' A',
3764 '-prefs->RegisterStringPref("foo", "default");',
3765 ' B']),
3766 action='M'),
3767 # The registration call was moved to a place in browser_prefs.cc that
3768 # is outside the migration functions.
3769 MockAffectedFile(
3770 'chrome/browser/prefs/browser_prefs.cc',
3771 [
3772 'prefs->RegisterStringPref("foo", "default");',
3773 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3774 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3775 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3776 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3777 ],
3778 [
3779 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3780 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3781 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3782 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3783 ],
3784 scm_diff='\n'.join([
3785 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
3786 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
3787 '@@ -1,2 +1,3 @@',
3788 '+prefs->RegisterStringPref("foo", "default");',
3789 ' // BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3790 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS']),
3791 action='M'),
3792 ]
3793 mock_output_api = MockOutputApi()
3794 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3795 mock_output_api)
3796 self.assertEqual(1, len(errors))
3797 self.assertTrue(
3798 'Discovered possible removal of preference registrations' in
3799 errors[0].message)
3800
3801 # Check that the presubmit fails if a marker line in brower_prefs.cc is
3802 # deleted.
3803 def testDeletedMarkerRaisesError(self):
3804 mock_input_api = MockInputApi()
3805 mock_input_api.files = [
3806 MockAffectedFile('chrome/browser/prefs/browser_prefs.cc',
3807 [
3808 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3809 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3810 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3811 # The following line is deleted for this test
3812 # '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3813 ])
3814 ]
3815 mock_output_api = MockOutputApi()
3816 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3817 mock_output_api)
3818 self.assertEqual(1, len(errors))
3819 self.assertEqual(
3820 'Broken .*MIGRATE_OBSOLETE_.*_PREFS markers in browser_prefs.cc.',
3821 errors[0].message)
3822
3823
[email protected]2299dcf2012-11-15 19:56:243824if __name__ == '__main__':
3825 unittest.main()