blob: ca9f27505ebef9e95d65e333f67cc21f75edf5ab [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):
2295 def _injectFakeOwnersClient(self, input_api, owners):
2296 class FakeOwnersClient(object):
2297 def ListOwners(self, f):
2298 return owners
2299
2300 input_api.owners_client = FakeOwnersClient()
2301
2302 def _injectFakeChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2303 def MockOwnerAndReviewers(input_api, email_regexp, approval_needed=False):
2304 return [owner, reviewers]
2305 input_api.canned_checks.GetCodereviewOwnerAndReviewers = \
2306 MockOwnerAndReviewers
2307
2308
2309class IpcSecurityOwnerTest(_SecurityOwnersTestCase):
2310 _test_cases = [
2311 ('*_messages.cc', 'scary_messages.cc'),
2312 ('*_messages*.h', 'scary_messages.h'),
2313 ('*_messages*.h', 'scary_messages_android.h'),
2314 ('*_param_traits*.*', 'scary_param_traits.h'),
2315 ('*_param_traits*.*', 'scary_param_traits_win.h'),
2316 ('*.mojom', 'scary.mojom'),
2317 ('*_mojom_traits*.*', 'scary_mojom_traits.h'),
2318 ('*_mojom_traits*.*', 'scary_mojom_traits_mac.h'),
2319 ('*_type_converter*.*', 'scary_type_converter.h'),
2320 ('*_type_converter*.*', 'scary_type_converter_nacl.h'),
2321 ('*.aidl', 'scary.aidl'),
2322 ]
2323
2324 # TODO(dcheng): add tests for when there are no missing per-file rules. These
2325 # are currently missing because `open()` is not injected.
Daniel Cheng3008dc12022-05-13 04:02:112326 def testMissingSecurityReviewerAtUpload(self):
2327 mock_input_api = MockInputApi()
2328 mock_input_api.files = [
2329 MockAffectedFile(f'services/goat/public/goat.mojom',
2330 ['// Scary contents.'])]
2331 self._injectFakeOwnersClient(
2332 mock_input_api,
2333 ['[email protected]', '[email protected]'])
2334 self._injectFakeChangeOwnerAndReviewers(
2335 mock_input_api, '[email protected]', ['[email protected]'])
2336 mock_input_api.is_committing = False
2337 mock_input_api.dry_run = False
2338 mock_output_api = MockOutputApi()
2339 results = PRESUBMIT.CheckSecurityOwners(
2340 mock_input_api, mock_output_api)
2341 # TODO(dcheng): This should be 1, but the PRESUBMIT currently opens the
2342 # OWNERS file in an unmockable way.
2343 self.assertEqual(2, len(results))
2344 self.assertEqual('warning', results[0].type)
2345 self.assertEqual(
2346 'Found missing security reviewers:', results[0].message)
2347
2348 def testMissingSecurityReviewerAtDryRunCommit(self):
2349 mock_input_api = MockInputApi()
2350 mock_input_api.files = [
2351 MockAffectedFile(f'services/goat/public/goat.mojom',
2352 ['// Scary contents.'])]
2353 self._injectFakeOwnersClient(
2354 mock_input_api,
2355 ['[email protected]', '[email protected]'])
2356 self._injectFakeChangeOwnerAndReviewers(
2357 mock_input_api, '[email protected]', ['[email protected]'])
2358 mock_input_api.is_committing = True
2359 mock_input_api.dry_run = True
2360 mock_output_api = MockOutputApi()
2361 results = PRESUBMIT.CheckSecurityOwners(
2362 mock_input_api, mock_output_api)
2363 # TODO(dcheng): This should be 1, but the PRESUBMIT currently opens the
2364 # OWNERS file in an unmockable way.
2365 self.assertEqual(2, len(results))
2366 self.assertEqual('error', results[0].type)
2367 self.assertEqual(
2368 'Found missing security reviewers:', results[0].message)
2369
2370 def testmissingSecurityApprovalAtRealCommit(self):
2371 mock_input_api = MockInputApi()
2372 mock_input_api.files = [
2373 MockAffectedFile(f'services/goat/public/goat.mojom',
2374 ['// Scary contents.'])]
2375 self._injectFakeOwnersClient(
2376 mock_input_api,
2377 ['[email protected]', '[email protected]'])
2378 self._injectFakeChangeOwnerAndReviewers(
2379 mock_input_api, '[email protected]', ['[email protected]'])
2380 mock_input_api.is_committing = True
2381 mock_input_api.dry_run = False
2382 mock_output_api = MockOutputApi()
2383 results = PRESUBMIT.CheckSecurityOwners(
2384 mock_input_api, mock_output_api)
2385 # TODO(dcheng): This should be 1, but the PRESUBMIT currently opens the
2386 # OWNERS file in an unmockable way.
2387 self.assertEqual(2, len(results))
2388 self.assertEqual('error', results[0].type)
2389 self.assertEqual(
2390 'Found missing security reviewers:', results[0].message)
Daniel Chenga37c03db2022-05-12 17:20:342391
2392 def testMissingPerFileRulesButNotSecurityReviewer(self):
2393 for pattern, filename in self._test_cases:
2394 with self.subTest(line=filename):
2395 mock_input_api = MockInputApi()
2396 mock_input_api.files = [
2397 MockAffectedFile(f'services/goat/public/{filename}',
2398 ['// Scary contents.'])]
2399 self._injectFakeOwnersClient(
2400 mock_input_api,
2401 ['[email protected]', '[email protected]'])
2402 self._injectFakeChangeOwnerAndReviewers(
2403 mock_input_api, '[email protected]', ['[email protected]'])
2404 mock_output_api = MockOutputApi()
2405 errors = PRESUBMIT.CheckSecurityOwners(
2406 mock_input_api, mock_output_api)
2407 self.assertEqual(1, len(errors))
2408 self.assertEqual(
2409 'Found OWNERS files with missing per-file rules for '
2410 'security-sensitive files.\nPlease update the OWNERS files below '
2411 'to add the missing rules:', errors[0].message)
2412 self.assertEqual(['[email protected]'],
2413 mock_output_api.more_cc)
2414
2415 def testIpcChangeNeedsSecurityOwner(self):
Daniel Cheng3008dc12022-05-13 04:02:112416 for is_committing in [True, False]:
2417 for pattern, filename in self._test_cases:
2418 with self.subTest(
2419 line=f'is_committing={is_committing}, filename={filename}'):
2420 mock_input_api = MockInputApi()
2421 mock_input_api.files = [
2422 MockAffectedFile(f'services/goat/public/{filename}',
2423 ['// Scary contents.'])]
2424 self._injectFakeOwnersClient(
2425 mock_input_api,
2426 ['[email protected]', '[email protected]'])
2427 self._injectFakeChangeOwnerAndReviewers(
2428 mock_input_api, '[email protected]', ['[email protected]'])
2429 mock_input_api.is_committing = is_committing
2430 mock_input_api.dry_run = False
2431 mock_output_api = MockOutputApi()
2432 results = PRESUBMIT.CheckSecurityOwners(
2433 mock_input_api, mock_output_api)
2434 self.assertEqual(2, len(results))
2435 if is_committing:
2436 self.assertEqual('error', results[0].type)
2437 else:
2438 self.assertEqual('warning', results[0].type)
2439 self.assertEqual(
2440 'Found missing security reviewers:', results[0].message)
2441 self.assertEqual('error', results[1].type)
2442 self.assertEqual(
2443 'Found OWNERS files with missing per-file rules for '
2444 'security-sensitive files.\nPlease update the OWNERS files below '
2445 'to add the missing rules:', results[1].message)
2446 self.assertEqual(['[email protected]'],
2447 mock_output_api.more_cc)
Daniel Chenga37c03db2022-05-12 17:20:342448
2449
Ken Rockot9f668262018-12-21 18:56:362450 def testServiceManifestChangeNeedsSecurityOwner(self):
2451 mock_input_api = MockInputApi()
2452 mock_input_api.files = [
2453 MockAffectedFile('services/goat/public/cpp/manifest.cc',
2454 [
2455 '#include "services/goat/public/cpp/manifest.h"',
2456 'const service_manager::Manifest& GetManifest() {}',
2457 ])]
Daniel Chenga37c03db2022-05-12 17:20:342458 self._injectFakeOwnersClient(mock_input_api,
2459 ['[email protected]', '[email protected]'])
2460 self._injectFakeChangeOwnerAndReviewers(
2461 mock_input_api, '[email protected]', ['[email protected]'])
Ken Rockot9f668262018-12-21 18:56:362462 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362463 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362464 mock_input_api, mock_output_api)
Daniel Chenga37c03db2022-05-12 17:20:342465 self.assertEqual(2, len(errors))
Ken Rockot9f668262018-12-21 18:56:362466 self.assertEqual(
Daniel Chenga37c03db2022-05-12 17:20:342467 'Found missing security reviewers:', errors[0].message)
2468 self.assertEqual(
2469 'Found OWNERS files with missing per-file rules for security-sensitive '
2470 'files.\nPlease update the OWNERS files below to '
2471 'add the missing rules:', errors[1].message)
2472 self.assertEqual(['[email protected]'], mock_output_api.more_cc)
Ken Rockot9f668262018-12-21 18:56:362473
2474 def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
2475 mock_input_api = MockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342476 self._injectFakeOwnersClient(mock_input_api,
2477 ['[email protected]', '[email protected]'])
2478 self._injectFakeChangeOwnerAndReviewers(
2479 mock_input_api, '[email protected]', ['[email protected]'])
Ken Rockot9f668262018-12-21 18:56:362480 mock_input_api.files = [
2481 MockAffectedFile('some/non/service/thing/foo_manifest.cc',
2482 [
2483 'const char kNoEnforcement[] = "not a manifest!";',
2484 ])]
2485 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362486 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032487 mock_input_api, mock_output_api)
2488 self.assertEqual([], errors)
Daniel Chenga37c03db2022-05-12 17:20:342489 self.assertEqual([], mock_output_api.more_cc)
Wez17c66962020-04-29 15:26:032490
2491
Daniel Chenga37c03db2022-05-12 17:20:342492class FuchsiaSecurityOwnerTest(_SecurityOwnersTestCase):
Wez17c66962020-04-29 15:26:032493 def testFidlChangeNeedsSecurityOwner(self):
2494 mock_input_api = MockInputApi()
2495 mock_input_api.files = [
2496 MockAffectedFile('potentially/scary/ipc.fidl',
2497 [
2498 'library test.fidl'
2499 ])]
Daniel Chenga37c03db2022-05-12 17:20:342500 self._injectFakeOwnersClient(mock_input_api,
2501 ['[email protected]', '[email protected]'])
2502 self._injectFakeChangeOwnerAndReviewers(
2503 mock_input_api, '[email protected]', ['[email protected]'])
Wez17c66962020-04-29 15:26:032504 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362505 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032506 mock_input_api, mock_output_api)
Daniel Chenga37c03db2022-05-12 17:20:342507 self.assertEqual(2, len(errors))
Wez17c66962020-04-29 15:26:032508 self.assertEqual(
Daniel Chenga37c03db2022-05-12 17:20:342509 'Found missing security reviewers:', errors[0].message)
2510 self.assertEqual(
2511 'Found OWNERS files with missing per-file rules for security-sensitive '
2512 'files.\nPlease update the OWNERS files below to '
2513 'add the missing rules:', errors[1].message)
Wez17c66962020-04-29 15:26:032514
2515 def testComponentManifestV1ChangeNeedsSecurityOwner(self):
2516 mock_input_api = MockInputApi()
2517 mock_input_api.files = [
2518 MockAffectedFile('potentially/scary/v2_manifest.cmx',
2519 [
2520 '{ "that is no": "manifest!" }'
2521 ])]
Daniel Chenga37c03db2022-05-12 17:20:342522 self._injectFakeOwnersClient(mock_input_api,
2523 ['[email protected]', '[email protected]'])
2524 self._injectFakeChangeOwnerAndReviewers(
2525 mock_input_api, '[email protected]', ['[email protected]'])
Wez17c66962020-04-29 15:26:032526 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362527 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032528 mock_input_api, mock_output_api)
Daniel Chenga37c03db2022-05-12 17:20:342529 self.assertEqual(2, len(errors))
Wez17c66962020-04-29 15:26:032530 self.assertEqual(
Daniel Chenga37c03db2022-05-12 17:20:342531 'Found missing security reviewers:', errors[0].message)
2532 self.assertEqual(
2533 'Found OWNERS files with missing per-file rules for security-sensitive '
2534 'files.\nPlease update the OWNERS files below to '
2535 'add the missing rules:', errors[1].message)
Wez17c66962020-04-29 15:26:032536
2537 def testComponentManifestV2NeedsSecurityOwner(self):
2538 mock_input_api = MockInputApi()
2539 mock_input_api.files = [
2540 MockAffectedFile('potentially/scary/v2_manifest.cml',
2541 [
2542 '{ "that is no": "manifest!" }'
2543 ])]
2544 mock_output_api = MockOutputApi()
Daniel Chenga37c03db2022-05-12 17:20:342545 self._injectFakeOwnersClient(mock_input_api,
2546 ['[email protected]', '[email protected]'])
2547 self._injectFakeChangeOwnerAndReviewers(
2548 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362549 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032550 mock_input_api, mock_output_api)
Daniel Chenga37c03db2022-05-12 17:20:342551 self.assertEqual(2, len(errors))
Wez17c66962020-04-29 15:26:032552 self.assertEqual(
Daniel Chenga37c03db2022-05-12 17:20:342553 'Found missing security reviewers:', errors[0].message)
2554 self.assertEqual(
2555 'Found OWNERS files with missing per-file rules for security-sensitive '
2556 'files.\nPlease update the OWNERS files below to '
2557 'add the missing rules:', errors[1].message)
Wez17c66962020-04-29 15:26:032558
Joshua Peraza1ca6d392020-12-08 00:14:092559 def testThirdPartyTestsDoNotRequireSecurityOwner(self):
2560 mock_input_api = MockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342561 self._injectFakeOwnersClient(mock_input_api,
2562 ['[email protected]', '[email protected]'])
2563 self._injectFakeChangeOwnerAndReviewers(
2564 mock_input_api, '[email protected]', ['[email protected]'])
Joshua Peraza1ca6d392020-12-08 00:14:092565 mock_input_api.files = [
2566 MockAffectedFile('third_party/crashpad/test/tests.cmx',
2567 [
2568 'const char kNoEnforcement[] = "Security?!? Pah!";',
2569 ])]
2570 mock_output_api = MockOutputApi()
2571 errors = PRESUBMIT.CheckSecurityOwners(
2572 mock_input_api, mock_output_api)
2573 self.assertEqual([], errors)
2574
Wez17c66962020-04-29 15:26:032575 def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2576 mock_input_api = MockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342577 self._injectFakeOwnersClient(mock_input_api,
2578 ['[email protected]', '[email protected]'])
2579 self._injectFakeChangeOwnerAndReviewers(
2580 mock_input_api, '[email protected]', ['[email protected]'])
Wez17c66962020-04-29 15:26:032581 mock_input_api.files = [
2582 MockAffectedFile('some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',
2583 [
2584 'const char kNoEnforcement[] = "Security?!? Pah!";',
2585 ])]
2586 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362587 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362588 mock_input_api, mock_output_api)
2589 self.assertEqual([], errors)
2590
Daniel Cheng13ca61a882017-08-25 15:11:252591
Daniel Chenga37c03db2022-05-12 17:20:342592class SecurityChangeTest(_SecurityOwnersTestCase):
Alex Goughbc964dd2020-06-15 17:52:372593 def testDiffGetServiceSandboxType(self):
Robert Sesek2c905332020-05-06 23:17:132594 mock_input_api = MockInputApi()
2595 mock_input_api.files = [
2596 MockAffectedFile(
2597 'services/goat/teleporter_host.cc',
2598 [
Alex Goughbc964dd2020-06-15 17:52:372599 'template <>',
2600 'inline content::SandboxType',
2601 'content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {',
2602 '#if defined(OS_WIN)',
2603 ' return SandboxType::kGoaty;',
2604 '#else',
2605 ' return SandboxType::kNoSandbox;',
2606 '#endif // !defined(OS_WIN)',
2607 '}'
Robert Sesek2c905332020-05-06 23:17:132608 ]
2609 ),
2610 ]
2611 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2612 mock_input_api)
2613 self.assertEqual({
2614 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372615 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132616 ])},
2617 files_to_functions)
2618
2619 def testDiffRemovingLine(self):
2620 mock_input_api = MockInputApi()
2621 mock_file = MockAffectedFile('services/goat/teleporter_host.cc', '')
2622 mock_file._scm_diff = """--- old 2020-05-04 14:08:25.000000000 -0400
2623+++ new 2020-05-04 14:08:32.000000000 -0400
2624@@ -1,5 +1,4 @@
Alex Goughbc964dd2020-06-15 17:52:372625 template <>
2626 inline content::SandboxType
2627-content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {
2628 #if defined(OS_WIN)
2629 return SandboxType::kGoaty;
Robert Sesek2c905332020-05-06 23:17:132630"""
2631 mock_input_api.files = [mock_file]
2632 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2633 mock_input_api)
2634 self.assertEqual({
2635 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372636 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132637 ])},
2638 files_to_functions)
2639
2640 def testChangeOwnersMissing(self):
2641 mock_input_api = MockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342642 self._injectFakeOwnersClient(mock_input_api,
2643 ['[email protected]', '[email protected]'])
2644 self._injectFakeChangeOwnerAndReviewers(
2645 mock_input_api, '[email protected]', ['[email protected]'])
Robert Sesek2c905332020-05-06 23:17:132646 mock_input_api.is_committing = False
2647 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372648 MockAffectedFile('file.cc', ['GetServiceSandboxType<Goat>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132649 ]
2650 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362651 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592652 self.assertEqual(1, len(result))
2653 self.assertEqual(result[0].type, 'notify')
2654 self.assertEqual(result[0].message,
Daniel Chenga37c03db2022-05-12 17:20:342655 'The following files change calls to security-sensitive functions\n' \
Robert Sesek2c905332020-05-06 23:17:132656 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2657 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372658 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132659
2660 def testChangeOwnersMissingAtCommit(self):
2661 mock_input_api = MockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342662 self._injectFakeOwnersClient(mock_input_api,
2663 ['[email protected]', '[email protected]'])
2664 self._injectFakeChangeOwnerAndReviewers(
2665 mock_input_api, '[email protected]', ['[email protected]'])
Robert Sesek2c905332020-05-06 23:17:132666 mock_input_api.is_committing = True
Daniel Cheng3008dc12022-05-13 04:02:112667 mock_input_api.dry_run = False
Robert Sesek2c905332020-05-06 23:17:132668 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372669 MockAffectedFile('file.cc', ['GetServiceSandboxType<mojom::Goat>()'])
Robert Sesek2c905332020-05-06 23:17:132670 ]
2671 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362672 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592673 self.assertEqual(1, len(result))
2674 self.assertEqual(result[0].type, 'error')
2675 self.assertEqual(result[0].message,
Daniel Chenga37c03db2022-05-12 17:20:342676 'The following files change calls to security-sensitive functions\n' \
Robert Sesek2c905332020-05-06 23:17:132677 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2678 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372679 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132680
2681 def testChangeOwnersPresent(self):
2682 mock_input_api = MockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342683 self._injectFakeOwnersClient(mock_input_api,
2684 ['[email protected]', '[email protected]'])
2685 self._injectFakeChangeOwnerAndReviewers(
2686 mock_input_api, '[email protected]',
2687 ['[email protected]', '[email protected]'])
Robert Sesek2c905332020-05-06 23:17:132688 mock_input_api.files = [
2689 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2690 ]
2691 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362692 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592693 self.assertEqual(0, len(result))
Robert Sesek2c905332020-05-06 23:17:132694
2695 def testChangeOwnerIsSecurityOwner(self):
2696 mock_input_api = MockInputApi()
Daniel Chenga37c03db2022-05-12 17:20:342697 self._injectFakeOwnersClient(mock_input_api,
2698 ['[email protected]', '[email protected]'])
2699 self._injectFakeChangeOwnerAndReviewers(
2700 mock_input_api, '[email protected]', ['[email protected]'])
Robert Sesek2c905332020-05-06 23:17:132701 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372702 MockAffectedFile('file.cc', ['GetServiceSandboxType<T>(Sandbox)'])
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))
Robert Sesek2c905332020-05-06 23:17:132707
2708
Mario Sanchez Prada2472cab2019-09-18 10:58:312709class BannedTypeCheckTest(unittest.TestCase):
Sylvain Defresnea8b73d252018-02-28 15:45:542710
Peter Kasting94a56c42019-10-25 21:54:042711 def testBannedCppFunctions(self):
2712 input_api = MockInputApi()
2713 input_api.files = [
2714 MockFile('some/cpp/problematic/file.cc',
2715 ['using namespace std;']),
Oksana Zhuravlovac8222d22019-12-19 19:21:162716 MockFile('third_party/blink/problematic/file.cc',
2717 ['GetInterfaceProvider()']),
Peter Kasting94a56c42019-10-25 21:54:042718 MockFile('some/cpp/ok/file.cc',
2719 ['using std::string;']),
Allen Bauer53b43fb12020-03-12 17:21:472720 MockFile('some/cpp/problematic/file2.cc',
2721 ['set_owned_by_client()']),
danakjd18e8892020-12-17 17:42:012722 MockFile('some/cpp/nocheck/file.cc',
2723 ['using namespace std; // nocheck']),
2724 MockFile('some/cpp/comment/file.cc',
2725 [' // A comment about `using namespace std;`']),
Peter Kasting94a56c42019-10-25 21:54:042726 ]
2727
Saagar Sanghavifceeaae2020-08-12 16:40:362728 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlovac8222d22019-12-19 19:21:162729
2730 # warnings are results[0], errors are results[1]
2731 self.assertEqual(2, len(results))
2732 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2733 self.assertTrue(
2734 'third_party/blink/problematic/file.cc' in results[0].message)
2735 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
Allen Bauer53b43fb12020-03-12 17:21:472736 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
danakjd18e8892020-12-17 17:42:012737 self.assertFalse('some/cpp/nocheck/file.cc' in results[0].message)
2738 self.assertFalse('some/cpp/nocheck/file.cc' in results[1].message)
2739 self.assertFalse('some/cpp/comment/file.cc' in results[0].message)
2740 self.assertFalse('some/cpp/comment/file.cc' in results[1].message)
Peter Kasting94a56c42019-10-25 21:54:042741
Peter K. Lee6c03ccff2019-07-15 14:40:052742 def testBannedIosObjcFunctions(self):
Sylvain Defresnea8b73d252018-02-28 15:45:542743 input_api = MockInputApi()
2744 input_api.files = [
2745 MockFile('some/ios/file.mm',
2746 ['TEST(SomeClassTest, SomeInteraction) {',
2747 '}']),
2748 MockFile('some/mac/file.mm',
2749 ['TEST(SomeClassTest, SomeInteraction) {',
2750 '}']),
2751 MockFile('another/ios_file.mm',
2752 ['class SomeTest : public testing::Test {};']),
Peter K. Lee6c03ccff2019-07-15 14:40:052753 MockFile('some/ios/file_egtest.mm',
2754 ['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
2755 MockFile('some/ios/file_unittest.mm',
2756 ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']),
Sylvain Defresnea8b73d252018-02-28 15:45:542757 ]
2758
Saagar Sanghavifceeaae2020-08-12 16:40:362759 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Sylvain Defresnea8b73d252018-02-28 15:45:542760 self.assertEqual(1, len(errors))
2761 self.assertTrue('some/ios/file.mm' in errors[0].message)
2762 self.assertTrue('another/ios_file.mm' in errors[0].message)
2763 self.assertTrue('some/mac/file.mm' not in errors[0].message)
Peter K. Lee6c03ccff2019-07-15 14:40:052764 self.assertTrue('some/ios/file_egtest.mm' in errors[0].message)
2765 self.assertTrue('some/ios/file_unittest.mm' not in errors[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542766
Carlos Knippschildab192b8c2019-04-08 20:02:382767 def testBannedMojoFunctions(self):
2768 input_api = MockInputApi()
2769 input_api.files = [
Oksana Zhuravlovafd247772019-05-16 16:57:292770 MockFile('some/cpp/problematic/file2.cc',
2771 ['mojo::ConvertTo<>']),
Oksana Zhuravlovafd247772019-05-16 16:57:292772 MockFile('third_party/blink/ok/file3.cc',
2773 ['mojo::ConvertTo<>']),
2774 MockFile('content/renderer/ok/file3.cc',
2775 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382776 ]
2777
Saagar Sanghavifceeaae2020-08-12 16:40:362778 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222779
2780 # warnings are results[0], errors are results[1]
Robert Sesek351d2d52021-02-02 01:47:072781 self.assertEqual(1, len(results))
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222782 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222783 self.assertTrue('third_party/blink/ok/file3.cc' not in results[0].message)
2784 self.assertTrue('content/renderer/ok/file3.cc' not in results[0].message)
Carlos Knippschildab192b8c2019-04-08 20:02:382785
Daniel Cheng92c15e32022-03-16 17:48:222786 def testBannedMojomPatterns(self):
2787 input_api = MockInputApi()
2788 input_api.files = [
2789 MockFile('bad.mojom',
2790 ['struct Bad {',
2791 ' handle<shared_buffer> buffer;',
2792 '};']),
2793 MockFile('good.mojom',
2794 ['struct Good {',
2795 ' mojo_base.mojom.ReadOnlySharedMemoryRegion region1;',
2796 ' mojo_base.mojom.WritableSharedMemoryRegion region2;',
2797 ' mojo_base.mojom.UnsafeSharedMemoryRegion region3;',
2798 '};']),
2799 ]
2800
2801 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
2802
2803 # warnings are results[0], errors are results[1]
2804 self.assertEqual(1, len(results))
2805 self.assertTrue('bad.mojom' in results[0].message)
2806 self.assertTrue('good.mojom' not in results[0].message)
2807
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272808class NoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:242809 def testTruePositives(self):
2810 mock_input_api = MockInputApi()
2811 mock_input_api.files = [
2812 MockFile('some/path/foo.cc', ['foo_for_testing();']),
2813 MockFile('some/path/foo.mm', ['FooForTesting();']),
2814 MockFile('some/path/foo.cxx', ['FooForTests();']),
2815 MockFile('some/path/foo.cpp', ['foo_for_test();']),
2816 ]
2817
Saagar Sanghavifceeaae2020-08-12 16:40:362818 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242819 mock_input_api, MockOutputApi())
2820 self.assertEqual(1, len(results))
2821 self.assertEqual(4, len(results[0].items))
2822 self.assertTrue('foo.cc' in results[0].items[0])
2823 self.assertTrue('foo.mm' in results[0].items[1])
2824 self.assertTrue('foo.cxx' in results[0].items[2])
2825 self.assertTrue('foo.cpp' in results[0].items[3])
2826
2827 def testFalsePositives(self):
2828 mock_input_api = MockInputApi()
2829 mock_input_api.files = [
2830 MockFile('some/path/foo.h', ['foo_for_testing();']),
2831 MockFile('some/path/foo.mm', ['FooForTesting() {']),
2832 MockFile('some/path/foo.cc', ['::FooForTests();']),
2833 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
2834 ]
2835
Saagar Sanghavifceeaae2020-08-12 16:40:362836 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242837 mock_input_api, MockOutputApi())
2838 self.assertEqual(0, len(results))
2839
James Cook1b4dc132021-03-09 22:45:132840 def testAllowedFiles(self):
2841 mock_input_api = MockInputApi()
2842 mock_input_api.files = [
2843 MockFile('path/foo_unittest.cc', ['foo_for_testing();']),
2844 MockFile('path/bar_unittest_mac.cc', ['foo_for_testing();']),
2845 MockFile('path/baz_unittests.cc', ['foo_for_testing();']),
2846 ]
2847
2848 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
2849 mock_input_api, MockOutputApi())
2850 self.assertEqual(0, len(results))
2851
Vaclav Brozekf01ed502018-03-16 19:38:242852
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272853class NoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:232854 def testTruePositives(self):
2855 mock_input_api = MockInputApi()
2856 mock_input_api.files = [
2857 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
2858 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392859 MockFile('dir/java/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232860 MockFile('dir/java/src/mult.java', [
2861 'int x = SomethingLongHere()',
2862 ' * SomethingLongHereForTesting();'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392863 ])
Vaclav Brozek7dbc28c2018-03-27 08:35:232864 ]
2865
Saagar Sanghavifceeaae2020-08-12 16:40:362866 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232867 mock_input_api, MockOutputApi())
2868 self.assertEqual(1, len(results))
2869 self.assertEqual(4, len(results[0].items))
2870 self.assertTrue('foo.java' in results[0].items[0])
2871 self.assertTrue('bar.java' in results[0].items[1])
2872 self.assertTrue('baz.java' in results[0].items[2])
2873 self.assertTrue('mult.java' in results[0].items[3])
2874
2875 def testFalsePositives(self):
2876 mock_input_api = MockInputApi()
2877 mock_input_api.files = [
2878 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
2879 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
2880 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
2881 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
Sky Malice9e6d6032020-10-15 22:49:552882 MockFile('dir/java/src/bar3.java', ['@VisibleForTesting']),
2883 MockFile('dir/java/src/bar4.java', ['@VisibleForTesting()']),
2884 MockFile('dir/java/src/bar5.java', [
2885 '@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)'
2886 ]),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392887 MockFile('dir/javatests/src/baz.java', ['FooForTest(', 'y', ');']),
2888 MockFile('dir/junit/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232889 MockFile('dir/junit/src/javadoc.java', [
2890 '/** Use FooForTest(); to obtain foo in tests.'
2891 ' */'
2892 ]),
2893 MockFile('dir/junit/src/javadoc2.java', [
2894 '/** ',
2895 ' * Use FooForTest(); to obtain foo in tests.'
2896 ' */'
2897 ]),
2898 ]
2899
Saagar Sanghavifceeaae2020-08-12 16:40:362900 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232901 mock_input_api, MockOutputApi())
2902 self.assertEqual(0, len(results))
2903
2904
Mohamed Heikald048240a2019-11-12 16:57:372905class NewImagesWarningTest(unittest.TestCase):
2906 def testTruePositives(self):
2907 mock_input_api = MockInputApi()
2908 mock_input_api.files = [
2909 MockFile('dir/android/res/drawable/foo.png', []),
2910 MockFile('dir/android/res/drawable-v21/bar.svg', []),
2911 MockFile('dir/android/res/mipmap-v21-en/baz.webp', []),
2912 MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png', []),
2913 ]
2914
2915 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2916 self.assertEqual(1, len(results))
2917 self.assertEqual(4, len(results[0].items))
2918 self.assertTrue('foo.png' in results[0].items[0].LocalPath())
2919 self.assertTrue('bar.svg' in results[0].items[1].LocalPath())
2920 self.assertTrue('baz.webp' in results[0].items[2].LocalPath())
2921 self.assertTrue('foobar.png' in results[0].items[3].LocalPath())
2922
2923 def testFalsePositives(self):
2924 mock_input_api = MockInputApi()
2925 mock_input_api.files = [
2926 MockFile('dir/pngs/README.md', []),
2927 MockFile('java/test/res/drawable/foo.png', []),
2928 MockFile('third_party/blink/foo.png', []),
2929 MockFile('dir/third_party/libpng/src/foo.cc', ['foobar']),
2930 MockFile('dir/resources.webp/.gitignore', ['foo.png']),
2931 ]
2932
2933 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2934 self.assertEqual(0, len(results))
2935
2936
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272937class CheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:052938 def testTruePositivesNullptr(self):
2939 mock_input_api = MockInputApi()
2940 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162941 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
2942 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
Vaclav Brozek851d9602018-04-04 16:13:052943 ]
2944
Saagar Sanghavifceeaae2020-08-12 16:40:362945 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052946 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162947 self.assertTrue('nullptr' in results[0].message)
Vaclav Brozek851d9602018-04-04 16:13:052948 self.assertEqual(2, len(results[0].items))
2949 self.assertTrue('baz.cc' in results[0].items[0])
2950 self.assertTrue('baz-p.cc' in results[0].items[1])
2951
2952 def testTruePositivesConstructor(self):
Vaclav Brozek52e18bf2018-04-03 07:05:242953 mock_input_api = MockInputApi()
2954 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162955 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
2956 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
2957 MockFile('dir/mult.cc', [
Vaclav Brozek95face62018-04-04 14:15:112958 'return',
2959 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
2960 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162961 MockFile('dir/mult2.cc', [
Vaclav Brozek95face62018-04-04 14:15:112962 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
2963 ' std::unique_ptr<T>(foo);'
2964 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162965 MockFile('dir/mult3.cc', [
Vaclav Brozek95face62018-04-04 14:15:112966 'bar = std::unique_ptr<T>(',
2967 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
2968 ]),
Vaclav Brozekb7fadb692018-08-30 06:39:532969 MockFile('dir/multi_arg.cc', [
2970 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']),
Vaclav Brozek52e18bf2018-04-03 07:05:242971 ]
2972
Saagar Sanghavifceeaae2020-08-12 16:40:362973 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052974 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162975 self.assertTrue('std::make_unique' in results[0].message)
Vaclav Brozekb7fadb692018-08-30 06:39:532976 self.assertEqual(6, len(results[0].items))
Vaclav Brozek851d9602018-04-04 16:13:052977 self.assertTrue('foo.cc' in results[0].items[0])
2978 self.assertTrue('bar.mm' in results[0].items[1])
2979 self.assertTrue('mult.cc' in results[0].items[2])
2980 self.assertTrue('mult2.cc' in results[0].items[3])
2981 self.assertTrue('mult3.cc' in results[0].items[4])
Vaclav Brozekb7fadb692018-08-30 06:39:532982 self.assertTrue('multi_arg.cc' in results[0].items[5])
Vaclav Brozek52e18bf2018-04-03 07:05:242983
2984 def testFalsePositives(self):
2985 mock_input_api = MockInputApi()
2986 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162987 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
2988 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
2989 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
2990 MockFile('dir/baz.cc', [
Vaclav Brozek52e18bf2018-04-03 07:05:242991 'std::unique_ptr<T> result = std::make_unique<T>();'
2992 ]),
Vaclav Brozeka54c528b2018-04-06 19:23:552993 MockFile('dir/baz2.cc', [
2994 'std::unique_ptr<T> result = std::make_unique<T>('
2995 ]),
2996 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
2997 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
Vaclav Brozekb7fadb692018-08-30 06:39:532998
2999 # Two-argument invocation of std::unique_ptr is exempt because there is
3000 # no equivalent using std::make_unique.
3001 MockFile('dir/multi_arg.cc', [
3002 'auto p = std::unique_ptr<T, D>(new T(), D());']),
Vaclav Brozek52e18bf2018-04-03 07:05:243003 ]
3004
Saagar Sanghavifceeaae2020-08-12 16:40:363005 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek52e18bf2018-04-03 07:05:243006 self.assertEqual(0, len(results))
3007
Danil Chapovalov3518f362018-08-11 16:13:433008class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
3009 def testBlocksDirectIncludes(self):
3010 mock_input_api = MockInputApi()
3011 mock_input_api.files = [
3012 MockFile('dir/foo_win.cc', ['#include "shlwapi.h"']),
3013 MockFile('dir/bar.h', ['#include <propvarutil.h>']),
3014 MockFile('dir/baz.h', ['#include <atlbase.h>']),
3015 MockFile('dir/jumbo.h', ['#include "sphelper.h"']),
3016 ]
3017 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:593018 self.assertEqual(1, len(results))
3019 self.assertEqual(4, len(results[0].items))
Danil Chapovalov3518f362018-08-11 16:13:433020 self.assertTrue('StrCat' in results[0].message)
3021 self.assertTrue('foo_win.cc' in results[0].items[0])
3022 self.assertTrue('bar.h' in results[0].items[1])
3023 self.assertTrue('baz.h' in results[0].items[2])
3024 self.assertTrue('jumbo.h' in results[0].items[3])
3025
3026 def testAllowsToIncludeWrapper(self):
3027 mock_input_api = MockInputApi()
3028 mock_input_api.files = [
3029 MockFile('dir/baz_win.cc', ['#include "base/win/shlwapi.h"']),
3030 MockFile('dir/baz-win.h', ['#include "base/win/atl.h"']),
3031 ]
3032 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:593033 self.assertEqual(0, len(results))
Danil Chapovalov3518f362018-08-11 16:13:433034
3035 def testAllowsToCreateWrapper(self):
3036 mock_input_api = MockInputApi()
3037 mock_input_api.files = [
3038 MockFile('base/win/shlwapi.h', [
3039 '#include <shlwapi.h>',
3040 '#include "base/win/windows_defines.inc"']),
3041 ]
3042 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:593043 self.assertEqual(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:243044
Mustafa Emre Acer51f2f742020-03-09 19:41:123045
Rainhard Findlingfc31844c52020-05-15 09:58:263046class StringTest(unittest.TestCase):
3047 """Tests ICU syntax check and translation screenshots check."""
3048
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143049 # An empty grd file.
3050 OLD_GRD_CONTENTS = """<?xml version="1.0" encoding="UTF-8"?>
3051 <grit latest_public_release="1" current_release="1">
3052 <release seq="1">
3053 <messages></messages>
3054 </release>
3055 </grit>
3056 """.splitlines()
3057 # A grd file with a single message.
3058 NEW_GRD_CONTENTS1 = """<?xml version="1.0" encoding="UTF-8"?>
3059 <grit latest_public_release="1" current_release="1">
3060 <release seq="1">
3061 <messages>
3062 <message name="IDS_TEST1">
3063 Test string 1
3064 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:483065 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE1"
3066 translateable="false">
3067 Non translateable message 1, should be ignored
3068 </message>
Mustafa Emre Acered1a48962020-06-30 19:15:393069 <message name="IDS_TEST_STRING_ACCESSIBILITY"
Mustafa Emre Acerd3ca8be2020-07-07 22:35:343070 is_accessibility_with_no_ui="true">
Mustafa Emre Acered1a48962020-06-30 19:15:393071 Accessibility label 1, should be ignored
3072 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143073 </messages>
3074 </release>
3075 </grit>
3076 """.splitlines()
3077 # A grd file with two messages.
3078 NEW_GRD_CONTENTS2 = """<?xml version="1.0" encoding="UTF-8"?>
3079 <grit latest_public_release="1" current_release="1">
3080 <release seq="1">
3081 <messages>
3082 <message name="IDS_TEST1">
3083 Test string 1
3084 </message>
3085 <message name="IDS_TEST2">
3086 Test string 2
3087 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:483088 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE2"
3089 translateable="false">
3090 Non translateable message 2, should be ignored
3091 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143092 </messages>
3093 </release>
3094 </grit>
3095 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:263096 # A grd file with one ICU syntax message without syntax errors.
3097 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1 = """<?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 {NUM, plural,
3103 =1 {Test text for numeric one}
3104 other {Test text for plural with {NUM} as number}}
3105 </message>
3106 </messages>
3107 </release>
3108 </grit>
3109 """.splitlines()
3110 # A grd file with one ICU syntax message without syntax errors.
3111 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2 = """<?xml version="1.0" encoding="UTF-8"?>
3112 <grit latest_public_release="1" current_release="1">
3113 <release seq="1">
3114 <messages>
3115 <message name="IDS_TEST1">
3116 {NUM, plural,
3117 =1 {Different test text for numeric one}
3118 other {Different test text for plural with {NUM} as number}}
3119 </message>
3120 </messages>
3121 </release>
3122 </grit>
3123 """.splitlines()
3124 # A grd file with one ICU syntax message with syntax errors (misses a comma).
3125 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
3126 <grit latest_public_release="1" current_release="1">
3127 <release seq="1">
3128 <messages>
3129 <message name="IDS_TEST1">
3130 {NUM, plural
3131 =1 {Test text for numeric one}
3132 other {Test text for plural with {NUM} as number}}
3133 </message>
3134 </messages>
3135 </release>
3136 </grit>
3137 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143138
meacerff8a9b62019-12-10 19:43:583139 OLD_GRDP_CONTENTS = (
3140 '<?xml version="1.0" encoding="utf-8"?>',
3141 '<grit-part>',
3142 '</grit-part>'
3143 )
3144
3145 NEW_GRDP_CONTENTS1 = (
3146 '<?xml version="1.0" encoding="utf-8"?>',
3147 '<grit-part>',
3148 '<message name="IDS_PART_TEST1">',
3149 'Part string 1',
3150 '</message>',
3151 '</grit-part>')
3152
3153 NEW_GRDP_CONTENTS2 = (
3154 '<?xml version="1.0" encoding="utf-8"?>',
3155 '<grit-part>',
3156 '<message name="IDS_PART_TEST1">',
3157 'Part string 1',
3158 '</message>',
3159 '<message name="IDS_PART_TEST2">',
3160 'Part string 2',
3161 '</message>',
3162 '</grit-part>')
3163
Rainhard Findlingd8d04372020-08-13 13:30:093164 NEW_GRDP_CONTENTS3 = (
3165 '<?xml version="1.0" encoding="utf-8"?>',
3166 '<grit-part>',
3167 '<message name="IDS_PART_TEST1" desc="Description with typo.">',
3168 'Part string 1',
3169 '</message>',
3170 '</grit-part>')
3171
3172 NEW_GRDP_CONTENTS4 = (
3173 '<?xml version="1.0" encoding="utf-8"?>',
3174 '<grit-part>',
3175 '<message name="IDS_PART_TEST1" desc="Description with typo fixed.">',
3176 'Part string 1',
3177 '</message>',
3178 '</grit-part>')
3179
Rainhard Findling1a3e71e2020-09-21 07:33:353180 NEW_GRDP_CONTENTS5 = (
3181 '<?xml version="1.0" encoding="utf-8"?>',
3182 '<grit-part>',
3183 '<message name="IDS_PART_TEST1" meaning="Meaning with typo.">',
3184 'Part string 1',
3185 '</message>',
3186 '</grit-part>')
3187
3188 NEW_GRDP_CONTENTS6 = (
3189 '<?xml version="1.0" encoding="utf-8"?>',
3190 '<grit-part>',
3191 '<message name="IDS_PART_TEST1" meaning="Meaning with typo fixed.">',
3192 'Part string 1',
3193 '</message>',
3194 '</grit-part>')
3195
Rainhard Findlingfc31844c52020-05-15 09:58:263196 # A grdp file with one ICU syntax message without syntax errors.
3197 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = (
3198 '<?xml version="1.0" encoding="utf-8"?>',
3199 '<grit-part>',
3200 '<message name="IDS_PART_TEST1">',
3201 '{NUM, plural,',
3202 '=1 {Test text for numeric one}',
3203 'other {Test text for plural with {NUM} as number}}',
3204 '</message>',
3205 '</grit-part>')
3206 # A grdp file with one ICU syntax message without syntax errors.
3207 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2 = (
3208 '<?xml version="1.0" encoding="utf-8"?>',
3209 '<grit-part>',
3210 '<message name="IDS_PART_TEST1">',
3211 '{NUM, plural,',
3212 '=1 {Different test text for numeric one}',
3213 'other {Different test text for plural with {NUM} as number}}',
3214 '</message>',
3215 '</grit-part>')
3216
3217 # A grdp file with one ICU syntax message with syntax errors (superfluent
3218 # whitespace).
3219 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR = (
3220 '<?xml version="1.0" encoding="utf-8"?>',
3221 '<grit-part>',
3222 '<message name="IDS_PART_TEST1">',
3223 '{NUM, plural,',
3224 '= 1 {Test text for numeric one}',
3225 'other {Test text for plural with {NUM} as number}}',
3226 '</message>',
3227 '</grit-part>')
3228
Mustafa Emre Acerc8a012d2018-07-31 00:00:393229 DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
3230 'changelist. Run '
3231 'tools/translate/upload_screenshots.py to '
3232 'upload them instead:')
3233 GENERATE_SIGNATURES_MESSAGE = ('You are adding or modifying UI strings.\n'
3234 'To ensure the best translations, take '
3235 'screenshots of the relevant UI '
3236 '(https://g.co/chrome/translation) and add '
3237 'these files to your changelist:')
3238 REMOVE_SIGNATURES_MESSAGE = ('You removed strings associated with these '
3239 'files. Remove:')
Rainhard Findlingfc31844c52020-05-15 09:58:263240 ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
3241 'strings (problems or feedback? Contact '
3242 '[email protected]):')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143243
3244 def makeInputApi(self, files):
3245 input_api = MockInputApi()
3246 input_api.files = files
meacere7be7532019-10-02 17:41:033247 # Override os_path.exists because the presubmit uses the actual
3248 # os.path.exists.
3249 input_api.CreateMockFileInPath(
3250 [x.LocalPath() for x in input_api.AffectedFiles(include_deletes=True)])
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143251 return input_api
3252
meacerff8a9b62019-12-10 19:43:583253 """ CL modified and added messages, but didn't add any screenshots."""
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143254 def testNoScreenshots(self):
meacerff8a9b62019-12-10 19:43:583255 # No new strings (file contents same). Should not warn.
3256 input_api = self.makeInputApi([
3257 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
3258 self.NEW_GRD_CONTENTS1, action='M'),
3259 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1,
3260 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363261 warnings = PRESUBMIT.CheckStrings(input_api,
meacerff8a9b62019-12-10 19:43:583262 MockOutputApi())
3263 self.assertEqual(0, len(warnings))
3264
3265 # Add two new strings. Should have two warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143266 input_api = self.makeInputApi([
3267 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:583268 self.NEW_GRD_CONTENTS1, action='M'),
3269 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
3270 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363271 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143272 MockOutputApi())
3273 self.assertEqual(1, len(warnings))
3274 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003275 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013276 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583277 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3278 os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
3279 warnings[0].items)
Mustafa Emre Acer36eaad52019-11-12 23:03:343280
meacerff8a9b62019-12-10 19:43:583281 # Add four new strings. Should have four warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213282 input_api = self.makeInputApi([
3283 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:583284 self.OLD_GRD_CONTENTS, action='M'),
3285 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
3286 self.OLD_GRDP_CONTENTS, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363287 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213288 MockOutputApi())
3289 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003290 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213291 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583292 self.assertEqual([
3293 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3294 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3295 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3296 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3297 ], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213298
Rainhard Findlingd8d04372020-08-13 13:30:093299 def testModifiedMessageDescription(self):
3300 # CL modified a message description for a message that does not yet have a
Rainhard Findling1a3e71e2020-09-21 07:33:353301 # screenshot. Should not warn.
Rainhard Findlingd8d04372020-08-13 13:30:093302 input_api = self.makeInputApi([
3303 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
3304 self.NEW_GRDP_CONTENTS4, action='M')])
3305 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findling1a3e71e2020-09-21 07:33:353306 self.assertEqual(0, len(warnings))
Rainhard Findlingd8d04372020-08-13 13:30:093307
3308 # CL modified a message description for a message that already has a
3309 # screenshot. Should not warn.
3310 input_api = self.makeInputApi([
3311 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
3312 self.NEW_GRDP_CONTENTS4, action='M'),
3313 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3314 'binary', action='A')])
3315 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3316 self.assertEqual(0, len(warnings))
3317
Rainhard Findling1a3e71e2020-09-21 07:33:353318 def testModifiedMessageMeaning(self):
3319 # CL modified a message meaning for a message that does not yet have a
3320 # screenshot. Should warn.
3321 input_api = self.makeInputApi([
3322 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3323 self.NEW_GRDP_CONTENTS6, action='M')])
3324 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3325 self.assertEqual(1, len(warnings))
3326
3327 # CL modified a message meaning for a message that already has a
3328 # screenshot. Should not warn.
3329 input_api = self.makeInputApi([
3330 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3331 self.NEW_GRDP_CONTENTS6, action='M'),
3332 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3333 'binary', action='A')])
3334 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3335 self.assertEqual(0, len(warnings))
3336
meacerff8a9b62019-12-10 19:43:583337 def testPngAddedSha1NotAdded(self):
3338 # CL added one new message in a grd file and added the png file associated
3339 # with it, but did not add the corresponding sha1 file. This should warn
3340 # twice:
3341 # - Once for the added png file (because we don't want developers to upload
3342 # actual images)
3343 # - Once for the missing .sha1 file
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143344 input_api = self.makeInputApi([
Mustafa Emre Acerea3e57a2018-12-17 23:51:013345 MockAffectedFile(
3346 'test.grd',
3347 self.NEW_GRD_CONTENTS1,
3348 self.OLD_GRD_CONTENTS,
3349 action='M'),
3350 MockAffectedFile(
3351 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
3352 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363353 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143354 MockOutputApi())
3355 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003356 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143357 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013358 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
3359 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003360 self.assertEqual('error', warnings[1].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143361 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013362 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3363 warnings[1].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143364
meacerff8a9b62019-12-10 19:43:583365 # CL added two messages (one in grd, one in grdp) and added the png files
3366 # associated with the messages, but did not add the corresponding sha1
3367 # files. This should warn twice:
3368 # - Once for the added png files (because we don't want developers to upload
3369 # actual images)
3370 # - Once for the missing .sha1 files
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143371 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583372 # Modified files:
Mustafa Emre Acer36eaad52019-11-12 23:03:343373 MockAffectedFile(
3374 'test.grd',
meacerff8a9b62019-12-10 19:43:583375 self.NEW_GRD_CONTENTS1,
Mustafa Emre Acer36eaad52019-11-12 23:03:343376 self.OLD_GRD_CONTENTS,
meacer2308d0742019-11-12 18:15:423377 action='M'),
Mustafa Emre Acer12e7fee2019-11-18 18:49:553378 MockAffectedFile(
meacerff8a9b62019-12-10 19:43:583379 'part.grdp',
3380 self.NEW_GRDP_CONTENTS1,
3381 self.OLD_GRDP_CONTENTS,
3382 action='M'),
3383 # Added files:
3384 MockAffectedFile(
3385 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A'),
3386 MockAffectedFile(
3387 os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary',
3388 action='A')
Mustafa Emre Acerad8fb082019-11-19 04:24:213389 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363390 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213391 MockOutputApi())
3392 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003393 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213394 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583395 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png'),
3396 os.path.join('test_grd', 'IDS_TEST1.png')],
Mustafa Emre Acerad8fb082019-11-19 04:24:213397 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003398 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213399 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
meacerff8a9b62019-12-10 19:43:583400 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3401 os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3402 warnings[1].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213403
3404 def testScreenshotsWithSha1(self):
meacerff8a9b62019-12-10 19:43:583405 # CL added four messages (two each in a grd and grdp) and their
3406 # corresponding .sha1 files. No warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213407 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583408 # Modified files:
Mustafa Emre Acerad8fb082019-11-19 04:24:213409 MockAffectedFile(
3410 'test.grd',
3411 self.NEW_GRD_CONTENTS2,
3412 self.OLD_GRD_CONTENTS,
Mustafa Emre Acer12e7fee2019-11-18 18:49:553413 action='M'),
meacerff8a9b62019-12-10 19:43:583414 MockAffectedFile(
3415 'part.grdp',
3416 self.NEW_GRDP_CONTENTS2,
3417 self.OLD_GRDP_CONTENTS,
3418 action='M'),
3419 # Added files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013420 MockFile(
3421 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3422 'binary',
3423 action='A'),
3424 MockFile(
3425 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3426 'binary',
meacerff8a9b62019-12-10 19:43:583427 action='A'),
3428 MockFile(
3429 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3430 'binary',
3431 action='A'),
3432 MockFile(
3433 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3434 'binary',
3435 action='A'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013436 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363437 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143438 MockOutputApi())
3439 self.assertEqual([], warnings)
3440
3441 def testScreenshotsRemovedWithSha1(self):
meacerff8a9b62019-12-10 19:43:583442 # Replace new contents with old contents in grd and grp files, removing
3443 # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3444 # Should warn to remove the sha1 files associated with these strings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143445 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583446 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013447 MockAffectedFile(
3448 'test.grd',
meacerff8a9b62019-12-10 19:43:583449 self.OLD_GRD_CONTENTS, # new_contents
3450 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013451 action='M'),
meacerff8a9b62019-12-10 19:43:583452 MockAffectedFile(
3453 'part.grdp',
3454 self.OLD_GRDP_CONTENTS, # new_contents
3455 self.NEW_GRDP_CONTENTS2, # old_contents
3456 action='M'),
3457 # Unmodified files:
3458 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
3459 MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', ''),
3460 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3461 'binary', ''),
3462 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3463 'binary', '')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013464 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363465 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143466 MockOutputApi())
3467 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003468 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143469 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013470 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583471 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3472 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013473 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3474 os.path.join('test_grd', 'IDS_TEST2.png.sha1')
3475 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143476
meacerff8a9b62019-12-10 19:43:583477 # Same as above, but this time one of the .sha1 files is also removed.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143478 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583479 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013480 MockAffectedFile(
3481 'test.grd',
meacerff8a9b62019-12-10 19:43:583482 self.OLD_GRD_CONTENTS, # new_contents
3483 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013484 action='M'),
meacerff8a9b62019-12-10 19:43:583485 MockAffectedFile(
3486 'part.grdp',
3487 self.OLD_GRDP_CONTENTS, # new_contents
3488 self.NEW_GRDP_CONTENTS2, # old_contents
3489 action='M'),
3490 # Unmodified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013491 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
meacerff8a9b62019-12-10 19:43:583492 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3493 'binary', ''),
3494 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013495 MockAffectedFile(
3496 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3497 '',
3498 'old_contents',
meacerff8a9b62019-12-10 19:43:583499 action='D'),
3500 MockAffectedFile(
3501 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3502 '',
3503 'old_contents',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013504 action='D')
3505 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363506 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143507 MockOutputApi())
3508 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003509 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143510 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583511 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3512 os.path.join('test_grd', 'IDS_TEST1.png.sha1')
3513 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143514
meacerff8a9b62019-12-10 19:43:583515 # Remove all sha1 files. There should be no warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143516 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583517 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013518 MockAffectedFile(
3519 'test.grd',
3520 self.OLD_GRD_CONTENTS,
3521 self.NEW_GRD_CONTENTS2,
3522 action='M'),
meacerff8a9b62019-12-10 19:43:583523 MockAffectedFile(
3524 'part.grdp',
3525 self.OLD_GRDP_CONTENTS,
3526 self.NEW_GRDP_CONTENTS2,
3527 action='M'),
3528 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013529 MockFile(
3530 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3531 'binary',
3532 action='D'),
3533 MockFile(
3534 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3535 'binary',
meacerff8a9b62019-12-10 19:43:583536 action='D'),
3537 MockFile(
3538 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3539 'binary',
3540 action='D'),
3541 MockFile(
3542 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3543 'binary',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013544 action='D')
3545 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363546 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143547 MockOutputApi())
3548 self.assertEqual([], warnings)
3549
Rainhard Findlingfc31844c52020-05-15 09:58:263550 def testIcuSyntax(self):
3551 # Add valid ICU syntax string. Should not raise an error.
3552 input_api = self.makeInputApi([
3553 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3554 self.NEW_GRD_CONTENTS1, action='M'),
3555 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3556 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363557 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263558 # We expect no ICU syntax errors.
3559 icu_errors = [e for e in results
3560 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3561 self.assertEqual(0, len(icu_errors))
3562
3563 # Valid changes in ICU syntax. Should not raise an error.
3564 input_api = self.makeInputApi([
3565 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3566 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3567 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3568 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363569 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263570 # We expect no ICU syntax errors.
3571 icu_errors = [e for e in results
3572 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3573 self.assertEqual(0, len(icu_errors))
3574
3575 # Add invalid ICU syntax strings. Should raise two errors.
3576 input_api = self.makeInputApi([
3577 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3578 self.NEW_GRD_CONTENTS1, action='M'),
3579 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3580 self.NEW_GRD_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363581 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263582 # We expect 2 ICU syntax errors.
3583 icu_errors = [e for e in results
3584 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3585 self.assertEqual(1, len(icu_errors))
3586 self.assertEqual([
3587 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3588 'ICU syntax.',
3589 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3590 ], icu_errors[0].items)
3591
3592 # Change two strings to have ICU syntax errors. Should raise two errors.
3593 input_api = self.makeInputApi([
3594 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3595 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3596 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3597 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363598 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263599 # We expect 2 ICU syntax errors.
3600 icu_errors = [e for e in results
3601 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3602 self.assertEqual(1, len(icu_errors))
3603 self.assertEqual([
3604 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3605 'ICU syntax.',
3606 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3607 ], icu_errors[0].items)
3608
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143609
Mustafa Emre Acer51f2f742020-03-09 19:41:123610class TranslationExpectationsTest(unittest.TestCase):
3611 ERROR_MESSAGE_FORMAT = (
3612 "Failed to get a list of translatable grd files. "
3613 "This happens when:\n"
3614 " - One of the modified grd or grdp files cannot be parsed or\n"
3615 " - %s is not updated.\n"
3616 "Stack:\n"
3617 )
3618 REPO_ROOT = os.path.join('tools', 'translation', 'testdata')
3619 # This lists all .grd files under REPO_ROOT.
3620 EXPECTATIONS = os.path.join(REPO_ROOT,
3621 "translation_expectations.pyl")
3622 # This lists all .grd files under REPO_ROOT except unlisted.grd.
3623 EXPECTATIONS_WITHOUT_UNLISTED_FILE = os.path.join(
3624 REPO_ROOT, "translation_expectations_without_unlisted_file.pyl")
3625
3626 # Tests that the presubmit doesn't return when no grd or grdp files are
3627 # modified.
3628 def testExpectationsNoModifiedGrd(self):
3629 input_api = MockInputApi()
3630 input_api.files = [
3631 MockAffectedFile('not_used.txt', 'not used', 'not used', action='M')
3632 ]
3633 # Fake list of all grd files in the repo. This list is missing all grd/grdps
3634 # under tools/translation/testdata. This is OK because the presubmit won't
3635 # run in the first place since there are no modified grd/grps in input_api.
3636 grd_files = ['doesnt_exist_doesnt_matter.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363637 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123638 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3639 grd_files)
3640 self.assertEqual(0, len(warnings))
3641
3642
3643 # Tests that the list of files passed to the presubmit matches the list of
3644 # files in the expectations.
3645 def testExpectationsSuccess(self):
3646 # Mock input file list needs a grd or grdp file in order to run the
3647 # presubmit. The file itself doesn't matter.
3648 input_api = MockInputApi()
3649 input_api.files = [
3650 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3651 ]
3652 # List of all grd files in the repo.
3653 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3654 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363655 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123656 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3657 grd_files)
3658 self.assertEqual(0, len(warnings))
3659
3660 # Tests that the presubmit warns when a file is listed in expectations, but
3661 # does not actually exist.
3662 def testExpectationsMissingFile(self):
3663 # Mock input file list needs a grd or grdp file in order to run the
3664 # presubmit.
3665 input_api = MockInputApi()
3666 input_api.files = [
3667 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3668 ]
3669 # unlisted.grd is listed under tools/translation/testdata but is not
3670 # included in translation expectations.
3671 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363672 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123673 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3674 grd_files)
3675 self.assertEqual(1, len(warnings))
3676 self.assertTrue(warnings[0].message.startswith(
3677 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS))
3678 self.assertTrue(
3679 ("test.grd is listed in the translation expectations, "
3680 "but this grd file does not exist")
3681 in warnings[0].message)
3682
3683 # Tests that the presubmit warns when a file is not listed in expectations but
3684 # does actually exist.
3685 def testExpectationsUnlistedFile(self):
3686 # Mock input file list needs a grd or grdp file in order to run the
3687 # presubmit.
3688 input_api = MockInputApi()
3689 input_api.files = [
3690 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3691 ]
3692 # unlisted.grd is listed under tools/translation/testdata but is not
3693 # included in translation expectations.
3694 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3695 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363696 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123697 input_api, MockOutputApi(), self.REPO_ROOT,
3698 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3699 self.assertEqual(1, len(warnings))
3700 self.assertTrue(warnings[0].message.startswith(
3701 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3702 self.assertTrue(
3703 ("unlisted.grd appears to be translatable "
3704 "(because it contains <file> or <message> elements), "
3705 "but is not listed in the translation expectations.")
3706 in warnings[0].message)
3707
3708 # Tests that the presubmit warns twice:
3709 # - for a non-existing file listed in expectations
3710 # - for an existing file not listed in expectations
3711 def testMultipleWarnings(self):
3712 # Mock input file list needs a grd or grdp file in order to run the
3713 # presubmit.
3714 input_api = MockInputApi()
3715 input_api.files = [
3716 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3717 ]
3718 # unlisted.grd is listed under tools/translation/testdata but is not
3719 # included in translation expectations.
3720 # test.grd is not listed under tools/translation/testdata but is included
3721 # in translation expectations.
3722 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363723 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123724 input_api, MockOutputApi(), self.REPO_ROOT,
3725 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3726 self.assertEqual(1, len(warnings))
3727 self.assertTrue(warnings[0].message.startswith(
3728 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3729 self.assertTrue(
3730 ("unlisted.grd appears to be translatable "
3731 "(because it contains <file> or <message> elements), "
3732 "but is not listed in the translation expectations.")
3733 in warnings[0].message)
3734 self.assertTrue(
3735 ("test.grd is listed in the translation expectations, "
3736 "but this grd file does not exist")
3737 in warnings[0].message)
3738
3739
Dominic Battre033531052018-09-24 15:45:343740class DISABLETypoInTest(unittest.TestCase):
3741
3742 def testPositive(self):
3743 # Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
3744 # where the desire is to disable a test.
3745 tests = [
3746 # Disabled on one platform:
3747 '#if defined(OS_WIN)\n'
3748 '#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
3749 '#else\n'
3750 '#define MAYBE_FoobarTest FoobarTest\n'
3751 '#endif\n',
3752 # Disabled on one platform spread cross lines:
3753 '#if defined(OS_WIN)\n'
3754 '#define MAYBE_FoobarTest \\\n'
3755 ' DISABLE_FoobarTest\n'
3756 '#else\n'
3757 '#define MAYBE_FoobarTest FoobarTest\n'
3758 '#endif\n',
3759 # Disabled on all platforms:
3760 ' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
3761 # Disabled on all platforms but multiple lines
3762 ' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
3763 ]
3764
3765 for test in tests:
3766 mock_input_api = MockInputApi()
3767 mock_input_api.files = [
3768 MockFile('some/path/foo_unittest.cc', test.splitlines()),
3769 ]
3770
Saagar Sanghavifceeaae2020-08-12 16:40:363771 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343772 MockOutputApi())
3773 self.assertEqual(
3774 1,
3775 len(results),
3776 msg=('expected len(results) == 1 but got %d in test: %s' %
3777 (len(results), test)))
3778 self.assertTrue(
3779 'foo_unittest.cc' in results[0].message,
3780 msg=('expected foo_unittest.cc in message but got %s in test %s' %
3781 (results[0].message, test)))
3782
3783 def testIngoreNotTestFiles(self):
3784 mock_input_api = MockInputApi()
3785 mock_input_api.files = [
3786 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'),
3787 ]
3788
Saagar Sanghavifceeaae2020-08-12 16:40:363789 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343790 MockOutputApi())
3791 self.assertEqual(0, len(results))
3792
Katie Df13948e2018-09-25 07:33:443793 def testIngoreDeletedFiles(self):
3794 mock_input_api = MockInputApi()
3795 mock_input_api.files = [
3796 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'),
3797 ]
3798
Saagar Sanghavifceeaae2020-08-12 16:40:363799 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Katie Df13948e2018-09-25 07:33:443800 MockOutputApi())
3801 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:343802
Nina Satragnof7660532021-09-20 18:03:353803class ForgettingMAYBEInTests(unittest.TestCase):
3804 def testPositive(self):
3805 test = (
3806 '#if defined(HAS_ENERGY)\n'
3807 '#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
3808 '#else\n'
3809 '#define MAYBE_CastExplosion CastExplosion\n'
3810 '#endif\n'
3811 'TEST_F(ArchWizard, CastExplosion) {\n'
3812 '#if defined(ARCH_PRIEST_IN_PARTY)\n'
3813 '#define MAYBE_ArchPriest ArchPriest\n'
3814 '#else\n'
3815 '#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
3816 '#endif\n'
3817 'TEST_F(ArchPriest, CastNaturesBounty) {\n'
3818 '#if !defined(CRUSADER_IN_PARTY)\n'
3819 '#define MAYBE_Crusader \\\n'
3820 ' DISABLED_Crusader \n'
3821 '#else\n'
3822 '#define MAYBE_Crusader \\\n'
3823 ' Crusader\n'
3824 '#endif\n'
3825 ' TEST_F(\n'
3826 ' Crusader,\n'
3827 ' CastTaunt) { }\n'
3828 '#if defined(LEARNED_BASIC_SKILLS)\n'
3829 '#define MAYBE_CastSteal \\\n'
3830 ' DISABLED_CastSteal \n'
3831 '#else\n'
3832 '#define MAYBE_CastSteal \\\n'
3833 ' CastSteal\n'
3834 '#endif\n'
3835 ' TEST_F(\n'
3836 ' ThiefClass,\n'
3837 ' CastSteal) { }\n'
3838 )
3839 mock_input_api = MockInputApi()
3840 mock_input_api.files = [
3841 MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
3842 ]
3843 results = PRESUBMIT.CheckForgettingMAYBEInTests(mock_input_api,
3844 MockOutputApi())
3845 self.assertEqual(4, len(results))
3846 self.assertTrue('CastExplosion' in results[0].message)
3847 self.assertTrue('fantasyworld/classes_unittest.cc:2' in results[0].message)
3848 self.assertTrue('ArchPriest' in results[1].message)
3849 self.assertTrue('fantasyworld/classes_unittest.cc:8' in results[1].message)
3850 self.assertTrue('Crusader' in results[2].message)
3851 self.assertTrue('fantasyworld/classes_unittest.cc:14' in results[2].message)
3852 self.assertTrue('CastSteal' in results[3].message)
3853 self.assertTrue('fantasyworld/classes_unittest.cc:24' in results[3].message)
3854
3855 def testNegative(self):
3856 test = (
3857 '#if defined(HAS_ENERGY)\n'
3858 '#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
3859 '#else\n'
3860 '#define MAYBE_CastExplosion CastExplosion\n'
3861 '#endif\n'
3862 'TEST_F(ArchWizard, MAYBE_CastExplosion) {\n'
3863 '#if defined(ARCH_PRIEST_IN_PARTY)\n'
3864 '#define MAYBE_ArchPriest ArchPriest\n'
3865 '#else\n'
3866 '#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
3867 '#endif\n'
3868 'TEST_F(MAYBE_ArchPriest, CastNaturesBounty) {\n'
3869 '#if !defined(CRUSADER_IN_PARTY)\n'
3870 '#define MAYBE_Crusader \\\n'
3871 ' DISABLED_Crusader \n'
3872 '#else\n'
3873 '#define MAYBE_Crusader \\\n'
3874 ' Crusader\n'
3875 '#endif\n'
3876 ' TEST_F(\n'
3877 ' MAYBE_Crusader,\n'
3878 ' CastTaunt) { }\n'
3879 '#if defined(LEARNED_BASIC_SKILLS)\n'
3880 '#define MAYBE_CastSteal \\\n'
3881 ' DISABLED_CastSteal \n'
3882 '#else\n'
3883 '#define MAYBE_CastSteal \\\n'
3884 ' CastSteal\n'
3885 '#endif\n'
3886 ' TEST_F(\n'
3887 ' ThiefClass,\n'
3888 ' MAYBE_CastSteal) { }\n'
3889 )
3890
3891 mock_input_api = MockInputApi()
3892 mock_input_api.files = [
3893 MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
3894 ]
3895 results = PRESUBMIT.CheckForgettingMAYBEInTests(mock_input_api,
3896 MockOutputApi())
3897 self.assertEqual(0, len(results))
Dirk Pranke3c18a382019-03-15 01:07:513898
Max Morozb47503b2019-08-08 21:03:273899class CheckFuzzTargetsTest(unittest.TestCase):
3900
3901 def _check(self, files):
3902 mock_input_api = MockInputApi()
3903 mock_input_api.files = []
3904 for fname, contents in files.items():
3905 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363906 return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api, MockOutputApi())
Max Morozb47503b2019-08-08 21:03:273907
3908 def testLibFuzzerSourcesIgnored(self):
3909 results = self._check({
3910 "third_party/lib/Fuzzer/FuzzerDriver.cpp": "LLVMFuzzerInitialize",
3911 })
3912 self.assertEqual(results, [])
3913
3914 def testNonCodeFilesIgnored(self):
3915 results = self._check({
3916 "README.md": "LLVMFuzzerInitialize",
3917 })
3918 self.assertEqual(results, [])
3919
3920 def testNoErrorHeaderPresent(self):
3921 results = self._check({
3922 "fuzzer.cc": (
3923 "#include \"testing/libfuzzer/libfuzzer_exports.h\"\n" +
3924 "LLVMFuzzerInitialize"
3925 )
3926 })
3927 self.assertEqual(results, [])
3928
3929 def testErrorMissingHeader(self):
3930 results = self._check({
3931 "fuzzer.cc": "LLVMFuzzerInitialize"
3932 })
3933 self.assertEqual(len(results), 1)
3934 self.assertEqual(results[0].items, ['fuzzer.cc'])
3935
3936
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263937class SetNoParentTest(unittest.TestCase):
John Abd-El-Malekdfd1edc2021-02-24 22:22:403938 def testSetNoParentTopLevelAllowed(self):
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263939 mock_input_api = MockInputApi()
3940 mock_input_api.files = [
3941 MockAffectedFile('goat/OWNERS',
3942 [
3943 'set noparent',
3944 '[email protected]',
John Abd-El-Malekdfd1edc2021-02-24 22:22:403945 ])
3946 ]
3947 mock_output_api = MockOutputApi()
3948 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
3949 self.assertEqual([], errors)
3950
3951 def testSetNoParentMissing(self):
3952 mock_input_api = MockInputApi()
3953 mock_input_api.files = [
3954 MockAffectedFile('services/goat/OWNERS',
3955 [
3956 'set noparent',
3957 '[email protected]',
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263958 'per-file *.json=set noparent',
3959 'per-file *[email protected]',
3960 ])
3961 ]
3962 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363963 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263964 self.assertEqual(1, len(errors))
3965 self.assertTrue('goat/OWNERS:1' in errors[0].long_text)
3966 self.assertTrue('goat/OWNERS:3' in errors[0].long_text)
3967
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263968 def testSetNoParentWithCorrectRule(self):
3969 mock_input_api = MockInputApi()
3970 mock_input_api.files = [
John Abd-El-Malekdfd1edc2021-02-24 22:22:403971 MockAffectedFile('services/goat/OWNERS',
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263972 [
3973 'set noparent',
3974 'file://ipc/SECURITY_OWNERS',
3975 'per-file *.json=set noparent',
3976 'per-file *.json=file://ipc/SECURITY_OWNERS',
3977 ])
3978 ]
3979 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363980 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263981 self.assertEqual([], errors)
3982
3983
Ken Rockotc31f4832020-05-29 18:58:513984class MojomStabilityCheckTest(unittest.TestCase):
3985 def runTestWithAffectedFiles(self, affected_files):
3986 mock_input_api = MockInputApi()
3987 mock_input_api.files = affected_files
3988 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363989 return PRESUBMIT.CheckStableMojomChanges(
Ken Rockotc31f4832020-05-29 18:58:513990 mock_input_api, mock_output_api)
3991
3992 def testSafeChangePasses(self):
3993 errors = self.runTestWithAffectedFiles([
3994 MockAffectedFile('foo/foo.mojom',
3995 ['[Stable] struct S { [MinVersion=1] int32 x; };'],
3996 old_contents=['[Stable] struct S {};'])
3997 ])
3998 self.assertEqual([], errors)
3999
4000 def testBadChangeFails(self):
4001 errors = self.runTestWithAffectedFiles([
4002 MockAffectedFile('foo/foo.mojom',
4003 ['[Stable] struct S { int32 x; };'],
4004 old_contents=['[Stable] struct S {};'])
4005 ])
4006 self.assertEqual(1, len(errors))
4007 self.assertTrue('not backward-compatible' in errors[0].message)
4008
Ken Rockotad7901f942020-06-04 20:17:094009 def testDeletedFile(self):
4010 """Regression test for https://crbug.com/1091407."""
4011 errors = self.runTestWithAffectedFiles([
4012 MockAffectedFile('a.mojom', [], old_contents=['struct S {};'],
4013 action='D'),
4014 MockAffectedFile('b.mojom',
4015 ['struct S {}; struct T { S s; };'],
4016 old_contents=['import "a.mojom"; struct T { S s; };'])
4017 ])
4018 self.assertEqual([], errors)
4019
Jose Magana2b456f22021-03-09 23:26:404020class CheckForUseOfChromeAppsDeprecationsTest(unittest.TestCase):
4021
4022 ERROR_MSG_PIECE = 'technologies which will soon be deprecated'
4023
4024 # Each positive test is also a naive negative test for the other cases.
4025
4026 def testWarningNMF(self):
4027 mock_input_api = MockInputApi()
4028 mock_input_api.files = [
4029 MockAffectedFile(
4030 'foo.NMF',
4031 ['"program"', '"Z":"content"', 'B'],
4032 ['"program"', 'B'],
4033 scm_diff='\n'.join([
4034 '--- foo.NMF.old 2020-12-02 20:40:54.430676385 +0100',
4035 '+++ foo.NMF.new 2020-12-02 20:41:02.086700197 +0100',
4036 '@@ -1,2 +1,3 @@',
4037 ' "program"',
4038 '+"Z":"content"',
4039 ' B']),
4040 action='M')
4041 ]
4042 mock_output_api = MockOutputApi()
4043 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
4044 mock_output_api)
4045 self.assertEqual(1, len(errors))
4046 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
4047 self.assertTrue( 'foo.NMF' in errors[0].message)
4048
4049 def testWarningManifest(self):
4050 mock_input_api = MockInputApi()
4051 mock_input_api.files = [
4052 MockAffectedFile(
4053 'manifest.json',
4054 ['"app":', '"Z":"content"', 'B'],
4055 ['"app":"', 'B'],
4056 scm_diff='\n'.join([
4057 '--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
4058 '+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
4059 '@@ -1,2 +1,3 @@',
4060 ' "app"',
4061 '+"Z":"content"',
4062 ' B']),
4063 action='M')
4064 ]
4065 mock_output_api = MockOutputApi()
4066 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
4067 mock_output_api)
4068 self.assertEqual(1, len(errors))
4069 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
4070 self.assertTrue( 'manifest.json' in errors[0].message)
4071
4072 def testOKWarningManifestWithoutApp(self):
4073 mock_input_api = MockInputApi()
4074 mock_input_api.files = [
4075 MockAffectedFile(
4076 'manifest.json',
4077 ['"name":', '"Z":"content"', 'B'],
4078 ['"name":"', 'B'],
4079 scm_diff='\n'.join([
4080 '--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
4081 '+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
4082 '@@ -1,2 +1,3 @@',
4083 ' "app"',
4084 '+"Z":"content"',
4085 ' B']),
4086 action='M')
4087 ]
4088 mock_output_api = MockOutputApi()
4089 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
4090 mock_output_api)
4091 self.assertEqual(0, len(errors))
4092
4093 def testWarningPPAPI(self):
4094 mock_input_api = MockInputApi()
4095 mock_input_api.files = [
4096 MockAffectedFile(
4097 'foo.hpp',
4098 ['A', '#include <ppapi.h>', 'B'],
4099 ['A', 'B'],
4100 scm_diff='\n'.join([
4101 '--- foo.hpp.old 2020-12-02 20:40:54.430676385 +0100',
4102 '+++ foo.hpp.new 2020-12-02 20:41:02.086700197 +0100',
4103 '@@ -1,2 +1,3 @@',
4104 ' A',
4105 '+#include <ppapi.h>',
4106 ' B']),
4107 action='M')
4108 ]
4109 mock_output_api = MockOutputApi()
4110 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
4111 mock_output_api)
4112 self.assertEqual(1, len(errors))
4113 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
4114 self.assertTrue( 'foo.hpp' in errors[0].message)
4115
4116 def testNoWarningPPAPI(self):
4117 mock_input_api = MockInputApi()
4118 mock_input_api.files = [
4119 MockAffectedFile(
4120 'foo.txt',
4121 ['A', 'Peppapig', 'B'],
4122 ['A', 'B'],
4123 scm_diff='\n'.join([
4124 '--- foo.txt.old 2020-12-02 20:40:54.430676385 +0100',
4125 '+++ foo.txt.new 2020-12-02 20:41:02.086700197 +0100',
4126 '@@ -1,2 +1,3 @@',
4127 ' A',
4128 '+Peppapig',
4129 ' B']),
4130 action='M')
4131 ]
4132 mock_output_api = MockOutputApi()
4133 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
4134 mock_output_api)
4135 self.assertEqual(0, len(errors))
4136
Dominic Battre645d42342020-12-04 16:14:104137class CheckDeprecationOfPreferencesTest(unittest.TestCase):
4138 # Test that a warning is generated if a preference registration is removed
4139 # from a random file.
4140 def testWarning(self):
4141 mock_input_api = MockInputApi()
4142 mock_input_api.files = [
4143 MockAffectedFile(
4144 'foo.cc',
4145 ['A', 'B'],
4146 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
4147 scm_diff='\n'.join([
4148 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
4149 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
4150 '@@ -1,3 +1,2 @@',
4151 ' A',
4152 '-prefs->RegisterStringPref("foo", "default");',
4153 ' B']),
4154 action='M')
4155 ]
4156 mock_output_api = MockOutputApi()
4157 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
4158 mock_output_api)
4159 self.assertEqual(1, len(errors))
4160 self.assertTrue(
4161 'Discovered possible removal of preference registrations' in
4162 errors[0].message)
4163
4164 # Test that a warning is inhibited if the preference registration was moved
4165 # to the deprecation functions in browser prefs.
4166 def testNoWarningForMigration(self):
4167 mock_input_api = MockInputApi()
4168 mock_input_api.files = [
4169 # RegisterStringPref was removed from foo.cc.
4170 MockAffectedFile(
4171 'foo.cc',
4172 ['A', 'B'],
4173 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
4174 scm_diff='\n'.join([
4175 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
4176 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
4177 '@@ -1,3 +1,2 @@',
4178 ' A',
4179 '-prefs->RegisterStringPref("foo", "default");',
4180 ' B']),
4181 action='M'),
4182 # But the preference was properly migrated.
4183 MockAffectedFile(
4184 'chrome/browser/prefs/browser_prefs.cc',
4185 [
4186 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4187 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4188 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4189 'prefs->RegisterStringPref("foo", "default");',
4190 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4191 ],
4192 [
4193 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4194 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4195 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4196 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4197 ],
4198 scm_diff='\n'.join([
4199 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
4200 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
4201 '@@ -2,3 +2,4 @@',
4202 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4203 ' // BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4204 '+prefs->RegisterStringPref("foo", "default");',
4205 ' // END_MIGRATE_OBSOLETE_PROFILE_PREFS']),
4206 action='M'),
4207 ]
4208 mock_output_api = MockOutputApi()
4209 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
4210 mock_output_api)
4211 self.assertEqual(0, len(errors))
4212
4213 # Test that a warning is NOT inhibited if the preference registration was
4214 # moved to a place outside of the migration functions in browser_prefs.cc
4215 def testWarningForImproperMigration(self):
4216 mock_input_api = MockInputApi()
4217 mock_input_api.files = [
4218 # RegisterStringPref was removed from foo.cc.
4219 MockAffectedFile(
4220 'foo.cc',
4221 ['A', 'B'],
4222 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
4223 scm_diff='\n'.join([
4224 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
4225 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
4226 '@@ -1,3 +1,2 @@',
4227 ' A',
4228 '-prefs->RegisterStringPref("foo", "default");',
4229 ' B']),
4230 action='M'),
4231 # The registration call was moved to a place in browser_prefs.cc that
4232 # is outside the migration functions.
4233 MockAffectedFile(
4234 'chrome/browser/prefs/browser_prefs.cc',
4235 [
4236 'prefs->RegisterStringPref("foo", "default");',
4237 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4238 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4239 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4240 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4241 ],
4242 [
4243 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4244 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4245 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4246 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4247 ],
4248 scm_diff='\n'.join([
4249 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
4250 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
4251 '@@ -1,2 +1,3 @@',
4252 '+prefs->RegisterStringPref("foo", "default");',
4253 ' // BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4254 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS']),
4255 action='M'),
4256 ]
4257 mock_output_api = MockOutputApi()
4258 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
4259 mock_output_api)
4260 self.assertEqual(1, len(errors))
4261 self.assertTrue(
4262 'Discovered possible removal of preference registrations' in
4263 errors[0].message)
4264
4265 # Check that the presubmit fails if a marker line in brower_prefs.cc is
4266 # deleted.
4267 def testDeletedMarkerRaisesError(self):
4268 mock_input_api = MockInputApi()
4269 mock_input_api.files = [
4270 MockAffectedFile('chrome/browser/prefs/browser_prefs.cc',
4271 [
4272 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4273 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4274 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4275 # The following line is deleted for this test
4276 # '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4277 ])
4278 ]
4279 mock_output_api = MockOutputApi()
4280 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
4281 mock_output_api)
4282 self.assertEqual(1, len(errors))
4283 self.assertEqual(
4284 'Broken .*MIGRATE_OBSOLETE_.*_PREFS markers in browser_prefs.cc.',
4285 errors[0].message)
4286
Kevin McNee967dd2d22021-11-15 16:09:294287class MPArchApiUsage(unittest.TestCase):
Kevin McNee4eeec792022-02-14 20:02:044288 def _assert_notify(
4289 self, expected_uses, msg, local_path, new_contents):
Kevin McNee967dd2d22021-11-15 16:09:294290 mock_input_api = MockInputApi()
4291 mock_output_api = MockOutputApi()
4292 mock_input_api.files = [
4293 MockFile(local_path, new_contents),
4294 ]
Kevin McNee4eeec792022-02-14 20:02:044295 result = PRESUBMIT.CheckMPArchApiUsage(mock_input_api, mock_output_api)
Kevin McNee967dd2d22021-11-15 16:09:294296 self.assertEqual(
Kevin McNee4eeec792022-02-14 20:02:044297 bool(expected_uses),
Kevin McNee967dd2d22021-11-15 16:09:294298 '[email protected]' in mock_output_api.more_cc,
4299 msg)
Kevin McNee4eeec792022-02-14 20:02:044300 if expected_uses:
4301 self.assertEqual(1, len(result), msg)
4302 self.assertEqual(result[0].type, 'notify', msg)
4303 self.assertEqual(sorted(result[0].items), sorted(expected_uses), msg)
Kevin McNee967dd2d22021-11-15 16:09:294304
4305 def testNotify(self):
4306 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044307 ['WebContentsObserver', 'WebContentsUserData'],
Kevin McNee967dd2d22021-11-15 16:09:294308 'Introduce WCO and WCUD',
4309 'chrome/my_feature.h',
4310 ['class MyFeature',
4311 ' : public content::WebContentsObserver,',
4312 ' public content::WebContentsUserData<MyFeature> {};',
4313 ])
4314 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044315 ['DidFinishNavigation'],
Kevin McNee967dd2d22021-11-15 16:09:294316 'Introduce WCO override',
4317 'chrome/my_feature.h',
4318 ['void DidFinishNavigation(',
4319 ' content::NavigationHandle* navigation_handle) override;',
4320 ])
4321 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044322 ['IsInMainFrame'],
Kevin McNee967dd2d22021-11-15 16:09:294323 'Introduce IsInMainFrame',
4324 'chrome/my_feature.cc',
4325 ['void DoSomething(content::NavigationHandle* navigation_handle) {',
4326 ' if (navigation_handle->IsInMainFrame())',
4327 ' all_of_our_page_state.reset();',
4328 '}',
4329 ])
4330 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044331 ['FromRenderFrameHost'],
Kevin McNee967dd2d22021-11-15 16:09:294332 'Introduce WC::FromRenderFrameHost',
4333 'chrome/my_feature.cc',
4334 ['void DoSomething(content::RenderFrameHost* rfh) {',
4335 ' auto* wc = content::WebContents::FromRenderFrameHost(rfh);',
4336 ' ChangeTabState(wc);',
4337 '}',
4338 ])
4339
4340 def testNoNotify(self):
4341 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044342 [],
Kevin McNee967dd2d22021-11-15 16:09:294343 'No API usage',
4344 'chrome/my_feature.cc',
4345 ['void DoSomething() {',
4346 ' // TODO: Something',
4347 '}',
4348 ])
4349 # Something under a top level directory we're not concerned about happens
4350 # to share a name with a content API.
4351 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044352 [],
Kevin McNee967dd2d22021-11-15 16:09:294353 'Uninteresting top level directory',
4354 'third_party/my_dep/my_code.cc',
4355 ['bool HasParent(Node* node) {',
4356 ' return node->GetParent();',
4357 '}',
4358 ])
4359 # We're not concerned with usage in test code.
4360 self._assert_notify(
Kevin McNee4eeec792022-02-14 20:02:044361 [],
Kevin McNee967dd2d22021-11-15 16:09:294362 'Usage in test code',
4363 'chrome/my_feature_unittest.cc',
4364 ['TEST_F(MyFeatureTest, DoesSomething) {',
4365 ' EXPECT_TRUE(web_contents()->GetMainFrame());',
4366 '}',
4367 ])
4368
Dominic Battre645d42342020-12-04 16:14:104369
Henrique Ferreiro2a4b55942021-11-29 23:45:364370class AssertAshOnlyCodeTest(unittest.TestCase):
4371 def testErrorsOnlyOnAshDirectories(self):
4372 files_in_ash = [
4373 MockFile('ash/BUILD.gn', []),
4374 MockFile('chrome/browser/ash/BUILD.gn', []),
4375 ]
4376 other_files = [
4377 MockFile('chrome/browser/BUILD.gn', []),
4378 MockFile('chrome/browser/BUILD.gn', ['assert(is_chromeos_ash)']),
4379 ]
4380 input_api = MockInputApi()
4381 input_api.files = files_in_ash
4382 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4383 self.assertEqual(2, len(errors))
4384
4385 input_api.files = other_files
4386 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4387 self.assertEqual(0, len(errors))
4388
4389 def testDoesNotErrorOnNonGNFiles(self):
4390 input_api = MockInputApi()
4391 input_api.files = [
4392 MockFile('ash/test.h', ['assert(is_chromeos_ash)']),
4393 MockFile('chrome/browser/ash/test.cc',
4394 ['assert(is_chromeos_ash)']),
4395 ]
4396 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4397 self.assertEqual(0, len(errors))
4398
Giovanni Ortuño Urquidiab84da62021-12-10 00:53:214399 def testDeletedFile(self):
4400 input_api = MockInputApi()
4401 input_api.files = [
4402 MockFile('ash/BUILD.gn', []),
4403 MockFile('ash/foo/BUILD.gn', [], action='D'),
4404 ]
4405 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4406 self.assertEqual(1, len(errors))
4407
Henrique Ferreiro2a4b55942021-11-29 23:45:364408 def testDoesNotErrorWithAssertion(self):
4409 input_api = MockInputApi()
4410 input_api.files = [
4411 MockFile('ash/BUILD.gn', ['assert(is_chromeos_ash)']),
4412 MockFile('chrome/browser/ash/BUILD.gn',
4413 ['assert(is_chromeos_ash)']),
4414 MockFile('chrome/browser/ash/BUILD.gn',
4415 ['assert(is_chromeos_ash, "test")']),
4416 ]
4417 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4418 self.assertEqual(0, len(errors))
4419
4420
Lukasz Anforowicz7016d05e2021-11-30 03:56:274421class CheckRawPtrUsageTest(unittest.TestCase):
4422 def testAllowedCases(self):
4423 mock_input_api = MockInputApi()
4424 mock_input_api.files = [
4425 # Browser-side files are allowed.
4426 MockAffectedFile('test10/browser/foo.h', ['raw_ptr<int>']),
4427 MockAffectedFile('test11/browser/foo.cc', ['raw_ptr<int>']),
4428 MockAffectedFile('test12/blink/common/foo.cc', ['raw_ptr<int>']),
4429 MockAffectedFile('test13/blink/public/common/foo.cc', ['raw_ptr<int>']),
4430 MockAffectedFile('test14/blink/public/platform/foo.cc',
4431 ['raw_ptr<int>']),
4432
4433 # Non-C++ files are allowed.
4434 MockAffectedFile('test20/renderer/foo.md', ['raw_ptr<int>']),
4435
4436 # Mentions in a comment are allowed.
4437 MockAffectedFile('test30/renderer/foo.cc', ['//raw_ptr<int>']),
4438 ]
4439 mock_output_api = MockOutputApi()
4440 errors = PRESUBMIT.CheckRawPtrUsage(mock_input_api, mock_output_api)
4441 self.assertFalse(errors)
4442
4443 def testDisallowedCases(self):
4444 mock_input_api = MockInputApi()
4445 mock_input_api.files = [
4446 MockAffectedFile('test1/renderer/foo.h', ['raw_ptr<int>']),
4447 MockAffectedFile('test2/renderer/foo.cc', ['raw_ptr<int>']),
4448 MockAffectedFile('test3/blink/public/web/foo.cc', ['raw_ptr<int>']),
4449 ]
4450 mock_output_api = MockOutputApi()
4451 errors = PRESUBMIT.CheckRawPtrUsage(mock_input_api, mock_output_api)
4452 self.assertEqual(len(mock_input_api.files), len(errors))
4453 for error in errors:
4454 self.assertTrue(
4455 'raw_ptr<T> should not be used in Renderer-only code' in
4456 error.message)
4457
4458
Henrique Ferreirof9819f2e32021-11-30 13:31:564459class AssertPythonShebangTest(unittest.TestCase):
4460 def testError(self):
4461 input_api = MockInputApi()
4462 input_api.files = [
4463 MockFile('ash/test.py', ['#!/usr/bin/python']),
4464 MockFile('chrome/test.py', ['#!/usr/bin/python2']),
4465 MockFile('third_party/blink/test.py', ['#!/usr/bin/python3']),
Takuto Ikuta36976512021-11-30 23:15:274466 MockFile('empty.py', []),
Henrique Ferreirof9819f2e32021-11-30 13:31:564467 ]
4468 errors = PRESUBMIT.CheckPythonShebang(input_api, MockOutputApi())
4469 self.assertEqual(3, len(errors))
4470
4471 def testNonError(self):
4472 input_api = MockInputApi()
4473 input_api.files = [
4474 MockFile('chrome/browser/BUILD.gn', ['#!/usr/bin/python']),
4475 MockFile('third_party/blink/web_tests/external/test.py',
4476 ['#!/usr/bin/python2']),
4477 MockFile('third_party/test/test.py', ['#!/usr/bin/python3']),
4478 ]
4479 errors = PRESUBMIT.CheckPythonShebang(input_api, MockOutputApi())
4480 self.assertEqual(0, len(errors))
4481
4482
[email protected]2299dcf2012-11-15 19:56:244483if __name__ == '__main__':
4484 unittest.main()