blob: 9eb7349ba6bfb8477e9540e44663340628578ffd [file] [log] [blame]
Andrew Grieve3f9b9662022-02-02 19:07:551#!/usr/bin/env python3
[email protected]2299dcf2012-11-15 19:56:242# Copyright (c) 2012 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
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
[email protected]2299dcf2012-11-15 19:56:249import unittest
10
11import PRESUBMIT
Saagar Sanghavifceeaae2020-08-12 16:40:3612
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3913from PRESUBMIT_test_mocks import MockFile, MockAffectedFile
gayane3dff8c22014-12-04 17:09:5114from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi
[email protected]2299dcf2012-11-15 19:56:2415
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3916
[email protected]99171a92014-06-03 08:44:4717_TEST_DATA_DIR = 'base/test/data/presubmit'
18
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3919
[email protected]b00342e7f2013-03-26 16:21:5420class VersionControlConflictsTest(unittest.TestCase):
[email protected]70ca77752012-11-20 03:45:0321 def testTypicalConflict(self):
22 lines = ['<<<<<<< HEAD',
23 ' base::ScopedTempDir temp_dir_;',
24 '=======',
25 ' ScopedTempDir temp_dir_;',
26 '>>>>>>> master']
27 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
28 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
29 self.assertEqual(3, len(errors))
30 self.assertTrue('1' in errors[0])
31 self.assertTrue('3' in errors[1])
32 self.assertTrue('5' in errors[2])
33
dbeam95c35a2f2015-06-02 01:40:2334 def testIgnoresReadmes(self):
35 lines = ['A First Level Header',
36 '====================',
37 '',
38 'A Second Level Header',
39 '---------------------']
40 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
41 MockInputApi(), MockFile('some/polymer/README.md', lines))
42 self.assertEqual(0, len(errors))
43
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3944
[email protected]b8079ae4a2012-12-05 19:56:4945class BadExtensionsTest(unittest.TestCase):
46 def testBadRejFile(self):
47 mock_input_api = MockInputApi()
48 mock_input_api.files = [
49 MockFile('some/path/foo.cc', ''),
50 MockFile('some/path/foo.cc.rej', ''),
51 MockFile('some/path2/bar.h.rej', ''),
52 ]
53
Saagar Sanghavifceeaae2020-08-12 16:40:3654 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:4955 self.assertEqual(1, len(results))
56 self.assertEqual(2, len(results[0].items))
57 self.assertTrue('foo.cc.rej' in results[0].items[0])
58 self.assertTrue('bar.h.rej' in results[0].items[1])
59
60 def testBadOrigFile(self):
61 mock_input_api = MockInputApi()
62 mock_input_api.files = [
63 MockFile('other/path/qux.h.orig', ''),
64 MockFile('other/path/qux.h', ''),
65 MockFile('other/path/qux.cc', ''),
66 ]
67
Saagar Sanghavifceeaae2020-08-12 16:40:3668 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:4969 self.assertEqual(1, len(results))
70 self.assertEqual(1, len(results[0].items))
71 self.assertTrue('qux.h.orig' in results[0].items[0])
72
73 def testGoodFiles(self):
74 mock_input_api = MockInputApi()
75 mock_input_api.files = [
76 MockFile('other/path/qux.h', ''),
77 MockFile('other/path/qux.cc', ''),
78 ]
Saagar Sanghavifceeaae2020-08-12 16:40:3679 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:4980 self.assertEqual(0, len(results))
81
82
Lei Zhang1c12a22f2021-05-12 11:28:4583class CheckForSuperfluousStlIncludesInHeadersTest(unittest.TestCase):
84 def testGoodFiles(self):
85 mock_input_api = MockInputApi()
86 mock_input_api.files = [
87 # The check is not smart enough to figure out which definitions correspond
88 # to which header.
89 MockFile('other/path/foo.h',
90 ['#include <string>',
91 'std::vector']),
92 # The check is not smart enough to do IWYU.
93 MockFile('other/path/bar.h',
94 ['#include "base/check.h"',
95 'std::vector']),
96 MockFile('other/path/qux.h',
97 ['#include "base/stl_util.h"',
98 'foobar']),
Lei Zhang0643e342021-05-12 18:02:1299 MockFile('other/path/baz.h',
100 ['#include "set/vector.h"',
101 'bazzab']),
Lei Zhang1c12a22f2021-05-12 11:28:45102 # The check is only for header files.
103 MockFile('other/path/not_checked.cc',
104 ['#include <vector>',
105 'bazbaz']),
106 ]
107 results = PRESUBMIT.CheckForSuperfluousStlIncludesInHeaders(
108 mock_input_api, MockOutputApi())
109 self.assertEqual(0, len(results))
110
111 def testBadFiles(self):
112 mock_input_api = MockInputApi()
113 mock_input_api.files = [
114 MockFile('other/path/foo.h',
115 ['#include <vector>',
116 'vector']),
117 MockFile('other/path/bar.h',
118 ['#include <limits>',
119 '#include <set>',
120 'no_std_namespace']),
121 ]
122 results = PRESUBMIT.CheckForSuperfluousStlIncludesInHeaders(
123 mock_input_api, MockOutputApi())
124 self.assertEqual(1, len(results))
125 self.assertTrue('foo.h: Includes STL' in results[0].message)
126 self.assertTrue('bar.h: Includes STL' in results[0].message)
127
128
glidere61efad2015-02-18 17:39:43129class CheckSingletonInHeadersTest(unittest.TestCase):
130 def testSingletonInArbitraryHeader(self):
131 diff_singleton_h = ['base::subtle::AtomicWord '
olli.raula36aa8be2015-09-10 11:14:22132 'base::Singleton<Type, Traits, DifferentiatingType>::']
133 diff_foo_h = ['// base::Singleton<Foo> in comment.',
134 'friend class base::Singleton<Foo>']
oysteinec430ad42015-10-22 20:55:24135 diff_foo2_h = [' //Foo* bar = base::Singleton<Foo>::get();']
olli.raula36aa8be2015-09-10 11:14:22136 diff_bad_h = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43137 mock_input_api = MockInputApi()
138 mock_input_api.files = [MockAffectedFile('base/memory/singleton.h',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39139 diff_singleton_h),
glidere61efad2015-02-18 17:39:43140 MockAffectedFile('foo.h', diff_foo_h),
oysteinec430ad42015-10-22 20:55:24141 MockAffectedFile('foo2.h', diff_foo2_h),
glidere61efad2015-02-18 17:39:43142 MockAffectedFile('bad.h', diff_bad_h)]
Saagar Sanghavifceeaae2020-08-12 16:40:36143 warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
glidere61efad2015-02-18 17:39:43144 MockOutputApi())
145 self.assertEqual(1, len(warnings))
Sylvain Defresnea8b73d252018-02-28 15:45:54146 self.assertEqual(1, len(warnings[0].items))
glidere61efad2015-02-18 17:39:43147 self.assertEqual('error', warnings[0].type)
olli.raula36aa8be2015-09-10 11:14:22148 self.assertTrue('Found base::Singleton<T>' in warnings[0].message)
glidere61efad2015-02-18 17:39:43149
150 def testSingletonInCC(self):
olli.raula36aa8be2015-09-10 11:14:22151 diff_cc = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43152 mock_input_api = MockInputApi()
153 mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)]
Saagar Sanghavifceeaae2020-08-12 16:40:36154 warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
glidere61efad2015-02-18 17:39:43155 MockOutputApi())
156 self.assertEqual(0, len(warnings))
157
158
Xiaohan Wang42d96c22022-01-20 17:23:11159class DeprecatedOSMacroNamesTest(unittest.TestCase):
160 def testDeprecatedOSMacroNames(self):
161 lines = ['#if defined(OS_WIN)',
[email protected]b00342e7f2013-03-26 16:21:54162 ' #elif defined(OS_WINDOW)',
Xiaohan Wang42d96c22022-01-20 17:23:11163 ' # if defined(OS_MAC) || defined(OS_CHROME)']
164 errors = PRESUBMIT._CheckForDeprecatedOSMacrosInFile(
[email protected]b00342e7f2013-03-26 16:21:54165 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
Xiaohan Wang42d96c22022-01-20 17:23:11166 self.assertEqual(len(lines) + 1, len(errors))
167 self.assertTrue(':1: defined(OS_WIN) -> BUILDFLAG(IS_WIN)' in errors[0])
[email protected]b00342e7f2013-03-26 16:21:54168
169
lliabraa35bab3932014-10-01 12:16:44170class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
171 def testInvalidIfDefinedMacroNames(self):
172 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
173 '#if !defined(TARGET_IPHONE_SIMULATOR)',
174 '#elif defined(TARGET_IPHONE_SIMULATOR)',
175 '#ifdef TARGET_IPHONE_SIMULATOR',
176 ' # ifdef TARGET_IPHONE_SIMULATOR',
177 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
178 '# else // defined(TARGET_IPHONE_SIMULATOR)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39179 '#endif // defined(TARGET_IPHONE_SIMULATOR)']
lliabraa35bab3932014-10-01 12:16:44180 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
181 MockInputApi(), MockFile('some/path/source.mm', lines))
182 self.assertEqual(len(lines), len(errors))
183
184 def testValidIfDefinedMacroNames(self):
185 lines = ['#if defined(FOO)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39186 '#ifdef BAR']
lliabraa35bab3932014-10-01 12:16:44187 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
188 MockInputApi(), MockFile('some/path/source.cc', lines))
189 self.assertEqual(0, len(errors))
190
191
Samuel Huang0db2ea22019-12-09 16:42:47192class CheckAddedDepsHaveTestApprovalsTest(unittest.TestCase):
Daniel Cheng4dcdb6b2017-04-13 08:30:17193
194 def calculate(self, old_include_rules, old_specific_include_rules,
195 new_include_rules, new_specific_include_rules):
196 return PRESUBMIT._CalculateAddedDeps(
197 os.path, 'include_rules = %r\nspecific_include_rules = %r' % (
198 old_include_rules, old_specific_include_rules),
199 'include_rules = %r\nspecific_include_rules = %r' % (
200 new_include_rules, new_specific_include_rules))
201
202 def testCalculateAddedDeps(self):
203 old_include_rules = [
204 '+base',
205 '-chrome',
206 '+content',
207 '-grit',
208 '-grit/",',
209 '+jni/fooblat.h',
210 '!sandbox',
[email protected]f32e2d1e2013-07-26 21:39:08211 ]
Daniel Cheng4dcdb6b2017-04-13 08:30:17212 old_specific_include_rules = {
213 'compositor\.*': {
214 '+cc',
215 },
216 }
217
218 new_include_rules = [
219 '-ash',
220 '+base',
221 '+chrome',
222 '+components',
223 '+content',
224 '+grit',
225 '+grit/generated_resources.h",',
226 '+grit/",',
227 '+jni/fooblat.h',
228 '+policy',
manzagop85e629e2017-05-09 22:11:48229 '+' + os.path.join('third_party', 'WebKit'),
Daniel Cheng4dcdb6b2017-04-13 08:30:17230 ]
231 new_specific_include_rules = {
232 'compositor\.*': {
233 '+cc',
234 },
235 'widget\.*': {
236 '+gpu',
237 },
238 }
239
[email protected]f32e2d1e2013-07-26 21:39:08240 expected = set([
manzagop85e629e2017-05-09 22:11:48241 os.path.join('chrome', 'DEPS'),
242 os.path.join('gpu', 'DEPS'),
243 os.path.join('components', 'DEPS'),
244 os.path.join('policy', 'DEPS'),
245 os.path.join('third_party', 'WebKit', 'DEPS'),
[email protected]f32e2d1e2013-07-26 21:39:08246 ])
Daniel Cheng4dcdb6b2017-04-13 08:30:17247 self.assertEqual(
248 expected,
249 self.calculate(old_include_rules, old_specific_include_rules,
250 new_include_rules, new_specific_include_rules))
251
252 def testCalculateAddedDepsIgnoresPermutations(self):
253 old_include_rules = [
254 '+base',
255 '+chrome',
256 ]
257 new_include_rules = [
258 '+chrome',
259 '+base',
260 ]
261 self.assertEqual(set(),
262 self.calculate(old_include_rules, {}, new_include_rules,
263 {}))
[email protected]f32e2d1e2013-07-26 21:39:08264
265
[email protected]99171a92014-06-03 08:44:47266class JSONParsingTest(unittest.TestCase):
267 def testSuccess(self):
268 input_api = MockInputApi()
269 filename = 'valid_json.json'
270 contents = ['// This is a comment.',
271 '{',
272 ' "key1": ["value1", "value2"],',
273 ' "key2": 3 // This is an inline comment.',
274 '}'
275 ]
276 input_api.files = [MockFile(filename, contents)]
277 self.assertEqual(None,
278 PRESUBMIT._GetJSONParseError(input_api, filename))
279
280 def testFailure(self):
281 input_api = MockInputApi()
282 test_data = [
283 ('invalid_json_1.json',
284 ['{ x }'],
Dirk Prankee3c9c62d2021-05-18 18:35:59285 'Expecting property name'),
[email protected]99171a92014-06-03 08:44:47286 ('invalid_json_2.json',
287 ['// Hello world!',
288 '{ "hello": "world }'],
[email protected]a3343272014-06-17 11:41:53289 'Unterminated string starting at:'),
[email protected]99171a92014-06-03 08:44:47290 ('invalid_json_3.json',
291 ['{ "a": "b", "c": "d", }'],
Dirk Prankee3c9c62d2021-05-18 18:35:59292 'Expecting property name'),
[email protected]99171a92014-06-03 08:44:47293 ('invalid_json_4.json',
294 ['{ "a": "b" "c": "d" }'],
Dirk Prankee3c9c62d2021-05-18 18:35:59295 "Expecting ',' delimiter:"),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39296 ]
[email protected]99171a92014-06-03 08:44:47297
298 input_api.files = [MockFile(filename, contents)
299 for (filename, contents, _) in test_data]
300
301 for (filename, _, expected_error) in test_data:
302 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
[email protected]a3343272014-06-17 11:41:53303 self.assertTrue(expected_error in str(actual_error),
304 "'%s' not found in '%s'" % (expected_error, actual_error))
[email protected]99171a92014-06-03 08:44:47305
306 def testNoEatComments(self):
307 input_api = MockInputApi()
308 file_with_comments = 'file_with_comments.json'
309 contents_with_comments = ['// This is a comment.',
310 '{',
311 ' "key1": ["value1", "value2"],',
312 ' "key2": 3 // This is an inline comment.',
313 '}'
314 ]
315 file_without_comments = 'file_without_comments.json'
316 contents_without_comments = ['{',
317 ' "key1": ["value1", "value2"],',
318 ' "key2": 3',
319 '}'
320 ]
321 input_api.files = [MockFile(file_with_comments, contents_with_comments),
322 MockFile(file_without_comments,
323 contents_without_comments)]
324
Dirk Prankee3c9c62d2021-05-18 18:35:59325 self.assertNotEqual(None,
326 str(PRESUBMIT._GetJSONParseError(input_api,
327 file_with_comments,
328 eat_comments=False)))
[email protected]99171a92014-06-03 08:44:47329 self.assertEqual(None,
330 PRESUBMIT._GetJSONParseError(input_api,
331 file_without_comments,
332 eat_comments=False))
333
334
335class IDLParsingTest(unittest.TestCase):
336 def testSuccess(self):
337 input_api = MockInputApi()
338 filename = 'valid_idl_basics.idl'
339 contents = ['// Tests a valid IDL file.',
340 'namespace idl_basics {',
341 ' enum EnumType {',
342 ' name1,',
343 ' name2',
344 ' };',
345 '',
346 ' dictionary MyType1 {',
347 ' DOMString a;',
348 ' };',
349 '',
350 ' callback Callback1 = void();',
351 ' callback Callback2 = void(long x);',
352 ' callback Callback3 = void(MyType1 arg);',
353 ' callback Callback4 = void(EnumType type);',
354 '',
355 ' interface Functions {',
356 ' static void function1();',
357 ' static void function2(long x);',
358 ' static void function3(MyType1 arg);',
359 ' static void function4(Callback1 cb);',
360 ' static void function5(Callback2 cb);',
361 ' static void function6(Callback3 cb);',
362 ' static void function7(Callback4 cb);',
363 ' };',
364 '',
365 ' interface Events {',
366 ' static void onFoo1();',
367 ' static void onFoo2(long x);',
368 ' static void onFoo2(MyType1 arg);',
369 ' static void onFoo3(EnumType type);',
370 ' };',
371 '};'
372 ]
373 input_api.files = [MockFile(filename, contents)]
374 self.assertEqual(None,
375 PRESUBMIT._GetIDLParseError(input_api, filename))
376
377 def testFailure(self):
378 input_api = MockInputApi()
379 test_data = [
380 ('invalid_idl_1.idl',
381 ['//',
382 'namespace test {',
383 ' dictionary {',
384 ' DOMString s;',
385 ' };',
386 '};'],
387 'Unexpected "{" after keyword "dictionary".\n'),
388 # TODO(yoz): Disabled because it causes the IDL parser to hang.
389 # See crbug.com/363830.
390 # ('invalid_idl_2.idl',
391 # (['namespace test {',
392 # ' dictionary MissingSemicolon {',
393 # ' DOMString a',
394 # ' DOMString b;',
395 # ' };',
396 # '};'],
397 # 'Unexpected symbol DOMString after symbol a.'),
398 ('invalid_idl_3.idl',
399 ['//',
400 'namespace test {',
401 ' enum MissingComma {',
402 ' name1',
403 ' name2',
404 ' };',
405 '};'],
406 'Unexpected symbol name2 after symbol name1.'),
407 ('invalid_idl_4.idl',
408 ['//',
409 'namespace test {',
410 ' enum TrailingComma {',
411 ' name1,',
412 ' name2,',
413 ' };',
414 '};'],
415 'Trailing comma in block.'),
416 ('invalid_idl_5.idl',
417 ['//',
418 'namespace test {',
419 ' callback Callback1 = void(;',
420 '};'],
421 'Unexpected ";" after "(".'),
422 ('invalid_idl_6.idl',
423 ['//',
424 'namespace test {',
425 ' callback Callback1 = void(long );',
426 '};'],
427 'Unexpected ")" after symbol long.'),
428 ('invalid_idl_7.idl',
429 ['//',
430 'namespace test {',
431 ' interace Events {',
432 ' static void onFoo1();',
433 ' };',
434 '};'],
435 'Unexpected symbol Events after symbol interace.'),
436 ('invalid_idl_8.idl',
437 ['//',
438 'namespace test {',
439 ' interface NotEvent {',
440 ' static void onFoo1();',
441 ' };',
442 '};'],
443 'Did not process Interface Interface(NotEvent)'),
444 ('invalid_idl_9.idl',
445 ['//',
446 'namespace test {',
447 ' interface {',
448 ' static void function1();',
449 ' };',
450 '};'],
451 'Interface missing name.'),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39452 ]
[email protected]99171a92014-06-03 08:44:47453
454 input_api.files = [MockFile(filename, contents)
455 for (filename, contents, _) in test_data]
456
457 for (filename, _, expected_error) in test_data:
458 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
459 self.assertTrue(expected_error in str(actual_error),
460 "'%s' not found in '%s'" % (expected_error, actual_error))
461
462
davileene0426252015-03-02 21:10:41463class UserMetricsActionTest(unittest.TestCase):
464 def testUserMetricsActionInActions(self):
465 input_api = MockInputApi()
466 file_with_user_action = 'file_with_user_action.cc'
467 contents_with_user_action = [
468 'base::UserMetricsAction("AboutChrome")'
469 ]
470
471 input_api.files = [MockFile(file_with_user_action,
472 contents_with_user_action)]
473
474 self.assertEqual(
Saagar Sanghavifceeaae2020-08-12 16:40:36475 [], PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi()))
davileene0426252015-03-02 21:10:41476
davileene0426252015-03-02 21:10:41477 def testUserMetricsActionNotAddedToActions(self):
478 input_api = MockInputApi()
479 file_with_user_action = 'file_with_user_action.cc'
480 contents_with_user_action = [
481 'base::UserMetricsAction("NotInActionsXml")'
482 ]
483
484 input_api.files = [MockFile(file_with_user_action,
485 contents_with_user_action)]
486
Saagar Sanghavifceeaae2020-08-12 16:40:36487 output = PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi())
davileene0426252015-03-02 21:10:41488 self.assertEqual(
489 ('File %s line %d: %s is missing in '
490 'tools/metrics/actions/actions.xml. Please run '
491 'tools/metrics/actions/extract_actions.py to update.'
492 % (file_with_user_action, 1, 'NotInActionsXml')),
493 output[0].message)
494
Alexei Svitkine64505a92021-03-11 22:00:54495 def testUserMetricsActionInTestFile(self):
496 input_api = MockInputApi()
497 file_with_user_action = 'file_with_user_action_unittest.cc'
498 contents_with_user_action = [
499 'base::UserMetricsAction("NotInActionsXml")'
500 ]
501
502 input_api.files = [MockFile(file_with_user_action,
503 contents_with_user_action)]
504
505 self.assertEqual(
506 [], PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi()))
507
davileene0426252015-03-02 21:10:41508
agrievef32bcc72016-04-04 14:57:40509class PydepsNeedsUpdatingTest(unittest.TestCase):
Andrew Grieve4deedb12022-02-03 21:34:50510 class MockPopen:
511 def __init__(self, stdout_func):
512 self._stdout_func = stdout_func
agrievef32bcc72016-04-04 14:57:40513
Andrew Grieve4deedb12022-02-03 21:34:50514 def wait(self):
515 self.stdout = io.StringIO(self._stdout_func())
516 return 0
517
518 class MockSubprocess:
agrievef32bcc72016-04-04 14:57:40519 CalledProcessError = subprocess.CalledProcessError
Andrew Grieve4deedb12022-02-03 21:34:50520 PIPE = 0
521
522 def __init__(self):
523 self._popen_func = None
524
525 def SetPopenCallback(self, func):
526 self._popen_func = func
527
528 def Popen(self, cmd, *args, **kwargs):
529 return PydepsNeedsUpdatingTest.MockPopen(lambda: self._popen_func(cmd))
agrievef32bcc72016-04-04 14:57:40530
Mohamed Heikal7cd4d8312020-06-16 16:49:40531 def _MockParseGclientArgs(self, is_android=True):
532 return lambda: {'checkout_android': 'true' if is_android else 'false' }
533
agrievef32bcc72016-04-04 14:57:40534 def setUp(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40535 mock_all_pydeps = ['A.pydeps', 'B.pydeps', 'D.pydeps']
agrievef32bcc72016-04-04 14:57:40536 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
537 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
Mohamed Heikal7cd4d8312020-06-16 16:49:40538 mock_android_pydeps = ['D.pydeps']
539 self.old_ANDROID_SPECIFIC_PYDEPS_FILES = (
540 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES)
541 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = mock_android_pydeps
542 self.old_ParseGclientArgs = PRESUBMIT._ParseGclientArgs
543 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs()
agrievef32bcc72016-04-04 14:57:40544 self.mock_input_api = MockInputApi()
545 self.mock_output_api = MockOutputApi()
546 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
547 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
548 self.checker._file_cache = {
Andrew Grieve5bb4cf702020-10-22 20:21:39549 'A.pydeps': '# Generated by:\n# CMD --output A.pydeps A\nA.py\nC.py\n',
550 'B.pydeps': '# Generated by:\n# CMD --output B.pydeps B\nB.py\nC.py\n',
551 'D.pydeps': '# Generated by:\n# CMD --output D.pydeps D\nD.py\n',
agrievef32bcc72016-04-04 14:57:40552 }
553
554 def tearDown(self):
555 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
Mohamed Heikal7cd4d8312020-06-16 16:49:40556 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = (
557 self.old_ANDROID_SPECIFIC_PYDEPS_FILES)
558 PRESUBMIT._ParseGclientArgs = self.old_ParseGclientArgs
agrievef32bcc72016-04-04 14:57:40559
560 def _RunCheck(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36561 return PRESUBMIT.CheckPydepsNeedsUpdating(self.mock_input_api,
agrievef32bcc72016-04-04 14:57:40562 self.mock_output_api,
563 checker_for_tests=self.checker)
564
565 def testAddedPydep(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36566 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30567 if not self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13568 return []
569
agrievef32bcc72016-04-04 14:57:40570 self.mock_input_api.files = [
571 MockAffectedFile('new.pydeps', [], action='A'),
572 ]
573
Zhiling Huang45cabf32018-03-10 00:50:03574 self.mock_input_api.CreateMockFileInPath(
575 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
576 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40577 results = self._RunCheck()
578 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39579 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40580
Zhiling Huang45cabf32018-03-10 00:50:03581 def testPydepNotInSrc(self):
582 self.mock_input_api.files = [
583 MockAffectedFile('new.pydeps', [], action='A'),
584 ]
585 self.mock_input_api.CreateMockFileInPath([])
586 results = self._RunCheck()
587 self.assertEqual(0, len(results))
588
agrievef32bcc72016-04-04 14:57:40589 def testRemovedPydep(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36590 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30591 if not self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13592 return []
593
agrievef32bcc72016-04-04 14:57:40594 self.mock_input_api.files = [
595 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
596 ]
Zhiling Huang45cabf32018-03-10 00:50:03597 self.mock_input_api.CreateMockFileInPath(
598 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
599 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40600 results = self._RunCheck()
601 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39602 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40603
604 def testRandomPyIgnored(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36605 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30606 if not self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13607 return []
608
agrievef32bcc72016-04-04 14:57:40609 self.mock_input_api.files = [
610 MockAffectedFile('random.py', []),
611 ]
612
613 results = self._RunCheck()
614 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
615
616 def testRelevantPyNoChange(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36617 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30618 if not self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13619 return []
620
agrievef32bcc72016-04-04 14:57:40621 self.mock_input_api.files = [
622 MockAffectedFile('A.py', []),
623 ]
624
Andrew Grieve4deedb12022-02-03 21:34:50625 def popen_callback(cmd):
Andrew Grieve5bb4cf702020-10-22 20:21:39626 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
agrievef32bcc72016-04-04 14:57:40627 return self.checker._file_cache['A.pydeps']
628
Andrew Grieve4deedb12022-02-03 21:34:50629 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
agrievef32bcc72016-04-04 14:57:40630
631 results = self._RunCheck()
632 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
633
634 def testRelevantPyOneChange(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36635 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30636 if not self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13637 return []
638
agrievef32bcc72016-04-04 14:57:40639 self.mock_input_api.files = [
640 MockAffectedFile('A.py', []),
641 ]
642
Andrew Grieve4deedb12022-02-03 21:34:50643 def popen_callback(cmd):
Andrew Grieve5bb4cf702020-10-22 20:21:39644 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
agrievef32bcc72016-04-04 14:57:40645 return 'changed data'
646
Andrew Grieve4deedb12022-02-03 21:34:50647 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
agrievef32bcc72016-04-04 14:57:40648
649 results = self._RunCheck()
650 self.assertEqual(1, len(results))
Andrew Grieve4deedb12022-02-03 21:34:50651 # Check that --output "" is not included.
652 self.assertNotIn('""', str(results[0]))
Andrew Grieve5bb4cf702020-10-22 20:21:39653 self.assertIn('File is stale', str(results[0]))
agrievef32bcc72016-04-04 14:57:40654
655 def testRelevantPyTwoChanges(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36656 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30657 if not self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13658 return []
659
agrievef32bcc72016-04-04 14:57:40660 self.mock_input_api.files = [
661 MockAffectedFile('C.py', []),
662 ]
663
Andrew Grieve4deedb12022-02-03 21:34:50664 def popen_callback(cmd):
agrievef32bcc72016-04-04 14:57:40665 return 'changed data'
666
Andrew Grieve4deedb12022-02-03 21:34:50667 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
agrievef32bcc72016-04-04 14:57:40668
669 results = self._RunCheck()
670 self.assertEqual(2, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39671 self.assertIn('File is stale', str(results[0]))
672 self.assertIn('File is stale', str(results[1]))
agrievef32bcc72016-04-04 14:57:40673
Mohamed Heikal7cd4d8312020-06-16 16:49:40674 def testRelevantAndroidPyInNonAndroidCheckout(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36675 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30676 if not self.mock_input_api.platform.startswith('linux'):
Mohamed Heikal7cd4d8312020-06-16 16:49:40677 return []
678
679 self.mock_input_api.files = [
680 MockAffectedFile('D.py', []),
681 ]
682
Andrew Grieve4deedb12022-02-03 21:34:50683 def popen_callback(cmd):
Andrew Grieve5bb4cf702020-10-22 20:21:39684 self.assertEqual('CMD --output D.pydeps D --output ""', cmd)
Mohamed Heikal7cd4d8312020-06-16 16:49:40685 return 'changed data'
686
Andrew Grieve4deedb12022-02-03 21:34:50687 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
Mohamed Heikal7cd4d8312020-06-16 16:49:40688 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs(is_android=False)
689
690 results = self._RunCheck()
691 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39692 self.assertIn('Android', str(results[0]))
693 self.assertIn('D.pydeps', str(results[0]))
694
695 def testGnPathsAndMissingOutputFlag(self):
696 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Xiaohan Wangcef8b002022-01-20 21:34:30697 if not self.mock_input_api.platform.startswith('linux'):
Andrew Grieve5bb4cf702020-10-22 20:21:39698 return []
699
700 self.checker._file_cache = {
701 'A.pydeps': '# Generated by:\n# CMD --gn-paths A\n//A.py\n//C.py\n',
702 'B.pydeps': '# Generated by:\n# CMD --gn-paths B\n//B.py\n//C.py\n',
703 'D.pydeps': '# Generated by:\n# CMD --gn-paths D\n//D.py\n',
704 }
705
706 self.mock_input_api.files = [
707 MockAffectedFile('A.py', []),
708 ]
709
Andrew Grieve4deedb12022-02-03 21:34:50710 def popen_callback(cmd):
Andrew Grieve5bb4cf702020-10-22 20:21:39711 self.assertEqual('CMD --gn-paths A --output A.pydeps --output ""', cmd)
712 return 'changed data'
713
Andrew Grieve4deedb12022-02-03 21:34:50714 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
Andrew Grieve5bb4cf702020-10-22 20:21:39715
716 results = self._RunCheck()
717 self.assertEqual(1, len(results))
718 self.assertIn('File is stale', str(results[0]))
Mohamed Heikal7cd4d8312020-06-16 16:49:40719
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39720
Daniel Bratell8ba52722018-03-02 16:06:14721class IncludeGuardTest(unittest.TestCase):
722 def testIncludeGuardChecks(self):
723 mock_input_api = MockInputApi()
724 mock_output_api = MockOutputApi()
725 mock_input_api.files = [
726 MockAffectedFile('content/browser/thing/foo.h', [
727 '// Comment',
728 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
729 '#define CONTENT_BROWSER_THING_FOO_H_',
730 'struct McBoatFace;',
731 '#endif // CONTENT_BROWSER_THING_FOO_H_',
732 ]),
733 MockAffectedFile('content/browser/thing/bar.h', [
734 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
735 '#define CONTENT_BROWSER_THING_BAR_H_',
736 'namespace content {',
737 '#endif // CONTENT_BROWSER_THING_BAR_H_',
738 '} // namespace content',
739 ]),
740 MockAffectedFile('content/browser/test1.h', [
741 'namespace content {',
742 '} // namespace content',
743 ]),
744 MockAffectedFile('content\\browser\\win.h', [
745 '#ifndef CONTENT_BROWSER_WIN_H_',
746 '#define CONTENT_BROWSER_WIN_H_',
747 'struct McBoatFace;',
748 '#endif // CONTENT_BROWSER_WIN_H_',
749 ]),
750 MockAffectedFile('content/browser/test2.h', [
751 '// Comment',
752 '#ifndef CONTENT_BROWSER_TEST2_H_',
753 'struct McBoatFace;',
754 '#endif // CONTENT_BROWSER_TEST2_H_',
755 ]),
756 MockAffectedFile('content/browser/internal.h', [
757 '// Comment',
758 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
759 '#define CONTENT_BROWSER_INTERNAL_H_',
760 '// Comment',
761 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
762 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
763 'namespace internal {',
764 '} // namespace internal',
765 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
766 'namespace content {',
767 '} // namespace content',
768 '#endif // CONTENT_BROWSER_THING_BAR_H_',
769 ]),
770 MockAffectedFile('content/browser/thing/foo.cc', [
771 '// This is a non-header.',
772 ]),
773 MockAffectedFile('content/browser/disabled.h', [
774 '// no-include-guard-because-multiply-included',
775 'struct McBoatFace;',
776 ]),
777 # New files don't allow misspelled include guards.
778 MockAffectedFile('content/browser/spleling.h', [
779 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
780 '#define CONTENT_BROWSER_SPLLEING_H_',
781 'struct McBoatFace;',
782 '#endif // CONTENT_BROWSER_SPLLEING_H_',
783 ]),
Olivier Robinbba137492018-07-30 11:31:34784 # New files don't allow + in include guards.
785 MockAffectedFile('content/browser/foo+bar.h', [
786 '#ifndef CONTENT_BROWSER_FOO+BAR_H_',
787 '#define CONTENT_BROWSER_FOO+BAR_H_',
788 'struct McBoatFace;',
789 '#endif // CONTENT_BROWSER_FOO+BAR_H_',
790 ]),
Daniel Bratell8ba52722018-03-02 16:06:14791 # Old files allow misspelled include guards (for now).
792 MockAffectedFile('chrome/old.h', [
793 '// New contents',
794 '#ifndef CHROME_ODL_H_',
795 '#define CHROME_ODL_H_',
796 '#endif // CHROME_ODL_H_',
797 ], [
798 '// Old contents',
799 '#ifndef CHROME_ODL_H_',
800 '#define CHROME_ODL_H_',
801 '#endif // CHROME_ODL_H_',
802 ]),
803 # Using a Blink style include guard outside Blink is wrong.
804 MockAffectedFile('content/NotInBlink.h', [
805 '#ifndef NotInBlink_h',
806 '#define NotInBlink_h',
807 'struct McBoatFace;',
808 '#endif // NotInBlink_h',
809 ]),
Daniel Bratell39b5b062018-05-16 18:09:57810 # Using a Blink style include guard in Blink is no longer ok.
811 MockAffectedFile('third_party/blink/InBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14812 '#ifndef InBlink_h',
813 '#define InBlink_h',
814 'struct McBoatFace;',
815 '#endif // InBlink_h',
816 ]),
817 # Using a bad include guard in Blink is not ok.
Daniel Bratell39b5b062018-05-16 18:09:57818 MockAffectedFile('third_party/blink/AlsoInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14819 '#ifndef WrongInBlink_h',
820 '#define WrongInBlink_h',
821 'struct McBoatFace;',
822 '#endif // WrongInBlink_h',
823 ]),
Daniel Bratell39b5b062018-05-16 18:09:57824 # Using a bad include guard in Blink is not accepted even if
825 # it's an old file.
826 MockAffectedFile('third_party/blink/StillInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14827 '// New contents',
828 '#ifndef AcceptedInBlink_h',
829 '#define AcceptedInBlink_h',
830 'struct McBoatFace;',
831 '#endif // AcceptedInBlink_h',
832 ], [
833 '// Old contents',
834 '#ifndef AcceptedInBlink_h',
835 '#define AcceptedInBlink_h',
836 'struct McBoatFace;',
837 '#endif // AcceptedInBlink_h',
838 ]),
Daniel Bratell39b5b062018-05-16 18:09:57839 # Using a non-Chromium include guard in third_party
840 # (outside blink) is accepted.
841 MockAffectedFile('third_party/foo/some_file.h', [
842 '#ifndef REQUIRED_RPCNDR_H_',
843 '#define REQUIRED_RPCNDR_H_',
844 'struct SomeFileFoo;',
845 '#endif // REQUIRED_RPCNDR_H_',
846 ]),
Kinuko Yasuda0cdb3da2019-07-31 21:50:32847 # Not having proper include guard in *_message_generator.h
848 # for old IPC messages is allowed.
849 MockAffectedFile('content/common/content_message_generator.h', [
850 '#undef CONTENT_COMMON_FOO_MESSAGES_H_',
851 '#include "content/common/foo_messages.h"',
852 '#ifndef CONTENT_COMMON_FOO_MESSAGES_H_',
853 '#error "Failed to include content/common/foo_messages.h"',
854 '#endif',
855 ]),
Daniel Bratell8ba52722018-03-02 16:06:14856 ]
Saagar Sanghavifceeaae2020-08-12 16:40:36857 msgs = PRESUBMIT.CheckForIncludeGuards(
Daniel Bratell8ba52722018-03-02 16:06:14858 mock_input_api, mock_output_api)
Olivier Robinbba137492018-07-30 11:31:34859 expected_fail_count = 8
Daniel Bratell8ba52722018-03-02 16:06:14860 self.assertEqual(expected_fail_count, len(msgs),
861 'Expected %d items, found %d: %s'
862 % (expected_fail_count, len(msgs), msgs))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39863 self.assertEqual(msgs[0].items, ['content/browser/thing/bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:14864 self.assertEqual(msgs[0].message,
865 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
866 'not covering the whole file')
867
Bruce Dawson32114b62022-04-11 16:45:49868 self.assertIn('content/browser/test1.h', msgs[1].message)
869 self.assertIn('Recommended name: CONTENT_BROWSER_TEST1_H_',
870 msgs[1].message)
Daniel Bratell8ba52722018-03-02 16:06:14871
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39872 self.assertEqual(msgs[2].items, ['content/browser/test2.h:3'])
Daniel Bratell8ba52722018-03-02 16:06:14873 self.assertEqual(msgs[2].message,
874 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
875 'include guard')
876
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39877 self.assertEqual(msgs[3].items, ['content/browser/spleling.h:1'])
Daniel Bratell8ba52722018-03-02 16:06:14878 self.assertEqual(msgs[3].message,
879 'Header using the wrong include guard name '
880 'CONTENT_BROWSER_SPLLEING_H_')
881
Bruce Dawson32114b62022-04-11 16:45:49882 self.assertIn('content/browser/foo+bar.h', msgs[4].message)
883 self.assertIn('Recommended name: CONTENT_BROWSER_FOO_BAR_H_',
884 msgs[4].message)
Olivier Robinbba137492018-07-30 11:31:34885
886 self.assertEqual(msgs[5].items, ['content/NotInBlink.h:1'])
887 self.assertEqual(msgs[5].message,
Daniel Bratell8ba52722018-03-02 16:06:14888 'Header using the wrong include guard name '
889 'NotInBlink_h')
890
Olivier Robinbba137492018-07-30 11:31:34891 self.assertEqual(msgs[6].items, ['third_party/blink/InBlink.h:1'])
892 self.assertEqual(msgs[6].message,
Daniel Bratell8ba52722018-03-02 16:06:14893 'Header using the wrong include guard name '
Daniel Bratell39b5b062018-05-16 18:09:57894 'InBlink_h')
895
Olivier Robinbba137492018-07-30 11:31:34896 self.assertEqual(msgs[7].items, ['third_party/blink/AlsoInBlink.h:1'])
897 self.assertEqual(msgs[7].message,
Daniel Bratell39b5b062018-05-16 18:09:57898 'Header using the wrong include guard name '
Daniel Bratell8ba52722018-03-02 16:06:14899 'WrongInBlink_h')
900
Chris Hall59f8d0c72020-05-01 07:31:19901class AccessibilityRelnotesFieldTest(unittest.TestCase):
902 def testRelnotesPresent(self):
903 mock_input_api = MockInputApi()
904 mock_output_api = MockOutputApi()
905
906 mock_input_api.files = [MockAffectedFile('ui/accessibility/foo.bar', [''])]
Akihiro Ota08108e542020-05-20 15:30:53907 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19908 mock_input_api.change.footers['AX-Relnotes'] = [
909 'Important user facing change']
910
Saagar Sanghavifceeaae2020-08-12 16:40:36911 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19912 mock_input_api, mock_output_api)
913 self.assertEqual(0, len(msgs),
914 'Expected %d messages, found %d: %s'
915 % (0, len(msgs), msgs))
916
917 def testRelnotesMissingFromAccessibilityChange(self):
918 mock_input_api = MockInputApi()
919 mock_output_api = MockOutputApi()
920
921 mock_input_api.files = [
922 MockAffectedFile('some/file', ['']),
923 MockAffectedFile('ui/accessibility/foo.bar', ['']),
924 MockAffectedFile('some/other/file', [''])
925 ]
Akihiro Ota08108e542020-05-20 15:30:53926 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19927
Saagar Sanghavifceeaae2020-08-12 16:40:36928 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19929 mock_input_api, mock_output_api)
930 self.assertEqual(1, len(msgs),
931 'Expected %d messages, found %d: %s'
932 % (1, len(msgs), msgs))
933 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
934 'Missing AX-Relnotes field message not found in errors')
935
936 # The relnotes footer is not required for changes which do not touch any
937 # accessibility directories.
938 def testIgnoresNonAccesssibilityCode(self):
939 mock_input_api = MockInputApi()
940 mock_output_api = MockOutputApi()
941
942 mock_input_api.files = [
943 MockAffectedFile('some/file', ['']),
944 MockAffectedFile('some/other/file', [''])
945 ]
Akihiro Ota08108e542020-05-20 15:30:53946 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19947
Saagar Sanghavifceeaae2020-08-12 16:40:36948 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19949 mock_input_api, mock_output_api)
950 self.assertEqual(0, len(msgs),
951 'Expected %d messages, found %d: %s'
952 % (0, len(msgs), msgs))
953
954 # Test that our presubmit correctly raises an error for a set of known paths.
955 def testExpectedPaths(self):
956 filesToTest = [
957 "chrome/browser/accessibility/foo.py",
Henrique Ferreirobb1bb4a2021-03-18 00:04:08958 "chrome/browser/ash/arc/accessibility/foo.cc",
Chris Hall59f8d0c72020-05-01 07:31:19959 "chrome/browser/ui/views/accessibility/foo.h",
960 "chrome/browser/extensions/api/automation/foo.h",
961 "chrome/browser/extensions/api/automation_internal/foo.cc",
962 "chrome/renderer/extensions/accessibility_foo.h",
963 "chrome/tests/data/accessibility/foo.html",
964 "content/browser/accessibility/foo.cc",
965 "content/renderer/accessibility/foo.h",
966 "content/tests/data/accessibility/foo.cc",
967 "extensions/renderer/api/automation/foo.h",
968 "ui/accessibility/foo/bar/baz.cc",
969 "ui/views/accessibility/foo/bar/baz.h",
970 ]
971
972 for testFile in filesToTest:
973 mock_input_api = MockInputApi()
974 mock_output_api = MockOutputApi()
975
976 mock_input_api.files = [
977 MockAffectedFile(testFile, [''])
978 ]
Akihiro Ota08108e542020-05-20 15:30:53979 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19980
Saagar Sanghavifceeaae2020-08-12 16:40:36981 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19982 mock_input_api, mock_output_api)
983 self.assertEqual(1, len(msgs),
984 'Expected %d messages, found %d: %s, for file %s'
985 % (1, len(msgs), msgs, testFile))
986 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
987 ('Missing AX-Relnotes field message not found in errors '
988 ' for file %s' % (testFile)))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39989
Akihiro Ota08108e542020-05-20 15:30:53990 # Test that AX-Relnotes field can appear in the commit description (as long
991 # as it appears at the beginning of a line).
992 def testRelnotesInCommitDescription(self):
993 mock_input_api = MockInputApi()
994 mock_output_api = MockOutputApi()
995
996 mock_input_api.files = [
997 MockAffectedFile('ui/accessibility/foo.bar', ['']),
998 ]
999 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1000 'AX-Relnotes: solves all accessibility issues forever')
1001
Saagar Sanghavifceeaae2020-08-12 16:40:361002 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531003 mock_input_api, mock_output_api)
1004 self.assertEqual(0, len(msgs),
1005 'Expected %d messages, found %d: %s'
1006 % (0, len(msgs), msgs))
1007
1008 # Test that we don't match AX-Relnotes if it appears in the middle of a line.
1009 def testRelnotesMustAppearAtBeginningOfLine(self):
1010 mock_input_api = MockInputApi()
1011 mock_output_api = MockOutputApi()
1012
1013 mock_input_api.files = [
1014 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1015 ]
1016 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1017 'This change has no AX-Relnotes: we should print a warning')
1018
Saagar Sanghavifceeaae2020-08-12 16:40:361019 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531020 mock_input_api, mock_output_api)
1021 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1022 'Missing AX-Relnotes field message not found in errors')
1023
1024 # Tests that the AX-Relnotes field can be lowercase and use a '=' in place
1025 # of a ':'.
1026 def testRelnotesLowercaseWithEqualSign(self):
1027 mock_input_api = MockInputApi()
1028 mock_output_api = MockOutputApi()
1029
1030 mock_input_api.files = [
1031 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1032 ]
1033 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1034 'ax-relnotes= this is a valid format for accessibiliy relnotes')
1035
Saagar Sanghavifceeaae2020-08-12 16:40:361036 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531037 mock_input_api, mock_output_api)
1038 self.assertEqual(0, len(msgs),
1039 'Expected %d messages, found %d: %s'
1040 % (0, len(msgs), msgs))
1041
Mark Schillacie5a0be22022-01-19 00:38:391042class AccessibilityEventsTestsAreIncludedForAndroidTest(unittest.TestCase):
1043 # Test that no warning is raised when the Android file is also modified.
1044 def testAndroidChangeIncluded(self):
1045 mock_input_api = MockInputApi()
1046
1047 mock_input_api.files = [
1048 MockAffectedFile('content/test/data/accessibility/event/foo.html',
1049 [''], action='A'),
1050 MockAffectedFile(
1051 'accessibility/WebContentsAccessibilityEventsTest.java',
1052 [''], action='M')
1053 ]
1054
1055 msgs = PRESUBMIT.CheckAccessibilityEventsTestsAreIncludedForAndroid(
1056 mock_input_api, MockOutputApi())
1057 self.assertEqual(0, len(msgs),
1058 'Expected %d messages, found %d: %s'
1059 % (0, len(msgs), msgs))
1060
1061 # Test that a warning is raised when the Android file is not modified.
1062 def testAndroidChangeMissing(self):
1063 mock_input_api = MockInputApi()
1064
1065 mock_input_api.files = [
1066 MockAffectedFile('content/test/data/accessibility/event/foo.html',
1067 [''], action='A'),
1068 ]
1069
1070 msgs = PRESUBMIT.CheckAccessibilityEventsTestsAreIncludedForAndroid(
1071 mock_input_api, MockOutputApi())
1072 self.assertEqual(1, len(msgs),
1073 'Expected %d messages, found %d: %s'
1074 % (1, len(msgs), msgs))
1075
1076 # Test that Android change is not required when no html file is added/removed.
1077 def testIgnoreNonHtmlFiles(self):
1078 mock_input_api = MockInputApi()
1079
1080 mock_input_api.files = [
1081 MockAffectedFile('content/test/data/accessibility/event/foo.txt',
1082 [''], action='A'),
1083 MockAffectedFile('content/test/data/accessibility/event/foo.cc',
1084 [''], action='A'),
1085 MockAffectedFile('content/test/data/accessibility/event/foo.h',
1086 [''], action='A'),
1087 MockAffectedFile('content/test/data/accessibility/event/foo.py',
1088 [''], action='A')
1089 ]
1090
1091 msgs = PRESUBMIT.CheckAccessibilityEventsTestsAreIncludedForAndroid(
1092 mock_input_api, MockOutputApi())
1093 self.assertEqual(0, len(msgs),
1094 'Expected %d messages, found %d: %s'
1095 % (0, len(msgs), msgs))
1096
1097 # Test that Android change is not required for unrelated html files.
1098 def testIgnoreNonRelatedHtmlFiles(self):
1099 mock_input_api = MockInputApi()
1100
1101 mock_input_api.files = [
1102 MockAffectedFile('content/test/data/accessibility/aria/foo.html',
1103 [''], action='A'),
1104 MockAffectedFile('content/test/data/accessibility/html/foo.html',
1105 [''], action='A'),
1106 MockAffectedFile('chrome/tests/data/accessibility/foo.html',
1107 [''], action='A')
1108 ]
1109
1110 msgs = PRESUBMIT.CheckAccessibilityEventsTestsAreIncludedForAndroid(
1111 mock_input_api, MockOutputApi())
1112 self.assertEqual(0, len(msgs),
1113 'Expected %d messages, found %d: %s'
1114 % (0, len(msgs), msgs))
1115
1116 # Test that only modifying an html file will not trigger the warning.
1117 def testIgnoreModifiedFiles(self):
1118 mock_input_api = MockInputApi()
1119
1120 mock_input_api.files = [
1121 MockAffectedFile('content/test/data/accessibility/event/foo.html',
1122 [''], action='M')
1123 ]
1124
1125 msgs = PRESUBMIT.CheckAccessibilityEventsTestsAreIncludedForAndroid(
1126 mock_input_api, MockOutputApi())
1127 self.assertEqual(0, len(msgs),
1128 'Expected %d messages, found %d: %s'
1129 % (0, len(msgs), msgs))
1130
1131 # Test that deleting an html file will trigger the warning.
1132 def testAndroidChangeMissingOnDeletedFile(self):
1133 mock_input_api = MockInputApi()
1134
1135 mock_input_api.files = [
1136 MockAffectedFile('content/test/data/accessibility/event/foo.html',
1137 [], action='D')
1138 ]
1139
1140 msgs = PRESUBMIT.CheckAccessibilityEventsTestsAreIncludedForAndroid(
1141 mock_input_api, MockOutputApi())
1142 self.assertEqual(1, len(msgs),
1143 'Expected %d messages, found %d: %s'
1144 % (1, len(msgs), msgs))
1145
1146class AccessibilityTreeTestsAreIncludedForAndroidTest(unittest.TestCase):
1147 # Test that no warning is raised when the Android file is also modified.
1148 def testAndroidChangeIncluded(self):
1149 mock_input_api = MockInputApi()
1150
1151 mock_input_api.files = [
1152 MockAffectedFile('content/test/data/accessibility/aria/foo.html',
1153 [''], action='A'),
1154 MockAffectedFile(
Mark Schillaci6f568a52022-02-17 18:41:441155 'accessibility/WebContentsAccessibilityTreeTest.java',
Mark Schillacie5a0be22022-01-19 00:38:391156 [''], action='M')
1157 ]
1158
1159 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1160 mock_input_api, MockOutputApi())
1161 self.assertEqual(0, len(msgs),
1162 'Expected %d messages, found %d: %s'
1163 % (0, len(msgs), msgs))
1164
1165 # Test that no warning is raised when the Android file is also modified.
1166 def testAndroidChangeIncludedManyFiles(self):
1167 mock_input_api = MockInputApi()
1168
1169 mock_input_api.files = [
1170 MockAffectedFile('content/test/data/accessibility/accname/foo.html',
1171 [''], action='A'),
1172 MockAffectedFile('content/test/data/accessibility/aria/foo.html',
1173 [''], action='A'),
1174 MockAffectedFile('content/test/data/accessibility/css/foo.html',
1175 [''], action='A'),
1176 MockAffectedFile('content/test/data/accessibility/html/foo.html',
1177 [''], action='A'),
1178 MockAffectedFile(
Mark Schillaci6f568a52022-02-17 18:41:441179 'accessibility/WebContentsAccessibilityTreeTest.java',
Mark Schillacie5a0be22022-01-19 00:38:391180 [''], action='M')
1181 ]
1182
1183 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1184 mock_input_api, MockOutputApi())
1185 self.assertEqual(0, len(msgs),
1186 'Expected %d messages, found %d: %s'
1187 % (0, len(msgs), msgs))
1188
1189 # Test that a warning is raised when the Android file is not modified.
1190 def testAndroidChangeMissing(self):
1191 mock_input_api = MockInputApi()
1192
1193 mock_input_api.files = [
1194 MockAffectedFile('content/test/data/accessibility/aria/foo.html',
1195 [''], action='A'),
1196 ]
1197
1198 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1199 mock_input_api, MockOutputApi())
1200 self.assertEqual(1, len(msgs),
1201 'Expected %d messages, found %d: %s'
1202 % (1, len(msgs), msgs))
1203
1204 # Test that Android change is not required when no html file is added/removed.
1205 def testIgnoreNonHtmlFiles(self):
1206 mock_input_api = MockInputApi()
1207
1208 mock_input_api.files = [
1209 MockAffectedFile('content/test/data/accessibility/accname/foo.txt',
1210 [''], action='A'),
1211 MockAffectedFile('content/test/data/accessibility/aria/foo.cc',
1212 [''], action='A'),
1213 MockAffectedFile('content/test/data/accessibility/css/foo.h',
1214 [''], action='A'),
1215 MockAffectedFile('content/test/data/accessibility/tree/foo.py',
1216 [''], action='A')
1217 ]
1218
1219 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1220 mock_input_api, MockOutputApi())
1221 self.assertEqual(0, len(msgs),
1222 'Expected %d messages, found %d: %s'
1223 % (0, len(msgs), msgs))
1224
1225 # Test that Android change is not required for unrelated html files.
1226 def testIgnoreNonRelatedHtmlFiles(self):
1227 mock_input_api = MockInputApi()
1228
1229 mock_input_api.files = [
1230 MockAffectedFile('content/test/data/accessibility/event/foo.html',
1231 [''], action='A'),
1232 ]
1233
1234 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1235 mock_input_api, MockOutputApi())
1236 self.assertEqual(0, len(msgs),
1237 'Expected %d messages, found %d: %s'
1238 % (0, len(msgs), msgs))
1239
1240 # Test that only modifying an html file will not trigger the warning.
1241 def testIgnoreModifiedFiles(self):
1242 mock_input_api = MockInputApi()
1243
1244 mock_input_api.files = [
1245 MockAffectedFile('content/test/data/accessibility/aria/foo.html',
1246 [''], action='M')
1247 ]
1248
1249 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1250 mock_input_api, MockOutputApi())
1251 self.assertEqual(0, len(msgs),
1252 'Expected %d messages, found %d: %s'
1253 % (0, len(msgs), msgs))
1254
1255 # Test that deleting an html file will trigger the warning.
1256 def testAndroidChangeMissingOnDeletedFile(self):
1257 mock_input_api = MockInputApi()
1258
1259 mock_input_api.files = [
1260 MockAffectedFile('content/test/data/accessibility/accname/foo.html',
1261 [], action='D')
1262 ]
1263
1264 msgs = PRESUBMIT.CheckAccessibilityTreeTestsAreIncludedForAndroid(
1265 mock_input_api, MockOutputApi())
1266 self.assertEqual(1, len(msgs),
1267 'Expected %d messages, found %d: %s'
1268 % (1, len(msgs), msgs))
1269
yolandyan45001472016-12-21 21:12:421270class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
1271 def testCheckAndroidTestAnnotationUsage(self):
1272 mock_input_api = MockInputApi()
1273 mock_output_api = MockOutputApi()
1274
1275 mock_input_api.files = [
1276 MockAffectedFile('LalaLand.java', [
1277 'random stuff'
1278 ]),
1279 MockAffectedFile('CorrectUsage.java', [
1280 'import android.support.test.filters.LargeTest;',
1281 'import android.support.test.filters.MediumTest;',
1282 'import android.support.test.filters.SmallTest;',
1283 ]),
1284 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
1285 'import android.test.suitebuilder.annotation.LargeTest;',
1286 ]),
1287 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
1288 'import android.test.suitebuilder.annotation.MediumTest;',
1289 ]),
1290 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
1291 'import android.test.suitebuilder.annotation.SmallTest;',
1292 ]),
1293 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
1294 'import android.test.suitebuilder.annotation.Smoke;',
1295 ])
1296 ]
1297 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
1298 mock_input_api, mock_output_api)
1299 self.assertEqual(1, len(msgs),
1300 'Expected %d items, found %d: %s'
1301 % (1, len(msgs), msgs))
1302 self.assertEqual(4, len(msgs[0].items),
1303 'Expected %d items, found %d: %s'
1304 % (4, len(msgs[0].items), msgs[0].items))
1305 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
1306 'UsedDeprecatedLargeTestAnnotation not found in errors')
1307 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
1308 in msgs[0].items,
1309 'UsedDeprecatedMediumTestAnnotation not found in errors')
1310 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
1311 'UsedDeprecatedSmallTestAnnotation not found in errors')
1312 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
1313 'UsedDeprecatedSmokeAnnotation not found in errors')
1314
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391315
Mohamed Heikal5e5b7922020-10-29 18:57:591316class CheckNoDownstreamDepsTest(unittest.TestCase):
1317 def testInvalidDepFromUpstream(self):
1318 mock_input_api = MockInputApi()
1319 mock_output_api = MockOutputApi()
1320
1321 mock_input_api.files = [
1322 MockAffectedFile('BUILD.gn', [
1323 'deps = [',
1324 ' "//clank/target:test",',
1325 ']'
1326 ]),
1327 MockAffectedFile('chrome/android/BUILD.gn', [
1328 'deps = [ "//clank/target:test" ]'
1329 ]),
1330 MockAffectedFile('chrome/chrome_java_deps.gni', [
1331 'java_deps = [',
1332 ' "//clank/target:test",',
1333 ']'
1334 ]),
1335 ]
1336 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1337 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1338 mock_input_api, mock_output_api)
1339 self.assertEqual(1, len(msgs),
1340 'Expected %d items, found %d: %s'
1341 % (1, len(msgs), msgs))
1342 self.assertEqual(3, len(msgs[0].items),
1343 'Expected %d items, found %d: %s'
1344 % (3, len(msgs[0].items), msgs[0].items))
1345 self.assertTrue(any('BUILD.gn:2' in item for item in msgs[0].items),
1346 'BUILD.gn not found in errors')
1347 self.assertTrue(
1348 any('chrome/android/BUILD.gn:1' in item for item in msgs[0].items),
1349 'chrome/android/BUILD.gn:1 not found in errors')
1350 self.assertTrue(
1351 any('chrome/chrome_java_deps.gni:2' in item for item in msgs[0].items),
1352 'chrome/chrome_java_deps.gni:2 not found in errors')
1353
1354 def testAllowsComments(self):
1355 mock_input_api = MockInputApi()
1356 mock_output_api = MockOutputApi()
1357
1358 mock_input_api.files = [
1359 MockAffectedFile('BUILD.gn', [
1360 '# real implementation in //clank/target:test',
1361 ]),
1362 ]
1363 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1364 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1365 mock_input_api, mock_output_api)
1366 self.assertEqual(0, len(msgs),
1367 'Expected %d items, found %d: %s'
1368 % (0, len(msgs), msgs))
1369
1370 def testOnlyChecksBuildFiles(self):
1371 mock_input_api = MockInputApi()
1372 mock_output_api = MockOutputApi()
1373
1374 mock_input_api.files = [
1375 MockAffectedFile('README.md', [
1376 'DEPS = [ "//clank/target:test" ]'
1377 ]),
1378 MockAffectedFile('chrome/android/java/file.java', [
1379 '//clank/ only function'
1380 ]),
1381 ]
1382 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1383 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1384 mock_input_api, mock_output_api)
1385 self.assertEqual(0, len(msgs),
1386 'Expected %d items, found %d: %s'
1387 % (0, len(msgs), msgs))
1388
1389 def testValidDepFromDownstream(self):
1390 mock_input_api = MockInputApi()
1391 mock_output_api = MockOutputApi()
1392
1393 mock_input_api.files = [
1394 MockAffectedFile('BUILD.gn', [
1395 'DEPS = [',
1396 ' "//clank/target:test",',
1397 ']'
1398 ]),
1399 MockAffectedFile('java/BUILD.gn', [
1400 'DEPS = [ "//clank/target:test" ]'
1401 ]),
1402 ]
1403 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src/clank'
1404 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1405 mock_input_api, mock_output_api)
1406 self.assertEqual(0, len(msgs),
1407 'Expected %d items, found %d: %s'
1408 % (0, len(msgs), msgs))
1409
Yoland Yanb92fa522017-08-28 17:37:061410class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271411 def testCheckAndroidTestJUnitFramework(self):
Yoland Yanb92fa522017-08-28 17:37:061412 mock_input_api = MockInputApi()
1413 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:421414
Yoland Yanb92fa522017-08-28 17:37:061415 mock_input_api.files = [
1416 MockAffectedFile('LalaLand.java', [
1417 'random stuff'
1418 ]),
1419 MockAffectedFile('CorrectUsage.java', [
1420 'import org.junit.ABC',
1421 'import org.junit.XYZ;',
1422 ]),
1423 MockAffectedFile('UsedDeprecatedJUnit.java', [
1424 'import junit.framework.*;',
1425 ]),
1426 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
1427 'import junit.framework.Assert;',
1428 ]),
1429 ]
1430 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
1431 mock_input_api, mock_output_api)
1432 self.assertEqual(1, len(msgs),
1433 'Expected %d items, found %d: %s'
1434 % (1, len(msgs), msgs))
1435 self.assertEqual(2, len(msgs[0].items),
1436 'Expected %d items, found %d: %s'
1437 % (2, len(msgs[0].items), msgs[0].items))
1438 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
1439 'UsedDeprecatedJUnit.java not found in errors')
1440 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
1441 in msgs[0].items,
1442 'UsedDeprecatedJUnitAssert not found in errors')
1443
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391444
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271445class AndroidJUnitBaseClassTest(unittest.TestCase):
1446 def testCheckAndroidTestJUnitBaseClass(self):
Yoland Yanb92fa522017-08-28 17:37:061447 mock_input_api = MockInputApi()
1448 mock_output_api = MockOutputApi()
1449
1450 mock_input_api.files = [
1451 MockAffectedFile('LalaLand.java', [
1452 'random stuff'
1453 ]),
1454 MockAffectedFile('CorrectTest.java', [
1455 '@RunWith(ABC.class);'
1456 'public class CorrectTest {',
1457 '}',
1458 ]),
1459 MockAffectedFile('HistoricallyIncorrectTest.java', [
1460 'public class Test extends BaseCaseA {',
1461 '}',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391462 ], old_contents=[
Yoland Yanb92fa522017-08-28 17:37:061463 'public class Test extends BaseCaseB {',
1464 '}',
1465 ]),
1466 MockAffectedFile('CorrectTestWithInterface.java', [
1467 '@RunWith(ABC.class);'
1468 'public class CorrectTest implement Interface {',
1469 '}',
1470 ]),
1471 MockAffectedFile('IncorrectTest.java', [
1472 'public class IncorrectTest extends TestCase {',
1473 '}',
1474 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241475 MockAffectedFile('IncorrectWithInterfaceTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061476 'public class Test implements X extends BaseClass {',
1477 '}',
1478 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241479 MockAffectedFile('IncorrectMultiLineTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061480 'public class Test implements X, Y, Z',
1481 ' extends TestBase {',
1482 '}',
1483 ]),
1484 ]
1485 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1486 mock_input_api, mock_output_api)
1487 self.assertEqual(1, len(msgs),
1488 'Expected %d items, found %d: %s'
1489 % (1, len(msgs), msgs))
1490 self.assertEqual(3, len(msgs[0].items),
1491 'Expected %d items, found %d: %s'
1492 % (3, len(msgs[0].items), msgs[0].items))
1493 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1494 'IncorrectTest not found in errors')
Vaclav Brozekf01ed502018-03-16 19:38:241495 self.assertTrue('IncorrectWithInterfaceTest.java:1'
Yoland Yanb92fa522017-08-28 17:37:061496 in msgs[0].items,
Vaclav Brozekf01ed502018-03-16 19:38:241497 'IncorrectWithInterfaceTest not found in errors')
1498 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1499 'IncorrectMultiLineTest not found in errors')
yolandyan45001472016-12-21 21:12:421500
Jinsong Fan91ebbbd2019-04-16 14:57:171501class AndroidDebuggableBuildTest(unittest.TestCase):
1502
1503 def testCheckAndroidDebuggableBuild(self):
1504 mock_input_api = MockInputApi()
1505 mock_output_api = MockOutputApi()
1506
1507 mock_input_api.files = [
1508 MockAffectedFile('RandomStuff.java', [
1509 'random stuff'
1510 ]),
1511 MockAffectedFile('CorrectUsage.java', [
1512 'import org.chromium.base.BuildInfo;',
1513 'some random stuff',
1514 'boolean isOsDebuggable = BuildInfo.isDebugAndroid();',
1515 ]),
1516 MockAffectedFile('JustCheckUserdebugBuild.java', [
1517 'import android.os.Build;',
1518 'some random stuff',
1519 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")',
1520 ]),
1521 MockAffectedFile('JustCheckEngineeringBuild.java', [
1522 'import android.os.Build;',
1523 'some random stuff',
1524 'boolean isOsDebuggable = "eng".equals(Build.TYPE)',
1525 ]),
1526 MockAffectedFile('UsedBuildType.java', [
1527 'import android.os.Build;',
1528 'some random stuff',
1529 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")'
1530 '|| "eng".equals(Build.TYPE)',
1531 ]),
1532 MockAffectedFile('UsedExplicitBuildType.java', [
1533 'some random stuff',
1534 'boolean isOsDebuggable = android.os.Build.TYPE.equals("userdebug")'
1535 '|| "eng".equals(android.os.Build.TYPE)',
1536 ]),
1537 ]
1538
1539 msgs = PRESUBMIT._CheckAndroidDebuggableBuild(
1540 mock_input_api, mock_output_api)
1541 self.assertEqual(1, len(msgs),
1542 'Expected %d items, found %d: %s'
1543 % (1, len(msgs), msgs))
1544 self.assertEqual(4, len(msgs[0].items),
1545 'Expected %d items, found %d: %s'
1546 % (4, len(msgs[0].items), msgs[0].items))
1547 self.assertTrue('JustCheckUserdebugBuild.java:3' in msgs[0].items)
1548 self.assertTrue('JustCheckEngineeringBuild.java:3' in msgs[0].items)
1549 self.assertTrue('UsedBuildType.java:3' in msgs[0].items)
1550 self.assertTrue('UsedExplicitBuildType.java:2' in msgs[0].items)
1551
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391552
dgn4401aa52015-04-29 16:26:171553class LogUsageTest(unittest.TestCase):
1554
dgnaa68d5e2015-06-10 10:08:221555 def testCheckAndroidCrLogUsage(self):
1556 mock_input_api = MockInputApi()
1557 mock_output_api = MockOutputApi()
1558
1559 mock_input_api.files = [
1560 MockAffectedFile('RandomStuff.java', [
1561 'random stuff'
1562 ]),
dgn87d9fb62015-06-12 09:15:121563 MockAffectedFile('HasAndroidLog.java', [
1564 'import android.util.Log;',
1565 'some random stuff',
1566 'Log.d("TAG", "foo");',
1567 ]),
1568 MockAffectedFile('HasExplicitUtilLog.java', [
1569 'some random stuff',
1570 'android.util.Log.d("TAG", "foo");',
1571 ]),
1572 MockAffectedFile('IsInBasePackage.java', [
1573 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511574 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121575 'Log.d(TAG, "foo");',
1576 ]),
1577 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1578 'package org.chromium.base;',
1579 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511580 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121581 'Log.d(TAG, "foo");',
1582 ]),
1583 MockAffectedFile('HasBothLog.java', [
1584 'import org.chromium.base.Log;',
1585 'some random stuff',
dgn38736db2015-09-18 19:20:511586 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121587 'Log.d(TAG, "foo");',
1588 'android.util.Log.d("TAG", "foo");',
1589 ]),
dgnaa68d5e2015-06-10 10:08:221590 MockAffectedFile('HasCorrectTag.java', [
1591 'import org.chromium.base.Log;',
1592 'some random stuff',
dgn38736db2015-09-18 19:20:511593 'private static final String TAG = "cr_Foo";',
1594 'Log.d(TAG, "foo");',
1595 ]),
1596 MockAffectedFile('HasOldTag.java', [
1597 'import org.chromium.base.Log;',
1598 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221599 'private static final String TAG = "cr.Foo";',
1600 'Log.d(TAG, "foo");',
1601 ]),
dgn38736db2015-09-18 19:20:511602 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221603 'import org.chromium.base.Log;',
1604 'some random stuff',
dgn38736db2015-09-18 19:20:511605 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221606 'Log.d(TAG, "foo");',
1607 ]),
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461608 MockAffectedFile('HasDottedTagPublic.java', [
1609 'import org.chromium.base.Log;',
1610 'some random stuff',
1611 'public static final String TAG = "cr_foo.bar";',
1612 'Log.d(TAG, "foo");',
1613 ]),
dgnaa68d5e2015-06-10 10:08:221614 MockAffectedFile('HasNoTagDecl.java', [
1615 'import org.chromium.base.Log;',
1616 'some random stuff',
1617 'Log.d(TAG, "foo");',
1618 ]),
1619 MockAffectedFile('HasIncorrectTagDecl.java', [
1620 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511621 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221622 'some random stuff',
1623 'Log.d(TAG, "foo");',
1624 ]),
1625 MockAffectedFile('HasInlineTag.java', [
1626 'import org.chromium.base.Log;',
1627 'some random stuff',
dgn38736db2015-09-18 19:20:511628 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221629 'Log.d("TAG", "foo");',
1630 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551631 MockAffectedFile('HasInlineTagWithSpace.java', [
1632 'import org.chromium.base.Log;',
1633 'some random stuff',
1634 'private static final String TAG = "cr_Foo";',
1635 'Log.d("log message", "foo");',
1636 ]),
dgn38736db2015-09-18 19:20:511637 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221638 'import org.chromium.base.Log;',
1639 'some random stuff',
1640 'private static final String TAG = "rubbish";',
1641 'Log.d(TAG, "foo");',
1642 ]),
1643 MockAffectedFile('HasTooLongTag.java', [
1644 'import org.chromium.base.Log;',
1645 'some random stuff',
dgn38736db2015-09-18 19:20:511646 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:221647 'Log.d(TAG, "foo");',
1648 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551649 MockAffectedFile('HasTooLongTagWithNoLogCallsInDiff.java', [
1650 'import org.chromium.base.Log;',
1651 'some random stuff',
1652 'private static final String TAG = "21_charachers_long___";',
1653 ]),
dgnaa68d5e2015-06-10 10:08:221654 ]
1655
1656 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1657 mock_input_api, mock_output_api)
1658
dgn38736db2015-09-18 19:20:511659 self.assertEqual(5, len(msgs),
1660 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221661
1662 # Declaration format
dgn38736db2015-09-18 19:20:511663 nb = len(msgs[0].items)
1664 self.assertEqual(2, nb,
1665 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221666 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1667 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221668
1669 # Tag length
dgn38736db2015-09-18 19:20:511670 nb = len(msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551671 self.assertEqual(2, nb,
1672 'Expected %d items, found %d: %s' % (2, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:221673 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551674 self.assertTrue('HasTooLongTagWithNoLogCallsInDiff.java' in msgs[1].items)
dgnaa68d5e2015-06-10 10:08:221675
1676 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511677 nb = len(msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551678 self.assertEqual(3, nb,
1679 'Expected %d items, found %d: %s' % (3, nb, msgs[2].items))
1680 self.assertTrue('HasBothLog.java:5' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221681 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551682 self.assertTrue('HasInlineTagWithSpace.java:4' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221683
dgn87d9fb62015-06-12 09:15:121684 # Util Log usage
dgn38736db2015-09-18 19:20:511685 nb = len(msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551686 self.assertEqual(3, nb,
1687 'Expected %d items, found %d: %s' % (3, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:121688 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551689 self.assertTrue('HasExplicitUtilLog.java:2' in msgs[3].items)
dgn87d9fb62015-06-12 09:15:121690 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:221691
dgn38736db2015-09-18 19:20:511692 # Tag must not contain
1693 nb = len(msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461694 self.assertEqual(3, nb,
dgn38736db2015-09-18 19:20:511695 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1696 self.assertTrue('HasDottedTag.java' in msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461697 self.assertTrue('HasDottedTagPublic.java' in msgs[4].items)
dgn38736db2015-09-18 19:20:511698 self.assertTrue('HasOldTag.java' in msgs[4].items)
1699
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391700
estadee17314a02017-01-12 16:22:161701class GoogleAnswerUrlFormatTest(unittest.TestCase):
1702
1703 def testCatchAnswerUrlId(self):
1704 input_api = MockInputApi()
1705 input_api.files = [
1706 MockFile('somewhere/file.cc',
1707 ['char* host = '
1708 ' "https://support.google.com/chrome/answer/123456";']),
1709 MockFile('somewhere_else/file.cc',
1710 ['char* host = '
1711 ' "https://support.google.com/chrome/a/answer/123456";']),
1712 ]
1713
Saagar Sanghavifceeaae2020-08-12 16:40:361714 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161715 input_api, MockOutputApi())
1716 self.assertEqual(1, len(warnings))
1717 self.assertEqual(2, len(warnings[0].items))
1718
1719 def testAllowAnswerUrlParam(self):
1720 input_api = MockInputApi()
1721 input_api.files = [
1722 MockFile('somewhere/file.cc',
1723 ['char* host = '
1724 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1725 ]
1726
Saagar Sanghavifceeaae2020-08-12 16:40:361727 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161728 input_api, MockOutputApi())
1729 self.assertEqual(0, len(warnings))
1730
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391731
reillyi38965732015-11-16 18:27:331732class HardcodedGoogleHostsTest(unittest.TestCase):
1733
1734 def testWarnOnAssignedLiterals(self):
1735 input_api = MockInputApi()
1736 input_api.files = [
1737 MockFile('content/file.cc',
1738 ['char* host = "https://www.google.com";']),
1739 MockFile('content/file.cc',
1740 ['char* host = "https://www.googleapis.com";']),
1741 MockFile('content/file.cc',
1742 ['char* host = "https://clients1.google.com";']),
1743 ]
1744
Saagar Sanghavifceeaae2020-08-12 16:40:361745 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331746 input_api, MockOutputApi())
1747 self.assertEqual(1, len(warnings))
1748 self.assertEqual(3, len(warnings[0].items))
1749
1750 def testAllowInComment(self):
1751 input_api = MockInputApi()
1752 input_api.files = [
1753 MockFile('content/file.cc',
1754 ['char* host = "https://www.aol.com"; // google.com'])
1755 ]
1756
Saagar Sanghavifceeaae2020-08-12 16:40:361757 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331758 input_api, MockOutputApi())
1759 self.assertEqual(0, len(warnings))
1760
dgn4401aa52015-04-29 16:26:171761
James Cook6b6597c2019-11-06 22:05:291762class ChromeOsSyncedPrefRegistrationTest(unittest.TestCase):
1763
1764 def testWarnsOnChromeOsDirectories(self):
Henrique Ferreiro2e1aa1092021-11-29 22:22:121765 files = [
James Cook6b6597c2019-11-06 22:05:291766 MockFile('ash/file.cc',
1767 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1768 MockFile('chrome/browser/chromeos/file.cc',
1769 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1770 MockFile('chromeos/file.cc',
1771 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1772 MockFile('components/arc/file.cc',
1773 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1774 MockFile('components/exo/file.cc',
1775 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1776 ]
Henrique Ferreiro2e1aa1092021-11-29 22:22:121777 input_api = MockInputApi()
1778 for file in files:
1779 input_api.files = [file]
1780 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
1781 input_api, MockOutputApi())
1782 self.assertEqual(1, len(warnings))
James Cook6b6597c2019-11-06 22:05:291783
1784 def testDoesNotWarnOnSyncOsPref(self):
1785 input_api = MockInputApi()
1786 input_api.files = [
1787 MockFile('chromeos/file.cc',
1788 ['PrefRegistrySyncable::SYNCABLE_OS_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(0, len(warnings))
1793
Henrique Ferreiro2e1aa1092021-11-29 22:22:121794 def testDoesNotWarnOnOtherDirectories(self):
James Cook6b6597c2019-11-06 22:05:291795 input_api = MockInputApi()
1796 input_api.files = [
1797 MockFile('chrome/browser/ui/file.cc',
1798 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1799 MockFile('components/sync/file.cc',
1800 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1801 MockFile('content/browser/file.cc',
1802 ['PrefRegistrySyncable::SYNCABLE_PREF']),
Henrique Ferreiro2e1aa1092021-11-29 22:22:121803 MockFile('a/notchromeos/file.cc',
1804 ['PrefRegistrySyncable::SYNCABLE_PREF']),
James Cook6b6597c2019-11-06 22:05:291805 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361806 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291807 input_api, MockOutputApi())
1808 self.assertEqual(0, len(warnings))
1809
1810 def testSeparateWarningForPriorityPrefs(self):
1811 input_api = MockInputApi()
1812 input_api.files = [
1813 MockFile('chromeos/file.cc',
1814 ['PrefRegistrySyncable::SYNCABLE_PREF',
1815 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']),
1816 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361817 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291818 input_api, MockOutputApi())
1819 self.assertEqual(2, len(warnings))
1820
1821
jbriance9e12f162016-11-25 07:57:501822class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311823 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501824 mock_input_api = MockInputApi()
1825 mock_input_api.files = [
1826 MockAffectedFile('somewhere/file.cc', [
1827 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311828 ]),
1829 MockAffectedFile('third_party/header.h', [
1830 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501831 ])
1832 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361833 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391834 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501835 self.assertEqual(0, len(warnings))
1836
1837 def testNoNestedDeclaration(self):
1838 mock_input_api = MockInputApi()
1839 mock_input_api.files = [
1840 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311841 'class SomeClass {',
1842 ' protected:',
1843 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501844 '};'
1845 ])
1846 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361847 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391848 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501849 self.assertEqual(0, len(warnings))
1850
1851 def testSubStrings(self):
1852 mock_input_api = MockInputApi()
1853 mock_input_api.files = [
1854 MockAffectedFile('somewhere/header.h', [
1855 'class NotUsefulClass;',
1856 'struct SomeStruct;',
1857 'UsefulClass *p1;',
1858 'SomeStructPtr *p2;'
1859 ])
1860 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361861 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391862 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501863 self.assertEqual(2, len(warnings))
1864
1865 def testUselessForwardDeclaration(self):
1866 mock_input_api = MockInputApi()
1867 mock_input_api.files = [
1868 MockAffectedFile('somewhere/header.h', [
1869 'class DummyClass;',
1870 'struct DummyStruct;',
1871 'class UsefulClass;',
1872 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311873 ])
jbriance9e12f162016-11-25 07:57:501874 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361875 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391876 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501877 self.assertEqual(2, len(warnings))
1878
jbriance2c51e821a2016-12-12 08:24:311879 def testBlinkHeaders(self):
1880 mock_input_api = MockInputApi()
1881 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491882 MockAffectedFile('third_party/blink/header.h', [
jbriance2c51e821a2016-12-12 08:24:311883 'class DummyClass;',
1884 'struct DummyStruct;',
1885 ]),
Kent Tamura32dbbcb2018-11-30 12:28:491886 MockAffectedFile('third_party\\blink\\header.h', [
jbriance2c51e821a2016-12-12 08:24:311887 'class DummyClass;',
1888 'struct DummyStruct;',
1889 ])
1890 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361891 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391892 MockOutputApi())
jbriance2c51e821a2016-12-12 08:24:311893 self.assertEqual(4, len(warnings))
1894
jbriance9e12f162016-11-25 07:57:501895
rlanday6802cf632017-05-30 17:48:361896class RelativeIncludesTest(unittest.TestCase):
1897 def testThirdPartyNotWebKitIgnored(self):
1898 mock_input_api = MockInputApi()
1899 mock_input_api.files = [
1900 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1901 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1902 ]
1903
1904 mock_output_api = MockOutputApi()
1905
Saagar Sanghavifceeaae2020-08-12 16:40:361906 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361907 mock_input_api, mock_output_api)
1908 self.assertEqual(0, len(errors))
1909
1910 def testNonCppFileIgnored(self):
1911 mock_input_api = MockInputApi()
1912 mock_input_api.files = [
1913 MockAffectedFile('test.py', '#include "../header.h"'),
1914 ]
1915
1916 mock_output_api = MockOutputApi()
1917
Saagar Sanghavifceeaae2020-08-12 16:40:361918 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361919 mock_input_api, mock_output_api)
1920 self.assertEqual(0, len(errors))
1921
1922 def testInnocuousChangesAllowed(self):
1923 mock_input_api = MockInputApi()
1924 mock_input_api.files = [
1925 MockAffectedFile('test.cpp', '#include "header.h"'),
1926 MockAffectedFile('test2.cpp', '../'),
1927 ]
1928
1929 mock_output_api = MockOutputApi()
1930
Saagar Sanghavifceeaae2020-08-12 16:40:361931 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361932 mock_input_api, mock_output_api)
1933 self.assertEqual(0, len(errors))
1934
1935 def testRelativeIncludeNonWebKitProducesError(self):
1936 mock_input_api = MockInputApi()
1937 mock_input_api.files = [
1938 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1939 ]
1940
1941 mock_output_api = MockOutputApi()
1942
Saagar Sanghavifceeaae2020-08-12 16:40:361943 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361944 mock_input_api, mock_output_api)
1945 self.assertEqual(1, len(errors))
1946
1947 def testRelativeIncludeWebKitProducesError(self):
1948 mock_input_api = MockInputApi()
1949 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491950 MockAffectedFile('third_party/blink/test.cpp',
rlanday6802cf632017-05-30 17:48:361951 ['#include "../header.h']),
1952 ]
1953
1954 mock_output_api = MockOutputApi()
1955
Saagar Sanghavifceeaae2020-08-12 16:40:361956 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361957 mock_input_api, mock_output_api)
1958 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241959
Daniel Cheng13ca61a882017-08-25 15:11:251960
Daniel Bratell65b033262019-04-23 08:17:061961class CCIncludeTest(unittest.TestCase):
1962 def testThirdPartyNotBlinkIgnored(self):
1963 mock_input_api = MockInputApi()
1964 mock_input_api.files = [
1965 MockAffectedFile('third_party/test.cpp', '#include "file.cc"'),
1966 ]
1967
1968 mock_output_api = MockOutputApi()
1969
Saagar Sanghavifceeaae2020-08-12 16:40:361970 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061971 mock_input_api, mock_output_api)
1972 self.assertEqual(0, len(errors))
1973
1974 def testPythonFileIgnored(self):
1975 mock_input_api = MockInputApi()
1976 mock_input_api.files = [
1977 MockAffectedFile('test.py', '#include "file.cc"'),
1978 ]
1979
1980 mock_output_api = MockOutputApi()
1981
Saagar Sanghavifceeaae2020-08-12 16:40:361982 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061983 mock_input_api, mock_output_api)
1984 self.assertEqual(0, len(errors))
1985
1986 def testIncFilesAccepted(self):
1987 mock_input_api = MockInputApi()
1988 mock_input_api.files = [
1989 MockAffectedFile('test.py', '#include "file.inc"'),
1990 ]
1991
1992 mock_output_api = MockOutputApi()
1993
Saagar Sanghavifceeaae2020-08-12 16:40:361994 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061995 mock_input_api, mock_output_api)
1996 self.assertEqual(0, len(errors))
1997
1998 def testInnocuousChangesAllowed(self):
1999 mock_input_api = MockInputApi()
2000 mock_input_api.files = [
2001 MockAffectedFile('test.cpp', '#include "header.h"'),
2002 MockAffectedFile('test2.cpp', 'Something "file.cc"'),
2003 ]
2004
2005 mock_output_api = MockOutputApi()
2006
Saagar Sanghavifceeaae2020-08-12 16:40:362007 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:062008 mock_input_api, mock_output_api)
2009 self.assertEqual(0, len(errors))
2010
2011 def testCcIncludeNonBlinkProducesError(self):
2012 mock_input_api = MockInputApi()
2013 mock_input_api.files = [
2014 MockAffectedFile('test.cpp', ['#include "file.cc"']),
2015 ]
2016
2017 mock_output_api = MockOutputApi()
2018
Saagar Sanghavifceeaae2020-08-12 16:40:362019 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:062020 mock_input_api, mock_output_api)
2021 self.assertEqual(1, len(errors))
2022
2023 def testCppIncludeBlinkProducesError(self):
2024 mock_input_api = MockInputApi()
2025 mock_input_api.files = [
2026 MockAffectedFile('third_party/blink/test.cpp',
2027 ['#include "foo/file.cpp"']),
2028 ]
2029
2030 mock_output_api = MockOutputApi()
2031
Saagar Sanghavifceeaae2020-08-12 16:40:362032 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:062033 mock_input_api, mock_output_api)
2034 self.assertEqual(1, len(errors))
2035
2036
Andrew Grieve1b290e4a22020-11-24 20:07:012037class GnGlobForwardTest(unittest.TestCase):
2038 def testAddBareGlobs(self):
2039 mock_input_api = MockInputApi()
2040 mock_input_api.files = [
2041 MockAffectedFile('base/stuff.gni', [
2042 'forward_variables_from(invoker, "*")']),
2043 MockAffectedFile('base/BUILD.gn', [
2044 'forward_variables_from(invoker, "*")']),
2045 ]
2046 warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
2047 self.assertEqual(1, len(warnings))
2048 msg = '\n'.join(warnings[0].items)
2049 self.assertIn('base/stuff.gni', msg)
2050 # Should not check .gn files. Local templates don't need to care about
2051 # visibility / testonly.
2052 self.assertNotIn('base/BUILD.gn', msg)
2053
2054 def testValidUses(self):
2055 mock_input_api = MockInputApi()
2056 mock_input_api.files = [
2057 MockAffectedFile('base/stuff.gni', [
2058 'forward_variables_from(invoker, "*", [])']),
2059 MockAffectedFile('base/stuff2.gni', [
2060 'forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)']),
2061 MockAffectedFile('base/stuff3.gni', [
2062 'forward_variables_from(invoker, [ "testonly" ])']),
2063 ]
2064 warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
2065 self.assertEqual([], warnings)
2066
2067
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192068class NewHeaderWithoutGnChangeTest(unittest.TestCase):
2069 def testAddHeaderWithoutGn(self):
2070 mock_input_api = MockInputApi()
2071 mock_input_api.files = [
2072 MockAffectedFile('base/stuff.h', ''),
2073 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362074 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192075 mock_input_api, MockOutputApi())
2076 self.assertEqual(1, len(warnings))
2077 self.assertTrue('base/stuff.h' in warnings[0].items)
2078
2079 def testModifyHeader(self):
2080 mock_input_api = MockInputApi()
2081 mock_input_api.files = [
2082 MockAffectedFile('base/stuff.h', '', action='M'),
2083 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362084 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192085 mock_input_api, MockOutputApi())
2086 self.assertEqual(0, len(warnings))
2087
2088 def testDeleteHeader(self):
2089 mock_input_api = MockInputApi()
2090 mock_input_api.files = [
2091 MockAffectedFile('base/stuff.h', '', action='D'),
2092 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362093 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192094 mock_input_api, MockOutputApi())
2095 self.assertEqual(0, len(warnings))
2096
2097 def testAddHeaderWithGn(self):
2098 mock_input_api = MockInputApi()
2099 mock_input_api.files = [
2100 MockAffectedFile('base/stuff.h', ''),
2101 MockAffectedFile('base/BUILD.gn', 'stuff.h'),
2102 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362103 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192104 mock_input_api, MockOutputApi())
2105 self.assertEqual(0, len(warnings))
2106
2107 def testAddHeaderWithGni(self):
2108 mock_input_api = MockInputApi()
2109 mock_input_api.files = [
2110 MockAffectedFile('base/stuff.h', ''),
2111 MockAffectedFile('base/files.gni', 'stuff.h'),
2112 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362113 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192114 mock_input_api, MockOutputApi())
2115 self.assertEqual(0, len(warnings))
2116
2117 def testAddHeaderWithOther(self):
2118 mock_input_api = MockInputApi()
2119 mock_input_api.files = [
2120 MockAffectedFile('base/stuff.h', ''),
2121 MockAffectedFile('base/stuff.cc', 'stuff.h'),
2122 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362123 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192124 mock_input_api, MockOutputApi())
2125 self.assertEqual(1, len(warnings))
2126
2127 def testAddHeaderWithWrongGn(self):
2128 mock_input_api = MockInputApi()
2129 mock_input_api.files = [
2130 MockAffectedFile('base/stuff.h', ''),
2131 MockAffectedFile('base/BUILD.gn', 'stuff_h'),
2132 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362133 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192134 mock_input_api, MockOutputApi())
2135 self.assertEqual(1, len(warnings))
2136
2137 def testAddHeadersWithGn(self):
2138 mock_input_api = MockInputApi()
2139 mock_input_api.files = [
2140 MockAffectedFile('base/stuff.h', ''),
2141 MockAffectedFile('base/another.h', ''),
2142 MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'),
2143 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362144 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192145 mock_input_api, MockOutputApi())
2146 self.assertEqual(0, len(warnings))
2147
2148 def testAddHeadersWithWrongGn(self):
2149 mock_input_api = MockInputApi()
2150 mock_input_api.files = [
2151 MockAffectedFile('base/stuff.h', ''),
2152 MockAffectedFile('base/another.h', ''),
2153 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'),
2154 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362155 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192156 mock_input_api, MockOutputApi())
2157 self.assertEqual(1, len(warnings))
2158 self.assertFalse('base/stuff.h' in warnings[0].items)
2159 self.assertTrue('base/another.h' in warnings[0].items)
2160
2161 def testAddHeadersWithWrongGn2(self):
2162 mock_input_api = MockInputApi()
2163 mock_input_api.files = [
2164 MockAffectedFile('base/stuff.h', ''),
2165 MockAffectedFile('base/another.h', ''),
2166 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'),
2167 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362168 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:192169 mock_input_api, MockOutputApi())
2170 self.assertEqual(1, len(warnings))
2171 self.assertTrue('base/stuff.h' in warnings[0].items)
2172 self.assertTrue('base/another.h' in warnings[0].items)
2173
2174
Michael Giuffridad3bc8672018-10-25 22:48:022175class CorrectProductNameInMessagesTest(unittest.TestCase):
2176 def testProductNameInDesc(self):
2177 mock_input_api = MockInputApi()
2178 mock_input_api.files = [
2179 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2180 '<message name="Foo" desc="Welcome to Chrome">',
2181 ' Welcome to Chrome!',
2182 '</message>',
2183 ]),
2184 MockAffectedFile('chrome/app/chromium_strings.grd', [
2185 '<message name="Bar" desc="Welcome to Chrome">',
2186 ' Welcome to Chromium!',
2187 '</message>',
2188 ]),
2189 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362190 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022191 mock_input_api, MockOutputApi())
2192 self.assertEqual(0, len(warnings))
2193
2194 def testChromeInChromium(self):
2195 mock_input_api = MockInputApi()
2196 mock_input_api.files = [
2197 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2198 '<message name="Foo" desc="Welcome to Chrome">',
2199 ' Welcome to Chrome!',
2200 '</message>',
2201 ]),
2202 MockAffectedFile('chrome/app/chromium_strings.grd', [
2203 '<message name="Bar" desc="Welcome to Chrome">',
2204 ' Welcome to Chrome!',
2205 '</message>',
2206 ]),
2207 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362208 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022209 mock_input_api, MockOutputApi())
2210 self.assertEqual(1, len(warnings))
2211 self.assertTrue('chrome/app/chromium_strings.grd' in warnings[0].items[0])
2212
2213 def testChromiumInChrome(self):
2214 mock_input_api = MockInputApi()
2215 mock_input_api.files = [
2216 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2217 '<message name="Foo" desc="Welcome to Chrome">',
2218 ' Welcome to Chromium!',
2219 '</message>',
2220 ]),
2221 MockAffectedFile('chrome/app/chromium_strings.grd', [
2222 '<message name="Bar" desc="Welcome to Chrome">',
2223 ' Welcome to Chromium!',
2224 '</message>',
2225 ]),
2226 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362227 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022228 mock_input_api, MockOutputApi())
2229 self.assertEqual(1, len(warnings))
2230 self.assertTrue(
2231 'chrome/app/google_chrome_strings.grd:2' in warnings[0].items[0])
2232
2233 def testMultipleInstances(self):
2234 mock_input_api = MockInputApi()
2235 mock_input_api.files = [
2236 MockAffectedFile('chrome/app/chromium_strings.grd', [
2237 '<message name="Bar" desc="Welcome to Chrome">',
2238 ' Welcome to Chrome!',
2239 '</message>',
2240 '<message name="Baz" desc="A correct message">',
2241 ' Chromium is the software you are using.',
2242 '</message>',
2243 '<message name="Bat" desc="An incorrect message">',
2244 ' Google Chrome is the software you are using.',
2245 '</message>',
2246 ]),
2247 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362248 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022249 mock_input_api, MockOutputApi())
2250 self.assertEqual(1, len(warnings))
2251 self.assertTrue(
2252 'chrome/app/chromium_strings.grd:2' in warnings[0].items[0])
2253 self.assertTrue(
2254 'chrome/app/chromium_strings.grd:8' in warnings[0].items[1])
2255
2256 def testMultipleWarnings(self):
2257 mock_input_api = MockInputApi()
2258 mock_input_api.files = [
2259 MockAffectedFile('chrome/app/chromium_strings.grd', [
2260 '<message name="Bar" desc="Welcome to Chrome">',
2261 ' Welcome to Chrome!',
2262 '</message>',
2263 '<message name="Baz" desc="A correct message">',
2264 ' Chromium is the software you are using.',
2265 '</message>',
2266 '<message name="Bat" desc="An incorrect message">',
2267 ' Google Chrome is the software you are using.',
2268 '</message>',
2269 ]),
2270 MockAffectedFile('components/components_google_chrome_strings.grd', [
2271 '<message name="Bar" desc="Welcome to Chrome">',
2272 ' Welcome to Chrome!',
2273 '</message>',
2274 '<message name="Baz" desc="A correct message">',
2275 ' Chromium is the software you are using.',
2276 '</message>',
2277 '<message name="Bat" desc="An incorrect message">',
2278 ' Google Chrome is the software you are using.',
2279 '</message>',
2280 ]),
2281 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362282 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022283 mock_input_api, MockOutputApi())
2284 self.assertEqual(2, len(warnings))
2285 self.assertTrue(
2286 'components/components_google_chrome_strings.grd:5'
2287 in warnings[0].items[0])
2288 self.assertTrue(
2289 'chrome/app/chromium_strings.grd:2' in warnings[1].items[0])
2290 self.assertTrue(
2291 'chrome/app/chromium_strings.grd:8' in warnings[1].items[1])
2292
2293
Daniel Chenga37c03db2022-05-12 17:20:342294class _SecurityOwnersTestCase(unittest.TestCase):
Daniel Cheng171dad8d2022-05-21 00:40:252295 def _createMockInputApi(self):
2296 mock_input_api = MockInputApi()
2297 def FakeRepositoryRoot():
2298 return mock_input_api.os_path.join('chromium', 'src')
2299 mock_input_api.change.RepositoryRoot = FakeRepositoryRoot
2300 self._injectFakeOwnersClient(
2301 mock_input_api,
2302 ['[email protected]', '[email protected]'])
2303 return mock_input_api
2304
Daniel Chengd88244472022-05-16 09:08:472305 def _setupFakeChange(self, input_api):
2306 class FakeGerrit(object):
2307 def IsOwnersOverrideApproved(self, issue):
2308 return False
2309
2310 input_api.change.issue = 123
2311 input_api.gerrit = FakeGerrit()
2312
Daniel Chenga37c03db2022-05-12 17:20:342313 def _injectFakeOwnersClient(self, input_api, owners):
2314 class FakeOwnersClient(object):
2315 def ListOwners(self, f):
2316 return owners
2317
2318 input_api.owners_client = FakeOwnersClient()
2319
2320 def _injectFakeChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2321 def MockOwnerAndReviewers(input_api, email_regexp, approval_needed=False):
2322 return [owner, reviewers]
2323 input_api.canned_checks.GetCodereviewOwnerAndReviewers = \
2324 MockOwnerAndReviewers
2325
2326
2327class IpcSecurityOwnerTest(_SecurityOwnersTestCase):
2328 _test_cases = [
2329 ('*_messages.cc', 'scary_messages.cc'),
2330 ('*_messages*.h', 'scary_messages.h'),
2331 ('*_messages*.h', 'scary_messages_android.h'),
2332 ('*_param_traits*.*', 'scary_param_traits.h'),
2333 ('*_param_traits*.*', 'scary_param_traits_win.h'),
2334 ('*.mojom', 'scary.mojom'),
2335 ('*_mojom_traits*.*', 'scary_mojom_traits.h'),
2336 ('*_mojom_traits*.*', 'scary_mojom_traits_mac.h'),
2337 ('*_type_converter*.*', 'scary_type_converter.h'),
2338 ('*_type_converter*.*', 'scary_type_converter_nacl.h'),
2339 ('*.aidl', 'scary.aidl'),
2340 ]
2341
Daniel Cheng171dad8d2022-05-21 00:40:252342 def testHasCorrectPerFileRulesAndSecurityReviewer(self):
2343 mock_input_api = self._createMockInputApi()
2344 new_owners_file_path = mock_input_api.os_path.join(
2345 'services', 'goat', 'public', 'OWNERS')
2346 new_owners_file = [
2347 'per-file *.mojom=set noparent',
2348 'per-file *.mojom=file://ipc/SECURITY_OWNERS'
2349 ]
2350 def FakeReadFile(filename):
2351 self.assertEqual(
2352 mock_input_api.os_path.join('chromium', 'src', new_owners_file_path),
2353 filename)
2354 return '\n'.join(new_owners_file)
2355 mock_input_api.ReadFile = FakeReadFile
Daniel Cheng3008dc12022-05-13 04:02:112356 mock_input_api.files = [
Daniel Cheng171dad8d2022-05-21 00:40:252357 MockAffectedFile(
2358 new_owners_file_path, new_owners_file),
2359 MockAffectedFile(
2360 mock_input_api.os_path.join(
2361 'services', 'goat', 'public', 'goat.mojom'),
2362 ['// Scary contents.'])]
Daniel Chengd88244472022-05-16 09:08:472363 self._setupFakeChange(mock_input_api)
Daniel Cheng171dad8d2022-05-21 00:40:252364 self._injectFakeChangeOwnerAndReviewers(
2365 mock_input_api, '[email protected]', ['[email protected]'])
2366 mock_input_api.is_committing = True
2367 mock_input_api.dry_run = False
2368 mock_output_api = MockOutputApi()
2369 results = PRESUBMIT.CheckSecurityOwners(
2370 mock_input_api, mock_output_api)
2371 self.assertEqual(0, len(results))
2372
2373 def testMissingSecurityReviewerAtUpload(self):
2374 mock_input_api = self._createMockInputApi()
2375 new_owners_file_path = mock_input_api.os_path.join(
2376 'services', 'goat', 'public', 'OWNERS')
2377 new_owners_file = [
2378 'per-file *.mojom=set noparent',
2379 'per-file *.mojom=file://ipc/SECURITY_OWNERS'
2380 ]
2381 def FakeReadFile(filename):
2382 self.assertEqual(
2383 mock_input_api.os_path.join('chromium', 'src', new_owners_file_path),
2384 filename)
2385 return '\n'.join(new_owners_file)
2386 mock_input_api.ReadFile = FakeReadFile
2387 mock_input_api.files = [
2388 MockAffectedFile(
2389 new_owners_file_path, new_owners_file),
2390 MockAffectedFile(
2391 mock_input_api.os_path.join(
2392 'services', 'goat', 'public', 'goat.mojom'),
2393 ['// Scary contents.'])]
2394 self._setupFakeChange(mock_input_api)
Daniel Cheng3008dc12022-05-13 04:02:112395 self._injectFakeChangeOwnerAndReviewers(
2396 mock_input_api, '[email protected]', ['[email protected]'])
2397 mock_input_api.is_committing = False
2398 mock_input_api.dry_run = False
2399 mock_output_api = MockOutputApi()
2400 results = PRESUBMIT.CheckSecurityOwners(
2401 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252402 self.assertEqual(1, len(results))
Daniel Cheng681bc122022-05-19 02:23:442403 self.assertEqual('notify', results[0].type)
Daniel Cheng3008dc12022-05-13 04:02:112404 self.assertEqual(
Daniel Cheng171dad8d2022-05-21 00:40:252405 'Review from an owner in ipc/SECURITY_OWNERS is required for the '
2406 'following newly-added files:', results[0].message)
Daniel Cheng3008dc12022-05-13 04:02:112407
2408 def testMissingSecurityReviewerAtDryRunCommit(self):
Daniel Cheng171dad8d2022-05-21 00:40:252409 mock_input_api = self._createMockInputApi()
2410 new_owners_file_path = mock_input_api.os_path.join(
2411 'services', 'goat', 'public', 'OWNERS')
2412 new_owners_file = [
2413 'per-file *.mojom=set noparent',
2414 'per-file *.mojom=file://ipc/SECURITY_OWNERS'
2415 ]
2416 def FakeReadFile(filename):
2417 self.assertEqual(
2418 mock_input_api.os_path.join('chromium', 'src', new_owners_file_path),
2419 filename)
2420 return '\n'.join(new_owners_file)
2421 mock_input_api.ReadFile = FakeReadFile
Daniel Cheng3008dc12022-05-13 04:02:112422 mock_input_api.files = [
Daniel Cheng171dad8d2022-05-21 00:40:252423 MockAffectedFile(
2424 new_owners_file_path, new_owners_file),
2425 MockAffectedFile(
2426 mock_input_api.os_path.join(
2427 'services', 'goat', 'public', 'goat.mojom'),
2428 ['// Scary contents.'])]
Daniel Chengd88244472022-05-16 09:08:472429 self._setupFakeChange(mock_input_api)
Daniel Cheng3008dc12022-05-13 04:02:112430 self._injectFakeChangeOwnerAndReviewers(
2431 mock_input_api, '[email protected]', ['[email protected]'])
2432 mock_input_api.is_committing = True
2433 mock_input_api.dry_run = True
2434 mock_output_api = MockOutputApi()
2435 results = PRESUBMIT.CheckSecurityOwners(
2436 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252437 self.assertEqual(1, len(results))
Daniel Cheng3008dc12022-05-13 04:02:112438 self.assertEqual('error', results[0].type)
2439 self.assertEqual(
Daniel Cheng171dad8d2022-05-21 00:40:252440 'Review from an owner in ipc/SECURITY_OWNERS is required for the '
2441 'following newly-added files:', results[0].message)
Daniel Cheng3008dc12022-05-13 04:02:112442
2443 def testmissingSecurityApprovalAtRealCommit(self):
Daniel Cheng171dad8d2022-05-21 00:40:252444 mock_input_api = self._createMockInputApi()
2445 new_owners_file_path = mock_input_api.os_path.join(
2446 'services', 'goat', 'public', 'OWNERS')
2447 new_owners_file = [
2448 'per-file *.mojom=set noparent',
2449 'per-file *.mojom=file://ipc/SECURITY_OWNERS'
2450 ]
2451 def FakeReadFile(filename):
2452 self.assertEqual(
2453 mock_input_api.os_path.join('chromium', 'src', new_owners_file_path),
2454 filename)
2455 return '\n'.join(new_owners_file)
2456 mock_input_api.ReadFile = FakeReadFile
Daniel Cheng3008dc12022-05-13 04:02:112457 mock_input_api.files = [
Daniel Cheng171dad8d2022-05-21 00:40:252458 MockAffectedFile(
2459 new_owners_file_path, new_owners_file),
2460 MockAffectedFile(
2461 mock_input_api.os_path.join(
2462 'services', 'goat', 'public', 'goat.mojom'),
2463 ['// Scary contents.'])]
Daniel Chengd88244472022-05-16 09:08:472464 self._setupFakeChange(mock_input_api)
Daniel Cheng3008dc12022-05-13 04:02:112465 self._injectFakeChangeOwnerAndReviewers(
2466 mock_input_api, '[email protected]', ['[email protected]'])
2467 mock_input_api.is_committing = True
2468 mock_input_api.dry_run = False
2469 mock_output_api = MockOutputApi()
2470 results = PRESUBMIT.CheckSecurityOwners(
2471 mock_input_api, mock_output_api)
Daniel Cheng3008dc12022-05-13 04:02:112472 self.assertEqual('error', results[0].type)
2473 self.assertEqual(
Daniel Cheng171dad8d2022-05-21 00:40:252474 'Review from an owner in ipc/SECURITY_OWNERS is required for the '
2475 'following newly-added files:', results[0].message)
Daniel Chenga37c03db2022-05-12 17:20:342476
2477 def testIpcChangeNeedsSecurityOwner(self):
Daniel Cheng3008dc12022-05-13 04:02:112478 for is_committing in [True, False]:
2479 for pattern, filename in self._test_cases:
2480 with self.subTest(
2481 line=f'is_committing={is_committing}, filename={filename}'):
Daniel Cheng171dad8d2022-05-21 00:40:252482 mock_input_api = self._createMockInputApi()
Daniel Cheng3008dc12022-05-13 04:02:112483 mock_input_api.files = [
Daniel Cheng171dad8d2022-05-21 00:40:252484 MockAffectedFile(
2485 mock_input_api.os_path.join(
2486 'services', 'goat', 'public', filename),
2487 ['// Scary contents.'])]
Daniel Chengd88244472022-05-16 09:08:472488 self._setupFakeChange(mock_input_api)
Daniel Cheng3008dc12022-05-13 04:02:112489 self._injectFakeChangeOwnerAndReviewers(
2490 mock_input_api, '[email protected]', ['[email protected]'])
2491 mock_input_api.is_committing = is_committing
2492 mock_input_api.dry_run = False
2493 mock_output_api = MockOutputApi()
2494 results = PRESUBMIT.CheckSecurityOwners(
2495 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252496 self.assertEqual(1, len(results))
2497 self.assertEqual('error', results[0].type)
2498 self.assertTrue(results[0].message.replace('\\', '/').startswith(
2499 'Found missing OWNERS lines for security-sensitive files. '
2500 'Please add the following lines to services/goat/public/OWNERS:'))
Daniel Cheng3008dc12022-05-13 04:02:112501 self.assertEqual(['[email protected]'],
2502 mock_output_api.more_cc)
Daniel Chenga37c03db2022-05-12 17:20:342503
2504
Ken Rockot9f668262018-12-21 18:56:362505 def testServiceManifestChangeNeedsSecurityOwner(self):
Daniel Cheng171dad8d2022-05-21 00:40:252506 mock_input_api = self._createMockInputApi()
Ken Rockot9f668262018-12-21 18:56:362507 mock_input_api.files = [
Daniel Cheng171dad8d2022-05-21 00:40:252508 MockAffectedFile(
2509 mock_input_api.os_path.join(
2510 'services', 'goat', 'public', 'cpp', 'manifest.cc'),
2511 [
2512 '#include "services/goat/public/cpp/manifest.h"',
2513 'const service_manager::Manifest& GetManifest() {}',
2514 ])]
Daniel Chengd88244472022-05-16 09:08:472515 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342516 self._injectFakeChangeOwnerAndReviewers(
2517 mock_input_api, '[email protected]', ['[email protected]'])
Ken Rockot9f668262018-12-21 18:56:362518 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362519 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362520 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252521 self.assertEqual(1, len(errors))
2522 self.assertTrue(errors[0].message.replace('\\', '/').startswith(
2523 'Found missing OWNERS lines for security-sensitive files. '
2524 'Please add the following lines to services/goat/public/cpp/OWNERS:'))
Daniel Chenga37c03db2022-05-12 17:20:342525 self.assertEqual(['[email protected]'], mock_output_api.more_cc)
Ken Rockot9f668262018-12-21 18:56:362526
2527 def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
Daniel Cheng171dad8d2022-05-21 00:40:252528 mock_input_api = self._createMockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342529 self._injectFakeChangeOwnerAndReviewers(
2530 mock_input_api, '[email protected]', ['[email protected]'])
Ken Rockot9f668262018-12-21 18:56:362531 mock_input_api.files = [
2532 MockAffectedFile('some/non/service/thing/foo_manifest.cc',
2533 [
2534 'const char kNoEnforcement[] = "not a manifest!";',
2535 ])]
2536 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362537 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032538 mock_input_api, mock_output_api)
2539 self.assertEqual([], errors)
Daniel Chenga37c03db2022-05-12 17:20:342540 self.assertEqual([], mock_output_api.more_cc)
Wez17c66962020-04-29 15:26:032541
2542
Daniel Chenga37c03db2022-05-12 17:20:342543class FuchsiaSecurityOwnerTest(_SecurityOwnersTestCase):
Wez17c66962020-04-29 15:26:032544 def testFidlChangeNeedsSecurityOwner(self):
Daniel Cheng171dad8d2022-05-21 00:40:252545 mock_input_api = self._createMockInputApi()
Wez17c66962020-04-29 15:26:032546 mock_input_api.files = [
2547 MockAffectedFile('potentially/scary/ipc.fidl',
2548 [
2549 'library test.fidl'
2550 ])]
Daniel Chengd88244472022-05-16 09:08:472551 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342552 self._injectFakeChangeOwnerAndReviewers(
2553 mock_input_api, '[email protected]', ['[email protected]'])
Wez17c66962020-04-29 15:26:032554 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362555 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032556 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252557 self.assertEqual(1, len(errors))
2558 self.assertTrue(errors[0].message.replace('\\', '/').startswith(
2559 'Found missing OWNERS lines for security-sensitive files. '
2560 'Please add the following lines to potentially/scary/OWNERS:'))
Wez17c66962020-04-29 15:26:032561
2562 def testComponentManifestV1ChangeNeedsSecurityOwner(self):
Daniel Cheng171dad8d2022-05-21 00:40:252563 mock_input_api = self._createMockInputApi()
Wez17c66962020-04-29 15:26:032564 mock_input_api.files = [
2565 MockAffectedFile('potentially/scary/v2_manifest.cmx',
2566 [
2567 '{ "that is no": "manifest!" }'
2568 ])]
Daniel Chengd88244472022-05-16 09:08:472569 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342570 self._injectFakeChangeOwnerAndReviewers(
2571 mock_input_api, '[email protected]', ['[email protected]'])
Wez17c66962020-04-29 15:26:032572 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362573 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032574 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252575 self.assertEqual(1, len(errors))
2576 self.assertTrue(errors[0].message.replace('\\', '/').startswith(
2577 'Found missing OWNERS lines for security-sensitive files. '
2578 'Please add the following lines to potentially/scary/OWNERS:'))
Wez17c66962020-04-29 15:26:032579
2580 def testComponentManifestV2NeedsSecurityOwner(self):
Daniel Cheng171dad8d2022-05-21 00:40:252581 mock_input_api = self._createMockInputApi()
Wez17c66962020-04-29 15:26:032582 mock_input_api.files = [
2583 MockAffectedFile('potentially/scary/v2_manifest.cml',
2584 [
2585 '{ "that is no": "manifest!" }'
2586 ])]
Daniel Chengd88244472022-05-16 09:08:472587 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342588 self._injectFakeChangeOwnerAndReviewers(
2589 mock_input_api, '[email protected]', ['[email protected]'])
Daniel Chengd88244472022-05-16 09:08:472590 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362591 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032592 mock_input_api, mock_output_api)
Daniel Cheng171dad8d2022-05-21 00:40:252593 self.assertEqual(1, len(errors))
2594 self.assertTrue(errors[0].message.replace('\\', '/').startswith(
2595 'Found missing OWNERS lines for security-sensitive files. '
2596 'Please add the following lines to potentially/scary/OWNERS:'))
Wez17c66962020-04-29 15:26:032597
Joshua Peraza1ca6d392020-12-08 00:14:092598 def testThirdPartyTestsDoNotRequireSecurityOwner(self):
2599 mock_input_api = MockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342600 self._injectFakeChangeOwnerAndReviewers(
2601 mock_input_api, '[email protected]', ['[email protected]'])
Joshua Peraza1ca6d392020-12-08 00:14:092602 mock_input_api.files = [
2603 MockAffectedFile('third_party/crashpad/test/tests.cmx',
2604 [
2605 'const char kNoEnforcement[] = "Security?!? Pah!";',
2606 ])]
2607 mock_output_api = MockOutputApi()
2608 errors = PRESUBMIT.CheckSecurityOwners(
2609 mock_input_api, mock_output_api)
2610 self.assertEqual([], errors)
2611
Wez17c66962020-04-29 15:26:032612 def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2613 mock_input_api = MockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342614 self._injectFakeChangeOwnerAndReviewers(
2615 mock_input_api, '[email protected]', ['[email protected]'])
Wez17c66962020-04-29 15:26:032616 mock_input_api.files = [
2617 MockAffectedFile('some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',
2618 [
2619 'const char kNoEnforcement[] = "Security?!? Pah!";',
2620 ])]
2621 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362622 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362623 mock_input_api, mock_output_api)
2624 self.assertEqual([], errors)
2625
Daniel Cheng13ca61a882017-08-25 15:11:252626
Daniel Chenga37c03db2022-05-12 17:20:342627class SecurityChangeTest(_SecurityOwnersTestCase):
Alex Goughbc964dd2020-06-15 17:52:372628 def testDiffGetServiceSandboxType(self):
Robert Sesek2c905332020-05-06 23:17:132629 mock_input_api = MockInputApi()
2630 mock_input_api.files = [
2631 MockAffectedFile(
2632 'services/goat/teleporter_host.cc',
2633 [
Alex Goughbc964dd2020-06-15 17:52:372634 'template <>',
2635 'inline content::SandboxType',
2636 'content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {',
2637 '#if defined(OS_WIN)',
2638 ' return SandboxType::kGoaty;',
2639 '#else',
2640 ' return SandboxType::kNoSandbox;',
2641 '#endif // !defined(OS_WIN)',
2642 '}'
Robert Sesek2c905332020-05-06 23:17:132643 ]
2644 ),
2645 ]
2646 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2647 mock_input_api)
2648 self.assertEqual({
2649 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372650 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132651 ])},
2652 files_to_functions)
2653
2654 def testDiffRemovingLine(self):
2655 mock_input_api = MockInputApi()
2656 mock_file = MockAffectedFile('services/goat/teleporter_host.cc', '')
2657 mock_file._scm_diff = """--- old 2020-05-04 14:08:25.000000000 -0400
2658+++ new 2020-05-04 14:08:32.000000000 -0400
2659@@ -1,5 +1,4 @@
Alex Goughbc964dd2020-06-15 17:52:372660 template <>
2661 inline content::SandboxType
2662-content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {
2663 #if defined(OS_WIN)
2664 return SandboxType::kGoaty;
Robert Sesek2c905332020-05-06 23:17:132665"""
2666 mock_input_api.files = [mock_file]
2667 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2668 mock_input_api)
2669 self.assertEqual({
2670 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372671 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132672 ])},
2673 files_to_functions)
2674
2675 def testChangeOwnersMissing(self):
Daniel Cheng171dad8d2022-05-21 00:40:252676 mock_input_api = self._createMockInputApi()
Daniel Chengd88244472022-05-16 09:08:472677 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342678 self._injectFakeChangeOwnerAndReviewers(
2679 mock_input_api, '[email protected]', ['[email protected]'])
Robert Sesek2c905332020-05-06 23:17:132680 mock_input_api.is_committing = False
2681 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372682 MockAffectedFile('file.cc', ['GetServiceSandboxType<Goat>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132683 ]
2684 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362685 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592686 self.assertEqual(1, len(result))
2687 self.assertEqual(result[0].type, 'notify')
2688 self.assertEqual(result[0].message,
Daniel Chenga37c03db2022-05-12 17:20:342689 'The following files change calls to security-sensitive functions\n' \
Robert Sesek2c905332020-05-06 23:17:132690 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2691 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372692 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132693
2694 def testChangeOwnersMissingAtCommit(self):
Daniel Cheng171dad8d2022-05-21 00:40:252695 mock_input_api = self._createMockInputApi()
Daniel Chengd88244472022-05-16 09:08:472696 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342697 self._injectFakeChangeOwnerAndReviewers(
2698 mock_input_api, '[email protected]', ['[email protected]'])
Robert Sesek2c905332020-05-06 23:17:132699 mock_input_api.is_committing = True
Daniel Cheng3008dc12022-05-13 04:02:112700 mock_input_api.dry_run = False
Robert Sesek2c905332020-05-06 23:17:132701 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372702 MockAffectedFile('file.cc', ['GetServiceSandboxType<mojom::Goat>()'])
Robert Sesek2c905332020-05-06 23:17:132703 ]
2704 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362705 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592706 self.assertEqual(1, len(result))
2707 self.assertEqual(result[0].type, 'error')
2708 self.assertEqual(result[0].message,
Daniel Chenga37c03db2022-05-12 17:20:342709 'The following files change calls to security-sensitive functions\n' \
Robert Sesek2c905332020-05-06 23:17:132710 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2711 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372712 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132713
2714 def testChangeOwnersPresent(self):
Daniel Cheng171dad8d2022-05-21 00:40:252715 mock_input_api = self._createMockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342716 self._injectFakeChangeOwnerAndReviewers(
2717 mock_input_api, '[email protected]',
2718 ['[email protected]', '[email protected]'])
Robert Sesek2c905332020-05-06 23:17:132719 mock_input_api.files = [
2720 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2721 ]
2722 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362723 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592724 self.assertEqual(0, len(result))
Robert Sesek2c905332020-05-06 23:17:132725
2726 def testChangeOwnerIsSecurityOwner(self):
Daniel Cheng171dad8d2022-05-21 00:40:252727 mock_input_api = self._createMockInputApi()
Daniel Chengd88244472022-05-16 09:08:472728 self._setupFakeChange(mock_input_api)
Daniel Chenga37c03db2022-05-12 17:20:342729 self._injectFakeChangeOwnerAndReviewers(
2730 mock_input_api, '[email protected]', ['[email protected]'])
Robert Sesek2c905332020-05-06 23:17:132731 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372732 MockAffectedFile('file.cc', ['GetServiceSandboxType<T>(Sandbox)'])
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))
Robert Sesek2c905332020-05-06 23:17:132737
2738
Mario Sanchez Prada2472cab2019-09-18 10:58:312739class BannedTypeCheckTest(unittest.TestCase):
Sylvain Defresnea8b73d252018-02-28 15:45:542740
Peter Kasting94a56c42019-10-25 21:54:042741 def testBannedCppFunctions(self):
2742 input_api = MockInputApi()
2743 input_api.files = [
2744 MockFile('some/cpp/problematic/file.cc',
2745 ['using namespace std;']),
Oksana Zhuravlovac8222d22019-12-19 19:21:162746 MockFile('third_party/blink/problematic/file.cc',
2747 ['GetInterfaceProvider()']),
Peter Kasting94a56c42019-10-25 21:54:042748 MockFile('some/cpp/ok/file.cc',
2749 ['using std::string;']),
Allen Bauer53b43fb12020-03-12 17:21:472750 MockFile('some/cpp/problematic/file2.cc',
2751 ['set_owned_by_client()']),
danakjd18e8892020-12-17 17:42:012752 MockFile('some/cpp/nocheck/file.cc',
2753 ['using namespace std; // nocheck']),
2754 MockFile('some/cpp/comment/file.cc',
2755 [' // A comment about `using namespace std;`']),
Peter Kasting94a56c42019-10-25 21:54:042756 ]
2757
Saagar Sanghavifceeaae2020-08-12 16:40:362758 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlovac8222d22019-12-19 19:21:162759
2760 # warnings are results[0], errors are results[1]
2761 self.assertEqual(2, len(results))
2762 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2763 self.assertTrue(
2764 'third_party/blink/problematic/file.cc' in results[0].message)
2765 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
Allen Bauer53b43fb12020-03-12 17:21:472766 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
danakjd18e8892020-12-17 17:42:012767 self.assertFalse('some/cpp/nocheck/file.cc' in results[0].message)
2768 self.assertFalse('some/cpp/nocheck/file.cc' in results[1].message)
2769 self.assertFalse('some/cpp/comment/file.cc' in results[0].message)
2770 self.assertFalse('some/cpp/comment/file.cc' in results[1].message)
Peter Kasting94a56c42019-10-25 21:54:042771
Peter K. Lee6c03ccff2019-07-15 14:40:052772 def testBannedIosObjcFunctions(self):
Sylvain Defresnea8b73d252018-02-28 15:45:542773 input_api = MockInputApi()
2774 input_api.files = [
2775 MockFile('some/ios/file.mm',
2776 ['TEST(SomeClassTest, SomeInteraction) {',
2777 '}']),
2778 MockFile('some/mac/file.mm',
2779 ['TEST(SomeClassTest, SomeInteraction) {',
2780 '}']),
2781 MockFile('another/ios_file.mm',
2782 ['class SomeTest : public testing::Test {};']),
Peter K. Lee6c03ccff2019-07-15 14:40:052783 MockFile('some/ios/file_egtest.mm',
2784 ['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
2785 MockFile('some/ios/file_unittest.mm',
2786 ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']),
Sylvain Defresnea8b73d252018-02-28 15:45:542787 ]
2788
Saagar Sanghavifceeaae2020-08-12 16:40:362789 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Sylvain Defresnea8b73d252018-02-28 15:45:542790 self.assertEqual(1, len(errors))
2791 self.assertTrue('some/ios/file.mm' in errors[0].message)
2792 self.assertTrue('another/ios_file.mm' in errors[0].message)
2793 self.assertTrue('some/mac/file.mm' not in errors[0].message)
Peter K. Lee6c03ccff2019-07-15 14:40:052794 self.assertTrue('some/ios/file_egtest.mm' in errors[0].message)
2795 self.assertTrue('some/ios/file_unittest.mm' not in errors[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542796
Carlos Knippschildab192b8c2019-04-08 20:02:382797 def testBannedMojoFunctions(self):
2798 input_api = MockInputApi()
2799 input_api.files = [
Oksana Zhuravlovafd247772019-05-16 16:57:292800 MockFile('some/cpp/problematic/file2.cc',
2801 ['mojo::ConvertTo<>']),
Oksana Zhuravlovafd247772019-05-16 16:57:292802 MockFile('third_party/blink/ok/file3.cc',
2803 ['mojo::ConvertTo<>']),
2804 MockFile('content/renderer/ok/file3.cc',
2805 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382806 ]
2807
Saagar Sanghavifceeaae2020-08-12 16:40:362808 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222809
2810 # warnings are results[0], errors are results[1]
Robert Sesek351d2d52021-02-02 01:47:072811 self.assertEqual(1, len(results))
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222812 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222813 self.assertTrue('third_party/blink/ok/file3.cc' not in results[0].message)
2814 self.assertTrue('content/renderer/ok/file3.cc' not in results[0].message)
Carlos Knippschildab192b8c2019-04-08 20:02:382815
Daniel Cheng92c15e32022-03-16 17:48:222816 def testBannedMojomPatterns(self):
2817 input_api = MockInputApi()
2818 input_api.files = [
2819 MockFile('bad.mojom',
2820 ['struct Bad {',
2821 ' handle<shared_buffer> buffer;',
2822 '};']),
2823 MockFile('good.mojom',
2824 ['struct Good {',
2825 ' mojo_base.mojom.ReadOnlySharedMemoryRegion region1;',
2826 ' mojo_base.mojom.WritableSharedMemoryRegion region2;',
2827 ' mojo_base.mojom.UnsafeSharedMemoryRegion region3;',
2828 '};']),
2829 ]
2830
2831 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
2832
2833 # warnings are results[0], errors are results[1]
2834 self.assertEqual(1, len(results))
2835 self.assertTrue('bad.mojom' in results[0].message)
2836 self.assertTrue('good.mojom' not in results[0].message)
2837
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272838class NoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:242839 def testTruePositives(self):
2840 mock_input_api = MockInputApi()
2841 mock_input_api.files = [
2842 MockFile('some/path/foo.cc', ['foo_for_testing();']),
2843 MockFile('some/path/foo.mm', ['FooForTesting();']),
2844 MockFile('some/path/foo.cxx', ['FooForTests();']),
2845 MockFile('some/path/foo.cpp', ['foo_for_test();']),
2846 ]
2847
Saagar Sanghavifceeaae2020-08-12 16:40:362848 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242849 mock_input_api, MockOutputApi())
2850 self.assertEqual(1, len(results))
2851 self.assertEqual(4, len(results[0].items))
2852 self.assertTrue('foo.cc' in results[0].items[0])
2853 self.assertTrue('foo.mm' in results[0].items[1])
2854 self.assertTrue('foo.cxx' in results[0].items[2])
2855 self.assertTrue('foo.cpp' in results[0].items[3])
2856
2857 def testFalsePositives(self):
2858 mock_input_api = MockInputApi()
2859 mock_input_api.files = [
2860 MockFile('some/path/foo.h', ['foo_for_testing();']),
2861 MockFile('some/path/foo.mm', ['FooForTesting() {']),
2862 MockFile('some/path/foo.cc', ['::FooForTests();']),
2863 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
2864 ]
2865
Saagar Sanghavifceeaae2020-08-12 16:40:362866 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242867 mock_input_api, MockOutputApi())
2868 self.assertEqual(0, len(results))
2869
James Cook1b4dc132021-03-09 22:45:132870 def testAllowedFiles(self):
2871 mock_input_api = MockInputApi()
2872 mock_input_api.files = [
2873 MockFile('path/foo_unittest.cc', ['foo_for_testing();']),
2874 MockFile('path/bar_unittest_mac.cc', ['foo_for_testing();']),
2875 MockFile('path/baz_unittests.cc', ['foo_for_testing();']),
2876 ]
2877
2878 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
2879 mock_input_api, MockOutputApi())
2880 self.assertEqual(0, len(results))
2881
Vaclav Brozekf01ed502018-03-16 19:38:242882
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272883class NoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:232884 def testTruePositives(self):
2885 mock_input_api = MockInputApi()
2886 mock_input_api.files = [
2887 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
2888 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392889 MockFile('dir/java/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232890 MockFile('dir/java/src/mult.java', [
2891 'int x = SomethingLongHere()',
2892 ' * SomethingLongHereForTesting();'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392893 ])
Vaclav Brozek7dbc28c2018-03-27 08:35:232894 ]
2895
Saagar Sanghavifceeaae2020-08-12 16:40:362896 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232897 mock_input_api, MockOutputApi())
2898 self.assertEqual(1, len(results))
2899 self.assertEqual(4, len(results[0].items))
2900 self.assertTrue('foo.java' in results[0].items[0])
2901 self.assertTrue('bar.java' in results[0].items[1])
2902 self.assertTrue('baz.java' in results[0].items[2])
2903 self.assertTrue('mult.java' in results[0].items[3])
2904
2905 def testFalsePositives(self):
2906 mock_input_api = MockInputApi()
2907 mock_input_api.files = [
2908 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
2909 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
2910 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
2911 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
Sky Malice9e6d6032020-10-15 22:49:552912 MockFile('dir/java/src/bar3.java', ['@VisibleForTesting']),
2913 MockFile('dir/java/src/bar4.java', ['@VisibleForTesting()']),
2914 MockFile('dir/java/src/bar5.java', [
2915 '@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)'
2916 ]),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392917 MockFile('dir/javatests/src/baz.java', ['FooForTest(', 'y', ');']),
2918 MockFile('dir/junit/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232919 MockFile('dir/junit/src/javadoc.java', [
2920 '/** Use FooForTest(); to obtain foo in tests.'
2921 ' */'
2922 ]),
2923 MockFile('dir/junit/src/javadoc2.java', [
2924 '/** ',
2925 ' * Use FooForTest(); to obtain foo in tests.'
2926 ' */'
2927 ]),
2928 ]
2929
Saagar Sanghavifceeaae2020-08-12 16:40:362930 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232931 mock_input_api, MockOutputApi())
2932 self.assertEqual(0, len(results))
2933
2934
Mohamed Heikald048240a2019-11-12 16:57:372935class NewImagesWarningTest(unittest.TestCase):
2936 def testTruePositives(self):
2937 mock_input_api = MockInputApi()
2938 mock_input_api.files = [
2939 MockFile('dir/android/res/drawable/foo.png', []),
2940 MockFile('dir/android/res/drawable-v21/bar.svg', []),
2941 MockFile('dir/android/res/mipmap-v21-en/baz.webp', []),
2942 MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png', []),
2943 ]
2944
2945 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2946 self.assertEqual(1, len(results))
2947 self.assertEqual(4, len(results[0].items))
2948 self.assertTrue('foo.png' in results[0].items[0].LocalPath())
2949 self.assertTrue('bar.svg' in results[0].items[1].LocalPath())
2950 self.assertTrue('baz.webp' in results[0].items[2].LocalPath())
2951 self.assertTrue('foobar.png' in results[0].items[3].LocalPath())
2952
2953 def testFalsePositives(self):
2954 mock_input_api = MockInputApi()
2955 mock_input_api.files = [
2956 MockFile('dir/pngs/README.md', []),
2957 MockFile('java/test/res/drawable/foo.png', []),
2958 MockFile('third_party/blink/foo.png', []),
2959 MockFile('dir/third_party/libpng/src/foo.cc', ['foobar']),
2960 MockFile('dir/resources.webp/.gitignore', ['foo.png']),
2961 ]
2962
2963 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2964 self.assertEqual(0, len(results))
2965
2966
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272967class CheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:052968 def testTruePositivesNullptr(self):
2969 mock_input_api = MockInputApi()
2970 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162971 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
2972 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
Vaclav Brozek851d9602018-04-04 16:13:052973 ]
2974
Saagar Sanghavifceeaae2020-08-12 16:40:362975 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052976 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162977 self.assertTrue('nullptr' in results[0].message)
Vaclav Brozek851d9602018-04-04 16:13:052978 self.assertEqual(2, len(results[0].items))
2979 self.assertTrue('baz.cc' in results[0].items[0])
2980 self.assertTrue('baz-p.cc' in results[0].items[1])
2981
2982 def testTruePositivesConstructor(self):
Vaclav Brozek52e18bf2018-04-03 07:05:242983 mock_input_api = MockInputApi()
2984 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162985 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
2986 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
2987 MockFile('dir/mult.cc', [
Vaclav Brozek95face62018-04-04 14:15:112988 'return',
2989 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
2990 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162991 MockFile('dir/mult2.cc', [
Vaclav Brozek95face62018-04-04 14:15:112992 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
2993 ' std::unique_ptr<T>(foo);'
2994 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162995 MockFile('dir/mult3.cc', [
Vaclav Brozek95face62018-04-04 14:15:112996 'bar = std::unique_ptr<T>(',
2997 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
2998 ]),
Vaclav Brozekb7fadb692018-08-30 06:39:532999 MockFile('dir/multi_arg.cc', [
3000 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']),
Vaclav Brozek52e18bf2018-04-03 07:05:243001 ]
3002
Saagar Sanghavifceeaae2020-08-12 16:40:363003 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:053004 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:163005 self.assertTrue('std::make_unique' in results[0].message)
Vaclav Brozekb7fadb692018-08-30 06:39:533006 self.assertEqual(6, len(results[0].items))
Vaclav Brozek851d9602018-04-04 16:13:053007 self.assertTrue('foo.cc' in results[0].items[0])
3008 self.assertTrue('bar.mm' in results[0].items[1])
3009 self.assertTrue('mult.cc' in results[0].items[2])
3010 self.assertTrue('mult2.cc' in results[0].items[3])
3011 self.assertTrue('mult3.cc' in results[0].items[4])
Vaclav Brozekb7fadb692018-08-30 06:39:533012 self.assertTrue('multi_arg.cc' in results[0].items[5])
Vaclav Brozek52e18bf2018-04-03 07:05:243013
3014 def testFalsePositives(self):
3015 mock_input_api = MockInputApi()
3016 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:163017 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
3018 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
3019 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
3020 MockFile('dir/baz.cc', [
Vaclav Brozek52e18bf2018-04-03 07:05:243021 'std::unique_ptr<T> result = std::make_unique<T>();'
3022 ]),
Vaclav Brozeka54c528b2018-04-06 19:23:553023 MockFile('dir/baz2.cc', [
3024 'std::unique_ptr<T> result = std::make_unique<T>('
3025 ]),
3026 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
3027 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
Vaclav Brozekb7fadb692018-08-30 06:39:533028
3029 # Two-argument invocation of std::unique_ptr is exempt because there is
3030 # no equivalent using std::make_unique.
3031 MockFile('dir/multi_arg.cc', [
3032 'auto p = std::unique_ptr<T, D>(new T(), D());']),
Vaclav Brozek52e18bf2018-04-03 07:05:243033 ]
3034
Saagar Sanghavifceeaae2020-08-12 16:40:363035 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek52e18bf2018-04-03 07:05:243036 self.assertEqual(0, len(results))
3037
Danil Chapovalov3518f362018-08-11 16:13:433038class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
3039 def testBlocksDirectIncludes(self):
3040 mock_input_api = MockInputApi()
3041 mock_input_api.files = [
3042 MockFile('dir/foo_win.cc', ['#include "shlwapi.h"']),
3043 MockFile('dir/bar.h', ['#include <propvarutil.h>']),
3044 MockFile('dir/baz.h', ['#include <atlbase.h>']),
3045 MockFile('dir/jumbo.h', ['#include "sphelper.h"']),
3046 ]
Aleksey Khoroshilov9b28c032022-06-03 16:35:323047 results = PRESUBMIT.CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:593048 self.assertEqual(1, len(results))
3049 self.assertEqual(4, len(results[0].items))
Danil Chapovalov3518f362018-08-11 16:13:433050 self.assertTrue('StrCat' in results[0].message)
3051 self.assertTrue('foo_win.cc' in results[0].items[0])
3052 self.assertTrue('bar.h' in results[0].items[1])
3053 self.assertTrue('baz.h' in results[0].items[2])
3054 self.assertTrue('jumbo.h' in results[0].items[3])
3055
3056 def testAllowsToIncludeWrapper(self):
3057 mock_input_api = MockInputApi()
3058 mock_input_api.files = [
3059 MockFile('dir/baz_win.cc', ['#include "base/win/shlwapi.h"']),
3060 MockFile('dir/baz-win.h', ['#include "base/win/atl.h"']),
3061 ]
Aleksey Khoroshilov9b28c032022-06-03 16:35:323062 results = PRESUBMIT.CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:593063 self.assertEqual(0, len(results))
Danil Chapovalov3518f362018-08-11 16:13:433064
3065 def testAllowsToCreateWrapper(self):
3066 mock_input_api = MockInputApi()
3067 mock_input_api.files = [
3068 MockFile('base/win/shlwapi.h', [
3069 '#include <shlwapi.h>',
3070 '#include "base/win/windows_defines.inc"']),
3071 ]
Aleksey Khoroshilov9b28c032022-06-03 16:35:323072 results = PRESUBMIT.CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
3073 self.assertEqual(0, len(results))
3074
3075 def testIgnoresNonImplAndHeaders(self):
3076 mock_input_api = MockInputApi()
3077 mock_input_api.files = [
3078 MockFile('dir/foo_win.txt', ['#include "shlwapi.h"']),
3079 MockFile('dir/bar.asm', ['#include <propvarutil.h>']),
3080 ]
3081 results = PRESUBMIT.CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:593082 self.assertEqual(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:243083
Mustafa Emre Acer51f2f742020-03-09 19:41:123084
Rainhard Findlingfc31844c52020-05-15 09:58:263085class StringTest(unittest.TestCase):
3086 """Tests ICU syntax check and translation screenshots check."""
3087
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143088 # An empty grd file.
3089 OLD_GRD_CONTENTS = """<?xml version="1.0" encoding="UTF-8"?>
3090 <grit latest_public_release="1" current_release="1">
3091 <release seq="1">
3092 <messages></messages>
3093 </release>
3094 </grit>
3095 """.splitlines()
3096 # A grd file with a single message.
3097 NEW_GRD_CONTENTS1 = """<?xml version="1.0" encoding="UTF-8"?>
3098 <grit latest_public_release="1" current_release="1">
3099 <release seq="1">
3100 <messages>
3101 <message name="IDS_TEST1">
3102 Test string 1
3103 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:483104 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE1"
3105 translateable="false">
3106 Non translateable message 1, should be ignored
3107 </message>
Mustafa Emre Acered1a48962020-06-30 19:15:393108 <message name="IDS_TEST_STRING_ACCESSIBILITY"
Mustafa Emre Acerd3ca8be2020-07-07 22:35:343109 is_accessibility_with_no_ui="true">
Mustafa Emre Acered1a48962020-06-30 19:15:393110 Accessibility label 1, should be ignored
3111 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143112 </messages>
3113 </release>
3114 </grit>
3115 """.splitlines()
3116 # A grd file with two messages.
3117 NEW_GRD_CONTENTS2 = """<?xml version="1.0" encoding="UTF-8"?>
3118 <grit latest_public_release="1" current_release="1">
3119 <release seq="1">
3120 <messages>
3121 <message name="IDS_TEST1">
3122 Test string 1
3123 </message>
3124 <message name="IDS_TEST2">
3125 Test string 2
3126 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:483127 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE2"
3128 translateable="false">
3129 Non translateable message 2, should be ignored
3130 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143131 </messages>
3132 </release>
3133 </grit>
3134 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:263135 # A grd file with one ICU syntax message without syntax errors.
3136 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1 = """<?xml version="1.0" encoding="UTF-8"?>
3137 <grit latest_public_release="1" current_release="1">
3138 <release seq="1">
3139 <messages>
3140 <message name="IDS_TEST1">
3141 {NUM, plural,
3142 =1 {Test text for numeric one}
3143 other {Test text for plural with {NUM} as number}}
3144 </message>
3145 </messages>
3146 </release>
3147 </grit>
3148 """.splitlines()
3149 # A grd file with one ICU syntax message without syntax errors.
3150 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2 = """<?xml version="1.0" encoding="UTF-8"?>
3151 <grit latest_public_release="1" current_release="1">
3152 <release seq="1">
3153 <messages>
3154 <message name="IDS_TEST1">
3155 {NUM, plural,
3156 =1 {Different test text for numeric one}
3157 other {Different test text for plural with {NUM} as number}}
3158 </message>
3159 </messages>
3160 </release>
3161 </grit>
3162 """.splitlines()
3163 # A grd file with one ICU syntax message with syntax errors (misses a comma).
3164 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
3165 <grit latest_public_release="1" current_release="1">
3166 <release seq="1">
3167 <messages>
3168 <message name="IDS_TEST1">
3169 {NUM, plural
3170 =1 {Test text for numeric one}
3171 other {Test text for plural with {NUM} as number}}
3172 </message>
3173 </messages>
3174 </release>
3175 </grit>
3176 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143177
meacerff8a9b62019-12-10 19:43:583178 OLD_GRDP_CONTENTS = (
3179 '<?xml version="1.0" encoding="utf-8"?>',
3180 '<grit-part>',
3181 '</grit-part>'
3182 )
3183
3184 NEW_GRDP_CONTENTS1 = (
3185 '<?xml version="1.0" encoding="utf-8"?>',
3186 '<grit-part>',
3187 '<message name="IDS_PART_TEST1">',
3188 'Part string 1',
3189 '</message>',
3190 '</grit-part>')
3191
3192 NEW_GRDP_CONTENTS2 = (
3193 '<?xml version="1.0" encoding="utf-8"?>',
3194 '<grit-part>',
3195 '<message name="IDS_PART_TEST1">',
3196 'Part string 1',
3197 '</message>',
3198 '<message name="IDS_PART_TEST2">',
3199 'Part string 2',
3200 '</message>',
3201 '</grit-part>')
3202
Rainhard Findlingd8d04372020-08-13 13:30:093203 NEW_GRDP_CONTENTS3 = (
3204 '<?xml version="1.0" encoding="utf-8"?>',
3205 '<grit-part>',
3206 '<message name="IDS_PART_TEST1" desc="Description with typo.">',
3207 'Part string 1',
3208 '</message>',
3209 '</grit-part>')
3210
3211 NEW_GRDP_CONTENTS4 = (
3212 '<?xml version="1.0" encoding="utf-8"?>',
3213 '<grit-part>',
3214 '<message name="IDS_PART_TEST1" desc="Description with typo fixed.">',
3215 'Part string 1',
3216 '</message>',
3217 '</grit-part>')
3218
Rainhard Findling1a3e71e2020-09-21 07:33:353219 NEW_GRDP_CONTENTS5 = (
3220 '<?xml version="1.0" encoding="utf-8"?>',
3221 '<grit-part>',
3222 '<message name="IDS_PART_TEST1" meaning="Meaning with typo.">',
3223 'Part string 1',
3224 '</message>',
3225 '</grit-part>')
3226
3227 NEW_GRDP_CONTENTS6 = (
3228 '<?xml version="1.0" encoding="utf-8"?>',
3229 '<grit-part>',
3230 '<message name="IDS_PART_TEST1" meaning="Meaning with typo fixed.">',
3231 'Part string 1',
3232 '</message>',
3233 '</grit-part>')
3234
Rainhard Findlingfc31844c52020-05-15 09:58:263235 # A grdp file with one ICU syntax message without syntax errors.
3236 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = (
3237 '<?xml version="1.0" encoding="utf-8"?>',
3238 '<grit-part>',
3239 '<message name="IDS_PART_TEST1">',
3240 '{NUM, plural,',
3241 '=1 {Test text for numeric one}',
3242 'other {Test text for plural with {NUM} as number}}',
3243 '</message>',
3244 '</grit-part>')
3245 # A grdp file with one ICU syntax message without syntax errors.
3246 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2 = (
3247 '<?xml version="1.0" encoding="utf-8"?>',
3248 '<grit-part>',
3249 '<message name="IDS_PART_TEST1">',
3250 '{NUM, plural,',
3251 '=1 {Different test text for numeric one}',
3252 'other {Different test text for plural with {NUM} as number}}',
3253 '</message>',
3254 '</grit-part>')
3255
3256 # A grdp file with one ICU syntax message with syntax errors (superfluent
3257 # whitespace).
3258 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR = (
3259 '<?xml version="1.0" encoding="utf-8"?>',
3260 '<grit-part>',
3261 '<message name="IDS_PART_TEST1">',
3262 '{NUM, plural,',
3263 '= 1 {Test text for numeric one}',
3264 'other {Test text for plural with {NUM} as number}}',
3265 '</message>',
3266 '</grit-part>')
3267
Mustafa Emre Acerc8a012d2018-07-31 00:00:393268 DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
3269 'changelist. Run '
3270 'tools/translate/upload_screenshots.py to '
3271 'upload them instead:')
3272 GENERATE_SIGNATURES_MESSAGE = ('You are adding or modifying UI strings.\n'
3273 'To ensure the best translations, take '
3274 'screenshots of the relevant UI '
3275 '(https://g.co/chrome/translation) and add '
3276 'these files to your changelist:')
3277 REMOVE_SIGNATURES_MESSAGE = ('You removed strings associated with these '
3278 'files. Remove:')
Rainhard Findlingfc31844c52020-05-15 09:58:263279 ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
3280 'strings (problems or feedback? Contact '
3281 '[email protected]):')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143282
3283 def makeInputApi(self, files):
3284 input_api = MockInputApi()
3285 input_api.files = files
meacere7be7532019-10-02 17:41:033286 # Override os_path.exists because the presubmit uses the actual
3287 # os.path.exists.
3288 input_api.CreateMockFileInPath(
3289 [x.LocalPath() for x in input_api.AffectedFiles(include_deletes=True)])
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143290 return input_api
3291
meacerff8a9b62019-12-10 19:43:583292 """ CL modified and added messages, but didn't add any screenshots."""
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143293 def testNoScreenshots(self):
meacerff8a9b62019-12-10 19:43:583294 # No new strings (file contents same). Should not warn.
3295 input_api = self.makeInputApi([
3296 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
3297 self.NEW_GRD_CONTENTS1, action='M'),
3298 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1,
3299 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363300 warnings = PRESUBMIT.CheckStrings(input_api,
meacerff8a9b62019-12-10 19:43:583301 MockOutputApi())
3302 self.assertEqual(0, len(warnings))
3303
3304 # Add two new strings. Should have two warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143305 input_api = self.makeInputApi([
3306 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:583307 self.NEW_GRD_CONTENTS1, action='M'),
3308 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
3309 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363310 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143311 MockOutputApi())
3312 self.assertEqual(1, len(warnings))
3313 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003314 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013315 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583316 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3317 os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
3318 warnings[0].items)
Mustafa Emre Acer36eaad52019-11-12 23:03:343319
meacerff8a9b62019-12-10 19:43:583320 # Add four new strings. Should have four warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213321 input_api = self.makeInputApi([
3322 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:583323 self.OLD_GRD_CONTENTS, action='M'),
3324 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
3325 self.OLD_GRDP_CONTENTS, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363326 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213327 MockOutputApi())
3328 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003329 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213330 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583331 self.assertEqual([
3332 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3333 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3334 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3335 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3336 ], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213337
Rainhard Findlingd8d04372020-08-13 13:30:093338 def testModifiedMessageDescription(self):
3339 # CL modified a message description for a message that does not yet have a
Rainhard Findling1a3e71e2020-09-21 07:33:353340 # screenshot. Should not warn.
Rainhard Findlingd8d04372020-08-13 13:30:093341 input_api = self.makeInputApi([
3342 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
3343 self.NEW_GRDP_CONTENTS4, action='M')])
3344 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findling1a3e71e2020-09-21 07:33:353345 self.assertEqual(0, len(warnings))
Rainhard Findlingd8d04372020-08-13 13:30:093346
3347 # CL modified a message description for a message that already has a
3348 # screenshot. Should not warn.
3349 input_api = self.makeInputApi([
3350 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
3351 self.NEW_GRDP_CONTENTS4, action='M'),
3352 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3353 'binary', action='A')])
3354 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3355 self.assertEqual(0, len(warnings))
3356
Rainhard Findling1a3e71e2020-09-21 07:33:353357 def testModifiedMessageMeaning(self):
3358 # CL modified a message meaning for a message that does not yet have a
3359 # screenshot. Should warn.
3360 input_api = self.makeInputApi([
3361 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3362 self.NEW_GRDP_CONTENTS6, action='M')])
3363 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3364 self.assertEqual(1, len(warnings))
3365
3366 # CL modified a message meaning for a message that already has a
3367 # screenshot. Should not warn.
3368 input_api = self.makeInputApi([
3369 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3370 self.NEW_GRDP_CONTENTS6, action='M'),
3371 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3372 'binary', action='A')])
3373 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3374 self.assertEqual(0, len(warnings))
3375
meacerff8a9b62019-12-10 19:43:583376 def testPngAddedSha1NotAdded(self):
3377 # CL added one new message in a grd file and added the png file associated
3378 # with it, but did not add the corresponding sha1 file. This should warn
3379 # twice:
3380 # - Once for the added png file (because we don't want developers to upload
3381 # actual images)
3382 # - Once for the missing .sha1 file
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143383 input_api = self.makeInputApi([
Mustafa Emre Acerea3e57a2018-12-17 23:51:013384 MockAffectedFile(
3385 'test.grd',
3386 self.NEW_GRD_CONTENTS1,
3387 self.OLD_GRD_CONTENTS,
3388 action='M'),
3389 MockAffectedFile(
3390 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
3391 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363392 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143393 MockOutputApi())
3394 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003395 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143396 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013397 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
3398 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003399 self.assertEqual('error', warnings[1].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143400 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013401 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3402 warnings[1].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143403
meacerff8a9b62019-12-10 19:43:583404 # CL added two messages (one in grd, one in grdp) and added the png files
3405 # associated with the messages, but did not add the corresponding sha1
3406 # files. This should warn twice:
3407 # - Once for the added png files (because we don't want developers to upload
3408 # actual images)
3409 # - Once for the missing .sha1 files
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143410 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583411 # Modified files:
Mustafa Emre Acer36eaad52019-11-12 23:03:343412 MockAffectedFile(
3413 'test.grd',
meacerff8a9b62019-12-10 19:43:583414 self.NEW_GRD_CONTENTS1,
Mustafa Emre Acer36eaad52019-11-12 23:03:343415 self.OLD_GRD_CONTENTS,
meacer2308d0742019-11-12 18:15:423416 action='M'),
Mustafa Emre Acer12e7fee2019-11-18 18:49:553417 MockAffectedFile(
meacerff8a9b62019-12-10 19:43:583418 'part.grdp',
3419 self.NEW_GRDP_CONTENTS1,
3420 self.OLD_GRDP_CONTENTS,
3421 action='M'),
3422 # Added files:
3423 MockAffectedFile(
3424 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A'),
3425 MockAffectedFile(
3426 os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary',
3427 action='A')
Mustafa Emre Acerad8fb082019-11-19 04:24:213428 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363429 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213430 MockOutputApi())
3431 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003432 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213433 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583434 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png'),
3435 os.path.join('test_grd', 'IDS_TEST1.png')],
Mustafa Emre Acerad8fb082019-11-19 04:24:213436 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003437 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213438 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
meacerff8a9b62019-12-10 19:43:583439 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3440 os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3441 warnings[1].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213442
3443 def testScreenshotsWithSha1(self):
meacerff8a9b62019-12-10 19:43:583444 # CL added four messages (two each in a grd and grdp) and their
3445 # corresponding .sha1 files. No warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213446 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583447 # Modified files:
Mustafa Emre Acerad8fb082019-11-19 04:24:213448 MockAffectedFile(
3449 'test.grd',
3450 self.NEW_GRD_CONTENTS2,
3451 self.OLD_GRD_CONTENTS,
Mustafa Emre Acer12e7fee2019-11-18 18:49:553452 action='M'),
meacerff8a9b62019-12-10 19:43:583453 MockAffectedFile(
3454 'part.grdp',
3455 self.NEW_GRDP_CONTENTS2,
3456 self.OLD_GRDP_CONTENTS,
3457 action='M'),
3458 # Added files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013459 MockFile(
3460 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3461 'binary',
3462 action='A'),
3463 MockFile(
3464 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3465 'binary',
meacerff8a9b62019-12-10 19:43:583466 action='A'),
3467 MockFile(
3468 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3469 'binary',
3470 action='A'),
3471 MockFile(
3472 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3473 'binary',
3474 action='A'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013475 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363476 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143477 MockOutputApi())
3478 self.assertEqual([], warnings)
3479
3480 def testScreenshotsRemovedWithSha1(self):
meacerff8a9b62019-12-10 19:43:583481 # Replace new contents with old contents in grd and grp files, removing
3482 # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3483 # Should warn to remove the sha1 files associated with these strings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143484 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583485 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013486 MockAffectedFile(
3487 'test.grd',
meacerff8a9b62019-12-10 19:43:583488 self.OLD_GRD_CONTENTS, # new_contents
3489 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013490 action='M'),
meacerff8a9b62019-12-10 19:43:583491 MockAffectedFile(
3492 'part.grdp',
3493 self.OLD_GRDP_CONTENTS, # new_contents
3494 self.NEW_GRDP_CONTENTS2, # old_contents
3495 action='M'),
3496 # Unmodified files:
3497 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
3498 MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', ''),
3499 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3500 'binary', ''),
3501 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3502 'binary', '')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013503 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363504 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143505 MockOutputApi())
3506 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003507 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143508 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013509 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583510 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3511 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013512 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3513 os.path.join('test_grd', 'IDS_TEST2.png.sha1')
3514 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143515
meacerff8a9b62019-12-10 19:43:583516 # Same as above, but this time one of the .sha1 files is also removed.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143517 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583518 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013519 MockAffectedFile(
3520 'test.grd',
meacerff8a9b62019-12-10 19:43:583521 self.OLD_GRD_CONTENTS, # new_contents
3522 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013523 action='M'),
meacerff8a9b62019-12-10 19:43:583524 MockAffectedFile(
3525 'part.grdp',
3526 self.OLD_GRDP_CONTENTS, # new_contents
3527 self.NEW_GRDP_CONTENTS2, # old_contents
3528 action='M'),
3529 # Unmodified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013530 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
meacerff8a9b62019-12-10 19:43:583531 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3532 'binary', ''),
3533 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013534 MockAffectedFile(
3535 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3536 '',
3537 'old_contents',
meacerff8a9b62019-12-10 19:43:583538 action='D'),
3539 MockAffectedFile(
3540 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3541 '',
3542 'old_contents',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013543 action='D')
3544 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363545 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143546 MockOutputApi())
3547 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003548 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143549 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583550 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3551 os.path.join('test_grd', 'IDS_TEST1.png.sha1')
3552 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143553
meacerff8a9b62019-12-10 19:43:583554 # Remove all sha1 files. There should be no warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143555 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583556 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013557 MockAffectedFile(
3558 'test.grd',
3559 self.OLD_GRD_CONTENTS,
3560 self.NEW_GRD_CONTENTS2,
3561 action='M'),
meacerff8a9b62019-12-10 19:43:583562 MockAffectedFile(
3563 'part.grdp',
3564 self.OLD_GRDP_CONTENTS,
3565 self.NEW_GRDP_CONTENTS2,
3566 action='M'),
3567 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013568 MockFile(
3569 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3570 'binary',
3571 action='D'),
3572 MockFile(
3573 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3574 'binary',
meacerff8a9b62019-12-10 19:43:583575 action='D'),
3576 MockFile(
3577 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3578 'binary',
3579 action='D'),
3580 MockFile(
3581 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3582 'binary',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013583 action='D')
3584 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363585 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143586 MockOutputApi())
3587 self.assertEqual([], warnings)
3588
Rainhard Findlingfc31844c52020-05-15 09:58:263589 def testIcuSyntax(self):
3590 # Add valid ICU syntax string. Should not raise an error.
3591 input_api = self.makeInputApi([
3592 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3593 self.NEW_GRD_CONTENTS1, action='M'),
3594 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3595 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363596 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263597 # We expect no ICU syntax errors.
3598 icu_errors = [e for e in results
3599 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3600 self.assertEqual(0, len(icu_errors))
3601
3602 # Valid changes in ICU syntax. Should not raise an error.
3603 input_api = self.makeInputApi([
3604 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3605 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3606 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3607 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363608 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263609 # We expect no ICU syntax errors.
3610 icu_errors = [e for e in results
3611 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3612 self.assertEqual(0, len(icu_errors))
3613
3614 # Add invalid ICU syntax strings. Should raise two errors.
3615 input_api = self.makeInputApi([
3616 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3617 self.NEW_GRD_CONTENTS1, action='M'),
3618 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3619 self.NEW_GRD_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363620 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263621 # We expect 2 ICU syntax errors.
3622 icu_errors = [e for e in results
3623 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3624 self.assertEqual(1, len(icu_errors))
3625 self.assertEqual([
3626 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3627 'ICU syntax.',
3628 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3629 ], icu_errors[0].items)
3630
3631 # Change two strings to have ICU syntax errors. Should raise two errors.
3632 input_api = self.makeInputApi([
3633 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3634 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3635 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3636 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363637 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263638 # We expect 2 ICU syntax errors.
3639 icu_errors = [e for e in results
3640 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3641 self.assertEqual(1, len(icu_errors))
3642 self.assertEqual([
3643 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3644 'ICU syntax.',
3645 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3646 ], icu_errors[0].items)
3647
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143648
Mustafa Emre Acer51f2f742020-03-09 19:41:123649class TranslationExpectationsTest(unittest.TestCase):
3650 ERROR_MESSAGE_FORMAT = (
3651 "Failed to get a list of translatable grd files. "
3652 "This happens when:\n"
3653 " - One of the modified grd or grdp files cannot be parsed or\n"
3654 " - %s is not updated.\n"
3655 "Stack:\n"
3656 )
3657 REPO_ROOT = os.path.join('tools', 'translation', 'testdata')
3658 # This lists all .grd files under REPO_ROOT.
3659 EXPECTATIONS = os.path.join(REPO_ROOT,
3660 "translation_expectations.pyl")
3661 # This lists all .grd files under REPO_ROOT except unlisted.grd.
3662 EXPECTATIONS_WITHOUT_UNLISTED_FILE = os.path.join(
3663 REPO_ROOT, "translation_expectations_without_unlisted_file.pyl")
3664
3665 # Tests that the presubmit doesn't return when no grd or grdp files are
3666 # modified.
3667 def testExpectationsNoModifiedGrd(self):
3668 input_api = MockInputApi()
3669 input_api.files = [
3670 MockAffectedFile('not_used.txt', 'not used', 'not used', action='M')
3671 ]
3672 # Fake list of all grd files in the repo. This list is missing all grd/grdps
3673 # under tools/translation/testdata. This is OK because the presubmit won't
3674 # run in the first place since there are no modified grd/grps in input_api.
3675 grd_files = ['doesnt_exist_doesnt_matter.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363676 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123677 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3678 grd_files)
3679 self.assertEqual(0, len(warnings))
3680
3681
3682 # Tests that the list of files passed to the presubmit matches the list of
3683 # files in the expectations.
3684 def testExpectationsSuccess(self):
3685 # Mock input file list needs a grd or grdp file in order to run the
3686 # presubmit. The file itself doesn't matter.
3687 input_api = MockInputApi()
3688 input_api.files = [
3689 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3690 ]
3691 # List of all grd files in the repo.
3692 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3693 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363694 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123695 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3696 grd_files)
3697 self.assertEqual(0, len(warnings))
3698
3699 # Tests that the presubmit warns when a file is listed in expectations, but
3700 # does not actually exist.
3701 def testExpectationsMissingFile(self):
3702 # Mock input file list needs a grd or grdp file in order to run the
3703 # presubmit.
3704 input_api = MockInputApi()
3705 input_api.files = [
3706 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3707 ]
3708 # unlisted.grd is listed under tools/translation/testdata but is not
3709 # included in translation expectations.
3710 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363711 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123712 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3713 grd_files)
3714 self.assertEqual(1, len(warnings))
3715 self.assertTrue(warnings[0].message.startswith(
3716 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS))
3717 self.assertTrue(
3718 ("test.grd is listed in the translation expectations, "
3719 "but this grd file does not exist")
3720 in warnings[0].message)
3721
3722 # Tests that the presubmit warns when a file is not listed in expectations but
3723 # does actually exist.
3724 def testExpectationsUnlistedFile(self):
3725 # Mock input file list needs a grd or grdp file in order to run the
3726 # presubmit.
3727 input_api = MockInputApi()
3728 input_api.files = [
3729 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3730 ]
3731 # unlisted.grd is listed under tools/translation/testdata but is not
3732 # included in translation expectations.
3733 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3734 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363735 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123736 input_api, MockOutputApi(), self.REPO_ROOT,
3737 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3738 self.assertEqual(1, len(warnings))
3739 self.assertTrue(warnings[0].message.startswith(
3740 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3741 self.assertTrue(
3742 ("unlisted.grd appears to be translatable "
3743 "(because it contains <file> or <message> elements), "
3744 "but is not listed in the translation expectations.")
3745 in warnings[0].message)
3746
3747 # Tests that the presubmit warns twice:
3748 # - for a non-existing file listed in expectations
3749 # - for an existing file not listed in expectations
3750 def testMultipleWarnings(self):
3751 # Mock input file list needs a grd or grdp file in order to run the
3752 # presubmit.
3753 input_api = MockInputApi()
3754 input_api.files = [
3755 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3756 ]
3757 # unlisted.grd is listed under tools/translation/testdata but is not
3758 # included in translation expectations.
3759 # test.grd is not listed under tools/translation/testdata but is included
3760 # in translation expectations.
3761 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363762 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123763 input_api, MockOutputApi(), self.REPO_ROOT,
3764 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3765 self.assertEqual(1, len(warnings))
3766 self.assertTrue(warnings[0].message.startswith(
3767 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3768 self.assertTrue(
3769 ("unlisted.grd appears to be translatable "
3770 "(because it contains <file> or <message> elements), "
3771 "but is not listed in the translation expectations.")
3772 in warnings[0].message)
3773 self.assertTrue(
3774 ("test.grd is listed in the translation expectations, "
3775 "but this grd file does not exist")
3776 in warnings[0].message)
3777
3778
Dominic Battre033531052018-09-24 15:45:343779class DISABLETypoInTest(unittest.TestCase):
3780
3781 def testPositive(self):
3782 # Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
3783 # where the desire is to disable a test.
3784 tests = [
3785 # Disabled on one platform:
3786 '#if defined(OS_WIN)\n'
3787 '#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
3788 '#else\n'
3789 '#define MAYBE_FoobarTest FoobarTest\n'
3790 '#endif\n',
3791 # Disabled on one platform spread cross lines:
3792 '#if defined(OS_WIN)\n'
3793 '#define MAYBE_FoobarTest \\\n'
3794 ' DISABLE_FoobarTest\n'
3795 '#else\n'
3796 '#define MAYBE_FoobarTest FoobarTest\n'
3797 '#endif\n',
3798 # Disabled on all platforms:
3799 ' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
3800 # Disabled on all platforms but multiple lines
3801 ' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
3802 ]
3803
3804 for test in tests:
3805 mock_input_api = MockInputApi()
3806 mock_input_api.files = [
3807 MockFile('some/path/foo_unittest.cc', test.splitlines()),
3808 ]
3809
Saagar Sanghavifceeaae2020-08-12 16:40:363810 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343811 MockOutputApi())
3812 self.assertEqual(
3813 1,
3814 len(results),
3815 msg=('expected len(results) == 1 but got %d in test: %s' %
3816 (len(results), test)))
3817 self.assertTrue(
3818 'foo_unittest.cc' in results[0].message,
3819 msg=('expected foo_unittest.cc in message but got %s in test %s' %
3820 (results[0].message, test)))
3821
3822 def testIngoreNotTestFiles(self):
3823 mock_input_api = MockInputApi()
3824 mock_input_api.files = [
3825 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'),
3826 ]
3827
Saagar Sanghavifceeaae2020-08-12 16:40:363828 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343829 MockOutputApi())
3830 self.assertEqual(0, len(results))
3831
Katie Df13948e2018-09-25 07:33:443832 def testIngoreDeletedFiles(self):
3833 mock_input_api = MockInputApi()
3834 mock_input_api.files = [
3835 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'),
3836 ]
3837
Saagar Sanghavifceeaae2020-08-12 16:40:363838 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Katie Df13948e2018-09-25 07:33:443839 MockOutputApi())
3840 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:343841
Nina Satragnof7660532021-09-20 18:03:353842class ForgettingMAYBEInTests(unittest.TestCase):
3843 def testPositive(self):
3844 test = (
3845 '#if defined(HAS_ENERGY)\n'
3846 '#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
3847 '#else\n'
3848 '#define MAYBE_CastExplosion CastExplosion\n'
3849 '#endif\n'
3850 'TEST_F(ArchWizard, CastExplosion) {\n'
3851 '#if defined(ARCH_PRIEST_IN_PARTY)\n'
3852 '#define MAYBE_ArchPriest ArchPriest\n'
3853 '#else\n'
3854 '#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
3855 '#endif\n'
3856 'TEST_F(ArchPriest, CastNaturesBounty) {\n'
3857 '#if !defined(CRUSADER_IN_PARTY)\n'
3858 '#define MAYBE_Crusader \\\n'
3859 ' DISABLED_Crusader \n'
3860 '#else\n'
3861 '#define MAYBE_Crusader \\\n'
3862 ' Crusader\n'
3863 '#endif\n'
3864 ' TEST_F(\n'
3865 ' Crusader,\n'
3866 ' CastTaunt) { }\n'
3867 '#if defined(LEARNED_BASIC_SKILLS)\n'
3868 '#define MAYBE_CastSteal \\\n'
3869 ' DISABLED_CastSteal \n'
3870 '#else\n'
3871 '#define MAYBE_CastSteal \\\n'
3872 ' CastSteal\n'
3873 '#endif\n'
3874 ' TEST_F(\n'
3875 ' ThiefClass,\n'
3876 ' CastSteal) { }\n'
3877 )
3878 mock_input_api = MockInputApi()
3879 mock_input_api.files = [
3880 MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
3881 ]
3882 results = PRESUBMIT.CheckForgettingMAYBEInTests(mock_input_api,
3883 MockOutputApi())
3884 self.assertEqual(4, len(results))
3885 self.assertTrue('CastExplosion' in results[0].message)
3886 self.assertTrue('fantasyworld/classes_unittest.cc:2' in results[0].message)
3887 self.assertTrue('ArchPriest' in results[1].message)
3888 self.assertTrue('fantasyworld/classes_unittest.cc:8' in results[1].message)
3889 self.assertTrue('Crusader' in results[2].message)
3890 self.assertTrue('fantasyworld/classes_unittest.cc:14' in results[2].message)
3891 self.assertTrue('CastSteal' in results[3].message)
3892 self.assertTrue('fantasyworld/classes_unittest.cc:24' in results[3].message)
3893
3894 def testNegative(self):
3895 test = (
3896 '#if defined(HAS_ENERGY)\n'
3897 '#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
3898 '#else\n'
3899 '#define MAYBE_CastExplosion CastExplosion\n'
3900 '#endif\n'
3901 'TEST_F(ArchWizard, MAYBE_CastExplosion) {\n'
3902 '#if defined(ARCH_PRIEST_IN_PARTY)\n'
3903 '#define MAYBE_ArchPriest ArchPriest\n'
3904 '#else\n'
3905 '#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
3906 '#endif\n'
3907 'TEST_F(MAYBE_ArchPriest, CastNaturesBounty) {\n'
3908 '#if !defined(CRUSADER_IN_PARTY)\n'
3909 '#define MAYBE_Crusader \\\n'
3910 ' DISABLED_Crusader \n'
3911 '#else\n'
3912 '#define MAYBE_Crusader \\\n'
3913 ' Crusader\n'
3914 '#endif\n'
3915 ' TEST_F(\n'
3916 ' MAYBE_Crusader,\n'
3917 ' CastTaunt) { }\n'
3918 '#if defined(LEARNED_BASIC_SKILLS)\n'
3919 '#define MAYBE_CastSteal \\\n'
3920 ' DISABLED_CastSteal \n'
3921 '#else\n'
3922 '#define MAYBE_CastSteal \\\n'
3923 ' CastSteal\n'
3924 '#endif\n'
3925 ' TEST_F(\n'
3926 ' ThiefClass,\n'
3927 ' MAYBE_CastSteal) { }\n'
3928 )
3929
3930 mock_input_api = MockInputApi()
3931 mock_input_api.files = [
3932 MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
3933 ]
3934 results = PRESUBMIT.CheckForgettingMAYBEInTests(mock_input_api,
3935 MockOutputApi())
3936 self.assertEqual(0, len(results))
Dirk Pranke3c18a382019-03-15 01:07:513937
Max Morozb47503b2019-08-08 21:03:273938class CheckFuzzTargetsTest(unittest.TestCase):
3939
3940 def _check(self, files):
3941 mock_input_api = MockInputApi()
3942 mock_input_api.files = []
3943 for fname, contents in files.items():
3944 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363945 return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api, MockOutputApi())
Max Morozb47503b2019-08-08 21:03:273946
3947 def testLibFuzzerSourcesIgnored(self):
3948 results = self._check({
3949 "third_party/lib/Fuzzer/FuzzerDriver.cpp": "LLVMFuzzerInitialize",
3950 })
3951 self.assertEqual(results, [])
3952
3953 def testNonCodeFilesIgnored(self):
3954 results = self._check({
3955 "README.md": "LLVMFuzzerInitialize",
3956 })
3957 self.assertEqual(results, [])
3958
3959 def testNoErrorHeaderPresent(self):
3960 results = self._check({
3961 "fuzzer.cc": (
3962 "#include \"testing/libfuzzer/libfuzzer_exports.h\"\n" +
3963 "LLVMFuzzerInitialize"
3964 )
3965 })
3966 self.assertEqual(results, [])
3967
3968 def testErrorMissingHeader(self):
3969 results = self._check({
3970 "fuzzer.cc": "LLVMFuzzerInitialize"
3971 })
3972 self.assertEqual(len(results), 1)
3973 self.assertEqual(results[0].items, ['fuzzer.cc'])
3974
3975
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263976class SetNoParentTest(unittest.TestCase):
John Abd-El-Malekdfd1edc2021-02-24 22:22:403977 def testSetNoParentTopLevelAllowed(self):
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263978 mock_input_api = MockInputApi()
3979 mock_input_api.files = [
3980 MockAffectedFile('goat/OWNERS',
3981 [
3982 'set noparent',
3983 '[email protected]',
John Abd-El-Malekdfd1edc2021-02-24 22:22:403984 ])
3985 ]
3986 mock_output_api = MockOutputApi()
3987 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
3988 self.assertEqual([], errors)
3989
3990 def testSetNoParentMissing(self):
3991 mock_input_api = MockInputApi()
3992 mock_input_api.files = [
3993 MockAffectedFile('services/goat/OWNERS',
3994 [
3995 'set noparent',
3996 '[email protected]',
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263997 'per-file *.json=set noparent',
3998 'per-file *[email protected]',
3999 ])
4000 ]
4001 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:364002 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264003 self.assertEqual(1, len(errors))
4004 self.assertTrue('goat/OWNERS:1' in errors[0].long_text)
4005 self.assertTrue('goat/OWNERS:3' in errors[0].long_text)
4006
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264007 def testSetNoParentWithCorrectRule(self):
4008 mock_input_api = MockInputApi()
4009 mock_input_api.files = [
John Abd-El-Malekdfd1edc2021-02-24 22:22:404010 MockAffectedFile('services/goat/OWNERS',
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264011 [
4012 'set noparent',
4013 'file://ipc/SECURITY_OWNERS',
4014 'per-file *.json=set noparent',
4015 'per-file *.json=file://ipc/SECURITY_OWNERS',
4016 ])
4017 ]
4018 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:364019 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264020 self.assertEqual([], errors)
4021
4022
Ken Rockotc31f4832020-05-29 18:58:514023class MojomStabilityCheckTest(unittest.TestCase):
4024 def runTestWithAffectedFiles(self, affected_files):
4025 mock_input_api = MockInputApi()
4026 mock_input_api.files = affected_files
4027 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:364028 return PRESUBMIT.CheckStableMojomChanges(
Ken Rockotc31f4832020-05-29 18:58:514029 mock_input_api, mock_output_api)
4030
4031 def testSafeChangePasses(self):
4032 errors = self.runTestWithAffectedFiles([
4033 MockAffectedFile('foo/foo.mojom',
4034 ['[Stable] struct S { [MinVersion=1] int32 x; };'],
4035 old_contents=['[Stable] struct S {};'])
4036 ])
4037 self.assertEqual([], errors)
4038
4039 def testBadChangeFails(self):
4040 errors = self.runTestWithAffectedFiles([
4041 MockAffectedFile('foo/foo.mojom',
4042 ['[Stable] struct S { int32 x; };'],
4043 old_contents=['[Stable] struct S {};'])
4044 ])
4045 self.assertEqual(1, len(errors))
4046 self.assertTrue('not backward-compatible' in errors[0].message)
4047
Ken Rockotad7901f942020-06-04 20:17:094048 def testDeletedFile(self):
4049 """Regression test for https://crbug.com/1091407."""
4050 errors = self.runTestWithAffectedFiles([
4051 MockAffectedFile('a.mojom', [], old_contents=['struct S {};'],
4052 action='D'),
4053 MockAffectedFile('b.mojom',
4054 ['struct S {}; struct T { S s; };'],
4055 old_contents=['import "a.mojom"; struct T { S s; };'])
4056 ])
4057 self.assertEqual([], errors)
4058
Jose Magana2b456f22021-03-09 23:26:404059class CheckForUseOfChromeAppsDeprecationsTest(unittest.TestCase):
4060
4061 ERROR_MSG_PIECE = 'technologies which will soon be deprecated'
4062
4063 # Each positive test is also a naive negative test for the other cases.
4064
4065 def testWarningNMF(self):
4066 mock_input_api = MockInputApi()
4067 mock_input_api.files = [
4068 MockAffectedFile(
4069 'foo.NMF',
4070 ['"program"', '"Z":"content"', 'B'],
4071 ['"program"', 'B'],
4072 scm_diff='\n'.join([
4073 '--- foo.NMF.old 2020-12-02 20:40:54.430676385 +0100',
4074 '+++ foo.NMF.new 2020-12-02 20:41:02.086700197 +0100',
4075 '@@ -1,2 +1,3 @@',
4076 ' "program"',
4077 '+"Z":"content"',
4078 ' B']),
4079 action='M')
4080 ]
4081 mock_output_api = MockOutputApi()
4082 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
4083 mock_output_api)
4084 self.assertEqual(1, len(errors))
4085 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
4086 self.assertTrue( 'foo.NMF' in errors[0].message)
4087
4088 def testWarningManifest(self):
4089 mock_input_api = MockInputApi()
4090 mock_input_api.files = [
4091 MockAffectedFile(
4092 'manifest.json',
4093 ['"app":', '"Z":"content"', 'B'],
4094 ['"app":"', 'B'],
4095 scm_diff='\n'.join([
4096 '--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
4097 '+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
4098 '@@ -1,2 +1,3 @@',
4099 ' "app"',
4100 '+"Z":"content"',
4101 ' B']),
4102 action='M')
4103 ]
4104 mock_output_api = MockOutputApi()
4105 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
4106 mock_output_api)
4107 self.assertEqual(1, len(errors))
4108 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
4109 self.assertTrue( 'manifest.json' in errors[0].message)
4110
4111 def testOKWarningManifestWithoutApp(self):
4112 mock_input_api = MockInputApi()
4113 mock_input_api.files = [
4114 MockAffectedFile(
4115 'manifest.json',
4116 ['"name":', '"Z":"content"', 'B'],
4117 ['"name":"', 'B'],
4118 scm_diff='\n'.join([
4119 '--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
4120 '+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
4121 '@@ -1,2 +1,3 @@',
4122 ' "app"',
4123 '+"Z":"content"',
4124 ' B']),
4125 action='M')
4126 ]
4127 mock_output_api = MockOutputApi()
4128 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
4129 mock_output_api)
4130 self.assertEqual(0, len(errors))
4131
4132 def testWarningPPAPI(self):
4133 mock_input_api = MockInputApi()
4134 mock_input_api.files = [
4135 MockAffectedFile(
4136 'foo.hpp',
4137 ['A', '#include <ppapi.h>', 'B'],
4138 ['A', 'B'],
4139 scm_diff='\n'.join([
4140 '--- foo.hpp.old 2020-12-02 20:40:54.430676385 +0100',
4141 '+++ foo.hpp.new 2020-12-02 20:41:02.086700197 +0100',
4142 '@@ -1,2 +1,3 @@',
4143 ' A',
4144 '+#include <ppapi.h>',
4145 ' B']),
4146 action='M')
4147 ]
4148 mock_output_api = MockOutputApi()
4149 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
4150 mock_output_api)
4151 self.assertEqual(1, len(errors))
4152 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
4153 self.assertTrue( 'foo.hpp' in errors[0].message)
4154
4155 def testNoWarningPPAPI(self):
4156 mock_input_api = MockInputApi()
4157 mock_input_api.files = [
4158 MockAffectedFile(
4159 'foo.txt',
4160 ['A', 'Peppapig', 'B'],
4161 ['A', 'B'],
4162 scm_diff='\n'.join([
4163 '--- foo.txt.old 2020-12-02 20:40:54.430676385 +0100',
4164 '+++ foo.txt.new 2020-12-02 20:41:02.086700197 +0100',
4165 '@@ -1,2 +1,3 @@',
4166 ' A',
4167 '+Peppapig',
4168 ' B']),
4169 action='M')
4170 ]
4171 mock_output_api = MockOutputApi()
4172 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
4173 mock_output_api)
4174 self.assertEqual(0, len(errors))
4175
Dominic Battre645d42342020-12-04 16:14:104176class CheckDeprecationOfPreferencesTest(unittest.TestCase):
4177 # Test that a warning is generated if a preference registration is removed
4178 # from a random file.
4179 def testWarning(self):
4180 mock_input_api = MockInputApi()
4181 mock_input_api.files = [
4182 MockAffectedFile(
4183 'foo.cc',
4184 ['A', 'B'],
4185 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
4186 scm_diff='\n'.join([
4187 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
4188 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
4189 '@@ -1,3 +1,2 @@',
4190 ' A',
4191 '-prefs->RegisterStringPref("foo", "default");',
4192 ' B']),
4193 action='M')
4194 ]
4195 mock_output_api = MockOutputApi()
4196 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
4197 mock_output_api)
4198 self.assertEqual(1, len(errors))
4199 self.assertTrue(
4200 'Discovered possible removal of preference registrations' in
4201 errors[0].message)
4202
4203 # Test that a warning is inhibited if the preference registration was moved
4204 # to the deprecation functions in browser prefs.
4205 def testNoWarningForMigration(self):
4206 mock_input_api = MockInputApi()
4207 mock_input_api.files = [
4208 # RegisterStringPref was removed from foo.cc.
4209 MockAffectedFile(
4210 'foo.cc',
4211 ['A', 'B'],
4212 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
4213 scm_diff='\n'.join([
4214 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
4215 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
4216 '@@ -1,3 +1,2 @@',
4217 ' A',
4218 '-prefs->RegisterStringPref("foo", "default");',
4219 ' B']),
4220 action='M'),
4221 # But the preference was properly migrated.
4222 MockAffectedFile(
4223 'chrome/browser/prefs/browser_prefs.cc',
4224 [
4225 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4226 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4227 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4228 'prefs->RegisterStringPref("foo", "default");',
4229 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4230 ],
4231 [
4232 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4233 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4234 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4235 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4236 ],
4237 scm_diff='\n'.join([
4238 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
4239 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
4240 '@@ -2,3 +2,4 @@',
4241 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4242 ' // BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4243 '+prefs->RegisterStringPref("foo", "default");',
4244 ' // END_MIGRATE_OBSOLETE_PROFILE_PREFS']),
4245 action='M'),
4246 ]
4247 mock_output_api = MockOutputApi()
4248 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
4249 mock_output_api)
4250 self.assertEqual(0, len(errors))
4251
4252 # Test that a warning is NOT inhibited if the preference registration was
4253 # moved to a place outside of the migration functions in browser_prefs.cc
4254 def testWarningForImproperMigration(self):
4255 mock_input_api = MockInputApi()
4256 mock_input_api.files = [
4257 # RegisterStringPref was removed from foo.cc.
4258 MockAffectedFile(
4259 'foo.cc',
4260 ['A', 'B'],
4261 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
4262 scm_diff='\n'.join([
4263 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
4264 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
4265 '@@ -1,3 +1,2 @@',
4266 ' A',
4267 '-prefs->RegisterStringPref("foo", "default");',
4268 ' B']),
4269 action='M'),
4270 # The registration call was moved to a place in browser_prefs.cc that
4271 # is outside the migration functions.
4272 MockAffectedFile(
4273 'chrome/browser/prefs/browser_prefs.cc',
4274 [
4275 'prefs->RegisterStringPref("foo", "default");',
4276 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4277 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4278 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4279 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4280 ],
4281 [
4282 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4283 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4284 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4285 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4286 ],
4287 scm_diff='\n'.join([
4288 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
4289 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
4290 '@@ -1,2 +1,3 @@',
4291 '+prefs->RegisterStringPref("foo", "default");',
4292 ' // BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4293 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS']),
4294 action='M'),
4295 ]
4296 mock_output_api = MockOutputApi()
4297 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
4298 mock_output_api)
4299 self.assertEqual(1, len(errors))
4300 self.assertTrue(
4301 'Discovered possible removal of preference registrations' in
4302 errors[0].message)
4303
4304 # Check that the presubmit fails if a marker line in brower_prefs.cc is
4305 # deleted.
4306 def testDeletedMarkerRaisesError(self):
4307 mock_input_api = MockInputApi()
4308 mock_input_api.files = [
4309 MockAffectedFile('chrome/browser/prefs/browser_prefs.cc',
4310 [
4311 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4312 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4313 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4314 # The following line is deleted for this test
4315 # '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4316 ])
4317 ]
4318 mock_output_api = MockOutputApi()
4319 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
4320 mock_output_api)
4321 self.assertEqual(1, len(errors))
4322 self.assertEqual(
4323 'Broken .*MIGRATE_OBSOLETE_.*_PREFS markers in browser_prefs.cc.',
4324 errors[0].message)
4325
Kevin McNee967dd2d22021-11-15 16:09:294326class MPArchApiUsage(unittest.TestCase):
Kevin McNee4eeec792022-02-14 20:02:044327 def _assert_notify(
4328 self, expected_uses, msg, local_path, new_contents):
Kevin McNee967dd2d22021-11-15 16:09:294329 mock_input_api = MockInputApi()
4330 mock_output_api = MockOutputApi()
4331 mock_input_api.files = [
4332 MockFile(local_path, new_contents),
4333 ]
Kevin McNee4eeec792022-02-14 20:02:044334 result = PRESUBMIT.CheckMPArchApiUsage(mock_input_api, mock_output_api)
Kevin McNee967dd2d22021-11-15 16:09:294335 self.assertEqual(
Kevin McNee4eeec792022-02-14 20:02:044336 bool(expected_uses),
Kevin McNee967dd2d22021-11-15 16:09:294337 '[email protected]' in mock_output_api.more_cc,
4338 msg)
Kevin McNee4eeec792022-02-14 20:02:044339 if expected_uses:
4340 self.assertEqual(1, len(result), msg)
4341 self.assertEqual(result[0].type, 'notify', msg)
4342 self.assertEqual(sorted(result[0].items), sorted(expected_uses), msg)
Kevin McNee967dd2d22021-11-15 16:09:294343
4344 def testNotify(self):
4345 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044346 ['WebContentsObserver', 'WebContentsUserData'],
Kevin McNee967dd2d22021-11-15 16:09:294347 'Introduce WCO and WCUD',
4348 'chrome/my_feature.h',
4349 ['class MyFeature',
4350 ' : public content::WebContentsObserver,',
4351 ' public content::WebContentsUserData<MyFeature> {};',
4352 ])
4353 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044354 ['DidFinishNavigation'],
Kevin McNee967dd2d22021-11-15 16:09:294355 'Introduce WCO override',
4356 'chrome/my_feature.h',
4357 ['void DidFinishNavigation(',
4358 ' content::NavigationHandle* navigation_handle) override;',
4359 ])
4360 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044361 ['IsInMainFrame'],
Kevin McNee967dd2d22021-11-15 16:09:294362 'Introduce IsInMainFrame',
4363 'chrome/my_feature.cc',
4364 ['void DoSomething(content::NavigationHandle* navigation_handle) {',
4365 ' if (navigation_handle->IsInMainFrame())',
4366 ' all_of_our_page_state.reset();',
4367 '}',
4368 ])
4369 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044370 ['FromRenderFrameHost'],
Kevin McNee967dd2d22021-11-15 16:09:294371 'Introduce WC::FromRenderFrameHost',
4372 'chrome/my_feature.cc',
4373 ['void DoSomething(content::RenderFrameHost* rfh) {',
4374 ' auto* wc = content::WebContents::FromRenderFrameHost(rfh);',
4375 ' ChangeTabState(wc);',
4376 '}',
4377 ])
4378
4379 def testNoNotify(self):
4380 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044381 [],
Kevin McNee967dd2d22021-11-15 16:09:294382 'No API usage',
4383 'chrome/my_feature.cc',
4384 ['void DoSomething() {',
4385 ' // TODO: Something',
4386 '}',
4387 ])
4388 # Something under a top level directory we're not concerned about happens
4389 # to share a name with a content API.
4390 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044391 [],
Kevin McNee967dd2d22021-11-15 16:09:294392 'Uninteresting top level directory',
4393 'third_party/my_dep/my_code.cc',
4394 ['bool HasParent(Node* node) {',
4395 ' return node->GetParent();',
4396 '}',
4397 ])
4398 # We're not concerned with usage in test code.
4399 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044400 [],
Kevin McNee967dd2d22021-11-15 16:09:294401 'Usage in test code',
4402 'chrome/my_feature_unittest.cc',
4403 ['TEST_F(MyFeatureTest, DoesSomething) {',
4404 ' EXPECT_TRUE(web_contents()->GetMainFrame());',
4405 '}',
4406 ])
4407
Dominic Battre645d42342020-12-04 16:14:104408
Henrique Ferreiro2a4b55942021-11-29 23:45:364409class AssertAshOnlyCodeTest(unittest.TestCase):
4410 def testErrorsOnlyOnAshDirectories(self):
4411 files_in_ash = [
4412 MockFile('ash/BUILD.gn', []),
4413 MockFile('chrome/browser/ash/BUILD.gn', []),
4414 ]
4415 other_files = [
4416 MockFile('chrome/browser/BUILD.gn', []),
4417 MockFile('chrome/browser/BUILD.gn', ['assert(is_chromeos_ash)']),
4418 ]
4419 input_api = MockInputApi()
4420 input_api.files = files_in_ash
4421 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4422 self.assertEqual(2, len(errors))
4423
4424 input_api.files = other_files
4425 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4426 self.assertEqual(0, len(errors))
4427
4428 def testDoesNotErrorOnNonGNFiles(self):
4429 input_api = MockInputApi()
4430 input_api.files = [
4431 MockFile('ash/test.h', ['assert(is_chromeos_ash)']),
4432 MockFile('chrome/browser/ash/test.cc',
4433 ['assert(is_chromeos_ash)']),
4434 ]
4435 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4436 self.assertEqual(0, len(errors))
4437
Giovanni Ortuño Urquidiab84da62021-12-10 00:53:214438 def testDeletedFile(self):
4439 input_api = MockInputApi()
4440 input_api.files = [
4441 MockFile('ash/BUILD.gn', []),
4442 MockFile('ash/foo/BUILD.gn', [], action='D'),
4443 ]
4444 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4445 self.assertEqual(1, len(errors))
4446
Henrique Ferreiro2a4b55942021-11-29 23:45:364447 def testDoesNotErrorWithAssertion(self):
4448 input_api = MockInputApi()
4449 input_api.files = [
4450 MockFile('ash/BUILD.gn', ['assert(is_chromeos_ash)']),
4451 MockFile('chrome/browser/ash/BUILD.gn',
4452 ['assert(is_chromeos_ash)']),
4453 MockFile('chrome/browser/ash/BUILD.gn',
4454 ['assert(is_chromeos_ash, "test")']),
4455 ]
4456 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4457 self.assertEqual(0, len(errors))
4458
4459
Lukasz Anforowicz7016d05e2021-11-30 03:56:274460class CheckRawPtrUsageTest(unittest.TestCase):
4461 def testAllowedCases(self):
4462 mock_input_api = MockInputApi()
4463 mock_input_api.files = [
4464 # Browser-side files are allowed.
4465 MockAffectedFile('test10/browser/foo.h', ['raw_ptr<int>']),
4466 MockAffectedFile('test11/browser/foo.cc', ['raw_ptr<int>']),
4467 MockAffectedFile('test12/blink/common/foo.cc', ['raw_ptr<int>']),
4468 MockAffectedFile('test13/blink/public/common/foo.cc', ['raw_ptr<int>']),
4469 MockAffectedFile('test14/blink/public/platform/foo.cc',
4470 ['raw_ptr<int>']),
4471
4472 # Non-C++ files are allowed.
4473 MockAffectedFile('test20/renderer/foo.md', ['raw_ptr<int>']),
4474
4475 # Mentions in a comment are allowed.
4476 MockAffectedFile('test30/renderer/foo.cc', ['//raw_ptr<int>']),
4477 ]
4478 mock_output_api = MockOutputApi()
4479 errors = PRESUBMIT.CheckRawPtrUsage(mock_input_api, mock_output_api)
4480 self.assertFalse(errors)
4481
4482 def testDisallowedCases(self):
4483 mock_input_api = MockInputApi()
4484 mock_input_api.files = [
4485 MockAffectedFile('test1/renderer/foo.h', ['raw_ptr<int>']),
4486 MockAffectedFile('test2/renderer/foo.cc', ['raw_ptr<int>']),
4487 MockAffectedFile('test3/blink/public/web/foo.cc', ['raw_ptr<int>']),
4488 ]
4489 mock_output_api = MockOutputApi()
4490 errors = PRESUBMIT.CheckRawPtrUsage(mock_input_api, mock_output_api)
4491 self.assertEqual(len(mock_input_api.files), len(errors))
4492 for error in errors:
4493 self.assertTrue(
4494 'raw_ptr<T> should not be used in Renderer-only code' in
4495 error.message)
4496
4497
Henrique Ferreirof9819f2e32021-11-30 13:31:564498class AssertPythonShebangTest(unittest.TestCase):
4499 def testError(self):
4500 input_api = MockInputApi()
4501 input_api.files = [
4502 MockFile('ash/test.py', ['#!/usr/bin/python']),
4503 MockFile('chrome/test.py', ['#!/usr/bin/python2']),
4504 MockFile('third_party/blink/test.py', ['#!/usr/bin/python3']),
Takuto Ikuta36976512021-11-30 23:15:274505 MockFile('empty.py', []),
Henrique Ferreirof9819f2e32021-11-30 13:31:564506 ]
4507 errors = PRESUBMIT.CheckPythonShebang(input_api, MockOutputApi())
4508 self.assertEqual(3, len(errors))
4509
4510 def testNonError(self):
4511 input_api = MockInputApi()
4512 input_api.files = [
4513 MockFile('chrome/browser/BUILD.gn', ['#!/usr/bin/python']),
4514 MockFile('third_party/blink/web_tests/external/test.py',
4515 ['#!/usr/bin/python2']),
4516 MockFile('third_party/test/test.py', ['#!/usr/bin/python3']),
4517 ]
4518 errors = PRESUBMIT.CheckPythonShebang(input_api, MockOutputApi())
4519 self.assertEqual(0, len(errors))
4520
Kalvin Lee4a3b79de2022-05-26 16:00:164521class VerifyDcheckParentheses(unittest.TestCase):
4522 def testPermissibleUsage(self):
4523 input_api = MockInputApi()
4524 input_api.files = [
4525 MockFile('okay1.cc', ['DCHECK_IS_ON()']),
4526 MockFile('okay2.cc', ['#if DCHECK_IS_ON()']),
4527
4528 # Other constructs that aren't exactly `DCHECK_IS_ON()` do their
4529 # own thing at their own risk.
4530 MockFile('okay3.cc', ['PA_DCHECK_IS_ON']),
4531 MockFile('okay4.cc', ['#if PA_DCHECK_IS_ON']),
4532 MockFile('okay6.cc', ['BUILDFLAG(PA_DCHECK_IS_ON)']),
4533 ]
4534 errors = PRESUBMIT.CheckDCHECK_IS_ONHasBraces(input_api, MockOutputApi())
4535 self.assertEqual(0, len(errors))
4536
4537 def testMissingParentheses(self):
4538 input_api = MockInputApi()
4539 input_api.files = [
4540 MockFile('bad1.cc', ['DCHECK_IS_ON']),
4541 MockFile('bad2.cc', ['#if DCHECK_IS_ON']),
4542 MockFile('bad3.cc', ['DCHECK_IS_ON && foo']),
4543 ]
4544 errors = PRESUBMIT.CheckDCHECK_IS_ONHasBraces(input_api, MockOutputApi())
4545 self.assertEqual(3, len(errors))
4546 for error in errors:
4547 self.assertRegex(error.message, r'DCHECK_IS_ON().+parentheses')
Henrique Ferreirof9819f2e32021-11-30 13:31:564548
[email protected]2299dcf2012-11-15 19:56:244549if __name__ == '__main__':
4550 unittest.main()