blob: 06ad9cb54ab3f5249778333a54e719d66cc3344b [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
Yoland Yanb92fa522017-08-28 17:37:061110class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271111 def testCheckAndroidTestJUnitFramework(self):
Yoland Yanb92fa522017-08-28 17:37:061112 mock_input_api = MockInputApi()
1113 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:421114
Yoland Yanb92fa522017-08-28 17:37:061115 mock_input_api.files = [
1116 MockAffectedFile('LalaLand.java', [
1117 'random stuff'
1118 ]),
1119 MockAffectedFile('CorrectUsage.java', [
1120 'import org.junit.ABC',
1121 'import org.junit.XYZ;',
1122 ]),
1123 MockAffectedFile('UsedDeprecatedJUnit.java', [
1124 'import junit.framework.*;',
1125 ]),
1126 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
1127 'import junit.framework.Assert;',
1128 ]),
1129 ]
1130 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
1131 mock_input_api, mock_output_api)
1132 self.assertEqual(1, len(msgs),
1133 'Expected %d items, found %d: %s'
1134 % (1, len(msgs), msgs))
1135 self.assertEqual(2, len(msgs[0].items),
1136 'Expected %d items, found %d: %s'
1137 % (2, len(msgs[0].items), msgs[0].items))
1138 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
1139 'UsedDeprecatedJUnit.java not found in errors')
1140 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
1141 in msgs[0].items,
1142 'UsedDeprecatedJUnitAssert not found in errors')
1143
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391144
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271145class AndroidJUnitBaseClassTest(unittest.TestCase):
1146 def testCheckAndroidTestJUnitBaseClass(self):
Yoland Yanb92fa522017-08-28 17:37:061147 mock_input_api = MockInputApi()
1148 mock_output_api = MockOutputApi()
1149
1150 mock_input_api.files = [
1151 MockAffectedFile('LalaLand.java', [
1152 'random stuff'
1153 ]),
1154 MockAffectedFile('CorrectTest.java', [
1155 '@RunWith(ABC.class);'
1156 'public class CorrectTest {',
1157 '}',
1158 ]),
1159 MockAffectedFile('HistoricallyIncorrectTest.java', [
1160 'public class Test extends BaseCaseA {',
1161 '}',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391162 ], old_contents=[
Yoland Yanb92fa522017-08-28 17:37:061163 'public class Test extends BaseCaseB {',
1164 '}',
1165 ]),
1166 MockAffectedFile('CorrectTestWithInterface.java', [
1167 '@RunWith(ABC.class);'
1168 'public class CorrectTest implement Interface {',
1169 '}',
1170 ]),
1171 MockAffectedFile('IncorrectTest.java', [
1172 'public class IncorrectTest extends TestCase {',
1173 '}',
1174 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241175 MockAffectedFile('IncorrectWithInterfaceTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061176 'public class Test implements X extends BaseClass {',
1177 '}',
1178 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241179 MockAffectedFile('IncorrectMultiLineTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061180 'public class Test implements X, Y, Z',
1181 ' extends TestBase {',
1182 '}',
1183 ]),
1184 ]
1185 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1186 mock_input_api, mock_output_api)
1187 self.assertEqual(1, len(msgs),
1188 'Expected %d items, found %d: %s'
1189 % (1, len(msgs), msgs))
1190 self.assertEqual(3, len(msgs[0].items),
1191 'Expected %d items, found %d: %s'
1192 % (3, len(msgs[0].items), msgs[0].items))
1193 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1194 'IncorrectTest not found in errors')
Vaclav Brozekf01ed502018-03-16 19:38:241195 self.assertTrue('IncorrectWithInterfaceTest.java:1'
Yoland Yanb92fa522017-08-28 17:37:061196 in msgs[0].items,
Vaclav Brozekf01ed502018-03-16 19:38:241197 'IncorrectWithInterfaceTest not found in errors')
1198 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1199 'IncorrectMultiLineTest not found in errors')
yolandyan45001472016-12-21 21:12:421200
Jinsong Fan91ebbbd2019-04-16 14:57:171201class AndroidDebuggableBuildTest(unittest.TestCase):
1202
1203 def testCheckAndroidDebuggableBuild(self):
1204 mock_input_api = MockInputApi()
1205 mock_output_api = MockOutputApi()
1206
1207 mock_input_api.files = [
1208 MockAffectedFile('RandomStuff.java', [
1209 'random stuff'
1210 ]),
1211 MockAffectedFile('CorrectUsage.java', [
1212 'import org.chromium.base.BuildInfo;',
1213 'some random stuff',
1214 'boolean isOsDebuggable = BuildInfo.isDebugAndroid();',
1215 ]),
1216 MockAffectedFile('JustCheckUserdebugBuild.java', [
1217 'import android.os.Build;',
1218 'some random stuff',
1219 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")',
1220 ]),
1221 MockAffectedFile('JustCheckEngineeringBuild.java', [
1222 'import android.os.Build;',
1223 'some random stuff',
1224 'boolean isOsDebuggable = "eng".equals(Build.TYPE)',
1225 ]),
1226 MockAffectedFile('UsedBuildType.java', [
1227 'import android.os.Build;',
1228 'some random stuff',
1229 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")'
1230 '|| "eng".equals(Build.TYPE)',
1231 ]),
1232 MockAffectedFile('UsedExplicitBuildType.java', [
1233 'some random stuff',
1234 'boolean isOsDebuggable = android.os.Build.TYPE.equals("userdebug")'
1235 '|| "eng".equals(android.os.Build.TYPE)',
1236 ]),
1237 ]
1238
1239 msgs = PRESUBMIT._CheckAndroidDebuggableBuild(
1240 mock_input_api, mock_output_api)
1241 self.assertEqual(1, len(msgs),
1242 'Expected %d items, found %d: %s'
1243 % (1, len(msgs), msgs))
1244 self.assertEqual(4, len(msgs[0].items),
1245 'Expected %d items, found %d: %s'
1246 % (4, len(msgs[0].items), msgs[0].items))
1247 self.assertTrue('JustCheckUserdebugBuild.java:3' in msgs[0].items)
1248 self.assertTrue('JustCheckEngineeringBuild.java:3' in msgs[0].items)
1249 self.assertTrue('UsedBuildType.java:3' in msgs[0].items)
1250 self.assertTrue('UsedExplicitBuildType.java:2' in msgs[0].items)
1251
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391252
dgn4401aa52015-04-29 16:26:171253class LogUsageTest(unittest.TestCase):
1254
dgnaa68d5e2015-06-10 10:08:221255 def testCheckAndroidCrLogUsage(self):
1256 mock_input_api = MockInputApi()
1257 mock_output_api = MockOutputApi()
1258
1259 mock_input_api.files = [
1260 MockAffectedFile('RandomStuff.java', [
1261 'random stuff'
1262 ]),
dgn87d9fb62015-06-12 09:15:121263 MockAffectedFile('HasAndroidLog.java', [
1264 'import android.util.Log;',
1265 'some random stuff',
1266 'Log.d("TAG", "foo");',
1267 ]),
1268 MockAffectedFile('HasExplicitUtilLog.java', [
1269 'some random stuff',
1270 'android.util.Log.d("TAG", "foo");',
1271 ]),
1272 MockAffectedFile('IsInBasePackage.java', [
1273 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511274 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121275 'Log.d(TAG, "foo");',
1276 ]),
1277 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1278 'package org.chromium.base;',
1279 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511280 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121281 'Log.d(TAG, "foo");',
1282 ]),
1283 MockAffectedFile('HasBothLog.java', [
1284 'import org.chromium.base.Log;',
1285 'some random stuff',
dgn38736db2015-09-18 19:20:511286 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121287 'Log.d(TAG, "foo");',
1288 'android.util.Log.d("TAG", "foo");',
1289 ]),
dgnaa68d5e2015-06-10 10:08:221290 MockAffectedFile('HasCorrectTag.java', [
1291 'import org.chromium.base.Log;',
1292 'some random stuff',
dgn38736db2015-09-18 19:20:511293 'private static final String TAG = "cr_Foo";',
1294 'Log.d(TAG, "foo");',
1295 ]),
1296 MockAffectedFile('HasOldTag.java', [
1297 'import org.chromium.base.Log;',
1298 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221299 'private static final String TAG = "cr.Foo";',
1300 'Log.d(TAG, "foo");',
1301 ]),
dgn38736db2015-09-18 19:20:511302 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221303 'import org.chromium.base.Log;',
1304 'some random stuff',
dgn38736db2015-09-18 19:20:511305 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221306 'Log.d(TAG, "foo");',
1307 ]),
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461308 MockAffectedFile('HasDottedTagPublic.java', [
1309 'import org.chromium.base.Log;',
1310 'some random stuff',
1311 'public static final String TAG = "cr_foo.bar";',
1312 'Log.d(TAG, "foo");',
1313 ]),
dgnaa68d5e2015-06-10 10:08:221314 MockAffectedFile('HasNoTagDecl.java', [
1315 'import org.chromium.base.Log;',
1316 'some random stuff',
1317 'Log.d(TAG, "foo");',
1318 ]),
1319 MockAffectedFile('HasIncorrectTagDecl.java', [
1320 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511321 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221322 'some random stuff',
1323 'Log.d(TAG, "foo");',
1324 ]),
1325 MockAffectedFile('HasInlineTag.java', [
1326 'import org.chromium.base.Log;',
1327 'some random stuff',
dgn38736db2015-09-18 19:20:511328 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221329 'Log.d("TAG", "foo");',
1330 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551331 MockAffectedFile('HasInlineTagWithSpace.java', [
1332 'import org.chromium.base.Log;',
1333 'some random stuff',
1334 'private static final String TAG = "cr_Foo";',
1335 'Log.d("log message", "foo");',
1336 ]),
dgn38736db2015-09-18 19:20:511337 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221338 'import org.chromium.base.Log;',
1339 'some random stuff',
1340 'private static final String TAG = "rubbish";',
1341 'Log.d(TAG, "foo");',
1342 ]),
1343 MockAffectedFile('HasTooLongTag.java', [
1344 'import org.chromium.base.Log;',
1345 'some random stuff',
dgn38736db2015-09-18 19:20:511346 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:221347 'Log.d(TAG, "foo");',
1348 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551349 MockAffectedFile('HasTooLongTagWithNoLogCallsInDiff.java', [
1350 'import org.chromium.base.Log;',
1351 'some random stuff',
1352 'private static final String TAG = "21_charachers_long___";',
1353 ]),
dgnaa68d5e2015-06-10 10:08:221354 ]
1355
1356 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1357 mock_input_api, mock_output_api)
1358
dgn38736db2015-09-18 19:20:511359 self.assertEqual(5, len(msgs),
1360 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221361
1362 # Declaration format
dgn38736db2015-09-18 19:20:511363 nb = len(msgs[0].items)
1364 self.assertEqual(2, nb,
1365 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221366 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1367 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221368
1369 # Tag length
dgn38736db2015-09-18 19:20:511370 nb = len(msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551371 self.assertEqual(2, nb,
1372 'Expected %d items, found %d: %s' % (2, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:221373 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551374 self.assertTrue('HasTooLongTagWithNoLogCallsInDiff.java' in msgs[1].items)
dgnaa68d5e2015-06-10 10:08:221375
1376 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511377 nb = len(msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551378 self.assertEqual(3, nb,
1379 'Expected %d items, found %d: %s' % (3, nb, msgs[2].items))
1380 self.assertTrue('HasBothLog.java:5' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221381 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551382 self.assertTrue('HasInlineTagWithSpace.java:4' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221383
dgn87d9fb62015-06-12 09:15:121384 # Util Log usage
dgn38736db2015-09-18 19:20:511385 nb = len(msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551386 self.assertEqual(3, nb,
1387 'Expected %d items, found %d: %s' % (3, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:121388 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551389 self.assertTrue('HasExplicitUtilLog.java:2' in msgs[3].items)
dgn87d9fb62015-06-12 09:15:121390 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:221391
dgn38736db2015-09-18 19:20:511392 # Tag must not contain
1393 nb = len(msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461394 self.assertEqual(3, nb,
dgn38736db2015-09-18 19:20:511395 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1396 self.assertTrue('HasDottedTag.java' in msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461397 self.assertTrue('HasDottedTagPublic.java' in msgs[4].items)
dgn38736db2015-09-18 19:20:511398 self.assertTrue('HasOldTag.java' in msgs[4].items)
1399
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391400
estadee17314a02017-01-12 16:22:161401class GoogleAnswerUrlFormatTest(unittest.TestCase):
1402
1403 def testCatchAnswerUrlId(self):
1404 input_api = MockInputApi()
1405 input_api.files = [
1406 MockFile('somewhere/file.cc',
1407 ['char* host = '
1408 ' "https://support.google.com/chrome/answer/123456";']),
1409 MockFile('somewhere_else/file.cc',
1410 ['char* host = '
1411 ' "https://support.google.com/chrome/a/answer/123456";']),
1412 ]
1413
Saagar Sanghavifceeaae2020-08-12 16:40:361414 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161415 input_api, MockOutputApi())
1416 self.assertEqual(1, len(warnings))
1417 self.assertEqual(2, len(warnings[0].items))
1418
1419 def testAllowAnswerUrlParam(self):
1420 input_api = MockInputApi()
1421 input_api.files = [
1422 MockFile('somewhere/file.cc',
1423 ['char* host = '
1424 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1425 ]
1426
Saagar Sanghavifceeaae2020-08-12 16:40:361427 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161428 input_api, MockOutputApi())
1429 self.assertEqual(0, len(warnings))
1430
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391431
reillyi38965732015-11-16 18:27:331432class HardcodedGoogleHostsTest(unittest.TestCase):
1433
1434 def testWarnOnAssignedLiterals(self):
1435 input_api = MockInputApi()
1436 input_api.files = [
1437 MockFile('content/file.cc',
1438 ['char* host = "https://www.google.com";']),
1439 MockFile('content/file.cc',
1440 ['char* host = "https://www.googleapis.com";']),
1441 MockFile('content/file.cc',
1442 ['char* host = "https://clients1.google.com";']),
1443 ]
1444
Saagar Sanghavifceeaae2020-08-12 16:40:361445 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331446 input_api, MockOutputApi())
1447 self.assertEqual(1, len(warnings))
1448 self.assertEqual(3, len(warnings[0].items))
1449
1450 def testAllowInComment(self):
1451 input_api = MockInputApi()
1452 input_api.files = [
1453 MockFile('content/file.cc',
1454 ['char* host = "https://www.aol.com"; // google.com'])
1455 ]
1456
Saagar Sanghavifceeaae2020-08-12 16:40:361457 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331458 input_api, MockOutputApi())
1459 self.assertEqual(0, len(warnings))
1460
dgn4401aa52015-04-29 16:26:171461
James Cook6b6597c2019-11-06 22:05:291462class ChromeOsSyncedPrefRegistrationTest(unittest.TestCase):
1463
1464 def testWarnsOnChromeOsDirectories(self):
1465 input_api = MockInputApi()
1466 input_api.files = [
1467 MockFile('ash/file.cc',
1468 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1469 MockFile('chrome/browser/chromeos/file.cc',
1470 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1471 MockFile('chromeos/file.cc',
1472 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1473 MockFile('components/arc/file.cc',
1474 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1475 MockFile('components/exo/file.cc',
1476 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1477 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361478 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291479 input_api, MockOutputApi())
1480 self.assertEqual(1, len(warnings))
1481
1482 def testDoesNotWarnOnSyncOsPref(self):
1483 input_api = MockInputApi()
1484 input_api.files = [
1485 MockFile('chromeos/file.cc',
1486 ['PrefRegistrySyncable::SYNCABLE_OS_PREF']),
1487 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361488 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291489 input_api, MockOutputApi())
1490 self.assertEqual(0, len(warnings))
1491
1492 def testDoesNotWarnOnCrossPlatformDirectories(self):
1493 input_api = MockInputApi()
1494 input_api.files = [
1495 MockFile('chrome/browser/ui/file.cc',
1496 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1497 MockFile('components/sync/file.cc',
1498 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1499 MockFile('content/browser/file.cc',
1500 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1501 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361502 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291503 input_api, MockOutputApi())
1504 self.assertEqual(0, len(warnings))
1505
1506 def testSeparateWarningForPriorityPrefs(self):
1507 input_api = MockInputApi()
1508 input_api.files = [
1509 MockFile('chromeos/file.cc',
1510 ['PrefRegistrySyncable::SYNCABLE_PREF',
1511 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']),
1512 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361513 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291514 input_api, MockOutputApi())
1515 self.assertEqual(2, len(warnings))
1516
1517
jbriance9e12f162016-11-25 07:57:501518class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311519 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501520 mock_input_api = MockInputApi()
1521 mock_input_api.files = [
1522 MockAffectedFile('somewhere/file.cc', [
1523 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311524 ]),
1525 MockAffectedFile('third_party/header.h', [
1526 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501527 ])
1528 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361529 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391530 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501531 self.assertEqual(0, len(warnings))
1532
1533 def testNoNestedDeclaration(self):
1534 mock_input_api = MockInputApi()
1535 mock_input_api.files = [
1536 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311537 'class SomeClass {',
1538 ' protected:',
1539 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501540 '};'
1541 ])
1542 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361543 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391544 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501545 self.assertEqual(0, len(warnings))
1546
1547 def testSubStrings(self):
1548 mock_input_api = MockInputApi()
1549 mock_input_api.files = [
1550 MockAffectedFile('somewhere/header.h', [
1551 'class NotUsefulClass;',
1552 'struct SomeStruct;',
1553 'UsefulClass *p1;',
1554 'SomeStructPtr *p2;'
1555 ])
1556 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361557 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391558 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501559 self.assertEqual(2, len(warnings))
1560
1561 def testUselessForwardDeclaration(self):
1562 mock_input_api = MockInputApi()
1563 mock_input_api.files = [
1564 MockAffectedFile('somewhere/header.h', [
1565 'class DummyClass;',
1566 'struct DummyStruct;',
1567 'class UsefulClass;',
1568 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311569 ])
jbriance9e12f162016-11-25 07:57:501570 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361571 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391572 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501573 self.assertEqual(2, len(warnings))
1574
jbriance2c51e821a2016-12-12 08:24:311575 def testBlinkHeaders(self):
1576 mock_input_api = MockInputApi()
1577 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491578 MockAffectedFile('third_party/blink/header.h', [
jbriance2c51e821a2016-12-12 08:24:311579 'class DummyClass;',
1580 'struct DummyStruct;',
1581 ]),
Kent Tamura32dbbcb2018-11-30 12:28:491582 MockAffectedFile('third_party\\blink\\header.h', [
jbriance2c51e821a2016-12-12 08:24:311583 'class DummyClass;',
1584 'struct DummyStruct;',
1585 ])
1586 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361587 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391588 MockOutputApi())
jbriance2c51e821a2016-12-12 08:24:311589 self.assertEqual(4, len(warnings))
1590
jbriance9e12f162016-11-25 07:57:501591
rlanday6802cf632017-05-30 17:48:361592class RelativeIncludesTest(unittest.TestCase):
1593 def testThirdPartyNotWebKitIgnored(self):
1594 mock_input_api = MockInputApi()
1595 mock_input_api.files = [
1596 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1597 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1598 ]
1599
1600 mock_output_api = MockOutputApi()
1601
Saagar Sanghavifceeaae2020-08-12 16:40:361602 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361603 mock_input_api, mock_output_api)
1604 self.assertEqual(0, len(errors))
1605
1606 def testNonCppFileIgnored(self):
1607 mock_input_api = MockInputApi()
1608 mock_input_api.files = [
1609 MockAffectedFile('test.py', '#include "../header.h"'),
1610 ]
1611
1612 mock_output_api = MockOutputApi()
1613
Saagar Sanghavifceeaae2020-08-12 16:40:361614 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361615 mock_input_api, mock_output_api)
1616 self.assertEqual(0, len(errors))
1617
1618 def testInnocuousChangesAllowed(self):
1619 mock_input_api = MockInputApi()
1620 mock_input_api.files = [
1621 MockAffectedFile('test.cpp', '#include "header.h"'),
1622 MockAffectedFile('test2.cpp', '../'),
1623 ]
1624
1625 mock_output_api = MockOutputApi()
1626
Saagar Sanghavifceeaae2020-08-12 16:40:361627 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361628 mock_input_api, mock_output_api)
1629 self.assertEqual(0, len(errors))
1630
1631 def testRelativeIncludeNonWebKitProducesError(self):
1632 mock_input_api = MockInputApi()
1633 mock_input_api.files = [
1634 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1635 ]
1636
1637 mock_output_api = MockOutputApi()
1638
Saagar Sanghavifceeaae2020-08-12 16:40:361639 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361640 mock_input_api, mock_output_api)
1641 self.assertEqual(1, len(errors))
1642
1643 def testRelativeIncludeWebKitProducesError(self):
1644 mock_input_api = MockInputApi()
1645 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491646 MockAffectedFile('third_party/blink/test.cpp',
rlanday6802cf632017-05-30 17:48:361647 ['#include "../header.h']),
1648 ]
1649
1650 mock_output_api = MockOutputApi()
1651
Saagar Sanghavifceeaae2020-08-12 16:40:361652 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361653 mock_input_api, mock_output_api)
1654 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241655
Daniel Cheng13ca61a882017-08-25 15:11:251656
Daniel Bratell65b033262019-04-23 08:17:061657class CCIncludeTest(unittest.TestCase):
1658 def testThirdPartyNotBlinkIgnored(self):
1659 mock_input_api = MockInputApi()
1660 mock_input_api.files = [
1661 MockAffectedFile('third_party/test.cpp', '#include "file.cc"'),
1662 ]
1663
1664 mock_output_api = MockOutputApi()
1665
Saagar Sanghavifceeaae2020-08-12 16:40:361666 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061667 mock_input_api, mock_output_api)
1668 self.assertEqual(0, len(errors))
1669
1670 def testPythonFileIgnored(self):
1671 mock_input_api = MockInputApi()
1672 mock_input_api.files = [
1673 MockAffectedFile('test.py', '#include "file.cc"'),
1674 ]
1675
1676 mock_output_api = MockOutputApi()
1677
Saagar Sanghavifceeaae2020-08-12 16:40:361678 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061679 mock_input_api, mock_output_api)
1680 self.assertEqual(0, len(errors))
1681
1682 def testIncFilesAccepted(self):
1683 mock_input_api = MockInputApi()
1684 mock_input_api.files = [
1685 MockAffectedFile('test.py', '#include "file.inc"'),
1686 ]
1687
1688 mock_output_api = MockOutputApi()
1689
Saagar Sanghavifceeaae2020-08-12 16:40:361690 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061691 mock_input_api, mock_output_api)
1692 self.assertEqual(0, len(errors))
1693
1694 def testInnocuousChangesAllowed(self):
1695 mock_input_api = MockInputApi()
1696 mock_input_api.files = [
1697 MockAffectedFile('test.cpp', '#include "header.h"'),
1698 MockAffectedFile('test2.cpp', 'Something "file.cc"'),
1699 ]
1700
1701 mock_output_api = MockOutputApi()
1702
Saagar Sanghavifceeaae2020-08-12 16:40:361703 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061704 mock_input_api, mock_output_api)
1705 self.assertEqual(0, len(errors))
1706
1707 def testCcIncludeNonBlinkProducesError(self):
1708 mock_input_api = MockInputApi()
1709 mock_input_api.files = [
1710 MockAffectedFile('test.cpp', ['#include "file.cc"']),
1711 ]
1712
1713 mock_output_api = MockOutputApi()
1714
Saagar Sanghavifceeaae2020-08-12 16:40:361715 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061716 mock_input_api, mock_output_api)
1717 self.assertEqual(1, len(errors))
1718
1719 def testCppIncludeBlinkProducesError(self):
1720 mock_input_api = MockInputApi()
1721 mock_input_api.files = [
1722 MockAffectedFile('third_party/blink/test.cpp',
1723 ['#include "foo/file.cpp"']),
1724 ]
1725
1726 mock_output_api = MockOutputApi()
1727
Saagar Sanghavifceeaae2020-08-12 16:40:361728 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061729 mock_input_api, mock_output_api)
1730 self.assertEqual(1, len(errors))
1731
1732
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191733class NewHeaderWithoutGnChangeTest(unittest.TestCase):
1734 def testAddHeaderWithoutGn(self):
1735 mock_input_api = MockInputApi()
1736 mock_input_api.files = [
1737 MockAffectedFile('base/stuff.h', ''),
1738 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361739 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191740 mock_input_api, MockOutputApi())
1741 self.assertEqual(1, len(warnings))
1742 self.assertTrue('base/stuff.h' in warnings[0].items)
1743
1744 def testModifyHeader(self):
1745 mock_input_api = MockInputApi()
1746 mock_input_api.files = [
1747 MockAffectedFile('base/stuff.h', '', action='M'),
1748 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361749 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191750 mock_input_api, MockOutputApi())
1751 self.assertEqual(0, len(warnings))
1752
1753 def testDeleteHeader(self):
1754 mock_input_api = MockInputApi()
1755 mock_input_api.files = [
1756 MockAffectedFile('base/stuff.h', '', action='D'),
1757 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361758 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191759 mock_input_api, MockOutputApi())
1760 self.assertEqual(0, len(warnings))
1761
1762 def testAddHeaderWithGn(self):
1763 mock_input_api = MockInputApi()
1764 mock_input_api.files = [
1765 MockAffectedFile('base/stuff.h', ''),
1766 MockAffectedFile('base/BUILD.gn', 'stuff.h'),
1767 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361768 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191769 mock_input_api, MockOutputApi())
1770 self.assertEqual(0, len(warnings))
1771
1772 def testAddHeaderWithGni(self):
1773 mock_input_api = MockInputApi()
1774 mock_input_api.files = [
1775 MockAffectedFile('base/stuff.h', ''),
1776 MockAffectedFile('base/files.gni', 'stuff.h'),
1777 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361778 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191779 mock_input_api, MockOutputApi())
1780 self.assertEqual(0, len(warnings))
1781
1782 def testAddHeaderWithOther(self):
1783 mock_input_api = MockInputApi()
1784 mock_input_api.files = [
1785 MockAffectedFile('base/stuff.h', ''),
1786 MockAffectedFile('base/stuff.cc', 'stuff.h'),
1787 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361788 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191789 mock_input_api, MockOutputApi())
1790 self.assertEqual(1, len(warnings))
1791
1792 def testAddHeaderWithWrongGn(self):
1793 mock_input_api = MockInputApi()
1794 mock_input_api.files = [
1795 MockAffectedFile('base/stuff.h', ''),
1796 MockAffectedFile('base/BUILD.gn', 'stuff_h'),
1797 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361798 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191799 mock_input_api, MockOutputApi())
1800 self.assertEqual(1, len(warnings))
1801
1802 def testAddHeadersWithGn(self):
1803 mock_input_api = MockInputApi()
1804 mock_input_api.files = [
1805 MockAffectedFile('base/stuff.h', ''),
1806 MockAffectedFile('base/another.h', ''),
1807 MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'),
1808 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361809 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191810 mock_input_api, MockOutputApi())
1811 self.assertEqual(0, len(warnings))
1812
1813 def testAddHeadersWithWrongGn(self):
1814 mock_input_api = MockInputApi()
1815 mock_input_api.files = [
1816 MockAffectedFile('base/stuff.h', ''),
1817 MockAffectedFile('base/another.h', ''),
1818 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'),
1819 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361820 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191821 mock_input_api, MockOutputApi())
1822 self.assertEqual(1, len(warnings))
1823 self.assertFalse('base/stuff.h' in warnings[0].items)
1824 self.assertTrue('base/another.h' in warnings[0].items)
1825
1826 def testAddHeadersWithWrongGn2(self):
1827 mock_input_api = MockInputApi()
1828 mock_input_api.files = [
1829 MockAffectedFile('base/stuff.h', ''),
1830 MockAffectedFile('base/another.h', ''),
1831 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'),
1832 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361833 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191834 mock_input_api, MockOutputApi())
1835 self.assertEqual(1, len(warnings))
1836 self.assertTrue('base/stuff.h' in warnings[0].items)
1837 self.assertTrue('base/another.h' in warnings[0].items)
1838
1839
Michael Giuffridad3bc8672018-10-25 22:48:021840class CorrectProductNameInMessagesTest(unittest.TestCase):
1841 def testProductNameInDesc(self):
1842 mock_input_api = MockInputApi()
1843 mock_input_api.files = [
1844 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1845 '<message name="Foo" desc="Welcome to Chrome">',
1846 ' Welcome to Chrome!',
1847 '</message>',
1848 ]),
1849 MockAffectedFile('chrome/app/chromium_strings.grd', [
1850 '<message name="Bar" desc="Welcome to Chrome">',
1851 ' Welcome to Chromium!',
1852 '</message>',
1853 ]),
1854 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361855 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021856 mock_input_api, MockOutputApi())
1857 self.assertEqual(0, len(warnings))
1858
1859 def testChromeInChromium(self):
1860 mock_input_api = MockInputApi()
1861 mock_input_api.files = [
1862 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1863 '<message name="Foo" desc="Welcome to Chrome">',
1864 ' Welcome to Chrome!',
1865 '</message>',
1866 ]),
1867 MockAffectedFile('chrome/app/chromium_strings.grd', [
1868 '<message name="Bar" desc="Welcome to Chrome">',
1869 ' Welcome to Chrome!',
1870 '</message>',
1871 ]),
1872 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361873 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021874 mock_input_api, MockOutputApi())
1875 self.assertEqual(1, len(warnings))
1876 self.assertTrue('chrome/app/chromium_strings.grd' in warnings[0].items[0])
1877
1878 def testChromiumInChrome(self):
1879 mock_input_api = MockInputApi()
1880 mock_input_api.files = [
1881 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1882 '<message name="Foo" desc="Welcome to Chrome">',
1883 ' Welcome to Chromium!',
1884 '</message>',
1885 ]),
1886 MockAffectedFile('chrome/app/chromium_strings.grd', [
1887 '<message name="Bar" desc="Welcome to Chrome">',
1888 ' Welcome to Chromium!',
1889 '</message>',
1890 ]),
1891 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361892 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021893 mock_input_api, MockOutputApi())
1894 self.assertEqual(1, len(warnings))
1895 self.assertTrue(
1896 'chrome/app/google_chrome_strings.grd:2' in warnings[0].items[0])
1897
1898 def testMultipleInstances(self):
1899 mock_input_api = MockInputApi()
1900 mock_input_api.files = [
1901 MockAffectedFile('chrome/app/chromium_strings.grd', [
1902 '<message name="Bar" desc="Welcome to Chrome">',
1903 ' Welcome to Chrome!',
1904 '</message>',
1905 '<message name="Baz" desc="A correct message">',
1906 ' Chromium is the software you are using.',
1907 '</message>',
1908 '<message name="Bat" desc="An incorrect message">',
1909 ' Google Chrome is the software you are using.',
1910 '</message>',
1911 ]),
1912 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361913 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021914 mock_input_api, MockOutputApi())
1915 self.assertEqual(1, len(warnings))
1916 self.assertTrue(
1917 'chrome/app/chromium_strings.grd:2' in warnings[0].items[0])
1918 self.assertTrue(
1919 'chrome/app/chromium_strings.grd:8' in warnings[0].items[1])
1920
1921 def testMultipleWarnings(self):
1922 mock_input_api = MockInputApi()
1923 mock_input_api.files = [
1924 MockAffectedFile('chrome/app/chromium_strings.grd', [
1925 '<message name="Bar" desc="Welcome to Chrome">',
1926 ' Welcome to Chrome!',
1927 '</message>',
1928 '<message name="Baz" desc="A correct message">',
1929 ' Chromium is the software you are using.',
1930 '</message>',
1931 '<message name="Bat" desc="An incorrect message">',
1932 ' Google Chrome is the software you are using.',
1933 '</message>',
1934 ]),
1935 MockAffectedFile('components/components_google_chrome_strings.grd', [
1936 '<message name="Bar" desc="Welcome to Chrome">',
1937 ' Welcome to Chrome!',
1938 '</message>',
1939 '<message name="Baz" desc="A correct message">',
1940 ' Chromium is the software you are using.',
1941 '</message>',
1942 '<message name="Bat" desc="An incorrect message">',
1943 ' Google Chrome is the software you are using.',
1944 '</message>',
1945 ]),
1946 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361947 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021948 mock_input_api, MockOutputApi())
1949 self.assertEqual(2, len(warnings))
1950 self.assertTrue(
1951 'components/components_google_chrome_strings.grd:5'
1952 in warnings[0].items[0])
1953 self.assertTrue(
1954 'chrome/app/chromium_strings.grd:2' in warnings[1].items[0])
1955 self.assertTrue(
1956 'chrome/app/chromium_strings.grd:8' in warnings[1].items[1])
1957
1958
Ken Rockot9f668262018-12-21 18:56:361959class ServiceManifestOwnerTest(unittest.TestCase):
Ken Rockot9f668262018-12-21 18:56:361960 def testServiceManifestChangeNeedsSecurityOwner(self):
1961 mock_input_api = MockInputApi()
1962 mock_input_api.files = [
1963 MockAffectedFile('services/goat/public/cpp/manifest.cc',
1964 [
1965 '#include "services/goat/public/cpp/manifest.h"',
1966 'const service_manager::Manifest& GetManifest() {}',
1967 ])]
1968 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:361969 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:361970 mock_input_api, mock_output_api)
1971 self.assertEqual(1, len(errors))
1972 self.assertEqual(
1973 'Found OWNERS files that need to be updated for IPC security review ' +
1974 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
1975
1976 def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
1977 mock_input_api = MockInputApi()
1978 mock_input_api.files = [
1979 MockAffectedFile('some/non/service/thing/foo_manifest.cc',
1980 [
1981 'const char kNoEnforcement[] = "not a manifest!";',
1982 ])]
1983 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:361984 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:031985 mock_input_api, mock_output_api)
1986 self.assertEqual([], errors)
1987
1988
1989class FuchsiaSecurityOwnerTest(unittest.TestCase):
1990 def testFidlChangeNeedsSecurityOwner(self):
1991 mock_input_api = MockInputApi()
1992 mock_input_api.files = [
1993 MockAffectedFile('potentially/scary/ipc.fidl',
1994 [
1995 'library test.fidl'
1996 ])]
1997 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:361998 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:031999 mock_input_api, mock_output_api)
2000 self.assertEqual(1, len(errors))
2001 self.assertEqual(
2002 'Found OWNERS files that need to be updated for IPC security review ' +
2003 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2004
2005 def testComponentManifestV1ChangeNeedsSecurityOwner(self):
2006 mock_input_api = MockInputApi()
2007 mock_input_api.files = [
2008 MockAffectedFile('potentially/scary/v2_manifest.cmx',
2009 [
2010 '{ "that is no": "manifest!" }'
2011 ])]
2012 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362013 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032014 mock_input_api, mock_output_api)
2015 self.assertEqual(1, len(errors))
2016 self.assertEqual(
2017 'Found OWNERS files that need to be updated for IPC security review ' +
2018 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2019
2020 def testComponentManifestV2NeedsSecurityOwner(self):
2021 mock_input_api = MockInputApi()
2022 mock_input_api.files = [
2023 MockAffectedFile('potentially/scary/v2_manifest.cml',
2024 [
2025 '{ "that is no": "manifest!" }'
2026 ])]
2027 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362028 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032029 mock_input_api, mock_output_api)
2030 self.assertEqual(1, len(errors))
2031 self.assertEqual(
2032 'Found OWNERS files that need to be updated for IPC security review ' +
2033 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2034
2035 def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2036 mock_input_api = MockInputApi()
2037 mock_input_api.files = [
2038 MockAffectedFile('some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',
2039 [
2040 'const char kNoEnforcement[] = "Security?!? Pah!";',
2041 ])]
2042 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362043 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362044 mock_input_api, mock_output_api)
2045 self.assertEqual([], errors)
2046
Daniel Cheng13ca61a882017-08-25 15:11:252047
Robert Sesek2c905332020-05-06 23:17:132048class SecurityChangeTest(unittest.TestCase):
2049 class _MockOwnersDB(object):
2050 def __init__(self):
2051 self.email_regexp = '.*'
2052
2053 def owners_rooted_at_file(self, f):
2054 return ['[email protected]', '[email protected]']
2055
2056 def _mockChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2057 def __MockOwnerAndReviewers(input_api, email_regexp, approval_needed=False):
2058 return [owner, reviewers]
2059 input_api.canned_checks.GetCodereviewOwnerAndReviewers = \
2060 __MockOwnerAndReviewers
2061
Alex Goughbc964dd2020-06-15 17:52:372062 def testDiffGetServiceSandboxType(self):
Robert Sesek2c905332020-05-06 23:17:132063 mock_input_api = MockInputApi()
2064 mock_input_api.files = [
2065 MockAffectedFile(
2066 'services/goat/teleporter_host.cc',
2067 [
Alex Goughbc964dd2020-06-15 17:52:372068 'template <>',
2069 'inline content::SandboxType',
2070 'content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {',
2071 '#if defined(OS_WIN)',
2072 ' return SandboxType::kGoaty;',
2073 '#else',
2074 ' return SandboxType::kNoSandbox;',
2075 '#endif // !defined(OS_WIN)',
2076 '}'
Robert Sesek2c905332020-05-06 23:17:132077 ]
2078 ),
2079 ]
2080 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2081 mock_input_api)
2082 self.assertEqual({
2083 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372084 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132085 ])},
2086 files_to_functions)
2087
2088 def testDiffRemovingLine(self):
2089 mock_input_api = MockInputApi()
2090 mock_file = MockAffectedFile('services/goat/teleporter_host.cc', '')
2091 mock_file._scm_diff = """--- old 2020-05-04 14:08:25.000000000 -0400
2092+++ new 2020-05-04 14:08:32.000000000 -0400
2093@@ -1,5 +1,4 @@
Alex Goughbc964dd2020-06-15 17:52:372094 template <>
2095 inline content::SandboxType
2096-content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {
2097 #if defined(OS_WIN)
2098 return SandboxType::kGoaty;
Robert Sesek2c905332020-05-06 23:17:132099"""
2100 mock_input_api.files = [mock_file]
2101 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2102 mock_input_api)
2103 self.assertEqual({
2104 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372105 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132106 ])},
2107 files_to_functions)
2108
2109 def testChangeOwnersMissing(self):
2110 mock_input_api = MockInputApi()
2111 mock_input_api.owners_db = self._MockOwnersDB()
2112 mock_input_api.is_committing = False
2113 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372114 MockAffectedFile('file.cc', ['GetServiceSandboxType<Goat>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132115 ]
2116 mock_output_api = MockOutputApi()
2117 self._mockChangeOwnerAndReviewers(
2118 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362119 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132120 self.assertEquals(1, len(result))
2121 self.assertEquals(result[0].type, 'notify')
2122 self.assertEquals(result[0].message,
2123 'The following files change calls to security-sensive functions\n' \
2124 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2125 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372126 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132127
2128 def testChangeOwnersMissingAtCommit(self):
2129 mock_input_api = MockInputApi()
2130 mock_input_api.owners_db = self._MockOwnersDB()
2131 mock_input_api.is_committing = True
2132 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372133 MockAffectedFile('file.cc', ['GetServiceSandboxType<mojom::Goat>()'])
Robert Sesek2c905332020-05-06 23:17:132134 ]
2135 mock_output_api = MockOutputApi()
2136 self._mockChangeOwnerAndReviewers(
2137 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362138 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132139 self.assertEquals(1, len(result))
2140 self.assertEquals(result[0].type, 'error')
2141 self.assertEquals(result[0].message,
2142 'The following files change calls to security-sensive functions\n' \
2143 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2144 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372145 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132146
2147 def testChangeOwnersPresent(self):
2148 mock_input_api = MockInputApi()
2149 mock_input_api.owners_db = self._MockOwnersDB()
2150 mock_input_api.files = [
2151 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2152 ]
2153 mock_output_api = MockOutputApi()
2154 self._mockChangeOwnerAndReviewers(
2155 mock_input_api, '[email protected]',
2156 ['[email protected]', '[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362157 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132158 self.assertEquals(0, len(result))
2159
2160 def testChangeOwnerIsSecurityOwner(self):
2161 mock_input_api = MockInputApi()
2162 mock_input_api.owners_db = self._MockOwnersDB()
2163 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372164 MockAffectedFile('file.cc', ['GetServiceSandboxType<T>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132165 ]
2166 mock_output_api = MockOutputApi()
2167 self._mockChangeOwnerAndReviewers(
2168 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362169 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132170 self.assertEquals(1, len(result))
2171
2172
Mario Sanchez Prada2472cab2019-09-18 10:58:312173class BannedTypeCheckTest(unittest.TestCase):
Sylvain Defresnea8b73d252018-02-28 15:45:542174
Peter Kasting94a56c42019-10-25 21:54:042175 def testBannedCppFunctions(self):
2176 input_api = MockInputApi()
2177 input_api.files = [
2178 MockFile('some/cpp/problematic/file.cc',
2179 ['using namespace std;']),
Oksana Zhuravlovac8222d22019-12-19 19:21:162180 MockFile('third_party/blink/problematic/file.cc',
2181 ['GetInterfaceProvider()']),
Peter Kasting94a56c42019-10-25 21:54:042182 MockFile('some/cpp/ok/file.cc',
2183 ['using std::string;']),
Allen Bauer53b43fb12020-03-12 17:21:472184 MockFile('some/cpp/problematic/file2.cc',
2185 ['set_owned_by_client()']),
Peter Kasting94a56c42019-10-25 21:54:042186 ]
2187
Saagar Sanghavifceeaae2020-08-12 16:40:362188 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlovac8222d22019-12-19 19:21:162189
2190 # warnings are results[0], errors are results[1]
2191 self.assertEqual(2, len(results))
2192 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2193 self.assertTrue(
2194 'third_party/blink/problematic/file.cc' in results[0].message)
2195 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
Allen Bauer53b43fb12020-03-12 17:21:472196 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
Peter Kasting94a56c42019-10-25 21:54:042197
Abhijeet Kandalkar1e7c2502019-10-29 15:05:452198 def testBannedBlinkDowncastHelpers(self):
2199 input_api = MockInputApi()
2200 input_api.files = [
2201 MockFile('some/cpp/problematic/file1.cc',
2202 ['DEFINE_TYPE_CASTS(ToType, FromType, from_argument,'
2203 'PointerPredicate(), ReferencePredicate());']),
2204 MockFile('some/cpp/problematic/file2.cc',
2205 ['bool is_test_ele = IsHTMLTestElement(n);']),
2206 MockFile('some/cpp/problematic/file3.cc',
2207 ['auto* html_test_ele = ToHTMLTestElement(n);']),
2208 MockFile('some/cpp/problematic/file4.cc',
2209 ['auto* html_test_ele_or_null = ToHTMLTestElementOrNull(n);']),
2210 MockFile('some/cpp/ok/file1.cc',
2211 ['bool is_test_ele = IsA<HTMLTestElement>(n);']),
2212 MockFile('some/cpp/ok/file2.cc',
2213 ['auto* html_test_ele = To<HTMLTestElement>(n);']),
2214 MockFile('some/cpp/ok/file3.cc',
2215 ['auto* html_test_ele_or_null = ',
2216 'DynamicTo<HTMLTestElement>(n);']),
2217 ]
2218
2219 # warnings are errors[0], errors are errors[1]
Saagar Sanghavifceeaae2020-08-12 16:40:362220 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Abhijeet Kandalkar1e7c2502019-10-29 15:05:452221 self.assertEqual(2, len(errors))
2222 self.assertTrue('some/cpp/problematic/file1.cc' in errors[1].message)
2223 self.assertTrue('some/cpp/problematic/file2.cc' in errors[0].message)
2224 self.assertTrue('some/cpp/problematic/file3.cc' in errors[0].message)
2225 self.assertTrue('some/cpp/problematic/file4.cc' in errors[0].message)
2226 self.assertTrue('some/cpp/ok/file1.cc' not in errors[0].message)
2227 self.assertTrue('some/cpp/ok/file2.cc' not in errors[0].message)
2228 self.assertTrue('some/cpp/ok/file3.cc' not in errors[0].message)
2229
Peter K. Lee6c03ccff2019-07-15 14:40:052230 def testBannedIosObjcFunctions(self):
Sylvain Defresnea8b73d252018-02-28 15:45:542231 input_api = MockInputApi()
2232 input_api.files = [
2233 MockFile('some/ios/file.mm',
2234 ['TEST(SomeClassTest, SomeInteraction) {',
2235 '}']),
2236 MockFile('some/mac/file.mm',
2237 ['TEST(SomeClassTest, SomeInteraction) {',
2238 '}']),
2239 MockFile('another/ios_file.mm',
2240 ['class SomeTest : public testing::Test {};']),
Peter K. Lee6c03ccff2019-07-15 14:40:052241 MockFile('some/ios/file_egtest.mm',
2242 ['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
2243 MockFile('some/ios/file_unittest.mm',
2244 ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']),
Sylvain Defresnea8b73d252018-02-28 15:45:542245 ]
2246
Saagar Sanghavifceeaae2020-08-12 16:40:362247 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Sylvain Defresnea8b73d252018-02-28 15:45:542248 self.assertEqual(1, len(errors))
2249 self.assertTrue('some/ios/file.mm' in errors[0].message)
2250 self.assertTrue('another/ios_file.mm' in errors[0].message)
2251 self.assertTrue('some/mac/file.mm' not in errors[0].message)
Peter K. Lee6c03ccff2019-07-15 14:40:052252 self.assertTrue('some/ios/file_egtest.mm' in errors[0].message)
2253 self.assertTrue('some/ios/file_unittest.mm' not in errors[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542254
Carlos Knippschildab192b8c2019-04-08 20:02:382255 def testBannedMojoFunctions(self):
2256 input_api = MockInputApi()
2257 input_api.files = [
2258 MockFile('some/cpp/problematic/file.cc',
2259 ['mojo::DataPipe();']),
Oksana Zhuravlovafd247772019-05-16 16:57:292260 MockFile('some/cpp/problematic/file2.cc',
2261 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382262 MockFile('some/cpp/ok/file.cc',
2263 ['CreateDataPipe();']),
Kinuko Yasuda376c2ce12019-04-16 01:20:372264 MockFile('some/cpp/ok/file2.cc',
2265 ['mojo::DataPipeDrainer();']),
Oksana Zhuravlovafd247772019-05-16 16:57:292266 MockFile('third_party/blink/ok/file3.cc',
2267 ['mojo::ConvertTo<>']),
2268 MockFile('content/renderer/ok/file3.cc',
2269 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382270 ]
2271
Saagar Sanghavifceeaae2020-08-12 16:40:362272 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222273
2274 # warnings are results[0], errors are results[1]
2275 self.assertEqual(2, len(results))
2276 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2277 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
2278 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
2279 self.assertTrue('some/cpp/ok/file2.cc' not in results[1].message)
2280 self.assertTrue('third_party/blink/ok/file3.cc' not in results[0].message)
2281 self.assertTrue('content/renderer/ok/file3.cc' not in results[0].message)
Carlos Knippschildab192b8c2019-04-08 20:02:382282
Mario Sanchez Prada2472cab2019-09-18 10:58:312283 def testDeprecatedMojoTypes(self):
Mario Sanchez Pradacec9cef2019-12-15 11:54:572284 ok_paths = ['components/arc']
2285 warning_paths = ['some/cpp']
Mario Sanchez Pradaaab91382019-12-19 08:57:092286 error_paths = ['third_party/blink', 'content']
Mario Sanchez Prada2472cab2019-09-18 10:58:312287 test_cases = [
2288 {
2289 'type': 'mojo::AssociatedBinding<>;',
2290 'file': 'file1.c'
2291 },
2292 {
2293 'type': 'mojo::AssociatedBindingSet<>;',
2294 'file': 'file2.c'
2295 },
2296 {
2297 'type': 'mojo::AssociatedInterfacePtr<>',
2298 'file': 'file3.cc'
2299 },
2300 {
2301 'type': 'mojo::AssociatedInterfacePtrInfo<>',
2302 'file': 'file4.cc'
2303 },
2304 {
2305 'type': 'mojo::AssociatedInterfaceRequest<>',
2306 'file': 'file5.cc'
2307 },
2308 {
2309 'type': 'mojo::Binding<>',
2310 'file': 'file6.cc'
2311 },
2312 {
2313 'type': 'mojo::BindingSet<>',
2314 'file': 'file7.cc'
2315 },
2316 {
2317 'type': 'mojo::InterfacePtr<>',
2318 'file': 'file8.cc'
2319 },
2320 {
2321 'type': 'mojo::InterfacePtrInfo<>',
2322 'file': 'file9.cc'
2323 },
2324 {
2325 'type': 'mojo::InterfaceRequest<>',
2326 'file': 'file10.cc'
2327 },
2328 {
2329 'type': 'mojo::MakeRequest()',
2330 'file': 'file11.cc'
2331 },
2332 {
2333 'type': 'mojo::MakeRequestAssociatedWithDedicatedPipe()',
2334 'file': 'file12.cc'
2335 },
2336 {
2337 'type': 'mojo::MakeStrongBinding()<>',
2338 'file': 'file13.cc'
2339 },
2340 {
2341 'type': 'mojo::MakeStrongAssociatedBinding()<>',
2342 'file': 'file14.cc'
2343 },
2344 {
Gyuyoung Kim4952ba62020-07-07 07:33:442345 'type': 'mojo::StrongAssociatedBinding<>',
Mario Sanchez Prada2472cab2019-09-18 10:58:312346 'file': 'file15.cc'
2347 },
2348 {
Gyuyoung Kim4952ba62020-07-07 07:33:442349 'type': 'mojo::StrongBinding<>',
Mario Sanchez Prada2472cab2019-09-18 10:58:312350 'file': 'file16.cc'
2351 },
Gyuyoung Kim4952ba62020-07-07 07:33:442352 {
2353 'type': 'mojo::StrongAssociatedBindingSet<>',
2354 'file': 'file17.cc'
2355 },
2356 {
2357 'type': 'mojo::StrongBindingSet<>',
2358 'file': 'file18.cc'
2359 },
Mario Sanchez Prada2472cab2019-09-18 10:58:312360 ]
2361
2362 # Build the list of MockFiles considering paths that should trigger warnings
Mario Sanchez Pradacec9cef2019-12-15 11:54:572363 # as well as paths that should trigger errors.
Mario Sanchez Prada2472cab2019-09-18 10:58:312364 input_api = MockInputApi()
2365 input_api.files = []
2366 for test_case in test_cases:
2367 for path in ok_paths:
2368 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2369 [test_case['type']]))
2370 for path in warning_paths:
2371 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2372 [test_case['type']]))
Mario Sanchez Pradacec9cef2019-12-15 11:54:572373 for path in error_paths:
2374 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2375 [test_case['type']]))
Mario Sanchez Prada2472cab2019-09-18 10:58:312376
Saagar Sanghavifceeaae2020-08-12 16:40:362377 results = PRESUBMIT.CheckNoDeprecatedMojoTypes(input_api, MockOutputApi())
Mario Sanchez Prada2472cab2019-09-18 10:58:312378
Mario Sanchez Pradacec9cef2019-12-15 11:54:572379 # warnings are results[0], errors are results[1]
2380 self.assertEqual(2, len(results))
Mario Sanchez Prada2472cab2019-09-18 10:58:312381
2382 for test_case in test_cases:
Mario Sanchez Pradacec9cef2019-12-15 11:54:572383 # Check that no warnings nor errors have been triggered for these paths.
Mario Sanchez Prada2472cab2019-09-18 10:58:312384 for path in ok_paths:
2385 self.assertFalse(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572386 self.assertFalse(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312387
2388 # Check warnings have been triggered for these paths.
2389 for path in warning_paths:
2390 self.assertTrue(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572391 self.assertFalse(path in results[1].message)
2392
2393 # Check errors have been triggered for these paths.
2394 for path in error_paths:
2395 self.assertFalse(path in results[0].message)
2396 self.assertTrue(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312397
Sylvain Defresnea8b73d252018-02-28 15:45:542398
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272399class NoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:242400 def testTruePositives(self):
2401 mock_input_api = MockInputApi()
2402 mock_input_api.files = [
2403 MockFile('some/path/foo.cc', ['foo_for_testing();']),
2404 MockFile('some/path/foo.mm', ['FooForTesting();']),
2405 MockFile('some/path/foo.cxx', ['FooForTests();']),
2406 MockFile('some/path/foo.cpp', ['foo_for_test();']),
2407 ]
2408
Saagar Sanghavifceeaae2020-08-12 16:40:362409 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242410 mock_input_api, MockOutputApi())
2411 self.assertEqual(1, len(results))
2412 self.assertEqual(4, len(results[0].items))
2413 self.assertTrue('foo.cc' in results[0].items[0])
2414 self.assertTrue('foo.mm' in results[0].items[1])
2415 self.assertTrue('foo.cxx' in results[0].items[2])
2416 self.assertTrue('foo.cpp' in results[0].items[3])
2417
2418 def testFalsePositives(self):
2419 mock_input_api = MockInputApi()
2420 mock_input_api.files = [
2421 MockFile('some/path/foo.h', ['foo_for_testing();']),
2422 MockFile('some/path/foo.mm', ['FooForTesting() {']),
2423 MockFile('some/path/foo.cc', ['::FooForTests();']),
2424 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
2425 ]
2426
Saagar Sanghavifceeaae2020-08-12 16:40:362427 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242428 mock_input_api, MockOutputApi())
2429 self.assertEqual(0, len(results))
2430
2431
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272432class NoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:232433 def testTruePositives(self):
2434 mock_input_api = MockInputApi()
2435 mock_input_api.files = [
2436 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
2437 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392438 MockFile('dir/java/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232439 MockFile('dir/java/src/mult.java', [
2440 'int x = SomethingLongHere()',
2441 ' * SomethingLongHereForTesting();'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392442 ])
Vaclav Brozek7dbc28c2018-03-27 08:35:232443 ]
2444
Saagar Sanghavifceeaae2020-08-12 16:40:362445 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232446 mock_input_api, MockOutputApi())
2447 self.assertEqual(1, len(results))
2448 self.assertEqual(4, len(results[0].items))
2449 self.assertTrue('foo.java' in results[0].items[0])
2450 self.assertTrue('bar.java' in results[0].items[1])
2451 self.assertTrue('baz.java' in results[0].items[2])
2452 self.assertTrue('mult.java' in results[0].items[3])
2453
2454 def testFalsePositives(self):
2455 mock_input_api = MockInputApi()
2456 mock_input_api.files = [
2457 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
2458 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
2459 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
2460 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
Sky Malice9e6d6032020-10-15 22:49:552461 MockFile('dir/java/src/bar3.java', ['@VisibleForTesting']),
2462 MockFile('dir/java/src/bar4.java', ['@VisibleForTesting()']),
2463 MockFile('dir/java/src/bar5.java', [
2464 '@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)'
2465 ]),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392466 MockFile('dir/javatests/src/baz.java', ['FooForTest(', 'y', ');']),
2467 MockFile('dir/junit/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232468 MockFile('dir/junit/src/javadoc.java', [
2469 '/** Use FooForTest(); to obtain foo in tests.'
2470 ' */'
2471 ]),
2472 MockFile('dir/junit/src/javadoc2.java', [
2473 '/** ',
2474 ' * Use FooForTest(); to obtain foo in tests.'
2475 ' */'
2476 ]),
2477 ]
2478
Saagar Sanghavifceeaae2020-08-12 16:40:362479 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232480 mock_input_api, MockOutputApi())
2481 self.assertEqual(0, len(results))
2482
2483
Mohamed Heikald048240a2019-11-12 16:57:372484class NewImagesWarningTest(unittest.TestCase):
2485 def testTruePositives(self):
2486 mock_input_api = MockInputApi()
2487 mock_input_api.files = [
2488 MockFile('dir/android/res/drawable/foo.png', []),
2489 MockFile('dir/android/res/drawable-v21/bar.svg', []),
2490 MockFile('dir/android/res/mipmap-v21-en/baz.webp', []),
2491 MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png', []),
2492 ]
2493
2494 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2495 self.assertEqual(1, len(results))
2496 self.assertEqual(4, len(results[0].items))
2497 self.assertTrue('foo.png' in results[0].items[0].LocalPath())
2498 self.assertTrue('bar.svg' in results[0].items[1].LocalPath())
2499 self.assertTrue('baz.webp' in results[0].items[2].LocalPath())
2500 self.assertTrue('foobar.png' in results[0].items[3].LocalPath())
2501
2502 def testFalsePositives(self):
2503 mock_input_api = MockInputApi()
2504 mock_input_api.files = [
2505 MockFile('dir/pngs/README.md', []),
2506 MockFile('java/test/res/drawable/foo.png', []),
2507 MockFile('third_party/blink/foo.png', []),
2508 MockFile('dir/third_party/libpng/src/foo.cc', ['foobar']),
2509 MockFile('dir/resources.webp/.gitignore', ['foo.png']),
2510 ]
2511
2512 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2513 self.assertEqual(0, len(results))
2514
2515
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272516class CheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:052517 def testTruePositivesNullptr(self):
2518 mock_input_api = MockInputApi()
2519 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162520 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
2521 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
Vaclav Brozek851d9602018-04-04 16:13:052522 ]
2523
Saagar Sanghavifceeaae2020-08-12 16:40:362524 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052525 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162526 self.assertTrue('nullptr' in results[0].message)
Vaclav Brozek851d9602018-04-04 16:13:052527 self.assertEqual(2, len(results[0].items))
2528 self.assertTrue('baz.cc' in results[0].items[0])
2529 self.assertTrue('baz-p.cc' in results[0].items[1])
2530
2531 def testTruePositivesConstructor(self):
Vaclav Brozek52e18bf2018-04-03 07:05:242532 mock_input_api = MockInputApi()
2533 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162534 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
2535 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
2536 MockFile('dir/mult.cc', [
Vaclav Brozek95face62018-04-04 14:15:112537 'return',
2538 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
2539 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162540 MockFile('dir/mult2.cc', [
Vaclav Brozek95face62018-04-04 14:15:112541 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
2542 ' std::unique_ptr<T>(foo);'
2543 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162544 MockFile('dir/mult3.cc', [
Vaclav Brozek95face62018-04-04 14:15:112545 'bar = std::unique_ptr<T>(',
2546 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
2547 ]),
Vaclav Brozekb7fadb692018-08-30 06:39:532548 MockFile('dir/multi_arg.cc', [
2549 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']),
Vaclav Brozek52e18bf2018-04-03 07:05:242550 ]
2551
Saagar Sanghavifceeaae2020-08-12 16:40:362552 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052553 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162554 self.assertTrue('std::make_unique' in results[0].message)
Vaclav Brozekb7fadb692018-08-30 06:39:532555 self.assertEqual(6, len(results[0].items))
Vaclav Brozek851d9602018-04-04 16:13:052556 self.assertTrue('foo.cc' in results[0].items[0])
2557 self.assertTrue('bar.mm' in results[0].items[1])
2558 self.assertTrue('mult.cc' in results[0].items[2])
2559 self.assertTrue('mult2.cc' in results[0].items[3])
2560 self.assertTrue('mult3.cc' in results[0].items[4])
Vaclav Brozekb7fadb692018-08-30 06:39:532561 self.assertTrue('multi_arg.cc' in results[0].items[5])
Vaclav Brozek52e18bf2018-04-03 07:05:242562
2563 def testFalsePositives(self):
2564 mock_input_api = MockInputApi()
2565 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162566 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
2567 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
2568 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
2569 MockFile('dir/baz.cc', [
Vaclav Brozek52e18bf2018-04-03 07:05:242570 'std::unique_ptr<T> result = std::make_unique<T>();'
2571 ]),
Vaclav Brozeka54c528b2018-04-06 19:23:552572 MockFile('dir/baz2.cc', [
2573 'std::unique_ptr<T> result = std::make_unique<T>('
2574 ]),
2575 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
2576 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
Vaclav Brozekb7fadb692018-08-30 06:39:532577
2578 # Two-argument invocation of std::unique_ptr is exempt because there is
2579 # no equivalent using std::make_unique.
2580 MockFile('dir/multi_arg.cc', [
2581 'auto p = std::unique_ptr<T, D>(new T(), D());']),
Vaclav Brozek52e18bf2018-04-03 07:05:242582 ]
2583
Saagar Sanghavifceeaae2020-08-12 16:40:362584 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek52e18bf2018-04-03 07:05:242585 self.assertEqual(0, len(results))
2586
Danil Chapovalov3518f362018-08-11 16:13:432587class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
2588 def testBlocksDirectIncludes(self):
2589 mock_input_api = MockInputApi()
2590 mock_input_api.files = [
2591 MockFile('dir/foo_win.cc', ['#include "shlwapi.h"']),
2592 MockFile('dir/bar.h', ['#include <propvarutil.h>']),
2593 MockFile('dir/baz.h', ['#include <atlbase.h>']),
2594 MockFile('dir/jumbo.h', ['#include "sphelper.h"']),
2595 ]
2596 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2597 self.assertEquals(1, len(results))
2598 self.assertEquals(4, len(results[0].items))
2599 self.assertTrue('StrCat' in results[0].message)
2600 self.assertTrue('foo_win.cc' in results[0].items[0])
2601 self.assertTrue('bar.h' in results[0].items[1])
2602 self.assertTrue('baz.h' in results[0].items[2])
2603 self.assertTrue('jumbo.h' in results[0].items[3])
2604
2605 def testAllowsToIncludeWrapper(self):
2606 mock_input_api = MockInputApi()
2607 mock_input_api.files = [
2608 MockFile('dir/baz_win.cc', ['#include "base/win/shlwapi.h"']),
2609 MockFile('dir/baz-win.h', ['#include "base/win/atl.h"']),
2610 ]
2611 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2612 self.assertEquals(0, len(results))
2613
2614 def testAllowsToCreateWrapper(self):
2615 mock_input_api = MockInputApi()
2616 mock_input_api.files = [
2617 MockFile('base/win/shlwapi.h', [
2618 '#include <shlwapi.h>',
2619 '#include "base/win/windows_defines.inc"']),
2620 ]
2621 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2622 self.assertEquals(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:242623
Mustafa Emre Acer51f2f742020-03-09 19:41:122624
Rainhard Findlingfc31844c52020-05-15 09:58:262625class StringTest(unittest.TestCase):
2626 """Tests ICU syntax check and translation screenshots check."""
2627
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142628 # An empty grd file.
2629 OLD_GRD_CONTENTS = """<?xml version="1.0" encoding="UTF-8"?>
2630 <grit latest_public_release="1" current_release="1">
2631 <release seq="1">
2632 <messages></messages>
2633 </release>
2634 </grit>
2635 """.splitlines()
2636 # A grd file with a single message.
2637 NEW_GRD_CONTENTS1 = """<?xml version="1.0" encoding="UTF-8"?>
2638 <grit latest_public_release="1" current_release="1">
2639 <release seq="1">
2640 <messages>
2641 <message name="IDS_TEST1">
2642 Test string 1
2643 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482644 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE1"
2645 translateable="false">
2646 Non translateable message 1, should be ignored
2647 </message>
Mustafa Emre Acered1a48962020-06-30 19:15:392648 <message name="IDS_TEST_STRING_ACCESSIBILITY"
Mustafa Emre Acerd3ca8be2020-07-07 22:35:342649 is_accessibility_with_no_ui="true">
Mustafa Emre Acered1a48962020-06-30 19:15:392650 Accessibility label 1, should be ignored
2651 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142652 </messages>
2653 </release>
2654 </grit>
2655 """.splitlines()
2656 # A grd file with two messages.
2657 NEW_GRD_CONTENTS2 = """<?xml version="1.0" encoding="UTF-8"?>
2658 <grit latest_public_release="1" current_release="1">
2659 <release seq="1">
2660 <messages>
2661 <message name="IDS_TEST1">
2662 Test string 1
2663 </message>
2664 <message name="IDS_TEST2">
2665 Test string 2
2666 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482667 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE2"
2668 translateable="false">
2669 Non translateable message 2, should be ignored
2670 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142671 </messages>
2672 </release>
2673 </grit>
2674 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:262675 # A grd file with one ICU syntax message without syntax errors.
2676 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1 = """<?xml version="1.0" encoding="UTF-8"?>
2677 <grit latest_public_release="1" current_release="1">
2678 <release seq="1">
2679 <messages>
2680 <message name="IDS_TEST1">
2681 {NUM, plural,
2682 =1 {Test text for numeric one}
2683 other {Test text for plural with {NUM} as number}}
2684 </message>
2685 </messages>
2686 </release>
2687 </grit>
2688 """.splitlines()
2689 # A grd file with one ICU syntax message without syntax errors.
2690 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2 = """<?xml version="1.0" encoding="UTF-8"?>
2691 <grit latest_public_release="1" current_release="1">
2692 <release seq="1">
2693 <messages>
2694 <message name="IDS_TEST1">
2695 {NUM, plural,
2696 =1 {Different test text for numeric one}
2697 other {Different test text for plural with {NUM} as number}}
2698 </message>
2699 </messages>
2700 </release>
2701 </grit>
2702 """.splitlines()
2703 # A grd file with one ICU syntax message with syntax errors (misses a comma).
2704 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
2705 <grit latest_public_release="1" current_release="1">
2706 <release seq="1">
2707 <messages>
2708 <message name="IDS_TEST1">
2709 {NUM, plural
2710 =1 {Test text for numeric one}
2711 other {Test text for plural with {NUM} as number}}
2712 </message>
2713 </messages>
2714 </release>
2715 </grit>
2716 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142717
meacerff8a9b62019-12-10 19:43:582718 OLD_GRDP_CONTENTS = (
2719 '<?xml version="1.0" encoding="utf-8"?>',
2720 '<grit-part>',
2721 '</grit-part>'
2722 )
2723
2724 NEW_GRDP_CONTENTS1 = (
2725 '<?xml version="1.0" encoding="utf-8"?>',
2726 '<grit-part>',
2727 '<message name="IDS_PART_TEST1">',
2728 'Part string 1',
2729 '</message>',
2730 '</grit-part>')
2731
2732 NEW_GRDP_CONTENTS2 = (
2733 '<?xml version="1.0" encoding="utf-8"?>',
2734 '<grit-part>',
2735 '<message name="IDS_PART_TEST1">',
2736 'Part string 1',
2737 '</message>',
2738 '<message name="IDS_PART_TEST2">',
2739 'Part string 2',
2740 '</message>',
2741 '</grit-part>')
2742
Rainhard Findlingd8d04372020-08-13 13:30:092743 NEW_GRDP_CONTENTS3 = (
2744 '<?xml version="1.0" encoding="utf-8"?>',
2745 '<grit-part>',
2746 '<message name="IDS_PART_TEST1" desc="Description with typo.">',
2747 'Part string 1',
2748 '</message>',
2749 '</grit-part>')
2750
2751 NEW_GRDP_CONTENTS4 = (
2752 '<?xml version="1.0" encoding="utf-8"?>',
2753 '<grit-part>',
2754 '<message name="IDS_PART_TEST1" desc="Description with typo fixed.">',
2755 'Part string 1',
2756 '</message>',
2757 '</grit-part>')
2758
Rainhard Findling1a3e71e2020-09-21 07:33:352759 NEW_GRDP_CONTENTS5 = (
2760 '<?xml version="1.0" encoding="utf-8"?>',
2761 '<grit-part>',
2762 '<message name="IDS_PART_TEST1" meaning="Meaning with typo.">',
2763 'Part string 1',
2764 '</message>',
2765 '</grit-part>')
2766
2767 NEW_GRDP_CONTENTS6 = (
2768 '<?xml version="1.0" encoding="utf-8"?>',
2769 '<grit-part>',
2770 '<message name="IDS_PART_TEST1" meaning="Meaning with typo fixed.">',
2771 'Part string 1',
2772 '</message>',
2773 '</grit-part>')
2774
Rainhard Findlingfc31844c52020-05-15 09:58:262775 # A grdp file with one ICU syntax message without syntax errors.
2776 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = (
2777 '<?xml version="1.0" encoding="utf-8"?>',
2778 '<grit-part>',
2779 '<message name="IDS_PART_TEST1">',
2780 '{NUM, plural,',
2781 '=1 {Test text for numeric one}',
2782 'other {Test text for plural with {NUM} as number}}',
2783 '</message>',
2784 '</grit-part>')
2785 # A grdp file with one ICU syntax message without syntax errors.
2786 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2 = (
2787 '<?xml version="1.0" encoding="utf-8"?>',
2788 '<grit-part>',
2789 '<message name="IDS_PART_TEST1">',
2790 '{NUM, plural,',
2791 '=1 {Different test text for numeric one}',
2792 'other {Different test text for plural with {NUM} as number}}',
2793 '</message>',
2794 '</grit-part>')
2795
2796 # A grdp file with one ICU syntax message with syntax errors (superfluent
2797 # whitespace).
2798 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR = (
2799 '<?xml version="1.0" encoding="utf-8"?>',
2800 '<grit-part>',
2801 '<message name="IDS_PART_TEST1">',
2802 '{NUM, plural,',
2803 '= 1 {Test text for numeric one}',
2804 'other {Test text for plural with {NUM} as number}}',
2805 '</message>',
2806 '</grit-part>')
2807
Mustafa Emre Acerc8a012d2018-07-31 00:00:392808 DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
2809 'changelist. Run '
2810 'tools/translate/upload_screenshots.py to '
2811 'upload them instead:')
2812 GENERATE_SIGNATURES_MESSAGE = ('You are adding or modifying UI strings.\n'
2813 'To ensure the best translations, take '
2814 'screenshots of the relevant UI '
2815 '(https://g.co/chrome/translation) and add '
2816 'these files to your changelist:')
2817 REMOVE_SIGNATURES_MESSAGE = ('You removed strings associated with these '
2818 'files. Remove:')
Rainhard Findlingfc31844c52020-05-15 09:58:262819 ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
2820 'strings (problems or feedback? Contact '
2821 '[email protected]):')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142822
2823 def makeInputApi(self, files):
2824 input_api = MockInputApi()
2825 input_api.files = files
meacere7be7532019-10-02 17:41:032826 # Override os_path.exists because the presubmit uses the actual
2827 # os.path.exists.
2828 input_api.CreateMockFileInPath(
2829 [x.LocalPath() for x in input_api.AffectedFiles(include_deletes=True)])
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142830 return input_api
2831
meacerff8a9b62019-12-10 19:43:582832 """ CL modified and added messages, but didn't add any screenshots."""
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142833 def testNoScreenshots(self):
meacerff8a9b62019-12-10 19:43:582834 # No new strings (file contents same). Should not warn.
2835 input_api = self.makeInputApi([
2836 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
2837 self.NEW_GRD_CONTENTS1, action='M'),
2838 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1,
2839 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362840 warnings = PRESUBMIT.CheckStrings(input_api,
meacerff8a9b62019-12-10 19:43:582841 MockOutputApi())
2842 self.assertEqual(0, len(warnings))
2843
2844 # Add two new strings. Should have two warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142845 input_api = self.makeInputApi([
2846 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582847 self.NEW_GRD_CONTENTS1, action='M'),
2848 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2849 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362850 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142851 MockOutputApi())
2852 self.assertEqual(1, len(warnings))
2853 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerc6ed2682020-07-07 07:24:002854 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012855 self.assertEqual([
meacerff8a9b62019-12-10 19:43:582856 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2857 os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
2858 warnings[0].items)
Mustafa Emre Acer36eaad52019-11-12 23:03:342859
meacerff8a9b62019-12-10 19:43:582860 # Add four new strings. Should have four warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:212861 input_api = self.makeInputApi([
2862 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582863 self.OLD_GRD_CONTENTS, action='M'),
2864 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2865 self.OLD_GRDP_CONTENTS, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362866 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:212867 MockOutputApi())
2868 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:002869 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:212870 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:582871 self.assertEqual([
2872 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2873 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2874 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
2875 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
2876 ], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:212877
Rainhard Findlingd8d04372020-08-13 13:30:092878 def testModifiedMessageDescription(self):
2879 # CL modified a message description for a message that does not yet have a
Rainhard Findling1a3e71e2020-09-21 07:33:352880 # screenshot. Should not warn.
Rainhard Findlingd8d04372020-08-13 13:30:092881 input_api = self.makeInputApi([
2882 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
2883 self.NEW_GRDP_CONTENTS4, action='M')])
2884 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findling1a3e71e2020-09-21 07:33:352885 self.assertEqual(0, len(warnings))
Rainhard Findlingd8d04372020-08-13 13:30:092886
2887 # CL modified a message description for a message that already has a
2888 # screenshot. Should not warn.
2889 input_api = self.makeInputApi([
2890 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
2891 self.NEW_GRDP_CONTENTS4, action='M'),
2892 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2893 'binary', action='A')])
2894 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
2895 self.assertEqual(0, len(warnings))
2896
Rainhard Findling1a3e71e2020-09-21 07:33:352897 def testModifiedMessageMeaning(self):
2898 # CL modified a message meaning for a message that does not yet have a
2899 # screenshot. Should warn.
2900 input_api = self.makeInputApi([
2901 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
2902 self.NEW_GRDP_CONTENTS6, action='M')])
2903 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
2904 self.assertEqual(1, len(warnings))
2905
2906 # CL modified a message meaning for a message that already has a
2907 # screenshot. Should not warn.
2908 input_api = self.makeInputApi([
2909 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
2910 self.NEW_GRDP_CONTENTS6, action='M'),
2911 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2912 'binary', action='A')])
2913 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
2914 self.assertEqual(0, len(warnings))
2915
meacerff8a9b62019-12-10 19:43:582916 def testPngAddedSha1NotAdded(self):
2917 # CL added one new message in a grd file and added the png file associated
2918 # with it, but did not add the corresponding sha1 file. This should warn
2919 # twice:
2920 # - Once for the added png file (because we don't want developers to upload
2921 # actual images)
2922 # - Once for the missing .sha1 file
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142923 input_api = self.makeInputApi([
Mustafa Emre Acerea3e57a2018-12-17 23:51:012924 MockAffectedFile(
2925 'test.grd',
2926 self.NEW_GRD_CONTENTS1,
2927 self.OLD_GRD_CONTENTS,
2928 action='M'),
2929 MockAffectedFile(
2930 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
2931 ])
Saagar Sanghavifceeaae2020-08-12 16:40:362932 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142933 MockOutputApi())
2934 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:002935 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142936 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012937 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
2938 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:002939 self.assertEqual('error', warnings[1].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142940 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012941 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
2942 warnings[1].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142943
meacerff8a9b62019-12-10 19:43:582944 # CL added two messages (one in grd, one in grdp) and added the png files
2945 # associated with the messages, but did not add the corresponding sha1
2946 # files. This should warn twice:
2947 # - Once for the added png files (because we don't want developers to upload
2948 # actual images)
2949 # - Once for the missing .sha1 files
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142950 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:582951 # Modified files:
Mustafa Emre Acer36eaad52019-11-12 23:03:342952 MockAffectedFile(
2953 'test.grd',
meacerff8a9b62019-12-10 19:43:582954 self.NEW_GRD_CONTENTS1,
Mustafa Emre Acer36eaad52019-11-12 23:03:342955 self.OLD_GRD_CONTENTS,
meacer2308d0742019-11-12 18:15:422956 action='M'),
Mustafa Emre Acer12e7fee2019-11-18 18:49:552957 MockAffectedFile(
meacerff8a9b62019-12-10 19:43:582958 'part.grdp',
2959 self.NEW_GRDP_CONTENTS1,
2960 self.OLD_GRDP_CONTENTS,
2961 action='M'),
2962 # Added files:
2963 MockAffectedFile(
2964 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A'),
2965 MockAffectedFile(
2966 os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary',
2967 action='A')
Mustafa Emre Acerad8fb082019-11-19 04:24:212968 ])
Saagar Sanghavifceeaae2020-08-12 16:40:362969 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:212970 MockOutputApi())
2971 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:002972 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:212973 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:582974 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png'),
2975 os.path.join('test_grd', 'IDS_TEST1.png')],
Mustafa Emre Acerad8fb082019-11-19 04:24:212976 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:002977 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:212978 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
meacerff8a9b62019-12-10 19:43:582979 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2980 os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
2981 warnings[1].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:212982
2983 def testScreenshotsWithSha1(self):
meacerff8a9b62019-12-10 19:43:582984 # CL added four messages (two each in a grd and grdp) and their
2985 # corresponding .sha1 files. No warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:212986 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:582987 # Modified files:
Mustafa Emre Acerad8fb082019-11-19 04:24:212988 MockAffectedFile(
2989 'test.grd',
2990 self.NEW_GRD_CONTENTS2,
2991 self.OLD_GRD_CONTENTS,
Mustafa Emre Acer12e7fee2019-11-18 18:49:552992 action='M'),
meacerff8a9b62019-12-10 19:43:582993 MockAffectedFile(
2994 'part.grdp',
2995 self.NEW_GRDP_CONTENTS2,
2996 self.OLD_GRDP_CONTENTS,
2997 action='M'),
2998 # Added files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:012999 MockFile(
3000 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3001 'binary',
3002 action='A'),
3003 MockFile(
3004 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3005 'binary',
meacerff8a9b62019-12-10 19:43:583006 action='A'),
3007 MockFile(
3008 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3009 'binary',
3010 action='A'),
3011 MockFile(
3012 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3013 'binary',
3014 action='A'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013015 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363016 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143017 MockOutputApi())
3018 self.assertEqual([], warnings)
3019
3020 def testScreenshotsRemovedWithSha1(self):
meacerff8a9b62019-12-10 19:43:583021 # Replace new contents with old contents in grd and grp files, removing
3022 # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3023 # Should warn to remove the sha1 files associated with these strings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143024 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583025 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013026 MockAffectedFile(
3027 'test.grd',
meacerff8a9b62019-12-10 19:43:583028 self.OLD_GRD_CONTENTS, # new_contents
3029 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013030 action='M'),
meacerff8a9b62019-12-10 19:43:583031 MockAffectedFile(
3032 'part.grdp',
3033 self.OLD_GRDP_CONTENTS, # new_contents
3034 self.NEW_GRDP_CONTENTS2, # old_contents
3035 action='M'),
3036 # Unmodified files:
3037 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
3038 MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', ''),
3039 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3040 'binary', ''),
3041 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3042 'binary', '')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013043 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363044 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143045 MockOutputApi())
3046 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003047 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143048 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013049 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583050 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3051 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013052 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3053 os.path.join('test_grd', 'IDS_TEST2.png.sha1')
3054 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143055
meacerff8a9b62019-12-10 19:43:583056 # Same as above, but this time one of the .sha1 files is also removed.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143057 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583058 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013059 MockAffectedFile(
3060 'test.grd',
meacerff8a9b62019-12-10 19:43:583061 self.OLD_GRD_CONTENTS, # new_contents
3062 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013063 action='M'),
meacerff8a9b62019-12-10 19:43:583064 MockAffectedFile(
3065 'part.grdp',
3066 self.OLD_GRDP_CONTENTS, # new_contents
3067 self.NEW_GRDP_CONTENTS2, # old_contents
3068 action='M'),
3069 # Unmodified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013070 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
meacerff8a9b62019-12-10 19:43:583071 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3072 'binary', ''),
3073 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013074 MockAffectedFile(
3075 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3076 '',
3077 'old_contents',
meacerff8a9b62019-12-10 19:43:583078 action='D'),
3079 MockAffectedFile(
3080 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3081 '',
3082 'old_contents',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013083 action='D')
3084 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363085 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143086 MockOutputApi())
3087 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003088 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143089 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583090 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3091 os.path.join('test_grd', 'IDS_TEST1.png.sha1')
3092 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143093
meacerff8a9b62019-12-10 19:43:583094 # Remove all sha1 files. There should be no warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143095 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583096 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013097 MockAffectedFile(
3098 'test.grd',
3099 self.OLD_GRD_CONTENTS,
3100 self.NEW_GRD_CONTENTS2,
3101 action='M'),
meacerff8a9b62019-12-10 19:43:583102 MockAffectedFile(
3103 'part.grdp',
3104 self.OLD_GRDP_CONTENTS,
3105 self.NEW_GRDP_CONTENTS2,
3106 action='M'),
3107 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013108 MockFile(
3109 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3110 'binary',
3111 action='D'),
3112 MockFile(
3113 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3114 'binary',
meacerff8a9b62019-12-10 19:43:583115 action='D'),
3116 MockFile(
3117 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3118 'binary',
3119 action='D'),
3120 MockFile(
3121 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3122 'binary',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013123 action='D')
3124 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363125 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143126 MockOutputApi())
3127 self.assertEqual([], warnings)
3128
Rainhard Findlingfc31844c52020-05-15 09:58:263129 def testIcuSyntax(self):
3130 # Add valid ICU syntax string. Should not raise an error.
3131 input_api = self.makeInputApi([
3132 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3133 self.NEW_GRD_CONTENTS1, action='M'),
3134 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3135 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363136 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263137 # We expect no ICU syntax errors.
3138 icu_errors = [e for e in results
3139 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3140 self.assertEqual(0, len(icu_errors))
3141
3142 # Valid changes in ICU syntax. Should not raise an error.
3143 input_api = self.makeInputApi([
3144 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3145 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3146 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3147 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363148 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263149 # We expect no ICU syntax errors.
3150 icu_errors = [e for e in results
3151 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3152 self.assertEqual(0, len(icu_errors))
3153
3154 # Add invalid ICU syntax strings. Should raise two errors.
3155 input_api = self.makeInputApi([
3156 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3157 self.NEW_GRD_CONTENTS1, action='M'),
3158 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3159 self.NEW_GRD_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363160 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263161 # We expect 2 ICU syntax errors.
3162 icu_errors = [e for e in results
3163 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3164 self.assertEqual(1, len(icu_errors))
3165 self.assertEqual([
3166 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3167 'ICU syntax.',
3168 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3169 ], icu_errors[0].items)
3170
3171 # Change two strings to have ICU syntax errors. Should raise two errors.
3172 input_api = self.makeInputApi([
3173 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3174 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3175 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3176 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363177 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263178 # We expect 2 ICU syntax errors.
3179 icu_errors = [e for e in results
3180 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3181 self.assertEqual(1, len(icu_errors))
3182 self.assertEqual([
3183 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3184 'ICU syntax.',
3185 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3186 ], icu_errors[0].items)
3187
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143188
Mustafa Emre Acer51f2f742020-03-09 19:41:123189class TranslationExpectationsTest(unittest.TestCase):
3190 ERROR_MESSAGE_FORMAT = (
3191 "Failed to get a list of translatable grd files. "
3192 "This happens when:\n"
3193 " - One of the modified grd or grdp files cannot be parsed or\n"
3194 " - %s is not updated.\n"
3195 "Stack:\n"
3196 )
3197 REPO_ROOT = os.path.join('tools', 'translation', 'testdata')
3198 # This lists all .grd files under REPO_ROOT.
3199 EXPECTATIONS = os.path.join(REPO_ROOT,
3200 "translation_expectations.pyl")
3201 # This lists all .grd files under REPO_ROOT except unlisted.grd.
3202 EXPECTATIONS_WITHOUT_UNLISTED_FILE = os.path.join(
3203 REPO_ROOT, "translation_expectations_without_unlisted_file.pyl")
3204
3205 # Tests that the presubmit doesn't return when no grd or grdp files are
3206 # modified.
3207 def testExpectationsNoModifiedGrd(self):
3208 input_api = MockInputApi()
3209 input_api.files = [
3210 MockAffectedFile('not_used.txt', 'not used', 'not used', action='M')
3211 ]
3212 # Fake list of all grd files in the repo. This list is missing all grd/grdps
3213 # under tools/translation/testdata. This is OK because the presubmit won't
3214 # run in the first place since there are no modified grd/grps in input_api.
3215 grd_files = ['doesnt_exist_doesnt_matter.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363216 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123217 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3218 grd_files)
3219 self.assertEqual(0, len(warnings))
3220
3221
3222 # Tests that the list of files passed to the presubmit matches the list of
3223 # files in the expectations.
3224 def testExpectationsSuccess(self):
3225 # Mock input file list needs a grd or grdp file in order to run the
3226 # presubmit. The file itself doesn't matter.
3227 input_api = MockInputApi()
3228 input_api.files = [
3229 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3230 ]
3231 # List of all grd files in the repo.
3232 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3233 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363234 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123235 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3236 grd_files)
3237 self.assertEqual(0, len(warnings))
3238
3239 # Tests that the presubmit warns when a file is listed in expectations, but
3240 # does not actually exist.
3241 def testExpectationsMissingFile(self):
3242 # Mock input file list needs a grd or grdp file in order to run the
3243 # presubmit.
3244 input_api = MockInputApi()
3245 input_api.files = [
3246 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3247 ]
3248 # unlisted.grd is listed under tools/translation/testdata but is not
3249 # included in translation expectations.
3250 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363251 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123252 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3253 grd_files)
3254 self.assertEqual(1, len(warnings))
3255 self.assertTrue(warnings[0].message.startswith(
3256 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS))
3257 self.assertTrue(
3258 ("test.grd is listed in the translation expectations, "
3259 "but this grd file does not exist")
3260 in warnings[0].message)
3261
3262 # Tests that the presubmit warns when a file is not listed in expectations but
3263 # does actually exist.
3264 def testExpectationsUnlistedFile(self):
3265 # Mock input file list needs a grd or grdp file in order to run the
3266 # presubmit.
3267 input_api = MockInputApi()
3268 input_api.files = [
3269 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3270 ]
3271 # unlisted.grd is listed under tools/translation/testdata but is not
3272 # included in translation expectations.
3273 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3274 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363275 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123276 input_api, MockOutputApi(), self.REPO_ROOT,
3277 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3278 self.assertEqual(1, len(warnings))
3279 self.assertTrue(warnings[0].message.startswith(
3280 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3281 self.assertTrue(
3282 ("unlisted.grd appears to be translatable "
3283 "(because it contains <file> or <message> elements), "
3284 "but is not listed in the translation expectations.")
3285 in warnings[0].message)
3286
3287 # Tests that the presubmit warns twice:
3288 # - for a non-existing file listed in expectations
3289 # - for an existing file not listed in expectations
3290 def testMultipleWarnings(self):
3291 # Mock input file list needs a grd or grdp file in order to run the
3292 # presubmit.
3293 input_api = MockInputApi()
3294 input_api.files = [
3295 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3296 ]
3297 # unlisted.grd is listed under tools/translation/testdata but is not
3298 # included in translation expectations.
3299 # test.grd is not listed under tools/translation/testdata but is included
3300 # in translation expectations.
3301 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363302 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123303 input_api, MockOutputApi(), self.REPO_ROOT,
3304 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3305 self.assertEqual(1, len(warnings))
3306 self.assertTrue(warnings[0].message.startswith(
3307 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3308 self.assertTrue(
3309 ("unlisted.grd appears to be translatable "
3310 "(because it contains <file> or <message> elements), "
3311 "but is not listed in the translation expectations.")
3312 in warnings[0].message)
3313 self.assertTrue(
3314 ("test.grd is listed in the translation expectations, "
3315 "but this grd file does not exist")
3316 in warnings[0].message)
3317
3318
Dominic Battre033531052018-09-24 15:45:343319class DISABLETypoInTest(unittest.TestCase):
3320
3321 def testPositive(self):
3322 # Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
3323 # where the desire is to disable a test.
3324 tests = [
3325 # Disabled on one platform:
3326 '#if defined(OS_WIN)\n'
3327 '#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
3328 '#else\n'
3329 '#define MAYBE_FoobarTest FoobarTest\n'
3330 '#endif\n',
3331 # Disabled on one platform spread cross lines:
3332 '#if defined(OS_WIN)\n'
3333 '#define MAYBE_FoobarTest \\\n'
3334 ' DISABLE_FoobarTest\n'
3335 '#else\n'
3336 '#define MAYBE_FoobarTest FoobarTest\n'
3337 '#endif\n',
3338 # Disabled on all platforms:
3339 ' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
3340 # Disabled on all platforms but multiple lines
3341 ' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
3342 ]
3343
3344 for test in tests:
3345 mock_input_api = MockInputApi()
3346 mock_input_api.files = [
3347 MockFile('some/path/foo_unittest.cc', test.splitlines()),
3348 ]
3349
Saagar Sanghavifceeaae2020-08-12 16:40:363350 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343351 MockOutputApi())
3352 self.assertEqual(
3353 1,
3354 len(results),
3355 msg=('expected len(results) == 1 but got %d in test: %s' %
3356 (len(results), test)))
3357 self.assertTrue(
3358 'foo_unittest.cc' in results[0].message,
3359 msg=('expected foo_unittest.cc in message but got %s in test %s' %
3360 (results[0].message, test)))
3361
3362 def testIngoreNotTestFiles(self):
3363 mock_input_api = MockInputApi()
3364 mock_input_api.files = [
3365 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'),
3366 ]
3367
Saagar Sanghavifceeaae2020-08-12 16:40:363368 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343369 MockOutputApi())
3370 self.assertEqual(0, len(results))
3371
Katie Df13948e2018-09-25 07:33:443372 def testIngoreDeletedFiles(self):
3373 mock_input_api = MockInputApi()
3374 mock_input_api.files = [
3375 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'),
3376 ]
3377
Saagar Sanghavifceeaae2020-08-12 16:40:363378 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Katie Df13948e2018-09-25 07:33:443379 MockOutputApi())
3380 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:343381
Dirk Pranke3c18a382019-03-15 01:07:513382
3383class BuildtoolsRevisionsAreInSyncTest(unittest.TestCase):
3384 # TODO(crbug.com/941824): We need to make sure the entries in
3385 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3386 # so that users of //buildtools in other projects get the same tooling
3387 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3388 # support to gclient, we can eliminate the duplication and delete
3389 # these tests for the corresponding presubmit check.
3390
3391 def _check(self, files):
3392 mock_input_api = MockInputApi()
3393 mock_input_api.files = []
3394 for fname, contents in files.items():
3395 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363396 return PRESUBMIT.CheckBuildtoolsRevisionsAreInSync(mock_input_api,
Dirk Pranke3c18a382019-03-15 01:07:513397 MockOutputApi())
3398
3399 def testOneFileChangedButNotTheOther(self):
3400 results = self._check({
3401 "DEPS": "'libunwind_revision': 'onerev'",
3402 })
3403 self.assertNotEqual(results, [])
3404
3405 def testNeitherFileChanged(self):
3406 results = self._check({
3407 "OWNERS": "[email protected]",
3408 })
3409 self.assertEqual(results, [])
3410
3411 def testBothFilesChangedAndMatch(self):
3412 results = self._check({
3413 "DEPS": "'libunwind_revision': 'onerev'",
3414 "buildtools/DEPS": "'libunwind_revision': 'onerev'",
3415 })
3416 self.assertEqual(results, [])
3417
3418 def testBothFilesWereChangedAndDontMatch(self):
3419 results = self._check({
3420 "DEPS": "'libunwind_revision': 'onerev'",
3421 "buildtools/DEPS": "'libunwind_revision': 'anotherrev'",
3422 })
3423 self.assertNotEqual(results, [])
3424
3425
Max Morozb47503b2019-08-08 21:03:273426class CheckFuzzTargetsTest(unittest.TestCase):
3427
3428 def _check(self, files):
3429 mock_input_api = MockInputApi()
3430 mock_input_api.files = []
3431 for fname, contents in files.items():
3432 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363433 return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api, MockOutputApi())
Max Morozb47503b2019-08-08 21:03:273434
3435 def testLibFuzzerSourcesIgnored(self):
3436 results = self._check({
3437 "third_party/lib/Fuzzer/FuzzerDriver.cpp": "LLVMFuzzerInitialize",
3438 })
3439 self.assertEqual(results, [])
3440
3441 def testNonCodeFilesIgnored(self):
3442 results = self._check({
3443 "README.md": "LLVMFuzzerInitialize",
3444 })
3445 self.assertEqual(results, [])
3446
3447 def testNoErrorHeaderPresent(self):
3448 results = self._check({
3449 "fuzzer.cc": (
3450 "#include \"testing/libfuzzer/libfuzzer_exports.h\"\n" +
3451 "LLVMFuzzerInitialize"
3452 )
3453 })
3454 self.assertEqual(results, [])
3455
3456 def testErrorMissingHeader(self):
3457 results = self._check({
3458 "fuzzer.cc": "LLVMFuzzerInitialize"
3459 })
3460 self.assertEqual(len(results), 1)
3461 self.assertEqual(results[0].items, ['fuzzer.cc'])
3462
3463
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263464class SetNoParentTest(unittest.TestCase):
3465 def testSetNoParentMissing(self):
3466 mock_input_api = MockInputApi()
3467 mock_input_api.files = [
3468 MockAffectedFile('goat/OWNERS',
3469 [
3470 'set noparent',
3471 '[email protected]',
3472 'per-file *.json=set noparent',
3473 'per-file *[email protected]',
3474 ])
3475 ]
3476 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363477 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263478 self.assertEqual(1, len(errors))
3479 self.assertTrue('goat/OWNERS:1' in errors[0].long_text)
3480 self.assertTrue('goat/OWNERS:3' in errors[0].long_text)
3481
3482
3483 def testSetNoParentWithCorrectRule(self):
3484 mock_input_api = MockInputApi()
3485 mock_input_api.files = [
3486 MockAffectedFile('goat/OWNERS',
3487 [
3488 'set noparent',
3489 'file://ipc/SECURITY_OWNERS',
3490 'per-file *.json=set noparent',
3491 'per-file *.json=file://ipc/SECURITY_OWNERS',
3492 ])
3493 ]
3494 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363495 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263496 self.assertEqual([], errors)
3497
3498
Ken Rockotc31f4832020-05-29 18:58:513499class MojomStabilityCheckTest(unittest.TestCase):
3500 def runTestWithAffectedFiles(self, affected_files):
3501 mock_input_api = MockInputApi()
3502 mock_input_api.files = affected_files
3503 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363504 return PRESUBMIT.CheckStableMojomChanges(
Ken Rockotc31f4832020-05-29 18:58:513505 mock_input_api, mock_output_api)
3506
3507 def testSafeChangePasses(self):
3508 errors = self.runTestWithAffectedFiles([
3509 MockAffectedFile('foo/foo.mojom',
3510 ['[Stable] struct S { [MinVersion=1] int32 x; };'],
3511 old_contents=['[Stable] struct S {};'])
3512 ])
3513 self.assertEqual([], errors)
3514
3515 def testBadChangeFails(self):
3516 errors = self.runTestWithAffectedFiles([
3517 MockAffectedFile('foo/foo.mojom',
3518 ['[Stable] struct S { int32 x; };'],
3519 old_contents=['[Stable] struct S {};'])
3520 ])
3521 self.assertEqual(1, len(errors))
3522 self.assertTrue('not backward-compatible' in errors[0].message)
3523
Ken Rockotad7901f942020-06-04 20:17:093524 def testDeletedFile(self):
3525 """Regression test for https://crbug.com/1091407."""
3526 errors = self.runTestWithAffectedFiles([
3527 MockAffectedFile('a.mojom', [], old_contents=['struct S {};'],
3528 action='D'),
3529 MockAffectedFile('b.mojom',
3530 ['struct S {}; struct T { S s; };'],
3531 old_contents=['import "a.mojom"; struct T { S s; };'])
3532 ])
3533 self.assertEqual([], errors)
3534
Ken Rockotc31f4832020-05-29 18:58:513535
[email protected]2299dcf2012-11-15 19:56:243536if __name__ == '__main__':
3537 unittest.main()