blob: 74c6d62a87992d6f081afefa3e1ecc988bbc1fe5 [file] [log] [blame]
[email protected]2299dcf2012-11-15 19:56:241#!/usr/bin/env python
2# Copyright (c) 2012 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
Daniel Cheng4dcdb6b2017-04-13 08:30:176import os.path
[email protected]99171a92014-06-03 08:44:477import subprocess
[email protected]2299dcf2012-11-15 19:56:248import unittest
9
10import PRESUBMIT
Saagar Sanghavifceeaae2020-08-12 16:40:3611
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3912from PRESUBMIT_test_mocks import MockFile, MockAffectedFile
gayane3dff8c22014-12-04 17:09:5113from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi
[email protected]2299dcf2012-11-15 19:56:2414
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3915
[email protected]99171a92014-06-03 08:44:4716_TEST_DATA_DIR = 'base/test/data/presubmit'
17
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3918
[email protected]b00342e7f2013-03-26 16:21:5419class VersionControlConflictsTest(unittest.TestCase):
[email protected]70ca77752012-11-20 03:45:0320 def testTypicalConflict(self):
21 lines = ['<<<<<<< HEAD',
22 ' base::ScopedTempDir temp_dir_;',
23 '=======',
24 ' ScopedTempDir temp_dir_;',
25 '>>>>>>> master']
26 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
27 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
28 self.assertEqual(3, len(errors))
29 self.assertTrue('1' in errors[0])
30 self.assertTrue('3' in errors[1])
31 self.assertTrue('5' in errors[2])
32
dbeam95c35a2f2015-06-02 01:40:2333 def testIgnoresReadmes(self):
34 lines = ['A First Level Header',
35 '====================',
36 '',
37 'A Second Level Header',
38 '---------------------']
39 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
40 MockInputApi(), MockFile('some/polymer/README.md', lines))
41 self.assertEqual(0, len(errors))
42
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3943
[email protected]b8079ae4a2012-12-05 19:56:4944class BadExtensionsTest(unittest.TestCase):
45 def testBadRejFile(self):
46 mock_input_api = MockInputApi()
47 mock_input_api.files = [
48 MockFile('some/path/foo.cc', ''),
49 MockFile('some/path/foo.cc.rej', ''),
50 MockFile('some/path2/bar.h.rej', ''),
51 ]
52
Saagar Sanghavifceeaae2020-08-12 16:40:3653 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:4954 self.assertEqual(1, len(results))
55 self.assertEqual(2, len(results[0].items))
56 self.assertTrue('foo.cc.rej' in results[0].items[0])
57 self.assertTrue('bar.h.rej' in results[0].items[1])
58
59 def testBadOrigFile(self):
60 mock_input_api = MockInputApi()
61 mock_input_api.files = [
62 MockFile('other/path/qux.h.orig', ''),
63 MockFile('other/path/qux.h', ''),
64 MockFile('other/path/qux.cc', ''),
65 ]
66
Saagar Sanghavifceeaae2020-08-12 16:40:3667 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:4968 self.assertEqual(1, len(results))
69 self.assertEqual(1, len(results[0].items))
70 self.assertTrue('qux.h.orig' in results[0].items[0])
71
72 def testGoodFiles(self):
73 mock_input_api = MockInputApi()
74 mock_input_api.files = [
75 MockFile('other/path/qux.h', ''),
76 MockFile('other/path/qux.cc', ''),
77 ]
Saagar Sanghavifceeaae2020-08-12 16:40:3678 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:4979 self.assertEqual(0, len(results))
80
81
Lei Zhang1c12a22f2021-05-12 11:28:4582class CheckForSuperfluousStlIncludesInHeadersTest(unittest.TestCase):
83 def testGoodFiles(self):
84 mock_input_api = MockInputApi()
85 mock_input_api.files = [
86 # The check is not smart enough to figure out which definitions correspond
87 # to which header.
88 MockFile('other/path/foo.h',
89 ['#include <string>',
90 'std::vector']),
91 # The check is not smart enough to do IWYU.
92 MockFile('other/path/bar.h',
93 ['#include "base/check.h"',
94 'std::vector']),
95 MockFile('other/path/qux.h',
96 ['#include "base/stl_util.h"',
97 'foobar']),
98 # The check is only for header files.
99 MockFile('other/path/not_checked.cc',
100 ['#include <vector>',
101 'bazbaz']),
102 ]
103 results = PRESUBMIT.CheckForSuperfluousStlIncludesInHeaders(
104 mock_input_api, MockOutputApi())
105 self.assertEqual(0, len(results))
106
107 def testBadFiles(self):
108 mock_input_api = MockInputApi()
109 mock_input_api.files = [
110 MockFile('other/path/foo.h',
111 ['#include <vector>',
112 'vector']),
113 MockFile('other/path/bar.h',
114 ['#include <limits>',
115 '#include <set>',
116 'no_std_namespace']),
117 ]
118 results = PRESUBMIT.CheckForSuperfluousStlIncludesInHeaders(
119 mock_input_api, MockOutputApi())
120 self.assertEqual(1, len(results))
121 self.assertTrue('foo.h: Includes STL' in results[0].message)
122 self.assertTrue('bar.h: Includes STL' in results[0].message)
123
124
glidere61efad2015-02-18 17:39:43125class CheckSingletonInHeadersTest(unittest.TestCase):
126 def testSingletonInArbitraryHeader(self):
127 diff_singleton_h = ['base::subtle::AtomicWord '
olli.raula36aa8be2015-09-10 11:14:22128 'base::Singleton<Type, Traits, DifferentiatingType>::']
129 diff_foo_h = ['// base::Singleton<Foo> in comment.',
130 'friend class base::Singleton<Foo>']
oysteinec430ad42015-10-22 20:55:24131 diff_foo2_h = [' //Foo* bar = base::Singleton<Foo>::get();']
olli.raula36aa8be2015-09-10 11:14:22132 diff_bad_h = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43133 mock_input_api = MockInputApi()
134 mock_input_api.files = [MockAffectedFile('base/memory/singleton.h',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39135 diff_singleton_h),
glidere61efad2015-02-18 17:39:43136 MockAffectedFile('foo.h', diff_foo_h),
oysteinec430ad42015-10-22 20:55:24137 MockAffectedFile('foo2.h', diff_foo2_h),
glidere61efad2015-02-18 17:39:43138 MockAffectedFile('bad.h', diff_bad_h)]
Saagar Sanghavifceeaae2020-08-12 16:40:36139 warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
glidere61efad2015-02-18 17:39:43140 MockOutputApi())
141 self.assertEqual(1, len(warnings))
Sylvain Defresnea8b73d252018-02-28 15:45:54142 self.assertEqual(1, len(warnings[0].items))
glidere61efad2015-02-18 17:39:43143 self.assertEqual('error', warnings[0].type)
olli.raula36aa8be2015-09-10 11:14:22144 self.assertTrue('Found base::Singleton<T>' in warnings[0].message)
glidere61efad2015-02-18 17:39:43145
146 def testSingletonInCC(self):
olli.raula36aa8be2015-09-10 11:14:22147 diff_cc = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43148 mock_input_api = MockInputApi()
149 mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)]
Saagar Sanghavifceeaae2020-08-12 16:40:36150 warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
glidere61efad2015-02-18 17:39:43151 MockOutputApi())
152 self.assertEqual(0, len(warnings))
153
154
[email protected]b00342e7f2013-03-26 16:21:54155class InvalidOSMacroNamesTest(unittest.TestCase):
156 def testInvalidOSMacroNames(self):
157 lines = ['#if defined(OS_WINDOWS)',
158 ' #elif defined(OS_WINDOW)',
Avi Drissman34594e902020-07-25 05:35:44159 ' # if defined(OS_MAC) || defined(OS_CHROME)',
Avi Drissman32967a9e2020-07-30 04:10:32160 '# else // defined(OS_MACOSX)',
[email protected]b00342e7f2013-03-26 16:21:54161 '#endif // defined(OS_MACOS)']
162 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
163 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
164 self.assertEqual(len(lines), len(errors))
165 self.assertTrue(':1 OS_WINDOWS' in errors[0])
166 self.assertTrue('(did you mean OS_WIN?)' in errors[0])
167
168 def testValidOSMacroNames(self):
169 lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS]
170 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
171 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
172 self.assertEqual(0, len(errors))
173
174
lliabraa35bab3932014-10-01 12:16:44175class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
176 def testInvalidIfDefinedMacroNames(self):
177 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
178 '#if !defined(TARGET_IPHONE_SIMULATOR)',
179 '#elif defined(TARGET_IPHONE_SIMULATOR)',
180 '#ifdef TARGET_IPHONE_SIMULATOR',
181 ' # ifdef TARGET_IPHONE_SIMULATOR',
182 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
183 '# else // defined(TARGET_IPHONE_SIMULATOR)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39184 '#endif // defined(TARGET_IPHONE_SIMULATOR)']
lliabraa35bab3932014-10-01 12:16:44185 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
186 MockInputApi(), MockFile('some/path/source.mm', lines))
187 self.assertEqual(len(lines), len(errors))
188
189 def testValidIfDefinedMacroNames(self):
190 lines = ['#if defined(FOO)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39191 '#ifdef BAR']
lliabraa35bab3932014-10-01 12:16:44192 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
193 MockInputApi(), MockFile('some/path/source.cc', lines))
194 self.assertEqual(0, len(errors))
195
196
Samuel Huang0db2ea22019-12-09 16:42:47197class CheckAddedDepsHaveTestApprovalsTest(unittest.TestCase):
Daniel Cheng4dcdb6b2017-04-13 08:30:17198
199 def calculate(self, old_include_rules, old_specific_include_rules,
200 new_include_rules, new_specific_include_rules):
201 return PRESUBMIT._CalculateAddedDeps(
202 os.path, 'include_rules = %r\nspecific_include_rules = %r' % (
203 old_include_rules, old_specific_include_rules),
204 'include_rules = %r\nspecific_include_rules = %r' % (
205 new_include_rules, new_specific_include_rules))
206
207 def testCalculateAddedDeps(self):
208 old_include_rules = [
209 '+base',
210 '-chrome',
211 '+content',
212 '-grit',
213 '-grit/",',
214 '+jni/fooblat.h',
215 '!sandbox',
[email protected]f32e2d1e2013-07-26 21:39:08216 ]
Daniel Cheng4dcdb6b2017-04-13 08:30:17217 old_specific_include_rules = {
218 'compositor\.*': {
219 '+cc',
220 },
221 }
222
223 new_include_rules = [
224 '-ash',
225 '+base',
226 '+chrome',
227 '+components',
228 '+content',
229 '+grit',
230 '+grit/generated_resources.h",',
231 '+grit/",',
232 '+jni/fooblat.h',
233 '+policy',
manzagop85e629e2017-05-09 22:11:48234 '+' + os.path.join('third_party', 'WebKit'),
Daniel Cheng4dcdb6b2017-04-13 08:30:17235 ]
236 new_specific_include_rules = {
237 'compositor\.*': {
238 '+cc',
239 },
240 'widget\.*': {
241 '+gpu',
242 },
243 }
244
[email protected]f32e2d1e2013-07-26 21:39:08245 expected = set([
manzagop85e629e2017-05-09 22:11:48246 os.path.join('chrome', 'DEPS'),
247 os.path.join('gpu', 'DEPS'),
248 os.path.join('components', 'DEPS'),
249 os.path.join('policy', 'DEPS'),
250 os.path.join('third_party', 'WebKit', 'DEPS'),
[email protected]f32e2d1e2013-07-26 21:39:08251 ])
Daniel Cheng4dcdb6b2017-04-13 08:30:17252 self.assertEqual(
253 expected,
254 self.calculate(old_include_rules, old_specific_include_rules,
255 new_include_rules, new_specific_include_rules))
256
257 def testCalculateAddedDepsIgnoresPermutations(self):
258 old_include_rules = [
259 '+base',
260 '+chrome',
261 ]
262 new_include_rules = [
263 '+chrome',
264 '+base',
265 ]
266 self.assertEqual(set(),
267 self.calculate(old_include_rules, {}, new_include_rules,
268 {}))
[email protected]f32e2d1e2013-07-26 21:39:08269
270
[email protected]99171a92014-06-03 08:44:47271class JSONParsingTest(unittest.TestCase):
272 def testSuccess(self):
273 input_api = MockInputApi()
274 filename = 'valid_json.json'
275 contents = ['// This is a comment.',
276 '{',
277 ' "key1": ["value1", "value2"],',
278 ' "key2": 3 // This is an inline comment.',
279 '}'
280 ]
281 input_api.files = [MockFile(filename, contents)]
282 self.assertEqual(None,
283 PRESUBMIT._GetJSONParseError(input_api, filename))
284
285 def testFailure(self):
286 input_api = MockInputApi()
287 test_data = [
288 ('invalid_json_1.json',
289 ['{ x }'],
[email protected]a3343272014-06-17 11:41:53290 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47291 ('invalid_json_2.json',
292 ['// Hello world!',
293 '{ "hello": "world }'],
[email protected]a3343272014-06-17 11:41:53294 'Unterminated string starting at:'),
[email protected]99171a92014-06-03 08:44:47295 ('invalid_json_3.json',
296 ['{ "a": "b", "c": "d", }'],
[email protected]a3343272014-06-17 11:41:53297 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47298 ('invalid_json_4.json',
299 ['{ "a": "b" "c": "d" }'],
[email protected]a3343272014-06-17 11:41:53300 'Expecting , delimiter:'),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39301 ]
[email protected]99171a92014-06-03 08:44:47302
303 input_api.files = [MockFile(filename, contents)
304 for (filename, contents, _) in test_data]
305
306 for (filename, _, expected_error) in test_data:
307 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
[email protected]a3343272014-06-17 11:41:53308 self.assertTrue(expected_error in str(actual_error),
309 "'%s' not found in '%s'" % (expected_error, actual_error))
[email protected]99171a92014-06-03 08:44:47310
311 def testNoEatComments(self):
312 input_api = MockInputApi()
313 file_with_comments = 'file_with_comments.json'
314 contents_with_comments = ['// This is a comment.',
315 '{',
316 ' "key1": ["value1", "value2"],',
317 ' "key2": 3 // This is an inline comment.',
318 '}'
319 ]
320 file_without_comments = 'file_without_comments.json'
321 contents_without_comments = ['{',
322 ' "key1": ["value1", "value2"],',
323 ' "key2": 3',
324 '}'
325 ]
326 input_api.files = [MockFile(file_with_comments, contents_with_comments),
327 MockFile(file_without_comments,
328 contents_without_comments)]
329
330 self.assertEqual('No JSON object could be decoded',
331 str(PRESUBMIT._GetJSONParseError(input_api,
332 file_with_comments,
333 eat_comments=False)))
334 self.assertEqual(None,
335 PRESUBMIT._GetJSONParseError(input_api,
336 file_without_comments,
337 eat_comments=False))
338
339
340class IDLParsingTest(unittest.TestCase):
341 def testSuccess(self):
342 input_api = MockInputApi()
343 filename = 'valid_idl_basics.idl'
344 contents = ['// Tests a valid IDL file.',
345 'namespace idl_basics {',
346 ' enum EnumType {',
347 ' name1,',
348 ' name2',
349 ' };',
350 '',
351 ' dictionary MyType1 {',
352 ' DOMString a;',
353 ' };',
354 '',
355 ' callback Callback1 = void();',
356 ' callback Callback2 = void(long x);',
357 ' callback Callback3 = void(MyType1 arg);',
358 ' callback Callback4 = void(EnumType type);',
359 '',
360 ' interface Functions {',
361 ' static void function1();',
362 ' static void function2(long x);',
363 ' static void function3(MyType1 arg);',
364 ' static void function4(Callback1 cb);',
365 ' static void function5(Callback2 cb);',
366 ' static void function6(Callback3 cb);',
367 ' static void function7(Callback4 cb);',
368 ' };',
369 '',
370 ' interface Events {',
371 ' static void onFoo1();',
372 ' static void onFoo2(long x);',
373 ' static void onFoo2(MyType1 arg);',
374 ' static void onFoo3(EnumType type);',
375 ' };',
376 '};'
377 ]
378 input_api.files = [MockFile(filename, contents)]
379 self.assertEqual(None,
380 PRESUBMIT._GetIDLParseError(input_api, filename))
381
382 def testFailure(self):
383 input_api = MockInputApi()
384 test_data = [
385 ('invalid_idl_1.idl',
386 ['//',
387 'namespace test {',
388 ' dictionary {',
389 ' DOMString s;',
390 ' };',
391 '};'],
392 'Unexpected "{" after keyword "dictionary".\n'),
393 # TODO(yoz): Disabled because it causes the IDL parser to hang.
394 # See crbug.com/363830.
395 # ('invalid_idl_2.idl',
396 # (['namespace test {',
397 # ' dictionary MissingSemicolon {',
398 # ' DOMString a',
399 # ' DOMString b;',
400 # ' };',
401 # '};'],
402 # 'Unexpected symbol DOMString after symbol a.'),
403 ('invalid_idl_3.idl',
404 ['//',
405 'namespace test {',
406 ' enum MissingComma {',
407 ' name1',
408 ' name2',
409 ' };',
410 '};'],
411 'Unexpected symbol name2 after symbol name1.'),
412 ('invalid_idl_4.idl',
413 ['//',
414 'namespace test {',
415 ' enum TrailingComma {',
416 ' name1,',
417 ' name2,',
418 ' };',
419 '};'],
420 'Trailing comma in block.'),
421 ('invalid_idl_5.idl',
422 ['//',
423 'namespace test {',
424 ' callback Callback1 = void(;',
425 '};'],
426 'Unexpected ";" after "(".'),
427 ('invalid_idl_6.idl',
428 ['//',
429 'namespace test {',
430 ' callback Callback1 = void(long );',
431 '};'],
432 'Unexpected ")" after symbol long.'),
433 ('invalid_idl_7.idl',
434 ['//',
435 'namespace test {',
436 ' interace Events {',
437 ' static void onFoo1();',
438 ' };',
439 '};'],
440 'Unexpected symbol Events after symbol interace.'),
441 ('invalid_idl_8.idl',
442 ['//',
443 'namespace test {',
444 ' interface NotEvent {',
445 ' static void onFoo1();',
446 ' };',
447 '};'],
448 'Did not process Interface Interface(NotEvent)'),
449 ('invalid_idl_9.idl',
450 ['//',
451 'namespace test {',
452 ' interface {',
453 ' static void function1();',
454 ' };',
455 '};'],
456 'Interface missing name.'),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39457 ]
[email protected]99171a92014-06-03 08:44:47458
459 input_api.files = [MockFile(filename, contents)
460 for (filename, contents, _) in test_data]
461
462 for (filename, _, expected_error) in test_data:
463 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
464 self.assertTrue(expected_error in str(actual_error),
465 "'%s' not found in '%s'" % (expected_error, actual_error))
466
467
davileene0426252015-03-02 21:10:41468class UserMetricsActionTest(unittest.TestCase):
469 def testUserMetricsActionInActions(self):
470 input_api = MockInputApi()
471 file_with_user_action = 'file_with_user_action.cc'
472 contents_with_user_action = [
473 'base::UserMetricsAction("AboutChrome")'
474 ]
475
476 input_api.files = [MockFile(file_with_user_action,
477 contents_with_user_action)]
478
479 self.assertEqual(
Saagar Sanghavifceeaae2020-08-12 16:40:36480 [], PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi()))
davileene0426252015-03-02 21:10:41481
davileene0426252015-03-02 21:10:41482 def testUserMetricsActionNotAddedToActions(self):
483 input_api = MockInputApi()
484 file_with_user_action = 'file_with_user_action.cc'
485 contents_with_user_action = [
486 'base::UserMetricsAction("NotInActionsXml")'
487 ]
488
489 input_api.files = [MockFile(file_with_user_action,
490 contents_with_user_action)]
491
Saagar Sanghavifceeaae2020-08-12 16:40:36492 output = PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi())
davileene0426252015-03-02 21:10:41493 self.assertEqual(
494 ('File %s line %d: %s is missing in '
495 'tools/metrics/actions/actions.xml. Please run '
496 'tools/metrics/actions/extract_actions.py to update.'
497 % (file_with_user_action, 1, 'NotInActionsXml')),
498 output[0].message)
499
Alexei Svitkine64505a92021-03-11 22:00:54500 def testUserMetricsActionInTestFile(self):
501 input_api = MockInputApi()
502 file_with_user_action = 'file_with_user_action_unittest.cc'
503 contents_with_user_action = [
504 'base::UserMetricsAction("NotInActionsXml")'
505 ]
506
507 input_api.files = [MockFile(file_with_user_action,
508 contents_with_user_action)]
509
510 self.assertEqual(
511 [], PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi()))
512
davileene0426252015-03-02 21:10:41513
agrievef32bcc72016-04-04 14:57:40514class PydepsNeedsUpdatingTest(unittest.TestCase):
515
516 class MockSubprocess(object):
517 CalledProcessError = subprocess.CalledProcessError
518
Mohamed Heikal7cd4d8312020-06-16 16:49:40519 def _MockParseGclientArgs(self, is_android=True):
520 return lambda: {'checkout_android': 'true' if is_android else 'false' }
521
agrievef32bcc72016-04-04 14:57:40522 def setUp(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40523 mock_all_pydeps = ['A.pydeps', 'B.pydeps', 'D.pydeps']
agrievef32bcc72016-04-04 14:57:40524 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
525 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
Mohamed Heikal7cd4d8312020-06-16 16:49:40526 mock_android_pydeps = ['D.pydeps']
527 self.old_ANDROID_SPECIFIC_PYDEPS_FILES = (
528 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES)
529 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = mock_android_pydeps
530 self.old_ParseGclientArgs = PRESUBMIT._ParseGclientArgs
531 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs()
agrievef32bcc72016-04-04 14:57:40532 self.mock_input_api = MockInputApi()
533 self.mock_output_api = MockOutputApi()
534 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
535 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
536 self.checker._file_cache = {
Andrew Grieve5bb4cf702020-10-22 20:21:39537 'A.pydeps': '# Generated by:\n# CMD --output A.pydeps A\nA.py\nC.py\n',
538 'B.pydeps': '# Generated by:\n# CMD --output B.pydeps B\nB.py\nC.py\n',
539 'D.pydeps': '# Generated by:\n# CMD --output D.pydeps D\nD.py\n',
agrievef32bcc72016-04-04 14:57:40540 }
541
542 def tearDown(self):
543 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
Mohamed Heikal7cd4d8312020-06-16 16:49:40544 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = (
545 self.old_ANDROID_SPECIFIC_PYDEPS_FILES)
546 PRESUBMIT._ParseGclientArgs = self.old_ParseGclientArgs
agrievef32bcc72016-04-04 14:57:40547
548 def _RunCheck(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36549 return PRESUBMIT.CheckPydepsNeedsUpdating(self.mock_input_api,
agrievef32bcc72016-04-04 14:57:40550 self.mock_output_api,
551 checker_for_tests=self.checker)
552
553 def testAddedPydep(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36554 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13555 if self.mock_input_api.platform != 'linux2':
556 return []
557
agrievef32bcc72016-04-04 14:57:40558 self.mock_input_api.files = [
559 MockAffectedFile('new.pydeps', [], action='A'),
560 ]
561
Zhiling Huang45cabf32018-03-10 00:50:03562 self.mock_input_api.CreateMockFileInPath(
563 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
564 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40565 results = self._RunCheck()
566 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39567 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40568
Zhiling Huang45cabf32018-03-10 00:50:03569 def testPydepNotInSrc(self):
570 self.mock_input_api.files = [
571 MockAffectedFile('new.pydeps', [], action='A'),
572 ]
573 self.mock_input_api.CreateMockFileInPath([])
574 results = self._RunCheck()
575 self.assertEqual(0, len(results))
576
agrievef32bcc72016-04-04 14:57:40577 def testRemovedPydep(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36578 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13579 if self.mock_input_api.platform != 'linux2':
580 return []
581
agrievef32bcc72016-04-04 14:57:40582 self.mock_input_api.files = [
583 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
584 ]
Zhiling Huang45cabf32018-03-10 00:50:03585 self.mock_input_api.CreateMockFileInPath(
586 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
587 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40588 results = self._RunCheck()
589 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39590 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40591
592 def testRandomPyIgnored(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36593 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13594 if self.mock_input_api.platform != 'linux2':
595 return []
596
agrievef32bcc72016-04-04 14:57:40597 self.mock_input_api.files = [
598 MockAffectedFile('random.py', []),
599 ]
600
601 results = self._RunCheck()
602 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
603
604 def testRelevantPyNoChange(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36605 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13606 if self.mock_input_api.platform != 'linux2':
607 return []
608
agrievef32bcc72016-04-04 14:57:40609 self.mock_input_api.files = [
610 MockAffectedFile('A.py', []),
611 ]
612
John Budorickab2fa102017-10-06 16:59:49613 def mock_check_output(cmd, shell=False, env=None):
Andrew Grieve5bb4cf702020-10-22 20:21:39614 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
agrievef32bcc72016-04-04 14:57:40615 return self.checker._file_cache['A.pydeps']
616
617 self.mock_input_api.subprocess.check_output = mock_check_output
618
619 results = self._RunCheck()
620 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
621
622 def testRelevantPyOneChange(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36623 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13624 if self.mock_input_api.platform != 'linux2':
625 return []
626
agrievef32bcc72016-04-04 14:57:40627 self.mock_input_api.files = [
628 MockAffectedFile('A.py', []),
629 ]
630
John Budorickab2fa102017-10-06 16:59:49631 def mock_check_output(cmd, shell=False, env=None):
Andrew Grieve5bb4cf702020-10-22 20:21:39632 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
agrievef32bcc72016-04-04 14:57:40633 return 'changed data'
634
635 self.mock_input_api.subprocess.check_output = mock_check_output
636
637 results = self._RunCheck()
638 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39639 self.assertIn('File is stale', str(results[0]))
agrievef32bcc72016-04-04 14:57:40640
641 def testRelevantPyTwoChanges(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36642 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13643 if self.mock_input_api.platform != 'linux2':
644 return []
645
agrievef32bcc72016-04-04 14:57:40646 self.mock_input_api.files = [
647 MockAffectedFile('C.py', []),
648 ]
649
John Budorickab2fa102017-10-06 16:59:49650 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40651 return 'changed data'
652
653 self.mock_input_api.subprocess.check_output = mock_check_output
654
655 results = self._RunCheck()
656 self.assertEqual(2, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39657 self.assertIn('File is stale', str(results[0]))
658 self.assertIn('File is stale', str(results[1]))
agrievef32bcc72016-04-04 14:57:40659
Mohamed Heikal7cd4d8312020-06-16 16:49:40660 def testRelevantAndroidPyInNonAndroidCheckout(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36661 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Mohamed Heikal7cd4d8312020-06-16 16:49:40662 if self.mock_input_api.platform != 'linux2':
663 return []
664
665 self.mock_input_api.files = [
666 MockAffectedFile('D.py', []),
667 ]
668
669 def mock_check_output(cmd, shell=False, env=None):
Andrew Grieve5bb4cf702020-10-22 20:21:39670 self.assertEqual('CMD --output D.pydeps D --output ""', cmd)
Mohamed Heikal7cd4d8312020-06-16 16:49:40671 return 'changed data'
672
673 self.mock_input_api.subprocess.check_output = mock_check_output
674 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs(is_android=False)
675
676 results = self._RunCheck()
677 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39678 self.assertIn('Android', str(results[0]))
679 self.assertIn('D.pydeps', str(results[0]))
680
681 def testGnPathsAndMissingOutputFlag(self):
682 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
683 if self.mock_input_api.platform != 'linux2':
684 return []
685
686 self.checker._file_cache = {
687 'A.pydeps': '# Generated by:\n# CMD --gn-paths A\n//A.py\n//C.py\n',
688 'B.pydeps': '# Generated by:\n# CMD --gn-paths B\n//B.py\n//C.py\n',
689 'D.pydeps': '# Generated by:\n# CMD --gn-paths D\n//D.py\n',
690 }
691
692 self.mock_input_api.files = [
693 MockAffectedFile('A.py', []),
694 ]
695
696 def mock_check_output(cmd, shell=False, env=None):
697 self.assertEqual('CMD --gn-paths A --output A.pydeps --output ""', cmd)
698 return 'changed data'
699
700 self.mock_input_api.subprocess.check_output = mock_check_output
701
702 results = self._RunCheck()
703 self.assertEqual(1, len(results))
704 self.assertIn('File is stale', str(results[0]))
Mohamed Heikal7cd4d8312020-06-16 16:49:40705
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39706
Daniel Bratell8ba52722018-03-02 16:06:14707class IncludeGuardTest(unittest.TestCase):
708 def testIncludeGuardChecks(self):
709 mock_input_api = MockInputApi()
710 mock_output_api = MockOutputApi()
711 mock_input_api.files = [
712 MockAffectedFile('content/browser/thing/foo.h', [
713 '// Comment',
714 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
715 '#define CONTENT_BROWSER_THING_FOO_H_',
716 'struct McBoatFace;',
717 '#endif // CONTENT_BROWSER_THING_FOO_H_',
718 ]),
719 MockAffectedFile('content/browser/thing/bar.h', [
720 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
721 '#define CONTENT_BROWSER_THING_BAR_H_',
722 'namespace content {',
723 '#endif // CONTENT_BROWSER_THING_BAR_H_',
724 '} // namespace content',
725 ]),
726 MockAffectedFile('content/browser/test1.h', [
727 'namespace content {',
728 '} // namespace content',
729 ]),
730 MockAffectedFile('content\\browser\\win.h', [
731 '#ifndef CONTENT_BROWSER_WIN_H_',
732 '#define CONTENT_BROWSER_WIN_H_',
733 'struct McBoatFace;',
734 '#endif // CONTENT_BROWSER_WIN_H_',
735 ]),
736 MockAffectedFile('content/browser/test2.h', [
737 '// Comment',
738 '#ifndef CONTENT_BROWSER_TEST2_H_',
739 'struct McBoatFace;',
740 '#endif // CONTENT_BROWSER_TEST2_H_',
741 ]),
742 MockAffectedFile('content/browser/internal.h', [
743 '// Comment',
744 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
745 '#define CONTENT_BROWSER_INTERNAL_H_',
746 '// Comment',
747 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
748 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
749 'namespace internal {',
750 '} // namespace internal',
751 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
752 'namespace content {',
753 '} // namespace content',
754 '#endif // CONTENT_BROWSER_THING_BAR_H_',
755 ]),
756 MockAffectedFile('content/browser/thing/foo.cc', [
757 '// This is a non-header.',
758 ]),
759 MockAffectedFile('content/browser/disabled.h', [
760 '// no-include-guard-because-multiply-included',
761 'struct McBoatFace;',
762 ]),
763 # New files don't allow misspelled include guards.
764 MockAffectedFile('content/browser/spleling.h', [
765 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
766 '#define CONTENT_BROWSER_SPLLEING_H_',
767 'struct McBoatFace;',
768 '#endif // CONTENT_BROWSER_SPLLEING_H_',
769 ]),
Olivier Robinbba137492018-07-30 11:31:34770 # New files don't allow + in include guards.
771 MockAffectedFile('content/browser/foo+bar.h', [
772 '#ifndef CONTENT_BROWSER_FOO+BAR_H_',
773 '#define CONTENT_BROWSER_FOO+BAR_H_',
774 'struct McBoatFace;',
775 '#endif // CONTENT_BROWSER_FOO+BAR_H_',
776 ]),
Daniel Bratell8ba52722018-03-02 16:06:14777 # Old files allow misspelled include guards (for now).
778 MockAffectedFile('chrome/old.h', [
779 '// New contents',
780 '#ifndef CHROME_ODL_H_',
781 '#define CHROME_ODL_H_',
782 '#endif // CHROME_ODL_H_',
783 ], [
784 '// Old contents',
785 '#ifndef CHROME_ODL_H_',
786 '#define CHROME_ODL_H_',
787 '#endif // CHROME_ODL_H_',
788 ]),
789 # Using a Blink style include guard outside Blink is wrong.
790 MockAffectedFile('content/NotInBlink.h', [
791 '#ifndef NotInBlink_h',
792 '#define NotInBlink_h',
793 'struct McBoatFace;',
794 '#endif // NotInBlink_h',
795 ]),
Daniel Bratell39b5b062018-05-16 18:09:57796 # Using a Blink style include guard in Blink is no longer ok.
797 MockAffectedFile('third_party/blink/InBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14798 '#ifndef InBlink_h',
799 '#define InBlink_h',
800 'struct McBoatFace;',
801 '#endif // InBlink_h',
802 ]),
803 # Using a bad include guard in Blink is not ok.
Daniel Bratell39b5b062018-05-16 18:09:57804 MockAffectedFile('third_party/blink/AlsoInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14805 '#ifndef WrongInBlink_h',
806 '#define WrongInBlink_h',
807 'struct McBoatFace;',
808 '#endif // WrongInBlink_h',
809 ]),
Daniel Bratell39b5b062018-05-16 18:09:57810 # Using a bad include guard in Blink is not accepted even if
811 # it's an old file.
812 MockAffectedFile('third_party/blink/StillInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14813 '// New contents',
814 '#ifndef AcceptedInBlink_h',
815 '#define AcceptedInBlink_h',
816 'struct McBoatFace;',
817 '#endif // AcceptedInBlink_h',
818 ], [
819 '// Old contents',
820 '#ifndef AcceptedInBlink_h',
821 '#define AcceptedInBlink_h',
822 'struct McBoatFace;',
823 '#endif // AcceptedInBlink_h',
824 ]),
Daniel Bratell39b5b062018-05-16 18:09:57825 # Using a non-Chromium include guard in third_party
826 # (outside blink) is accepted.
827 MockAffectedFile('third_party/foo/some_file.h', [
828 '#ifndef REQUIRED_RPCNDR_H_',
829 '#define REQUIRED_RPCNDR_H_',
830 'struct SomeFileFoo;',
831 '#endif // REQUIRED_RPCNDR_H_',
832 ]),
Kinuko Yasuda0cdb3da2019-07-31 21:50:32833 # Not having proper include guard in *_message_generator.h
834 # for old IPC messages is allowed.
835 MockAffectedFile('content/common/content_message_generator.h', [
836 '#undef CONTENT_COMMON_FOO_MESSAGES_H_',
837 '#include "content/common/foo_messages.h"',
838 '#ifndef CONTENT_COMMON_FOO_MESSAGES_H_',
839 '#error "Failed to include content/common/foo_messages.h"',
840 '#endif',
841 ]),
Daniel Bratell8ba52722018-03-02 16:06:14842 ]
Saagar Sanghavifceeaae2020-08-12 16:40:36843 msgs = PRESUBMIT.CheckForIncludeGuards(
Daniel Bratell8ba52722018-03-02 16:06:14844 mock_input_api, mock_output_api)
Olivier Robinbba137492018-07-30 11:31:34845 expected_fail_count = 8
Daniel Bratell8ba52722018-03-02 16:06:14846 self.assertEqual(expected_fail_count, len(msgs),
847 'Expected %d items, found %d: %s'
848 % (expected_fail_count, len(msgs), msgs))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39849 self.assertEqual(msgs[0].items, ['content/browser/thing/bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:14850 self.assertEqual(msgs[0].message,
851 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
852 'not covering the whole file')
853
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39854 self.assertEqual(msgs[1].items, ['content/browser/test1.h'])
Daniel Bratell8ba52722018-03-02 16:06:14855 self.assertEqual(msgs[1].message,
856 'Missing include guard CONTENT_BROWSER_TEST1_H_')
857
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39858 self.assertEqual(msgs[2].items, ['content/browser/test2.h:3'])
Daniel Bratell8ba52722018-03-02 16:06:14859 self.assertEqual(msgs[2].message,
860 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
861 'include guard')
862
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39863 self.assertEqual(msgs[3].items, ['content/browser/spleling.h:1'])
Daniel Bratell8ba52722018-03-02 16:06:14864 self.assertEqual(msgs[3].message,
865 'Header using the wrong include guard name '
866 'CONTENT_BROWSER_SPLLEING_H_')
867
Olivier Robinbba137492018-07-30 11:31:34868 self.assertEqual(msgs[4].items, ['content/browser/foo+bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:14869 self.assertEqual(msgs[4].message,
Olivier Robinbba137492018-07-30 11:31:34870 'Missing include guard CONTENT_BROWSER_FOO_BAR_H_')
871
872 self.assertEqual(msgs[5].items, ['content/NotInBlink.h:1'])
873 self.assertEqual(msgs[5].message,
Daniel Bratell8ba52722018-03-02 16:06:14874 'Header using the wrong include guard name '
875 'NotInBlink_h')
876
Olivier Robinbba137492018-07-30 11:31:34877 self.assertEqual(msgs[6].items, ['third_party/blink/InBlink.h:1'])
878 self.assertEqual(msgs[6].message,
Daniel Bratell8ba52722018-03-02 16:06:14879 'Header using the wrong include guard name '
Daniel Bratell39b5b062018-05-16 18:09:57880 'InBlink_h')
881
Olivier Robinbba137492018-07-30 11:31:34882 self.assertEqual(msgs[7].items, ['third_party/blink/AlsoInBlink.h:1'])
883 self.assertEqual(msgs[7].message,
Daniel Bratell39b5b062018-05-16 18:09:57884 'Header using the wrong include guard name '
Daniel Bratell8ba52722018-03-02 16:06:14885 'WrongInBlink_h')
886
Chris Hall59f8d0c72020-05-01 07:31:19887class AccessibilityRelnotesFieldTest(unittest.TestCase):
888 def testRelnotesPresent(self):
889 mock_input_api = MockInputApi()
890 mock_output_api = MockOutputApi()
891
892 mock_input_api.files = [MockAffectedFile('ui/accessibility/foo.bar', [''])]
Akihiro Ota08108e542020-05-20 15:30:53893 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19894 mock_input_api.change.footers['AX-Relnotes'] = [
895 'Important user facing change']
896
Saagar Sanghavifceeaae2020-08-12 16:40:36897 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19898 mock_input_api, mock_output_api)
899 self.assertEqual(0, len(msgs),
900 'Expected %d messages, found %d: %s'
901 % (0, len(msgs), msgs))
902
903 def testRelnotesMissingFromAccessibilityChange(self):
904 mock_input_api = MockInputApi()
905 mock_output_api = MockOutputApi()
906
907 mock_input_api.files = [
908 MockAffectedFile('some/file', ['']),
909 MockAffectedFile('ui/accessibility/foo.bar', ['']),
910 MockAffectedFile('some/other/file', [''])
911 ]
Akihiro Ota08108e542020-05-20 15:30:53912 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19913
Saagar Sanghavifceeaae2020-08-12 16:40:36914 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19915 mock_input_api, mock_output_api)
916 self.assertEqual(1, len(msgs),
917 'Expected %d messages, found %d: %s'
918 % (1, len(msgs), msgs))
919 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
920 'Missing AX-Relnotes field message not found in errors')
921
922 # The relnotes footer is not required for changes which do not touch any
923 # accessibility directories.
924 def testIgnoresNonAccesssibilityCode(self):
925 mock_input_api = MockInputApi()
926 mock_output_api = MockOutputApi()
927
928 mock_input_api.files = [
929 MockAffectedFile('some/file', ['']),
930 MockAffectedFile('some/other/file', [''])
931 ]
Akihiro Ota08108e542020-05-20 15:30:53932 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19933
Saagar Sanghavifceeaae2020-08-12 16:40:36934 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19935 mock_input_api, mock_output_api)
936 self.assertEqual(0, len(msgs),
937 'Expected %d messages, found %d: %s'
938 % (0, len(msgs), msgs))
939
940 # Test that our presubmit correctly raises an error for a set of known paths.
941 def testExpectedPaths(self):
942 filesToTest = [
943 "chrome/browser/accessibility/foo.py",
Henrique Ferreirobb1bb4a2021-03-18 00:04:08944 "chrome/browser/ash/arc/accessibility/foo.cc",
Chris Hall59f8d0c72020-05-01 07:31:19945 "chrome/browser/ui/views/accessibility/foo.h",
946 "chrome/browser/extensions/api/automation/foo.h",
947 "chrome/browser/extensions/api/automation_internal/foo.cc",
948 "chrome/renderer/extensions/accessibility_foo.h",
949 "chrome/tests/data/accessibility/foo.html",
950 "content/browser/accessibility/foo.cc",
951 "content/renderer/accessibility/foo.h",
952 "content/tests/data/accessibility/foo.cc",
953 "extensions/renderer/api/automation/foo.h",
954 "ui/accessibility/foo/bar/baz.cc",
955 "ui/views/accessibility/foo/bar/baz.h",
956 ]
957
958 for testFile in filesToTest:
959 mock_input_api = MockInputApi()
960 mock_output_api = MockOutputApi()
961
962 mock_input_api.files = [
963 MockAffectedFile(testFile, [''])
964 ]
Akihiro Ota08108e542020-05-20 15:30:53965 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19966
Saagar Sanghavifceeaae2020-08-12 16:40:36967 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19968 mock_input_api, mock_output_api)
969 self.assertEqual(1, len(msgs),
970 'Expected %d messages, found %d: %s, for file %s'
971 % (1, len(msgs), msgs, testFile))
972 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
973 ('Missing AX-Relnotes field message not found in errors '
974 ' for file %s' % (testFile)))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39975
Akihiro Ota08108e542020-05-20 15:30:53976 # Test that AX-Relnotes field can appear in the commit description (as long
977 # as it appears at the beginning of a line).
978 def testRelnotesInCommitDescription(self):
979 mock_input_api = MockInputApi()
980 mock_output_api = MockOutputApi()
981
982 mock_input_api.files = [
983 MockAffectedFile('ui/accessibility/foo.bar', ['']),
984 ]
985 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
986 'AX-Relnotes: solves all accessibility issues forever')
987
Saagar Sanghavifceeaae2020-08-12 16:40:36988 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:53989 mock_input_api, mock_output_api)
990 self.assertEqual(0, len(msgs),
991 'Expected %d messages, found %d: %s'
992 % (0, len(msgs), msgs))
993
994 # Test that we don't match AX-Relnotes if it appears in the middle of a line.
995 def testRelnotesMustAppearAtBeginningOfLine(self):
996 mock_input_api = MockInputApi()
997 mock_output_api = MockOutputApi()
998
999 mock_input_api.files = [
1000 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1001 ]
1002 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1003 'This change has no AX-Relnotes: we should print a warning')
1004
Saagar Sanghavifceeaae2020-08-12 16:40:361005 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531006 mock_input_api, mock_output_api)
1007 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1008 'Missing AX-Relnotes field message not found in errors')
1009
1010 # Tests that the AX-Relnotes field can be lowercase and use a '=' in place
1011 # of a ':'.
1012 def testRelnotesLowercaseWithEqualSign(self):
1013 mock_input_api = MockInputApi()
1014 mock_output_api = MockOutputApi()
1015
1016 mock_input_api.files = [
1017 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1018 ]
1019 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1020 'ax-relnotes= this is a valid format for accessibiliy relnotes')
1021
Saagar Sanghavifceeaae2020-08-12 16:40:361022 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531023 mock_input_api, mock_output_api)
1024 self.assertEqual(0, len(msgs),
1025 'Expected %d messages, found %d: %s'
1026 % (0, len(msgs), msgs))
1027
yolandyan45001472016-12-21 21:12:421028class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
1029 def testCheckAndroidTestAnnotationUsage(self):
1030 mock_input_api = MockInputApi()
1031 mock_output_api = MockOutputApi()
1032
1033 mock_input_api.files = [
1034 MockAffectedFile('LalaLand.java', [
1035 'random stuff'
1036 ]),
1037 MockAffectedFile('CorrectUsage.java', [
1038 'import android.support.test.filters.LargeTest;',
1039 'import android.support.test.filters.MediumTest;',
1040 'import android.support.test.filters.SmallTest;',
1041 ]),
1042 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
1043 'import android.test.suitebuilder.annotation.LargeTest;',
1044 ]),
1045 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
1046 'import android.test.suitebuilder.annotation.MediumTest;',
1047 ]),
1048 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
1049 'import android.test.suitebuilder.annotation.SmallTest;',
1050 ]),
1051 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
1052 'import android.test.suitebuilder.annotation.Smoke;',
1053 ])
1054 ]
1055 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
1056 mock_input_api, mock_output_api)
1057 self.assertEqual(1, len(msgs),
1058 'Expected %d items, found %d: %s'
1059 % (1, len(msgs), msgs))
1060 self.assertEqual(4, len(msgs[0].items),
1061 'Expected %d items, found %d: %s'
1062 % (4, len(msgs[0].items), msgs[0].items))
1063 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
1064 'UsedDeprecatedLargeTestAnnotation not found in errors')
1065 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
1066 in msgs[0].items,
1067 'UsedDeprecatedMediumTestAnnotation not found in errors')
1068 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
1069 'UsedDeprecatedSmallTestAnnotation not found in errors')
1070 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
1071 'UsedDeprecatedSmokeAnnotation not found in errors')
1072
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391073
Mohamed Heikal5e5b7922020-10-29 18:57:591074class CheckNoDownstreamDepsTest(unittest.TestCase):
1075 def testInvalidDepFromUpstream(self):
1076 mock_input_api = MockInputApi()
1077 mock_output_api = MockOutputApi()
1078
1079 mock_input_api.files = [
1080 MockAffectedFile('BUILD.gn', [
1081 'deps = [',
1082 ' "//clank/target:test",',
1083 ']'
1084 ]),
1085 MockAffectedFile('chrome/android/BUILD.gn', [
1086 'deps = [ "//clank/target:test" ]'
1087 ]),
1088 MockAffectedFile('chrome/chrome_java_deps.gni', [
1089 'java_deps = [',
1090 ' "//clank/target:test",',
1091 ']'
1092 ]),
1093 ]
1094 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1095 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1096 mock_input_api, mock_output_api)
1097 self.assertEqual(1, len(msgs),
1098 'Expected %d items, found %d: %s'
1099 % (1, len(msgs), msgs))
1100 self.assertEqual(3, len(msgs[0].items),
1101 'Expected %d items, found %d: %s'
1102 % (3, len(msgs[0].items), msgs[0].items))
1103 self.assertTrue(any('BUILD.gn:2' in item for item in msgs[0].items),
1104 'BUILD.gn not found in errors')
1105 self.assertTrue(
1106 any('chrome/android/BUILD.gn:1' in item for item in msgs[0].items),
1107 'chrome/android/BUILD.gn:1 not found in errors')
1108 self.assertTrue(
1109 any('chrome/chrome_java_deps.gni:2' in item for item in msgs[0].items),
1110 'chrome/chrome_java_deps.gni:2 not found in errors')
1111
1112 def testAllowsComments(self):
1113 mock_input_api = MockInputApi()
1114 mock_output_api = MockOutputApi()
1115
1116 mock_input_api.files = [
1117 MockAffectedFile('BUILD.gn', [
1118 '# real implementation in //clank/target:test',
1119 ]),
1120 ]
1121 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1122 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1123 mock_input_api, mock_output_api)
1124 self.assertEqual(0, len(msgs),
1125 'Expected %d items, found %d: %s'
1126 % (0, len(msgs), msgs))
1127
1128 def testOnlyChecksBuildFiles(self):
1129 mock_input_api = MockInputApi()
1130 mock_output_api = MockOutputApi()
1131
1132 mock_input_api.files = [
1133 MockAffectedFile('README.md', [
1134 'DEPS = [ "//clank/target:test" ]'
1135 ]),
1136 MockAffectedFile('chrome/android/java/file.java', [
1137 '//clank/ only function'
1138 ]),
1139 ]
1140 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1141 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1142 mock_input_api, mock_output_api)
1143 self.assertEqual(0, len(msgs),
1144 'Expected %d items, found %d: %s'
1145 % (0, len(msgs), msgs))
1146
1147 def testValidDepFromDownstream(self):
1148 mock_input_api = MockInputApi()
1149 mock_output_api = MockOutputApi()
1150
1151 mock_input_api.files = [
1152 MockAffectedFile('BUILD.gn', [
1153 'DEPS = [',
1154 ' "//clank/target:test",',
1155 ']'
1156 ]),
1157 MockAffectedFile('java/BUILD.gn', [
1158 'DEPS = [ "//clank/target:test" ]'
1159 ]),
1160 ]
1161 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src/clank'
1162 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1163 mock_input_api, mock_output_api)
1164 self.assertEqual(0, len(msgs),
1165 'Expected %d items, found %d: %s'
1166 % (0, len(msgs), msgs))
1167
Yoland Yanb92fa522017-08-28 17:37:061168class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271169 def testCheckAndroidTestJUnitFramework(self):
Yoland Yanb92fa522017-08-28 17:37:061170 mock_input_api = MockInputApi()
1171 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:421172
Yoland Yanb92fa522017-08-28 17:37:061173 mock_input_api.files = [
1174 MockAffectedFile('LalaLand.java', [
1175 'random stuff'
1176 ]),
1177 MockAffectedFile('CorrectUsage.java', [
1178 'import org.junit.ABC',
1179 'import org.junit.XYZ;',
1180 ]),
1181 MockAffectedFile('UsedDeprecatedJUnit.java', [
1182 'import junit.framework.*;',
1183 ]),
1184 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
1185 'import junit.framework.Assert;',
1186 ]),
1187 ]
1188 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
1189 mock_input_api, mock_output_api)
1190 self.assertEqual(1, len(msgs),
1191 'Expected %d items, found %d: %s'
1192 % (1, len(msgs), msgs))
1193 self.assertEqual(2, len(msgs[0].items),
1194 'Expected %d items, found %d: %s'
1195 % (2, len(msgs[0].items), msgs[0].items))
1196 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
1197 'UsedDeprecatedJUnit.java not found in errors')
1198 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
1199 in msgs[0].items,
1200 'UsedDeprecatedJUnitAssert not found in errors')
1201
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391202
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271203class AndroidJUnitBaseClassTest(unittest.TestCase):
1204 def testCheckAndroidTestJUnitBaseClass(self):
Yoland Yanb92fa522017-08-28 17:37:061205 mock_input_api = MockInputApi()
1206 mock_output_api = MockOutputApi()
1207
1208 mock_input_api.files = [
1209 MockAffectedFile('LalaLand.java', [
1210 'random stuff'
1211 ]),
1212 MockAffectedFile('CorrectTest.java', [
1213 '@RunWith(ABC.class);'
1214 'public class CorrectTest {',
1215 '}',
1216 ]),
1217 MockAffectedFile('HistoricallyIncorrectTest.java', [
1218 'public class Test extends BaseCaseA {',
1219 '}',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391220 ], old_contents=[
Yoland Yanb92fa522017-08-28 17:37:061221 'public class Test extends BaseCaseB {',
1222 '}',
1223 ]),
1224 MockAffectedFile('CorrectTestWithInterface.java', [
1225 '@RunWith(ABC.class);'
1226 'public class CorrectTest implement Interface {',
1227 '}',
1228 ]),
1229 MockAffectedFile('IncorrectTest.java', [
1230 'public class IncorrectTest extends TestCase {',
1231 '}',
1232 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241233 MockAffectedFile('IncorrectWithInterfaceTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061234 'public class Test implements X extends BaseClass {',
1235 '}',
1236 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241237 MockAffectedFile('IncorrectMultiLineTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061238 'public class Test implements X, Y, Z',
1239 ' extends TestBase {',
1240 '}',
1241 ]),
1242 ]
1243 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1244 mock_input_api, mock_output_api)
1245 self.assertEqual(1, len(msgs),
1246 'Expected %d items, found %d: %s'
1247 % (1, len(msgs), msgs))
1248 self.assertEqual(3, len(msgs[0].items),
1249 'Expected %d items, found %d: %s'
1250 % (3, len(msgs[0].items), msgs[0].items))
1251 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1252 'IncorrectTest not found in errors')
Vaclav Brozekf01ed502018-03-16 19:38:241253 self.assertTrue('IncorrectWithInterfaceTest.java:1'
Yoland Yanb92fa522017-08-28 17:37:061254 in msgs[0].items,
Vaclav Brozekf01ed502018-03-16 19:38:241255 'IncorrectWithInterfaceTest not found in errors')
1256 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1257 'IncorrectMultiLineTest not found in errors')
yolandyan45001472016-12-21 21:12:421258
Jinsong Fan91ebbbd2019-04-16 14:57:171259class AndroidDebuggableBuildTest(unittest.TestCase):
1260
1261 def testCheckAndroidDebuggableBuild(self):
1262 mock_input_api = MockInputApi()
1263 mock_output_api = MockOutputApi()
1264
1265 mock_input_api.files = [
1266 MockAffectedFile('RandomStuff.java', [
1267 'random stuff'
1268 ]),
1269 MockAffectedFile('CorrectUsage.java', [
1270 'import org.chromium.base.BuildInfo;',
1271 'some random stuff',
1272 'boolean isOsDebuggable = BuildInfo.isDebugAndroid();',
1273 ]),
1274 MockAffectedFile('JustCheckUserdebugBuild.java', [
1275 'import android.os.Build;',
1276 'some random stuff',
1277 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")',
1278 ]),
1279 MockAffectedFile('JustCheckEngineeringBuild.java', [
1280 'import android.os.Build;',
1281 'some random stuff',
1282 'boolean isOsDebuggable = "eng".equals(Build.TYPE)',
1283 ]),
1284 MockAffectedFile('UsedBuildType.java', [
1285 'import android.os.Build;',
1286 'some random stuff',
1287 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")'
1288 '|| "eng".equals(Build.TYPE)',
1289 ]),
1290 MockAffectedFile('UsedExplicitBuildType.java', [
1291 'some random stuff',
1292 'boolean isOsDebuggable = android.os.Build.TYPE.equals("userdebug")'
1293 '|| "eng".equals(android.os.Build.TYPE)',
1294 ]),
1295 ]
1296
1297 msgs = PRESUBMIT._CheckAndroidDebuggableBuild(
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('JustCheckUserdebugBuild.java:3' in msgs[0].items)
1306 self.assertTrue('JustCheckEngineeringBuild.java:3' in msgs[0].items)
1307 self.assertTrue('UsedBuildType.java:3' in msgs[0].items)
1308 self.assertTrue('UsedExplicitBuildType.java:2' in msgs[0].items)
1309
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391310
dgn4401aa52015-04-29 16:26:171311class LogUsageTest(unittest.TestCase):
1312
dgnaa68d5e2015-06-10 10:08:221313 def testCheckAndroidCrLogUsage(self):
1314 mock_input_api = MockInputApi()
1315 mock_output_api = MockOutputApi()
1316
1317 mock_input_api.files = [
1318 MockAffectedFile('RandomStuff.java', [
1319 'random stuff'
1320 ]),
dgn87d9fb62015-06-12 09:15:121321 MockAffectedFile('HasAndroidLog.java', [
1322 'import android.util.Log;',
1323 'some random stuff',
1324 'Log.d("TAG", "foo");',
1325 ]),
1326 MockAffectedFile('HasExplicitUtilLog.java', [
1327 'some random stuff',
1328 'android.util.Log.d("TAG", "foo");',
1329 ]),
1330 MockAffectedFile('IsInBasePackage.java', [
1331 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511332 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121333 'Log.d(TAG, "foo");',
1334 ]),
1335 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1336 'package org.chromium.base;',
1337 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511338 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121339 'Log.d(TAG, "foo");',
1340 ]),
1341 MockAffectedFile('HasBothLog.java', [
1342 'import org.chromium.base.Log;',
1343 'some random stuff',
dgn38736db2015-09-18 19:20:511344 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121345 'Log.d(TAG, "foo");',
1346 'android.util.Log.d("TAG", "foo");',
1347 ]),
dgnaa68d5e2015-06-10 10:08:221348 MockAffectedFile('HasCorrectTag.java', [
1349 'import org.chromium.base.Log;',
1350 'some random stuff',
dgn38736db2015-09-18 19:20:511351 'private static final String TAG = "cr_Foo";',
1352 'Log.d(TAG, "foo");',
1353 ]),
1354 MockAffectedFile('HasOldTag.java', [
1355 'import org.chromium.base.Log;',
1356 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221357 'private static final String TAG = "cr.Foo";',
1358 'Log.d(TAG, "foo");',
1359 ]),
dgn38736db2015-09-18 19:20:511360 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221361 'import org.chromium.base.Log;',
1362 'some random stuff',
dgn38736db2015-09-18 19:20:511363 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221364 'Log.d(TAG, "foo");',
1365 ]),
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461366 MockAffectedFile('HasDottedTagPublic.java', [
1367 'import org.chromium.base.Log;',
1368 'some random stuff',
1369 'public static final String TAG = "cr_foo.bar";',
1370 'Log.d(TAG, "foo");',
1371 ]),
dgnaa68d5e2015-06-10 10:08:221372 MockAffectedFile('HasNoTagDecl.java', [
1373 'import org.chromium.base.Log;',
1374 'some random stuff',
1375 'Log.d(TAG, "foo");',
1376 ]),
1377 MockAffectedFile('HasIncorrectTagDecl.java', [
1378 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511379 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221380 'some random stuff',
1381 'Log.d(TAG, "foo");',
1382 ]),
1383 MockAffectedFile('HasInlineTag.java', [
1384 'import org.chromium.base.Log;',
1385 'some random stuff',
dgn38736db2015-09-18 19:20:511386 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221387 'Log.d("TAG", "foo");',
1388 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551389 MockAffectedFile('HasInlineTagWithSpace.java', [
1390 'import org.chromium.base.Log;',
1391 'some random stuff',
1392 'private static final String TAG = "cr_Foo";',
1393 'Log.d("log message", "foo");',
1394 ]),
dgn38736db2015-09-18 19:20:511395 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221396 'import org.chromium.base.Log;',
1397 'some random stuff',
1398 'private static final String TAG = "rubbish";',
1399 'Log.d(TAG, "foo");',
1400 ]),
1401 MockAffectedFile('HasTooLongTag.java', [
1402 'import org.chromium.base.Log;',
1403 'some random stuff',
dgn38736db2015-09-18 19:20:511404 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:221405 'Log.d(TAG, "foo");',
1406 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551407 MockAffectedFile('HasTooLongTagWithNoLogCallsInDiff.java', [
1408 'import org.chromium.base.Log;',
1409 'some random stuff',
1410 'private static final String TAG = "21_charachers_long___";',
1411 ]),
dgnaa68d5e2015-06-10 10:08:221412 ]
1413
1414 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1415 mock_input_api, mock_output_api)
1416
dgn38736db2015-09-18 19:20:511417 self.assertEqual(5, len(msgs),
1418 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221419
1420 # Declaration format
dgn38736db2015-09-18 19:20:511421 nb = len(msgs[0].items)
1422 self.assertEqual(2, nb,
1423 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221424 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1425 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221426
1427 # Tag length
dgn38736db2015-09-18 19:20:511428 nb = len(msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551429 self.assertEqual(2, nb,
1430 'Expected %d items, found %d: %s' % (2, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:221431 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551432 self.assertTrue('HasTooLongTagWithNoLogCallsInDiff.java' in msgs[1].items)
dgnaa68d5e2015-06-10 10:08:221433
1434 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511435 nb = len(msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551436 self.assertEqual(3, nb,
1437 'Expected %d items, found %d: %s' % (3, nb, msgs[2].items))
1438 self.assertTrue('HasBothLog.java:5' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221439 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551440 self.assertTrue('HasInlineTagWithSpace.java:4' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221441
dgn87d9fb62015-06-12 09:15:121442 # Util Log usage
dgn38736db2015-09-18 19:20:511443 nb = len(msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551444 self.assertEqual(3, nb,
1445 'Expected %d items, found %d: %s' % (3, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:121446 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551447 self.assertTrue('HasExplicitUtilLog.java:2' in msgs[3].items)
dgn87d9fb62015-06-12 09:15:121448 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:221449
dgn38736db2015-09-18 19:20:511450 # Tag must not contain
1451 nb = len(msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461452 self.assertEqual(3, nb,
dgn38736db2015-09-18 19:20:511453 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1454 self.assertTrue('HasDottedTag.java' in msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461455 self.assertTrue('HasDottedTagPublic.java' in msgs[4].items)
dgn38736db2015-09-18 19:20:511456 self.assertTrue('HasOldTag.java' in msgs[4].items)
1457
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391458
estadee17314a02017-01-12 16:22:161459class GoogleAnswerUrlFormatTest(unittest.TestCase):
1460
1461 def testCatchAnswerUrlId(self):
1462 input_api = MockInputApi()
1463 input_api.files = [
1464 MockFile('somewhere/file.cc',
1465 ['char* host = '
1466 ' "https://support.google.com/chrome/answer/123456";']),
1467 MockFile('somewhere_else/file.cc',
1468 ['char* host = '
1469 ' "https://support.google.com/chrome/a/answer/123456";']),
1470 ]
1471
Saagar Sanghavifceeaae2020-08-12 16:40:361472 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161473 input_api, MockOutputApi())
1474 self.assertEqual(1, len(warnings))
1475 self.assertEqual(2, len(warnings[0].items))
1476
1477 def testAllowAnswerUrlParam(self):
1478 input_api = MockInputApi()
1479 input_api.files = [
1480 MockFile('somewhere/file.cc',
1481 ['char* host = '
1482 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1483 ]
1484
Saagar Sanghavifceeaae2020-08-12 16:40:361485 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161486 input_api, MockOutputApi())
1487 self.assertEqual(0, len(warnings))
1488
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391489
reillyi38965732015-11-16 18:27:331490class HardcodedGoogleHostsTest(unittest.TestCase):
1491
1492 def testWarnOnAssignedLiterals(self):
1493 input_api = MockInputApi()
1494 input_api.files = [
1495 MockFile('content/file.cc',
1496 ['char* host = "https://www.google.com";']),
1497 MockFile('content/file.cc',
1498 ['char* host = "https://www.googleapis.com";']),
1499 MockFile('content/file.cc',
1500 ['char* host = "https://clients1.google.com";']),
1501 ]
1502
Saagar Sanghavifceeaae2020-08-12 16:40:361503 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331504 input_api, MockOutputApi())
1505 self.assertEqual(1, len(warnings))
1506 self.assertEqual(3, len(warnings[0].items))
1507
1508 def testAllowInComment(self):
1509 input_api = MockInputApi()
1510 input_api.files = [
1511 MockFile('content/file.cc',
1512 ['char* host = "https://www.aol.com"; // google.com'])
1513 ]
1514
Saagar Sanghavifceeaae2020-08-12 16:40:361515 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331516 input_api, MockOutputApi())
1517 self.assertEqual(0, len(warnings))
1518
dgn4401aa52015-04-29 16:26:171519
James Cook6b6597c2019-11-06 22:05:291520class ChromeOsSyncedPrefRegistrationTest(unittest.TestCase):
1521
1522 def testWarnsOnChromeOsDirectories(self):
1523 input_api = MockInputApi()
1524 input_api.files = [
1525 MockFile('ash/file.cc',
1526 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1527 MockFile('chrome/browser/chromeos/file.cc',
1528 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1529 MockFile('chromeos/file.cc',
1530 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1531 MockFile('components/arc/file.cc',
1532 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1533 MockFile('components/exo/file.cc',
1534 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1535 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361536 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291537 input_api, MockOutputApi())
1538 self.assertEqual(1, len(warnings))
1539
1540 def testDoesNotWarnOnSyncOsPref(self):
1541 input_api = MockInputApi()
1542 input_api.files = [
1543 MockFile('chromeos/file.cc',
1544 ['PrefRegistrySyncable::SYNCABLE_OS_PREF']),
1545 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361546 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291547 input_api, MockOutputApi())
1548 self.assertEqual(0, len(warnings))
1549
1550 def testDoesNotWarnOnCrossPlatformDirectories(self):
1551 input_api = MockInputApi()
1552 input_api.files = [
1553 MockFile('chrome/browser/ui/file.cc',
1554 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1555 MockFile('components/sync/file.cc',
1556 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1557 MockFile('content/browser/file.cc',
1558 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1559 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361560 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291561 input_api, MockOutputApi())
1562 self.assertEqual(0, len(warnings))
1563
1564 def testSeparateWarningForPriorityPrefs(self):
1565 input_api = MockInputApi()
1566 input_api.files = [
1567 MockFile('chromeos/file.cc',
1568 ['PrefRegistrySyncable::SYNCABLE_PREF',
1569 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']),
1570 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361571 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291572 input_api, MockOutputApi())
1573 self.assertEqual(2, len(warnings))
1574
1575
jbriance9e12f162016-11-25 07:57:501576class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311577 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501578 mock_input_api = MockInputApi()
1579 mock_input_api.files = [
1580 MockAffectedFile('somewhere/file.cc', [
1581 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311582 ]),
1583 MockAffectedFile('third_party/header.h', [
1584 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501585 ])
1586 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361587 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391588 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501589 self.assertEqual(0, len(warnings))
1590
1591 def testNoNestedDeclaration(self):
1592 mock_input_api = MockInputApi()
1593 mock_input_api.files = [
1594 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311595 'class SomeClass {',
1596 ' protected:',
1597 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501598 '};'
1599 ])
1600 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361601 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391602 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501603 self.assertEqual(0, len(warnings))
1604
1605 def testSubStrings(self):
1606 mock_input_api = MockInputApi()
1607 mock_input_api.files = [
1608 MockAffectedFile('somewhere/header.h', [
1609 'class NotUsefulClass;',
1610 'struct SomeStruct;',
1611 'UsefulClass *p1;',
1612 'SomeStructPtr *p2;'
1613 ])
1614 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361615 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391616 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501617 self.assertEqual(2, len(warnings))
1618
1619 def testUselessForwardDeclaration(self):
1620 mock_input_api = MockInputApi()
1621 mock_input_api.files = [
1622 MockAffectedFile('somewhere/header.h', [
1623 'class DummyClass;',
1624 'struct DummyStruct;',
1625 'class UsefulClass;',
1626 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311627 ])
jbriance9e12f162016-11-25 07:57:501628 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361629 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391630 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501631 self.assertEqual(2, len(warnings))
1632
jbriance2c51e821a2016-12-12 08:24:311633 def testBlinkHeaders(self):
1634 mock_input_api = MockInputApi()
1635 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491636 MockAffectedFile('third_party/blink/header.h', [
jbriance2c51e821a2016-12-12 08:24:311637 'class DummyClass;',
1638 'struct DummyStruct;',
1639 ]),
Kent Tamura32dbbcb2018-11-30 12:28:491640 MockAffectedFile('third_party\\blink\\header.h', [
jbriance2c51e821a2016-12-12 08:24:311641 'class DummyClass;',
1642 'struct DummyStruct;',
1643 ])
1644 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361645 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391646 MockOutputApi())
jbriance2c51e821a2016-12-12 08:24:311647 self.assertEqual(4, len(warnings))
1648
jbriance9e12f162016-11-25 07:57:501649
rlanday6802cf632017-05-30 17:48:361650class RelativeIncludesTest(unittest.TestCase):
1651 def testThirdPartyNotWebKitIgnored(self):
1652 mock_input_api = MockInputApi()
1653 mock_input_api.files = [
1654 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1655 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1656 ]
1657
1658 mock_output_api = MockOutputApi()
1659
Saagar Sanghavifceeaae2020-08-12 16:40:361660 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361661 mock_input_api, mock_output_api)
1662 self.assertEqual(0, len(errors))
1663
1664 def testNonCppFileIgnored(self):
1665 mock_input_api = MockInputApi()
1666 mock_input_api.files = [
1667 MockAffectedFile('test.py', '#include "../header.h"'),
1668 ]
1669
1670 mock_output_api = MockOutputApi()
1671
Saagar Sanghavifceeaae2020-08-12 16:40:361672 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361673 mock_input_api, mock_output_api)
1674 self.assertEqual(0, len(errors))
1675
1676 def testInnocuousChangesAllowed(self):
1677 mock_input_api = MockInputApi()
1678 mock_input_api.files = [
1679 MockAffectedFile('test.cpp', '#include "header.h"'),
1680 MockAffectedFile('test2.cpp', '../'),
1681 ]
1682
1683 mock_output_api = MockOutputApi()
1684
Saagar Sanghavifceeaae2020-08-12 16:40:361685 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361686 mock_input_api, mock_output_api)
1687 self.assertEqual(0, len(errors))
1688
1689 def testRelativeIncludeNonWebKitProducesError(self):
1690 mock_input_api = MockInputApi()
1691 mock_input_api.files = [
1692 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1693 ]
1694
1695 mock_output_api = MockOutputApi()
1696
Saagar Sanghavifceeaae2020-08-12 16:40:361697 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361698 mock_input_api, mock_output_api)
1699 self.assertEqual(1, len(errors))
1700
1701 def testRelativeIncludeWebKitProducesError(self):
1702 mock_input_api = MockInputApi()
1703 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491704 MockAffectedFile('third_party/blink/test.cpp',
rlanday6802cf632017-05-30 17:48:361705 ['#include "../header.h']),
1706 ]
1707
1708 mock_output_api = MockOutputApi()
1709
Saagar Sanghavifceeaae2020-08-12 16:40:361710 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361711 mock_input_api, mock_output_api)
1712 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241713
Daniel Cheng13ca61a882017-08-25 15:11:251714
Daniel Bratell65b033262019-04-23 08:17:061715class CCIncludeTest(unittest.TestCase):
1716 def testThirdPartyNotBlinkIgnored(self):
1717 mock_input_api = MockInputApi()
1718 mock_input_api.files = [
1719 MockAffectedFile('third_party/test.cpp', '#include "file.cc"'),
1720 ]
1721
1722 mock_output_api = MockOutputApi()
1723
Saagar Sanghavifceeaae2020-08-12 16:40:361724 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061725 mock_input_api, mock_output_api)
1726 self.assertEqual(0, len(errors))
1727
1728 def testPythonFileIgnored(self):
1729 mock_input_api = MockInputApi()
1730 mock_input_api.files = [
1731 MockAffectedFile('test.py', '#include "file.cc"'),
1732 ]
1733
1734 mock_output_api = MockOutputApi()
1735
Saagar Sanghavifceeaae2020-08-12 16:40:361736 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061737 mock_input_api, mock_output_api)
1738 self.assertEqual(0, len(errors))
1739
1740 def testIncFilesAccepted(self):
1741 mock_input_api = MockInputApi()
1742 mock_input_api.files = [
1743 MockAffectedFile('test.py', '#include "file.inc"'),
1744 ]
1745
1746 mock_output_api = MockOutputApi()
1747
Saagar Sanghavifceeaae2020-08-12 16:40:361748 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061749 mock_input_api, mock_output_api)
1750 self.assertEqual(0, len(errors))
1751
1752 def testInnocuousChangesAllowed(self):
1753 mock_input_api = MockInputApi()
1754 mock_input_api.files = [
1755 MockAffectedFile('test.cpp', '#include "header.h"'),
1756 MockAffectedFile('test2.cpp', 'Something "file.cc"'),
1757 ]
1758
1759 mock_output_api = MockOutputApi()
1760
Saagar Sanghavifceeaae2020-08-12 16:40:361761 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061762 mock_input_api, mock_output_api)
1763 self.assertEqual(0, len(errors))
1764
1765 def testCcIncludeNonBlinkProducesError(self):
1766 mock_input_api = MockInputApi()
1767 mock_input_api.files = [
1768 MockAffectedFile('test.cpp', ['#include "file.cc"']),
1769 ]
1770
1771 mock_output_api = MockOutputApi()
1772
Saagar Sanghavifceeaae2020-08-12 16:40:361773 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061774 mock_input_api, mock_output_api)
1775 self.assertEqual(1, len(errors))
1776
1777 def testCppIncludeBlinkProducesError(self):
1778 mock_input_api = MockInputApi()
1779 mock_input_api.files = [
1780 MockAffectedFile('third_party/blink/test.cpp',
1781 ['#include "foo/file.cpp"']),
1782 ]
1783
1784 mock_output_api = MockOutputApi()
1785
Saagar Sanghavifceeaae2020-08-12 16:40:361786 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061787 mock_input_api, mock_output_api)
1788 self.assertEqual(1, len(errors))
1789
1790
Andrew Grieve1b290e4a22020-11-24 20:07:011791class GnGlobForwardTest(unittest.TestCase):
1792 def testAddBareGlobs(self):
1793 mock_input_api = MockInputApi()
1794 mock_input_api.files = [
1795 MockAffectedFile('base/stuff.gni', [
1796 'forward_variables_from(invoker, "*")']),
1797 MockAffectedFile('base/BUILD.gn', [
1798 'forward_variables_from(invoker, "*")']),
1799 ]
1800 warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
1801 self.assertEqual(1, len(warnings))
1802 msg = '\n'.join(warnings[0].items)
1803 self.assertIn('base/stuff.gni', msg)
1804 # Should not check .gn files. Local templates don't need to care about
1805 # visibility / testonly.
1806 self.assertNotIn('base/BUILD.gn', msg)
1807
1808 def testValidUses(self):
1809 mock_input_api = MockInputApi()
1810 mock_input_api.files = [
1811 MockAffectedFile('base/stuff.gni', [
1812 'forward_variables_from(invoker, "*", [])']),
1813 MockAffectedFile('base/stuff2.gni', [
1814 'forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)']),
1815 MockAffectedFile('base/stuff3.gni', [
1816 'forward_variables_from(invoker, [ "testonly" ])']),
1817 ]
1818 warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
1819 self.assertEqual([], warnings)
1820
1821
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191822class NewHeaderWithoutGnChangeTest(unittest.TestCase):
1823 def testAddHeaderWithoutGn(self):
1824 mock_input_api = MockInputApi()
1825 mock_input_api.files = [
1826 MockAffectedFile('base/stuff.h', ''),
1827 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361828 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191829 mock_input_api, MockOutputApi())
1830 self.assertEqual(1, len(warnings))
1831 self.assertTrue('base/stuff.h' in warnings[0].items)
1832
1833 def testModifyHeader(self):
1834 mock_input_api = MockInputApi()
1835 mock_input_api.files = [
1836 MockAffectedFile('base/stuff.h', '', action='M'),
1837 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361838 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191839 mock_input_api, MockOutputApi())
1840 self.assertEqual(0, len(warnings))
1841
1842 def testDeleteHeader(self):
1843 mock_input_api = MockInputApi()
1844 mock_input_api.files = [
1845 MockAffectedFile('base/stuff.h', '', action='D'),
1846 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361847 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191848 mock_input_api, MockOutputApi())
1849 self.assertEqual(0, len(warnings))
1850
1851 def testAddHeaderWithGn(self):
1852 mock_input_api = MockInputApi()
1853 mock_input_api.files = [
1854 MockAffectedFile('base/stuff.h', ''),
1855 MockAffectedFile('base/BUILD.gn', 'stuff.h'),
1856 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361857 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191858 mock_input_api, MockOutputApi())
1859 self.assertEqual(0, len(warnings))
1860
1861 def testAddHeaderWithGni(self):
1862 mock_input_api = MockInputApi()
1863 mock_input_api.files = [
1864 MockAffectedFile('base/stuff.h', ''),
1865 MockAffectedFile('base/files.gni', 'stuff.h'),
1866 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361867 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191868 mock_input_api, MockOutputApi())
1869 self.assertEqual(0, len(warnings))
1870
1871 def testAddHeaderWithOther(self):
1872 mock_input_api = MockInputApi()
1873 mock_input_api.files = [
1874 MockAffectedFile('base/stuff.h', ''),
1875 MockAffectedFile('base/stuff.cc', 'stuff.h'),
1876 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361877 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191878 mock_input_api, MockOutputApi())
1879 self.assertEqual(1, len(warnings))
1880
1881 def testAddHeaderWithWrongGn(self):
1882 mock_input_api = MockInputApi()
1883 mock_input_api.files = [
1884 MockAffectedFile('base/stuff.h', ''),
1885 MockAffectedFile('base/BUILD.gn', 'stuff_h'),
1886 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361887 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191888 mock_input_api, MockOutputApi())
1889 self.assertEqual(1, len(warnings))
1890
1891 def testAddHeadersWithGn(self):
1892 mock_input_api = MockInputApi()
1893 mock_input_api.files = [
1894 MockAffectedFile('base/stuff.h', ''),
1895 MockAffectedFile('base/another.h', ''),
1896 MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'),
1897 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361898 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191899 mock_input_api, MockOutputApi())
1900 self.assertEqual(0, len(warnings))
1901
1902 def testAddHeadersWithWrongGn(self):
1903 mock_input_api = MockInputApi()
1904 mock_input_api.files = [
1905 MockAffectedFile('base/stuff.h', ''),
1906 MockAffectedFile('base/another.h', ''),
1907 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'),
1908 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361909 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191910 mock_input_api, MockOutputApi())
1911 self.assertEqual(1, len(warnings))
1912 self.assertFalse('base/stuff.h' in warnings[0].items)
1913 self.assertTrue('base/another.h' in warnings[0].items)
1914
1915 def testAddHeadersWithWrongGn2(self):
1916 mock_input_api = MockInputApi()
1917 mock_input_api.files = [
1918 MockAffectedFile('base/stuff.h', ''),
1919 MockAffectedFile('base/another.h', ''),
1920 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'),
1921 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361922 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191923 mock_input_api, MockOutputApi())
1924 self.assertEqual(1, len(warnings))
1925 self.assertTrue('base/stuff.h' in warnings[0].items)
1926 self.assertTrue('base/another.h' in warnings[0].items)
1927
1928
Michael Giuffridad3bc8672018-10-25 22:48:021929class CorrectProductNameInMessagesTest(unittest.TestCase):
1930 def testProductNameInDesc(self):
1931 mock_input_api = MockInputApi()
1932 mock_input_api.files = [
1933 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1934 '<message name="Foo" desc="Welcome to Chrome">',
1935 ' Welcome to Chrome!',
1936 '</message>',
1937 ]),
1938 MockAffectedFile('chrome/app/chromium_strings.grd', [
1939 '<message name="Bar" desc="Welcome to Chrome">',
1940 ' Welcome to Chromium!',
1941 '</message>',
1942 ]),
1943 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361944 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021945 mock_input_api, MockOutputApi())
1946 self.assertEqual(0, len(warnings))
1947
1948 def testChromeInChromium(self):
1949 mock_input_api = MockInputApi()
1950 mock_input_api.files = [
1951 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1952 '<message name="Foo" desc="Welcome to Chrome">',
1953 ' Welcome to Chrome!',
1954 '</message>',
1955 ]),
1956 MockAffectedFile('chrome/app/chromium_strings.grd', [
1957 '<message name="Bar" desc="Welcome to Chrome">',
1958 ' Welcome to Chrome!',
1959 '</message>',
1960 ]),
1961 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361962 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021963 mock_input_api, MockOutputApi())
1964 self.assertEqual(1, len(warnings))
1965 self.assertTrue('chrome/app/chromium_strings.grd' in warnings[0].items[0])
1966
1967 def testChromiumInChrome(self):
1968 mock_input_api = MockInputApi()
1969 mock_input_api.files = [
1970 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1971 '<message name="Foo" desc="Welcome to Chrome">',
1972 ' Welcome to Chromium!',
1973 '</message>',
1974 ]),
1975 MockAffectedFile('chrome/app/chromium_strings.grd', [
1976 '<message name="Bar" desc="Welcome to Chrome">',
1977 ' Welcome to Chromium!',
1978 '</message>',
1979 ]),
1980 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361981 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021982 mock_input_api, MockOutputApi())
1983 self.assertEqual(1, len(warnings))
1984 self.assertTrue(
1985 'chrome/app/google_chrome_strings.grd:2' in warnings[0].items[0])
1986
1987 def testMultipleInstances(self):
1988 mock_input_api = MockInputApi()
1989 mock_input_api.files = [
1990 MockAffectedFile('chrome/app/chromium_strings.grd', [
1991 '<message name="Bar" desc="Welcome to Chrome">',
1992 ' Welcome to Chrome!',
1993 '</message>',
1994 '<message name="Baz" desc="A correct message">',
1995 ' Chromium is the software you are using.',
1996 '</message>',
1997 '<message name="Bat" desc="An incorrect message">',
1998 ' Google Chrome is the software you are using.',
1999 '</message>',
2000 ]),
2001 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362002 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022003 mock_input_api, MockOutputApi())
2004 self.assertEqual(1, len(warnings))
2005 self.assertTrue(
2006 'chrome/app/chromium_strings.grd:2' in warnings[0].items[0])
2007 self.assertTrue(
2008 'chrome/app/chromium_strings.grd:8' in warnings[0].items[1])
2009
2010 def testMultipleWarnings(self):
2011 mock_input_api = MockInputApi()
2012 mock_input_api.files = [
2013 MockAffectedFile('chrome/app/chromium_strings.grd', [
2014 '<message name="Bar" desc="Welcome to Chrome">',
2015 ' Welcome to Chrome!',
2016 '</message>',
2017 '<message name="Baz" desc="A correct message">',
2018 ' Chromium is the software you are using.',
2019 '</message>',
2020 '<message name="Bat" desc="An incorrect message">',
2021 ' Google Chrome is the software you are using.',
2022 '</message>',
2023 ]),
2024 MockAffectedFile('components/components_google_chrome_strings.grd', [
2025 '<message name="Bar" desc="Welcome to Chrome">',
2026 ' Welcome to Chrome!',
2027 '</message>',
2028 '<message name="Baz" desc="A correct message">',
2029 ' Chromium is the software you are using.',
2030 '</message>',
2031 '<message name="Bat" desc="An incorrect message">',
2032 ' Google Chrome is the software you are using.',
2033 '</message>',
2034 ]),
2035 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362036 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022037 mock_input_api, MockOutputApi())
2038 self.assertEqual(2, len(warnings))
2039 self.assertTrue(
2040 'components/components_google_chrome_strings.grd:5'
2041 in warnings[0].items[0])
2042 self.assertTrue(
2043 'chrome/app/chromium_strings.grd:2' in warnings[1].items[0])
2044 self.assertTrue(
2045 'chrome/app/chromium_strings.grd:8' in warnings[1].items[1])
2046
2047
Ken Rockot9f668262018-12-21 18:56:362048class ServiceManifestOwnerTest(unittest.TestCase):
Ken Rockot9f668262018-12-21 18:56:362049 def testServiceManifestChangeNeedsSecurityOwner(self):
2050 mock_input_api = MockInputApi()
2051 mock_input_api.files = [
2052 MockAffectedFile('services/goat/public/cpp/manifest.cc',
2053 [
2054 '#include "services/goat/public/cpp/manifest.h"',
2055 'const service_manager::Manifest& GetManifest() {}',
2056 ])]
2057 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362058 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362059 mock_input_api, mock_output_api)
2060 self.assertEqual(1, len(errors))
2061 self.assertEqual(
2062 'Found OWNERS files that need to be updated for IPC security review ' +
2063 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2064
2065 def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
2066 mock_input_api = MockInputApi()
2067 mock_input_api.files = [
2068 MockAffectedFile('some/non/service/thing/foo_manifest.cc',
2069 [
2070 'const char kNoEnforcement[] = "not a manifest!";',
2071 ])]
2072 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362073 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032074 mock_input_api, mock_output_api)
2075 self.assertEqual([], errors)
2076
2077
2078class FuchsiaSecurityOwnerTest(unittest.TestCase):
2079 def testFidlChangeNeedsSecurityOwner(self):
2080 mock_input_api = MockInputApi()
2081 mock_input_api.files = [
2082 MockAffectedFile('potentially/scary/ipc.fidl',
2083 [
2084 'library test.fidl'
2085 ])]
2086 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362087 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032088 mock_input_api, mock_output_api)
2089 self.assertEqual(1, len(errors))
2090 self.assertEqual(
2091 'Found OWNERS files that need to be updated for IPC security review ' +
2092 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2093
2094 def testComponentManifestV1ChangeNeedsSecurityOwner(self):
2095 mock_input_api = MockInputApi()
2096 mock_input_api.files = [
2097 MockAffectedFile('potentially/scary/v2_manifest.cmx',
2098 [
2099 '{ "that is no": "manifest!" }'
2100 ])]
2101 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362102 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032103 mock_input_api, mock_output_api)
2104 self.assertEqual(1, len(errors))
2105 self.assertEqual(
2106 'Found OWNERS files that need to be updated for IPC security review ' +
2107 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2108
2109 def testComponentManifestV2NeedsSecurityOwner(self):
2110 mock_input_api = MockInputApi()
2111 mock_input_api.files = [
2112 MockAffectedFile('potentially/scary/v2_manifest.cml',
2113 [
2114 '{ "that is no": "manifest!" }'
2115 ])]
2116 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362117 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032118 mock_input_api, mock_output_api)
2119 self.assertEqual(1, len(errors))
2120 self.assertEqual(
2121 'Found OWNERS files that need to be updated for IPC security review ' +
2122 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2123
Joshua Peraza1ca6d392020-12-08 00:14:092124 def testThirdPartyTestsDoNotRequireSecurityOwner(self):
2125 mock_input_api = MockInputApi()
2126 mock_input_api.files = [
2127 MockAffectedFile('third_party/crashpad/test/tests.cmx',
2128 [
2129 'const char kNoEnforcement[] = "Security?!? Pah!";',
2130 ])]
2131 mock_output_api = MockOutputApi()
2132 errors = PRESUBMIT.CheckSecurityOwners(
2133 mock_input_api, mock_output_api)
2134 self.assertEqual([], errors)
2135
Wez17c66962020-04-29 15:26:032136 def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2137 mock_input_api = MockInputApi()
2138 mock_input_api.files = [
2139 MockAffectedFile('some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',
2140 [
2141 'const char kNoEnforcement[] = "Security?!? Pah!";',
2142 ])]
2143 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362144 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362145 mock_input_api, mock_output_api)
2146 self.assertEqual([], errors)
2147
Daniel Cheng13ca61a882017-08-25 15:11:252148
Robert Sesek2c905332020-05-06 23:17:132149class SecurityChangeTest(unittest.TestCase):
Edward Lesmes1e9fade2021-02-08 20:31:122150 class _MockOwnersClient(object):
2151 def ListOwners(self, f):
Robert Sesek2c905332020-05-06 23:17:132152 return ['[email protected]', '[email protected]']
2153
2154 def _mockChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2155 def __MockOwnerAndReviewers(input_api, email_regexp, approval_needed=False):
2156 return [owner, reviewers]
2157 input_api.canned_checks.GetCodereviewOwnerAndReviewers = \
2158 __MockOwnerAndReviewers
2159
Alex Goughbc964dd2020-06-15 17:52:372160 def testDiffGetServiceSandboxType(self):
Robert Sesek2c905332020-05-06 23:17:132161 mock_input_api = MockInputApi()
2162 mock_input_api.files = [
2163 MockAffectedFile(
2164 'services/goat/teleporter_host.cc',
2165 [
Alex Goughbc964dd2020-06-15 17:52:372166 'template <>',
2167 'inline content::SandboxType',
2168 'content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {',
2169 '#if defined(OS_WIN)',
2170 ' return SandboxType::kGoaty;',
2171 '#else',
2172 ' return SandboxType::kNoSandbox;',
2173 '#endif // !defined(OS_WIN)',
2174 '}'
Robert Sesek2c905332020-05-06 23:17:132175 ]
2176 ),
2177 ]
2178 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2179 mock_input_api)
2180 self.assertEqual({
2181 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372182 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132183 ])},
2184 files_to_functions)
2185
2186 def testDiffRemovingLine(self):
2187 mock_input_api = MockInputApi()
2188 mock_file = MockAffectedFile('services/goat/teleporter_host.cc', '')
2189 mock_file._scm_diff = """--- old 2020-05-04 14:08:25.000000000 -0400
2190+++ new 2020-05-04 14:08:32.000000000 -0400
2191@@ -1,5 +1,4 @@
Alex Goughbc964dd2020-06-15 17:52:372192 template <>
2193 inline content::SandboxType
2194-content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {
2195 #if defined(OS_WIN)
2196 return SandboxType::kGoaty;
Robert Sesek2c905332020-05-06 23:17:132197"""
2198 mock_input_api.files = [mock_file]
2199 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2200 mock_input_api)
2201 self.assertEqual({
2202 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372203 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132204 ])},
2205 files_to_functions)
2206
2207 def testChangeOwnersMissing(self):
2208 mock_input_api = MockInputApi()
Edward Lesmes1e9fade2021-02-08 20:31:122209 mock_input_api.owners_client = self._MockOwnersClient()
Robert Sesek2c905332020-05-06 23:17:132210 mock_input_api.is_committing = False
2211 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372212 MockAffectedFile('file.cc', ['GetServiceSandboxType<Goat>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132213 ]
2214 mock_output_api = MockOutputApi()
2215 self._mockChangeOwnerAndReviewers(
2216 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362217 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132218 self.assertEquals(1, len(result))
2219 self.assertEquals(result[0].type, 'notify')
2220 self.assertEquals(result[0].message,
2221 'The following files change calls to security-sensive functions\n' \
2222 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2223 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372224 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132225
2226 def testChangeOwnersMissingAtCommit(self):
2227 mock_input_api = MockInputApi()
Edward Lesmes1e9fade2021-02-08 20:31:122228 mock_input_api.owners_client = self._MockOwnersClient()
Robert Sesek2c905332020-05-06 23:17:132229 mock_input_api.is_committing = True
2230 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372231 MockAffectedFile('file.cc', ['GetServiceSandboxType<mojom::Goat>()'])
Robert Sesek2c905332020-05-06 23:17:132232 ]
2233 mock_output_api = MockOutputApi()
2234 self._mockChangeOwnerAndReviewers(
2235 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362236 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132237 self.assertEquals(1, len(result))
2238 self.assertEquals(result[0].type, 'error')
2239 self.assertEquals(result[0].message,
2240 'The following files change calls to security-sensive functions\n' \
2241 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2242 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372243 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132244
2245 def testChangeOwnersPresent(self):
2246 mock_input_api = MockInputApi()
Edward Lesmes1e9fade2021-02-08 20:31:122247 mock_input_api.owners_client = self._MockOwnersClient()
Robert Sesek2c905332020-05-06 23:17:132248 mock_input_api.files = [
2249 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2250 ]
2251 mock_output_api = MockOutputApi()
2252 self._mockChangeOwnerAndReviewers(
2253 mock_input_api, '[email protected]',
2254 ['[email protected]', '[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362255 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132256 self.assertEquals(0, len(result))
2257
2258 def testChangeOwnerIsSecurityOwner(self):
2259 mock_input_api = MockInputApi()
Edward Lesmes1e9fade2021-02-08 20:31:122260 mock_input_api.owners_client = self._MockOwnersClient()
Robert Sesek2c905332020-05-06 23:17:132261 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372262 MockAffectedFile('file.cc', ['GetServiceSandboxType<T>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132263 ]
2264 mock_output_api = MockOutputApi()
2265 self._mockChangeOwnerAndReviewers(
2266 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362267 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132268 self.assertEquals(1, len(result))
2269
2270
Mario Sanchez Prada2472cab2019-09-18 10:58:312271class BannedTypeCheckTest(unittest.TestCase):
Sylvain Defresnea8b73d252018-02-28 15:45:542272
Peter Kasting94a56c42019-10-25 21:54:042273 def testBannedCppFunctions(self):
2274 input_api = MockInputApi()
2275 input_api.files = [
2276 MockFile('some/cpp/problematic/file.cc',
2277 ['using namespace std;']),
Oksana Zhuravlovac8222d22019-12-19 19:21:162278 MockFile('third_party/blink/problematic/file.cc',
2279 ['GetInterfaceProvider()']),
Peter Kasting94a56c42019-10-25 21:54:042280 MockFile('some/cpp/ok/file.cc',
2281 ['using std::string;']),
Allen Bauer53b43fb12020-03-12 17:21:472282 MockFile('some/cpp/problematic/file2.cc',
2283 ['set_owned_by_client()']),
danakjd18e8892020-12-17 17:42:012284 MockFile('some/cpp/nocheck/file.cc',
2285 ['using namespace std; // nocheck']),
2286 MockFile('some/cpp/comment/file.cc',
2287 [' // A comment about `using namespace std;`']),
Peter Kasting94a56c42019-10-25 21:54:042288 ]
2289
Saagar Sanghavifceeaae2020-08-12 16:40:362290 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlovac8222d22019-12-19 19:21:162291
2292 # warnings are results[0], errors are results[1]
2293 self.assertEqual(2, len(results))
2294 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2295 self.assertTrue(
2296 'third_party/blink/problematic/file.cc' in results[0].message)
2297 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
Allen Bauer53b43fb12020-03-12 17:21:472298 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
danakjd18e8892020-12-17 17:42:012299 self.assertFalse('some/cpp/nocheck/file.cc' in results[0].message)
2300 self.assertFalse('some/cpp/nocheck/file.cc' in results[1].message)
2301 self.assertFalse('some/cpp/comment/file.cc' in results[0].message)
2302 self.assertFalse('some/cpp/comment/file.cc' in results[1].message)
Peter Kasting94a56c42019-10-25 21:54:042303
Peter K. Lee6c03ccff2019-07-15 14:40:052304 def testBannedIosObjcFunctions(self):
Sylvain Defresnea8b73d252018-02-28 15:45:542305 input_api = MockInputApi()
2306 input_api.files = [
2307 MockFile('some/ios/file.mm',
2308 ['TEST(SomeClassTest, SomeInteraction) {',
2309 '}']),
2310 MockFile('some/mac/file.mm',
2311 ['TEST(SomeClassTest, SomeInteraction) {',
2312 '}']),
2313 MockFile('another/ios_file.mm',
2314 ['class SomeTest : public testing::Test {};']),
Peter K. Lee6c03ccff2019-07-15 14:40:052315 MockFile('some/ios/file_egtest.mm',
2316 ['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
2317 MockFile('some/ios/file_unittest.mm',
2318 ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']),
Sylvain Defresnea8b73d252018-02-28 15:45:542319 ]
2320
Saagar Sanghavifceeaae2020-08-12 16:40:362321 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Sylvain Defresnea8b73d252018-02-28 15:45:542322 self.assertEqual(1, len(errors))
2323 self.assertTrue('some/ios/file.mm' in errors[0].message)
2324 self.assertTrue('another/ios_file.mm' in errors[0].message)
2325 self.assertTrue('some/mac/file.mm' not in errors[0].message)
Peter K. Lee6c03ccff2019-07-15 14:40:052326 self.assertTrue('some/ios/file_egtest.mm' in errors[0].message)
2327 self.assertTrue('some/ios/file_unittest.mm' not in errors[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542328
Carlos Knippschildab192b8c2019-04-08 20:02:382329 def testBannedMojoFunctions(self):
2330 input_api = MockInputApi()
2331 input_api.files = [
Oksana Zhuravlovafd247772019-05-16 16:57:292332 MockFile('some/cpp/problematic/file2.cc',
2333 ['mojo::ConvertTo<>']),
Oksana Zhuravlovafd247772019-05-16 16:57:292334 MockFile('third_party/blink/ok/file3.cc',
2335 ['mojo::ConvertTo<>']),
2336 MockFile('content/renderer/ok/file3.cc',
2337 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382338 ]
2339
Saagar Sanghavifceeaae2020-08-12 16:40:362340 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222341
2342 # warnings are results[0], errors are results[1]
Robert Sesek351d2d52021-02-02 01:47:072343 self.assertEqual(1, len(results))
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222344 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222345 self.assertTrue('third_party/blink/ok/file3.cc' not in results[0].message)
2346 self.assertTrue('content/renderer/ok/file3.cc' not in results[0].message)
Carlos Knippschildab192b8c2019-04-08 20:02:382347
Mario Sanchez Prada2472cab2019-09-18 10:58:312348 def testDeprecatedMojoTypes(self):
Mario Sanchez Pradacec9cef2019-12-15 11:54:572349 ok_paths = ['components/arc']
2350 warning_paths = ['some/cpp']
Mario Sanchez Pradaaab91382019-12-19 08:57:092351 error_paths = ['third_party/blink', 'content']
Mario Sanchez Prada2472cab2019-09-18 10:58:312352 test_cases = [
2353 {
2354 'type': 'mojo::AssociatedBinding<>;',
2355 'file': 'file1.c'
2356 },
2357 {
2358 'type': 'mojo::AssociatedBindingSet<>;',
2359 'file': 'file2.c'
2360 },
2361 {
2362 'type': 'mojo::AssociatedInterfacePtr<>',
2363 'file': 'file3.cc'
2364 },
2365 {
2366 'type': 'mojo::AssociatedInterfacePtrInfo<>',
2367 'file': 'file4.cc'
2368 },
2369 {
2370 'type': 'mojo::AssociatedInterfaceRequest<>',
2371 'file': 'file5.cc'
2372 },
2373 {
2374 'type': 'mojo::Binding<>',
2375 'file': 'file6.cc'
2376 },
2377 {
2378 'type': 'mojo::BindingSet<>',
2379 'file': 'file7.cc'
2380 },
2381 {
2382 'type': 'mojo::InterfacePtr<>',
2383 'file': 'file8.cc'
2384 },
2385 {
2386 'type': 'mojo::InterfacePtrInfo<>',
2387 'file': 'file9.cc'
2388 },
2389 {
2390 'type': 'mojo::InterfaceRequest<>',
2391 'file': 'file10.cc'
2392 },
2393 {
2394 'type': 'mojo::MakeRequest()',
2395 'file': 'file11.cc'
2396 },
2397 {
2398 'type': 'mojo::MakeRequestAssociatedWithDedicatedPipe()',
2399 'file': 'file12.cc'
2400 },
2401 {
2402 'type': 'mojo::MakeStrongBinding()<>',
2403 'file': 'file13.cc'
2404 },
2405 {
2406 'type': 'mojo::MakeStrongAssociatedBinding()<>',
2407 'file': 'file14.cc'
2408 },
2409 {
Gyuyoung Kim4952ba62020-07-07 07:33:442410 'type': 'mojo::StrongAssociatedBinding<>',
Mario Sanchez Prada2472cab2019-09-18 10:58:312411 'file': 'file15.cc'
2412 },
2413 {
Gyuyoung Kim4952ba62020-07-07 07:33:442414 'type': 'mojo::StrongBinding<>',
Mario Sanchez Prada2472cab2019-09-18 10:58:312415 'file': 'file16.cc'
2416 },
Gyuyoung Kim4952ba62020-07-07 07:33:442417 {
2418 'type': 'mojo::StrongAssociatedBindingSet<>',
2419 'file': 'file17.cc'
2420 },
2421 {
2422 'type': 'mojo::StrongBindingSet<>',
2423 'file': 'file18.cc'
2424 },
Mario Sanchez Prada2472cab2019-09-18 10:58:312425 ]
2426
2427 # Build the list of MockFiles considering paths that should trigger warnings
Mario Sanchez Pradacec9cef2019-12-15 11:54:572428 # as well as paths that should trigger errors.
Mario Sanchez Prada2472cab2019-09-18 10:58:312429 input_api = MockInputApi()
2430 input_api.files = []
2431 for test_case in test_cases:
2432 for path in ok_paths:
2433 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2434 [test_case['type']]))
2435 for path in warning_paths:
2436 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2437 [test_case['type']]))
Mario Sanchez Pradacec9cef2019-12-15 11:54:572438 for path in error_paths:
2439 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2440 [test_case['type']]))
Mario Sanchez Prada2472cab2019-09-18 10:58:312441
Saagar Sanghavifceeaae2020-08-12 16:40:362442 results = PRESUBMIT.CheckNoDeprecatedMojoTypes(input_api, MockOutputApi())
Mario Sanchez Prada2472cab2019-09-18 10:58:312443
Mario Sanchez Pradacec9cef2019-12-15 11:54:572444 # warnings are results[0], errors are results[1]
2445 self.assertEqual(2, len(results))
Mario Sanchez Prada2472cab2019-09-18 10:58:312446
2447 for test_case in test_cases:
Mario Sanchez Pradacec9cef2019-12-15 11:54:572448 # Check that no warnings nor errors have been triggered for these paths.
Mario Sanchez Prada2472cab2019-09-18 10:58:312449 for path in ok_paths:
2450 self.assertFalse(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572451 self.assertFalse(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312452
2453 # Check warnings have been triggered for these paths.
2454 for path in warning_paths:
2455 self.assertTrue(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572456 self.assertFalse(path in results[1].message)
2457
2458 # Check errors have been triggered for these paths.
2459 for path in error_paths:
2460 self.assertFalse(path in results[0].message)
2461 self.assertTrue(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312462
Sylvain Defresnea8b73d252018-02-28 15:45:542463
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272464class NoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:242465 def testTruePositives(self):
2466 mock_input_api = MockInputApi()
2467 mock_input_api.files = [
2468 MockFile('some/path/foo.cc', ['foo_for_testing();']),
2469 MockFile('some/path/foo.mm', ['FooForTesting();']),
2470 MockFile('some/path/foo.cxx', ['FooForTests();']),
2471 MockFile('some/path/foo.cpp', ['foo_for_test();']),
2472 ]
2473
Saagar Sanghavifceeaae2020-08-12 16:40:362474 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242475 mock_input_api, MockOutputApi())
2476 self.assertEqual(1, len(results))
2477 self.assertEqual(4, len(results[0].items))
2478 self.assertTrue('foo.cc' in results[0].items[0])
2479 self.assertTrue('foo.mm' in results[0].items[1])
2480 self.assertTrue('foo.cxx' in results[0].items[2])
2481 self.assertTrue('foo.cpp' in results[0].items[3])
2482
2483 def testFalsePositives(self):
2484 mock_input_api = MockInputApi()
2485 mock_input_api.files = [
2486 MockFile('some/path/foo.h', ['foo_for_testing();']),
2487 MockFile('some/path/foo.mm', ['FooForTesting() {']),
2488 MockFile('some/path/foo.cc', ['::FooForTests();']),
2489 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
2490 ]
2491
Saagar Sanghavifceeaae2020-08-12 16:40:362492 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242493 mock_input_api, MockOutputApi())
2494 self.assertEqual(0, len(results))
2495
James Cook1b4dc132021-03-09 22:45:132496 def testAllowedFiles(self):
2497 mock_input_api = MockInputApi()
2498 mock_input_api.files = [
2499 MockFile('path/foo_unittest.cc', ['foo_for_testing();']),
2500 MockFile('path/bar_unittest_mac.cc', ['foo_for_testing();']),
2501 MockFile('path/baz_unittests.cc', ['foo_for_testing();']),
2502 ]
2503
2504 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
2505 mock_input_api, MockOutputApi())
2506 self.assertEqual(0, len(results))
2507
Vaclav Brozekf01ed502018-03-16 19:38:242508
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272509class NoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:232510 def testTruePositives(self):
2511 mock_input_api = MockInputApi()
2512 mock_input_api.files = [
2513 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
2514 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392515 MockFile('dir/java/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232516 MockFile('dir/java/src/mult.java', [
2517 'int x = SomethingLongHere()',
2518 ' * SomethingLongHereForTesting();'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392519 ])
Vaclav Brozek7dbc28c2018-03-27 08:35:232520 ]
2521
Saagar Sanghavifceeaae2020-08-12 16:40:362522 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232523 mock_input_api, MockOutputApi())
2524 self.assertEqual(1, len(results))
2525 self.assertEqual(4, len(results[0].items))
2526 self.assertTrue('foo.java' in results[0].items[0])
2527 self.assertTrue('bar.java' in results[0].items[1])
2528 self.assertTrue('baz.java' in results[0].items[2])
2529 self.assertTrue('mult.java' in results[0].items[3])
2530
2531 def testFalsePositives(self):
2532 mock_input_api = MockInputApi()
2533 mock_input_api.files = [
2534 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
2535 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
2536 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
2537 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
Sky Malice9e6d6032020-10-15 22:49:552538 MockFile('dir/java/src/bar3.java', ['@VisibleForTesting']),
2539 MockFile('dir/java/src/bar4.java', ['@VisibleForTesting()']),
2540 MockFile('dir/java/src/bar5.java', [
2541 '@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)'
2542 ]),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392543 MockFile('dir/javatests/src/baz.java', ['FooForTest(', 'y', ');']),
2544 MockFile('dir/junit/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232545 MockFile('dir/junit/src/javadoc.java', [
2546 '/** Use FooForTest(); to obtain foo in tests.'
2547 ' */'
2548 ]),
2549 MockFile('dir/junit/src/javadoc2.java', [
2550 '/** ',
2551 ' * Use FooForTest(); to obtain foo in tests.'
2552 ' */'
2553 ]),
2554 ]
2555
Saagar Sanghavifceeaae2020-08-12 16:40:362556 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232557 mock_input_api, MockOutputApi())
2558 self.assertEqual(0, len(results))
2559
2560
Mohamed Heikald048240a2019-11-12 16:57:372561class NewImagesWarningTest(unittest.TestCase):
2562 def testTruePositives(self):
2563 mock_input_api = MockInputApi()
2564 mock_input_api.files = [
2565 MockFile('dir/android/res/drawable/foo.png', []),
2566 MockFile('dir/android/res/drawable-v21/bar.svg', []),
2567 MockFile('dir/android/res/mipmap-v21-en/baz.webp', []),
2568 MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png', []),
2569 ]
2570
2571 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2572 self.assertEqual(1, len(results))
2573 self.assertEqual(4, len(results[0].items))
2574 self.assertTrue('foo.png' in results[0].items[0].LocalPath())
2575 self.assertTrue('bar.svg' in results[0].items[1].LocalPath())
2576 self.assertTrue('baz.webp' in results[0].items[2].LocalPath())
2577 self.assertTrue('foobar.png' in results[0].items[3].LocalPath())
2578
2579 def testFalsePositives(self):
2580 mock_input_api = MockInputApi()
2581 mock_input_api.files = [
2582 MockFile('dir/pngs/README.md', []),
2583 MockFile('java/test/res/drawable/foo.png', []),
2584 MockFile('third_party/blink/foo.png', []),
2585 MockFile('dir/third_party/libpng/src/foo.cc', ['foobar']),
2586 MockFile('dir/resources.webp/.gitignore', ['foo.png']),
2587 ]
2588
2589 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2590 self.assertEqual(0, len(results))
2591
2592
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272593class CheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:052594 def testTruePositivesNullptr(self):
2595 mock_input_api = MockInputApi()
2596 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162597 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
2598 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
Vaclav Brozek851d9602018-04-04 16:13:052599 ]
2600
Saagar Sanghavifceeaae2020-08-12 16:40:362601 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052602 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162603 self.assertTrue('nullptr' in results[0].message)
Vaclav Brozek851d9602018-04-04 16:13:052604 self.assertEqual(2, len(results[0].items))
2605 self.assertTrue('baz.cc' in results[0].items[0])
2606 self.assertTrue('baz-p.cc' in results[0].items[1])
2607
2608 def testTruePositivesConstructor(self):
Vaclav Brozek52e18bf2018-04-03 07:05:242609 mock_input_api = MockInputApi()
2610 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162611 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
2612 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
2613 MockFile('dir/mult.cc', [
Vaclav Brozek95face62018-04-04 14:15:112614 'return',
2615 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
2616 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162617 MockFile('dir/mult2.cc', [
Vaclav Brozek95face62018-04-04 14:15:112618 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
2619 ' std::unique_ptr<T>(foo);'
2620 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162621 MockFile('dir/mult3.cc', [
Vaclav Brozek95face62018-04-04 14:15:112622 'bar = std::unique_ptr<T>(',
2623 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
2624 ]),
Vaclav Brozekb7fadb692018-08-30 06:39:532625 MockFile('dir/multi_arg.cc', [
2626 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']),
Vaclav Brozek52e18bf2018-04-03 07:05:242627 ]
2628
Saagar Sanghavifceeaae2020-08-12 16:40:362629 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052630 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162631 self.assertTrue('std::make_unique' in results[0].message)
Vaclav Brozekb7fadb692018-08-30 06:39:532632 self.assertEqual(6, len(results[0].items))
Vaclav Brozek851d9602018-04-04 16:13:052633 self.assertTrue('foo.cc' in results[0].items[0])
2634 self.assertTrue('bar.mm' in results[0].items[1])
2635 self.assertTrue('mult.cc' in results[0].items[2])
2636 self.assertTrue('mult2.cc' in results[0].items[3])
2637 self.assertTrue('mult3.cc' in results[0].items[4])
Vaclav Brozekb7fadb692018-08-30 06:39:532638 self.assertTrue('multi_arg.cc' in results[0].items[5])
Vaclav Brozek52e18bf2018-04-03 07:05:242639
2640 def testFalsePositives(self):
2641 mock_input_api = MockInputApi()
2642 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162643 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
2644 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
2645 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
2646 MockFile('dir/baz.cc', [
Vaclav Brozek52e18bf2018-04-03 07:05:242647 'std::unique_ptr<T> result = std::make_unique<T>();'
2648 ]),
Vaclav Brozeka54c528b2018-04-06 19:23:552649 MockFile('dir/baz2.cc', [
2650 'std::unique_ptr<T> result = std::make_unique<T>('
2651 ]),
2652 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
2653 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
Vaclav Brozekb7fadb692018-08-30 06:39:532654
2655 # Two-argument invocation of std::unique_ptr is exempt because there is
2656 # no equivalent using std::make_unique.
2657 MockFile('dir/multi_arg.cc', [
2658 'auto p = std::unique_ptr<T, D>(new T(), D());']),
Vaclav Brozek52e18bf2018-04-03 07:05:242659 ]
2660
Saagar Sanghavifceeaae2020-08-12 16:40:362661 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek52e18bf2018-04-03 07:05:242662 self.assertEqual(0, len(results))
2663
Danil Chapovalov3518f362018-08-11 16:13:432664class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
2665 def testBlocksDirectIncludes(self):
2666 mock_input_api = MockInputApi()
2667 mock_input_api.files = [
2668 MockFile('dir/foo_win.cc', ['#include "shlwapi.h"']),
2669 MockFile('dir/bar.h', ['#include <propvarutil.h>']),
2670 MockFile('dir/baz.h', ['#include <atlbase.h>']),
2671 MockFile('dir/jumbo.h', ['#include "sphelper.h"']),
2672 ]
2673 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2674 self.assertEquals(1, len(results))
2675 self.assertEquals(4, len(results[0].items))
2676 self.assertTrue('StrCat' in results[0].message)
2677 self.assertTrue('foo_win.cc' in results[0].items[0])
2678 self.assertTrue('bar.h' in results[0].items[1])
2679 self.assertTrue('baz.h' in results[0].items[2])
2680 self.assertTrue('jumbo.h' in results[0].items[3])
2681
2682 def testAllowsToIncludeWrapper(self):
2683 mock_input_api = MockInputApi()
2684 mock_input_api.files = [
2685 MockFile('dir/baz_win.cc', ['#include "base/win/shlwapi.h"']),
2686 MockFile('dir/baz-win.h', ['#include "base/win/atl.h"']),
2687 ]
2688 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2689 self.assertEquals(0, len(results))
2690
2691 def testAllowsToCreateWrapper(self):
2692 mock_input_api = MockInputApi()
2693 mock_input_api.files = [
2694 MockFile('base/win/shlwapi.h', [
2695 '#include <shlwapi.h>',
2696 '#include "base/win/windows_defines.inc"']),
2697 ]
2698 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2699 self.assertEquals(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:242700
Mustafa Emre Acer51f2f742020-03-09 19:41:122701
Rainhard Findlingfc31844c52020-05-15 09:58:262702class StringTest(unittest.TestCase):
2703 """Tests ICU syntax check and translation screenshots check."""
2704
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142705 # An empty grd file.
2706 OLD_GRD_CONTENTS = """<?xml version="1.0" encoding="UTF-8"?>
2707 <grit latest_public_release="1" current_release="1">
2708 <release seq="1">
2709 <messages></messages>
2710 </release>
2711 </grit>
2712 """.splitlines()
2713 # A grd file with a single message.
2714 NEW_GRD_CONTENTS1 = """<?xml version="1.0" encoding="UTF-8"?>
2715 <grit latest_public_release="1" current_release="1">
2716 <release seq="1">
2717 <messages>
2718 <message name="IDS_TEST1">
2719 Test string 1
2720 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482721 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE1"
2722 translateable="false">
2723 Non translateable message 1, should be ignored
2724 </message>
Mustafa Emre Acered1a48962020-06-30 19:15:392725 <message name="IDS_TEST_STRING_ACCESSIBILITY"
Mustafa Emre Acerd3ca8be2020-07-07 22:35:342726 is_accessibility_with_no_ui="true">
Mustafa Emre Acered1a48962020-06-30 19:15:392727 Accessibility label 1, should be ignored
2728 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142729 </messages>
2730 </release>
2731 </grit>
2732 """.splitlines()
2733 # A grd file with two messages.
2734 NEW_GRD_CONTENTS2 = """<?xml version="1.0" encoding="UTF-8"?>
2735 <grit latest_public_release="1" current_release="1">
2736 <release seq="1">
2737 <messages>
2738 <message name="IDS_TEST1">
2739 Test string 1
2740 </message>
2741 <message name="IDS_TEST2">
2742 Test string 2
2743 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482744 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE2"
2745 translateable="false">
2746 Non translateable message 2, should be ignored
2747 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142748 </messages>
2749 </release>
2750 </grit>
2751 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:262752 # A grd file with one ICU syntax message without syntax errors.
2753 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1 = """<?xml version="1.0" encoding="UTF-8"?>
2754 <grit latest_public_release="1" current_release="1">
2755 <release seq="1">
2756 <messages>
2757 <message name="IDS_TEST1">
2758 {NUM, plural,
2759 =1 {Test text for numeric one}
2760 other {Test text for plural with {NUM} as number}}
2761 </message>
2762 </messages>
2763 </release>
2764 </grit>
2765 """.splitlines()
2766 # A grd file with one ICU syntax message without syntax errors.
2767 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2 = """<?xml version="1.0" encoding="UTF-8"?>
2768 <grit latest_public_release="1" current_release="1">
2769 <release seq="1">
2770 <messages>
2771 <message name="IDS_TEST1">
2772 {NUM, plural,
2773 =1 {Different test text for numeric one}
2774 other {Different test text for plural with {NUM} as number}}
2775 </message>
2776 </messages>
2777 </release>
2778 </grit>
2779 """.splitlines()
2780 # A grd file with one ICU syntax message with syntax errors (misses a comma).
2781 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
2782 <grit latest_public_release="1" current_release="1">
2783 <release seq="1">
2784 <messages>
2785 <message name="IDS_TEST1">
2786 {NUM, plural
2787 =1 {Test text for numeric one}
2788 other {Test text for plural with {NUM} as number}}
2789 </message>
2790 </messages>
2791 </release>
2792 </grit>
2793 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142794
meacerff8a9b62019-12-10 19:43:582795 OLD_GRDP_CONTENTS = (
2796 '<?xml version="1.0" encoding="utf-8"?>',
2797 '<grit-part>',
2798 '</grit-part>'
2799 )
2800
2801 NEW_GRDP_CONTENTS1 = (
2802 '<?xml version="1.0" encoding="utf-8"?>',
2803 '<grit-part>',
2804 '<message name="IDS_PART_TEST1">',
2805 'Part string 1',
2806 '</message>',
2807 '</grit-part>')
2808
2809 NEW_GRDP_CONTENTS2 = (
2810 '<?xml version="1.0" encoding="utf-8"?>',
2811 '<grit-part>',
2812 '<message name="IDS_PART_TEST1">',
2813 'Part string 1',
2814 '</message>',
2815 '<message name="IDS_PART_TEST2">',
2816 'Part string 2',
2817 '</message>',
2818 '</grit-part>')
2819
Rainhard Findlingd8d04372020-08-13 13:30:092820 NEW_GRDP_CONTENTS3 = (
2821 '<?xml version="1.0" encoding="utf-8"?>',
2822 '<grit-part>',
2823 '<message name="IDS_PART_TEST1" desc="Description with typo.">',
2824 'Part string 1',
2825 '</message>',
2826 '</grit-part>')
2827
2828 NEW_GRDP_CONTENTS4 = (
2829 '<?xml version="1.0" encoding="utf-8"?>',
2830 '<grit-part>',
2831 '<message name="IDS_PART_TEST1" desc="Description with typo fixed.">',
2832 'Part string 1',
2833 '</message>',
2834 '</grit-part>')
2835
Rainhard Findling1a3e71e2020-09-21 07:33:352836 NEW_GRDP_CONTENTS5 = (
2837 '<?xml version="1.0" encoding="utf-8"?>',
2838 '<grit-part>',
2839 '<message name="IDS_PART_TEST1" meaning="Meaning with typo.">',
2840 'Part string 1',
2841 '</message>',
2842 '</grit-part>')
2843
2844 NEW_GRDP_CONTENTS6 = (
2845 '<?xml version="1.0" encoding="utf-8"?>',
2846 '<grit-part>',
2847 '<message name="IDS_PART_TEST1" meaning="Meaning with typo fixed.">',
2848 'Part string 1',
2849 '</message>',
2850 '</grit-part>')
2851
Rainhard Findlingfc31844c52020-05-15 09:58:262852 # A grdp file with one ICU syntax message without syntax errors.
2853 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = (
2854 '<?xml version="1.0" encoding="utf-8"?>',
2855 '<grit-part>',
2856 '<message name="IDS_PART_TEST1">',
2857 '{NUM, plural,',
2858 '=1 {Test text for numeric one}',
2859 'other {Test text for plural with {NUM} as number}}',
2860 '</message>',
2861 '</grit-part>')
2862 # A grdp file with one ICU syntax message without syntax errors.
2863 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2 = (
2864 '<?xml version="1.0" encoding="utf-8"?>',
2865 '<grit-part>',
2866 '<message name="IDS_PART_TEST1">',
2867 '{NUM, plural,',
2868 '=1 {Different test text for numeric one}',
2869 'other {Different test text for plural with {NUM} as number}}',
2870 '</message>',
2871 '</grit-part>')
2872
2873 # A grdp file with one ICU syntax message with syntax errors (superfluent
2874 # whitespace).
2875 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR = (
2876 '<?xml version="1.0" encoding="utf-8"?>',
2877 '<grit-part>',
2878 '<message name="IDS_PART_TEST1">',
2879 '{NUM, plural,',
2880 '= 1 {Test text for numeric one}',
2881 'other {Test text for plural with {NUM} as number}}',
2882 '</message>',
2883 '</grit-part>')
2884
Mustafa Emre Acerc8a012d2018-07-31 00:00:392885 DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
2886 'changelist. Run '
2887 'tools/translate/upload_screenshots.py to '
2888 'upload them instead:')
2889 GENERATE_SIGNATURES_MESSAGE = ('You are adding or modifying UI strings.\n'
2890 'To ensure the best translations, take '
2891 'screenshots of the relevant UI '
2892 '(https://g.co/chrome/translation) and add '
2893 'these files to your changelist:')
2894 REMOVE_SIGNATURES_MESSAGE = ('You removed strings associated with these '
2895 'files. Remove:')
Rainhard Findlingfc31844c52020-05-15 09:58:262896 ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
2897 'strings (problems or feedback? Contact '
2898 '[email protected]):')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142899
2900 def makeInputApi(self, files):
2901 input_api = MockInputApi()
2902 input_api.files = files
meacere7be7532019-10-02 17:41:032903 # Override os_path.exists because the presubmit uses the actual
2904 # os.path.exists.
2905 input_api.CreateMockFileInPath(
2906 [x.LocalPath() for x in input_api.AffectedFiles(include_deletes=True)])
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142907 return input_api
2908
meacerff8a9b62019-12-10 19:43:582909 """ CL modified and added messages, but didn't add any screenshots."""
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142910 def testNoScreenshots(self):
meacerff8a9b62019-12-10 19:43:582911 # No new strings (file contents same). Should not warn.
2912 input_api = self.makeInputApi([
2913 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
2914 self.NEW_GRD_CONTENTS1, action='M'),
2915 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1,
2916 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362917 warnings = PRESUBMIT.CheckStrings(input_api,
meacerff8a9b62019-12-10 19:43:582918 MockOutputApi())
2919 self.assertEqual(0, len(warnings))
2920
2921 # Add two new strings. Should have two warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142922 input_api = self.makeInputApi([
2923 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582924 self.NEW_GRD_CONTENTS1, action='M'),
2925 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2926 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362927 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142928 MockOutputApi())
2929 self.assertEqual(1, len(warnings))
2930 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerc6ed2682020-07-07 07:24:002931 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012932 self.assertEqual([
meacerff8a9b62019-12-10 19:43:582933 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2934 os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
2935 warnings[0].items)
Mustafa Emre Acer36eaad52019-11-12 23:03:342936
meacerff8a9b62019-12-10 19:43:582937 # Add four new strings. Should have four warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:212938 input_api = self.makeInputApi([
2939 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582940 self.OLD_GRD_CONTENTS, action='M'),
2941 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2942 self.OLD_GRDP_CONTENTS, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362943 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:212944 MockOutputApi())
2945 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:002946 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:212947 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:582948 self.assertEqual([
2949 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2950 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2951 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
2952 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
2953 ], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:212954
Rainhard Findlingd8d04372020-08-13 13:30:092955 def testModifiedMessageDescription(self):
2956 # CL modified a message description for a message that does not yet have a
Rainhard Findling1a3e71e2020-09-21 07:33:352957 # screenshot. Should not warn.
Rainhard Findlingd8d04372020-08-13 13:30:092958 input_api = self.makeInputApi([
2959 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
2960 self.NEW_GRDP_CONTENTS4, action='M')])
2961 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findling1a3e71e2020-09-21 07:33:352962 self.assertEqual(0, len(warnings))
Rainhard Findlingd8d04372020-08-13 13:30:092963
2964 # CL modified a message description for a message that already has a
2965 # screenshot. Should not warn.
2966 input_api = self.makeInputApi([
2967 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
2968 self.NEW_GRDP_CONTENTS4, action='M'),
2969 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2970 'binary', action='A')])
2971 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
2972 self.assertEqual(0, len(warnings))
2973
Rainhard Findling1a3e71e2020-09-21 07:33:352974 def testModifiedMessageMeaning(self):
2975 # CL modified a message meaning for a message that does not yet have a
2976 # screenshot. Should warn.
2977 input_api = self.makeInputApi([
2978 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
2979 self.NEW_GRDP_CONTENTS6, action='M')])
2980 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
2981 self.assertEqual(1, len(warnings))
2982
2983 # CL modified a message meaning for a message that already has a
2984 # screenshot. Should not warn.
2985 input_api = self.makeInputApi([
2986 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
2987 self.NEW_GRDP_CONTENTS6, action='M'),
2988 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2989 'binary', action='A')])
2990 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
2991 self.assertEqual(0, len(warnings))
2992
meacerff8a9b62019-12-10 19:43:582993 def testPngAddedSha1NotAdded(self):
2994 # CL added one new message in a grd file and added the png file associated
2995 # with it, but did not add the corresponding sha1 file. This should warn
2996 # twice:
2997 # - Once for the added png file (because we don't want developers to upload
2998 # actual images)
2999 # - Once for the missing .sha1 file
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143000 input_api = self.makeInputApi([
Mustafa Emre Acerea3e57a2018-12-17 23:51:013001 MockAffectedFile(
3002 'test.grd',
3003 self.NEW_GRD_CONTENTS1,
3004 self.OLD_GRD_CONTENTS,
3005 action='M'),
3006 MockAffectedFile(
3007 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
3008 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363009 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143010 MockOutputApi())
3011 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003012 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143013 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013014 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
3015 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003016 self.assertEqual('error', warnings[1].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143017 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013018 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3019 warnings[1].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143020
meacerff8a9b62019-12-10 19:43:583021 # CL added two messages (one in grd, one in grdp) and added the png files
3022 # associated with the messages, but did not add the corresponding sha1
3023 # files. This should warn twice:
3024 # - Once for the added png files (because we don't want developers to upload
3025 # actual images)
3026 # - Once for the missing .sha1 files
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143027 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583028 # Modified files:
Mustafa Emre Acer36eaad52019-11-12 23:03:343029 MockAffectedFile(
3030 'test.grd',
meacerff8a9b62019-12-10 19:43:583031 self.NEW_GRD_CONTENTS1,
Mustafa Emre Acer36eaad52019-11-12 23:03:343032 self.OLD_GRD_CONTENTS,
meacer2308d0742019-11-12 18:15:423033 action='M'),
Mustafa Emre Acer12e7fee2019-11-18 18:49:553034 MockAffectedFile(
meacerff8a9b62019-12-10 19:43:583035 'part.grdp',
3036 self.NEW_GRDP_CONTENTS1,
3037 self.OLD_GRDP_CONTENTS,
3038 action='M'),
3039 # Added files:
3040 MockAffectedFile(
3041 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A'),
3042 MockAffectedFile(
3043 os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary',
3044 action='A')
Mustafa Emre Acerad8fb082019-11-19 04:24:213045 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363046 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213047 MockOutputApi())
3048 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003049 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213050 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583051 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png'),
3052 os.path.join('test_grd', 'IDS_TEST1.png')],
Mustafa Emre Acerad8fb082019-11-19 04:24:213053 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003054 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213055 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
meacerff8a9b62019-12-10 19:43:583056 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3057 os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3058 warnings[1].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213059
3060 def testScreenshotsWithSha1(self):
meacerff8a9b62019-12-10 19:43:583061 # CL added four messages (two each in a grd and grdp) and their
3062 # corresponding .sha1 files. No warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213063 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583064 # Modified files:
Mustafa Emre Acerad8fb082019-11-19 04:24:213065 MockAffectedFile(
3066 'test.grd',
3067 self.NEW_GRD_CONTENTS2,
3068 self.OLD_GRD_CONTENTS,
Mustafa Emre Acer12e7fee2019-11-18 18:49:553069 action='M'),
meacerff8a9b62019-12-10 19:43:583070 MockAffectedFile(
3071 'part.grdp',
3072 self.NEW_GRDP_CONTENTS2,
3073 self.OLD_GRDP_CONTENTS,
3074 action='M'),
3075 # Added files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013076 MockFile(
3077 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3078 'binary',
3079 action='A'),
3080 MockFile(
3081 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3082 'binary',
meacerff8a9b62019-12-10 19:43:583083 action='A'),
3084 MockFile(
3085 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3086 'binary',
3087 action='A'),
3088 MockFile(
3089 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3090 'binary',
3091 action='A'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013092 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363093 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143094 MockOutputApi())
3095 self.assertEqual([], warnings)
3096
3097 def testScreenshotsRemovedWithSha1(self):
meacerff8a9b62019-12-10 19:43:583098 # Replace new contents with old contents in grd and grp files, removing
3099 # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3100 # Should warn to remove the sha1 files associated with these strings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143101 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583102 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013103 MockAffectedFile(
3104 'test.grd',
meacerff8a9b62019-12-10 19:43:583105 self.OLD_GRD_CONTENTS, # new_contents
3106 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013107 action='M'),
meacerff8a9b62019-12-10 19:43:583108 MockAffectedFile(
3109 'part.grdp',
3110 self.OLD_GRDP_CONTENTS, # new_contents
3111 self.NEW_GRDP_CONTENTS2, # old_contents
3112 action='M'),
3113 # Unmodified files:
3114 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
3115 MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', ''),
3116 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3117 'binary', ''),
3118 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3119 'binary', '')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013120 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363121 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143122 MockOutputApi())
3123 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003124 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143125 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013126 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583127 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3128 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013129 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3130 os.path.join('test_grd', 'IDS_TEST2.png.sha1')
3131 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143132
meacerff8a9b62019-12-10 19:43:583133 # Same as above, but this time one of the .sha1 files is also removed.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143134 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583135 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013136 MockAffectedFile(
3137 'test.grd',
meacerff8a9b62019-12-10 19:43:583138 self.OLD_GRD_CONTENTS, # new_contents
3139 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013140 action='M'),
meacerff8a9b62019-12-10 19:43:583141 MockAffectedFile(
3142 'part.grdp',
3143 self.OLD_GRDP_CONTENTS, # new_contents
3144 self.NEW_GRDP_CONTENTS2, # old_contents
3145 action='M'),
3146 # Unmodified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013147 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
meacerff8a9b62019-12-10 19:43:583148 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3149 'binary', ''),
3150 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013151 MockAffectedFile(
3152 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3153 '',
3154 'old_contents',
meacerff8a9b62019-12-10 19:43:583155 action='D'),
3156 MockAffectedFile(
3157 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3158 '',
3159 'old_contents',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013160 action='D')
3161 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363162 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143163 MockOutputApi())
3164 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003165 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143166 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583167 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3168 os.path.join('test_grd', 'IDS_TEST1.png.sha1')
3169 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143170
meacerff8a9b62019-12-10 19:43:583171 # Remove all sha1 files. There should be no warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143172 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583173 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013174 MockAffectedFile(
3175 'test.grd',
3176 self.OLD_GRD_CONTENTS,
3177 self.NEW_GRD_CONTENTS2,
3178 action='M'),
meacerff8a9b62019-12-10 19:43:583179 MockAffectedFile(
3180 'part.grdp',
3181 self.OLD_GRDP_CONTENTS,
3182 self.NEW_GRDP_CONTENTS2,
3183 action='M'),
3184 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013185 MockFile(
3186 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3187 'binary',
3188 action='D'),
3189 MockFile(
3190 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3191 'binary',
meacerff8a9b62019-12-10 19:43:583192 action='D'),
3193 MockFile(
3194 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3195 'binary',
3196 action='D'),
3197 MockFile(
3198 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3199 'binary',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013200 action='D')
3201 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363202 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143203 MockOutputApi())
3204 self.assertEqual([], warnings)
3205
Rainhard Findlingfc31844c52020-05-15 09:58:263206 def testIcuSyntax(self):
3207 # Add valid ICU syntax string. Should not raise an error.
3208 input_api = self.makeInputApi([
3209 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3210 self.NEW_GRD_CONTENTS1, action='M'),
3211 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3212 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363213 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263214 # We expect no ICU syntax errors.
3215 icu_errors = [e for e in results
3216 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3217 self.assertEqual(0, len(icu_errors))
3218
3219 # Valid changes in ICU syntax. Should not raise an error.
3220 input_api = self.makeInputApi([
3221 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3222 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3223 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3224 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363225 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263226 # We expect no ICU syntax errors.
3227 icu_errors = [e for e in results
3228 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3229 self.assertEqual(0, len(icu_errors))
3230
3231 # Add invalid ICU syntax strings. Should raise two errors.
3232 input_api = self.makeInputApi([
3233 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3234 self.NEW_GRD_CONTENTS1, action='M'),
3235 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3236 self.NEW_GRD_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363237 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263238 # We expect 2 ICU syntax errors.
3239 icu_errors = [e for e in results
3240 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3241 self.assertEqual(1, len(icu_errors))
3242 self.assertEqual([
3243 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3244 'ICU syntax.',
3245 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3246 ], icu_errors[0].items)
3247
3248 # Change two strings to have ICU syntax errors. Should raise two errors.
3249 input_api = self.makeInputApi([
3250 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3251 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3252 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3253 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363254 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263255 # We expect 2 ICU syntax errors.
3256 icu_errors = [e for e in results
3257 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3258 self.assertEqual(1, len(icu_errors))
3259 self.assertEqual([
3260 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3261 'ICU syntax.',
3262 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3263 ], icu_errors[0].items)
3264
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143265
Mustafa Emre Acer51f2f742020-03-09 19:41:123266class TranslationExpectationsTest(unittest.TestCase):
3267 ERROR_MESSAGE_FORMAT = (
3268 "Failed to get a list of translatable grd files. "
3269 "This happens when:\n"
3270 " - One of the modified grd or grdp files cannot be parsed or\n"
3271 " - %s is not updated.\n"
3272 "Stack:\n"
3273 )
3274 REPO_ROOT = os.path.join('tools', 'translation', 'testdata')
3275 # This lists all .grd files under REPO_ROOT.
3276 EXPECTATIONS = os.path.join(REPO_ROOT,
3277 "translation_expectations.pyl")
3278 # This lists all .grd files under REPO_ROOT except unlisted.grd.
3279 EXPECTATIONS_WITHOUT_UNLISTED_FILE = os.path.join(
3280 REPO_ROOT, "translation_expectations_without_unlisted_file.pyl")
3281
3282 # Tests that the presubmit doesn't return when no grd or grdp files are
3283 # modified.
3284 def testExpectationsNoModifiedGrd(self):
3285 input_api = MockInputApi()
3286 input_api.files = [
3287 MockAffectedFile('not_used.txt', 'not used', 'not used', action='M')
3288 ]
3289 # Fake list of all grd files in the repo. This list is missing all grd/grdps
3290 # under tools/translation/testdata. This is OK because the presubmit won't
3291 # run in the first place since there are no modified grd/grps in input_api.
3292 grd_files = ['doesnt_exist_doesnt_matter.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363293 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123294 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3295 grd_files)
3296 self.assertEqual(0, len(warnings))
3297
3298
3299 # Tests that the list of files passed to the presubmit matches the list of
3300 # files in the expectations.
3301 def testExpectationsSuccess(self):
3302 # Mock input file list needs a grd or grdp file in order to run the
3303 # presubmit. The file itself doesn't matter.
3304 input_api = MockInputApi()
3305 input_api.files = [
3306 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3307 ]
3308 # List of all grd files in the repo.
3309 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3310 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363311 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123312 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3313 grd_files)
3314 self.assertEqual(0, len(warnings))
3315
3316 # Tests that the presubmit warns when a file is listed in expectations, but
3317 # does not actually exist.
3318 def testExpectationsMissingFile(self):
3319 # Mock input file list needs a grd or grdp file in order to run the
3320 # presubmit.
3321 input_api = MockInputApi()
3322 input_api.files = [
3323 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3324 ]
3325 # unlisted.grd is listed under tools/translation/testdata but is not
3326 # included in translation expectations.
3327 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363328 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123329 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3330 grd_files)
3331 self.assertEqual(1, len(warnings))
3332 self.assertTrue(warnings[0].message.startswith(
3333 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS))
3334 self.assertTrue(
3335 ("test.grd is listed in the translation expectations, "
3336 "but this grd file does not exist")
3337 in warnings[0].message)
3338
3339 # Tests that the presubmit warns when a file is not listed in expectations but
3340 # does actually exist.
3341 def testExpectationsUnlistedFile(self):
3342 # Mock input file list needs a grd or grdp file in order to run the
3343 # presubmit.
3344 input_api = MockInputApi()
3345 input_api.files = [
3346 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3347 ]
3348 # unlisted.grd is listed under tools/translation/testdata but is not
3349 # included in translation expectations.
3350 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3351 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363352 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123353 input_api, MockOutputApi(), self.REPO_ROOT,
3354 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3355 self.assertEqual(1, len(warnings))
3356 self.assertTrue(warnings[0].message.startswith(
3357 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3358 self.assertTrue(
3359 ("unlisted.grd appears to be translatable "
3360 "(because it contains <file> or <message> elements), "
3361 "but is not listed in the translation expectations.")
3362 in warnings[0].message)
3363
3364 # Tests that the presubmit warns twice:
3365 # - for a non-existing file listed in expectations
3366 # - for an existing file not listed in expectations
3367 def testMultipleWarnings(self):
3368 # Mock input file list needs a grd or grdp file in order to run the
3369 # presubmit.
3370 input_api = MockInputApi()
3371 input_api.files = [
3372 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3373 ]
3374 # unlisted.grd is listed under tools/translation/testdata but is not
3375 # included in translation expectations.
3376 # test.grd is not listed under tools/translation/testdata but is included
3377 # in translation expectations.
3378 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363379 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123380 input_api, MockOutputApi(), self.REPO_ROOT,
3381 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3382 self.assertEqual(1, len(warnings))
3383 self.assertTrue(warnings[0].message.startswith(
3384 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3385 self.assertTrue(
3386 ("unlisted.grd appears to be translatable "
3387 "(because it contains <file> or <message> elements), "
3388 "but is not listed in the translation expectations.")
3389 in warnings[0].message)
3390 self.assertTrue(
3391 ("test.grd is listed in the translation expectations, "
3392 "but this grd file does not exist")
3393 in warnings[0].message)
3394
3395
Dominic Battre033531052018-09-24 15:45:343396class DISABLETypoInTest(unittest.TestCase):
3397
3398 def testPositive(self):
3399 # Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
3400 # where the desire is to disable a test.
3401 tests = [
3402 # Disabled on one platform:
3403 '#if defined(OS_WIN)\n'
3404 '#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
3405 '#else\n'
3406 '#define MAYBE_FoobarTest FoobarTest\n'
3407 '#endif\n',
3408 # Disabled on one platform spread cross lines:
3409 '#if defined(OS_WIN)\n'
3410 '#define MAYBE_FoobarTest \\\n'
3411 ' DISABLE_FoobarTest\n'
3412 '#else\n'
3413 '#define MAYBE_FoobarTest FoobarTest\n'
3414 '#endif\n',
3415 # Disabled on all platforms:
3416 ' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
3417 # Disabled on all platforms but multiple lines
3418 ' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
3419 ]
3420
3421 for test in tests:
3422 mock_input_api = MockInputApi()
3423 mock_input_api.files = [
3424 MockFile('some/path/foo_unittest.cc', test.splitlines()),
3425 ]
3426
Saagar Sanghavifceeaae2020-08-12 16:40:363427 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343428 MockOutputApi())
3429 self.assertEqual(
3430 1,
3431 len(results),
3432 msg=('expected len(results) == 1 but got %d in test: %s' %
3433 (len(results), test)))
3434 self.assertTrue(
3435 'foo_unittest.cc' in results[0].message,
3436 msg=('expected foo_unittest.cc in message but got %s in test %s' %
3437 (results[0].message, test)))
3438
3439 def testIngoreNotTestFiles(self):
3440 mock_input_api = MockInputApi()
3441 mock_input_api.files = [
3442 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'),
3443 ]
3444
Saagar Sanghavifceeaae2020-08-12 16:40:363445 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343446 MockOutputApi())
3447 self.assertEqual(0, len(results))
3448
Katie Df13948e2018-09-25 07:33:443449 def testIngoreDeletedFiles(self):
3450 mock_input_api = MockInputApi()
3451 mock_input_api.files = [
3452 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'),
3453 ]
3454
Saagar Sanghavifceeaae2020-08-12 16:40:363455 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Katie Df13948e2018-09-25 07:33:443456 MockOutputApi())
3457 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:343458
Dirk Pranke3c18a382019-03-15 01:07:513459
Max Morozb47503b2019-08-08 21:03:273460class CheckFuzzTargetsTest(unittest.TestCase):
3461
3462 def _check(self, files):
3463 mock_input_api = MockInputApi()
3464 mock_input_api.files = []
3465 for fname, contents in files.items():
3466 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363467 return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api, MockOutputApi())
Max Morozb47503b2019-08-08 21:03:273468
3469 def testLibFuzzerSourcesIgnored(self):
3470 results = self._check({
3471 "third_party/lib/Fuzzer/FuzzerDriver.cpp": "LLVMFuzzerInitialize",
3472 })
3473 self.assertEqual(results, [])
3474
3475 def testNonCodeFilesIgnored(self):
3476 results = self._check({
3477 "README.md": "LLVMFuzzerInitialize",
3478 })
3479 self.assertEqual(results, [])
3480
3481 def testNoErrorHeaderPresent(self):
3482 results = self._check({
3483 "fuzzer.cc": (
3484 "#include \"testing/libfuzzer/libfuzzer_exports.h\"\n" +
3485 "LLVMFuzzerInitialize"
3486 )
3487 })
3488 self.assertEqual(results, [])
3489
3490 def testErrorMissingHeader(self):
3491 results = self._check({
3492 "fuzzer.cc": "LLVMFuzzerInitialize"
3493 })
3494 self.assertEqual(len(results), 1)
3495 self.assertEqual(results[0].items, ['fuzzer.cc'])
3496
3497
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263498class SetNoParentTest(unittest.TestCase):
John Abd-El-Malekdfd1edc2021-02-24 22:22:403499 def testSetNoParentTopLevelAllowed(self):
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263500 mock_input_api = MockInputApi()
3501 mock_input_api.files = [
3502 MockAffectedFile('goat/OWNERS',
3503 [
3504 'set noparent',
3505 '[email protected]',
John Abd-El-Malekdfd1edc2021-02-24 22:22:403506 ])
3507 ]
3508 mock_output_api = MockOutputApi()
3509 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
3510 self.assertEqual([], errors)
3511
3512 def testSetNoParentMissing(self):
3513 mock_input_api = MockInputApi()
3514 mock_input_api.files = [
3515 MockAffectedFile('services/goat/OWNERS',
3516 [
3517 'set noparent',
3518 '[email protected]',
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263519 'per-file *.json=set noparent',
3520 'per-file *[email protected]',
3521 ])
3522 ]
3523 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363524 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263525 self.assertEqual(1, len(errors))
3526 self.assertTrue('goat/OWNERS:1' in errors[0].long_text)
3527 self.assertTrue('goat/OWNERS:3' in errors[0].long_text)
3528
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263529 def testSetNoParentWithCorrectRule(self):
3530 mock_input_api = MockInputApi()
3531 mock_input_api.files = [
John Abd-El-Malekdfd1edc2021-02-24 22:22:403532 MockAffectedFile('services/goat/OWNERS',
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263533 [
3534 'set noparent',
3535 'file://ipc/SECURITY_OWNERS',
3536 'per-file *.json=set noparent',
3537 'per-file *.json=file://ipc/SECURITY_OWNERS',
3538 ])
3539 ]
3540 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363541 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263542 self.assertEqual([], errors)
3543
3544
Ken Rockotc31f4832020-05-29 18:58:513545class MojomStabilityCheckTest(unittest.TestCase):
3546 def runTestWithAffectedFiles(self, affected_files):
3547 mock_input_api = MockInputApi()
3548 mock_input_api.files = affected_files
3549 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363550 return PRESUBMIT.CheckStableMojomChanges(
Ken Rockotc31f4832020-05-29 18:58:513551 mock_input_api, mock_output_api)
3552
3553 def testSafeChangePasses(self):
3554 errors = self.runTestWithAffectedFiles([
3555 MockAffectedFile('foo/foo.mojom',
3556 ['[Stable] struct S { [MinVersion=1] int32 x; };'],
3557 old_contents=['[Stable] struct S {};'])
3558 ])
3559 self.assertEqual([], errors)
3560
3561 def testBadChangeFails(self):
3562 errors = self.runTestWithAffectedFiles([
3563 MockAffectedFile('foo/foo.mojom',
3564 ['[Stable] struct S { int32 x; };'],
3565 old_contents=['[Stable] struct S {};'])
3566 ])
3567 self.assertEqual(1, len(errors))
3568 self.assertTrue('not backward-compatible' in errors[0].message)
3569
Ken Rockotad7901f942020-06-04 20:17:093570 def testDeletedFile(self):
3571 """Regression test for https://crbug.com/1091407."""
3572 errors = self.runTestWithAffectedFiles([
3573 MockAffectedFile('a.mojom', [], old_contents=['struct S {};'],
3574 action='D'),
3575 MockAffectedFile('b.mojom',
3576 ['struct S {}; struct T { S s; };'],
3577 old_contents=['import "a.mojom"; struct T { S s; };'])
3578 ])
3579 self.assertEqual([], errors)
3580
Jose Magana2b456f22021-03-09 23:26:403581class CheckForUseOfChromeAppsDeprecationsTest(unittest.TestCase):
3582
3583 ERROR_MSG_PIECE = 'technologies which will soon be deprecated'
3584
3585 # Each positive test is also a naive negative test for the other cases.
3586
3587 def testWarningNMF(self):
3588 mock_input_api = MockInputApi()
3589 mock_input_api.files = [
3590 MockAffectedFile(
3591 'foo.NMF',
3592 ['"program"', '"Z":"content"', 'B'],
3593 ['"program"', 'B'],
3594 scm_diff='\n'.join([
3595 '--- foo.NMF.old 2020-12-02 20:40:54.430676385 +0100',
3596 '+++ foo.NMF.new 2020-12-02 20:41:02.086700197 +0100',
3597 '@@ -1,2 +1,3 @@',
3598 ' "program"',
3599 '+"Z":"content"',
3600 ' B']),
3601 action='M')
3602 ]
3603 mock_output_api = MockOutputApi()
3604 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3605 mock_output_api)
3606 self.assertEqual(1, len(errors))
3607 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
3608 self.assertTrue( 'foo.NMF' in errors[0].message)
3609
3610 def testWarningManifest(self):
3611 mock_input_api = MockInputApi()
3612 mock_input_api.files = [
3613 MockAffectedFile(
3614 'manifest.json',
3615 ['"app":', '"Z":"content"', 'B'],
3616 ['"app":"', 'B'],
3617 scm_diff='\n'.join([
3618 '--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
3619 '+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
3620 '@@ -1,2 +1,3 @@',
3621 ' "app"',
3622 '+"Z":"content"',
3623 ' B']),
3624 action='M')
3625 ]
3626 mock_output_api = MockOutputApi()
3627 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3628 mock_output_api)
3629 self.assertEqual(1, len(errors))
3630 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
3631 self.assertTrue( 'manifest.json' in errors[0].message)
3632
3633 def testOKWarningManifestWithoutApp(self):
3634 mock_input_api = MockInputApi()
3635 mock_input_api.files = [
3636 MockAffectedFile(
3637 'manifest.json',
3638 ['"name":', '"Z":"content"', 'B'],
3639 ['"name":"', 'B'],
3640 scm_diff='\n'.join([
3641 '--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
3642 '+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
3643 '@@ -1,2 +1,3 @@',
3644 ' "app"',
3645 '+"Z":"content"',
3646 ' B']),
3647 action='M')
3648 ]
3649 mock_output_api = MockOutputApi()
3650 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3651 mock_output_api)
3652 self.assertEqual(0, len(errors))
3653
3654 def testWarningPPAPI(self):
3655 mock_input_api = MockInputApi()
3656 mock_input_api.files = [
3657 MockAffectedFile(
3658 'foo.hpp',
3659 ['A', '#include <ppapi.h>', 'B'],
3660 ['A', 'B'],
3661 scm_diff='\n'.join([
3662 '--- foo.hpp.old 2020-12-02 20:40:54.430676385 +0100',
3663 '+++ foo.hpp.new 2020-12-02 20:41:02.086700197 +0100',
3664 '@@ -1,2 +1,3 @@',
3665 ' A',
3666 '+#include <ppapi.h>',
3667 ' B']),
3668 action='M')
3669 ]
3670 mock_output_api = MockOutputApi()
3671 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3672 mock_output_api)
3673 self.assertEqual(1, len(errors))
3674 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
3675 self.assertTrue( 'foo.hpp' in errors[0].message)
3676
3677 def testNoWarningPPAPI(self):
3678 mock_input_api = MockInputApi()
3679 mock_input_api.files = [
3680 MockAffectedFile(
3681 'foo.txt',
3682 ['A', 'Peppapig', 'B'],
3683 ['A', 'B'],
3684 scm_diff='\n'.join([
3685 '--- foo.txt.old 2020-12-02 20:40:54.430676385 +0100',
3686 '+++ foo.txt.new 2020-12-02 20:41:02.086700197 +0100',
3687 '@@ -1,2 +1,3 @@',
3688 ' A',
3689 '+Peppapig',
3690 ' B']),
3691 action='M')
3692 ]
3693 mock_output_api = MockOutputApi()
3694 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3695 mock_output_api)
3696 self.assertEqual(0, len(errors))
3697
Dominic Battre645d42342020-12-04 16:14:103698class CheckDeprecationOfPreferencesTest(unittest.TestCase):
3699 # Test that a warning is generated if a preference registration is removed
3700 # from a random file.
3701 def testWarning(self):
3702 mock_input_api = MockInputApi()
3703 mock_input_api.files = [
3704 MockAffectedFile(
3705 'foo.cc',
3706 ['A', 'B'],
3707 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
3708 scm_diff='\n'.join([
3709 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
3710 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
3711 '@@ -1,3 +1,2 @@',
3712 ' A',
3713 '-prefs->RegisterStringPref("foo", "default");',
3714 ' B']),
3715 action='M')
3716 ]
3717 mock_output_api = MockOutputApi()
3718 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3719 mock_output_api)
3720 self.assertEqual(1, len(errors))
3721 self.assertTrue(
3722 'Discovered possible removal of preference registrations' in
3723 errors[0].message)
3724
3725 # Test that a warning is inhibited if the preference registration was moved
3726 # to the deprecation functions in browser prefs.
3727 def testNoWarningForMigration(self):
3728 mock_input_api = MockInputApi()
3729 mock_input_api.files = [
3730 # RegisterStringPref was removed from foo.cc.
3731 MockAffectedFile(
3732 'foo.cc',
3733 ['A', 'B'],
3734 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
3735 scm_diff='\n'.join([
3736 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
3737 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
3738 '@@ -1,3 +1,2 @@',
3739 ' A',
3740 '-prefs->RegisterStringPref("foo", "default");',
3741 ' B']),
3742 action='M'),
3743 # But the preference was properly migrated.
3744 MockAffectedFile(
3745 'chrome/browser/prefs/browser_prefs.cc',
3746 [
3747 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3748 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3749 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3750 'prefs->RegisterStringPref("foo", "default");',
3751 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3752 ],
3753 [
3754 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3755 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3756 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3757 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3758 ],
3759 scm_diff='\n'.join([
3760 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
3761 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
3762 '@@ -2,3 +2,4 @@',
3763 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3764 ' // BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3765 '+prefs->RegisterStringPref("foo", "default");',
3766 ' // END_MIGRATE_OBSOLETE_PROFILE_PREFS']),
3767 action='M'),
3768 ]
3769 mock_output_api = MockOutputApi()
3770 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3771 mock_output_api)
3772 self.assertEqual(0, len(errors))
3773
3774 # Test that a warning is NOT inhibited if the preference registration was
3775 # moved to a place outside of the migration functions in browser_prefs.cc
3776 def testWarningForImproperMigration(self):
3777 mock_input_api = MockInputApi()
3778 mock_input_api.files = [
3779 # RegisterStringPref was removed from foo.cc.
3780 MockAffectedFile(
3781 'foo.cc',
3782 ['A', 'B'],
3783 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
3784 scm_diff='\n'.join([
3785 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
3786 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
3787 '@@ -1,3 +1,2 @@',
3788 ' A',
3789 '-prefs->RegisterStringPref("foo", "default");',
3790 ' B']),
3791 action='M'),
3792 # The registration call was moved to a place in browser_prefs.cc that
3793 # is outside the migration functions.
3794 MockAffectedFile(
3795 'chrome/browser/prefs/browser_prefs.cc',
3796 [
3797 'prefs->RegisterStringPref("foo", "default");',
3798 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3799 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3800 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3801 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3802 ],
3803 [
3804 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3805 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3806 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3807 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3808 ],
3809 scm_diff='\n'.join([
3810 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
3811 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
3812 '@@ -1,2 +1,3 @@',
3813 '+prefs->RegisterStringPref("foo", "default");',
3814 ' // BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3815 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS']),
3816 action='M'),
3817 ]
3818 mock_output_api = MockOutputApi()
3819 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3820 mock_output_api)
3821 self.assertEqual(1, len(errors))
3822 self.assertTrue(
3823 'Discovered possible removal of preference registrations' in
3824 errors[0].message)
3825
3826 # Check that the presubmit fails if a marker line in brower_prefs.cc is
3827 # deleted.
3828 def testDeletedMarkerRaisesError(self):
3829 mock_input_api = MockInputApi()
3830 mock_input_api.files = [
3831 MockAffectedFile('chrome/browser/prefs/browser_prefs.cc',
3832 [
3833 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3834 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3835 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3836 # The following line is deleted for this test
3837 # '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3838 ])
3839 ]
3840 mock_output_api = MockOutputApi()
3841 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3842 mock_output_api)
3843 self.assertEqual(1, len(errors))
3844 self.assertEqual(
3845 'Broken .*MIGRATE_OBSOLETE_.*_PREFS markers in browser_prefs.cc.',
3846 errors[0].message)
3847
3848
[email protected]2299dcf2012-11-15 19:56:243849if __name__ == '__main__':
3850 unittest.main()