blob: 5b88a882ccbb155c41df9fb47860432d51b6d5b8 [file] [log] [blame]
Andrew Grieve3f9b9662022-02-02 19:07:551#!/usr/bin/env python3
Avi Drissman24976592022-09-12 15:24:312# Copyright 2012 The Chromium Authors
[email protected]2299dcf2012-11-15 19:56:243# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
Andrew Grieve4deedb12022-02-03 21:34:506import io
Daniel Cheng4dcdb6b2017-04-13 08:30:177import os.path
[email protected]99171a92014-06-03 08:44:478import subprocess
Min Qinbc44383c2023-02-22 17:25:269import textwrap
[email protected]2299dcf2012-11-15 19:56:2410import unittest
11
12import PRESUBMIT
Saagar Sanghavifceeaae2020-08-12 16:40:3613
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3914from PRESUBMIT_test_mocks import MockFile, MockAffectedFile
gayane3dff8c22014-12-04 17:09:5115from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi
[email protected]2299dcf2012-11-15 19:56:2416
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3917
[email protected]99171a92014-06-03 08:44:4718_TEST_DATA_DIR = 'base/test/data/presubmit'
19
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3920
[email protected]b00342e7f2013-03-26 16:21:5421class VersionControlConflictsTest(unittest.TestCase):
[email protected]70ca77752012-11-20 03:45:0322 def testTypicalConflict(self):
23 lines = ['<<<<<<< HEAD',
24 ' base::ScopedTempDir temp_dir_;',
25 '=======',
26 ' ScopedTempDir temp_dir_;',
27 '>>>>>>> master']
28 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
29 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
30 self.assertEqual(3, len(errors))
31 self.assertTrue('1' in errors[0])
32 self.assertTrue('3' in errors[1])
33 self.assertTrue('5' in errors[2])
34
dbeam95c35a2f2015-06-02 01:40:2335 def testIgnoresReadmes(self):
36 lines = ['A First Level Header',
37 '====================',
38 '',
39 'A Second Level Header',
40 '---------------------']
41 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
42 MockInputApi(), MockFile('some/polymer/README.md', lines))
43 self.assertEqual(0, len(errors))
44
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3945
[email protected]b8079ae4a2012-12-05 19:56:4946class BadExtensionsTest(unittest.TestCase):
47 def testBadRejFile(self):
48 mock_input_api = MockInputApi()
49 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:4050 MockFile('some/path/foo.cc', ''),
51 MockFile('some/path/foo.cc.rej', ''),
52 MockFile('some/path2/bar.h.rej', ''),
[email protected]b8079ae4a2012-12-05 19:56:4953 ]
54
Saagar Sanghavifceeaae2020-08-12 16:40:3655 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:4956 self.assertEqual(1, len(results))
57 self.assertEqual(2, len(results[0].items))
58 self.assertTrue('foo.cc.rej' in results[0].items[0])
59 self.assertTrue('bar.h.rej' in results[0].items[1])
60
61 def testBadOrigFile(self):
62 mock_input_api = MockInputApi()
63 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:4064 MockFile('other/path/qux.h.orig', ''),
65 MockFile('other/path/qux.h', ''),
66 MockFile('other/path/qux.cc', ''),
[email protected]b8079ae4a2012-12-05 19:56:4967 ]
68
Saagar Sanghavifceeaae2020-08-12 16:40:3669 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:4970 self.assertEqual(1, len(results))
71 self.assertEqual(1, len(results[0].items))
72 self.assertTrue('qux.h.orig' in results[0].items[0])
73
74 def testGoodFiles(self):
75 mock_input_api = MockInputApi()
76 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:4077 MockFile('other/path/qux.h', ''),
78 MockFile('other/path/qux.cc', ''),
[email protected]b8079ae4a2012-12-05 19:56:4979 ]
Saagar Sanghavifceeaae2020-08-12 16:40:3680 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:4981 self.assertEqual(0, len(results))
82
83
Lei Zhang1c12a22f2021-05-12 11:28:4584class CheckForSuperfluousStlIncludesInHeadersTest(unittest.TestCase):
85 def testGoodFiles(self):
86 mock_input_api = MockInputApi()
87 mock_input_api.files = [
88 # The check is not smart enough to figure out which definitions correspond
89 # to which header.
90 MockFile('other/path/foo.h',
91 ['#include <string>',
92 'std::vector']),
93 # The check is not smart enough to do IWYU.
94 MockFile('other/path/bar.h',
95 ['#include "base/check.h"',
96 'std::vector']),
97 MockFile('other/path/qux.h',
98 ['#include "base/stl_util.h"',
99 'foobar']),
Lei Zhang0643e342021-05-12 18:02:12100 MockFile('other/path/baz.h',
101 ['#include "set/vector.h"',
102 'bazzab']),
Lei Zhang1c12a22f2021-05-12 11:28:45103 # The check is only for header files.
104 MockFile('other/path/not_checked.cc',
105 ['#include <vector>',
106 'bazbaz']),
107 ]
108 results = PRESUBMIT.CheckForSuperfluousStlIncludesInHeaders(
109 mock_input_api, MockOutputApi())
110 self.assertEqual(0, len(results))
111
112 def testBadFiles(self):
113 mock_input_api = MockInputApi()
114 mock_input_api.files = [
115 MockFile('other/path/foo.h',
116 ['#include <vector>',
117 'vector']),
118 MockFile('other/path/bar.h',
119 ['#include <limits>',
120 '#include <set>',
121 'no_std_namespace']),
122 ]
123 results = PRESUBMIT.CheckForSuperfluousStlIncludesInHeaders(
124 mock_input_api, MockOutputApi())
125 self.assertEqual(1, len(results))
126 self.assertTrue('foo.h: Includes STL' in results[0].message)
127 self.assertTrue('bar.h: Includes STL' in results[0].message)
128
129
glidere61efad2015-02-18 17:39:43130class CheckSingletonInHeadersTest(unittest.TestCase):
131 def testSingletonInArbitraryHeader(self):
132 diff_singleton_h = ['base::subtle::AtomicWord '
olli.raula36aa8be2015-09-10 11:14:22133 'base::Singleton<Type, Traits, DifferentiatingType>::']
134 diff_foo_h = ['// base::Singleton<Foo> in comment.',
135 'friend class base::Singleton<Foo>']
oysteinec430ad42015-10-22 20:55:24136 diff_foo2_h = [' //Foo* bar = base::Singleton<Foo>::get();']
olli.raula36aa8be2015-09-10 11:14:22137 diff_bad_h = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43138 mock_input_api = MockInputApi()
139 mock_input_api.files = [MockAffectedFile('base/memory/singleton.h',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39140 diff_singleton_h),
glidere61efad2015-02-18 17:39:43141 MockAffectedFile('foo.h', diff_foo_h),
oysteinec430ad42015-10-22 20:55:24142 MockAffectedFile('foo2.h', diff_foo2_h),
glidere61efad2015-02-18 17:39:43143 MockAffectedFile('bad.h', diff_bad_h)]
Saagar Sanghavifceeaae2020-08-12 16:40:36144 warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
glidere61efad2015-02-18 17:39:43145 MockOutputApi())
146 self.assertEqual(1, len(warnings))
Sylvain Defresnea8b73d252018-02-28 15:45:54147 self.assertEqual(1, len(warnings[0].items))
glidere61efad2015-02-18 17:39:43148 self.assertEqual('error', warnings[0].type)
olli.raula36aa8be2015-09-10 11:14:22149 self.assertTrue('Found base::Singleton<T>' in warnings[0].message)
glidere61efad2015-02-18 17:39:43150
151 def testSingletonInCC(self):
olli.raula36aa8be2015-09-10 11:14:22152 diff_cc = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43153 mock_input_api = MockInputApi()
154 mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)]
Saagar Sanghavifceeaae2020-08-12 16:40:36155 warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
glidere61efad2015-02-18 17:39:43156 MockOutputApi())
157 self.assertEqual(0, len(warnings))
158
159
Xiaohan Wang42d96c22022-01-20 17:23:11160class DeprecatedOSMacroNamesTest(unittest.TestCase):
161 def testDeprecatedOSMacroNames(self):
162 lines = ['#if defined(OS_WIN)',
[email protected]b00342e7f2013-03-26 16:21:54163 ' #elif defined(OS_WINDOW)',
Xiaohan Wang42d96c22022-01-20 17:23:11164 ' # if defined(OS_MAC) || defined(OS_CHROME)']
165 errors = PRESUBMIT._CheckForDeprecatedOSMacrosInFile(
[email protected]b00342e7f2013-03-26 16:21:54166 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
Xiaohan Wang42d96c22022-01-20 17:23:11167 self.assertEqual(len(lines) + 1, len(errors))
168 self.assertTrue(':1: defined(OS_WIN) -> BUILDFLAG(IS_WIN)' in errors[0])
[email protected]b00342e7f2013-03-26 16:21:54169
170
lliabraa35bab3932014-10-01 12:16:44171class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
172 def testInvalidIfDefinedMacroNames(self):
173 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
174 '#if !defined(TARGET_IPHONE_SIMULATOR)',
175 '#elif defined(TARGET_IPHONE_SIMULATOR)',
176 '#ifdef TARGET_IPHONE_SIMULATOR',
177 ' # ifdef TARGET_IPHONE_SIMULATOR',
178 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
179 '# else // defined(TARGET_IPHONE_SIMULATOR)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39180 '#endif // defined(TARGET_IPHONE_SIMULATOR)']
lliabraa35bab3932014-10-01 12:16:44181 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
182 MockInputApi(), MockFile('some/path/source.mm', lines))
183 self.assertEqual(len(lines), len(errors))
184
185 def testValidIfDefinedMacroNames(self):
186 lines = ['#if defined(FOO)',
Andrew Williamsc9f69b482023-07-10 16:07:36187 '#ifdef BAR',
188 '#if TARGET_IPHONE_SIMULATOR']
lliabraa35bab3932014-10-01 12:16:44189 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
190 MockInputApi(), MockFile('some/path/source.cc', lines))
191 self.assertEqual(0, len(errors))
192
193
Andrew Williamsc9f69b482023-07-10 16:07:36194class CheckNoUNIT_TESTInSourceFilesTest(unittest.TestCase):
195 def testUnitTestMacros(self):
196 lines = ['#if defined(UNIT_TEST)',
197 '#if defined UNIT_TEST',
198 '#if !defined(UNIT_TEST)',
199 '#elif defined(UNIT_TEST)',
200 '#ifdef UNIT_TEST',
201 ' # ifdef UNIT_TEST',
202 '#ifndef UNIT_TEST',
203 '# if defined(VALID) || defined(UNIT_TEST)',
204 '# if defined(UNIT_TEST) && defined(VALID)',
205 '# else // defined(UNIT_TEST)',
206 '#endif // defined(UNIT_TEST)']
207 errors = PRESUBMIT._CheckNoUNIT_TESTInSourceFiles(
208 MockInputApi(), MockFile('some/path/source.cc', lines))
209 self.assertEqual(len(lines), len(errors))
210
211 def testNotUnitTestMacros(self):
212 lines = ['// Comment about "#if defined(UNIT_TEST)"',
213 '/* Comment about #if defined(UNIT_TEST)" */',
214 '#ifndef UNIT_TEST_H',
215 '#define UNIT_TEST_H',
216 '#ifndef TEST_UNIT_TEST',
217 '#define TEST_UNIT_TEST',
218 '#if defined(_UNIT_TEST)',
219 '#if defined(UNIT_TEST_)',
220 '#ifdef _UNIT_TEST',
221 '#ifdef UNIT_TEST_',
222 '#ifndef _UNIT_TEST',
223 '#ifndef UNIT_TEST_']
224 errors = PRESUBMIT._CheckNoUNIT_TESTInSourceFiles(
225 MockInputApi(), MockFile('some/path/source.cc', lines))
226 self.assertEqual(0, len(errors))
227
Samuel Huang0db2ea22019-12-09 16:42:47228class CheckAddedDepsHaveTestApprovalsTest(unittest.TestCase):
Daniel Cheng4dcdb6b2017-04-13 08:30:17229
230 def calculate(self, old_include_rules, old_specific_include_rules,
231 new_include_rules, new_specific_include_rules):
232 return PRESUBMIT._CalculateAddedDeps(
233 os.path, 'include_rules = %r\nspecific_include_rules = %r' % (
234 old_include_rules, old_specific_include_rules),
235 'include_rules = %r\nspecific_include_rules = %r' % (
236 new_include_rules, new_specific_include_rules))
237
238 def testCalculateAddedDeps(self):
239 old_include_rules = [
240 '+base',
241 '-chrome',
242 '+content',
243 '-grit',
244 '-grit/",',
245 '+jni/fooblat.h',
246 '!sandbox',
[email protected]f32e2d1e2013-07-26 21:39:08247 ]
Daniel Cheng4dcdb6b2017-04-13 08:30:17248 old_specific_include_rules = {
249 'compositor\.*': {
250 '+cc',
251 },
252 }
253
254 new_include_rules = [
255 '-ash',
256 '+base',
257 '+chrome',
258 '+components',
259 '+content',
260 '+grit',
261 '+grit/generated_resources.h",',
262 '+grit/",',
263 '+jni/fooblat.h',
264 '+policy',
manzagop85e629e2017-05-09 22:11:48265 '+' + os.path.join('third_party', 'WebKit'),
Daniel Cheng4dcdb6b2017-04-13 08:30:17266 ]
267 new_specific_include_rules = {
268 'compositor\.*': {
269 '+cc',
270 },
271 'widget\.*': {
272 '+gpu',
273 },
274 }
275
[email protected]f32e2d1e2013-07-26 21:39:08276 expected = set([
manzagop85e629e2017-05-09 22:11:48277 os.path.join('chrome', 'DEPS'),
278 os.path.join('gpu', 'DEPS'),
279 os.path.join('components', 'DEPS'),
280 os.path.join('policy', 'DEPS'),
281 os.path.join('third_party', 'WebKit', 'DEPS'),
[email protected]f32e2d1e2013-07-26 21:39:08282 ])
Daniel Cheng4dcdb6b2017-04-13 08:30:17283 self.assertEqual(
284 expected,
285 self.calculate(old_include_rules, old_specific_include_rules,
286 new_include_rules, new_specific_include_rules))
287
288 def testCalculateAddedDepsIgnoresPermutations(self):
289 old_include_rules = [
290 '+base',
291 '+chrome',
292 ]
293 new_include_rules = [
294 '+chrome',
295 '+base',
296 ]
297 self.assertEqual(set(),
298 self.calculate(old_include_rules, {}, new_include_rules,
299 {}))
[email protected]f32e2d1e2013-07-26 21:39:08300
301
[email protected]99171a92014-06-03 08:44:47302class JSONParsingTest(unittest.TestCase):
303 def testSuccess(self):
304 input_api = MockInputApi()
305 filename = 'valid_json.json'
306 contents = ['// This is a comment.',
307 '{',
308 ' "key1": ["value1", "value2"],',
309 ' "key2": 3 // This is an inline comment.',
310 '}'
311 ]
312 input_api.files = [MockFile(filename, contents)]
313 self.assertEqual(None,
314 PRESUBMIT._GetJSONParseError(input_api, filename))
315
316 def testFailure(self):
317 input_api = MockInputApi()
318 test_data = [
319 ('invalid_json_1.json',
320 ['{ x }'],
Dirk Prankee3c9c62d2021-05-18 18:35:59321 'Expecting property name'),
[email protected]99171a92014-06-03 08:44:47322 ('invalid_json_2.json',
323 ['// Hello world!',
324 '{ "hello": "world }'],
[email protected]a3343272014-06-17 11:41:53325 'Unterminated string starting at:'),
[email protected]99171a92014-06-03 08:44:47326 ('invalid_json_3.json',
327 ['{ "a": "b", "c": "d", }'],
Dirk Prankee3c9c62d2021-05-18 18:35:59328 'Expecting property name'),
[email protected]99171a92014-06-03 08:44:47329 ('invalid_json_4.json',
330 ['{ "a": "b" "c": "d" }'],
Dirk Prankee3c9c62d2021-05-18 18:35:59331 "Expecting ',' delimiter:"),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39332 ]
[email protected]99171a92014-06-03 08:44:47333
334 input_api.files = [MockFile(filename, contents)
335 for (filename, contents, _) in test_data]
336
337 for (filename, _, expected_error) in test_data:
338 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
[email protected]a3343272014-06-17 11:41:53339 self.assertTrue(expected_error in str(actual_error),
340 "'%s' not found in '%s'" % (expected_error, actual_error))
[email protected]99171a92014-06-03 08:44:47341
342 def testNoEatComments(self):
343 input_api = MockInputApi()
344 file_with_comments = 'file_with_comments.json'
345 contents_with_comments = ['// This is a comment.',
346 '{',
347 ' "key1": ["value1", "value2"],',
348 ' "key2": 3 // This is an inline comment.',
349 '}'
350 ]
351 file_without_comments = 'file_without_comments.json'
352 contents_without_comments = ['{',
353 ' "key1": ["value1", "value2"],',
354 ' "key2": 3',
355 '}'
356 ]
357 input_api.files = [MockFile(file_with_comments, contents_with_comments),
358 MockFile(file_without_comments,
359 contents_without_comments)]
360
Dirk Prankee3c9c62d2021-05-18 18:35:59361 self.assertNotEqual(None,
362 str(PRESUBMIT._GetJSONParseError(input_api,
363 file_with_comments,
364 eat_comments=False)))
[email protected]99171a92014-06-03 08:44:47365 self.assertEqual(None,
366 PRESUBMIT._GetJSONParseError(input_api,
367 file_without_comments,
368 eat_comments=False))
369
370
371class IDLParsingTest(unittest.TestCase):
372 def testSuccess(self):
373 input_api = MockInputApi()
374 filename = 'valid_idl_basics.idl'
375 contents = ['// Tests a valid IDL file.',
376 'namespace idl_basics {',
377 ' enum EnumType {',
378 ' name1,',
379 ' name2',
380 ' };',
381 '',
382 ' dictionary MyType1 {',
383 ' DOMString a;',
384 ' };',
385 '',
386 ' callback Callback1 = void();',
387 ' callback Callback2 = void(long x);',
388 ' callback Callback3 = void(MyType1 arg);',
389 ' callback Callback4 = void(EnumType type);',
390 '',
391 ' interface Functions {',
392 ' static void function1();',
393 ' static void function2(long x);',
394 ' static void function3(MyType1 arg);',
395 ' static void function4(Callback1 cb);',
396 ' static void function5(Callback2 cb);',
397 ' static void function6(Callback3 cb);',
398 ' static void function7(Callback4 cb);',
399 ' };',
400 '',
401 ' interface Events {',
402 ' static void onFoo1();',
403 ' static void onFoo2(long x);',
404 ' static void onFoo2(MyType1 arg);',
405 ' static void onFoo3(EnumType type);',
406 ' };',
407 '};'
408 ]
409 input_api.files = [MockFile(filename, contents)]
410 self.assertEqual(None,
411 PRESUBMIT._GetIDLParseError(input_api, filename))
412
413 def testFailure(self):
414 input_api = MockInputApi()
415 test_data = [
416 ('invalid_idl_1.idl',
417 ['//',
418 'namespace test {',
419 ' dictionary {',
420 ' DOMString s;',
421 ' };',
422 '};'],
423 'Unexpected "{" after keyword "dictionary".\n'),
424 # TODO(yoz): Disabled because it causes the IDL parser to hang.
425 # See crbug.com/363830.
426 # ('invalid_idl_2.idl',
427 # (['namespace test {',
428 # ' dictionary MissingSemicolon {',
429 # ' DOMString a',
430 # ' DOMString b;',
431 # ' };',
432 # '};'],
433 # 'Unexpected symbol DOMString after symbol a.'),
434 ('invalid_idl_3.idl',
435 ['//',
436 'namespace test {',
437 ' enum MissingComma {',
438 ' name1',
439 ' name2',
440 ' };',
441 '};'],
442 'Unexpected symbol name2 after symbol name1.'),
443 ('invalid_idl_4.idl',
444 ['//',
445 'namespace test {',
446 ' enum TrailingComma {',
447 ' name1,',
448 ' name2,',
449 ' };',
450 '};'],
451 'Trailing comma in block.'),
452 ('invalid_idl_5.idl',
453 ['//',
454 'namespace test {',
455 ' callback Callback1 = void(;',
456 '};'],
457 'Unexpected ";" after "(".'),
458 ('invalid_idl_6.idl',
459 ['//',
460 'namespace test {',
461 ' callback Callback1 = void(long );',
462 '};'],
463 'Unexpected ")" after symbol long.'),
464 ('invalid_idl_7.idl',
465 ['//',
466 'namespace test {',
467 ' interace Events {',
468 ' static void onFoo1();',
469 ' };',
470 '};'],
471 'Unexpected symbol Events after symbol interace.'),
472 ('invalid_idl_8.idl',
473 ['//',
474 'namespace test {',
475 ' interface NotEvent {',
476 ' static void onFoo1();',
477 ' };',
478 '};'],
479 'Did not process Interface Interface(NotEvent)'),
480 ('invalid_idl_9.idl',
481 ['//',
482 'namespace test {',
483 ' interface {',
484 ' static void function1();',
485 ' };',
486 '};'],
487 'Interface missing name.'),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39488 ]
[email protected]99171a92014-06-03 08:44:47489
490 input_api.files = [MockFile(filename, contents)
491 for (filename, contents, _) in test_data]
492
493 for (filename, _, expected_error) in test_data:
494 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
495 self.assertTrue(expected_error in str(actual_error),
496 "'%s' not found in '%s'" % (expected_error, actual_error))
497
498
davileene0426252015-03-02 21:10:41499class UserMetricsActionTest(unittest.TestCase):
500 def testUserMetricsActionInActions(self):
501 input_api = MockInputApi()
502 file_with_user_action = 'file_with_user_action.cc'
503 contents_with_user_action = [
504 'base::UserMetricsAction("AboutChrome")'
505 ]
506
507 input_api.files = [MockFile(file_with_user_action,
508 contents_with_user_action)]
509
510 self.assertEqual(
Saagar Sanghavifceeaae2020-08-12 16:40:36511 [], PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi()))
davileene0426252015-03-02 21:10:41512
davileene0426252015-03-02 21:10:41513 def testUserMetricsActionNotAddedToActions(self):
514 input_api = MockInputApi()
515 file_with_user_action = 'file_with_user_action.cc'
516 contents_with_user_action = [
517 'base::UserMetricsAction("NotInActionsXml")'
518 ]
519
520 input_api.files = [MockFile(file_with_user_action,
521 contents_with_user_action)]
522
Saagar Sanghavifceeaae2020-08-12 16:40:36523 output = PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi())
davileene0426252015-03-02 21:10:41524 self.assertEqual(
525 ('File %s line %d: %s is missing in '
526 'tools/metrics/actions/actions.xml. Please run '
527 'tools/metrics/actions/extract_actions.py to update.'
528 % (file_with_user_action, 1, 'NotInActionsXml')),
529 output[0].message)
530
Alexei Svitkine64505a92021-03-11 22:00:54531 def testUserMetricsActionInTestFile(self):
532 input_api = MockInputApi()
533 file_with_user_action = 'file_with_user_action_unittest.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
541 self.assertEqual(
542 [], PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi()))
543
davileene0426252015-03-02 21:10:41544
agrievef32bcc72016-04-04 14:57:40545class PydepsNeedsUpdatingTest(unittest.TestCase):
Andrew Grieve4deedb12022-02-03 21:34:50546 class MockPopen:
Andrew Grieved27620b62023-07-13 16:35:07547 def __init__(self, stdout):
548 self.stdout = io.StringIO(stdout)
agrievef32bcc72016-04-04 14:57:40549
Andrew Grieve4deedb12022-02-03 21:34:50550 def wait(self):
Andrew Grieve4deedb12022-02-03 21:34:50551 return 0
552
553 class MockSubprocess:
agrievef32bcc72016-04-04 14:57:40554 CalledProcessError = subprocess.CalledProcessError
Andrew Grieve4deedb12022-02-03 21:34:50555 PIPE = 0
556
557 def __init__(self):
558 self._popen_func = None
559
560 def SetPopenCallback(self, func):
561 self._popen_func = func
562
563 def Popen(self, cmd, *args, **kwargs):
Andrew Grieved27620b62023-07-13 16:35:07564 return PydepsNeedsUpdatingTest.MockPopen(self._popen_func(cmd))
agrievef32bcc72016-04-04 14:57:40565
Mohamed Heikal7cd4d8312020-06-16 16:49:40566 def _MockParseGclientArgs(self, is_android=True):
567 return lambda: {'checkout_android': 'true' if is_android else 'false' }
568
agrievef32bcc72016-04-04 14:57:40569 def setUp(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40570 mock_all_pydeps = ['A.pydeps', 'B.pydeps', 'D.pydeps']
agrievef32bcc72016-04-04 14:57:40571 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
572 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
Mohamed Heikal7cd4d8312020-06-16 16:49:40573 mock_android_pydeps = ['D.pydeps']
574 self.old_ANDROID_SPECIFIC_PYDEPS_FILES = (
575 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES)
576 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = mock_android_pydeps
577 self.old_ParseGclientArgs = PRESUBMIT._ParseGclientArgs
578 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs()
agrievef32bcc72016-04-04 14:57:40579 self.mock_input_api = MockInputApi()
580 self.mock_output_api = MockOutputApi()
581 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
582 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
583 self.checker._file_cache = {
Andrew Grieve5bb4cf702020-10-22 20:21:39584 'A.pydeps': '# Generated by:\n# CMD --output A.pydeps A\nA.py\nC.py\n',
585 'B.pydeps': '# Generated by:\n# CMD --output B.pydeps B\nB.py\nC.py\n',
586 'D.pydeps': '# Generated by:\n# CMD --output D.pydeps D\nD.py\n',
agrievef32bcc72016-04-04 14:57:40587 }
588
589 def tearDown(self):
590 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
Mohamed Heikal7cd4d8312020-06-16 16:49:40591 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = (
592 self.old_ANDROID_SPECIFIC_PYDEPS_FILES)
593 PRESUBMIT._ParseGclientArgs = self.old_ParseGclientArgs
agrievef32bcc72016-04-04 14:57:40594
595 def _RunCheck(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36596 return PRESUBMIT.CheckPydepsNeedsUpdating(self.mock_input_api,
agrievef32bcc72016-04-04 14:57:40597 self.mock_output_api,
598 checker_for_tests=self.checker)
599
600 def testAddedPydep(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36601 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30602 if not self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13603 return []
604
agrievef32bcc72016-04-04 14:57:40605 self.mock_input_api.files = [
606 MockAffectedFile('new.pydeps', [], action='A'),
607 ]
608
Zhiling Huang45cabf32018-03-10 00:50:03609 self.mock_input_api.CreateMockFileInPath(
610 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
611 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40612 results = self._RunCheck()
613 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39614 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40615
Zhiling Huang45cabf32018-03-10 00:50:03616 def testPydepNotInSrc(self):
617 self.mock_input_api.files = [
618 MockAffectedFile('new.pydeps', [], action='A'),
619 ]
620 self.mock_input_api.CreateMockFileInPath([])
621 results = self._RunCheck()
622 self.assertEqual(0, len(results))
623
agrievef32bcc72016-04-04 14:57:40624 def testRemovedPydep(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36625 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30626 if not self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13627 return []
628
agrievef32bcc72016-04-04 14:57:40629 self.mock_input_api.files = [
630 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
631 ]
Zhiling Huang45cabf32018-03-10 00:50:03632 self.mock_input_api.CreateMockFileInPath(
633 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
634 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40635 results = self._RunCheck()
636 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39637 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40638
639 def testRandomPyIgnored(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36640 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30641 if not self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13642 return []
643
agrievef32bcc72016-04-04 14:57:40644 self.mock_input_api.files = [
645 MockAffectedFile('random.py', []),
646 ]
647
648 results = self._RunCheck()
649 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
650
651 def testRelevantPyNoChange(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36652 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30653 if not self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13654 return []
655
agrievef32bcc72016-04-04 14:57:40656 self.mock_input_api.files = [
657 MockAffectedFile('A.py', []),
658 ]
659
Andrew Grieve4deedb12022-02-03 21:34:50660 def popen_callback(cmd):
Andrew Grieve5bb4cf702020-10-22 20:21:39661 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
agrievef32bcc72016-04-04 14:57:40662 return self.checker._file_cache['A.pydeps']
663
Andrew Grieve4deedb12022-02-03 21:34:50664 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
agrievef32bcc72016-04-04 14:57:40665
666 results = self._RunCheck()
667 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
668
669 def testRelevantPyOneChange(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36670 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30671 if not self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13672 return []
673
agrievef32bcc72016-04-04 14:57:40674 self.mock_input_api.files = [
675 MockAffectedFile('A.py', []),
676 ]
677
Andrew Grieve4deedb12022-02-03 21:34:50678 def popen_callback(cmd):
Andrew Grieve5bb4cf702020-10-22 20:21:39679 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
agrievef32bcc72016-04-04 14:57:40680 return 'changed data'
681
Andrew Grieve4deedb12022-02-03 21:34:50682 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
agrievef32bcc72016-04-04 14:57:40683
684 results = self._RunCheck()
685 self.assertEqual(1, len(results))
Andrew Grieve4deedb12022-02-03 21:34:50686 # Check that --output "" is not included.
687 self.assertNotIn('""', str(results[0]))
Andrew Grieve5bb4cf702020-10-22 20:21:39688 self.assertIn('File is stale', str(results[0]))
agrievef32bcc72016-04-04 14:57:40689
690 def testRelevantPyTwoChanges(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36691 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30692 if not self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13693 return []
694
agrievef32bcc72016-04-04 14:57:40695 self.mock_input_api.files = [
696 MockAffectedFile('C.py', []),
697 ]
698
Andrew Grieve4deedb12022-02-03 21:34:50699 def popen_callback(cmd):
agrievef32bcc72016-04-04 14:57:40700 return 'changed data'
701
Andrew Grieve4deedb12022-02-03 21:34:50702 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
agrievef32bcc72016-04-04 14:57:40703
704 results = self._RunCheck()
705 self.assertEqual(2, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39706 self.assertIn('File is stale', str(results[0]))
707 self.assertIn('File is stale', str(results[1]))
agrievef32bcc72016-04-04 14:57:40708
Mohamed Heikal7cd4d8312020-06-16 16:49:40709 def testRelevantAndroidPyInNonAndroidCheckout(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36710 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30711 if not self.mock_input_api.platform.startswith('linux'):
Mohamed Heikal7cd4d8312020-06-16 16:49:40712 return []
713
714 self.mock_input_api.files = [
715 MockAffectedFile('D.py', []),
716 ]
717
Andrew Grieve4deedb12022-02-03 21:34:50718 def popen_callback(cmd):
Andrew Grieve5bb4cf702020-10-22 20:21:39719 self.assertEqual('CMD --output D.pydeps D --output ""', cmd)
Mohamed Heikal7cd4d8312020-06-16 16:49:40720 return 'changed data'
721
Andrew Grieve4deedb12022-02-03 21:34:50722 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
Mohamed Heikal7cd4d8312020-06-16 16:49:40723 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs(is_android=False)
724
725 results = self._RunCheck()
726 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39727 self.assertIn('Android', str(results[0]))
728 self.assertIn('D.pydeps', str(results[0]))
729
730 def testGnPathsAndMissingOutputFlag(self):
731 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30732 if not self.mock_input_api.platform.startswith('linux'):
Andrew Grieve5bb4cf702020-10-22 20:21:39733 return []
734
735 self.checker._file_cache = {
736 'A.pydeps': '# Generated by:\n# CMD --gn-paths A\n//A.py\n//C.py\n',
737 'B.pydeps': '# Generated by:\n# CMD --gn-paths B\n//B.py\n//C.py\n',
738 'D.pydeps': '# Generated by:\n# CMD --gn-paths D\n//D.py\n',
739 }
740
741 self.mock_input_api.files = [
742 MockAffectedFile('A.py', []),
743 ]
744
Andrew Grieve4deedb12022-02-03 21:34:50745 def popen_callback(cmd):
Andrew Grieve5bb4cf702020-10-22 20:21:39746 self.assertEqual('CMD --gn-paths A --output A.pydeps --output ""', cmd)
747 return 'changed data'
748
Andrew Grieve4deedb12022-02-03 21:34:50749 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
Andrew Grieve5bb4cf702020-10-22 20:21:39750
751 results = self._RunCheck()
752 self.assertEqual(1, len(results))
753 self.assertIn('File is stale', str(results[0]))
Mohamed Heikal7cd4d8312020-06-16 16:49:40754
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39755
Daniel Bratell8ba52722018-03-02 16:06:14756class IncludeGuardTest(unittest.TestCase):
757 def testIncludeGuardChecks(self):
758 mock_input_api = MockInputApi()
759 mock_output_api = MockOutputApi()
760 mock_input_api.files = [
761 MockAffectedFile('content/browser/thing/foo.h', [
762 '// Comment',
763 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
764 '#define CONTENT_BROWSER_THING_FOO_H_',
765 'struct McBoatFace;',
766 '#endif // CONTENT_BROWSER_THING_FOO_H_',
767 ]),
768 MockAffectedFile('content/browser/thing/bar.h', [
769 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
770 '#define CONTENT_BROWSER_THING_BAR_H_',
771 'namespace content {',
772 '#endif // CONTENT_BROWSER_THING_BAR_H_',
773 '} // namespace content',
774 ]),
775 MockAffectedFile('content/browser/test1.h', [
776 'namespace content {',
777 '} // namespace content',
778 ]),
779 MockAffectedFile('content\\browser\\win.h', [
780 '#ifndef CONTENT_BROWSER_WIN_H_',
781 '#define CONTENT_BROWSER_WIN_H_',
782 'struct McBoatFace;',
783 '#endif // CONTENT_BROWSER_WIN_H_',
784 ]),
785 MockAffectedFile('content/browser/test2.h', [
786 '// Comment',
787 '#ifndef CONTENT_BROWSER_TEST2_H_',
788 'struct McBoatFace;',
789 '#endif // CONTENT_BROWSER_TEST2_H_',
790 ]),
791 MockAffectedFile('content/browser/internal.h', [
792 '// Comment',
793 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
794 '#define CONTENT_BROWSER_INTERNAL_H_',
795 '// Comment',
796 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
797 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
798 'namespace internal {',
799 '} // namespace internal',
800 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
801 'namespace content {',
802 '} // namespace content',
803 '#endif // CONTENT_BROWSER_THING_BAR_H_',
804 ]),
805 MockAffectedFile('content/browser/thing/foo.cc', [
806 '// This is a non-header.',
807 ]),
808 MockAffectedFile('content/browser/disabled.h', [
809 '// no-include-guard-because-multiply-included',
810 'struct McBoatFace;',
811 ]),
812 # New files don't allow misspelled include guards.
813 MockAffectedFile('content/browser/spleling.h', [
814 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
815 '#define CONTENT_BROWSER_SPLLEING_H_',
816 'struct McBoatFace;',
817 '#endif // CONTENT_BROWSER_SPLLEING_H_',
818 ]),
Olivier Robinbba137492018-07-30 11:31:34819 # New files don't allow + in include guards.
820 MockAffectedFile('content/browser/foo+bar.h', [
821 '#ifndef CONTENT_BROWSER_FOO+BAR_H_',
822 '#define CONTENT_BROWSER_FOO+BAR_H_',
823 'struct McBoatFace;',
824 '#endif // CONTENT_BROWSER_FOO+BAR_H_',
825 ]),
Daniel Bratell8ba52722018-03-02 16:06:14826 # Old files allow misspelled include guards (for now).
827 MockAffectedFile('chrome/old.h', [
828 '// New contents',
829 '#ifndef CHROME_ODL_H_',
830 '#define CHROME_ODL_H_',
831 '#endif // CHROME_ODL_H_',
832 ], [
833 '// Old contents',
834 '#ifndef CHROME_ODL_H_',
835 '#define CHROME_ODL_H_',
836 '#endif // CHROME_ODL_H_',
Bruce Dawson95eb7562022-09-14 15:27:16837 ], action='M'),
Daniel Bratell8ba52722018-03-02 16:06:14838 # Using a Blink style include guard outside Blink is wrong.
839 MockAffectedFile('content/NotInBlink.h', [
840 '#ifndef NotInBlink_h',
841 '#define NotInBlink_h',
842 'struct McBoatFace;',
843 '#endif // NotInBlink_h',
844 ]),
Daniel Bratell39b5b062018-05-16 18:09:57845 # Using a Blink style include guard in Blink is no longer ok.
846 MockAffectedFile('third_party/blink/InBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14847 '#ifndef InBlink_h',
848 '#define InBlink_h',
849 'struct McBoatFace;',
850 '#endif // InBlink_h',
851 ]),
852 # Using a bad include guard in Blink is not ok.
Daniel Bratell39b5b062018-05-16 18:09:57853 MockAffectedFile('third_party/blink/AlsoInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14854 '#ifndef WrongInBlink_h',
855 '#define WrongInBlink_h',
856 'struct McBoatFace;',
857 '#endif // WrongInBlink_h',
858 ]),
Bruce Dawson95eb7562022-09-14 15:27:16859 # Using a bad include guard in Blink is not supposed to be accepted even
860 # if it's an old file. However the current presubmit has accepted this
861 # for a while.
Daniel Bratell39b5b062018-05-16 18:09:57862 MockAffectedFile('third_party/blink/StillInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14863 '// New contents',
864 '#ifndef AcceptedInBlink_h',
865 '#define AcceptedInBlink_h',
866 'struct McBoatFace;',
867 '#endif // AcceptedInBlink_h',
868 ], [
869 '// Old contents',
870 '#ifndef AcceptedInBlink_h',
871 '#define AcceptedInBlink_h',
872 'struct McBoatFace;',
873 '#endif // AcceptedInBlink_h',
Bruce Dawson95eb7562022-09-14 15:27:16874 ], action='M'),
Daniel Bratell39b5b062018-05-16 18:09:57875 # Using a non-Chromium include guard in third_party
876 # (outside blink) is accepted.
877 MockAffectedFile('third_party/foo/some_file.h', [
878 '#ifndef REQUIRED_RPCNDR_H_',
879 '#define REQUIRED_RPCNDR_H_',
880 'struct SomeFileFoo;',
881 '#endif // REQUIRED_RPCNDR_H_',
882 ]),
Kinuko Yasuda0cdb3da2019-07-31 21:50:32883 # Not having proper include guard in *_message_generator.h
884 # for old IPC messages is allowed.
885 MockAffectedFile('content/common/content_message_generator.h', [
886 '#undef CONTENT_COMMON_FOO_MESSAGES_H_',
887 '#include "content/common/foo_messages.h"',
888 '#ifndef CONTENT_COMMON_FOO_MESSAGES_H_',
889 '#error "Failed to include content/common/foo_messages.h"',
890 '#endif',
891 ]),
Daniel Bratell8ba52722018-03-02 16:06:14892 ]
Saagar Sanghavifceeaae2020-08-12 16:40:36893 msgs = PRESUBMIT.CheckForIncludeGuards(
Daniel Bratell8ba52722018-03-02 16:06:14894 mock_input_api, mock_output_api)
Olivier Robinbba137492018-07-30 11:31:34895 expected_fail_count = 8
Daniel Bratell8ba52722018-03-02 16:06:14896 self.assertEqual(expected_fail_count, len(msgs),
897 'Expected %d items, found %d: %s'
898 % (expected_fail_count, len(msgs), msgs))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39899 self.assertEqual(msgs[0].items, ['content/browser/thing/bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:14900 self.assertEqual(msgs[0].message,
901 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
902 'not covering the whole file')
903
Bruce Dawson32114b62022-04-11 16:45:49904 self.assertIn('content/browser/test1.h', msgs[1].message)
905 self.assertIn('Recommended name: CONTENT_BROWSER_TEST1_H_',
906 msgs[1].message)
Daniel Bratell8ba52722018-03-02 16:06:14907
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39908 self.assertEqual(msgs[2].items, ['content/browser/test2.h:3'])
Daniel Bratell8ba52722018-03-02 16:06:14909 self.assertEqual(msgs[2].message,
910 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
911 'include guard')
912
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39913 self.assertEqual(msgs[3].items, ['content/browser/spleling.h:1'])
Daniel Bratell8ba52722018-03-02 16:06:14914 self.assertEqual(msgs[3].message,
915 'Header using the wrong include guard name '
916 'CONTENT_BROWSER_SPLLEING_H_')
917
Bruce Dawson32114b62022-04-11 16:45:49918 self.assertIn('content/browser/foo+bar.h', msgs[4].message)
919 self.assertIn('Recommended name: CONTENT_BROWSER_FOO_BAR_H_',
920 msgs[4].message)
Olivier Robinbba137492018-07-30 11:31:34921
922 self.assertEqual(msgs[5].items, ['content/NotInBlink.h:1'])
923 self.assertEqual(msgs[5].message,
Daniel Bratell8ba52722018-03-02 16:06:14924 'Header using the wrong include guard name '
925 'NotInBlink_h')
926
Olivier Robinbba137492018-07-30 11:31:34927 self.assertEqual(msgs[6].items, ['third_party/blink/InBlink.h:1'])
928 self.assertEqual(msgs[6].message,
Daniel Bratell8ba52722018-03-02 16:06:14929 'Header using the wrong include guard name '
Daniel Bratell39b5b062018-05-16 18:09:57930 'InBlink_h')
931
Olivier Robinbba137492018-07-30 11:31:34932 self.assertEqual(msgs[7].items, ['third_party/blink/AlsoInBlink.h:1'])
933 self.assertEqual(msgs[7].message,
Daniel Bratell39b5b062018-05-16 18:09:57934 'Header using the wrong include guard name '
Daniel Bratell8ba52722018-03-02 16:06:14935 'WrongInBlink_h')
936
Chris Hall59f8d0c72020-05-01 07:31:19937class AccessibilityRelnotesFieldTest(unittest.TestCase):
938 def testRelnotesPresent(self):
939 mock_input_api = MockInputApi()
940 mock_output_api = MockOutputApi()
941
942 mock_input_api.files = [MockAffectedFile('ui/accessibility/foo.bar', [''])]
Akihiro Ota08108e542020-05-20 15:30:53943 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19944 mock_input_api.change.footers['AX-Relnotes'] = [
945 'Important user facing change']
946
Saagar Sanghavifceeaae2020-08-12 16:40:36947 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19948 mock_input_api, mock_output_api)
949 self.assertEqual(0, len(msgs),
950 'Expected %d messages, found %d: %s'
951 % (0, len(msgs), msgs))
952
953 def testRelnotesMissingFromAccessibilityChange(self):
954 mock_input_api = MockInputApi()
955 mock_output_api = MockOutputApi()
956
957 mock_input_api.files = [
958 MockAffectedFile('some/file', ['']),
959 MockAffectedFile('ui/accessibility/foo.bar', ['']),
960 MockAffectedFile('some/other/file', [''])
961 ]
Akihiro Ota08108e542020-05-20 15:30:53962 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19963
Saagar Sanghavifceeaae2020-08-12 16:40:36964 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19965 mock_input_api, mock_output_api)
966 self.assertEqual(1, len(msgs),
967 'Expected %d messages, found %d: %s'
968 % (1, len(msgs), msgs))
969 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
970 'Missing AX-Relnotes field message not found in errors')
971
972 # The relnotes footer is not required for changes which do not touch any
973 # accessibility directories.
Gao Shenga79ebd42022-08-08 17:25:59974 def testIgnoresNonAccessibilityCode(self):
Chris Hall59f8d0c72020-05-01 07:31:19975 mock_input_api = MockInputApi()
976 mock_output_api = MockOutputApi()
977
978 mock_input_api.files = [
979 MockAffectedFile('some/file', ['']),
980 MockAffectedFile('some/other/file', [''])
981 ]
Akihiro Ota08108e542020-05-20 15:30:53982 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19983
Saagar Sanghavifceeaae2020-08-12 16:40:36984 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19985 mock_input_api, mock_output_api)
986 self.assertEqual(0, len(msgs),
987 'Expected %d messages, found %d: %s'
988 % (0, len(msgs), msgs))
989
990 # Test that our presubmit correctly raises an error for a set of known paths.
991 def testExpectedPaths(self):
992 filesToTest = [
993 "chrome/browser/accessibility/foo.py",
Henrique Ferreirobb1bb4a2021-03-18 00:04:08994 "chrome/browser/ash/arc/accessibility/foo.cc",
Chris Hall59f8d0c72020-05-01 07:31:19995 "chrome/browser/ui/views/accessibility/foo.h",
996 "chrome/browser/extensions/api/automation/foo.h",
997 "chrome/browser/extensions/api/automation_internal/foo.cc",
998 "chrome/renderer/extensions/accessibility_foo.h",
999 "chrome/tests/data/accessibility/foo.html",
1000 "content/browser/accessibility/foo.cc",
1001 "content/renderer/accessibility/foo.h",
1002 "content/tests/data/accessibility/foo.cc",
1003 "extensions/renderer/api/automation/foo.h",
1004 "ui/accessibility/foo/bar/baz.cc",
1005 "ui/views/accessibility/foo/bar/baz.h",
1006 ]
1007
1008 for testFile in filesToTest:
1009 mock_input_api = MockInputApi()
1010 mock_output_api = MockOutputApi()
1011
1012 mock_input_api.files = [
1013 MockAffectedFile(testFile, [''])
1014 ]
Akihiro Ota08108e542020-05-20 15:30:531015 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191016
Saagar Sanghavifceeaae2020-08-12 16:40:361017 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:191018 mock_input_api, mock_output_api)
1019 self.assertEqual(1, len(msgs),
1020 'Expected %d messages, found %d: %s, for file %s'
1021 % (1, len(msgs), msgs, testFile))
1022 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1023 ('Missing AX-Relnotes field message not found in errors '
1024 ' for file %s' % (testFile)))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391025
Akihiro Ota08108e542020-05-20 15:30:531026 # Test that AX-Relnotes field can appear in the commit description (as long
1027 # as it appears at the beginning of a line).
1028 def testRelnotesInCommitDescription(self):
1029 mock_input_api = MockInputApi()
1030 mock_output_api = MockOutputApi()
1031
1032 mock_input_api.files = [
1033 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1034 ]
1035 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1036 'AX-Relnotes: solves all accessibility issues forever')
1037
Saagar Sanghavifceeaae2020-08-12 16:40:361038 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531039 mock_input_api, mock_output_api)
1040 self.assertEqual(0, len(msgs),
1041 'Expected %d messages, found %d: %s'
1042 % (0, len(msgs), msgs))
1043
1044 # Test that we don't match AX-Relnotes if it appears in the middle of a line.
1045 def testRelnotesMustAppearAtBeginningOfLine(self):
1046 mock_input_api = MockInputApi()
1047 mock_output_api = MockOutputApi()
1048
1049 mock_input_api.files = [
1050 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1051 ]
1052 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1053 'This change has no AX-Relnotes: we should print a warning')
1054
Saagar Sanghavifceeaae2020-08-12 16:40:361055 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531056 mock_input_api, mock_output_api)
1057 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1058 'Missing AX-Relnotes field message not found in errors')
1059
1060 # Tests that the AX-Relnotes field can be lowercase and use a '=' in place
1061 # of a ':'.
1062 def testRelnotesLowercaseWithEqualSign(self):
1063 mock_input_api = MockInputApi()
1064 mock_output_api = MockOutputApi()
1065
1066 mock_input_api.files = [
1067 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1068 ]
1069 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
Gao Shenga79ebd42022-08-08 17:25:591070 'ax-relnotes= this is a valid format for accessibility relnotes')
Akihiro Ota08108e542020-05-20 15:30:531071
Saagar Sanghavifceeaae2020-08-12 16:40:361072 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531073 mock_input_api, mock_output_api)
1074 self.assertEqual(0, len(msgs),
1075 'Expected %d messages, found %d: %s'
1076 % (0, len(msgs), msgs))
1077
Mark Schillacie5a0be22022-01-19 00:38:391078class AccessibilityEventsTestsAreIncludedForAndroidTest(unittest.TestCase):
1079 # Test that no warning is raised when the Android file is also modified.
1080 def testAndroidChangeIncluded(self):
1081 mock_input_api = MockInputApi()
1082
1083 mock_input_api.files = [
Aaron Leventhal267119f2023-08-18 22:45:341084 MockAffectedFile(
1085 'content/test/data/accessibility/event/foo-expected-mac.txt',
Mark Schillacie5a0be22022-01-19 00:38:391086 [''], action='A'),
1087 MockAffectedFile(
1088 'accessibility/WebContentsAccessibilityEventsTest.java',
1089 [''], action='M')
1090 ]
1091
1092 msgs = PRESUBMIT.CheckAccessibilityEventsTestsAreIncludedForAndroid(
1093 mock_input_api, MockOutputApi())
1094 self.assertEqual(0, len(msgs),
1095 'Expected %d messages, found %d: %s'
1096 % (0, len(msgs), msgs))
1097
Mark Schillacie5a0be22022-01-19 00:38:391098 # Test that Android change is not required when no html file is added/removed.
1099 def testIgnoreNonHtmlFiles(self):
1100 mock_input_api = MockInputApi()
1101
1102 mock_input_api.files = [
1103 MockAffectedFile('content/test/data/accessibility/event/foo.txt',
1104 [''], action='A'),
1105 MockAffectedFile('content/test/data/accessibility/event/foo.cc',
1106 [''], action='A'),
1107 MockAffectedFile('content/test/data/accessibility/event/foo.h',
1108 [''], action='A'),
1109 MockAffectedFile('content/test/data/accessibility/event/foo.py',
1110 [''], action='A')
1111 ]
1112
1113 msgs = PRESUBMIT.CheckAccessibilityEventsTestsAreIncludedForAndroid(
1114 mock_input_api, MockOutputApi())
1115 self.assertEqual(0, len(msgs),
1116 'Expected %d messages, found %d: %s'
1117 % (0, len(msgs), msgs))
1118
1119 # Test that Android change is not required for unrelated html files.
1120 def testIgnoreNonRelatedHtmlFiles(self):
1121 mock_input_api = MockInputApi()
1122
1123 mock_input_api.files = [
1124 MockAffectedFile('content/test/data/accessibility/aria/foo.html',
1125 [''], action='A'),
1126 MockAffectedFile('content/test/data/accessibility/html/foo.html',
1127 [''], action='A'),
1128 MockAffectedFile('chrome/tests/data/accessibility/foo.html',
1129 [''], action='A')
1130 ]
1131
1132 msgs = PRESUBMIT.CheckAccessibilityEventsTestsAreIncludedForAndroid(
1133 mock_input_api, MockOutputApi())
1134 self.assertEqual(0, len(msgs),
1135 'Expected %d messages, found %d: %s'
1136 % (0, len(msgs), msgs))
1137
1138 # Test that only modifying an html file will not trigger the warning.
1139 def testIgnoreModifiedFiles(self):
1140 mock_input_api = MockInputApi()
1141
1142 mock_input_api.files = [
Aaron Leventhal267119f2023-08-18 22:45:341143 MockAffectedFile(
1144 'content/test/data/accessibility/event/foo-expected-win.txt',
Mark Schillacie5a0be22022-01-19 00:38:391145 [''], action='M')
1146 ]
1147
1148 msgs = PRESUBMIT.CheckAccessibilityEventsTestsAreIncludedForAndroid(
1149 mock_input_api, MockOutputApi())
1150 self.assertEqual(0, len(msgs),
1151 'Expected %d messages, found %d: %s'
1152 % (0, len(msgs), msgs))
1153
Mark Schillacie5a0be22022-01-19 00:38:391154class AccessibilityTreeTestsAreIncludedForAndroidTest(unittest.TestCase):
1155 # Test that no warning is raised when the Android file is also modified.
1156 def testAndroidChangeIncluded(self):
1157 mock_input_api = MockInputApi()
1158
1159 mock_input_api.files = [
1160 MockAffectedFile('content/test/data/accessibility/aria/foo.html',
1161 [''], action='A'),
1162 MockAffectedFile(
Mark Schillaci6f568a52022-02-17 18:41:441163 'accessibility/WebContentsAccessibilityTreeTest.java',
Mark Schillacie5a0be22022-01-19 00:38:391164 [''], action='M')
1165 ]
1166
1167 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1168 mock_input_api, MockOutputApi())
1169 self.assertEqual(0, len(msgs),
1170 'Expected %d messages, found %d: %s'
1171 % (0, len(msgs), msgs))
1172
1173 # Test that no warning is raised when the Android file is also modified.
1174 def testAndroidChangeIncludedManyFiles(self):
1175 mock_input_api = MockInputApi()
1176
1177 mock_input_api.files = [
1178 MockAffectedFile('content/test/data/accessibility/accname/foo.html',
1179 [''], action='A'),
1180 MockAffectedFile('content/test/data/accessibility/aria/foo.html',
1181 [''], action='A'),
1182 MockAffectedFile('content/test/data/accessibility/css/foo.html',
1183 [''], action='A'),
1184 MockAffectedFile('content/test/data/accessibility/html/foo.html',
1185 [''], action='A'),
1186 MockAffectedFile(
Mark Schillaci6f568a52022-02-17 18:41:441187 'accessibility/WebContentsAccessibilityTreeTest.java',
Mark Schillacie5a0be22022-01-19 00:38:391188 [''], action='M')
1189 ]
1190
1191 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1192 mock_input_api, MockOutputApi())
1193 self.assertEqual(0, len(msgs),
1194 'Expected %d messages, found %d: %s'
1195 % (0, len(msgs), msgs))
1196
1197 # Test that a warning is raised when the Android file is not modified.
1198 def testAndroidChangeMissing(self):
1199 mock_input_api = MockInputApi()
1200
1201 mock_input_api.files = [
Aaron Leventhal267119f2023-08-18 22:45:341202 MockAffectedFile(
1203 'content/test/data/accessibility/aria/foo-expected-win.txt',
Mark Schillacie5a0be22022-01-19 00:38:391204 [''], action='A'),
1205 ]
1206
1207 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1208 mock_input_api, MockOutputApi())
1209 self.assertEqual(1, len(msgs),
1210 'Expected %d messages, found %d: %s'
1211 % (1, len(msgs), msgs))
1212
Aaron Leventhal267119f2023-08-18 22:45:341213 # Test that Android change is not required when no platform expectations files are changed.
1214 def testAndroidChangNotMissing(self):
Mark Schillacie5a0be22022-01-19 00:38:391215 mock_input_api = MockInputApi()
1216
1217 mock_input_api.files = [
1218 MockAffectedFile('content/test/data/accessibility/accname/foo.txt',
1219 [''], action='A'),
Aaron Leventhal267119f2023-08-18 22:45:341220 MockAffectedFile(
1221 'content/test/data/accessibility/html/foo-expected-blink.txt',
1222 [''], action='A'),
1223 MockAffectedFile('content/test/data/accessibility/html/foo.html',
1224 [''], action='A'),
Mark Schillacie5a0be22022-01-19 00:38:391225 MockAffectedFile('content/test/data/accessibility/aria/foo.cc',
1226 [''], action='A'),
1227 MockAffectedFile('content/test/data/accessibility/css/foo.h',
1228 [''], action='A'),
1229 MockAffectedFile('content/test/data/accessibility/tree/foo.py',
1230 [''], action='A')
1231 ]
1232
1233 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1234 mock_input_api, MockOutputApi())
1235 self.assertEqual(0, len(msgs),
1236 'Expected %d messages, found %d: %s'
1237 % (0, len(msgs), msgs))
1238
1239 # Test that Android change is not required for unrelated html files.
1240 def testIgnoreNonRelatedHtmlFiles(self):
1241 mock_input_api = MockInputApi()
1242
1243 mock_input_api.files = [
1244 MockAffectedFile('content/test/data/accessibility/event/foo.html',
1245 [''], action='A'),
1246 ]
1247
1248 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1249 mock_input_api, MockOutputApi())
1250 self.assertEqual(0, len(msgs),
1251 'Expected %d messages, found %d: %s'
1252 % (0, len(msgs), msgs))
1253
1254 # Test that only modifying an html file will not trigger the warning.
1255 def testIgnoreModifiedFiles(self):
1256 mock_input_api = MockInputApi()
1257
1258 mock_input_api.files = [
1259 MockAffectedFile('content/test/data/accessibility/aria/foo.html',
1260 [''], action='M')
1261 ]
1262
1263 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1264 mock_input_api, MockOutputApi())
1265 self.assertEqual(0, len(msgs),
1266 'Expected %d messages, found %d: %s'
1267 % (0, len(msgs), msgs))
1268
yolandyan45001472016-12-21 21:12:421269class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
1270 def testCheckAndroidTestAnnotationUsage(self):
1271 mock_input_api = MockInputApi()
1272 mock_output_api = MockOutputApi()
1273
1274 mock_input_api.files = [
1275 MockAffectedFile('LalaLand.java', [
1276 'random stuff'
1277 ]),
1278 MockAffectedFile('CorrectUsage.java', [
Mohamed Heikal3d7a94c2023-03-28 16:55:241279 'import androidx.test.filters.LargeTest;',
1280 'import androidx.test.filters.MediumTest;',
1281 'import androidx.test.filters.SmallTest;',
yolandyan45001472016-12-21 21:12:421282 ]),
1283 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
1284 'import android.test.suitebuilder.annotation.LargeTest;',
1285 ]),
1286 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
1287 'import android.test.suitebuilder.annotation.MediumTest;',
1288 ]),
1289 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
1290 'import android.test.suitebuilder.annotation.SmallTest;',
1291 ]),
1292 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
1293 'import android.test.suitebuilder.annotation.Smoke;',
1294 ])
1295 ]
1296 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
1297 mock_input_api, mock_output_api)
1298 self.assertEqual(1, len(msgs),
1299 'Expected %d items, found %d: %s'
1300 % (1, len(msgs), msgs))
1301 self.assertEqual(4, len(msgs[0].items),
1302 'Expected %d items, found %d: %s'
1303 % (4, len(msgs[0].items), msgs[0].items))
1304 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
1305 'UsedDeprecatedLargeTestAnnotation not found in errors')
1306 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
1307 in msgs[0].items,
1308 'UsedDeprecatedMediumTestAnnotation not found in errors')
1309 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
1310 'UsedDeprecatedSmallTestAnnotation not found in errors')
1311 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
1312 'UsedDeprecatedSmokeAnnotation not found in errors')
1313
Min Qinbc44383c2023-02-22 17:25:261314class AndroidBannedImportTest(unittest.TestCase):
1315 def testCheckAndroidNoBannedImports(self):
1316 mock_input_api = MockInputApi()
1317 mock_output_api = MockOutputApi()
1318
1319 test_files = [
1320 MockAffectedFile('RandomStufff.java', [
1321 'random stuff'
1322 ]),
1323 MockAffectedFile('NoBannedImports.java', [
Mohamed Heikal3d7a94c2023-03-28 16:55:241324 'import androidx.test.filters.LargeTest;',
1325 'import androidx.test.filters.MediumTest;',
1326 'import androidx.test.filters.SmallTest;',
Min Qinbc44383c2023-02-22 17:25:261327 ]),
1328 MockAffectedFile('BannedUri.java', [
1329 'import java.net.URI;',
1330 ]),
1331 MockAffectedFile('BannedTargetApi.java', [
1332 'import android.annotation.TargetApi;',
1333 ]),
1334 MockAffectedFile('BannedUiThreadTestRule.java', [
Mohamed Heikal3d7a94c2023-03-28 16:55:241335 'import androidx.test.rule.UiThreadTestRule;',
Min Qinbc44383c2023-02-22 17:25:261336 ]),
1337 MockAffectedFile('BannedUiThreadTest.java', [
Mohamed Heikal3d7a94c2023-03-28 16:55:241338 'import androidx.test.annotation.UiThreadTest;',
Min Qinbc44383c2023-02-22 17:25:261339 ]),
1340 MockAffectedFile('BannedActivityTestRule.java', [
Mohamed Heikal3d7a94c2023-03-28 16:55:241341 'import androidx.test.rule.ActivityTestRule;',
Min Qinbc44383c2023-02-22 17:25:261342 ]),
1343 MockAffectedFile('BannedVectorDrawableCompat.java', [
1344 'import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;',
1345 ])
1346 ]
1347 msgs = []
1348 for file in test_files:
1349 mock_input_api.files = [file]
1350 msgs.append(PRESUBMIT._CheckAndroidNoBannedImports(
1351 mock_input_api, mock_output_api))
1352 self.assertEqual(0, len(msgs[0]))
1353 self.assertEqual(0, len(msgs[1]))
1354 self.assertTrue(msgs[2][0].message.startswith(textwrap.dedent("""\
1355 Banned imports were used.
1356 BannedUri.java:1:"""
1357 )))
1358 self.assertTrue(msgs[3][0].message.startswith(textwrap.dedent("""\
1359 Banned imports were used.
1360 BannedTargetApi.java:1:"""
1361 )))
1362 self.assertTrue(msgs[4][0].message.startswith(textwrap.dedent("""\
1363 Banned imports were used.
1364 BannedUiThreadTestRule.java:1:"""
1365 )))
1366 self.assertTrue(msgs[5][0].message.startswith(textwrap.dedent("""\
1367 Banned imports were used.
1368 BannedUiThreadTest.java:1:"""
1369 )))
1370 self.assertTrue(msgs[6][0].message.startswith(textwrap.dedent("""\
1371 Banned imports were used.
1372 BannedActivityTestRule.java:1:"""
1373 )))
1374 self.assertTrue(msgs[7][0].message.startswith(textwrap.dedent("""\
1375 Banned imports were used.
1376 BannedVectorDrawableCompat.java:1:"""
1377 )))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391378
Mohamed Heikal5e5b7922020-10-29 18:57:591379class CheckNoDownstreamDepsTest(unittest.TestCase):
1380 def testInvalidDepFromUpstream(self):
1381 mock_input_api = MockInputApi()
1382 mock_output_api = MockOutputApi()
1383
1384 mock_input_api.files = [
1385 MockAffectedFile('BUILD.gn', [
1386 'deps = [',
1387 ' "//clank/target:test",',
1388 ']'
1389 ]),
1390 MockAffectedFile('chrome/android/BUILD.gn', [
1391 'deps = [ "//clank/target:test" ]'
1392 ]),
1393 MockAffectedFile('chrome/chrome_java_deps.gni', [
1394 'java_deps = [',
1395 ' "//clank/target:test",',
1396 ']'
1397 ]),
1398 ]
1399 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1400 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1401 mock_input_api, mock_output_api)
1402 self.assertEqual(1, len(msgs),
1403 'Expected %d items, found %d: %s'
1404 % (1, len(msgs), msgs))
1405 self.assertEqual(3, len(msgs[0].items),
1406 'Expected %d items, found %d: %s'
1407 % (3, len(msgs[0].items), msgs[0].items))
1408 self.assertTrue(any('BUILD.gn:2' in item for item in msgs[0].items),
1409 'BUILD.gn not found in errors')
1410 self.assertTrue(
1411 any('chrome/android/BUILD.gn:1' in item for item in msgs[0].items),
1412 'chrome/android/BUILD.gn:1 not found in errors')
1413 self.assertTrue(
1414 any('chrome/chrome_java_deps.gni:2' in item for item in msgs[0].items),
1415 'chrome/chrome_java_deps.gni:2 not found in errors')
1416
1417 def testAllowsComments(self):
1418 mock_input_api = MockInputApi()
1419 mock_output_api = MockOutputApi()
1420
1421 mock_input_api.files = [
1422 MockAffectedFile('BUILD.gn', [
1423 '# real implementation in //clank/target:test',
1424 ]),
1425 ]
1426 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1427 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1428 mock_input_api, mock_output_api)
1429 self.assertEqual(0, len(msgs),
1430 'Expected %d items, found %d: %s'
1431 % (0, len(msgs), msgs))
1432
1433 def testOnlyChecksBuildFiles(self):
1434 mock_input_api = MockInputApi()
1435 mock_output_api = MockOutputApi()
1436
1437 mock_input_api.files = [
1438 MockAffectedFile('README.md', [
1439 'DEPS = [ "//clank/target:test" ]'
1440 ]),
1441 MockAffectedFile('chrome/android/java/file.java', [
1442 '//clank/ only function'
1443 ]),
1444 ]
1445 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1446 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1447 mock_input_api, mock_output_api)
1448 self.assertEqual(0, len(msgs),
1449 'Expected %d items, found %d: %s'
1450 % (0, len(msgs), msgs))
1451
1452 def testValidDepFromDownstream(self):
1453 mock_input_api = MockInputApi()
1454 mock_output_api = MockOutputApi()
1455
1456 mock_input_api.files = [
1457 MockAffectedFile('BUILD.gn', [
1458 'DEPS = [',
1459 ' "//clank/target:test",',
1460 ']'
1461 ]),
1462 MockAffectedFile('java/BUILD.gn', [
1463 'DEPS = [ "//clank/target:test" ]'
1464 ]),
1465 ]
1466 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src/clank'
1467 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1468 mock_input_api, mock_output_api)
1469 self.assertEqual(0, len(msgs),
1470 'Expected %d items, found %d: %s'
1471 % (0, len(msgs), msgs))
1472
yolandyan45001472016-12-21 21:12:421473
Jinsong Fan91ebbbd2019-04-16 14:57:171474class AndroidDebuggableBuildTest(unittest.TestCase):
1475
1476 def testCheckAndroidDebuggableBuild(self):
1477 mock_input_api = MockInputApi()
1478 mock_output_api = MockOutputApi()
1479
1480 mock_input_api.files = [
1481 MockAffectedFile('RandomStuff.java', [
1482 'random stuff'
1483 ]),
1484 MockAffectedFile('CorrectUsage.java', [
1485 'import org.chromium.base.BuildInfo;',
1486 'some random stuff',
1487 'boolean isOsDebuggable = BuildInfo.isDebugAndroid();',
1488 ]),
1489 MockAffectedFile('JustCheckUserdebugBuild.java', [
1490 'import android.os.Build;',
1491 'some random stuff',
1492 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")',
1493 ]),
1494 MockAffectedFile('JustCheckEngineeringBuild.java', [
1495 'import android.os.Build;',
1496 'some random stuff',
1497 'boolean isOsDebuggable = "eng".equals(Build.TYPE)',
1498 ]),
1499 MockAffectedFile('UsedBuildType.java', [
1500 'import android.os.Build;',
1501 'some random stuff',
1502 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")'
1503 '|| "eng".equals(Build.TYPE)',
1504 ]),
1505 MockAffectedFile('UsedExplicitBuildType.java', [
1506 'some random stuff',
1507 'boolean isOsDebuggable = android.os.Build.TYPE.equals("userdebug")'
1508 '|| "eng".equals(android.os.Build.TYPE)',
1509 ]),
1510 ]
1511
1512 msgs = PRESUBMIT._CheckAndroidDebuggableBuild(
1513 mock_input_api, mock_output_api)
1514 self.assertEqual(1, len(msgs),
1515 'Expected %d items, found %d: %s'
1516 % (1, len(msgs), msgs))
1517 self.assertEqual(4, len(msgs[0].items),
1518 'Expected %d items, found %d: %s'
1519 % (4, len(msgs[0].items), msgs[0].items))
1520 self.assertTrue('JustCheckUserdebugBuild.java:3' in msgs[0].items)
1521 self.assertTrue('JustCheckEngineeringBuild.java:3' in msgs[0].items)
1522 self.assertTrue('UsedBuildType.java:3' in msgs[0].items)
1523 self.assertTrue('UsedExplicitBuildType.java:2' in msgs[0].items)
1524
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391525
dgn4401aa52015-04-29 16:26:171526class LogUsageTest(unittest.TestCase):
1527
dgnaa68d5e2015-06-10 10:08:221528 def testCheckAndroidCrLogUsage(self):
1529 mock_input_api = MockInputApi()
1530 mock_output_api = MockOutputApi()
1531
1532 mock_input_api.files = [
1533 MockAffectedFile('RandomStuff.java', [
1534 'random stuff'
1535 ]),
dgn87d9fb62015-06-12 09:15:121536 MockAffectedFile('HasAndroidLog.java', [
1537 'import android.util.Log;',
1538 'some random stuff',
1539 'Log.d("TAG", "foo");',
1540 ]),
1541 MockAffectedFile('HasExplicitUtilLog.java', [
1542 'some random stuff',
1543 'android.util.Log.d("TAG", "foo");',
1544 ]),
1545 MockAffectedFile('IsInBasePackage.java', [
1546 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511547 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121548 'Log.d(TAG, "foo");',
1549 ]),
1550 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1551 'package org.chromium.base;',
1552 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511553 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121554 'Log.d(TAG, "foo");',
1555 ]),
1556 MockAffectedFile('HasBothLog.java', [
1557 'import org.chromium.base.Log;',
1558 'some random stuff',
dgn38736db2015-09-18 19:20:511559 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121560 'Log.d(TAG, "foo");',
1561 'android.util.Log.d("TAG", "foo");',
1562 ]),
dgnaa68d5e2015-06-10 10:08:221563 MockAffectedFile('HasCorrectTag.java', [
1564 'import org.chromium.base.Log;',
1565 'some random stuff',
dgn38736db2015-09-18 19:20:511566 'private static final String TAG = "cr_Foo";',
1567 'Log.d(TAG, "foo");',
1568 ]),
1569 MockAffectedFile('HasOldTag.java', [
1570 'import org.chromium.base.Log;',
1571 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221572 'private static final String TAG = "cr.Foo";',
1573 'Log.d(TAG, "foo");',
1574 ]),
dgn38736db2015-09-18 19:20:511575 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221576 'import org.chromium.base.Log;',
1577 'some random stuff',
dgn38736db2015-09-18 19:20:511578 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221579 'Log.d(TAG, "foo");',
1580 ]),
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461581 MockAffectedFile('HasDottedTagPublic.java', [
1582 'import org.chromium.base.Log;',
1583 'some random stuff',
1584 'public static final String TAG = "cr_foo.bar";',
1585 'Log.d(TAG, "foo");',
1586 ]),
dgnaa68d5e2015-06-10 10:08:221587 MockAffectedFile('HasNoTagDecl.java', [
1588 'import org.chromium.base.Log;',
1589 'some random stuff',
1590 'Log.d(TAG, "foo");',
1591 ]),
1592 MockAffectedFile('HasIncorrectTagDecl.java', [
1593 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511594 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221595 'some random stuff',
1596 'Log.d(TAG, "foo");',
1597 ]),
1598 MockAffectedFile('HasInlineTag.java', [
1599 'import org.chromium.base.Log;',
1600 'some random stuff',
dgn38736db2015-09-18 19:20:511601 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221602 'Log.d("TAG", "foo");',
1603 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551604 MockAffectedFile('HasInlineTagWithSpace.java', [
1605 'import org.chromium.base.Log;',
1606 'some random stuff',
1607 'private static final String TAG = "cr_Foo";',
1608 'Log.d("log message", "foo");',
1609 ]),
dgn38736db2015-09-18 19:20:511610 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221611 'import org.chromium.base.Log;',
1612 'some random stuff',
1613 'private static final String TAG = "rubbish";',
1614 'Log.d(TAG, "foo");',
1615 ]),
1616 MockAffectedFile('HasTooLongTag.java', [
1617 'import org.chromium.base.Log;',
1618 'some random stuff',
Gao Shenga79ebd42022-08-08 17:25:591619 'private static final String TAG = "21_characters_long___";',
dgnaa68d5e2015-06-10 10:08:221620 'Log.d(TAG, "foo");',
1621 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551622 MockAffectedFile('HasTooLongTagWithNoLogCallsInDiff.java', [
1623 'import org.chromium.base.Log;',
1624 'some random stuff',
Gao Shenga79ebd42022-08-08 17:25:591625 'private static final String TAG = "21_characters_long___";',
Tomasz Śniatowski3ae2f102020-03-23 15:35:551626 ]),
dgnaa68d5e2015-06-10 10:08:221627 ]
1628
1629 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1630 mock_input_api, mock_output_api)
1631
Andrew Grieved3a35d82024-01-02 21:24:381632 self.assertEqual(5, len(msgs),
1633 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221634
1635 # Declaration format
dgn38736db2015-09-18 19:20:511636 nb = len(msgs[0].items)
1637 self.assertEqual(2, nb,
1638 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221639 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1640 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221641
Andrew Grieved3a35d82024-01-02 21:24:381642 # Tag length
Geoff Huang77e3d6f2023-12-25 06:27:381643 nb = len(msgs[1].items)
Andrew Grieved3a35d82024-01-02 21:24:381644 self.assertEqual(2, nb,
1645 'Expected %d items, found %d: %s' % (2, nb, msgs[1].items))
1646 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
1647 self.assertTrue('HasTooLongTagWithNoLogCallsInDiff.java' in msgs[1].items)
Geoff Huang77e3d6f2023-12-25 06:27:381648
Andrew Grieved3a35d82024-01-02 21:24:381649 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511650 nb = len(msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551651 self.assertEqual(3, nb,
1652 'Expected %d items, found %d: %s' % (3, nb, msgs[2].items))
Andrew Grieved3a35d82024-01-02 21:24:381653 self.assertTrue('HasBothLog.java:5' in msgs[2].items)
1654 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
1655 self.assertTrue('HasInlineTagWithSpace.java:4' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221656
Andrew Grieved3a35d82024-01-02 21:24:381657 # Util Log usage
Geoff Huang77e3d6f2023-12-25 06:27:381658 nb = len(msgs[3].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461659 self.assertEqual(3, nb,
Andrew Grieved3a35d82024-01-02 21:24:381660 'Expected %d items, found %d: %s' % (3, nb, msgs[3].items))
1661 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
1662 self.assertTrue('HasExplicitUtilLog.java:2' in msgs[3].items)
1663 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
1664
1665 # Tag must not contain
1666 nb = len(msgs[4].items)
1667 self.assertEqual(3, nb,
1668 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1669 self.assertTrue('HasDottedTag.java' in msgs[4].items)
1670 self.assertTrue('HasDottedTagPublic.java' in msgs[4].items)
1671 self.assertTrue('HasOldTag.java' in msgs[4].items)
dgn38736db2015-09-18 19:20:511672
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391673
estadee17314a02017-01-12 16:22:161674class GoogleAnswerUrlFormatTest(unittest.TestCase):
1675
1676 def testCatchAnswerUrlId(self):
1677 input_api = MockInputApi()
1678 input_api.files = [
1679 MockFile('somewhere/file.cc',
1680 ['char* host = '
1681 ' "https://support.google.com/chrome/answer/123456";']),
1682 MockFile('somewhere_else/file.cc',
1683 ['char* host = '
1684 ' "https://support.google.com/chrome/a/answer/123456";']),
1685 ]
1686
Saagar Sanghavifceeaae2020-08-12 16:40:361687 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161688 input_api, MockOutputApi())
1689 self.assertEqual(1, len(warnings))
1690 self.assertEqual(2, len(warnings[0].items))
1691
1692 def testAllowAnswerUrlParam(self):
1693 input_api = MockInputApi()
1694 input_api.files = [
1695 MockFile('somewhere/file.cc',
1696 ['char* host = '
1697 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1698 ]
1699
Saagar Sanghavifceeaae2020-08-12 16:40:361700 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161701 input_api, MockOutputApi())
1702 self.assertEqual(0, len(warnings))
1703
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391704
reillyi38965732015-11-16 18:27:331705class HardcodedGoogleHostsTest(unittest.TestCase):
1706
1707 def testWarnOnAssignedLiterals(self):
1708 input_api = MockInputApi()
1709 input_api.files = [
1710 MockFile('content/file.cc',
1711 ['char* host = "https://www.google.com";']),
1712 MockFile('content/file.cc',
1713 ['char* host = "https://www.googleapis.com";']),
1714 MockFile('content/file.cc',
1715 ['char* host = "https://clients1.google.com";']),
1716 ]
1717
Saagar Sanghavifceeaae2020-08-12 16:40:361718 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331719 input_api, MockOutputApi())
1720 self.assertEqual(1, len(warnings))
1721 self.assertEqual(3, len(warnings[0].items))
1722
1723 def testAllowInComment(self):
1724 input_api = MockInputApi()
1725 input_api.files = [
1726 MockFile('content/file.cc',
1727 ['char* host = "https://www.aol.com"; // google.com'])
1728 ]
1729
Saagar Sanghavifceeaae2020-08-12 16:40:361730 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331731 input_api, MockOutputApi())
1732 self.assertEqual(0, len(warnings))
1733
dgn4401aa52015-04-29 16:26:171734
James Cook6b6597c2019-11-06 22:05:291735class ChromeOsSyncedPrefRegistrationTest(unittest.TestCase):
1736
1737 def testWarnsOnChromeOsDirectories(self):
Henrique Ferreiro2e1aa1092021-11-29 22:22:121738 files = [
James Cook6b6597c2019-11-06 22:05:291739 MockFile('ash/file.cc',
1740 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1741 MockFile('chrome/browser/chromeos/file.cc',
1742 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1743 MockFile('chromeos/file.cc',
1744 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1745 MockFile('components/arc/file.cc',
1746 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1747 MockFile('components/exo/file.cc',
1748 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1749 ]
Henrique Ferreiro2e1aa1092021-11-29 22:22:121750 input_api = MockInputApi()
1751 for file in files:
1752 input_api.files = [file]
1753 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
1754 input_api, MockOutputApi())
1755 self.assertEqual(1, len(warnings))
James Cook6b6597c2019-11-06 22:05:291756
1757 def testDoesNotWarnOnSyncOsPref(self):
1758 input_api = MockInputApi()
1759 input_api.files = [
1760 MockFile('chromeos/file.cc',
1761 ['PrefRegistrySyncable::SYNCABLE_OS_PREF']),
1762 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361763 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291764 input_api, MockOutputApi())
1765 self.assertEqual(0, len(warnings))
1766
Henrique Ferreiro2e1aa1092021-11-29 22:22:121767 def testDoesNotWarnOnOtherDirectories(self):
James Cook6b6597c2019-11-06 22:05:291768 input_api = MockInputApi()
1769 input_api.files = [
1770 MockFile('chrome/browser/ui/file.cc',
1771 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1772 MockFile('components/sync/file.cc',
1773 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1774 MockFile('content/browser/file.cc',
1775 ['PrefRegistrySyncable::SYNCABLE_PREF']),
Henrique Ferreiro2e1aa1092021-11-29 22:22:121776 MockFile('a/notchromeos/file.cc',
1777 ['PrefRegistrySyncable::SYNCABLE_PREF']),
James Cook6b6597c2019-11-06 22:05:291778 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361779 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291780 input_api, MockOutputApi())
1781 self.assertEqual(0, len(warnings))
1782
1783 def testSeparateWarningForPriorityPrefs(self):
1784 input_api = MockInputApi()
1785 input_api.files = [
1786 MockFile('chromeos/file.cc',
1787 ['PrefRegistrySyncable::SYNCABLE_PREF',
1788 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']),
1789 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361790 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291791 input_api, MockOutputApi())
1792 self.assertEqual(2, len(warnings))
1793
1794
jbriance9e12f162016-11-25 07:57:501795class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311796 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501797 mock_input_api = MockInputApi()
1798 mock_input_api.files = [
1799 MockAffectedFile('somewhere/file.cc', [
1800 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311801 ]),
1802 MockAffectedFile('third_party/header.h', [
1803 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501804 ])
1805 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361806 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391807 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501808 self.assertEqual(0, len(warnings))
1809
1810 def testNoNestedDeclaration(self):
1811 mock_input_api = MockInputApi()
1812 mock_input_api.files = [
1813 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311814 'class SomeClass {',
1815 ' protected:',
1816 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501817 '};'
1818 ])
1819 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361820 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391821 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501822 self.assertEqual(0, len(warnings))
1823
1824 def testSubStrings(self):
1825 mock_input_api = MockInputApi()
1826 mock_input_api.files = [
1827 MockAffectedFile('somewhere/header.h', [
1828 'class NotUsefulClass;',
1829 'struct SomeStruct;',
1830 'UsefulClass *p1;',
1831 'SomeStructPtr *p2;'
1832 ])
1833 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361834 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391835 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501836 self.assertEqual(2, len(warnings))
1837
1838 def testUselessForwardDeclaration(self):
1839 mock_input_api = MockInputApi()
1840 mock_input_api.files = [
1841 MockAffectedFile('somewhere/header.h', [
1842 'class DummyClass;',
1843 'struct DummyStruct;',
1844 'class UsefulClass;',
1845 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311846 ])
jbriance9e12f162016-11-25 07:57:501847 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361848 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391849 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501850 self.assertEqual(2, len(warnings))
1851
jbriance2c51e821a2016-12-12 08:24:311852 def testBlinkHeaders(self):
1853 mock_input_api = MockInputApi()
1854 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491855 MockAffectedFile('third_party/blink/header.h', [
jbriance2c51e821a2016-12-12 08:24:311856 'class DummyClass;',
1857 'struct DummyStruct;',
1858 ]),
Kent Tamura32dbbcb2018-11-30 12:28:491859 MockAffectedFile('third_party\\blink\\header.h', [
jbriance2c51e821a2016-12-12 08:24:311860 'class DummyClass;',
1861 'struct DummyStruct;',
1862 ])
1863 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361864 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391865 MockOutputApi())
jbriance2c51e821a2016-12-12 08:24:311866 self.assertEqual(4, len(warnings))
1867
jbriance9e12f162016-11-25 07:57:501868
rlanday6802cf632017-05-30 17:48:361869class RelativeIncludesTest(unittest.TestCase):
1870 def testThirdPartyNotWebKitIgnored(self):
1871 mock_input_api = MockInputApi()
1872 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:401873 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1874 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
rlanday6802cf632017-05-30 17:48:361875 ]
1876
1877 mock_output_api = MockOutputApi()
1878
Saagar Sanghavifceeaae2020-08-12 16:40:361879 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361880 mock_input_api, mock_output_api)
1881 self.assertEqual(0, len(errors))
1882
1883 def testNonCppFileIgnored(self):
1884 mock_input_api = MockInputApi()
1885 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:401886 MockAffectedFile('test.py', '#include "../header.h"'),
rlanday6802cf632017-05-30 17:48:361887 ]
1888
1889 mock_output_api = MockOutputApi()
1890
Saagar Sanghavifceeaae2020-08-12 16:40:361891 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361892 mock_input_api, mock_output_api)
1893 self.assertEqual(0, len(errors))
1894
1895 def testInnocuousChangesAllowed(self):
1896 mock_input_api = MockInputApi()
1897 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:401898 MockAffectedFile('test.cpp', '#include "header.h"'),
1899 MockAffectedFile('test2.cpp', '../'),
rlanday6802cf632017-05-30 17:48:361900 ]
1901
1902 mock_output_api = MockOutputApi()
1903
Saagar Sanghavifceeaae2020-08-12 16:40:361904 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361905 mock_input_api, mock_output_api)
1906 self.assertEqual(0, len(errors))
1907
1908 def testRelativeIncludeNonWebKitProducesError(self):
1909 mock_input_api = MockInputApi()
1910 mock_input_api.files = [
1911 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1912 ]
1913
1914 mock_output_api = MockOutputApi()
1915
Saagar Sanghavifceeaae2020-08-12 16:40:361916 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361917 mock_input_api, mock_output_api)
1918 self.assertEqual(1, len(errors))
1919
1920 def testRelativeIncludeWebKitProducesError(self):
1921 mock_input_api = MockInputApi()
1922 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491923 MockAffectedFile('third_party/blink/test.cpp',
rlanday6802cf632017-05-30 17:48:361924 ['#include "../header.h']),
1925 ]
1926
1927 mock_output_api = MockOutputApi()
1928
Saagar Sanghavifceeaae2020-08-12 16:40:361929 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361930 mock_input_api, mock_output_api)
1931 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241932
Daniel Cheng13ca61a882017-08-25 15:11:251933
Daniel Bratell65b033262019-04-23 08:17:061934class CCIncludeTest(unittest.TestCase):
1935 def testThirdPartyNotBlinkIgnored(self):
1936 mock_input_api = MockInputApi()
1937 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:401938 MockAffectedFile('third_party/test.cpp', '#include "file.cc"'),
Daniel Bratell65b033262019-04-23 08:17:061939 ]
1940
1941 mock_output_api = MockOutputApi()
1942
Saagar Sanghavifceeaae2020-08-12 16:40:361943 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061944 mock_input_api, mock_output_api)
1945 self.assertEqual(0, len(errors))
1946
1947 def testPythonFileIgnored(self):
1948 mock_input_api = MockInputApi()
1949 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:401950 MockAffectedFile('test.py', '#include "file.cc"'),
Daniel Bratell65b033262019-04-23 08:17:061951 ]
1952
1953 mock_output_api = MockOutputApi()
1954
Saagar Sanghavifceeaae2020-08-12 16:40:361955 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061956 mock_input_api, mock_output_api)
1957 self.assertEqual(0, len(errors))
1958
1959 def testIncFilesAccepted(self):
1960 mock_input_api = MockInputApi()
1961 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:401962 MockAffectedFile('test.py', '#include "file.inc"'),
Daniel Bratell65b033262019-04-23 08:17:061963 ]
1964
1965 mock_output_api = MockOutputApi()
1966
Saagar Sanghavifceeaae2020-08-12 16:40:361967 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061968 mock_input_api, mock_output_api)
1969 self.assertEqual(0, len(errors))
1970
1971 def testInnocuousChangesAllowed(self):
1972 mock_input_api = MockInputApi()
1973 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:401974 MockAffectedFile('test.cpp', '#include "header.h"'),
1975 MockAffectedFile('test2.cpp', 'Something "file.cc"'),
Daniel Bratell65b033262019-04-23 08:17:061976 ]
1977
1978 mock_output_api = MockOutputApi()
1979
Saagar Sanghavifceeaae2020-08-12 16:40:361980 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061981 mock_input_api, mock_output_api)
1982 self.assertEqual(0, len(errors))
1983
1984 def testCcIncludeNonBlinkProducesError(self):
1985 mock_input_api = MockInputApi()
1986 mock_input_api.files = [
1987 MockAffectedFile('test.cpp', ['#include "file.cc"']),
1988 ]
1989
1990 mock_output_api = MockOutputApi()
1991
Saagar Sanghavifceeaae2020-08-12 16:40:361992 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061993 mock_input_api, mock_output_api)
1994 self.assertEqual(1, len(errors))
1995
1996 def testCppIncludeBlinkProducesError(self):
1997 mock_input_api = MockInputApi()
1998 mock_input_api.files = [
1999 MockAffectedFile('third_party/blink/test.cpp',
2000 ['#include "foo/file.cpp"']),
2001 ]
2002
2003 mock_output_api = MockOutputApi()
2004
Saagar Sanghavifceeaae2020-08-12 16:40:362005 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:062006 mock_input_api, mock_output_api)
2007 self.assertEqual(1, len(errors))
2008
2009
Andrew Grieve1b290e4a22020-11-24 20:07:012010class GnGlobForwardTest(unittest.TestCase):
2011 def testAddBareGlobs(self):
2012 mock_input_api = MockInputApi()
2013 mock_input_api.files = [
2014 MockAffectedFile('base/stuff.gni', [
2015 'forward_variables_from(invoker, "*")']),
2016 MockAffectedFile('base/BUILD.gn', [
2017 'forward_variables_from(invoker, "*")']),
2018 ]
2019 warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
2020 self.assertEqual(1, len(warnings))
2021 msg = '\n'.join(warnings[0].items)
2022 self.assertIn('base/stuff.gni', msg)
2023 # Should not check .gn files. Local templates don't need to care about
2024 # visibility / testonly.
2025 self.assertNotIn('base/BUILD.gn', msg)
2026
2027 def testValidUses(self):
2028 mock_input_api = MockInputApi()
2029 mock_input_api.files = [
2030 MockAffectedFile('base/stuff.gni', [
2031 'forward_variables_from(invoker, "*", [])']),
2032 MockAffectedFile('base/stuff2.gni', [
2033 'forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)']),
2034 MockAffectedFile('base/stuff3.gni', [
2035 'forward_variables_from(invoker, [ "testonly" ])']),
2036 ]
2037 warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
2038 self.assertEqual([], warnings)
2039
2040
Sean Kaucb7c9b32022-10-25 21:25:522041class GnRebasePathTest(unittest.TestCase):
2042 def testAddAbsolutePath(self):
2043 mock_input_api = MockInputApi()
2044 mock_input_api.files = [
2045 MockAffectedFile('base/BUILD.gn', ['rebase_path("$target_gen_dir", "//")']),
2046 MockAffectedFile('base/root/BUILD.gn', ['rebase_path("$target_gen_dir", "/")']),
2047 MockAffectedFile('base/variable/BUILD.gn', ['rebase_path(target_gen_dir, "/")']),
2048 ]
2049 warnings = PRESUBMIT.CheckGnRebasePath(mock_input_api, MockOutputApi())
2050 self.assertEqual(1, len(warnings))
2051 msg = '\n'.join(warnings[0].items)
2052 self.assertIn('base/BUILD.gn', msg)
2053 self.assertIn('base/root/BUILD.gn', msg)
2054 self.assertIn('base/variable/BUILD.gn', msg)
2055 self.assertEqual(3, len(warnings[0].items))
2056
2057 def testValidUses(self):
2058 mock_input_api = MockInputApi()
2059 mock_input_api.files = [
2060 MockAffectedFile('base/foo/BUILD.gn', ['rebase_path("$target_gen_dir", root_build_dir)']),
2061 MockAffectedFile('base/bar/BUILD.gn', ['rebase_path("$target_gen_dir", root_build_dir, "/")']),
2062 MockAffectedFile('base/baz/BUILD.gn', ['rebase_path(target_gen_dir, root_build_dir)']),
2063 MockAffectedFile('base/baz/BUILD.gn', ['rebase_path(target_gen_dir, "//some/arbitrary/path")']),
2064 MockAffectedFile('base/okay_slash/BUILD.gn', ['rebase_path(".", "//")']),
2065 ]
2066 warnings = PRESUBMIT.CheckGnRebasePath(mock_input_api, MockOutputApi())
2067 self.assertEqual([], warnings)
2068
2069
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192070class NewHeaderWithoutGnChangeTest(unittest.TestCase):
2071 def testAddHeaderWithoutGn(self):
2072 mock_input_api = MockInputApi()
2073 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:402074 MockAffectedFile('base/stuff.h', ''),
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192075 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362076 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192077 mock_input_api, MockOutputApi())
2078 self.assertEqual(1, len(warnings))
2079 self.assertTrue('base/stuff.h' in warnings[0].items)
2080
2081 def testModifyHeader(self):
2082 mock_input_api = MockInputApi()
2083 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:402084 MockAffectedFile('base/stuff.h', '', action='M'),
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192085 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362086 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192087 mock_input_api, MockOutputApi())
2088 self.assertEqual(0, len(warnings))
2089
2090 def testDeleteHeader(self):
2091 mock_input_api = MockInputApi()
2092 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:402093 MockAffectedFile('base/stuff.h', '', action='D'),
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192094 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362095 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192096 mock_input_api, MockOutputApi())
2097 self.assertEqual(0, len(warnings))
2098
2099 def testAddHeaderWithGn(self):
2100 mock_input_api = MockInputApi()
2101 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:402102 MockAffectedFile('base/stuff.h', ''),
2103 MockAffectedFile('base/BUILD.gn', 'stuff.h'),
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192104 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362105 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192106 mock_input_api, MockOutputApi())
2107 self.assertEqual(0, len(warnings))
2108
2109 def testAddHeaderWithGni(self):
2110 mock_input_api = MockInputApi()
2111 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:402112 MockAffectedFile('base/stuff.h', ''),
2113 MockAffectedFile('base/files.gni', 'stuff.h'),
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192114 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362115 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192116 mock_input_api, MockOutputApi())
2117 self.assertEqual(0, len(warnings))
2118
2119 def testAddHeaderWithOther(self):
2120 mock_input_api = MockInputApi()
2121 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:402122 MockAffectedFile('base/stuff.h', ''),
2123 MockAffectedFile('base/stuff.cc', 'stuff.h'),
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192124 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362125 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192126 mock_input_api, MockOutputApi())
2127 self.assertEqual(1, len(warnings))
2128
2129 def testAddHeaderWithWrongGn(self):
2130 mock_input_api = MockInputApi()
2131 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:402132 MockAffectedFile('base/stuff.h', ''),
2133 MockAffectedFile('base/BUILD.gn', 'stuff_h'),
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192134 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362135 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192136 mock_input_api, MockOutputApi())
2137 self.assertEqual(1, len(warnings))
2138
2139 def testAddHeadersWithGn(self):
2140 mock_input_api = MockInputApi()
2141 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:402142 MockAffectedFile('base/stuff.h', ''),
2143 MockAffectedFile('base/another.h', ''),
2144 MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'),
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192145 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362146 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192147 mock_input_api, MockOutputApi())
2148 self.assertEqual(0, len(warnings))
2149
2150 def testAddHeadersWithWrongGn(self):
2151 mock_input_api = MockInputApi()
2152 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:402153 MockAffectedFile('base/stuff.h', ''),
2154 MockAffectedFile('base/another.h', ''),
2155 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'),
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192156 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362157 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192158 mock_input_api, MockOutputApi())
2159 self.assertEqual(1, len(warnings))
2160 self.assertFalse('base/stuff.h' in warnings[0].items)
2161 self.assertTrue('base/another.h' in warnings[0].items)
2162
2163 def testAddHeadersWithWrongGn2(self):
2164 mock_input_api = MockInputApi()
2165 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:402166 MockAffectedFile('base/stuff.h', ''),
2167 MockAffectedFile('base/another.h', ''),
2168 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'),
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192169 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362170 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192171 mock_input_api, MockOutputApi())
2172 self.assertEqual(1, len(warnings))
2173 self.assertTrue('base/stuff.h' in warnings[0].items)
2174 self.assertTrue('base/another.h' in warnings[0].items)
2175
2176
Michael Giuffridad3bc8672018-10-25 22:48:022177class CorrectProductNameInMessagesTest(unittest.TestCase):
2178 def testProductNameInDesc(self):
2179 mock_input_api = MockInputApi()
2180 mock_input_api.files = [
2181 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2182 '<message name="Foo" desc="Welcome to Chrome">',
2183 ' Welcome to Chrome!',
2184 '</message>',
2185 ]),
2186 MockAffectedFile('chrome/app/chromium_strings.grd', [
2187 '<message name="Bar" desc="Welcome to Chrome">',
2188 ' Welcome to Chromium!',
2189 '</message>',
2190 ]),
2191 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362192 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022193 mock_input_api, MockOutputApi())
2194 self.assertEqual(0, len(warnings))
2195
2196 def testChromeInChromium(self):
2197 mock_input_api = MockInputApi()
2198 mock_input_api.files = [
2199 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2200 '<message name="Foo" desc="Welcome to Chrome">',
2201 ' Welcome to Chrome!',
2202 '</message>',
2203 ]),
2204 MockAffectedFile('chrome/app/chromium_strings.grd', [
2205 '<message name="Bar" desc="Welcome to Chrome">',
2206 ' Welcome to Chrome!',
2207 '</message>',
2208 ]),
2209 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362210 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022211 mock_input_api, MockOutputApi())
2212 self.assertEqual(1, len(warnings))
2213 self.assertTrue('chrome/app/chromium_strings.grd' in warnings[0].items[0])
2214
2215 def testChromiumInChrome(self):
2216 mock_input_api = MockInputApi()
2217 mock_input_api.files = [
2218 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2219 '<message name="Foo" desc="Welcome to Chrome">',
2220 ' Welcome to Chromium!',
2221 '</message>',
2222 ]),
2223 MockAffectedFile('chrome/app/chromium_strings.grd', [
2224 '<message name="Bar" desc="Welcome to Chrome">',
2225 ' Welcome to Chromium!',
2226 '</message>',
2227 ]),
2228 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362229 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022230 mock_input_api, MockOutputApi())
2231 self.assertEqual(1, len(warnings))
2232 self.assertTrue(
2233 'chrome/app/google_chrome_strings.grd:2' in warnings[0].items[0])
2234
Thiago Perrotta099034f2023-06-05 18:10:202235 def testChromeForTestingInChromium(self):
2236 mock_input_api = MockInputApi()
2237 mock_input_api.files = [
2238 MockAffectedFile('chrome/app/chromium_strings.grd', [
2239 '<message name="Bar" desc="Welcome to Chrome">',
2240 ' Welcome to Chrome for Testing!',
2241 '</message>',
2242 ]),
2243 ]
2244 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
2245 mock_input_api, MockOutputApi())
2246 self.assertEqual(0, len(warnings))
2247
2248 def testChromeForTestingInChrome(self):
2249 mock_input_api = MockInputApi()
2250 mock_input_api.files = [
2251 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2252 '<message name="Bar" desc="Welcome to Chrome">',
2253 ' Welcome to Chrome for Testing!',
2254 '</message>',
2255 ]),
2256 ]
2257 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
2258 mock_input_api, MockOutputApi())
2259 self.assertEqual(1, len(warnings))
2260 self.assertTrue(
2261 'chrome/app/google_chrome_strings.grd:2' in warnings[0].items[0])
2262
Michael Giuffridad3bc8672018-10-25 22:48:022263 def testMultipleInstances(self):
2264 mock_input_api = MockInputApi()
2265 mock_input_api.files = [
2266 MockAffectedFile('chrome/app/chromium_strings.grd', [
2267 '<message name="Bar" desc="Welcome to Chrome">',
2268 ' Welcome to Chrome!',
2269 '</message>',
2270 '<message name="Baz" desc="A correct message">',
2271 ' Chromium is the software you are using.',
2272 '</message>',
2273 '<message name="Bat" desc="An incorrect message">',
2274 ' Google Chrome is the software you are using.',
2275 '</message>',
2276 ]),
2277 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362278 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022279 mock_input_api, MockOutputApi())
2280 self.assertEqual(1, len(warnings))
2281 self.assertTrue(
2282 'chrome/app/chromium_strings.grd:2' in warnings[0].items[0])
2283 self.assertTrue(
2284 'chrome/app/chromium_strings.grd:8' in warnings[0].items[1])
2285
2286 def testMultipleWarnings(self):
2287 mock_input_api = MockInputApi()
2288 mock_input_api.files = [
2289 MockAffectedFile('chrome/app/chromium_strings.grd', [
2290 '<message name="Bar" desc="Welcome to Chrome">',
2291 ' Welcome to Chrome!',
2292 '</message>',
2293 '<message name="Baz" desc="A correct message">',
2294 ' Chromium is the software you are using.',
2295 '</message>',
2296 '<message name="Bat" desc="An incorrect message">',
2297 ' Google Chrome is the software you are using.',
2298 '</message>',
2299 ]),
2300 MockAffectedFile('components/components_google_chrome_strings.grd', [
2301 '<message name="Bar" desc="Welcome to Chrome">',
2302 ' Welcome to Chrome!',
2303 '</message>',
2304 '<message name="Baz" desc="A correct message">',
2305 ' Chromium is the software you are using.',
2306 '</message>',
2307 '<message name="Bat" desc="An incorrect message">',
2308 ' Google Chrome is the software you are using.',
2309 '</message>',
2310 ]),
2311 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362312 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022313 mock_input_api, MockOutputApi())
2314 self.assertEqual(2, len(warnings))
2315 self.assertTrue(
2316 'components/components_google_chrome_strings.grd:5'
2317 in warnings[0].items[0])
2318 self.assertTrue(
2319 'chrome/app/chromium_strings.grd:2' in warnings[1].items[0])
2320 self.assertTrue(
2321 'chrome/app/chromium_strings.grd:8' in warnings[1].items[1])
2322
2323
Daniel Chenga37c03db2022-05-12 17:20:342324class _SecurityOwnersTestCase(unittest.TestCase):
Daniel Cheng171dad8d2022-05-21 00:40:252325 def _createMockInputApi(self):
2326 mock_input_api = MockInputApi()
2327 def FakeRepositoryRoot():
2328 return mock_input_api.os_path.join('chromium', 'src')
2329 mock_input_api.change.RepositoryRoot = FakeRepositoryRoot
2330 self._injectFakeOwnersClient(
2331 mock_input_api,
2332 ['[email protected]', '[email protected]'])
2333 return mock_input_api
2334
Daniel Chengd88244472022-05-16 09:08:472335 def _setupFakeChange(self, input_api):
2336 class FakeGerrit(object):
2337 def IsOwnersOverrideApproved(self, issue):
2338 return False
2339
2340 input_api.change.issue = 123
2341 input_api.gerrit = FakeGerrit()
2342
Daniel Chenga37c03db2022-05-12 17:20:342343 def _injectFakeOwnersClient(self, input_api, owners):
2344 class FakeOwnersClient(object):
2345 def ListOwners(self, f):
2346 return owners
2347
2348 input_api.owners_client = FakeOwnersClient()
2349
2350 def _injectFakeChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2351 def MockOwnerAndReviewers(input_api, email_regexp, approval_needed=False):
2352 return [owner, reviewers]
2353 input_api.canned_checks.GetCodereviewOwnerAndReviewers = \
2354 MockOwnerAndReviewers
2355
2356
2357class IpcSecurityOwnerTest(_SecurityOwnersTestCase):
2358 _test_cases = [
2359 ('*_messages.cc', 'scary_messages.cc'),
2360 ('*_messages*.h', 'scary_messages.h'),
2361 ('*_messages*.h', 'scary_messages_android.h'),
2362 ('*_param_traits*.*', 'scary_param_traits.h'),
2363 ('*_param_traits*.*', 'scary_param_traits_win.h'),
2364 ('*.mojom', 'scary.mojom'),
2365 ('*_mojom_traits*.*', 'scary_mojom_traits.h'),
2366 ('*_mojom_traits*.*', 'scary_mojom_traits_mac.h'),
2367 ('*_type_converter*.*', 'scary_type_converter.h'),
2368 ('*_type_converter*.*', 'scary_type_converter_nacl.h'),
2369 ('*.aidl', 'scary.aidl'),
2370 ]
2371
Daniel Cheng171dad8d2022-05-21 00:40:252372 def testHasCorrectPerFileRulesAndSecurityReviewer(self):
2373 mock_input_api = self._createMockInputApi()
2374 new_owners_file_path = mock_input_api.os_path.join(
2375 'services', 'goat', 'public', 'OWNERS')
2376 new_owners_file = [
2377 'per-file *.mojom=set noparent',
2378 'per-file *.mojom=file://ipc/SECURITY_OWNERS'
2379 ]
2380 def FakeReadFile(filename):
2381 self.assertEqual(
2382 mock_input_api.os_path.join('chromium', 'src', new_owners_file_path),
2383 filename)
2384 return '\n'.join(new_owners_file)
2385 mock_input_api.ReadFile = FakeReadFile
Daniel Cheng3008dc12022-05-13 04:02:112386 mock_input_api.files = [
Daniel Cheng171dad8d2022-05-21 00:40:252387 MockAffectedFile(
2388 new_owners_file_path, new_owners_file),
2389 MockAffectedFile(
2390 mock_input_api.os_path.join(
2391 'services', 'goat', 'public', 'goat.mojom'),
2392 ['// Scary contents.'])]
Daniel Chengd88244472022-05-16 09:08:472393 self._setupFakeChange(mock_input_api)
Daniel Cheng171dad8d2022-05-21 00:40:252394 self._injectFakeChangeOwnerAndReviewers(
2395 mock_input_api, '[email protected]', ['[email protected]'])
2396 mock_input_api.is_committing = True
2397 mock_input_api.dry_run = False
2398 mock_output_api = MockOutputApi()
2399 results = PRESUBMIT.CheckSecurityOwners(
2400 mock_input_api, mock_output_api)
2401 self.assertEqual(0, len(results))
2402
2403 def testMissingSecurityReviewerAtUpload(self):
2404 mock_input_api = self._createMockInputApi()
2405 new_owners_file_path = mock_input_api.os_path.join(
2406 'services', 'goat', 'public', 'OWNERS')
2407 new_owners_file = [
2408 'per-file *.mojom=set noparent',
2409 'per-file *.mojom=file://ipc/SECURITY_OWNERS'
2410 ]
2411 def FakeReadFile(filename):
2412 self.assertEqual(
2413 mock_input_api.os_path.join('chromium', 'src', new_owners_file_path),
2414 filename)
2415 return '\n'.join(new_owners_file)
2416 mock_input_api.ReadFile = FakeReadFile
2417 mock_input_api.files = [
2418 MockAffectedFile(
2419 new_owners_file_path, new_owners_file),
2420 MockAffectedFile(
2421 mock_input_api.os_path.join(
2422 'services', 'goat', 'public', 'goat.mojom'),
2423 ['// Scary contents.'])]
2424 self._setupFakeChange(mock_input_api)
Daniel Cheng3008dc12022-05-13 04:02:112425 self._injectFakeChangeOwnerAndReviewers(
2426 mock_input_api, '[email protected]', ['[email protected]'])
2427 mock_input_api.is_committing = False
2428 mock_input_api.dry_run = False
2429 mock_output_api = MockOutputApi()
2430 results = PRESUBMIT.CheckSecurityOwners(
2431 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252432 self.assertEqual(1, len(results))
Daniel Cheng681bc122022-05-19 02:23:442433 self.assertEqual('notify', results[0].type)
Daniel Cheng3008dc12022-05-13 04:02:112434 self.assertEqual(
Daniel Cheng171dad8d2022-05-21 00:40:252435 'Review from an owner in ipc/SECURITY_OWNERS is required for the '
2436 'following newly-added files:', results[0].message)
Daniel Cheng3008dc12022-05-13 04:02:112437
2438 def testMissingSecurityReviewerAtDryRunCommit(self):
Daniel Cheng171dad8d2022-05-21 00:40:252439 mock_input_api = self._createMockInputApi()
2440 new_owners_file_path = mock_input_api.os_path.join(
2441 'services', 'goat', 'public', 'OWNERS')
2442 new_owners_file = [
2443 'per-file *.mojom=set noparent',
2444 'per-file *.mojom=file://ipc/SECURITY_OWNERS'
2445 ]
2446 def FakeReadFile(filename):
2447 self.assertEqual(
2448 mock_input_api.os_path.join('chromium', 'src', new_owners_file_path),
2449 filename)
2450 return '\n'.join(new_owners_file)
2451 mock_input_api.ReadFile = FakeReadFile
Daniel Cheng3008dc12022-05-13 04:02:112452 mock_input_api.files = [
Daniel Cheng171dad8d2022-05-21 00:40:252453 MockAffectedFile(
2454 new_owners_file_path, new_owners_file),
2455 MockAffectedFile(
2456 mock_input_api.os_path.join(
2457 'services', 'goat', 'public', 'goat.mojom'),
2458 ['// Scary contents.'])]
Daniel Chengd88244472022-05-16 09:08:472459 self._setupFakeChange(mock_input_api)
Daniel Cheng3008dc12022-05-13 04:02:112460 self._injectFakeChangeOwnerAndReviewers(
2461 mock_input_api, '[email protected]', ['[email protected]'])
2462 mock_input_api.is_committing = True
2463 mock_input_api.dry_run = True
2464 mock_output_api = MockOutputApi()
2465 results = PRESUBMIT.CheckSecurityOwners(
2466 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252467 self.assertEqual(1, len(results))
Daniel Cheng3008dc12022-05-13 04:02:112468 self.assertEqual('error', results[0].type)
2469 self.assertEqual(
Daniel Cheng171dad8d2022-05-21 00:40:252470 'Review from an owner in ipc/SECURITY_OWNERS is required for the '
2471 'following newly-added files:', results[0].message)
Daniel Cheng3008dc12022-05-13 04:02:112472
Gao Shenga79ebd42022-08-08 17:25:592473 def testMissingSecurityApprovalAtRealCommit(self):
Daniel Cheng171dad8d2022-05-21 00:40:252474 mock_input_api = self._createMockInputApi()
2475 new_owners_file_path = mock_input_api.os_path.join(
2476 'services', 'goat', 'public', 'OWNERS')
2477 new_owners_file = [
2478 'per-file *.mojom=set noparent',
2479 'per-file *.mojom=file://ipc/SECURITY_OWNERS'
2480 ]
2481 def FakeReadFile(filename):
2482 self.assertEqual(
2483 mock_input_api.os_path.join('chromium', 'src', new_owners_file_path),
2484 filename)
2485 return '\n'.join(new_owners_file)
2486 mock_input_api.ReadFile = FakeReadFile
Daniel Cheng3008dc12022-05-13 04:02:112487 mock_input_api.files = [
Daniel Cheng171dad8d2022-05-21 00:40:252488 MockAffectedFile(
2489 new_owners_file_path, new_owners_file),
2490 MockAffectedFile(
2491 mock_input_api.os_path.join(
2492 'services', 'goat', 'public', 'goat.mojom'),
2493 ['// Scary contents.'])]
Daniel Chengd88244472022-05-16 09:08:472494 self._setupFakeChange(mock_input_api)
Daniel Cheng3008dc12022-05-13 04:02:112495 self._injectFakeChangeOwnerAndReviewers(
2496 mock_input_api, '[email protected]', ['[email protected]'])
2497 mock_input_api.is_committing = True
2498 mock_input_api.dry_run = False
2499 mock_output_api = MockOutputApi()
2500 results = PRESUBMIT.CheckSecurityOwners(
2501 mock_input_api, mock_output_api)
Daniel Cheng3008dc12022-05-13 04:02:112502 self.assertEqual('error', results[0].type)
2503 self.assertEqual(
Daniel Cheng171dad8d2022-05-21 00:40:252504 'Review from an owner in ipc/SECURITY_OWNERS is required for the '
2505 'following newly-added files:', results[0].message)
Daniel Chenga37c03db2022-05-12 17:20:342506
2507 def testIpcChangeNeedsSecurityOwner(self):
Daniel Cheng3008dc12022-05-13 04:02:112508 for is_committing in [True, False]:
2509 for pattern, filename in self._test_cases:
2510 with self.subTest(
2511 line=f'is_committing={is_committing}, filename={filename}'):
Daniel Cheng171dad8d2022-05-21 00:40:252512 mock_input_api = self._createMockInputApi()
Daniel Cheng3008dc12022-05-13 04:02:112513 mock_input_api.files = [
Daniel Cheng171dad8d2022-05-21 00:40:252514 MockAffectedFile(
2515 mock_input_api.os_path.join(
2516 'services', 'goat', 'public', filename),
2517 ['// Scary contents.'])]
Daniel Chengd88244472022-05-16 09:08:472518 self._setupFakeChange(mock_input_api)
Daniel Cheng3008dc12022-05-13 04:02:112519 self._injectFakeChangeOwnerAndReviewers(
2520 mock_input_api, '[email protected]', ['[email protected]'])
2521 mock_input_api.is_committing = is_committing
2522 mock_input_api.dry_run = False
2523 mock_output_api = MockOutputApi()
2524 results = PRESUBMIT.CheckSecurityOwners(
2525 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252526 self.assertEqual(1, len(results))
2527 self.assertEqual('error', results[0].type)
2528 self.assertTrue(results[0].message.replace('\\', '/').startswith(
2529 'Found missing OWNERS lines for security-sensitive files. '
2530 'Please add the following lines to services/goat/public/OWNERS:'))
Daniel Cheng3008dc12022-05-13 04:02:112531 self.assertEqual(['[email protected]'],
2532 mock_output_api.more_cc)
Daniel Chenga37c03db2022-05-12 17:20:342533
2534
Ken Rockot9f668262018-12-21 18:56:362535 def testServiceManifestChangeNeedsSecurityOwner(self):
Daniel Cheng171dad8d2022-05-21 00:40:252536 mock_input_api = self._createMockInputApi()
Ken Rockot9f668262018-12-21 18:56:362537 mock_input_api.files = [
Daniel Cheng171dad8d2022-05-21 00:40:252538 MockAffectedFile(
2539 mock_input_api.os_path.join(
2540 'services', 'goat', 'public', 'cpp', 'manifest.cc'),
2541 [
2542 '#include "services/goat/public/cpp/manifest.h"',
2543 'const service_manager::Manifest& GetManifest() {}',
2544 ])]
Daniel Chengd88244472022-05-16 09:08:472545 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342546 self._injectFakeChangeOwnerAndReviewers(
2547 mock_input_api, '[email protected]', ['[email protected]'])
Ken Rockot9f668262018-12-21 18:56:362548 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362549 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362550 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252551 self.assertEqual(1, len(errors))
2552 self.assertTrue(errors[0].message.replace('\\', '/').startswith(
2553 'Found missing OWNERS lines for security-sensitive files. '
2554 'Please add the following lines to services/goat/public/cpp/OWNERS:'))
Daniel Chenga37c03db2022-05-12 17:20:342555 self.assertEqual(['[email protected]'], mock_output_api.more_cc)
Ken Rockot9f668262018-12-21 18:56:362556
2557 def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
Daniel Cheng171dad8d2022-05-21 00:40:252558 mock_input_api = self._createMockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342559 self._injectFakeChangeOwnerAndReviewers(
2560 mock_input_api, '[email protected]', ['[email protected]'])
Ken Rockot9f668262018-12-21 18:56:362561 mock_input_api.files = [
2562 MockAffectedFile('some/non/service/thing/foo_manifest.cc',
2563 [
2564 'const char kNoEnforcement[] = "not a manifest!";',
2565 ])]
2566 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362567 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032568 mock_input_api, mock_output_api)
2569 self.assertEqual([], errors)
Daniel Chenga37c03db2022-05-12 17:20:342570 self.assertEqual([], mock_output_api.more_cc)
Wez17c66962020-04-29 15:26:032571
2572
Daniel Chenga37c03db2022-05-12 17:20:342573class FuchsiaSecurityOwnerTest(_SecurityOwnersTestCase):
Wez17c66962020-04-29 15:26:032574 def testFidlChangeNeedsSecurityOwner(self):
Daniel Cheng171dad8d2022-05-21 00:40:252575 mock_input_api = self._createMockInputApi()
Wez17c66962020-04-29 15:26:032576 mock_input_api.files = [
2577 MockAffectedFile('potentially/scary/ipc.fidl',
2578 [
2579 'library test.fidl'
2580 ])]
Daniel Chengd88244472022-05-16 09:08:472581 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342582 self._injectFakeChangeOwnerAndReviewers(
2583 mock_input_api, '[email protected]', ['[email protected]'])
Wez17c66962020-04-29 15:26:032584 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362585 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032586 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252587 self.assertEqual(1, len(errors))
2588 self.assertTrue(errors[0].message.replace('\\', '/').startswith(
2589 'Found missing OWNERS lines for security-sensitive files. '
2590 'Please add the following lines to potentially/scary/OWNERS:'))
Wez17c66962020-04-29 15:26:032591
2592 def testComponentManifestV1ChangeNeedsSecurityOwner(self):
Daniel Cheng171dad8d2022-05-21 00:40:252593 mock_input_api = self._createMockInputApi()
Wez17c66962020-04-29 15:26:032594 mock_input_api.files = [
2595 MockAffectedFile('potentially/scary/v2_manifest.cmx',
2596 [
2597 '{ "that is no": "manifest!" }'
2598 ])]
Daniel Chengd88244472022-05-16 09:08:472599 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342600 self._injectFakeChangeOwnerAndReviewers(
2601 mock_input_api, '[email protected]', ['[email protected]'])
Wez17c66962020-04-29 15:26:032602 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362603 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032604 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252605 self.assertEqual(1, len(errors))
2606 self.assertTrue(errors[0].message.replace('\\', '/').startswith(
2607 'Found missing OWNERS lines for security-sensitive files. '
2608 'Please add the following lines to potentially/scary/OWNERS:'))
Wez17c66962020-04-29 15:26:032609
2610 def testComponentManifestV2NeedsSecurityOwner(self):
Daniel Cheng171dad8d2022-05-21 00:40:252611 mock_input_api = self._createMockInputApi()
Wez17c66962020-04-29 15:26:032612 mock_input_api.files = [
2613 MockAffectedFile('potentially/scary/v2_manifest.cml',
2614 [
2615 '{ "that is no": "manifest!" }'
2616 ])]
Daniel Chengd88244472022-05-16 09:08:472617 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342618 self._injectFakeChangeOwnerAndReviewers(
2619 mock_input_api, '[email protected]', ['[email protected]'])
Daniel Chengd88244472022-05-16 09:08:472620 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362621 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032622 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252623 self.assertEqual(1, len(errors))
2624 self.assertTrue(errors[0].message.replace('\\', '/').startswith(
2625 'Found missing OWNERS lines for security-sensitive files. '
2626 'Please add the following lines to potentially/scary/OWNERS:'))
Wez17c66962020-04-29 15:26:032627
Joshua Peraza1ca6d392020-12-08 00:14:092628 def testThirdPartyTestsDoNotRequireSecurityOwner(self):
2629 mock_input_api = MockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342630 self._injectFakeChangeOwnerAndReviewers(
2631 mock_input_api, '[email protected]', ['[email protected]'])
Joshua Peraza1ca6d392020-12-08 00:14:092632 mock_input_api.files = [
2633 MockAffectedFile('third_party/crashpad/test/tests.cmx',
2634 [
2635 'const char kNoEnforcement[] = "Security?!? Pah!";',
2636 ])]
2637 mock_output_api = MockOutputApi()
2638 errors = PRESUBMIT.CheckSecurityOwners(
2639 mock_input_api, mock_output_api)
2640 self.assertEqual([], errors)
2641
Wez17c66962020-04-29 15:26:032642 def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2643 mock_input_api = MockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342644 self._injectFakeChangeOwnerAndReviewers(
2645 mock_input_api, '[email protected]', ['[email protected]'])
Wez17c66962020-04-29 15:26:032646 mock_input_api.files = [
2647 MockAffectedFile('some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',
2648 [
2649 'const char kNoEnforcement[] = "Security?!? Pah!";',
2650 ])]
2651 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362652 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362653 mock_input_api, mock_output_api)
2654 self.assertEqual([], errors)
2655
Daniel Cheng13ca61a882017-08-25 15:11:252656
Daniel Chenga37c03db2022-05-12 17:20:342657class SecurityChangeTest(_SecurityOwnersTestCase):
Alex Goughbc964dd2020-06-15 17:52:372658 def testDiffGetServiceSandboxType(self):
Robert Sesek2c905332020-05-06 23:17:132659 mock_input_api = MockInputApi()
2660 mock_input_api.files = [
2661 MockAffectedFile(
2662 'services/goat/teleporter_host.cc',
2663 [
Alex Goughbc964dd2020-06-15 17:52:372664 'template <>',
2665 'inline content::SandboxType',
2666 'content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {',
2667 '#if defined(OS_WIN)',
2668 ' return SandboxType::kGoaty;',
2669 '#else',
2670 ' return SandboxType::kNoSandbox;',
2671 '#endif // !defined(OS_WIN)',
2672 '}'
Robert Sesek2c905332020-05-06 23:17:132673 ]
2674 ),
2675 ]
2676 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2677 mock_input_api)
2678 self.assertEqual({
2679 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372680 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132681 ])},
2682 files_to_functions)
2683
2684 def testDiffRemovingLine(self):
2685 mock_input_api = MockInputApi()
Daniel Cheng99f90e6b2023-11-28 22:54:402686 mock_file = MockAffectedFile('services/goat/teleporter_host.cc', '')
Robert Sesek2c905332020-05-06 23:17:132687 mock_file._scm_diff = """--- old 2020-05-04 14:08:25.000000000 -0400
2688+++ new 2020-05-04 14:08:32.000000000 -0400
2689@@ -1,5 +1,4 @@
Alex Goughbc964dd2020-06-15 17:52:372690 template <>
2691 inline content::SandboxType
2692-content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {
2693 #if defined(OS_WIN)
2694 return SandboxType::kGoaty;
Robert Sesek2c905332020-05-06 23:17:132695"""
2696 mock_input_api.files = [mock_file]
2697 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2698 mock_input_api)
2699 self.assertEqual({
2700 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372701 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132702 ])},
2703 files_to_functions)
2704
2705 def testChangeOwnersMissing(self):
Daniel Cheng171dad8d2022-05-21 00:40:252706 mock_input_api = self._createMockInputApi()
Daniel Chengd88244472022-05-16 09:08:472707 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342708 self._injectFakeChangeOwnerAndReviewers(
2709 mock_input_api, '[email protected]', ['[email protected]'])
Robert Sesek2c905332020-05-06 23:17:132710 mock_input_api.is_committing = False
2711 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372712 MockAffectedFile('file.cc', ['GetServiceSandboxType<Goat>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132713 ]
2714 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362715 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592716 self.assertEqual(1, len(result))
2717 self.assertEqual(result[0].type, 'notify')
2718 self.assertEqual(result[0].message,
Daniel Chenga37c03db2022-05-12 17:20:342719 'The following files change calls to security-sensitive functions\n' \
Robert Sesek2c905332020-05-06 23:17:132720 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2721 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372722 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132723
2724 def testChangeOwnersMissingAtCommit(self):
Daniel Cheng171dad8d2022-05-21 00:40:252725 mock_input_api = self._createMockInputApi()
Daniel Chengd88244472022-05-16 09:08:472726 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342727 self._injectFakeChangeOwnerAndReviewers(
2728 mock_input_api, '[email protected]', ['[email protected]'])
Robert Sesek2c905332020-05-06 23:17:132729 mock_input_api.is_committing = True
Daniel Cheng3008dc12022-05-13 04:02:112730 mock_input_api.dry_run = False
Robert Sesek2c905332020-05-06 23:17:132731 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372732 MockAffectedFile('file.cc', ['GetServiceSandboxType<mojom::Goat>()'])
Robert Sesek2c905332020-05-06 23:17:132733 ]
2734 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362735 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592736 self.assertEqual(1, len(result))
2737 self.assertEqual(result[0].type, 'error')
2738 self.assertEqual(result[0].message,
Daniel Chenga37c03db2022-05-12 17:20:342739 'The following files change calls to security-sensitive functions\n' \
Robert Sesek2c905332020-05-06 23:17:132740 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2741 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372742 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132743
2744 def testChangeOwnersPresent(self):
Daniel Cheng171dad8d2022-05-21 00:40:252745 mock_input_api = self._createMockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342746 self._injectFakeChangeOwnerAndReviewers(
2747 mock_input_api, '[email protected]',
2748 ['[email protected]', '[email protected]'])
Robert Sesek2c905332020-05-06 23:17:132749 mock_input_api.files = [
2750 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2751 ]
2752 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362753 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592754 self.assertEqual(0, len(result))
Robert Sesek2c905332020-05-06 23:17:132755
2756 def testChangeOwnerIsSecurityOwner(self):
Daniel Cheng171dad8d2022-05-21 00:40:252757 mock_input_api = self._createMockInputApi()
Daniel Chengd88244472022-05-16 09:08:472758 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342759 self._injectFakeChangeOwnerAndReviewers(
2760 mock_input_api, '[email protected]', ['[email protected]'])
Robert Sesek2c905332020-05-06 23:17:132761 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372762 MockAffectedFile('file.cc', ['GetServiceSandboxType<T>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132763 ]
2764 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362765 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592766 self.assertEqual(1, len(result))
Robert Sesek2c905332020-05-06 23:17:132767
2768
Mario Sanchez Prada2472cab2019-09-18 10:58:312769class BannedTypeCheckTest(unittest.TestCase):
Clement Yan9b330cb2022-11-17 05:25:292770 def testBannedJsFunctions(self):
2771 input_api = MockInputApi()
2772 input_api.files = [
2773 MockFile('ash/webui/file.js',
2774 ['chrome.send(something);']),
2775 MockFile('some/js/ok/file.js',
2776 ['chrome.send(something);']),
2777 ]
2778
2779 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
2780
2781 self.assertEqual(1, len(results))
2782 self.assertTrue('ash/webui/file.js' in results[0].message)
2783 self.assertFalse('some/js/ok/file.js' in results[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542784
Min Qinbc44383c2023-02-22 17:25:262785 def testBannedJavaFunctions(self):
2786 input_api = MockInputApi()
2787 input_api.files = [
2788 MockFile('some/java/problematic/diskread.java',
2789 ['StrictMode.allowThreadDiskReads();']),
2790 MockFile('some/java/problematic/diskwrite.java',
2791 ['StrictMode.allowThreadDiskWrites();']),
2792 MockFile('some/java/ok/diskwrite.java',
2793 ['StrictModeContext.allowDiskWrites();']),
2794 MockFile('some/java/problematic/waitidleforsync.java',
2795 ['instrumentation.waitForIdleSync();']),
2796 MockFile('some/java/problematic/registerreceiver.java',
2797 ['context.registerReceiver();']),
2798 MockFile('some/java/problematic/property.java',
2799 ['new Property<abc, Integer>;']),
2800 MockFile('some/java/problematic/requestlayout.java',
2801 ['requestLayout();']),
2802 MockFile('some/java/problematic/lastprofile.java',
Ted Chocf486e3f2024-02-17 05:37:032803 ['ProfileManager.getLastUsedRegularProfile();']),
Min Qinbc44383c2023-02-22 17:25:262804 MockFile('some/java/problematic/getdrawable1.java',
2805 ['ResourcesCompat.getDrawable();']),
2806 MockFile('some/java/problematic/getdrawable2.java',
2807 ['getResources().getDrawable();']),
2808 ]
2809
2810 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
2811 self.assertEqual(2, len(errors))
2812 self.assertTrue('some/java/problematic/diskread.java' in errors[0].message)
2813 self.assertTrue('some/java/problematic/diskwrite.java' in errors[0].message)
2814 self.assertFalse('some/java/ok/diskwrite.java' in errors[0].message)
2815 self.assertFalse('some/java/ok/diskwrite.java' in errors[1].message)
2816 self.assertTrue('some/java/problematic/waitidleforsync.java' in errors[0].message)
2817 self.assertTrue('some/java/problematic/registerreceiver.java' in errors[1].message)
2818 self.assertTrue('some/java/problematic/property.java' in errors[0].message)
2819 self.assertTrue('some/java/problematic/requestlayout.java' in errors[0].message)
2820 self.assertTrue('some/java/problematic/lastprofile.java' in errors[0].message)
2821 self.assertTrue('some/java/problematic/getdrawable1.java' in errors[0].message)
2822 self.assertTrue('some/java/problematic/getdrawable2.java' in errors[0].message)
2823
Peter Kasting94a56c42019-10-25 21:54:042824 def testBannedCppFunctions(self):
2825 input_api = MockInputApi()
2826 input_api.files = [
2827 MockFile('some/cpp/problematic/file.cc',
2828 ['using namespace std;']),
Oksana Zhuravlovac8222d22019-12-19 19:21:162829 MockFile('third_party/blink/problematic/file.cc',
2830 ['GetInterfaceProvider()']),
Peter Kasting94a56c42019-10-25 21:54:042831 MockFile('some/cpp/ok/file.cc',
2832 ['using std::string;']),
Allen Bauer53b43fb12020-03-12 17:21:472833 MockFile('some/cpp/problematic/file2.cc',
2834 ['set_owned_by_client()']),
danakjd18e8892020-12-17 17:42:012835 MockFile('some/cpp/nocheck/file.cc',
2836 ['using namespace std; // nocheck']),
2837 MockFile('some/cpp/comment/file.cc',
2838 [' // A comment about `using namespace std;`']),
Peter Kasting94a56c42019-10-25 21:54:042839 ]
2840
Saagar Sanghavifceeaae2020-08-12 16:40:362841 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlovac8222d22019-12-19 19:21:162842
2843 # warnings are results[0], errors are results[1]
2844 self.assertEqual(2, len(results))
2845 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2846 self.assertTrue(
2847 'third_party/blink/problematic/file.cc' in results[0].message)
2848 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
Allen Bauer53b43fb12020-03-12 17:21:472849 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
danakjd18e8892020-12-17 17:42:012850 self.assertFalse('some/cpp/nocheck/file.cc' in results[0].message)
2851 self.assertFalse('some/cpp/nocheck/file.cc' in results[1].message)
2852 self.assertFalse('some/cpp/comment/file.cc' in results[0].message)
2853 self.assertFalse('some/cpp/comment/file.cc' in results[1].message)
Peter Kasting94a56c42019-10-25 21:54:042854
Daniel Cheng192683f2022-11-01 20:52:442855 def testBannedCppRandomFunctions(self):
2856 banned_rngs = [
2857 'absl::BitGen',
2858 'absl::InsecureBitGen',
2859 'std::linear_congruential_engine',
2860 'std::mersenne_twister_engine',
2861 'std::subtract_with_carry_engine',
2862 'std::discard_block_engine',
2863 'std::independent_bits_engine',
2864 'std::shuffle_order_engine',
2865 'std::minstd_rand0',
2866 'std::minstd_rand',
2867 'std::mt19937',
2868 'std::mt19937_64',
2869 'std::ranlux24_base',
2870 'std::ranlux48_base',
2871 'std::ranlux24',
2872 'std::ranlux48',
2873 'std::knuth_b',
2874 'std::default_random_engine',
2875 'std::random_device',
2876 ]
2877 for banned_rng in banned_rngs:
2878 input_api = MockInputApi()
2879 input_api.files = [
2880 MockFile('some/cpp/problematic/file.cc',
2881 [f'{banned_rng} engine;']),
2882 MockFile('third_party/blink/problematic/file.cc',
2883 [f'{banned_rng} engine;']),
2884 MockFile('third_party/ok/file.cc',
2885 [f'{banned_rng} engine;']),
2886 ]
2887 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
2888 self.assertEqual(1, len(results), banned_rng)
2889 self.assertTrue('some/cpp/problematic/file.cc' in results[0].message,
2890 banned_rng)
2891 self.assertTrue(
2892 'third_party/blink/problematic/file.cc' in results[0].message,
2893 banned_rng)
2894 self.assertFalse(
2895 'third_party/ok/file.cc' in results[0].message, banned_rng)
2896
Peter K. Lee6c03ccff2019-07-15 14:40:052897 def testBannedIosObjcFunctions(self):
Sylvain Defresnea8b73d252018-02-28 15:45:542898 input_api = MockInputApi()
2899 input_api.files = [
2900 MockFile('some/ios/file.mm',
2901 ['TEST(SomeClassTest, SomeInteraction) {',
2902 '}']),
2903 MockFile('some/mac/file.mm',
2904 ['TEST(SomeClassTest, SomeInteraction) {',
2905 '}']),
2906 MockFile('another/ios_file.mm',
2907 ['class SomeTest : public testing::Test {};']),
Peter K. Lee6c03ccff2019-07-15 14:40:052908 MockFile('some/ios/file_egtest.mm',
2909 ['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
2910 MockFile('some/ios/file_unittest.mm',
2911 ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']),
Sylvain Defresnea8b73d252018-02-28 15:45:542912 ]
2913
Saagar Sanghavifceeaae2020-08-12 16:40:362914 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Sylvain Defresnea8b73d252018-02-28 15:45:542915 self.assertEqual(1, len(errors))
2916 self.assertTrue('some/ios/file.mm' in errors[0].message)
2917 self.assertTrue('another/ios_file.mm' in errors[0].message)
2918 self.assertTrue('some/mac/file.mm' not in errors[0].message)
Peter K. Lee6c03ccff2019-07-15 14:40:052919 self.assertTrue('some/ios/file_egtest.mm' in errors[0].message)
2920 self.assertTrue('some/ios/file_unittest.mm' not in errors[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542921
Carlos Knippschildab192b8c2019-04-08 20:02:382922 def testBannedMojoFunctions(self):
2923 input_api = MockInputApi()
2924 input_api.files = [
Oksana Zhuravlovafd247772019-05-16 16:57:292925 MockFile('some/cpp/problematic/file2.cc',
2926 ['mojo::ConvertTo<>']),
Oksana Zhuravlovafd247772019-05-16 16:57:292927 MockFile('third_party/blink/ok/file3.cc',
2928 ['mojo::ConvertTo<>']),
2929 MockFile('content/renderer/ok/file3.cc',
2930 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382931 ]
2932
Saagar Sanghavifceeaae2020-08-12 16:40:362933 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222934
2935 # warnings are results[0], errors are results[1]
Robert Sesek351d2d52021-02-02 01:47:072936 self.assertEqual(1, len(results))
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222937 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222938 self.assertTrue('third_party/blink/ok/file3.cc' not in results[0].message)
2939 self.assertTrue('content/renderer/ok/file3.cc' not in results[0].message)
Carlos Knippschildab192b8c2019-04-08 20:02:382940
Daniel Cheng92c15e32022-03-16 17:48:222941 def testBannedMojomPatterns(self):
2942 input_api = MockInputApi()
2943 input_api.files = [
2944 MockFile('bad.mojom',
2945 ['struct Bad {',
2946 ' handle<shared_buffer> buffer;',
2947 '};']),
2948 MockFile('good.mojom',
2949 ['struct Good {',
2950 ' mojo_base.mojom.ReadOnlySharedMemoryRegion region1;',
2951 ' mojo_base.mojom.WritableSharedMemoryRegion region2;',
2952 ' mojo_base.mojom.UnsafeSharedMemoryRegion region3;',
2953 '};']),
2954 ]
2955
2956 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
2957
2958 # warnings are results[0], errors are results[1]
2959 self.assertEqual(1, len(results))
2960 self.assertTrue('bad.mojom' in results[0].message)
2961 self.assertTrue('good.mojom' not in results[0].message)
2962
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272963class NoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:242964 def testTruePositives(self):
2965 mock_input_api = MockInputApi()
2966 mock_input_api.files = [
2967 MockFile('some/path/foo.cc', ['foo_for_testing();']),
2968 MockFile('some/path/foo.mm', ['FooForTesting();']),
2969 MockFile('some/path/foo.cxx', ['FooForTests();']),
2970 MockFile('some/path/foo.cpp', ['foo_for_test();']),
2971 ]
2972
Saagar Sanghavifceeaae2020-08-12 16:40:362973 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242974 mock_input_api, MockOutputApi())
2975 self.assertEqual(1, len(results))
2976 self.assertEqual(4, len(results[0].items))
2977 self.assertTrue('foo.cc' in results[0].items[0])
2978 self.assertTrue('foo.mm' in results[0].items[1])
2979 self.assertTrue('foo.cxx' in results[0].items[2])
2980 self.assertTrue('foo.cpp' in results[0].items[3])
2981
2982 def testFalsePositives(self):
2983 mock_input_api = MockInputApi()
2984 mock_input_api.files = [
2985 MockFile('some/path/foo.h', ['foo_for_testing();']),
2986 MockFile('some/path/foo.mm', ['FooForTesting() {']),
2987 MockFile('some/path/foo.cc', ['::FooForTests();']),
2988 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
Andrew Grieve40f451d2023-07-06 19:46:512989 MockFile('some/path/foo.cxx', ['foo_for_test(); // IN-TEST']),
Vaclav Brozekf01ed502018-03-16 19:38:242990 ]
2991
Saagar Sanghavifceeaae2020-08-12 16:40:362992 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242993 mock_input_api, MockOutputApi())
2994 self.assertEqual(0, len(results))
2995
James Cook1b4dc132021-03-09 22:45:132996 def testAllowedFiles(self):
2997 mock_input_api = MockInputApi()
2998 mock_input_api.files = [
2999 MockFile('path/foo_unittest.cc', ['foo_for_testing();']),
3000 MockFile('path/bar_unittest_mac.cc', ['foo_for_testing();']),
3001 MockFile('path/baz_unittests.cc', ['foo_for_testing();']),
3002 ]
3003
3004 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
3005 mock_input_api, MockOutputApi())
3006 self.assertEqual(0, len(results))
3007
Vaclav Brozekf01ed502018-03-16 19:38:243008
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:273009class NoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:233010 def testTruePositives(self):
3011 mock_input_api = MockInputApi()
3012 mock_input_api.files = [
3013 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
3014 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:393015 MockFile('dir/java/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:233016 MockFile('dir/java/src/mult.java', [
3017 'int x = SomethingLongHere()',
3018 ' * SomethingLongHereForTesting();'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:393019 ])
Vaclav Brozek7dbc28c2018-03-27 08:35:233020 ]
3021
Saagar Sanghavifceeaae2020-08-12 16:40:363022 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:233023 mock_input_api, MockOutputApi())
3024 self.assertEqual(1, len(results))
3025 self.assertEqual(4, len(results[0].items))
3026 self.assertTrue('foo.java' in results[0].items[0])
3027 self.assertTrue('bar.java' in results[0].items[1])
3028 self.assertTrue('baz.java' in results[0].items[2])
3029 self.assertTrue('mult.java' in results[0].items[3])
3030
3031 def testFalsePositives(self):
3032 mock_input_api = MockInputApi()
3033 mock_input_api.files = [
3034 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
3035 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
3036 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
3037 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
Sky Malice9e6d6032020-10-15 22:49:553038 MockFile('dir/java/src/bar3.java', ['@VisibleForTesting']),
3039 MockFile('dir/java/src/bar4.java', ['@VisibleForTesting()']),
3040 MockFile('dir/java/src/bar5.java', [
3041 '@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)'
3042 ]),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:393043 MockFile('dir/javatests/src/baz.java', ['FooForTest(', 'y', ');']),
3044 MockFile('dir/junit/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:233045 MockFile('dir/junit/src/javadoc.java', [
3046 '/** Use FooForTest(); to obtain foo in tests.'
3047 ' */'
3048 ]),
3049 MockFile('dir/junit/src/javadoc2.java', [
3050 '/** ',
3051 ' * Use FooForTest(); to obtain foo in tests.'
3052 ' */'
3053 ]),
Andrew Grieve40f451d2023-07-06 19:46:513054 MockFile('dir/java/src/bar6.java', ['FooForTesting(); // IN-TEST']),
Vaclav Brozek7dbc28c2018-03-27 08:35:233055 ]
3056
Saagar Sanghavifceeaae2020-08-12 16:40:363057 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:233058 mock_input_api, MockOutputApi())
3059 self.assertEqual(0, len(results))
3060
3061
Mohamed Heikald048240a2019-11-12 16:57:373062class NewImagesWarningTest(unittest.TestCase):
3063 def testTruePositives(self):
3064 mock_input_api = MockInputApi()
3065 mock_input_api.files = [
3066 MockFile('dir/android/res/drawable/foo.png', []),
3067 MockFile('dir/android/res/drawable-v21/bar.svg', []),
3068 MockFile('dir/android/res/mipmap-v21-en/baz.webp', []),
3069 MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png', []),
3070 ]
3071
3072 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
3073 self.assertEqual(1, len(results))
3074 self.assertEqual(4, len(results[0].items))
3075 self.assertTrue('foo.png' in results[0].items[0].LocalPath())
3076 self.assertTrue('bar.svg' in results[0].items[1].LocalPath())
3077 self.assertTrue('baz.webp' in results[0].items[2].LocalPath())
3078 self.assertTrue('foobar.png' in results[0].items[3].LocalPath())
3079
3080 def testFalsePositives(self):
3081 mock_input_api = MockInputApi()
3082 mock_input_api.files = [
3083 MockFile('dir/pngs/README.md', []),
3084 MockFile('java/test/res/drawable/foo.png', []),
3085 MockFile('third_party/blink/foo.png', []),
3086 MockFile('dir/third_party/libpng/src/foo.cc', ['foobar']),
3087 MockFile('dir/resources.webp/.gitignore', ['foo.png']),
3088 ]
3089
3090 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
3091 self.assertEqual(0, len(results))
3092
Evan Stade7cd4a2c2022-08-04 23:37:253093class ProductIconsTest(unittest.TestCase):
3094 def test(self):
3095 mock_input_api = MockInputApi()
3096 mock_input_api.files = [
3097 MockFile('components/vector_icons/google_jetpack.icon', []),
3098 MockFile('components/vector_icons/generic_jetpack.icon', []),
3099 ]
3100
3101 results = PRESUBMIT.CheckNoProductIconsAddedToPublicRepo(mock_input_api, MockOutputApi())
3102 self.assertEqual(1, len(results))
3103 self.assertEqual(1, len(results[0].items))
3104 self.assertTrue('google_jetpack.icon' in results[0].items[0])
Mohamed Heikald048240a2019-11-12 16:57:373105
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:273106class CheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:053107 def testTruePositivesNullptr(self):
3108 mock_input_api = MockInputApi()
3109 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:163110 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
3111 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
Vaclav Brozek851d9602018-04-04 16:13:053112 ]
3113
Saagar Sanghavifceeaae2020-08-12 16:40:363114 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:053115 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:163116 self.assertTrue('nullptr' in results[0].message)
Vaclav Brozek851d9602018-04-04 16:13:053117 self.assertEqual(2, len(results[0].items))
3118 self.assertTrue('baz.cc' in results[0].items[0])
3119 self.assertTrue('baz-p.cc' in results[0].items[1])
3120
3121 def testTruePositivesConstructor(self):
Vaclav Brozek52e18bf2018-04-03 07:05:243122 mock_input_api = MockInputApi()
3123 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:163124 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
3125 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
3126 MockFile('dir/mult.cc', [
Vaclav Brozek95face62018-04-04 14:15:113127 'return',
3128 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
3129 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:163130 MockFile('dir/mult2.cc', [
Vaclav Brozek95face62018-04-04 14:15:113131 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
3132 ' std::unique_ptr<T>(foo);'
3133 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:163134 MockFile('dir/mult3.cc', [
Vaclav Brozek95face62018-04-04 14:15:113135 'bar = std::unique_ptr<T>(',
3136 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
3137 ]),
Vaclav Brozekb7fadb692018-08-30 06:39:533138 MockFile('dir/multi_arg.cc', [
3139 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']),
Vaclav Brozek52e18bf2018-04-03 07:05:243140 ]
3141
Saagar Sanghavifceeaae2020-08-12 16:40:363142 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:053143 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:163144 self.assertTrue('std::make_unique' in results[0].message)
Vaclav Brozekb7fadb692018-08-30 06:39:533145 self.assertEqual(6, len(results[0].items))
Vaclav Brozek851d9602018-04-04 16:13:053146 self.assertTrue('foo.cc' in results[0].items[0])
3147 self.assertTrue('bar.mm' in results[0].items[1])
3148 self.assertTrue('mult.cc' in results[0].items[2])
3149 self.assertTrue('mult2.cc' in results[0].items[3])
3150 self.assertTrue('mult3.cc' in results[0].items[4])
Vaclav Brozekb7fadb692018-08-30 06:39:533151 self.assertTrue('multi_arg.cc' in results[0].items[5])
Vaclav Brozek52e18bf2018-04-03 07:05:243152
3153 def testFalsePositives(self):
3154 mock_input_api = MockInputApi()
3155 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:163156 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
3157 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
3158 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
3159 MockFile('dir/baz.cc', [
Vaclav Brozek52e18bf2018-04-03 07:05:243160 'std::unique_ptr<T> result = std::make_unique<T>();'
3161 ]),
Vaclav Brozeka54c528b2018-04-06 19:23:553162 MockFile('dir/baz2.cc', [
3163 'std::unique_ptr<T> result = std::make_unique<T>('
3164 ]),
3165 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
3166 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
Glen Robertson9142ffd72024-05-16 01:37:473167 # Changed line is inside a multiline template block.
3168 MockFile('dir/template.cc', [' std::unique_ptr<T>>(']),
3169 MockFile('dir/template2.cc', [' std::unique_ptr<T>>()']),
Vaclav Brozekb7fadb692018-08-30 06:39:533170
3171 # Two-argument invocation of std::unique_ptr is exempt because there is
3172 # no equivalent using std::make_unique.
3173 MockFile('dir/multi_arg.cc', [
3174 'auto p = std::unique_ptr<T, D>(new T(), D());']),
Vaclav Brozek52e18bf2018-04-03 07:05:243175 ]
3176
Saagar Sanghavifceeaae2020-08-12 16:40:363177 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Glen Robertson9142ffd72024-05-16 01:37:473178 self.assertEqual([], results)
Vaclav Brozek52e18bf2018-04-03 07:05:243179
Danil Chapovalov3518f362018-08-11 16:13:433180class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
3181 def testBlocksDirectIncludes(self):
3182 mock_input_api = MockInputApi()
3183 mock_input_api.files = [
3184 MockFile('dir/foo_win.cc', ['#include "shlwapi.h"']),
3185 MockFile('dir/bar.h', ['#include <propvarutil.h>']),
3186 MockFile('dir/baz.h', ['#include <atlbase.h>']),
3187 MockFile('dir/jumbo.h', ['#include "sphelper.h"']),
3188 ]
Aleksey Khoroshilov9b28c032022-06-03 16:35:323189 results = PRESUBMIT.CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:593190 self.assertEqual(1, len(results))
3191 self.assertEqual(4, len(results[0].items))
Danil Chapovalov3518f362018-08-11 16:13:433192 self.assertTrue('StrCat' in results[0].message)
3193 self.assertTrue('foo_win.cc' in results[0].items[0])
3194 self.assertTrue('bar.h' in results[0].items[1])
3195 self.assertTrue('baz.h' in results[0].items[2])
3196 self.assertTrue('jumbo.h' in results[0].items[3])
3197
3198 def testAllowsToIncludeWrapper(self):
3199 mock_input_api = MockInputApi()
3200 mock_input_api.files = [
3201 MockFile('dir/baz_win.cc', ['#include "base/win/shlwapi.h"']),
3202 MockFile('dir/baz-win.h', ['#include "base/win/atl.h"']),
3203 ]
Aleksey Khoroshilov9b28c032022-06-03 16:35:323204 results = PRESUBMIT.CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:593205 self.assertEqual(0, len(results))
Danil Chapovalov3518f362018-08-11 16:13:433206
3207 def testAllowsToCreateWrapper(self):
3208 mock_input_api = MockInputApi()
3209 mock_input_api.files = [
3210 MockFile('base/win/shlwapi.h', [
3211 '#include <shlwapi.h>',
3212 '#include "base/win/windows_defines.inc"']),
3213 ]
Aleksey Khoroshilov9b28c032022-06-03 16:35:323214 results = PRESUBMIT.CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
3215 self.assertEqual(0, len(results))
3216
3217 def testIgnoresNonImplAndHeaders(self):
3218 mock_input_api = MockInputApi()
3219 mock_input_api.files = [
3220 MockFile('dir/foo_win.txt', ['#include "shlwapi.h"']),
3221 MockFile('dir/bar.asm', ['#include <propvarutil.h>']),
3222 ]
3223 results = PRESUBMIT.CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:593224 self.assertEqual(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:243225
Mustafa Emre Acer51f2f742020-03-09 19:41:123226
Rainhard Findlingfc31844c52020-05-15 09:58:263227class StringTest(unittest.TestCase):
3228 """Tests ICU syntax check and translation screenshots check."""
3229
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143230 # An empty grd file.
3231 OLD_GRD_CONTENTS = """<?xml version="1.0" encoding="UTF-8"?>
3232 <grit latest_public_release="1" current_release="1">
3233 <release seq="1">
3234 <messages></messages>
3235 </release>
3236 </grit>
3237 """.splitlines()
3238 # A grd file with a single message.
3239 NEW_GRD_CONTENTS1 = """<?xml version="1.0" encoding="UTF-8"?>
3240 <grit latest_public_release="1" current_release="1">
3241 <release seq="1">
3242 <messages>
3243 <message name="IDS_TEST1">
3244 Test string 1
3245 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:483246 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE1"
3247 translateable="false">
3248 Non translateable message 1, should be ignored
3249 </message>
Mustafa Emre Acered1a48962020-06-30 19:15:393250 <message name="IDS_TEST_STRING_ACCESSIBILITY"
Mustafa Emre Acerd3ca8be2020-07-07 22:35:343251 is_accessibility_with_no_ui="true">
Mustafa Emre Acered1a48962020-06-30 19:15:393252 Accessibility label 1, should be ignored
3253 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143254 </messages>
3255 </release>
3256 </grit>
3257 """.splitlines()
3258 # A grd file with two messages.
3259 NEW_GRD_CONTENTS2 = """<?xml version="1.0" encoding="UTF-8"?>
3260 <grit latest_public_release="1" current_release="1">
3261 <release seq="1">
3262 <messages>
3263 <message name="IDS_TEST1">
3264 Test string 1
3265 </message>
3266 <message name="IDS_TEST2">
3267 Test string 2
3268 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:483269 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE2"
3270 translateable="false">
3271 Non translateable message 2, should be ignored
3272 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143273 </messages>
3274 </release>
3275 </grit>
3276 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:263277 # A grd file with one ICU syntax message without syntax errors.
3278 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1 = """<?xml version="1.0" encoding="UTF-8"?>
3279 <grit latest_public_release="1" current_release="1">
3280 <release seq="1">
3281 <messages>
3282 <message name="IDS_TEST1">
3283 {NUM, plural,
3284 =1 {Test text for numeric one}
3285 other {Test text for plural with {NUM} as number}}
3286 </message>
3287 </messages>
3288 </release>
3289 </grit>
3290 """.splitlines()
3291 # A grd file with one ICU syntax message without syntax errors.
3292 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2 = """<?xml version="1.0" encoding="UTF-8"?>
3293 <grit latest_public_release="1" current_release="1">
3294 <release seq="1">
3295 <messages>
3296 <message name="IDS_TEST1">
3297 {NUM, plural,
3298 =1 {Different test text for numeric one}
3299 other {Different test text for plural with {NUM} as number}}
3300 </message>
3301 </messages>
3302 </release>
3303 </grit>
3304 """.splitlines()
Rainhard Findling3cde3ef02024-02-05 18:40:323305 # A grd file with multiple ICU syntax messages without syntax errors.
3306 NEW_GRD_CONTENTS_ICU_SYNTAX_OK3 = """<?xml version="1.0" encoding="UTF-8"?>
3307 <grit latest_public_release="1" current_release="1">
3308 <release seq="1">
3309 <messages>
3310 <message name="IDS_TEST1">
3311 {NUM, plural,
3312 =0 {New test text for numeric zero}
3313 =1 {Different test text for numeric one}
3314 =2 {New test text for numeric two}
3315 =3 {New test text for numeric three}
3316 other {Different test text for plural with {NUM} as number}}
3317 </message>
3318 </messages>
3319 </release>
3320 </grit>
3321 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:263322 # A grd file with one ICU syntax message with syntax errors (misses a comma).
3323 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
3324 <grit latest_public_release="1" current_release="1">
3325 <release seq="1">
3326 <messages>
3327 <message name="IDS_TEST1">
3328 {NUM, plural
3329 =1 {Test text for numeric one}
3330 other {Test text for plural with {NUM} as number}}
3331 </message>
3332 </messages>
3333 </release>
3334 </grit>
3335 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143336
meacerff8a9b62019-12-10 19:43:583337 OLD_GRDP_CONTENTS = (
3338 '<?xml version="1.0" encoding="utf-8"?>',
3339 '<grit-part>',
3340 '</grit-part>'
3341 )
3342
3343 NEW_GRDP_CONTENTS1 = (
3344 '<?xml version="1.0" encoding="utf-8"?>',
3345 '<grit-part>',
3346 '<message name="IDS_PART_TEST1">',
3347 'Part string 1',
3348 '</message>',
3349 '</grit-part>')
3350
3351 NEW_GRDP_CONTENTS2 = (
3352 '<?xml version="1.0" encoding="utf-8"?>',
3353 '<grit-part>',
3354 '<message name="IDS_PART_TEST1">',
3355 'Part string 1',
3356 '</message>',
3357 '<message name="IDS_PART_TEST2">',
3358 'Part string 2',
3359 '</message>',
3360 '</grit-part>')
3361
Rainhard Findlingd8d04372020-08-13 13:30:093362 NEW_GRDP_CONTENTS3 = (
3363 '<?xml version="1.0" encoding="utf-8"?>',
3364 '<grit-part>',
3365 '<message name="IDS_PART_TEST1" desc="Description with typo.">',
3366 'Part string 1',
3367 '</message>',
3368 '</grit-part>')
3369
3370 NEW_GRDP_CONTENTS4 = (
3371 '<?xml version="1.0" encoding="utf-8"?>',
3372 '<grit-part>',
3373 '<message name="IDS_PART_TEST1" desc="Description with typo fixed.">',
3374 'Part string 1',
3375 '</message>',
3376 '</grit-part>')
3377
Rainhard Findling1a3e71e2020-09-21 07:33:353378 NEW_GRDP_CONTENTS5 = (
3379 '<?xml version="1.0" encoding="utf-8"?>',
3380 '<grit-part>',
3381 '<message name="IDS_PART_TEST1" meaning="Meaning with typo.">',
3382 'Part string 1',
3383 '</message>',
3384 '</grit-part>')
3385
3386 NEW_GRDP_CONTENTS6 = (
3387 '<?xml version="1.0" encoding="utf-8"?>',
3388 '<grit-part>',
3389 '<message name="IDS_PART_TEST1" meaning="Meaning with typo fixed.">',
3390 'Part string 1',
3391 '</message>',
3392 '</grit-part>')
3393
Rainhard Findlingfc31844c52020-05-15 09:58:263394 # A grdp file with one ICU syntax message without syntax errors.
3395 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = (
3396 '<?xml version="1.0" encoding="utf-8"?>',
3397 '<grit-part>',
3398 '<message name="IDS_PART_TEST1">',
3399 '{NUM, plural,',
3400 '=1 {Test text for numeric one}',
3401 'other {Test text for plural with {NUM} as number}}',
3402 '</message>',
3403 '</grit-part>')
3404 # A grdp file with one ICU syntax message without syntax errors.
3405 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2 = (
3406 '<?xml version="1.0" encoding="utf-8"?>',
3407 '<grit-part>',
3408 '<message name="IDS_PART_TEST1">',
3409 '{NUM, plural,',
3410 '=1 {Different test text for numeric one}',
3411 'other {Different test text for plural with {NUM} as number}}',
3412 '</message>',
3413 '</grit-part>')
Rainhard Findling3cde3ef02024-02-05 18:40:323414 # A grdp file with multiple ICU syntax messages without syntax errors.
3415 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK3 = (
3416 '<?xml version="1.0" encoding="utf-8"?>',
3417 '<grit-part>',
3418 '<message name="IDS_PART_TEST1">',
3419 '{NUM, plural,',
3420 '=0 {New test text for numeric zero}',
3421 '=1 {Different test text for numeric one}',
3422 '=2 {New test text for numeric two}',
3423 '=3 {New test text for numeric three}',
3424 'other {Different test text for plural with {NUM} as number}}',
3425 '</message>',
3426 '</grit-part>')
Rainhard Findlingfc31844c52020-05-15 09:58:263427
Rainhard Findling3cde3ef02024-02-05 18:40:323428 # A grdp file with one ICU syntax message with syntax errors (superfluous
3429 # space).
Rainhard Findlingfc31844c52020-05-15 09:58:263430 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR = (
3431 '<?xml version="1.0" encoding="utf-8"?>',
3432 '<grit-part>',
3433 '<message name="IDS_PART_TEST1">',
3434 '{NUM, plural,',
3435 '= 1 {Test text for numeric one}',
3436 'other {Test text for plural with {NUM} as number}}',
3437 '</message>',
3438 '</grit-part>')
3439
Jens Mueller054652c2023-05-10 15:12:303440 VALID_SHA1 = ('0000000000000000000000000000000000000000',)
Mustafa Emre Acerc8a012d2018-07-31 00:00:393441 DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
3442 'changelist. Run '
3443 'tools/translate/upload_screenshots.py to '
3444 'upload them instead:')
Bruce Dawson55776c42022-12-09 17:23:473445 ADD_SIGNATURES_MESSAGE = ('You are adding UI strings.\n'
Mustafa Emre Acerc8a012d2018-07-31 00:00:393446 'To ensure the best translations, take '
3447 'screenshots of the relevant UI '
3448 '(https://g.co/chrome/translation) and add '
3449 'these files to your changelist:')
3450 REMOVE_SIGNATURES_MESSAGE = ('You removed strings associated with these '
3451 'files. Remove:')
Rainhard Findlingfc31844c52020-05-15 09:58:263452 ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
3453 'strings (problems or feedback? Contact '
3454 '[email protected]):')
Jens Mueller054652c2023-05-10 15:12:303455 SHA1_FORMAT_MESSAGE = ('The following files do not seem to contain valid sha1 '
3456 'hashes. Make sure they contain hashes created by '
3457 'tools/translate/upload_screenshots.py:')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143458
3459 def makeInputApi(self, files):
3460 input_api = MockInputApi()
3461 input_api.files = files
meacere7be7532019-10-02 17:41:033462 # Override os_path.exists because the presubmit uses the actual
3463 # os.path.exists.
3464 input_api.CreateMockFileInPath(
3465 [x.LocalPath() for x in input_api.AffectedFiles(include_deletes=True)])
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143466 return input_api
3467
meacerff8a9b62019-12-10 19:43:583468 """ CL modified and added messages, but didn't add any screenshots."""
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143469 def testNoScreenshots(self):
meacerff8a9b62019-12-10 19:43:583470 # No new strings (file contents same). Should not warn.
3471 input_api = self.makeInputApi([
3472 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
3473 self.NEW_GRD_CONTENTS1, action='M'),
3474 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1,
3475 self.NEW_GRDP_CONTENTS1, action='M')])
Gao Shenga79ebd42022-08-08 17:25:593476 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
meacerff8a9b62019-12-10 19:43:583477 self.assertEqual(0, len(warnings))
3478
3479 # Add two new strings. Should have two warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143480 input_api = self.makeInputApi([
3481 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:583482 self.NEW_GRD_CONTENTS1, action='M'),
3483 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
3484 self.NEW_GRDP_CONTENTS1, action='M')])
Gao Shenga79ebd42022-08-08 17:25:593485 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143486 self.assertEqual(1, len(warnings))
Bruce Dawson55776c42022-12-09 17:23:473487 self.assertEqual(self.ADD_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003488 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013489 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583490 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3491 os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
3492 warnings[0].items)
Mustafa Emre Acer36eaad52019-11-12 23:03:343493
meacerff8a9b62019-12-10 19:43:583494 # Add four new strings. Should have four warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213495 input_api = self.makeInputApi([
3496 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:583497 self.OLD_GRD_CONTENTS, action='M'),
3498 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
3499 self.OLD_GRDP_CONTENTS, action='M')])
Gao Shenga79ebd42022-08-08 17:25:593500 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Mustafa Emre Acerad8fb082019-11-19 04:24:213501 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003502 self.assertEqual('error', warnings[0].type)
Bruce Dawson55776c42022-12-09 17:23:473503 self.assertEqual(self.ADD_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583504 self.assertEqual([
3505 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3506 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3507 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3508 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3509 ], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213510
Rainhard Findlingd8d04372020-08-13 13:30:093511 def testModifiedMessageDescription(self):
3512 # CL modified a message description for a message that does not yet have a
Rainhard Findling1a3e71e2020-09-21 07:33:353513 # screenshot. Should not warn.
Rainhard Findlingd8d04372020-08-13 13:30:093514 input_api = self.makeInputApi([
3515 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
3516 self.NEW_GRDP_CONTENTS4, action='M')])
3517 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findling1a3e71e2020-09-21 07:33:353518 self.assertEqual(0, len(warnings))
Rainhard Findlingd8d04372020-08-13 13:30:093519
3520 # CL modified a message description for a message that already has a
3521 # screenshot. Should not warn.
3522 input_api = self.makeInputApi([
3523 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
3524 self.NEW_GRDP_CONTENTS4, action='M'),
3525 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:303526 self.VALID_SHA1, action='A')])
Rainhard Findlingd8d04372020-08-13 13:30:093527 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3528 self.assertEqual(0, len(warnings))
3529
Rainhard Findling1a3e71e2020-09-21 07:33:353530 def testModifiedMessageMeaning(self):
3531 # CL modified a message meaning for a message that does not yet have a
3532 # screenshot. Should warn.
3533 input_api = self.makeInputApi([
3534 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3535 self.NEW_GRDP_CONTENTS6, action='M')])
3536 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3537 self.assertEqual(1, len(warnings))
3538
3539 # CL modified a message meaning for a message that already has a
3540 # screenshot. Should not warn.
3541 input_api = self.makeInputApi([
3542 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3543 self.NEW_GRDP_CONTENTS6, action='M'),
3544 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:303545 self.VALID_SHA1, action='A')])
Rainhard Findling1a3e71e2020-09-21 07:33:353546 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3547 self.assertEqual(0, len(warnings))
3548
Jens Mueller054652c2023-05-10 15:12:303549 def testModifiedIntroducedInvalidSha1(self):
3550 # CL modified a message and the sha1 file changed to invalid
3551 input_api = self.makeInputApi([
3552 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3553 self.NEW_GRDP_CONTENTS6, action='M'),
3554 MockAffectedFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3555 ('some invalid sha1',), self.VALID_SHA1, action='M')])
3556 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3557 self.assertEqual(1, len(warnings))
3558
meacerff8a9b62019-12-10 19:43:583559 def testPngAddedSha1NotAdded(self):
3560 # CL added one new message in a grd file and added the png file associated
3561 # with it, but did not add the corresponding sha1 file. This should warn
3562 # twice:
3563 # - Once for the added png file (because we don't want developers to upload
3564 # actual images)
3565 # - Once for the missing .sha1 file
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143566 input_api = self.makeInputApi([
Mustafa Emre Acerea3e57a2018-12-17 23:51:013567 MockAffectedFile(
3568 'test.grd',
3569 self.NEW_GRD_CONTENTS1,
3570 self.OLD_GRD_CONTENTS,
3571 action='M'),
3572 MockAffectedFile(
Daniel Cheng99f90e6b2023-11-28 22:54:403573 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013574 ])
Gao Shenga79ebd42022-08-08 17:25:593575 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143576 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003577 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143578 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013579 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
3580 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003581 self.assertEqual('error', warnings[1].type)
Bruce Dawson55776c42022-12-09 17:23:473582 self.assertEqual(self.ADD_SIGNATURES_MESSAGE, warnings[1].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013583 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3584 warnings[1].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143585
meacerff8a9b62019-12-10 19:43:583586 # CL added two messages (one in grd, one in grdp) and added the png files
3587 # associated with the messages, but did not add the corresponding sha1
3588 # files. This should warn twice:
3589 # - Once for the added png files (because we don't want developers to upload
3590 # actual images)
3591 # - Once for the missing .sha1 files
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143592 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583593 # Modified files:
Mustafa Emre Acer36eaad52019-11-12 23:03:343594 MockAffectedFile(
3595 'test.grd',
meacerff8a9b62019-12-10 19:43:583596 self.NEW_GRD_CONTENTS1,
Mustafa Emre Acer36eaad52019-11-12 23:03:343597 self.OLD_GRD_CONTENTS,
meacer2308d0742019-11-12 18:15:423598 action='M'),
Mustafa Emre Acer12e7fee2019-11-18 18:49:553599 MockAffectedFile(
meacerff8a9b62019-12-10 19:43:583600 'part.grdp',
3601 self.NEW_GRDP_CONTENTS1,
3602 self.OLD_GRDP_CONTENTS,
3603 action='M'),
3604 # Added files:
3605 MockAffectedFile(
Daniel Cheng99f90e6b2023-11-28 22:54:403606 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A'),
meacerff8a9b62019-12-10 19:43:583607 MockAffectedFile(
Daniel Cheng99f90e6b2023-11-28 22:54:403608 os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary',
meacerff8a9b62019-12-10 19:43:583609 action='A')
Mustafa Emre Acerad8fb082019-11-19 04:24:213610 ])
Gao Shenga79ebd42022-08-08 17:25:593611 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Mustafa Emre Acerad8fb082019-11-19 04:24:213612 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003613 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213614 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583615 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png'),
3616 os.path.join('test_grd', 'IDS_TEST1.png')],
Mustafa Emre Acerad8fb082019-11-19 04:24:213617 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003618 self.assertEqual('error', warnings[0].type)
Bruce Dawson55776c42022-12-09 17:23:473619 self.assertEqual(self.ADD_SIGNATURES_MESSAGE, warnings[1].message)
meacerff8a9b62019-12-10 19:43:583620 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3621 os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3622 warnings[1].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213623
Jens Mueller054652c2023-05-10 15:12:303624
Mustafa Emre Acerad8fb082019-11-19 04:24:213625 def testScreenshotsWithSha1(self):
meacerff8a9b62019-12-10 19:43:583626 # CL added four messages (two each in a grd and grdp) and their
3627 # corresponding .sha1 files. No warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213628 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583629 # Modified files:
Mustafa Emre Acerad8fb082019-11-19 04:24:213630 MockAffectedFile(
3631 'test.grd',
3632 self.NEW_GRD_CONTENTS2,
3633 self.OLD_GRD_CONTENTS,
Mustafa Emre Acer12e7fee2019-11-18 18:49:553634 action='M'),
meacerff8a9b62019-12-10 19:43:583635 MockAffectedFile(
3636 'part.grdp',
3637 self.NEW_GRDP_CONTENTS2,
3638 self.OLD_GRDP_CONTENTS,
3639 action='M'),
3640 # Added files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013641 MockFile(
3642 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:303643 self.VALID_SHA1,
Mustafa Emre Acerea3e57a2018-12-17 23:51:013644 action='A'),
3645 MockFile(
3646 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:303647 ('0000000000000000000000000000000000000000', ''),
meacerff8a9b62019-12-10 19:43:583648 action='A'),
3649 MockFile(
3650 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:303651 self.VALID_SHA1,
meacerff8a9b62019-12-10 19:43:583652 action='A'),
3653 MockFile(
3654 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:303655 self.VALID_SHA1,
meacerff8a9b62019-12-10 19:43:583656 action='A'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013657 ])
Gao Shenga79ebd42022-08-08 17:25:593658 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143659 self.assertEqual([], warnings)
3660
Jens Mueller054652c2023-05-10 15:12:303661
3662 def testScreenshotsWithInvalidSha1(self):
3663 input_api = self.makeInputApi([
3664 # Modified files:
3665 MockAffectedFile(
3666 'test.grd',
3667 self.NEW_GRD_CONTENTS2,
3668 self.OLD_GRD_CONTENTS,
3669 action='M'),
3670 MockAffectedFile(
3671 'part.grdp',
3672 self.NEW_GRDP_CONTENTS2,
3673 self.OLD_GRDP_CONTENTS,
3674 action='M'),
3675 # Added files:
3676 MockFile(
3677 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3678 self.VALID_SHA1,
3679 action='A'),
3680 MockFile(
3681 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3682 ('‰PNG', 'test'),
3683 action='A'),
3684 MockFile(
3685 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3686 self.VALID_SHA1,
3687 action='A'),
3688 MockFile(
3689 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3690 self.VALID_SHA1,
3691 action='A'),
3692 ])
3693 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3694 self.assertEqual(1, len(warnings))
3695 self.assertEqual('error', warnings[0].type)
3696 self.assertEqual(self.SHA1_FORMAT_MESSAGE, warnings[0].message)
3697 self.assertEqual([os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
3698 warnings[0].items)
3699
3700
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143701 def testScreenshotsRemovedWithSha1(self):
meacerff8a9b62019-12-10 19:43:583702 # Replace new contents with old contents in grd and grp files, removing
3703 # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3704 # Should warn to remove the sha1 files associated with these strings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143705 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583706 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013707 MockAffectedFile(
3708 'test.grd',
meacerff8a9b62019-12-10 19:43:583709 self.OLD_GRD_CONTENTS, # new_contents
3710 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013711 action='M'),
meacerff8a9b62019-12-10 19:43:583712 MockAffectedFile(
3713 'part.grdp',
3714 self.OLD_GRDP_CONTENTS, # new_contents
3715 self.NEW_GRDP_CONTENTS2, # old_contents
3716 action='M'),
3717 # Unmodified files:
Jens Mueller054652c2023-05-10 15:12:303718 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
Daniel Cheng99f90e6b2023-11-28 22:54:403719 self.VALID_SHA1, ''),
Jens Mueller054652c2023-05-10 15:12:303720 MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
Daniel Cheng99f90e6b2023-11-28 22:54:403721 self.VALID_SHA1, ''),
meacerff8a9b62019-12-10 19:43:583722 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
Daniel Cheng99f90e6b2023-11-28 22:54:403723 self.VALID_SHA1, ''),
meacerff8a9b62019-12-10 19:43:583724 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Daniel Cheng99f90e6b2023-11-28 22:54:403725 self.VALID_SHA1, '')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013726 ])
Gao Shenga79ebd42022-08-08 17:25:593727 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143728 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003729 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143730 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013731 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583732 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3733 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013734 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3735 os.path.join('test_grd', 'IDS_TEST2.png.sha1')
3736 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143737
meacerff8a9b62019-12-10 19:43:583738 # Same as above, but this time one of the .sha1 files is also removed.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143739 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583740 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013741 MockAffectedFile(
3742 'test.grd',
meacerff8a9b62019-12-10 19:43:583743 self.OLD_GRD_CONTENTS, # new_contents
3744 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013745 action='M'),
meacerff8a9b62019-12-10 19:43:583746 MockAffectedFile(
3747 'part.grdp',
3748 self.OLD_GRDP_CONTENTS, # new_contents
3749 self.NEW_GRDP_CONTENTS2, # old_contents
3750 action='M'),
3751 # Unmodified files:
Jens Mueller054652c2023-05-10 15:12:303752 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
Daniel Cheng99f90e6b2023-11-28 22:54:403753 self.VALID_SHA1, ''),
meacerff8a9b62019-12-10 19:43:583754 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
Daniel Cheng99f90e6b2023-11-28 22:54:403755 self.VALID_SHA1, ''),
meacerff8a9b62019-12-10 19:43:583756 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013757 MockAffectedFile(
3758 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
Daniel Cheng99f90e6b2023-11-28 22:54:403759 '',
3760 'old_contents',
meacerff8a9b62019-12-10 19:43:583761 action='D'),
3762 MockAffectedFile(
3763 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Daniel Cheng99f90e6b2023-11-28 22:54:403764 '',
3765 'old_contents',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013766 action='D')
3767 ])
Gao Shenga79ebd42022-08-08 17:25:593768 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143769 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003770 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143771 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583772 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3773 os.path.join('test_grd', 'IDS_TEST1.png.sha1')
3774 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143775
meacerff8a9b62019-12-10 19:43:583776 # Remove all sha1 files. There should be no warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143777 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583778 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013779 MockAffectedFile(
3780 'test.grd',
3781 self.OLD_GRD_CONTENTS,
3782 self.NEW_GRD_CONTENTS2,
3783 action='M'),
meacerff8a9b62019-12-10 19:43:583784 MockAffectedFile(
3785 'part.grdp',
3786 self.OLD_GRDP_CONTENTS,
3787 self.NEW_GRDP_CONTENTS2,
3788 action='M'),
3789 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013790 MockFile(
3791 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:303792 self.VALID_SHA1,
Mustafa Emre Acerea3e57a2018-12-17 23:51:013793 action='D'),
3794 MockFile(
3795 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:303796 self.VALID_SHA1,
meacerff8a9b62019-12-10 19:43:583797 action='D'),
3798 MockFile(
3799 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:303800 self.VALID_SHA1,
meacerff8a9b62019-12-10 19:43:583801 action='D'),
3802 MockFile(
3803 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:303804 self.VALID_SHA1,
Mustafa Emre Acerea3e57a2018-12-17 23:51:013805 action='D')
3806 ])
Gao Shenga79ebd42022-08-08 17:25:593807 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143808 self.assertEqual([], warnings)
3809
Rainhard Findlingfc31844c52020-05-15 09:58:263810 def testIcuSyntax(self):
3811 # Add valid ICU syntax string. Should not raise an error.
3812 input_api = self.makeInputApi([
3813 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3814 self.NEW_GRD_CONTENTS1, action='M'),
3815 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3816 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363817 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263818 # We expect no ICU syntax errors.
3819 icu_errors = [e for e in results
3820 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3821 self.assertEqual(0, len(icu_errors))
3822
3823 # Valid changes in ICU syntax. Should not raise an error.
3824 input_api = self.makeInputApi([
3825 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3826 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3827 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3828 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363829 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263830 # We expect no ICU syntax errors.
3831 icu_errors = [e for e in results
3832 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3833 self.assertEqual(0, len(icu_errors))
3834
Rainhard Findling3cde3ef02024-02-05 18:40:323835 # Valid changes in ICU syntax. Should not raise an error.
3836 input_api = self.makeInputApi([
3837 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK3,
3838 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3839 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK3,
3840 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
3841 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3842 # We expect no ICU syntax errors.
3843 icu_errors = [e for e in results
3844 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3845 self.assertEqual(0, len(icu_errors))
3846
Rainhard Findlingfc31844c52020-05-15 09:58:263847 # Add invalid ICU syntax strings. Should raise two errors.
3848 input_api = self.makeInputApi([
3849 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3850 self.NEW_GRD_CONTENTS1, action='M'),
3851 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3852 self.NEW_GRD_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363853 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263854 # We expect 2 ICU syntax errors.
3855 icu_errors = [e for e in results
3856 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3857 self.assertEqual(1, len(icu_errors))
3858 self.assertEqual([
3859 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3860 'ICU syntax.',
3861 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3862 ], icu_errors[0].items)
3863
3864 # Change two strings to have ICU syntax errors. Should raise two errors.
3865 input_api = self.makeInputApi([
3866 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3867 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3868 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3869 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363870 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263871 # We expect 2 ICU syntax errors.
3872 icu_errors = [e for e in results
3873 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3874 self.assertEqual(1, len(icu_errors))
3875 self.assertEqual([
3876 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3877 'ICU syntax.',
3878 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3879 ], icu_errors[0].items)
3880
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143881
Mustafa Emre Acer51f2f742020-03-09 19:41:123882class TranslationExpectationsTest(unittest.TestCase):
3883 ERROR_MESSAGE_FORMAT = (
3884 "Failed to get a list of translatable grd files. "
3885 "This happens when:\n"
3886 " - One of the modified grd or grdp files cannot be parsed or\n"
3887 " - %s is not updated.\n"
3888 "Stack:\n"
3889 )
3890 REPO_ROOT = os.path.join('tools', 'translation', 'testdata')
3891 # This lists all .grd files under REPO_ROOT.
3892 EXPECTATIONS = os.path.join(REPO_ROOT,
3893 "translation_expectations.pyl")
3894 # This lists all .grd files under REPO_ROOT except unlisted.grd.
3895 EXPECTATIONS_WITHOUT_UNLISTED_FILE = os.path.join(
3896 REPO_ROOT, "translation_expectations_without_unlisted_file.pyl")
3897
3898 # Tests that the presubmit doesn't return when no grd or grdp files are
3899 # modified.
3900 def testExpectationsNoModifiedGrd(self):
3901 input_api = MockInputApi()
3902 input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:403903 MockAffectedFile('not_used.txt', 'not used', 'not used', action='M')
Mustafa Emre Acer51f2f742020-03-09 19:41:123904 ]
3905 # Fake list of all grd files in the repo. This list is missing all grd/grdps
3906 # under tools/translation/testdata. This is OK because the presubmit won't
3907 # run in the first place since there are no modified grd/grps in input_api.
3908 grd_files = ['doesnt_exist_doesnt_matter.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363909 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123910 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3911 grd_files)
3912 self.assertEqual(0, len(warnings))
3913
3914
3915 # Tests that the list of files passed to the presubmit matches the list of
3916 # files in the expectations.
3917 def testExpectationsSuccess(self):
3918 # Mock input file list needs a grd or grdp file in order to run the
3919 # presubmit. The file itself doesn't matter.
3920 input_api = MockInputApi()
3921 input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:403922 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
Mustafa Emre Acer51f2f742020-03-09 19:41:123923 ]
3924 # List of all grd files in the repo.
3925 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3926 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363927 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123928 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3929 grd_files)
3930 self.assertEqual(0, len(warnings))
3931
3932 # Tests that the presubmit warns when a file is listed in expectations, but
3933 # does not actually exist.
3934 def testExpectationsMissingFile(self):
3935 # Mock input file list needs a grd or grdp file in order to run the
3936 # presubmit.
3937 input_api = MockInputApi()
3938 input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:403939 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
Mustafa Emre Acer51f2f742020-03-09 19:41:123940 ]
3941 # unlisted.grd is listed under tools/translation/testdata but is not
3942 # included in translation expectations.
3943 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363944 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123945 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3946 grd_files)
3947 self.assertEqual(1, len(warnings))
3948 self.assertTrue(warnings[0].message.startswith(
3949 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS))
3950 self.assertTrue(
3951 ("test.grd is listed in the translation expectations, "
3952 "but this grd file does not exist")
3953 in warnings[0].message)
3954
3955 # Tests that the presubmit warns when a file is not listed in expectations but
3956 # does actually exist.
3957 def testExpectationsUnlistedFile(self):
3958 # Mock input file list needs a grd or grdp file in order to run the
3959 # presubmit.
3960 input_api = MockInputApi()
3961 input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:403962 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
Mustafa Emre Acer51f2f742020-03-09 19:41:123963 ]
3964 # unlisted.grd is listed under tools/translation/testdata but is not
3965 # included in translation expectations.
3966 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3967 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363968 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123969 input_api, MockOutputApi(), self.REPO_ROOT,
3970 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3971 self.assertEqual(1, len(warnings))
3972 self.assertTrue(warnings[0].message.startswith(
3973 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3974 self.assertTrue(
3975 ("unlisted.grd appears to be translatable "
3976 "(because it contains <file> or <message> elements), "
3977 "but is not listed in the translation expectations.")
3978 in warnings[0].message)
3979
3980 # Tests that the presubmit warns twice:
3981 # - for a non-existing file listed in expectations
3982 # - for an existing file not listed in expectations
3983 def testMultipleWarnings(self):
3984 # Mock input file list needs a grd or grdp file in order to run the
3985 # presubmit.
3986 input_api = MockInputApi()
3987 input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:403988 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
Mustafa Emre Acer51f2f742020-03-09 19:41:123989 ]
3990 # unlisted.grd is listed under tools/translation/testdata but is not
3991 # included in translation expectations.
3992 # test.grd is not listed under tools/translation/testdata but is included
3993 # in translation expectations.
3994 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363995 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123996 input_api, MockOutputApi(), self.REPO_ROOT,
3997 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3998 self.assertEqual(1, len(warnings))
3999 self.assertTrue(warnings[0].message.startswith(
4000 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
4001 self.assertTrue(
4002 ("unlisted.grd appears to be translatable "
4003 "(because it contains <file> or <message> elements), "
4004 "but is not listed in the translation expectations.")
4005 in warnings[0].message)
4006 self.assertTrue(
4007 ("test.grd is listed in the translation expectations, "
4008 "but this grd file does not exist")
4009 in warnings[0].message)
4010
4011
Dominic Battre033531052018-09-24 15:45:344012class DISABLETypoInTest(unittest.TestCase):
4013
4014 def testPositive(self):
4015 # Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
4016 # where the desire is to disable a test.
4017 tests = [
4018 # Disabled on one platform:
4019 '#if defined(OS_WIN)\n'
4020 '#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
4021 '#else\n'
4022 '#define MAYBE_FoobarTest FoobarTest\n'
4023 '#endif\n',
4024 # Disabled on one platform spread cross lines:
4025 '#if defined(OS_WIN)\n'
4026 '#define MAYBE_FoobarTest \\\n'
4027 ' DISABLE_FoobarTest\n'
4028 '#else\n'
4029 '#define MAYBE_FoobarTest FoobarTest\n'
4030 '#endif\n',
4031 # Disabled on all platforms:
4032 ' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
4033 # Disabled on all platforms but multiple lines
4034 ' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
4035 ]
4036
4037 for test in tests:
4038 mock_input_api = MockInputApi()
4039 mock_input_api.files = [
4040 MockFile('some/path/foo_unittest.cc', test.splitlines()),
4041 ]
4042
Saagar Sanghavifceeaae2020-08-12 16:40:364043 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:344044 MockOutputApi())
4045 self.assertEqual(
4046 1,
4047 len(results),
4048 msg=('expected len(results) == 1 but got %d in test: %s' %
4049 (len(results), test)))
4050 self.assertTrue(
4051 'foo_unittest.cc' in results[0].message,
4052 msg=('expected foo_unittest.cc in message but got %s in test %s' %
4053 (results[0].message, test)))
4054
Gao Shenga79ebd42022-08-08 17:25:594055 def testIgnoreNotTestFiles(self):
Dominic Battre033531052018-09-24 15:45:344056 mock_input_api = MockInputApi()
4057 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:404058 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'),
Dominic Battre033531052018-09-24 15:45:344059 ]
4060
Saagar Sanghavifceeaae2020-08-12 16:40:364061 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:344062 MockOutputApi())
4063 self.assertEqual(0, len(results))
4064
Gao Shenga79ebd42022-08-08 17:25:594065 def testIgnoreDeletedFiles(self):
Katie Df13948e2018-09-25 07:33:444066 mock_input_api = MockInputApi()
4067 mock_input_api.files = [
Daniel Cheng99f90e6b2023-11-28 22:54:404068 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'),
Katie Df13948e2018-09-25 07:33:444069 ]
4070
Saagar Sanghavifceeaae2020-08-12 16:40:364071 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Katie Df13948e2018-09-25 07:33:444072 MockOutputApi())
4073 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:344074
Nina Satragnof7660532021-09-20 18:03:354075class ForgettingMAYBEInTests(unittest.TestCase):
4076 def testPositive(self):
4077 test = (
4078 '#if defined(HAS_ENERGY)\n'
4079 '#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
4080 '#else\n'
4081 '#define MAYBE_CastExplosion CastExplosion\n'
4082 '#endif\n'
4083 'TEST_F(ArchWizard, CastExplosion) {\n'
4084 '#if defined(ARCH_PRIEST_IN_PARTY)\n'
4085 '#define MAYBE_ArchPriest ArchPriest\n'
4086 '#else\n'
4087 '#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
4088 '#endif\n'
4089 'TEST_F(ArchPriest, CastNaturesBounty) {\n'
4090 '#if !defined(CRUSADER_IN_PARTY)\n'
4091 '#define MAYBE_Crusader \\\n'
4092 ' DISABLED_Crusader \n'
4093 '#else\n'
4094 '#define MAYBE_Crusader \\\n'
4095 ' Crusader\n'
4096 '#endif\n'
4097 ' TEST_F(\n'
4098 ' Crusader,\n'
4099 ' CastTaunt) { }\n'
4100 '#if defined(LEARNED_BASIC_SKILLS)\n'
4101 '#define MAYBE_CastSteal \\\n'
4102 ' DISABLED_CastSteal \n'
4103 '#else\n'
4104 '#define MAYBE_CastSteal \\\n'
4105 ' CastSteal\n'
4106 '#endif\n'
4107 ' TEST_F(\n'
4108 ' ThiefClass,\n'
4109 ' CastSteal) { }\n'
4110 )
4111 mock_input_api = MockInputApi()
4112 mock_input_api.files = [
4113 MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
4114 ]
4115 results = PRESUBMIT.CheckForgettingMAYBEInTests(mock_input_api,
4116 MockOutputApi())
4117 self.assertEqual(4, len(results))
4118 self.assertTrue('CastExplosion' in results[0].message)
4119 self.assertTrue('fantasyworld/classes_unittest.cc:2' in results[0].message)
4120 self.assertTrue('ArchPriest' in results[1].message)
4121 self.assertTrue('fantasyworld/classes_unittest.cc:8' in results[1].message)
4122 self.assertTrue('Crusader' in results[2].message)
4123 self.assertTrue('fantasyworld/classes_unittest.cc:14' in results[2].message)
4124 self.assertTrue('CastSteal' in results[3].message)
4125 self.assertTrue('fantasyworld/classes_unittest.cc:24' in results[3].message)
4126
4127 def testNegative(self):
4128 test = (
4129 '#if defined(HAS_ENERGY)\n'
4130 '#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
4131 '#else\n'
4132 '#define MAYBE_CastExplosion CastExplosion\n'
4133 '#endif\n'
4134 'TEST_F(ArchWizard, MAYBE_CastExplosion) {\n'
4135 '#if defined(ARCH_PRIEST_IN_PARTY)\n'
4136 '#define MAYBE_ArchPriest ArchPriest\n'
4137 '#else\n'
4138 '#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
4139 '#endif\n'
4140 'TEST_F(MAYBE_ArchPriest, CastNaturesBounty) {\n'
4141 '#if !defined(CRUSADER_IN_PARTY)\n'
4142 '#define MAYBE_Crusader \\\n'
4143 ' DISABLED_Crusader \n'
4144 '#else\n'
4145 '#define MAYBE_Crusader \\\n'
4146 ' Crusader\n'
4147 '#endif\n'
4148 ' TEST_F(\n'
4149 ' MAYBE_Crusader,\n'
4150 ' CastTaunt) { }\n'
4151 '#if defined(LEARNED_BASIC_SKILLS)\n'
4152 '#define MAYBE_CastSteal \\\n'
4153 ' DISABLED_CastSteal \n'
4154 '#else\n'
4155 '#define MAYBE_CastSteal \\\n'
4156 ' CastSteal\n'
4157 '#endif\n'
4158 ' TEST_F(\n'
4159 ' ThiefClass,\n'
4160 ' MAYBE_CastSteal) { }\n'
4161 )
4162
4163 mock_input_api = MockInputApi()
4164 mock_input_api.files = [
4165 MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
4166 ]
4167 results = PRESUBMIT.CheckForgettingMAYBEInTests(mock_input_api,
4168 MockOutputApi())
4169 self.assertEqual(0, len(results))
Dirk Pranke3c18a382019-03-15 01:07:514170
Max Morozb47503b2019-08-08 21:03:274171class CheckFuzzTargetsTest(unittest.TestCase):
4172
4173 def _check(self, files):
4174 mock_input_api = MockInputApi()
4175 mock_input_api.files = []
4176 for fname, contents in files.items():
4177 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:364178 return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api, MockOutputApi())
Max Morozb47503b2019-08-08 21:03:274179
4180 def testLibFuzzerSourcesIgnored(self):
4181 results = self._check({
4182 "third_party/lib/Fuzzer/FuzzerDriver.cpp": "LLVMFuzzerInitialize",
4183 })
4184 self.assertEqual(results, [])
4185
4186 def testNonCodeFilesIgnored(self):
4187 results = self._check({
4188 "README.md": "LLVMFuzzerInitialize",
4189 })
4190 self.assertEqual(results, [])
4191
4192 def testNoErrorHeaderPresent(self):
4193 results = self._check({
4194 "fuzzer.cc": (
4195 "#include \"testing/libfuzzer/libfuzzer_exports.h\"\n" +
4196 "LLVMFuzzerInitialize"
4197 )
4198 })
4199 self.assertEqual(results, [])
4200
4201 def testErrorMissingHeader(self):
4202 results = self._check({
4203 "fuzzer.cc": "LLVMFuzzerInitialize"
4204 })
4205 self.assertEqual(len(results), 1)
4206 self.assertEqual(results[0].items, ['fuzzer.cc'])
4207
4208
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264209class SetNoParentTest(unittest.TestCase):
John Abd-El-Malekdfd1edc2021-02-24 22:22:404210 def testSetNoParentTopLevelAllowed(self):
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264211 mock_input_api = MockInputApi()
4212 mock_input_api.files = [
4213 MockAffectedFile('goat/OWNERS',
4214 [
4215 'set noparent',
4216 '[email protected]',
John Abd-El-Malekdfd1edc2021-02-24 22:22:404217 ])
4218 ]
4219 mock_output_api = MockOutputApi()
4220 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
4221 self.assertEqual([], errors)
4222
4223 def testSetNoParentMissing(self):
4224 mock_input_api = MockInputApi()
4225 mock_input_api.files = [
4226 MockAffectedFile('services/goat/OWNERS',
4227 [
4228 'set noparent',
4229 '[email protected]',
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264230 'per-file *.json=set noparent',
4231 'per-file *[email protected]',
4232 ])
4233 ]
4234 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:364235 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264236 self.assertEqual(1, len(errors))
4237 self.assertTrue('goat/OWNERS:1' in errors[0].long_text)
4238 self.assertTrue('goat/OWNERS:3' in errors[0].long_text)
4239
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264240 def testSetNoParentWithCorrectRule(self):
4241 mock_input_api = MockInputApi()
4242 mock_input_api.files = [
John Abd-El-Malekdfd1edc2021-02-24 22:22:404243 MockAffectedFile('services/goat/OWNERS',
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264244 [
4245 'set noparent',
4246 'file://ipc/SECURITY_OWNERS',
4247 'per-file *.json=set noparent',
4248 'per-file *.json=file://ipc/SECURITY_OWNERS',
4249 ])
4250 ]
4251 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:364252 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264253 self.assertEqual([], errors)
4254
4255
Ken Rockotc31f4832020-05-29 18:58:514256class MojomStabilityCheckTest(unittest.TestCase):
4257 def runTestWithAffectedFiles(self, affected_files):
4258 mock_input_api = MockInputApi()
4259 mock_input_api.files = affected_files
4260 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:364261 return PRESUBMIT.CheckStableMojomChanges(
Ken Rockotc31f4832020-05-29 18:58:514262 mock_input_api, mock_output_api)
4263
4264 def testSafeChangePasses(self):
4265 errors = self.runTestWithAffectedFiles([
4266 MockAffectedFile('foo/foo.mojom',
4267 ['[Stable] struct S { [MinVersion=1] int32 x; };'],
4268 old_contents=['[Stable] struct S {};'])
4269 ])
4270 self.assertEqual([], errors)
4271
4272 def testBadChangeFails(self):
4273 errors = self.runTestWithAffectedFiles([
4274 MockAffectedFile('foo/foo.mojom',
4275 ['[Stable] struct S { int32 x; };'],
4276 old_contents=['[Stable] struct S {};'])
4277 ])
4278 self.assertEqual(1, len(errors))
4279 self.assertTrue('not backward-compatible' in errors[0].message)
4280
Ken Rockotad7901f942020-06-04 20:17:094281 def testDeletedFile(self):
4282 """Regression test for https://crbug.com/1091407."""
4283 errors = self.runTestWithAffectedFiles([
4284 MockAffectedFile('a.mojom', [], old_contents=['struct S {};'],
4285 action='D'),
4286 MockAffectedFile('b.mojom',
4287 ['struct S {}; struct T { S s; };'],
4288 old_contents=['import "a.mojom"; struct T { S s; };'])
4289 ])
4290 self.assertEqual([], errors)
4291
Jose Magana2b456f22021-03-09 23:26:404292class CheckForUseOfChromeAppsDeprecationsTest(unittest.TestCase):
4293
4294 ERROR_MSG_PIECE = 'technologies which will soon be deprecated'
4295
4296 # Each positive test is also a naive negative test for the other cases.
4297
4298 def testWarningNMF(self):
4299 mock_input_api = MockInputApi()
4300 mock_input_api.files = [
4301 MockAffectedFile(
4302 'foo.NMF',
4303 ['"program"', '"Z":"content"', 'B'],
4304 ['"program"', 'B'],
4305 scm_diff='\n'.join([
4306 '--- foo.NMF.old 2020-12-02 20:40:54.430676385 +0100',
4307 '+++ foo.NMF.new 2020-12-02 20:41:02.086700197 +0100',
4308 '@@ -1,2 +1,3 @@',
4309 ' "program"',
4310 '+"Z":"content"',
4311 ' B']),
4312 action='M')
4313 ]
4314 mock_output_api = MockOutputApi()
4315 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
Gao Shenga79ebd42022-08-08 17:25:594316 mock_output_api)
Jose Magana2b456f22021-03-09 23:26:404317 self.assertEqual(1, len(errors))
4318 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
4319 self.assertTrue( 'foo.NMF' in errors[0].message)
4320
4321 def testWarningManifest(self):
4322 mock_input_api = MockInputApi()
4323 mock_input_api.files = [
4324 MockAffectedFile(
4325 'manifest.json',
4326 ['"app":', '"Z":"content"', 'B'],
4327 ['"app":"', 'B'],
4328 scm_diff='\n'.join([
4329 '--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
4330 '+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
4331 '@@ -1,2 +1,3 @@',
4332 ' "app"',
4333 '+"Z":"content"',
4334 ' B']),
4335 action='M')
4336 ]
4337 mock_output_api = MockOutputApi()
4338 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
Gao Shenga79ebd42022-08-08 17:25:594339 mock_output_api)
Jose Magana2b456f22021-03-09 23:26:404340 self.assertEqual(1, len(errors))
4341 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
4342 self.assertTrue( 'manifest.json' in errors[0].message)
4343
4344 def testOKWarningManifestWithoutApp(self):
4345 mock_input_api = MockInputApi()
4346 mock_input_api.files = [
4347 MockAffectedFile(
4348 'manifest.json',
4349 ['"name":', '"Z":"content"', 'B'],
4350 ['"name":"', 'B'],
4351 scm_diff='\n'.join([
4352 '--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
4353 '+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
4354 '@@ -1,2 +1,3 @@',
4355 ' "app"',
4356 '+"Z":"content"',
4357 ' B']),
4358 action='M')
4359 ]
4360 mock_output_api = MockOutputApi()
4361 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
Gao Shenga79ebd42022-08-08 17:25:594362 mock_output_api)
Jose Magana2b456f22021-03-09 23:26:404363 self.assertEqual(0, len(errors))
4364
4365 def testWarningPPAPI(self):
4366 mock_input_api = MockInputApi()
4367 mock_input_api.files = [
4368 MockAffectedFile(
4369 'foo.hpp',
4370 ['A', '#include <ppapi.h>', 'B'],
4371 ['A', 'B'],
4372 scm_diff='\n'.join([
4373 '--- foo.hpp.old 2020-12-02 20:40:54.430676385 +0100',
4374 '+++ foo.hpp.new 2020-12-02 20:41:02.086700197 +0100',
4375 '@@ -1,2 +1,3 @@',
4376 ' A',
4377 '+#include <ppapi.h>',
4378 ' B']),
4379 action='M')
4380 ]
4381 mock_output_api = MockOutputApi()
4382 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
Gao Shenga79ebd42022-08-08 17:25:594383 mock_output_api)
Jose Magana2b456f22021-03-09 23:26:404384 self.assertEqual(1, len(errors))
4385 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
4386 self.assertTrue( 'foo.hpp' in errors[0].message)
4387
4388 def testNoWarningPPAPI(self):
4389 mock_input_api = MockInputApi()
4390 mock_input_api.files = [
4391 MockAffectedFile(
4392 'foo.txt',
4393 ['A', 'Peppapig', 'B'],
4394 ['A', 'B'],
4395 scm_diff='\n'.join([
4396 '--- foo.txt.old 2020-12-02 20:40:54.430676385 +0100',
4397 '+++ foo.txt.new 2020-12-02 20:41:02.086700197 +0100',
4398 '@@ -1,2 +1,3 @@',
4399 ' A',
4400 '+Peppapig',
4401 ' B']),
4402 action='M')
4403 ]
4404 mock_output_api = MockOutputApi()
4405 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
Gao Shenga79ebd42022-08-08 17:25:594406 mock_output_api)
Jose Magana2b456f22021-03-09 23:26:404407 self.assertEqual(0, len(errors))
4408
Dominic Battre645d42342020-12-04 16:14:104409class CheckDeprecationOfPreferencesTest(unittest.TestCase):
4410 # Test that a warning is generated if a preference registration is removed
4411 # from a random file.
4412 def testWarning(self):
4413 mock_input_api = MockInputApi()
4414 mock_input_api.files = [
4415 MockAffectedFile(
4416 'foo.cc',
4417 ['A', 'B'],
4418 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
4419 scm_diff='\n'.join([
4420 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
4421 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
4422 '@@ -1,3 +1,2 @@',
4423 ' A',
4424 '-prefs->RegisterStringPref("foo", "default");',
4425 ' B']),
4426 action='M')
4427 ]
4428 mock_output_api = MockOutputApi()
4429 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
4430 mock_output_api)
4431 self.assertEqual(1, len(errors))
4432 self.assertTrue(
4433 'Discovered possible removal of preference registrations' in
4434 errors[0].message)
4435
4436 # Test that a warning is inhibited if the preference registration was moved
4437 # to the deprecation functions in browser prefs.
4438 def testNoWarningForMigration(self):
4439 mock_input_api = MockInputApi()
4440 mock_input_api.files = [
4441 # RegisterStringPref was removed from foo.cc.
4442 MockAffectedFile(
4443 'foo.cc',
4444 ['A', 'B'],
4445 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
4446 scm_diff='\n'.join([
4447 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
4448 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
4449 '@@ -1,3 +1,2 @@',
4450 ' A',
4451 '-prefs->RegisterStringPref("foo", "default");',
4452 ' B']),
4453 action='M'),
4454 # But the preference was properly migrated.
4455 MockAffectedFile(
4456 'chrome/browser/prefs/browser_prefs.cc',
4457 [
4458 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4459 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4460 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4461 'prefs->RegisterStringPref("foo", "default");',
4462 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4463 ],
4464 [
4465 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4466 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4467 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4468 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4469 ],
4470 scm_diff='\n'.join([
4471 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
4472 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
4473 '@@ -2,3 +2,4 @@',
4474 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4475 ' // BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4476 '+prefs->RegisterStringPref("foo", "default");',
4477 ' // END_MIGRATE_OBSOLETE_PROFILE_PREFS']),
4478 action='M'),
4479 ]
4480 mock_output_api = MockOutputApi()
4481 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
4482 mock_output_api)
4483 self.assertEqual(0, len(errors))
4484
4485 # Test that a warning is NOT inhibited if the preference registration was
4486 # moved to a place outside of the migration functions in browser_prefs.cc
4487 def testWarningForImproperMigration(self):
4488 mock_input_api = MockInputApi()
4489 mock_input_api.files = [
4490 # RegisterStringPref was removed from foo.cc.
4491 MockAffectedFile(
4492 'foo.cc',
4493 ['A', 'B'],
4494 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
4495 scm_diff='\n'.join([
4496 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
4497 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
4498 '@@ -1,3 +1,2 @@',
4499 ' A',
4500 '-prefs->RegisterStringPref("foo", "default");',
4501 ' B']),
4502 action='M'),
4503 # The registration call was moved to a place in browser_prefs.cc that
4504 # is outside the migration functions.
4505 MockAffectedFile(
4506 'chrome/browser/prefs/browser_prefs.cc',
4507 [
4508 'prefs->RegisterStringPref("foo", "default");',
4509 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4510 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4511 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4512 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4513 ],
4514 [
4515 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4516 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4517 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4518 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4519 ],
4520 scm_diff='\n'.join([
4521 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
4522 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
4523 '@@ -1,2 +1,3 @@',
4524 '+prefs->RegisterStringPref("foo", "default");',
4525 ' // BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4526 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS']),
4527 action='M'),
4528 ]
4529 mock_output_api = MockOutputApi()
4530 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
4531 mock_output_api)
4532 self.assertEqual(1, len(errors))
4533 self.assertTrue(
4534 'Discovered possible removal of preference registrations' in
4535 errors[0].message)
4536
Gao Shenga79ebd42022-08-08 17:25:594537 # Check that the presubmit fails if a marker line in browser_prefs.cc is
Dominic Battre645d42342020-12-04 16:14:104538 # deleted.
4539 def testDeletedMarkerRaisesError(self):
4540 mock_input_api = MockInputApi()
4541 mock_input_api.files = [
4542 MockAffectedFile('chrome/browser/prefs/browser_prefs.cc',
4543 [
4544 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4545 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4546 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4547 # The following line is deleted for this test
4548 # '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4549 ])
4550 ]
4551 mock_output_api = MockOutputApi()
4552 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
4553 mock_output_api)
4554 self.assertEqual(1, len(errors))
4555 self.assertEqual(
4556 'Broken .*MIGRATE_OBSOLETE_.*_PREFS markers in browser_prefs.cc.',
4557 errors[0].message)
4558
Sven Zheng76a79ea2022-12-21 21:25:244559class CheckCrosApiNeedBrowserTestTest(unittest.TestCase):
4560 def testWarning(self):
4561 mock_input_api = MockInputApi()
4562 mock_output_api = MockOutputApi()
4563 mock_input_api.files = [
4564 MockAffectedFile('chromeos/crosapi/mojom/example.mojom', [], action='A'),
4565 ]
4566 result = PRESUBMIT.CheckCrosApiNeedBrowserTest(mock_input_api, mock_output_api)
4567 self.assertEqual(1, len(result))
4568 self.assertEqual(result[0].type, 'warning')
4569
4570 def testNoWarningWithBrowserTest(self):
4571 mock_input_api = MockInputApi()
4572 mock_output_api = MockOutputApi()
4573 mock_input_api.files = [
4574 MockAffectedFile('chromeos/crosapi/mojom/example.mojom', [], action='A'),
4575 MockAffectedFile('chrome/example_browsertest.cc', [], action='A'),
4576 ]
4577 result = PRESUBMIT.CheckCrosApiNeedBrowserTest(mock_input_api, mock_output_api)
4578 self.assertEqual(0, len(result))
4579
4580 def testNoWarningModifyCrosapi(self):
4581 mock_input_api = MockInputApi()
4582 mock_output_api = MockOutputApi()
4583 mock_input_api.files = [
4584 MockAffectedFile('chromeos/crosapi/mojom/example.mojom', [], action='M'),
4585 ]
4586 result = PRESUBMIT.CheckCrosApiNeedBrowserTest(mock_input_api, mock_output_api)
4587 self.assertEqual(0, len(result))
4588
4589 def testNoWarningAddNonMojomFile(self):
4590 mock_input_api = MockInputApi()
4591 mock_output_api = MockOutputApi()
4592 mock_input_api.files = [
4593 MockAffectedFile('chromeos/crosapi/mojom/example.cc', [], action='A'),
4594 ]
4595 result = PRESUBMIT.CheckCrosApiNeedBrowserTest(mock_input_api, mock_output_api)
4596 self.assertEqual(0, len(result))
4597
4598 def testNoWarningNoneRelatedMojom(self):
4599 mock_input_api = MockInputApi()
4600 mock_output_api = MockOutputApi()
4601 mock_input_api.files = [
4602 MockAffectedFile('random/folder/example.mojom', [], action='A'),
4603 ]
4604 result = PRESUBMIT.CheckCrosApiNeedBrowserTest(mock_input_api, mock_output_api)
4605 self.assertEqual(0, len(result))
4606
4607
Henrique Ferreiro2a4b55942021-11-29 23:45:364608class AssertAshOnlyCodeTest(unittest.TestCase):
4609 def testErrorsOnlyOnAshDirectories(self):
4610 files_in_ash = [
4611 MockFile('ash/BUILD.gn', []),
4612 MockFile('chrome/browser/ash/BUILD.gn', []),
4613 ]
4614 other_files = [
4615 MockFile('chrome/browser/BUILD.gn', []),
4616 MockFile('chrome/browser/BUILD.gn', ['assert(is_chromeos_ash)']),
4617 ]
4618 input_api = MockInputApi()
4619 input_api.files = files_in_ash
4620 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4621 self.assertEqual(2, len(errors))
4622
4623 input_api.files = other_files
4624 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4625 self.assertEqual(0, len(errors))
4626
4627 def testDoesNotErrorOnNonGNFiles(self):
4628 input_api = MockInputApi()
4629 input_api.files = [
4630 MockFile('ash/test.h', ['assert(is_chromeos_ash)']),
4631 MockFile('chrome/browser/ash/test.cc',
4632 ['assert(is_chromeos_ash)']),
4633 ]
4634 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4635 self.assertEqual(0, len(errors))
4636
Giovanni Ortuño Urquidiab84da62021-12-10 00:53:214637 def testDeletedFile(self):
4638 input_api = MockInputApi()
4639 input_api.files = [
4640 MockFile('ash/BUILD.gn', []),
4641 MockFile('ash/foo/BUILD.gn', [], action='D'),
4642 ]
4643 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4644 self.assertEqual(1, len(errors))
4645
Henrique Ferreiro2a4b55942021-11-29 23:45:364646 def testDoesNotErrorWithAssertion(self):
4647 input_api = MockInputApi()
4648 input_api.files = [
4649 MockFile('ash/BUILD.gn', ['assert(is_chromeos_ash)']),
4650 MockFile('chrome/browser/ash/BUILD.gn',
4651 ['assert(is_chromeos_ash)']),
4652 MockFile('chrome/browser/ash/BUILD.gn',
4653 ['assert(is_chromeos_ash, "test")']),
4654 ]
4655 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4656 self.assertEqual(0, len(errors))
4657
4658
Lukasz Anforowicz7016d05e2021-11-30 03:56:274659class CheckRawPtrUsageTest(unittest.TestCase):
4660 def testAllowedCases(self):
4661 mock_input_api = MockInputApi()
4662 mock_input_api.files = [
4663 # Browser-side files are allowed.
4664 MockAffectedFile('test10/browser/foo.h', ['raw_ptr<int>']),
4665 MockAffectedFile('test11/browser/foo.cc', ['raw_ptr<int>']),
4666 MockAffectedFile('test12/blink/common/foo.cc', ['raw_ptr<int>']),
4667 MockAffectedFile('test13/blink/public/common/foo.cc', ['raw_ptr<int>']),
4668 MockAffectedFile('test14/blink/public/platform/foo.cc',
4669 ['raw_ptr<int>']),
4670
4671 # Non-C++ files are allowed.
4672 MockAffectedFile('test20/renderer/foo.md', ['raw_ptr<int>']),
4673
Kalvin Lee84ad17a2023-09-25 11:14:414674 # Renderer code is generally allowed (except specifically
4675 # disallowed directories).
4676 MockAffectedFile('test30/renderer/foo.cc', ['raw_ptr<int>']),
Lukasz Anforowicz7016d05e2021-11-30 03:56:274677 ]
4678 mock_output_api = MockOutputApi()
4679 errors = PRESUBMIT.CheckRawPtrUsage(mock_input_api, mock_output_api)
4680 self.assertFalse(errors)
4681
4682 def testDisallowedCases(self):
4683 mock_input_api = MockInputApi()
4684 mock_input_api.files = [
Kalvin Lee84ad17a2023-09-25 11:14:414685 MockAffectedFile('test1/third_party/blink/renderer/core/foo.h',
4686 ['raw_ptr<int>']),
4687 MockAffectedFile(
4688 'test2/third_party/blink/renderer/platform/heap/foo.cc',
4689 ['raw_ptr<int>']),
4690 MockAffectedFile(
4691 'test3/third_party/blink/renderer/platform/wtf/foo.cc',
4692 ['raw_ptr<int>']),
4693 MockAffectedFile('test4/blink/public/web/foo.cc', ['raw_ptr<int>']),
Lukasz Anforowicz7016d05e2021-11-30 03:56:274694 ]
4695 mock_output_api = MockOutputApi()
4696 errors = PRESUBMIT.CheckRawPtrUsage(mock_input_api, mock_output_api)
4697 self.assertEqual(len(mock_input_api.files), len(errors))
4698 for error in errors:
4699 self.assertTrue(
Kalvin Lee84ad17a2023-09-25 11:14:414700 'raw_ptr<T> should not be used in this renderer code' in
Lukasz Anforowicz7016d05e2021-11-30 03:56:274701 error.message)
4702
mikt9337567c2023-09-08 18:38:174703class CheckAdvancedMemorySafetyChecksUsageTest(unittest.TestCase):
4704 def testAllowedCases(self):
4705 mock_input_api = MockInputApi()
4706 mock_input_api.files = [
4707 # Non-C++ files are allowed.
4708 MockAffectedFile(
4709 'test20/renderer/foo.md', ['ADVANCED_MEMORY_SAFETY_CHECKS()']),
4710
4711 # Mentions in a comment are allowed.
4712 MockAffectedFile(
4713 'test30/renderer/foo.cc', ['//ADVANCED_MEMORY_SAFETY_CHECKS()']),
4714 ]
4715 mock_output_api = MockOutputApi()
4716 errors = PRESUBMIT.CheckAdvancedMemorySafetyChecksUsage(
4717 mock_input_api, mock_output_api)
4718 self.assertFalse(errors)
4719
4720 def testDisallowedCases(self):
4721 mock_input_api = MockInputApi()
4722 mock_input_api.files = [
4723 MockAffectedFile('test1/foo.h', ['ADVANCED_MEMORY_SAFETY_CHECKS()']),
4724 MockAffectedFile('test2/foo.cc', ['ADVANCED_MEMORY_SAFETY_CHECKS()']),
4725 ]
4726 mock_output_api = MockOutputApi()
4727 errors = PRESUBMIT.CheckAdvancedMemorySafetyChecksUsage(mock_input_api, mock_output_api)
4728 self.assertEqual(1, len(errors))
4729 self.assertTrue(
4730 'ADVANCED_MEMORY_SAFETY_CHECKS() macro is managed by' in
4731 errors[0].message)
Lukasz Anforowicz7016d05e2021-11-30 03:56:274732
Henrique Ferreirof9819f2e32021-11-30 13:31:564733class AssertPythonShebangTest(unittest.TestCase):
4734 def testError(self):
4735 input_api = MockInputApi()
4736 input_api.files = [
4737 MockFile('ash/test.py', ['#!/usr/bin/python']),
4738 MockFile('chrome/test.py', ['#!/usr/bin/python2']),
4739 MockFile('third_party/blink/test.py', ['#!/usr/bin/python3']),
Takuto Ikuta36976512021-11-30 23:15:274740 MockFile('empty.py', []),
Henrique Ferreirof9819f2e32021-11-30 13:31:564741 ]
4742 errors = PRESUBMIT.CheckPythonShebang(input_api, MockOutputApi())
4743 self.assertEqual(3, len(errors))
4744
4745 def testNonError(self):
4746 input_api = MockInputApi()
4747 input_api.files = [
4748 MockFile('chrome/browser/BUILD.gn', ['#!/usr/bin/python']),
4749 MockFile('third_party/blink/web_tests/external/test.py',
4750 ['#!/usr/bin/python2']),
4751 MockFile('third_party/test/test.py', ['#!/usr/bin/python3']),
4752 ]
4753 errors = PRESUBMIT.CheckPythonShebang(input_api, MockOutputApi())
4754 self.assertEqual(0, len(errors))
4755
Kalvin Lee4a3b79de2022-05-26 16:00:164756class VerifyDcheckParentheses(unittest.TestCase):
4757 def testPermissibleUsage(self):
4758 input_api = MockInputApi()
4759 input_api.files = [
4760 MockFile('okay1.cc', ['DCHECK_IS_ON()']),
4761 MockFile('okay2.cc', ['#if DCHECK_IS_ON()']),
4762
4763 # Other constructs that aren't exactly `DCHECK_IS_ON()` do their
4764 # own thing at their own risk.
4765 MockFile('okay3.cc', ['PA_DCHECK_IS_ON']),
4766 MockFile('okay4.cc', ['#if PA_DCHECK_IS_ON']),
Arthur Sonzogni62e877a2024-04-30 16:09:434767 MockFile('okay6.cc', ['PA_BUILDFLAG(PA_DCHECK_IS_ON)']),
Kalvin Lee4a3b79de2022-05-26 16:00:164768 ]
4769 errors = PRESUBMIT.CheckDCHECK_IS_ONHasBraces(input_api, MockOutputApi())
4770 self.assertEqual(0, len(errors))
4771
4772 def testMissingParentheses(self):
4773 input_api = MockInputApi()
4774 input_api.files = [
4775 MockFile('bad1.cc', ['DCHECK_IS_ON']),
4776 MockFile('bad2.cc', ['#if DCHECK_IS_ON']),
4777 MockFile('bad3.cc', ['DCHECK_IS_ON && foo']),
4778 ]
4779 errors = PRESUBMIT.CheckDCHECK_IS_ONHasBraces(input_api, MockOutputApi())
4780 self.assertEqual(3, len(errors))
4781 for error in errors:
4782 self.assertRegex(error.message, r'DCHECK_IS_ON().+parentheses')
Henrique Ferreirof9819f2e32021-11-30 13:31:564783
Sam Maier4cef9242022-10-03 14:21:244784
James Shen81cc0e22022-06-15 21:10:454785class CheckBatchAnnotation(unittest.TestCase):
4786 """Test the CheckBatchAnnotation presubmit check."""
4787
4788 def testTruePositives(self):
4789 """Examples of when there is no @Batch or @DoNotBatch is correctly flagged.
4790"""
4791 mock_input = MockInputApi()
4792 mock_input.files = [
4793 MockFile('path/OneTest.java', ['public class OneTest']),
4794 MockFile('path/TwoTest.java', ['public class TwoTest']),
ckitagawae8fd23b2022-06-17 15:29:384795 MockFile('path/ThreeTest.java',
4796 ['@Batch(Batch.PER_CLASS)',
4797 'import org.chromium.base.test.BaseRobolectricTestRunner;',
4798 'public class Three {']),
4799 MockFile('path/FourTest.java',
Mark Schillaci8ef0d872023-07-18 22:07:594800 ['@DoNotBatch(reason = "placeholder reason 1")',
ckitagawae8fd23b2022-06-17 15:29:384801 'import org.chromium.base.test.BaseRobolectricTestRunner;',
4802 'public class Four {']),
James Shen81cc0e22022-06-15 21:10:454803 ]
4804 errors = PRESUBMIT.CheckBatchAnnotation(mock_input, MockOutputApi())
ckitagawae8fd23b2022-06-17 15:29:384805 self.assertEqual(2, len(errors))
James Shen81cc0e22022-06-15 21:10:454806 self.assertEqual(2, len(errors[0].items))
4807 self.assertIn('OneTest.java', errors[0].items[0])
4808 self.assertIn('TwoTest.java', errors[0].items[1])
ckitagawae8fd23b2022-06-17 15:29:384809 self.assertEqual(2, len(errors[1].items))
4810 self.assertIn('ThreeTest.java', errors[1].items[0])
4811 self.assertIn('FourTest.java', errors[1].items[1])
4812
James Shen81cc0e22022-06-15 21:10:454813
4814 def testAnnotationsPresent(self):
4815 """Examples of when there is @Batch or @DoNotBatch is correctly flagged."""
4816 mock_input = MockInputApi()
4817 mock_input.files = [
4818 MockFile('path/OneTest.java',
4819 ['@Batch(Batch.PER_CLASS)', 'public class One {']),
4820 MockFile('path/TwoTest.java',
Mark Schillaci8ef0d872023-07-18 22:07:594821 ['@DoNotBatch(reason = "placeholder reasons.")', 'public class Two {'
James Shen81cc0e22022-06-15 21:10:454822 ]),
4823 MockFile('path/ThreeTest.java',
4824 ['@Batch(Batch.PER_CLASS)',
4825 'public class Three extends BaseTestA {'],
4826 ['@Batch(Batch.PER_CLASS)',
4827 'public class Three extends BaseTestB {']),
4828 MockFile('path/FourTest.java',
Mark Schillaci8ef0d872023-07-18 22:07:594829 ['@DoNotBatch(reason = "placeholder reason 1")',
James Shen81cc0e22022-06-15 21:10:454830 'public class Four extends BaseTestA {'],
Mark Schillaci8ef0d872023-07-18 22:07:594831 ['@DoNotBatch(reason = "placeholder reason 2")',
James Shen81cc0e22022-06-15 21:10:454832 'public class Four extends BaseTestB {']),
4833 MockFile('path/FiveTest.java',
4834 ['import androidx.test.uiautomator.UiDevice;',
4835 'public class Five extends BaseTestA {'],
4836 ['import androidx.test.uiautomator.UiDevice;',
4837 'public class Five extends BaseTestB {']),
4838 MockFile('path/SixTest.java',
4839 ['import org.chromium.base.test.BaseRobolectricTestRunner;',
4840 'public class Six extends BaseTestA {'],
4841 ['import org.chromium.base.test.BaseRobolectricTestRunner;',
4842 'public class Six extends BaseTestB {']),
4843 MockFile('path/SevenTest.java',
4844 ['import org.robolectric.annotation.Config;',
4845 'public class Seven extends BaseTestA {'],
4846 ['import org.robolectric.annotation.Config;',
4847 'public class Seven extends BaseTestB {']),
4848 MockFile(
4849 'path/OtherClass.java',
4850 ['public class OtherClass {'],
4851 ),
4852 MockFile('path/PRESUBMIT.py',
4853 ['@Batch(Batch.PER_CLASS)',
Mark Schillaci8ef0d872023-07-18 22:07:594854 '@DoNotBatch(reason = "placeholder reason)']),
4855 MockFile('path/AnnotationTest.java',
4856 ['public @interface SomeAnnotation {'],),
James Shen81cc0e22022-06-15 21:10:454857 ]
4858 errors = PRESUBMIT.CheckBatchAnnotation(mock_input, MockOutputApi())
4859 self.assertEqual(0, len(errors))
4860
Sam Maier4cef9242022-10-03 14:21:244861
4862class CheckMockAnnotation(unittest.TestCase):
4863 """Test the CheckMockAnnotation presubmit check."""
4864
4865 def testTruePositives(self):
4866 """Examples of @Mock or @Spy being used and nothing should be flagged."""
4867 mock_input = MockInputApi()
4868 mock_input.files = [
4869 MockFile('path/OneTest.java', [
4870 'import a.b.c.Bar;',
4871 'import a.b.c.Foo;',
Sam Maierb8a66a02023-10-10 13:50:554872 '@Mock public static Foo f = new Foo();',
Sam Maier4cef9242022-10-03 14:21:244873 'Mockito.mock(new Bar(a, b, c))'
4874 ]),
4875 MockFile('path/TwoTest.java', [
4876 'package x.y.z;',
4877 'import static org.mockito.Mockito.spy;',
4878 '@Spy',
4879 'public static FooBar<Baz> f;',
4880 'a = spy(Baz.class)'
4881 ]),
4882 ]
4883 errors = PRESUBMIT.CheckMockAnnotation(mock_input, MockOutputApi())
4884 self.assertEqual(1, len(errors))
4885 self.assertEqual(2, len(errors[0].items))
4886 self.assertIn('a.b.c.Bar in path/OneTest.java', errors[0].items)
4887 self.assertIn('x.y.z.Baz in path/TwoTest.java', errors[0].items)
4888
4889 def testTrueNegatives(self):
4890 """Examples of when we should not be flagging mock() or spy() calls."""
4891 mock_input = MockInputApi()
4892 mock_input.files = [
4893 MockFile('path/OneTest.java', [
4894 'package a.b.c;',
4895 'import org.chromium.base.test.BaseRobolectricTestRunner;',
4896 'Mockito.mock(Abc.class)'
4897 ]),
4898 MockFile('path/TwoTest.java', [
4899 'package a.b.c;',
4900 'import androidx.test.uiautomator.UiDevice;',
4901 'Mockito.spy(new Def())'
4902 ]),
4903 MockFile('path/ThreeTest.java', [
4904 'package a.b.c;',
4905 'import static org.mockito.Mockito.spy;',
4906 '@Spy',
4907 'public static Foo f = new Abc();',
4908 'a = spy(Foo.class)'
4909 ]),
4910 MockFile('path/FourTest.java', [
4911 'package a.b.c;',
4912 'import static org.mockito.Mockito.mock;',
4913 '@Spy',
4914 'public static Bar b = new Abc(a, b, c, d);',
4915 ' mock(new Bar(a,b,c))'
4916 ]),
4917 MockFile('path/FiveTest.java', [
4918 'package a.b.c;',
4919 '@Mock',
4920 'public static Baz<abc> b;',
Sam Maierb8a66a02023-10-10 13:50:554921 'Mockito.mock(Baz.class)'
4922 ]),
Sam Maier4cef9242022-10-03 14:21:244923 MockFile('path/SixTest.java', [
4924 'package a.b.c;',
4925 'import android.view.View;',
4926 'import java.ArrayList;',
4927 'Mockito.spy(new View())',
4928 'Mockito.mock(ArrayList.class)'
4929 ]),
Sam Maierb8a66a02023-10-10 13:50:554930 MockFile('path/SevenTest.java', [
4931 'package a.b.c;',
4932 '@Mock private static Seven s;',
4933 'Mockito.mock(Seven.class)'
4934 ]),
4935 MockFile('path/EightTest.java', [
4936 'package a.b.c;',
4937 '@Spy Eight e = new Eight2();',
4938 'Mockito.py(new Eight())'
4939 ]),
Sam Maier4cef9242022-10-03 14:21:244940 ]
4941 errors = PRESUBMIT.CheckMockAnnotation(mock_input, MockOutputApi())
4942 self.assertEqual(0, len(errors))
4943
4944
Mike Dougherty1b8be712022-10-20 00:15:134945class AssertNoJsInIosTest(unittest.TestCase):
4946 def testErrorJs(self):
4947 input_api = MockInputApi()
4948 input_api.files = [
4949 MockFile('components/feature/ios/resources/script.js', []),
4950 MockFile('ios/chrome/feature/resources/script.js', []),
4951 ]
4952 results = PRESUBMIT.CheckNoJsInIos(input_api, MockOutputApi())
4953 self.assertEqual(1, len(results))
4954 self.assertEqual('error', results[0].type)
4955 self.assertEqual(2, len(results[0].items))
4956
4957 def testNonError(self):
4958 input_api = MockInputApi()
4959 input_api.files = [
4960 MockFile('chrome/resources/script.js', []),
4961 MockFile('components/feature/ios/resources/script.ts', []),
4962 MockFile('ios/chrome/feature/resources/script.ts', []),
4963 MockFile('ios/web/feature/resources/script.ts', []),
4964 MockFile('ios/third_party/script.js', []),
4965 MockFile('third_party/ios/script.js', []),
4966 ]
4967 results = PRESUBMIT.CheckNoJsInIos(input_api, MockOutputApi())
4968 self.assertEqual(0, len(results))
4969
4970 def testExistingFilesWarningOnly(self):
4971 input_api = MockInputApi()
4972 input_api.files = [
4973 MockFile('ios/chrome/feature/resources/script.js', [], action='M'),
4974 MockFile('ios/chrome/feature/resources/script2.js', [], action='D'),
4975 ]
4976 results = PRESUBMIT.CheckNoJsInIos(input_api, MockOutputApi())
4977 self.assertEqual(1, len(results))
4978 self.assertEqual('warning', results[0].type)
4979 self.assertEqual(1, len(results[0].items))
4980
Mike Dougherty4d1050b2023-03-14 15:59:534981 def testMovedScriptWarningOnly(self):
4982 input_api = MockInputApi()
4983 input_api.files = [
4984 MockFile('ios/chrome/feature/resources/script.js', [], action='D'),
4985 MockFile('ios/chrome/renamed_feature/resources/script.js', [], action='A'),
4986 ]
4987 results = PRESUBMIT.CheckNoJsInIos(input_api, MockOutputApi())
4988 self.assertEqual(1, len(results))
4989 self.assertEqual('warning', results[0].type)
4990 self.assertEqual(1, len(results[0].items))
4991
Yuanqing Zhu9eef02832022-12-04 14:42:174992class CheckNoAbbreviationInPngFileNameTest(unittest.TestCase):
4993 def testHasAbbreviation(self):
4994 """test png file names with abbreviation that fails the check"""
4995 input_api = MockInputApi()
4996 input_api.files = [
4997 MockFile('image_a.png', [], action='A'),
4998 MockFile('image_a_.png', [], action='A'),
4999 MockFile('image_a_name.png', [], action='A'),
5000 MockFile('chrome/ui/feature_name/resources/image_a.png', [], action='A'),
5001 MockFile('chrome/ui/feature_name/resources/image_a_.png', [], action='A'),
5002 MockFile('chrome/ui/feature_name/resources/image_a_name.png', [], action='A'),
5003 ]
5004 results = PRESUBMIT.CheckNoAbbreviationInPngFileName(input_api, MockOutputApi())
5005 self.assertEqual(1, len(results))
5006 self.assertEqual('error', results[0].type)
5007 self.assertEqual(len(input_api.files), len(results[0].items))
5008
5009 def testNoAbbreviation(self):
5010 """test png file names without abbreviation that passes the check"""
5011 input_api = MockInputApi()
5012 input_api.files = [
5013 MockFile('a.png', [], action='A'),
5014 MockFile('_a.png', [], action='A'),
5015 MockFile('image.png', [], action='A'),
5016 MockFile('image_ab_.png', [], action='A'),
5017 MockFile('image_ab_name.png', [], action='A'),
5018 # These paths used to fail because `feature_a_name` matched the regex by mistake.
5019 # They should pass now because the path components ahead of the file name are ignored in the check.
5020 MockFile('chrome/ui/feature_a_name/resources/a.png', [], action='A'),
5021 MockFile('chrome/ui/feature_a_name/resources/_a.png', [], action='A'),
5022 MockFile('chrome/ui/feature_a_name/resources/image.png', [], action='A'),
5023 MockFile('chrome/ui/feature_a_name/resources/image_ab_.png', [], action='A'),
5024 MockFile('chrome/ui/feature_a_name/resources/image_ab_name.png', [], action='A'),
5025 ]
5026 results = PRESUBMIT.CheckNoAbbreviationInPngFileName(input_api, MockOutputApi())
5027 self.assertEqual(0, len(results))
5028
Arthur Sonzogni7109bd32023-10-03 10:34:425029class CheckDanglingUntriagedTest(unittest.TestCase):
5030 def testError(self):
5031 """Test patch adding dangling pointers are reported"""
5032 mock_input_api = MockInputApi()
5033 mock_output_api = MockOutputApi()
5034
5035 mock_input_api.change.DescriptionText = lambda: "description"
5036 mock_input_api.files = [
5037 MockAffectedFile(
5038 local_path="foo/foo.cc",
Arthur Sonzogni9eafd222023-11-10 08:50:395039 old_contents=["raw_ptr<T>"],
5040 new_contents=["raw_ptr<T, DanglingUntriaged>"],
Arthur Sonzogni7109bd32023-10-03 10:34:425041 )
5042 ]
5043 msgs = PRESUBMIT.CheckDanglingUntriaged(mock_input_api, mock_output_api)
5044 self.assertEqual(len(msgs), 1)
5045 self.assertEqual(len(msgs[0].message), 10)
5046 self.assertEqual(
5047 msgs[0].message[0],
5048 "Unexpected new occurrences of `DanglingUntriaged` detected. Please",
5049 )
5050
5051class CheckDanglingUntriagedTest(unittest.TestCase):
5052 def testError(self):
5053 """Test patch adding dangling pointers are reported"""
5054 mock_input_api = MockInputApi()
5055 mock_output_api = MockOutputApi()
5056
5057 mock_input_api.change.DescriptionText = lambda: "description"
5058 mock_input_api.files = [
5059 MockAffectedFile(
5060 local_path="foo/foo.cc",
Arthur Sonzogni9eafd222023-11-10 08:50:395061 old_contents=["raw_ptr<T>"],
5062 new_contents=["raw_ptr<T, DanglingUntriaged>"],
Arthur Sonzogni7109bd32023-10-03 10:34:425063 )
5064 ]
5065 msgs = PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5066 mock_output_api)
5067 self.assertEqual(len(msgs), 1)
Arthur Sonzogni9eafd222023-11-10 08:50:395068 self.assertTrue(("Unexpected new occurrences of `DanglingUntriaged` detected"
5069 in msgs[0].message))
Arthur Sonzogni7109bd32023-10-03 10:34:425070
5071 def testNonCppFile(self):
5072 """Test patch adding dangling pointers are not reported in non C++ files"""
5073 mock_input_api = MockInputApi()
5074 mock_output_api = MockOutputApi()
5075
5076 mock_input_api.change.DescriptionText = lambda: "description"
5077 mock_input_api.files = [
5078 MockAffectedFile(
5079 local_path="foo/README.md",
Arthur Sonzogni9eafd222023-11-10 08:50:395080 old_contents=[""],
5081 new_contents=["The DanglingUntriaged annotation means"],
Arthur Sonzogni7109bd32023-10-03 10:34:425082 )
5083 ]
5084 msgs = PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5085 mock_output_api)
5086 self.assertEqual(len(msgs), 0)
5087
5088 def testDeveloperAcknowledgeInCommitDescription(self):
5089 """Test patch adding dangling pointers, but acknowledged by the developers
5090 aren't reported"""
5091 mock_input_api = MockInputApi()
5092 mock_output_api = MockOutputApi()
5093
5094 mock_input_api.files = [
5095 MockAffectedFile(
5096 local_path="foo/foo.cc",
Arthur Sonzogni9eafd222023-11-10 08:50:395097 old_contents=["raw_ptr<T>"],
5098 new_contents=["raw_ptr<T, DanglingUntriaged>"],
Arthur Sonzogni7109bd32023-10-03 10:34:425099 )
5100 ]
5101 mock_input_api.change.DescriptionText = lambda: (
5102 "DanglingUntriaged-notes: Sorry about this!")
5103 msgs = PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5104 mock_output_api)
5105 self.assertEqual(len(msgs), 0)
5106
5107 def testDeveloperAcknowledgeInCommitFooter(self):
5108 """Test patch adding dangling pointers, but acknowledged by the developers
5109 aren't reported"""
5110 mock_input_api = MockInputApi()
5111 mock_output_api = MockOutputApi()
5112
5113 mock_input_api.files = [
5114 MockAffectedFile(
5115 local_path="foo/foo.cc",
Arthur Sonzogni9eafd222023-11-10 08:50:395116 old_contents=["raw_ptr<T>"],
5117 new_contents=["raw_ptr<T, DanglingUntriaged>"],
Arthur Sonzogni7109bd32023-10-03 10:34:425118 )
5119 ]
5120 mock_input_api.change.DescriptionText = lambda: "description"
5121 mock_input_api.change.footers["DanglingUntriaged-notes"] = ["Sorry!"]
5122 msgs = PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5123 mock_output_api)
5124 self.assertEqual(len(msgs), 0)
5125
5126 def testCongrats(self):
5127 """Test the presubmit congrats users removing dangling pointers"""
5128 mock_input_api = MockInputApi()
5129 mock_output_api = MockOutputApi()
5130
5131 mock_input_api.files = [
5132 MockAffectedFile(
5133 local_path="foo/foo.cc",
Arthur Sonzogni9eafd222023-11-10 08:50:395134 old_contents=["raw_ptr<T, DanglingUntriaged>"],
5135 new_contents=["raw_ptr<T>"],
Arthur Sonzogni7109bd32023-10-03 10:34:425136 )
5137 ]
5138 mock_input_api.change.DescriptionText = lambda: (
5139 "This patch fixes some DanglingUntriaged pointers!")
5140 msgs = PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5141 mock_output_api)
5142 self.assertEqual(len(msgs), 1)
5143 self.assertTrue(
5144 "DanglingUntriaged pointers removed: 1" in msgs[0].message)
5145 self.assertTrue("Thank you!" in msgs[0].message)
5146
5147 def testRenameFile(self):
5148 """Patch that we do not warn about DanglingUntriaged when moving files"""
5149 mock_input_api = MockInputApi()
5150 mock_output_api = MockOutputApi()
5151
5152 mock_input_api.files = [
5153 MockAffectedFile(
5154 local_path="foo/foo.cc",
Arthur Sonzogni9eafd222023-11-10 08:50:395155 old_contents=["raw_ptr<T, DanglingUntriaged>"],
5156 new_contents=[""],
Arthur Sonzogni7109bd32023-10-03 10:34:425157 action="D",
5158 ),
5159 MockAffectedFile(
5160 local_path="foo/foo.cc",
Arthur Sonzogni9eafd222023-11-10 08:50:395161 old_contents=[""],
5162 new_contents=["raw_ptr<T, DanglingUntriaged>"],
Arthur Sonzogni7109bd32023-10-03 10:34:425163 action="A",
5164 ),
5165 ]
5166 mock_input_api.change.DescriptionText = lambda: (
5167 "This patch moves files")
5168 msgs = PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5169 mock_output_api)
5170 self.assertEqual(len(msgs), 0)
5171
Jan Keitel77be7522023-10-12 20:40:495172class CheckInlineConstexprDefinitionsInHeadersTest(unittest.TestCase):
5173 def testNoInlineConstexprInHeaderFile(self):
5174 """Tests that non-inlined constexpr variables in headers fail the test."""
5175 input_api = MockInputApi()
5176 input_api.files = [
5177 MockAffectedFile('src/constants.h', ['constexpr int kVersion = 5;'])
5178 ]
5179 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5180 self.assertEqual(1, len(warnings))
5181
5182 def testNoInlineConstexprInHeaderFileInitializedFromFunction(self):
5183 """Tests that non-inlined constexpr header variables that are initialized from a function fail."""
5184 input_api = MockInputApi()
5185 input_api.files = [
5186 MockAffectedFile('src/constants.h', ['constexpr int kVersion = GetVersion();'])
5187 ]
5188 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5189 self.assertEqual(1, len(warnings))
5190
5191 def testNoInlineConstexprInHeaderFileInitializedWithExpression(self):
5192 """Tests that non-inlined constexpr header variables initialized with an expression fail."""
5193 input_api = MockInputApi()
5194 input_api.files = [
5195 MockAffectedFile('src/constants.h', ['constexpr int kVersion = (4 + 5)*3;'])
5196 ]
5197 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5198 self.assertEqual(1, len(warnings))
5199
5200 def testNoInlineConstexprInHeaderFileBraceInitialized(self):
5201 """Tests that non-inlined constexpr header variables that are brace-initialized fail."""
5202 input_api = MockInputApi()
5203 input_api.files = [
5204 MockAffectedFile('src/constants.h', ['constexpr int kVersion{5};'])
5205 ]
5206 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5207 self.assertEqual(1, len(warnings))
5208
5209 def testNoInlineConstexprInHeaderWithAttribute(self):
5210 """Tests that non-inlined constexpr header variables that have compiler attributes fail."""
5211 input_api = MockInputApi()
5212 input_api.files = [
5213 MockAffectedFile('src/constants.h', ['constexpr [[maybe_unused]] int kVersion{5};'])
5214 ]
5215 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5216 self.assertEqual(1, len(warnings))
5217
5218 def testInlineConstexprInHeaderWithAttribute(self):
5219 """Tests that inlined constexpr header variables that have compiler attributes pass."""
5220 input_api = MockInputApi()
5221 input_api.files = [
5222 MockAffectedFile('src/constants.h', ['inline constexpr [[maybe_unused]] int kVersion{5};']),
5223 MockAffectedFile('src/constants.h', ['constexpr inline [[maybe_unused]] int kVersion{5};']),
5224 MockAffectedFile('src/constants.h', ['inline constexpr [[maybe_unused]] inline int kVersion{5};'])
5225 ]
5226 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5227 self.assertEqual(0, len(warnings))
5228
5229 def testNoInlineConstexprInHeaderFileMultipleLines(self):
5230 """Tests that non-inlined constexpr header variable definitions spanning multiple lines fail."""
5231 input_api = MockInputApi()
5232 lines = ['constexpr char kLongName =',
5233 ' "This is a very long name of something.";'
5234 ]
5235 input_api.files = [MockAffectedFile('src/constants.h', lines)]
5236 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5237 self.assertEqual(1, len(warnings))
5238
5239 def testNoInlineConstexprInCCFile(self):
5240 """Tests that non-inlined constexpr variables in .cc files pass the test."""
5241 input_api = MockInputApi()
5242 input_api.files = [
5243 MockAffectedFile('src/implementation.cc', ['constexpr int kVersion = 5;'])
5244 ]
5245 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5246 self.assertEqual(0, len(warnings))
5247
5248 def testInlineConstexprInHeaderFile(self):
5249 """Tests that inlined constexpr variables in header files pass the test."""
5250 input_api = MockInputApi()
5251 input_api.files = [
5252 MockAffectedFile('src/constants.h', ['constexpr inline int kX = 5;']),
5253 MockAffectedFile('src/version.h', ['inline constexpr float kY = 5.0f;'])
5254 ]
5255 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5256 self.assertEqual(0, len(warnings))
5257
5258 def testConstexprStandaloneFunctionInHeaderFile(self):
5259 """Tests that non-inlined constexpr functions in headers pass the test."""
5260 input_api = MockInputApi()
5261 input_api.files = [
5262 MockAffectedFile('src/helpers.h', ['constexpr int GetVersion();'])
5263 ]
5264 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5265 self.assertEqual(0, len(warnings))
5266
5267 def testConstexprWithAbseilAttributeInHeader(self):
5268 """Tests that non-inlined constexpr variables with Abseil-type prefixes in headers fail."""
5269 input_api = MockInputApi()
5270 input_api.files = [
5271 MockAffectedFile('src/helpers.h', ['ABSL_FOOFOO constexpr int i = 5;'])
5272 ]
5273 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5274 self.assertEqual(1, len(warnings))
5275
5276 def testInlineConstexprWithAbseilAttributeInHeader(self):
5277 """Tests that inlined constexpr variables with Abseil-type prefixes in headers pass."""
5278 input_api = MockInputApi()
5279 input_api.files = [
5280 MockAffectedFile('src/helpers.h', ['constexpr ABSL_FOO inline int i = 5;'])
5281 ]
5282 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5283 self.assertEqual(0, len(warnings))
5284
5285 def testConstexprWithClangAttributeInHeader(self):
5286 """Tests that non-inlined constexpr variables with attributes with colons in headers fail."""
5287 input_api = MockInputApi()
5288 input_api.files = [
5289 MockAffectedFile('src/helpers.h', ['[[clang::someattribute]] constexpr int i = 5;'])
5290 ]
5291 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5292 self.assertEqual(1, len(warnings))
5293
5294 def testInlineConstexprWithClangAttributeInHeader(self):
5295 """Tests that inlined constexpr variables with attributes with colons in headers pass."""
5296 input_api = MockInputApi()
5297 input_api.files = [
5298 MockAffectedFile('src/helpers.h', ['constexpr [[clang::someattribute]] inline int i = 5;'])
5299 ]
5300 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5301 self.assertEqual(0, len(warnings))
5302
5303 def testNoExplicitInlineConstexprInsideClassInHeaderFile(self):
5304 """Tests that non-inlined constexpr class members pass the test."""
5305 input_api = MockInputApi()
5306 lines = ['class SomeClass {',
5307 ' public:',
5308 ' static constexpr kVersion = 5;',
5309 '};']
5310 input_api.files = [
5311 MockAffectedFile('src/class.h', lines)
5312 ]
5313 warnings = PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(input_api, MockOutputApi())
5314 self.assertEqual(0, len(warnings))
Arthur Sonzogni7109bd32023-10-03 10:34:425315
Alison Galed6b25fe2024-04-17 13:59:045316 def testTodoBugReferencesWithOldBugId(self):
5317 """Tests that an old monorail bug ID in a TODO fails."""
5318 input_api = MockInputApi()
5319 input_api.files = [
5320 MockAffectedFile('src/helpers.h', ['// TODO(crbug.com/12345)'])
5321 ]
5322 warnings = PRESUBMIT.CheckTodoBugReferences(input_api, MockOutputApi())
5323 self.assertEqual(1, len(warnings))
5324
5325 def testTodoBugReferencesWithUpdatedBugId(self):
5326 """Tests that a new issue tracker bug ID in a TODO passes."""
5327 input_api = MockInputApi()
5328 input_api.files = [
5329 MockAffectedFile('src/helpers.h', ['// TODO(crbug.com/40781525)'])
5330 ]
5331 warnings = PRESUBMIT.CheckTodoBugReferences(input_api, MockOutputApi())
5332 self.assertEqual(0, len(warnings))
5333
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:155334class CheckDeprecatedSyncConsentFunctionsTest(unittest.TestCase):
5335 """Test the presubmit for deprecated ConsentLevel::kSync functions."""
5336
5337 def testCppMobilePlatformPath(self):
5338 input_api = MockInputApi()
5339 input_api.files = [
5340 MockFile('chrome/browser/android/file.cc', ['OtherFunction']),
5341 MockFile('chrome/android/file.cc', ['HasSyncConsent']),
5342 MockFile('ios/file.mm', ['CanSyncFeatureStart']),
5343 MockFile('components/foo/ios/file.cc', ['IsSyncFeatureEnabled']),
5344 MockFile('components/foo/delegate_android.cc', ['IsSyncFeatureActive']),
5345 MockFile('components/foo/delegate_ios.cc', ['IsSyncFeatureActive']),
5346 MockFile('components/foo/android_delegate.cc', ['IsSyncFeatureActive']),
5347 MockFile('components/foo/ios_delegate.cc', ['IsSyncFeatureActive']),
5348 ]
5349
5350 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
5351
5352 self.assertEqual(1, len(results))
5353 self.assertFalse('chrome/browser/android/file.cc' in results[0].message),
5354 self.assertTrue('chrome/android/file.cc' in results[0].message),
5355 self.assertTrue('ios/file.mm' in results[0].message),
5356 self.assertTrue('components/foo/ios/file.cc' in results[0].message),
5357 self.assertTrue('components/foo/delegate_android.cc' in results[0].message),
5358 self.assertTrue('components/foo/delegate_ios.cc' in results[0].message),
5359 self.assertTrue('components/foo/android_delegate.cc' in results[0].message),
5360 self.assertTrue('components/foo/ios_delegate.cc' in results[0].message),
5361
5362 def testCppNonMobilePlatformPath(self):
5363 input_api = MockInputApi()
5364 input_api.files = [
5365 MockFile('chrome/browser/file.cc', ['HasSyncConsent']),
5366 MockFile('bios/file.cc', ['HasSyncConsent']),
5367 MockFile('components/kiosk/file.cc', ['HasSyncConsent']),
5368 ]
5369
5370 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
5371
5372 self.assertEqual(0, len(results))
5373
5374 def testJavaPath(self):
5375 input_api = MockInputApi()
5376 input_api.files = [
5377 MockFile('components/foo/file1.java', ['otherFunction']),
5378 MockFile('components/foo/file2.java', ['hasSyncConsent']),
5379 MockFile('chrome/foo/file3.java', ['canSyncFeatureStart']),
5380 MockFile('chrome/foo/file4.java', ['isSyncFeatureEnabled']),
5381 MockFile('chrome/foo/file5.java', ['isSyncFeatureActive']),
5382 ]
5383
5384 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
5385
5386 self.assertEqual(1, len(results))
5387 self.assertFalse('components/foo/file1.java' in results[0].message),
5388 self.assertTrue('components/foo/file2.java' in results[0].message),
5389 self.assertTrue('chrome/foo/file3.java' in results[0].message),
5390 self.assertTrue('chrome/foo/file4.java' in results[0].message),
5391 self.assertTrue('chrome/foo/file5.java' in results[0].message),
5392
5393
[email protected]2299dcf2012-11-15 19:56:245394if __name__ == '__main__':
5395 unittest.main()