blob: 67847d1e4058ebfac6d72193804c46409fe37362 [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']),
Lei Zhang0643e342021-05-12 18:02:1298 MockFile('other/path/baz.h',
99 ['#include "set/vector.h"',
100 'bazzab']),
Lei Zhang1c12a22f2021-05-12 11:28:45101 # The check is only for header files.
102 MockFile('other/path/not_checked.cc',
103 ['#include <vector>',
104 'bazbaz']),
105 ]
106 results = PRESUBMIT.CheckForSuperfluousStlIncludesInHeaders(
107 mock_input_api, MockOutputApi())
108 self.assertEqual(0, len(results))
109
110 def testBadFiles(self):
111 mock_input_api = MockInputApi()
112 mock_input_api.files = [
113 MockFile('other/path/foo.h',
114 ['#include <vector>',
115 'vector']),
116 MockFile('other/path/bar.h',
117 ['#include <limits>',
118 '#include <set>',
119 'no_std_namespace']),
120 ]
121 results = PRESUBMIT.CheckForSuperfluousStlIncludesInHeaders(
122 mock_input_api, MockOutputApi())
123 self.assertEqual(1, len(results))
124 self.assertTrue('foo.h: Includes STL' in results[0].message)
125 self.assertTrue('bar.h: Includes STL' in results[0].message)
126
127
glidere61efad2015-02-18 17:39:43128class CheckSingletonInHeadersTest(unittest.TestCase):
129 def testSingletonInArbitraryHeader(self):
130 diff_singleton_h = ['base::subtle::AtomicWord '
olli.raula36aa8be2015-09-10 11:14:22131 'base::Singleton<Type, Traits, DifferentiatingType>::']
132 diff_foo_h = ['// base::Singleton<Foo> in comment.',
133 'friend class base::Singleton<Foo>']
oysteinec430ad42015-10-22 20:55:24134 diff_foo2_h = [' //Foo* bar = base::Singleton<Foo>::get();']
olli.raula36aa8be2015-09-10 11:14:22135 diff_bad_h = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43136 mock_input_api = MockInputApi()
137 mock_input_api.files = [MockAffectedFile('base/memory/singleton.h',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39138 diff_singleton_h),
glidere61efad2015-02-18 17:39:43139 MockAffectedFile('foo.h', diff_foo_h),
oysteinec430ad42015-10-22 20:55:24140 MockAffectedFile('foo2.h', diff_foo2_h),
glidere61efad2015-02-18 17:39:43141 MockAffectedFile('bad.h', diff_bad_h)]
Saagar Sanghavifceeaae2020-08-12 16:40:36142 warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
glidere61efad2015-02-18 17:39:43143 MockOutputApi())
144 self.assertEqual(1, len(warnings))
Sylvain Defresnea8b73d252018-02-28 15:45:54145 self.assertEqual(1, len(warnings[0].items))
glidere61efad2015-02-18 17:39:43146 self.assertEqual('error', warnings[0].type)
olli.raula36aa8be2015-09-10 11:14:22147 self.assertTrue('Found base::Singleton<T>' in warnings[0].message)
glidere61efad2015-02-18 17:39:43148
149 def testSingletonInCC(self):
olli.raula36aa8be2015-09-10 11:14:22150 diff_cc = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43151 mock_input_api = MockInputApi()
152 mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)]
Saagar Sanghavifceeaae2020-08-12 16:40:36153 warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
glidere61efad2015-02-18 17:39:43154 MockOutputApi())
155 self.assertEqual(0, len(warnings))
156
157
[email protected]b00342e7f2013-03-26 16:21:54158class InvalidOSMacroNamesTest(unittest.TestCase):
159 def testInvalidOSMacroNames(self):
160 lines = ['#if defined(OS_WINDOWS)',
161 ' #elif defined(OS_WINDOW)',
Avi Drissman34594e902020-07-25 05:35:44162 ' # if defined(OS_MAC) || defined(OS_CHROME)',
Avi Drissman32967a9e2020-07-30 04:10:32163 '# else // defined(OS_MACOSX)',
[email protected]b00342e7f2013-03-26 16:21:54164 '#endif // defined(OS_MACOS)']
165 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
166 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
167 self.assertEqual(len(lines), len(errors))
168 self.assertTrue(':1 OS_WINDOWS' in errors[0])
169 self.assertTrue('(did you mean OS_WIN?)' in errors[0])
170
171 def testValidOSMacroNames(self):
172 lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS]
173 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
174 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
175 self.assertEqual(0, len(errors))
176
177
lliabraa35bab3932014-10-01 12:16:44178class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
179 def testInvalidIfDefinedMacroNames(self):
180 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
181 '#if !defined(TARGET_IPHONE_SIMULATOR)',
182 '#elif defined(TARGET_IPHONE_SIMULATOR)',
183 '#ifdef TARGET_IPHONE_SIMULATOR',
184 ' # ifdef TARGET_IPHONE_SIMULATOR',
185 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
186 '# else // defined(TARGET_IPHONE_SIMULATOR)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39187 '#endif // defined(TARGET_IPHONE_SIMULATOR)']
lliabraa35bab3932014-10-01 12:16:44188 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
189 MockInputApi(), MockFile('some/path/source.mm', lines))
190 self.assertEqual(len(lines), len(errors))
191
192 def testValidIfDefinedMacroNames(self):
193 lines = ['#if defined(FOO)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39194 '#ifdef BAR']
lliabraa35bab3932014-10-01 12:16:44195 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
196 MockInputApi(), MockFile('some/path/source.cc', lines))
197 self.assertEqual(0, len(errors))
198
199
Samuel Huang0db2ea22019-12-09 16:42:47200class CheckAddedDepsHaveTestApprovalsTest(unittest.TestCase):
Daniel Cheng4dcdb6b2017-04-13 08:30:17201
202 def calculate(self, old_include_rules, old_specific_include_rules,
203 new_include_rules, new_specific_include_rules):
204 return PRESUBMIT._CalculateAddedDeps(
205 os.path, 'include_rules = %r\nspecific_include_rules = %r' % (
206 old_include_rules, old_specific_include_rules),
207 'include_rules = %r\nspecific_include_rules = %r' % (
208 new_include_rules, new_specific_include_rules))
209
210 def testCalculateAddedDeps(self):
211 old_include_rules = [
212 '+base',
213 '-chrome',
214 '+content',
215 '-grit',
216 '-grit/",',
217 '+jni/fooblat.h',
218 '!sandbox',
[email protected]f32e2d1e2013-07-26 21:39:08219 ]
Daniel Cheng4dcdb6b2017-04-13 08:30:17220 old_specific_include_rules = {
221 'compositor\.*': {
222 '+cc',
223 },
224 }
225
226 new_include_rules = [
227 '-ash',
228 '+base',
229 '+chrome',
230 '+components',
231 '+content',
232 '+grit',
233 '+grit/generated_resources.h",',
234 '+grit/",',
235 '+jni/fooblat.h',
236 '+policy',
manzagop85e629e2017-05-09 22:11:48237 '+' + os.path.join('third_party', 'WebKit'),
Daniel Cheng4dcdb6b2017-04-13 08:30:17238 ]
239 new_specific_include_rules = {
240 'compositor\.*': {
241 '+cc',
242 },
243 'widget\.*': {
244 '+gpu',
245 },
246 }
247
[email protected]f32e2d1e2013-07-26 21:39:08248 expected = set([
manzagop85e629e2017-05-09 22:11:48249 os.path.join('chrome', 'DEPS'),
250 os.path.join('gpu', 'DEPS'),
251 os.path.join('components', 'DEPS'),
252 os.path.join('policy', 'DEPS'),
253 os.path.join('third_party', 'WebKit', 'DEPS'),
[email protected]f32e2d1e2013-07-26 21:39:08254 ])
Daniel Cheng4dcdb6b2017-04-13 08:30:17255 self.assertEqual(
256 expected,
257 self.calculate(old_include_rules, old_specific_include_rules,
258 new_include_rules, new_specific_include_rules))
259
260 def testCalculateAddedDepsIgnoresPermutations(self):
261 old_include_rules = [
262 '+base',
263 '+chrome',
264 ]
265 new_include_rules = [
266 '+chrome',
267 '+base',
268 ]
269 self.assertEqual(set(),
270 self.calculate(old_include_rules, {}, new_include_rules,
271 {}))
[email protected]f32e2d1e2013-07-26 21:39:08272
273
[email protected]99171a92014-06-03 08:44:47274class JSONParsingTest(unittest.TestCase):
275 def testSuccess(self):
276 input_api = MockInputApi()
277 filename = 'valid_json.json'
278 contents = ['// This is a comment.',
279 '{',
280 ' "key1": ["value1", "value2"],',
281 ' "key2": 3 // This is an inline comment.',
282 '}'
283 ]
284 input_api.files = [MockFile(filename, contents)]
285 self.assertEqual(None,
286 PRESUBMIT._GetJSONParseError(input_api, filename))
287
288 def testFailure(self):
289 input_api = MockInputApi()
290 test_data = [
291 ('invalid_json_1.json',
292 ['{ x }'],
Dirk Prankee3c9c62d2021-05-18 18:35:59293 'Expecting property name'),
[email protected]99171a92014-06-03 08:44:47294 ('invalid_json_2.json',
295 ['// Hello world!',
296 '{ "hello": "world }'],
[email protected]a3343272014-06-17 11:41:53297 'Unterminated string starting at:'),
[email protected]99171a92014-06-03 08:44:47298 ('invalid_json_3.json',
299 ['{ "a": "b", "c": "d", }'],
Dirk Prankee3c9c62d2021-05-18 18:35:59300 'Expecting property name'),
[email protected]99171a92014-06-03 08:44:47301 ('invalid_json_4.json',
302 ['{ "a": "b" "c": "d" }'],
Dirk Prankee3c9c62d2021-05-18 18:35:59303 "Expecting ',' delimiter:"),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39304 ]
[email protected]99171a92014-06-03 08:44:47305
306 input_api.files = [MockFile(filename, contents)
307 for (filename, contents, _) in test_data]
308
309 for (filename, _, expected_error) in test_data:
310 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
[email protected]a3343272014-06-17 11:41:53311 self.assertTrue(expected_error in str(actual_error),
312 "'%s' not found in '%s'" % (expected_error, actual_error))
[email protected]99171a92014-06-03 08:44:47313
314 def testNoEatComments(self):
315 input_api = MockInputApi()
316 file_with_comments = 'file_with_comments.json'
317 contents_with_comments = ['// This is a comment.',
318 '{',
319 ' "key1": ["value1", "value2"],',
320 ' "key2": 3 // This is an inline comment.',
321 '}'
322 ]
323 file_without_comments = 'file_without_comments.json'
324 contents_without_comments = ['{',
325 ' "key1": ["value1", "value2"],',
326 ' "key2": 3',
327 '}'
328 ]
329 input_api.files = [MockFile(file_with_comments, contents_with_comments),
330 MockFile(file_without_comments,
331 contents_without_comments)]
332
Dirk Prankee3c9c62d2021-05-18 18:35:59333 self.assertNotEqual(None,
334 str(PRESUBMIT._GetJSONParseError(input_api,
335 file_with_comments,
336 eat_comments=False)))
[email protected]99171a92014-06-03 08:44:47337 self.assertEqual(None,
338 PRESUBMIT._GetJSONParseError(input_api,
339 file_without_comments,
340 eat_comments=False))
341
342
343class IDLParsingTest(unittest.TestCase):
344 def testSuccess(self):
345 input_api = MockInputApi()
346 filename = 'valid_idl_basics.idl'
347 contents = ['// Tests a valid IDL file.',
348 'namespace idl_basics {',
349 ' enum EnumType {',
350 ' name1,',
351 ' name2',
352 ' };',
353 '',
354 ' dictionary MyType1 {',
355 ' DOMString a;',
356 ' };',
357 '',
358 ' callback Callback1 = void();',
359 ' callback Callback2 = void(long x);',
360 ' callback Callback3 = void(MyType1 arg);',
361 ' callback Callback4 = void(EnumType type);',
362 '',
363 ' interface Functions {',
364 ' static void function1();',
365 ' static void function2(long x);',
366 ' static void function3(MyType1 arg);',
367 ' static void function4(Callback1 cb);',
368 ' static void function5(Callback2 cb);',
369 ' static void function6(Callback3 cb);',
370 ' static void function7(Callback4 cb);',
371 ' };',
372 '',
373 ' interface Events {',
374 ' static void onFoo1();',
375 ' static void onFoo2(long x);',
376 ' static void onFoo2(MyType1 arg);',
377 ' static void onFoo3(EnumType type);',
378 ' };',
379 '};'
380 ]
381 input_api.files = [MockFile(filename, contents)]
382 self.assertEqual(None,
383 PRESUBMIT._GetIDLParseError(input_api, filename))
384
385 def testFailure(self):
386 input_api = MockInputApi()
387 test_data = [
388 ('invalid_idl_1.idl',
389 ['//',
390 'namespace test {',
391 ' dictionary {',
392 ' DOMString s;',
393 ' };',
394 '};'],
395 'Unexpected "{" after keyword "dictionary".\n'),
396 # TODO(yoz): Disabled because it causes the IDL parser to hang.
397 # See crbug.com/363830.
398 # ('invalid_idl_2.idl',
399 # (['namespace test {',
400 # ' dictionary MissingSemicolon {',
401 # ' DOMString a',
402 # ' DOMString b;',
403 # ' };',
404 # '};'],
405 # 'Unexpected symbol DOMString after symbol a.'),
406 ('invalid_idl_3.idl',
407 ['//',
408 'namespace test {',
409 ' enum MissingComma {',
410 ' name1',
411 ' name2',
412 ' };',
413 '};'],
414 'Unexpected symbol name2 after symbol name1.'),
415 ('invalid_idl_4.idl',
416 ['//',
417 'namespace test {',
418 ' enum TrailingComma {',
419 ' name1,',
420 ' name2,',
421 ' };',
422 '};'],
423 'Trailing comma in block.'),
424 ('invalid_idl_5.idl',
425 ['//',
426 'namespace test {',
427 ' callback Callback1 = void(;',
428 '};'],
429 'Unexpected ";" after "(".'),
430 ('invalid_idl_6.idl',
431 ['//',
432 'namespace test {',
433 ' callback Callback1 = void(long );',
434 '};'],
435 'Unexpected ")" after symbol long.'),
436 ('invalid_idl_7.idl',
437 ['//',
438 'namespace test {',
439 ' interace Events {',
440 ' static void onFoo1();',
441 ' };',
442 '};'],
443 'Unexpected symbol Events after symbol interace.'),
444 ('invalid_idl_8.idl',
445 ['//',
446 'namespace test {',
447 ' interface NotEvent {',
448 ' static void onFoo1();',
449 ' };',
450 '};'],
451 'Did not process Interface Interface(NotEvent)'),
452 ('invalid_idl_9.idl',
453 ['//',
454 'namespace test {',
455 ' interface {',
456 ' static void function1();',
457 ' };',
458 '};'],
459 'Interface missing name.'),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39460 ]
[email protected]99171a92014-06-03 08:44:47461
462 input_api.files = [MockFile(filename, contents)
463 for (filename, contents, _) in test_data]
464
465 for (filename, _, expected_error) in test_data:
466 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
467 self.assertTrue(expected_error in str(actual_error),
468 "'%s' not found in '%s'" % (expected_error, actual_error))
469
470
davileene0426252015-03-02 21:10:41471class UserMetricsActionTest(unittest.TestCase):
472 def testUserMetricsActionInActions(self):
473 input_api = MockInputApi()
474 file_with_user_action = 'file_with_user_action.cc'
475 contents_with_user_action = [
476 'base::UserMetricsAction("AboutChrome")'
477 ]
478
479 input_api.files = [MockFile(file_with_user_action,
480 contents_with_user_action)]
481
482 self.assertEqual(
Saagar Sanghavifceeaae2020-08-12 16:40:36483 [], PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi()))
davileene0426252015-03-02 21:10:41484
davileene0426252015-03-02 21:10:41485 def testUserMetricsActionNotAddedToActions(self):
486 input_api = MockInputApi()
487 file_with_user_action = 'file_with_user_action.cc'
488 contents_with_user_action = [
489 'base::UserMetricsAction("NotInActionsXml")'
490 ]
491
492 input_api.files = [MockFile(file_with_user_action,
493 contents_with_user_action)]
494
Saagar Sanghavifceeaae2020-08-12 16:40:36495 output = PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi())
davileene0426252015-03-02 21:10:41496 self.assertEqual(
497 ('File %s line %d: %s is missing in '
498 'tools/metrics/actions/actions.xml. Please run '
499 'tools/metrics/actions/extract_actions.py to update.'
500 % (file_with_user_action, 1, 'NotInActionsXml')),
501 output[0].message)
502
Alexei Svitkine64505a92021-03-11 22:00:54503 def testUserMetricsActionInTestFile(self):
504 input_api = MockInputApi()
505 file_with_user_action = 'file_with_user_action_unittest.cc'
506 contents_with_user_action = [
507 'base::UserMetricsAction("NotInActionsXml")'
508 ]
509
510 input_api.files = [MockFile(file_with_user_action,
511 contents_with_user_action)]
512
513 self.assertEqual(
514 [], PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi()))
515
davileene0426252015-03-02 21:10:41516
agrievef32bcc72016-04-04 14:57:40517class PydepsNeedsUpdatingTest(unittest.TestCase):
518
519 class MockSubprocess(object):
520 CalledProcessError = subprocess.CalledProcessError
521
Mohamed Heikal7cd4d8312020-06-16 16:49:40522 def _MockParseGclientArgs(self, is_android=True):
523 return lambda: {'checkout_android': 'true' if is_android else 'false' }
524
agrievef32bcc72016-04-04 14:57:40525 def setUp(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40526 mock_all_pydeps = ['A.pydeps', 'B.pydeps', 'D.pydeps']
agrievef32bcc72016-04-04 14:57:40527 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
528 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
Mohamed Heikal7cd4d8312020-06-16 16:49:40529 mock_android_pydeps = ['D.pydeps']
530 self.old_ANDROID_SPECIFIC_PYDEPS_FILES = (
531 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES)
532 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = mock_android_pydeps
533 self.old_ParseGclientArgs = PRESUBMIT._ParseGclientArgs
534 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs()
agrievef32bcc72016-04-04 14:57:40535 self.mock_input_api = MockInputApi()
536 self.mock_output_api = MockOutputApi()
537 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
538 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
539 self.checker._file_cache = {
Andrew Grieve5bb4cf702020-10-22 20:21:39540 'A.pydeps': '# Generated by:\n# CMD --output A.pydeps A\nA.py\nC.py\n',
541 'B.pydeps': '# Generated by:\n# CMD --output B.pydeps B\nB.py\nC.py\n',
542 'D.pydeps': '# Generated by:\n# CMD --output D.pydeps D\nD.py\n',
agrievef32bcc72016-04-04 14:57:40543 }
544
545 def tearDown(self):
546 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
Mohamed Heikal7cd4d8312020-06-16 16:49:40547 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = (
548 self.old_ANDROID_SPECIFIC_PYDEPS_FILES)
549 PRESUBMIT._ParseGclientArgs = self.old_ParseGclientArgs
agrievef32bcc72016-04-04 14:57:40550
551 def _RunCheck(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36552 return PRESUBMIT.CheckPydepsNeedsUpdating(self.mock_input_api,
agrievef32bcc72016-04-04 14:57:40553 self.mock_output_api,
554 checker_for_tests=self.checker)
555
556 def testAddedPydep(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36557 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Mohamed Heikal112874d2021-11-15 14:42:20558 if self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13559 return []
560
agrievef32bcc72016-04-04 14:57:40561 self.mock_input_api.files = [
562 MockAffectedFile('new.pydeps', [], action='A'),
563 ]
564
Zhiling Huang45cabf32018-03-10 00:50:03565 self.mock_input_api.CreateMockFileInPath(
566 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
567 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40568 results = self._RunCheck()
569 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39570 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40571
Zhiling Huang45cabf32018-03-10 00:50:03572 def testPydepNotInSrc(self):
573 self.mock_input_api.files = [
574 MockAffectedFile('new.pydeps', [], action='A'),
575 ]
576 self.mock_input_api.CreateMockFileInPath([])
577 results = self._RunCheck()
578 self.assertEqual(0, len(results))
579
agrievef32bcc72016-04-04 14:57:40580 def testRemovedPydep(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36581 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Mohamed Heikal112874d2021-11-15 14:42:20582 if self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13583 return []
584
agrievef32bcc72016-04-04 14:57:40585 self.mock_input_api.files = [
586 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
587 ]
Zhiling Huang45cabf32018-03-10 00:50:03588 self.mock_input_api.CreateMockFileInPath(
589 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
590 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40591 results = self._RunCheck()
592 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39593 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40594
595 def testRandomPyIgnored(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36596 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Mohamed Heikal112874d2021-11-15 14:42:20597 if self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13598 return []
599
agrievef32bcc72016-04-04 14:57:40600 self.mock_input_api.files = [
601 MockAffectedFile('random.py', []),
602 ]
603
604 results = self._RunCheck()
605 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
606
607 def testRelevantPyNoChange(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36608 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Mohamed Heikal112874d2021-11-15 14:42:20609 if self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13610 return []
611
agrievef32bcc72016-04-04 14:57:40612 self.mock_input_api.files = [
613 MockAffectedFile('A.py', []),
614 ]
615
John Budorickab2fa102017-10-06 16:59:49616 def mock_check_output(cmd, shell=False, env=None):
Andrew Grieve5bb4cf702020-10-22 20:21:39617 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
agrievef32bcc72016-04-04 14:57:40618 return self.checker._file_cache['A.pydeps']
619
620 self.mock_input_api.subprocess.check_output = mock_check_output
621
622 results = self._RunCheck()
623 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
624
625 def testRelevantPyOneChange(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36626 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Mohamed Heikal112874d2021-11-15 14:42:20627 if self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13628 return []
629
agrievef32bcc72016-04-04 14:57:40630 self.mock_input_api.files = [
631 MockAffectedFile('A.py', []),
632 ]
633
John Budorickab2fa102017-10-06 16:59:49634 def mock_check_output(cmd, shell=False, env=None):
Andrew Grieve5bb4cf702020-10-22 20:21:39635 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
agrievef32bcc72016-04-04 14:57:40636 return 'changed data'
637
638 self.mock_input_api.subprocess.check_output = mock_check_output
639
640 results = self._RunCheck()
641 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39642 self.assertIn('File is stale', str(results[0]))
agrievef32bcc72016-04-04 14:57:40643
644 def testRelevantPyTwoChanges(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36645 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Mohamed Heikal112874d2021-11-15 14:42:20646 if self.mock_input_api.platform.startswith('linux'):
pastarmovj89f7ee12016-09-20 14:58:13647 return []
648
agrievef32bcc72016-04-04 14:57:40649 self.mock_input_api.files = [
650 MockAffectedFile('C.py', []),
651 ]
652
John Budorickab2fa102017-10-06 16:59:49653 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40654 return 'changed data'
655
656 self.mock_input_api.subprocess.check_output = mock_check_output
657
658 results = self._RunCheck()
659 self.assertEqual(2, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39660 self.assertIn('File is stale', str(results[0]))
661 self.assertIn('File is stale', str(results[1]))
agrievef32bcc72016-04-04 14:57:40662
Mohamed Heikal7cd4d8312020-06-16 16:49:40663 def testRelevantAndroidPyInNonAndroidCheckout(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36664 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Mohamed Heikal112874d2021-11-15 14:42:20665 if self.mock_input_api.platform.startswith('linux'):
Mohamed Heikal7cd4d8312020-06-16 16:49:40666 return []
667
668 self.mock_input_api.files = [
669 MockAffectedFile('D.py', []),
670 ]
671
672 def mock_check_output(cmd, shell=False, env=None):
Andrew Grieve5bb4cf702020-10-22 20:21:39673 self.assertEqual('CMD --output D.pydeps D --output ""', cmd)
Mohamed Heikal7cd4d8312020-06-16 16:49:40674 return 'changed data'
675
676 self.mock_input_api.subprocess.check_output = mock_check_output
677 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs(is_android=False)
678
679 results = self._RunCheck()
680 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39681 self.assertIn('Android', str(results[0]))
682 self.assertIn('D.pydeps', str(results[0]))
683
684 def testGnPathsAndMissingOutputFlag(self):
685 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Mohamed Heikal112874d2021-11-15 14:42:20686 if self.mock_input_api.platform.startswith('linux'):
Andrew Grieve5bb4cf702020-10-22 20:21:39687 return []
688
689 self.checker._file_cache = {
690 'A.pydeps': '# Generated by:\n# CMD --gn-paths A\n//A.py\n//C.py\n',
691 'B.pydeps': '# Generated by:\n# CMD --gn-paths B\n//B.py\n//C.py\n',
692 'D.pydeps': '# Generated by:\n# CMD --gn-paths D\n//D.py\n',
693 }
694
695 self.mock_input_api.files = [
696 MockAffectedFile('A.py', []),
697 ]
698
699 def mock_check_output(cmd, shell=False, env=None):
700 self.assertEqual('CMD --gn-paths A --output A.pydeps --output ""', cmd)
701 return 'changed data'
702
703 self.mock_input_api.subprocess.check_output = mock_check_output
704
705 results = self._RunCheck()
706 self.assertEqual(1, len(results))
707 self.assertIn('File is stale', str(results[0]))
Mohamed Heikal7cd4d8312020-06-16 16:49:40708
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39709
Daniel Bratell8ba52722018-03-02 16:06:14710class IncludeGuardTest(unittest.TestCase):
711 def testIncludeGuardChecks(self):
712 mock_input_api = MockInputApi()
713 mock_output_api = MockOutputApi()
714 mock_input_api.files = [
715 MockAffectedFile('content/browser/thing/foo.h', [
716 '// Comment',
717 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
718 '#define CONTENT_BROWSER_THING_FOO_H_',
719 'struct McBoatFace;',
720 '#endif // CONTENT_BROWSER_THING_FOO_H_',
721 ]),
722 MockAffectedFile('content/browser/thing/bar.h', [
723 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
724 '#define CONTENT_BROWSER_THING_BAR_H_',
725 'namespace content {',
726 '#endif // CONTENT_BROWSER_THING_BAR_H_',
727 '} // namespace content',
728 ]),
729 MockAffectedFile('content/browser/test1.h', [
730 'namespace content {',
731 '} // namespace content',
732 ]),
733 MockAffectedFile('content\\browser\\win.h', [
734 '#ifndef CONTENT_BROWSER_WIN_H_',
735 '#define CONTENT_BROWSER_WIN_H_',
736 'struct McBoatFace;',
737 '#endif // CONTENT_BROWSER_WIN_H_',
738 ]),
739 MockAffectedFile('content/browser/test2.h', [
740 '// Comment',
741 '#ifndef CONTENT_BROWSER_TEST2_H_',
742 'struct McBoatFace;',
743 '#endif // CONTENT_BROWSER_TEST2_H_',
744 ]),
745 MockAffectedFile('content/browser/internal.h', [
746 '// Comment',
747 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
748 '#define CONTENT_BROWSER_INTERNAL_H_',
749 '// Comment',
750 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
751 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
752 'namespace internal {',
753 '} // namespace internal',
754 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
755 'namespace content {',
756 '} // namespace content',
757 '#endif // CONTENT_BROWSER_THING_BAR_H_',
758 ]),
759 MockAffectedFile('content/browser/thing/foo.cc', [
760 '// This is a non-header.',
761 ]),
762 MockAffectedFile('content/browser/disabled.h', [
763 '// no-include-guard-because-multiply-included',
764 'struct McBoatFace;',
765 ]),
766 # New files don't allow misspelled include guards.
767 MockAffectedFile('content/browser/spleling.h', [
768 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
769 '#define CONTENT_BROWSER_SPLLEING_H_',
770 'struct McBoatFace;',
771 '#endif // CONTENT_BROWSER_SPLLEING_H_',
772 ]),
Olivier Robinbba137492018-07-30 11:31:34773 # New files don't allow + in include guards.
774 MockAffectedFile('content/browser/foo+bar.h', [
775 '#ifndef CONTENT_BROWSER_FOO+BAR_H_',
776 '#define CONTENT_BROWSER_FOO+BAR_H_',
777 'struct McBoatFace;',
778 '#endif // CONTENT_BROWSER_FOO+BAR_H_',
779 ]),
Daniel Bratell8ba52722018-03-02 16:06:14780 # Old files allow misspelled include guards (for now).
781 MockAffectedFile('chrome/old.h', [
782 '// New contents',
783 '#ifndef CHROME_ODL_H_',
784 '#define CHROME_ODL_H_',
785 '#endif // CHROME_ODL_H_',
786 ], [
787 '// Old contents',
788 '#ifndef CHROME_ODL_H_',
789 '#define CHROME_ODL_H_',
790 '#endif // CHROME_ODL_H_',
791 ]),
792 # Using a Blink style include guard outside Blink is wrong.
793 MockAffectedFile('content/NotInBlink.h', [
794 '#ifndef NotInBlink_h',
795 '#define NotInBlink_h',
796 'struct McBoatFace;',
797 '#endif // NotInBlink_h',
798 ]),
Daniel Bratell39b5b062018-05-16 18:09:57799 # Using a Blink style include guard in Blink is no longer ok.
800 MockAffectedFile('third_party/blink/InBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14801 '#ifndef InBlink_h',
802 '#define InBlink_h',
803 'struct McBoatFace;',
804 '#endif // InBlink_h',
805 ]),
806 # Using a bad include guard in Blink is not ok.
Daniel Bratell39b5b062018-05-16 18:09:57807 MockAffectedFile('third_party/blink/AlsoInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14808 '#ifndef WrongInBlink_h',
809 '#define WrongInBlink_h',
810 'struct McBoatFace;',
811 '#endif // WrongInBlink_h',
812 ]),
Daniel Bratell39b5b062018-05-16 18:09:57813 # Using a bad include guard in Blink is not accepted even if
814 # it's an old file.
815 MockAffectedFile('third_party/blink/StillInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14816 '// New contents',
817 '#ifndef AcceptedInBlink_h',
818 '#define AcceptedInBlink_h',
819 'struct McBoatFace;',
820 '#endif // AcceptedInBlink_h',
821 ], [
822 '// Old contents',
823 '#ifndef AcceptedInBlink_h',
824 '#define AcceptedInBlink_h',
825 'struct McBoatFace;',
826 '#endif // AcceptedInBlink_h',
827 ]),
Daniel Bratell39b5b062018-05-16 18:09:57828 # Using a non-Chromium include guard in third_party
829 # (outside blink) is accepted.
830 MockAffectedFile('third_party/foo/some_file.h', [
831 '#ifndef REQUIRED_RPCNDR_H_',
832 '#define REQUIRED_RPCNDR_H_',
833 'struct SomeFileFoo;',
834 '#endif // REQUIRED_RPCNDR_H_',
835 ]),
Kinuko Yasuda0cdb3da2019-07-31 21:50:32836 # Not having proper include guard in *_message_generator.h
837 # for old IPC messages is allowed.
838 MockAffectedFile('content/common/content_message_generator.h', [
839 '#undef CONTENT_COMMON_FOO_MESSAGES_H_',
840 '#include "content/common/foo_messages.h"',
841 '#ifndef CONTENT_COMMON_FOO_MESSAGES_H_',
842 '#error "Failed to include content/common/foo_messages.h"',
843 '#endif',
844 ]),
Daniel Bratell8ba52722018-03-02 16:06:14845 ]
Saagar Sanghavifceeaae2020-08-12 16:40:36846 msgs = PRESUBMIT.CheckForIncludeGuards(
Daniel Bratell8ba52722018-03-02 16:06:14847 mock_input_api, mock_output_api)
Olivier Robinbba137492018-07-30 11:31:34848 expected_fail_count = 8
Daniel Bratell8ba52722018-03-02 16:06:14849 self.assertEqual(expected_fail_count, len(msgs),
850 'Expected %d items, found %d: %s'
851 % (expected_fail_count, len(msgs), msgs))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39852 self.assertEqual(msgs[0].items, ['content/browser/thing/bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:14853 self.assertEqual(msgs[0].message,
854 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
855 'not covering the whole file')
856
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39857 self.assertEqual(msgs[1].items, ['content/browser/test1.h'])
Daniel Bratell8ba52722018-03-02 16:06:14858 self.assertEqual(msgs[1].message,
859 'Missing include guard CONTENT_BROWSER_TEST1_H_')
860
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39861 self.assertEqual(msgs[2].items, ['content/browser/test2.h:3'])
Daniel Bratell8ba52722018-03-02 16:06:14862 self.assertEqual(msgs[2].message,
863 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
864 'include guard')
865
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39866 self.assertEqual(msgs[3].items, ['content/browser/spleling.h:1'])
Daniel Bratell8ba52722018-03-02 16:06:14867 self.assertEqual(msgs[3].message,
868 'Header using the wrong include guard name '
869 'CONTENT_BROWSER_SPLLEING_H_')
870
Olivier Robinbba137492018-07-30 11:31:34871 self.assertEqual(msgs[4].items, ['content/browser/foo+bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:14872 self.assertEqual(msgs[4].message,
Olivier Robinbba137492018-07-30 11:31:34873 'Missing include guard CONTENT_BROWSER_FOO_BAR_H_')
874
875 self.assertEqual(msgs[5].items, ['content/NotInBlink.h:1'])
876 self.assertEqual(msgs[5].message,
Daniel Bratell8ba52722018-03-02 16:06:14877 'Header using the wrong include guard name '
878 'NotInBlink_h')
879
Olivier Robinbba137492018-07-30 11:31:34880 self.assertEqual(msgs[6].items, ['third_party/blink/InBlink.h:1'])
881 self.assertEqual(msgs[6].message,
Daniel Bratell8ba52722018-03-02 16:06:14882 'Header using the wrong include guard name '
Daniel Bratell39b5b062018-05-16 18:09:57883 'InBlink_h')
884
Olivier Robinbba137492018-07-30 11:31:34885 self.assertEqual(msgs[7].items, ['third_party/blink/AlsoInBlink.h:1'])
886 self.assertEqual(msgs[7].message,
Daniel Bratell39b5b062018-05-16 18:09:57887 'Header using the wrong include guard name '
Daniel Bratell8ba52722018-03-02 16:06:14888 'WrongInBlink_h')
889
Chris Hall59f8d0c72020-05-01 07:31:19890class AccessibilityRelnotesFieldTest(unittest.TestCase):
891 def testRelnotesPresent(self):
892 mock_input_api = MockInputApi()
893 mock_output_api = MockOutputApi()
894
895 mock_input_api.files = [MockAffectedFile('ui/accessibility/foo.bar', [''])]
Akihiro Ota08108e542020-05-20 15:30:53896 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19897 mock_input_api.change.footers['AX-Relnotes'] = [
898 'Important user facing change']
899
Saagar Sanghavifceeaae2020-08-12 16:40:36900 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19901 mock_input_api, mock_output_api)
902 self.assertEqual(0, len(msgs),
903 'Expected %d messages, found %d: %s'
904 % (0, len(msgs), msgs))
905
906 def testRelnotesMissingFromAccessibilityChange(self):
907 mock_input_api = MockInputApi()
908 mock_output_api = MockOutputApi()
909
910 mock_input_api.files = [
911 MockAffectedFile('some/file', ['']),
912 MockAffectedFile('ui/accessibility/foo.bar', ['']),
913 MockAffectedFile('some/other/file', [''])
914 ]
Akihiro Ota08108e542020-05-20 15:30:53915 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19916
Saagar Sanghavifceeaae2020-08-12 16:40:36917 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19918 mock_input_api, mock_output_api)
919 self.assertEqual(1, len(msgs),
920 'Expected %d messages, found %d: %s'
921 % (1, len(msgs), msgs))
922 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
923 'Missing AX-Relnotes field message not found in errors')
924
925 # The relnotes footer is not required for changes which do not touch any
926 # accessibility directories.
927 def testIgnoresNonAccesssibilityCode(self):
928 mock_input_api = MockInputApi()
929 mock_output_api = MockOutputApi()
930
931 mock_input_api.files = [
932 MockAffectedFile('some/file', ['']),
933 MockAffectedFile('some/other/file', [''])
934 ]
Akihiro Ota08108e542020-05-20 15:30:53935 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19936
Saagar Sanghavifceeaae2020-08-12 16:40:36937 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19938 mock_input_api, mock_output_api)
939 self.assertEqual(0, len(msgs),
940 'Expected %d messages, found %d: %s'
941 % (0, len(msgs), msgs))
942
943 # Test that our presubmit correctly raises an error for a set of known paths.
944 def testExpectedPaths(self):
945 filesToTest = [
946 "chrome/browser/accessibility/foo.py",
Henrique Ferreirobb1bb4a2021-03-18 00:04:08947 "chrome/browser/ash/arc/accessibility/foo.cc",
Chris Hall59f8d0c72020-05-01 07:31:19948 "chrome/browser/ui/views/accessibility/foo.h",
949 "chrome/browser/extensions/api/automation/foo.h",
950 "chrome/browser/extensions/api/automation_internal/foo.cc",
951 "chrome/renderer/extensions/accessibility_foo.h",
952 "chrome/tests/data/accessibility/foo.html",
953 "content/browser/accessibility/foo.cc",
954 "content/renderer/accessibility/foo.h",
955 "content/tests/data/accessibility/foo.cc",
956 "extensions/renderer/api/automation/foo.h",
957 "ui/accessibility/foo/bar/baz.cc",
958 "ui/views/accessibility/foo/bar/baz.h",
959 ]
960
961 for testFile in filesToTest:
962 mock_input_api = MockInputApi()
963 mock_output_api = MockOutputApi()
964
965 mock_input_api.files = [
966 MockAffectedFile(testFile, [''])
967 ]
Akihiro Ota08108e542020-05-20 15:30:53968 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19969
Saagar Sanghavifceeaae2020-08-12 16:40:36970 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:19971 mock_input_api, mock_output_api)
972 self.assertEqual(1, len(msgs),
973 'Expected %d messages, found %d: %s, for file %s'
974 % (1, len(msgs), msgs, testFile))
975 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
976 ('Missing AX-Relnotes field message not found in errors '
977 ' for file %s' % (testFile)))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39978
Akihiro Ota08108e542020-05-20 15:30:53979 # Test that AX-Relnotes field can appear in the commit description (as long
980 # as it appears at the beginning of a line).
981 def testRelnotesInCommitDescription(self):
982 mock_input_api = MockInputApi()
983 mock_output_api = MockOutputApi()
984
985 mock_input_api.files = [
986 MockAffectedFile('ui/accessibility/foo.bar', ['']),
987 ]
988 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
989 'AX-Relnotes: solves all accessibility issues forever')
990
Saagar Sanghavifceeaae2020-08-12 16:40:36991 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:53992 mock_input_api, mock_output_api)
993 self.assertEqual(0, len(msgs),
994 'Expected %d messages, found %d: %s'
995 % (0, len(msgs), msgs))
996
997 # Test that we don't match AX-Relnotes if it appears in the middle of a line.
998 def testRelnotesMustAppearAtBeginningOfLine(self):
999 mock_input_api = MockInputApi()
1000 mock_output_api = MockOutputApi()
1001
1002 mock_input_api.files = [
1003 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1004 ]
1005 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1006 'This change has no AX-Relnotes: we should print a warning')
1007
Saagar Sanghavifceeaae2020-08-12 16:40:361008 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531009 mock_input_api, mock_output_api)
1010 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1011 'Missing AX-Relnotes field message not found in errors')
1012
1013 # Tests that the AX-Relnotes field can be lowercase and use a '=' in place
1014 # of a ':'.
1015 def testRelnotesLowercaseWithEqualSign(self):
1016 mock_input_api = MockInputApi()
1017 mock_output_api = MockOutputApi()
1018
1019 mock_input_api.files = [
1020 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1021 ]
1022 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1023 'ax-relnotes= this is a valid format for accessibiliy relnotes')
1024
Saagar Sanghavifceeaae2020-08-12 16:40:361025 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531026 mock_input_api, mock_output_api)
1027 self.assertEqual(0, len(msgs),
1028 'Expected %d messages, found %d: %s'
1029 % (0, len(msgs), msgs))
1030
yolandyan45001472016-12-21 21:12:421031class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
1032 def testCheckAndroidTestAnnotationUsage(self):
1033 mock_input_api = MockInputApi()
1034 mock_output_api = MockOutputApi()
1035
1036 mock_input_api.files = [
1037 MockAffectedFile('LalaLand.java', [
1038 'random stuff'
1039 ]),
1040 MockAffectedFile('CorrectUsage.java', [
1041 'import android.support.test.filters.LargeTest;',
1042 'import android.support.test.filters.MediumTest;',
1043 'import android.support.test.filters.SmallTest;',
1044 ]),
1045 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
1046 'import android.test.suitebuilder.annotation.LargeTest;',
1047 ]),
1048 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
1049 'import android.test.suitebuilder.annotation.MediumTest;',
1050 ]),
1051 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
1052 'import android.test.suitebuilder.annotation.SmallTest;',
1053 ]),
1054 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
1055 'import android.test.suitebuilder.annotation.Smoke;',
1056 ])
1057 ]
1058 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
1059 mock_input_api, mock_output_api)
1060 self.assertEqual(1, len(msgs),
1061 'Expected %d items, found %d: %s'
1062 % (1, len(msgs), msgs))
1063 self.assertEqual(4, len(msgs[0].items),
1064 'Expected %d items, found %d: %s'
1065 % (4, len(msgs[0].items), msgs[0].items))
1066 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
1067 'UsedDeprecatedLargeTestAnnotation not found in errors')
1068 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
1069 in msgs[0].items,
1070 'UsedDeprecatedMediumTestAnnotation not found in errors')
1071 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
1072 'UsedDeprecatedSmallTestAnnotation not found in errors')
1073 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
1074 'UsedDeprecatedSmokeAnnotation not found in errors')
1075
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391076
Mohamed Heikal5e5b7922020-10-29 18:57:591077class CheckNoDownstreamDepsTest(unittest.TestCase):
1078 def testInvalidDepFromUpstream(self):
1079 mock_input_api = MockInputApi()
1080 mock_output_api = MockOutputApi()
1081
1082 mock_input_api.files = [
1083 MockAffectedFile('BUILD.gn', [
1084 'deps = [',
1085 ' "//clank/target:test",',
1086 ']'
1087 ]),
1088 MockAffectedFile('chrome/android/BUILD.gn', [
1089 'deps = [ "//clank/target:test" ]'
1090 ]),
1091 MockAffectedFile('chrome/chrome_java_deps.gni', [
1092 'java_deps = [',
1093 ' "//clank/target:test",',
1094 ']'
1095 ]),
1096 ]
1097 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1098 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1099 mock_input_api, mock_output_api)
1100 self.assertEqual(1, len(msgs),
1101 'Expected %d items, found %d: %s'
1102 % (1, len(msgs), msgs))
1103 self.assertEqual(3, len(msgs[0].items),
1104 'Expected %d items, found %d: %s'
1105 % (3, len(msgs[0].items), msgs[0].items))
1106 self.assertTrue(any('BUILD.gn:2' in item for item in msgs[0].items),
1107 'BUILD.gn not found in errors')
1108 self.assertTrue(
1109 any('chrome/android/BUILD.gn:1' in item for item in msgs[0].items),
1110 'chrome/android/BUILD.gn:1 not found in errors')
1111 self.assertTrue(
1112 any('chrome/chrome_java_deps.gni:2' in item for item in msgs[0].items),
1113 'chrome/chrome_java_deps.gni:2 not found in errors')
1114
1115 def testAllowsComments(self):
1116 mock_input_api = MockInputApi()
1117 mock_output_api = MockOutputApi()
1118
1119 mock_input_api.files = [
1120 MockAffectedFile('BUILD.gn', [
1121 '# real implementation in //clank/target:test',
1122 ]),
1123 ]
1124 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1125 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1126 mock_input_api, mock_output_api)
1127 self.assertEqual(0, len(msgs),
1128 'Expected %d items, found %d: %s'
1129 % (0, len(msgs), msgs))
1130
1131 def testOnlyChecksBuildFiles(self):
1132 mock_input_api = MockInputApi()
1133 mock_output_api = MockOutputApi()
1134
1135 mock_input_api.files = [
1136 MockAffectedFile('README.md', [
1137 'DEPS = [ "//clank/target:test" ]'
1138 ]),
1139 MockAffectedFile('chrome/android/java/file.java', [
1140 '//clank/ only function'
1141 ]),
1142 ]
1143 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src'
1144 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1145 mock_input_api, mock_output_api)
1146 self.assertEqual(0, len(msgs),
1147 'Expected %d items, found %d: %s'
1148 % (0, len(msgs), msgs))
1149
1150 def testValidDepFromDownstream(self):
1151 mock_input_api = MockInputApi()
1152 mock_output_api = MockOutputApi()
1153
1154 mock_input_api.files = [
1155 MockAffectedFile('BUILD.gn', [
1156 'DEPS = [',
1157 ' "//clank/target:test",',
1158 ']'
1159 ]),
1160 MockAffectedFile('java/BUILD.gn', [
1161 'DEPS = [ "//clank/target:test" ]'
1162 ]),
1163 ]
1164 mock_input_api.change.RepositoryRoot = lambda: 'chromium/src/clank'
1165 msgs = PRESUBMIT.CheckNoUpstreamDepsOnClank(
1166 mock_input_api, mock_output_api)
1167 self.assertEqual(0, len(msgs),
1168 'Expected %d items, found %d: %s'
1169 % (0, len(msgs), msgs))
1170
Yoland Yanb92fa522017-08-28 17:37:061171class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271172 def testCheckAndroidTestJUnitFramework(self):
Yoland Yanb92fa522017-08-28 17:37:061173 mock_input_api = MockInputApi()
1174 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:421175
Yoland Yanb92fa522017-08-28 17:37:061176 mock_input_api.files = [
1177 MockAffectedFile('LalaLand.java', [
1178 'random stuff'
1179 ]),
1180 MockAffectedFile('CorrectUsage.java', [
1181 'import org.junit.ABC',
1182 'import org.junit.XYZ;',
1183 ]),
1184 MockAffectedFile('UsedDeprecatedJUnit.java', [
1185 'import junit.framework.*;',
1186 ]),
1187 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
1188 'import junit.framework.Assert;',
1189 ]),
1190 ]
1191 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
1192 mock_input_api, mock_output_api)
1193 self.assertEqual(1, len(msgs),
1194 'Expected %d items, found %d: %s'
1195 % (1, len(msgs), msgs))
1196 self.assertEqual(2, len(msgs[0].items),
1197 'Expected %d items, found %d: %s'
1198 % (2, len(msgs[0].items), msgs[0].items))
1199 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
1200 'UsedDeprecatedJUnit.java not found in errors')
1201 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
1202 in msgs[0].items,
1203 'UsedDeprecatedJUnitAssert not found in errors')
1204
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391205
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271206class AndroidJUnitBaseClassTest(unittest.TestCase):
1207 def testCheckAndroidTestJUnitBaseClass(self):
Yoland Yanb92fa522017-08-28 17:37:061208 mock_input_api = MockInputApi()
1209 mock_output_api = MockOutputApi()
1210
1211 mock_input_api.files = [
1212 MockAffectedFile('LalaLand.java', [
1213 'random stuff'
1214 ]),
1215 MockAffectedFile('CorrectTest.java', [
1216 '@RunWith(ABC.class);'
1217 'public class CorrectTest {',
1218 '}',
1219 ]),
1220 MockAffectedFile('HistoricallyIncorrectTest.java', [
1221 'public class Test extends BaseCaseA {',
1222 '}',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391223 ], old_contents=[
Yoland Yanb92fa522017-08-28 17:37:061224 'public class Test extends BaseCaseB {',
1225 '}',
1226 ]),
1227 MockAffectedFile('CorrectTestWithInterface.java', [
1228 '@RunWith(ABC.class);'
1229 'public class CorrectTest implement Interface {',
1230 '}',
1231 ]),
1232 MockAffectedFile('IncorrectTest.java', [
1233 'public class IncorrectTest extends TestCase {',
1234 '}',
1235 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241236 MockAffectedFile('IncorrectWithInterfaceTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061237 'public class Test implements X extends BaseClass {',
1238 '}',
1239 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241240 MockAffectedFile('IncorrectMultiLineTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061241 'public class Test implements X, Y, Z',
1242 ' extends TestBase {',
1243 '}',
1244 ]),
1245 ]
1246 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1247 mock_input_api, mock_output_api)
1248 self.assertEqual(1, len(msgs),
1249 'Expected %d items, found %d: %s'
1250 % (1, len(msgs), msgs))
1251 self.assertEqual(3, len(msgs[0].items),
1252 'Expected %d items, found %d: %s'
1253 % (3, len(msgs[0].items), msgs[0].items))
1254 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1255 'IncorrectTest not found in errors')
Vaclav Brozekf01ed502018-03-16 19:38:241256 self.assertTrue('IncorrectWithInterfaceTest.java:1'
Yoland Yanb92fa522017-08-28 17:37:061257 in msgs[0].items,
Vaclav Brozekf01ed502018-03-16 19:38:241258 'IncorrectWithInterfaceTest not found in errors')
1259 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1260 'IncorrectMultiLineTest not found in errors')
yolandyan45001472016-12-21 21:12:421261
Jinsong Fan91ebbbd2019-04-16 14:57:171262class AndroidDebuggableBuildTest(unittest.TestCase):
1263
1264 def testCheckAndroidDebuggableBuild(self):
1265 mock_input_api = MockInputApi()
1266 mock_output_api = MockOutputApi()
1267
1268 mock_input_api.files = [
1269 MockAffectedFile('RandomStuff.java', [
1270 'random stuff'
1271 ]),
1272 MockAffectedFile('CorrectUsage.java', [
1273 'import org.chromium.base.BuildInfo;',
1274 'some random stuff',
1275 'boolean isOsDebuggable = BuildInfo.isDebugAndroid();',
1276 ]),
1277 MockAffectedFile('JustCheckUserdebugBuild.java', [
1278 'import android.os.Build;',
1279 'some random stuff',
1280 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")',
1281 ]),
1282 MockAffectedFile('JustCheckEngineeringBuild.java', [
1283 'import android.os.Build;',
1284 'some random stuff',
1285 'boolean isOsDebuggable = "eng".equals(Build.TYPE)',
1286 ]),
1287 MockAffectedFile('UsedBuildType.java', [
1288 'import android.os.Build;',
1289 'some random stuff',
1290 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")'
1291 '|| "eng".equals(Build.TYPE)',
1292 ]),
1293 MockAffectedFile('UsedExplicitBuildType.java', [
1294 'some random stuff',
1295 'boolean isOsDebuggable = android.os.Build.TYPE.equals("userdebug")'
1296 '|| "eng".equals(android.os.Build.TYPE)',
1297 ]),
1298 ]
1299
1300 msgs = PRESUBMIT._CheckAndroidDebuggableBuild(
1301 mock_input_api, mock_output_api)
1302 self.assertEqual(1, len(msgs),
1303 'Expected %d items, found %d: %s'
1304 % (1, len(msgs), msgs))
1305 self.assertEqual(4, len(msgs[0].items),
1306 'Expected %d items, found %d: %s'
1307 % (4, len(msgs[0].items), msgs[0].items))
1308 self.assertTrue('JustCheckUserdebugBuild.java:3' in msgs[0].items)
1309 self.assertTrue('JustCheckEngineeringBuild.java:3' in msgs[0].items)
1310 self.assertTrue('UsedBuildType.java:3' in msgs[0].items)
1311 self.assertTrue('UsedExplicitBuildType.java:2' in msgs[0].items)
1312
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391313
dgn4401aa52015-04-29 16:26:171314class LogUsageTest(unittest.TestCase):
1315
dgnaa68d5e2015-06-10 10:08:221316 def testCheckAndroidCrLogUsage(self):
1317 mock_input_api = MockInputApi()
1318 mock_output_api = MockOutputApi()
1319
1320 mock_input_api.files = [
1321 MockAffectedFile('RandomStuff.java', [
1322 'random stuff'
1323 ]),
dgn87d9fb62015-06-12 09:15:121324 MockAffectedFile('HasAndroidLog.java', [
1325 'import android.util.Log;',
1326 'some random stuff',
1327 'Log.d("TAG", "foo");',
1328 ]),
1329 MockAffectedFile('HasExplicitUtilLog.java', [
1330 'some random stuff',
1331 'android.util.Log.d("TAG", "foo");',
1332 ]),
1333 MockAffectedFile('IsInBasePackage.java', [
1334 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511335 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121336 'Log.d(TAG, "foo");',
1337 ]),
1338 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1339 'package org.chromium.base;',
1340 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511341 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121342 'Log.d(TAG, "foo");',
1343 ]),
1344 MockAffectedFile('HasBothLog.java', [
1345 'import org.chromium.base.Log;',
1346 'some random stuff',
dgn38736db2015-09-18 19:20:511347 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121348 'Log.d(TAG, "foo");',
1349 'android.util.Log.d("TAG", "foo");',
1350 ]),
dgnaa68d5e2015-06-10 10:08:221351 MockAffectedFile('HasCorrectTag.java', [
1352 'import org.chromium.base.Log;',
1353 'some random stuff',
dgn38736db2015-09-18 19:20:511354 'private static final String TAG = "cr_Foo";',
1355 'Log.d(TAG, "foo");',
1356 ]),
1357 MockAffectedFile('HasOldTag.java', [
1358 'import org.chromium.base.Log;',
1359 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221360 'private static final String TAG = "cr.Foo";',
1361 'Log.d(TAG, "foo");',
1362 ]),
dgn38736db2015-09-18 19:20:511363 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221364 'import org.chromium.base.Log;',
1365 'some random stuff',
dgn38736db2015-09-18 19:20:511366 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221367 'Log.d(TAG, "foo");',
1368 ]),
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461369 MockAffectedFile('HasDottedTagPublic.java', [
1370 'import org.chromium.base.Log;',
1371 'some random stuff',
1372 'public static final String TAG = "cr_foo.bar";',
1373 'Log.d(TAG, "foo");',
1374 ]),
dgnaa68d5e2015-06-10 10:08:221375 MockAffectedFile('HasNoTagDecl.java', [
1376 'import org.chromium.base.Log;',
1377 'some random stuff',
1378 'Log.d(TAG, "foo");',
1379 ]),
1380 MockAffectedFile('HasIncorrectTagDecl.java', [
1381 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511382 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221383 'some random stuff',
1384 'Log.d(TAG, "foo");',
1385 ]),
1386 MockAffectedFile('HasInlineTag.java', [
1387 'import org.chromium.base.Log;',
1388 'some random stuff',
dgn38736db2015-09-18 19:20:511389 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221390 'Log.d("TAG", "foo");',
1391 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551392 MockAffectedFile('HasInlineTagWithSpace.java', [
1393 'import org.chromium.base.Log;',
1394 'some random stuff',
1395 'private static final String TAG = "cr_Foo";',
1396 'Log.d("log message", "foo");',
1397 ]),
dgn38736db2015-09-18 19:20:511398 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221399 'import org.chromium.base.Log;',
1400 'some random stuff',
1401 'private static final String TAG = "rubbish";',
1402 'Log.d(TAG, "foo");',
1403 ]),
1404 MockAffectedFile('HasTooLongTag.java', [
1405 'import org.chromium.base.Log;',
1406 'some random stuff',
dgn38736db2015-09-18 19:20:511407 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:221408 'Log.d(TAG, "foo");',
1409 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551410 MockAffectedFile('HasTooLongTagWithNoLogCallsInDiff.java', [
1411 'import org.chromium.base.Log;',
1412 'some random stuff',
1413 'private static final String TAG = "21_charachers_long___";',
1414 ]),
dgnaa68d5e2015-06-10 10:08:221415 ]
1416
1417 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1418 mock_input_api, mock_output_api)
1419
dgn38736db2015-09-18 19:20:511420 self.assertEqual(5, len(msgs),
1421 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221422
1423 # Declaration format
dgn38736db2015-09-18 19:20:511424 nb = len(msgs[0].items)
1425 self.assertEqual(2, nb,
1426 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221427 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1428 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221429
1430 # Tag length
dgn38736db2015-09-18 19:20:511431 nb = len(msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551432 self.assertEqual(2, nb,
1433 'Expected %d items, found %d: %s' % (2, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:221434 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551435 self.assertTrue('HasTooLongTagWithNoLogCallsInDiff.java' in msgs[1].items)
dgnaa68d5e2015-06-10 10:08:221436
1437 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511438 nb = len(msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551439 self.assertEqual(3, nb,
1440 'Expected %d items, found %d: %s' % (3, nb, msgs[2].items))
1441 self.assertTrue('HasBothLog.java:5' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221442 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551443 self.assertTrue('HasInlineTagWithSpace.java:4' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221444
dgn87d9fb62015-06-12 09:15:121445 # Util Log usage
dgn38736db2015-09-18 19:20:511446 nb = len(msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551447 self.assertEqual(3, nb,
1448 'Expected %d items, found %d: %s' % (3, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:121449 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551450 self.assertTrue('HasExplicitUtilLog.java:2' in msgs[3].items)
dgn87d9fb62015-06-12 09:15:121451 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:221452
dgn38736db2015-09-18 19:20:511453 # Tag must not contain
1454 nb = len(msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461455 self.assertEqual(3, nb,
dgn38736db2015-09-18 19:20:511456 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1457 self.assertTrue('HasDottedTag.java' in msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461458 self.assertTrue('HasDottedTagPublic.java' in msgs[4].items)
dgn38736db2015-09-18 19:20:511459 self.assertTrue('HasOldTag.java' in msgs[4].items)
1460
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391461
estadee17314a02017-01-12 16:22:161462class GoogleAnswerUrlFormatTest(unittest.TestCase):
1463
1464 def testCatchAnswerUrlId(self):
1465 input_api = MockInputApi()
1466 input_api.files = [
1467 MockFile('somewhere/file.cc',
1468 ['char* host = '
1469 ' "https://support.google.com/chrome/answer/123456";']),
1470 MockFile('somewhere_else/file.cc',
1471 ['char* host = '
1472 ' "https://support.google.com/chrome/a/answer/123456";']),
1473 ]
1474
Saagar Sanghavifceeaae2020-08-12 16:40:361475 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161476 input_api, MockOutputApi())
1477 self.assertEqual(1, len(warnings))
1478 self.assertEqual(2, len(warnings[0].items))
1479
1480 def testAllowAnswerUrlParam(self):
1481 input_api = MockInputApi()
1482 input_api.files = [
1483 MockFile('somewhere/file.cc',
1484 ['char* host = '
1485 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1486 ]
1487
Saagar Sanghavifceeaae2020-08-12 16:40:361488 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161489 input_api, MockOutputApi())
1490 self.assertEqual(0, len(warnings))
1491
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391492
reillyi38965732015-11-16 18:27:331493class HardcodedGoogleHostsTest(unittest.TestCase):
1494
1495 def testWarnOnAssignedLiterals(self):
1496 input_api = MockInputApi()
1497 input_api.files = [
1498 MockFile('content/file.cc',
1499 ['char* host = "https://www.google.com";']),
1500 MockFile('content/file.cc',
1501 ['char* host = "https://www.googleapis.com";']),
1502 MockFile('content/file.cc',
1503 ['char* host = "https://clients1.google.com";']),
1504 ]
1505
Saagar Sanghavifceeaae2020-08-12 16:40:361506 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331507 input_api, MockOutputApi())
1508 self.assertEqual(1, len(warnings))
1509 self.assertEqual(3, len(warnings[0].items))
1510
1511 def testAllowInComment(self):
1512 input_api = MockInputApi()
1513 input_api.files = [
1514 MockFile('content/file.cc',
1515 ['char* host = "https://www.aol.com"; // google.com'])
1516 ]
1517
Saagar Sanghavifceeaae2020-08-12 16:40:361518 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331519 input_api, MockOutputApi())
1520 self.assertEqual(0, len(warnings))
1521
dgn4401aa52015-04-29 16:26:171522
James Cook6b6597c2019-11-06 22:05:291523class ChromeOsSyncedPrefRegistrationTest(unittest.TestCase):
1524
1525 def testWarnsOnChromeOsDirectories(self):
1526 input_api = MockInputApi()
1527 input_api.files = [
1528 MockFile('ash/file.cc',
1529 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1530 MockFile('chrome/browser/chromeos/file.cc',
1531 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1532 MockFile('chromeos/file.cc',
1533 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1534 MockFile('components/arc/file.cc',
1535 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1536 MockFile('components/exo/file.cc',
1537 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1538 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361539 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291540 input_api, MockOutputApi())
1541 self.assertEqual(1, len(warnings))
1542
1543 def testDoesNotWarnOnSyncOsPref(self):
1544 input_api = MockInputApi()
1545 input_api.files = [
1546 MockFile('chromeos/file.cc',
1547 ['PrefRegistrySyncable::SYNCABLE_OS_PREF']),
1548 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361549 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291550 input_api, MockOutputApi())
1551 self.assertEqual(0, len(warnings))
1552
1553 def testDoesNotWarnOnCrossPlatformDirectories(self):
1554 input_api = MockInputApi()
1555 input_api.files = [
1556 MockFile('chrome/browser/ui/file.cc',
1557 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1558 MockFile('components/sync/file.cc',
1559 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1560 MockFile('content/browser/file.cc',
1561 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1562 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361563 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291564 input_api, MockOutputApi())
1565 self.assertEqual(0, len(warnings))
1566
1567 def testSeparateWarningForPriorityPrefs(self):
1568 input_api = MockInputApi()
1569 input_api.files = [
1570 MockFile('chromeos/file.cc',
1571 ['PrefRegistrySyncable::SYNCABLE_PREF',
1572 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']),
1573 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361574 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291575 input_api, MockOutputApi())
1576 self.assertEqual(2, len(warnings))
1577
1578
jbriance9e12f162016-11-25 07:57:501579class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311580 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501581 mock_input_api = MockInputApi()
1582 mock_input_api.files = [
1583 MockAffectedFile('somewhere/file.cc', [
1584 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311585 ]),
1586 MockAffectedFile('third_party/header.h', [
1587 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501588 ])
1589 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361590 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391591 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501592 self.assertEqual(0, len(warnings))
1593
1594 def testNoNestedDeclaration(self):
1595 mock_input_api = MockInputApi()
1596 mock_input_api.files = [
1597 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311598 'class SomeClass {',
1599 ' protected:',
1600 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501601 '};'
1602 ])
1603 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361604 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391605 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501606 self.assertEqual(0, len(warnings))
1607
1608 def testSubStrings(self):
1609 mock_input_api = MockInputApi()
1610 mock_input_api.files = [
1611 MockAffectedFile('somewhere/header.h', [
1612 'class NotUsefulClass;',
1613 'struct SomeStruct;',
1614 'UsefulClass *p1;',
1615 'SomeStructPtr *p2;'
1616 ])
1617 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361618 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391619 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501620 self.assertEqual(2, len(warnings))
1621
1622 def testUselessForwardDeclaration(self):
1623 mock_input_api = MockInputApi()
1624 mock_input_api.files = [
1625 MockAffectedFile('somewhere/header.h', [
1626 'class DummyClass;',
1627 'struct DummyStruct;',
1628 'class UsefulClass;',
1629 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311630 ])
jbriance9e12f162016-11-25 07:57:501631 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361632 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391633 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501634 self.assertEqual(2, len(warnings))
1635
jbriance2c51e821a2016-12-12 08:24:311636 def testBlinkHeaders(self):
1637 mock_input_api = MockInputApi()
1638 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491639 MockAffectedFile('third_party/blink/header.h', [
jbriance2c51e821a2016-12-12 08:24:311640 'class DummyClass;',
1641 'struct DummyStruct;',
1642 ]),
Kent Tamura32dbbcb2018-11-30 12:28:491643 MockAffectedFile('third_party\\blink\\header.h', [
jbriance2c51e821a2016-12-12 08:24:311644 'class DummyClass;',
1645 'struct DummyStruct;',
1646 ])
1647 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361648 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391649 MockOutputApi())
jbriance2c51e821a2016-12-12 08:24:311650 self.assertEqual(4, len(warnings))
1651
jbriance9e12f162016-11-25 07:57:501652
rlanday6802cf632017-05-30 17:48:361653class RelativeIncludesTest(unittest.TestCase):
1654 def testThirdPartyNotWebKitIgnored(self):
1655 mock_input_api = MockInputApi()
1656 mock_input_api.files = [
1657 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1658 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1659 ]
1660
1661 mock_output_api = MockOutputApi()
1662
Saagar Sanghavifceeaae2020-08-12 16:40:361663 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361664 mock_input_api, mock_output_api)
1665 self.assertEqual(0, len(errors))
1666
1667 def testNonCppFileIgnored(self):
1668 mock_input_api = MockInputApi()
1669 mock_input_api.files = [
1670 MockAffectedFile('test.py', '#include "../header.h"'),
1671 ]
1672
1673 mock_output_api = MockOutputApi()
1674
Saagar Sanghavifceeaae2020-08-12 16:40:361675 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361676 mock_input_api, mock_output_api)
1677 self.assertEqual(0, len(errors))
1678
1679 def testInnocuousChangesAllowed(self):
1680 mock_input_api = MockInputApi()
1681 mock_input_api.files = [
1682 MockAffectedFile('test.cpp', '#include "header.h"'),
1683 MockAffectedFile('test2.cpp', '../'),
1684 ]
1685
1686 mock_output_api = MockOutputApi()
1687
Saagar Sanghavifceeaae2020-08-12 16:40:361688 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361689 mock_input_api, mock_output_api)
1690 self.assertEqual(0, len(errors))
1691
1692 def testRelativeIncludeNonWebKitProducesError(self):
1693 mock_input_api = MockInputApi()
1694 mock_input_api.files = [
1695 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1696 ]
1697
1698 mock_output_api = MockOutputApi()
1699
Saagar Sanghavifceeaae2020-08-12 16:40:361700 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361701 mock_input_api, mock_output_api)
1702 self.assertEqual(1, len(errors))
1703
1704 def testRelativeIncludeWebKitProducesError(self):
1705 mock_input_api = MockInputApi()
1706 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491707 MockAffectedFile('third_party/blink/test.cpp',
rlanday6802cf632017-05-30 17:48:361708 ['#include "../header.h']),
1709 ]
1710
1711 mock_output_api = MockOutputApi()
1712
Saagar Sanghavifceeaae2020-08-12 16:40:361713 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361714 mock_input_api, mock_output_api)
1715 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241716
Daniel Cheng13ca61a882017-08-25 15:11:251717
Daniel Bratell65b033262019-04-23 08:17:061718class CCIncludeTest(unittest.TestCase):
1719 def testThirdPartyNotBlinkIgnored(self):
1720 mock_input_api = MockInputApi()
1721 mock_input_api.files = [
1722 MockAffectedFile('third_party/test.cpp', '#include "file.cc"'),
1723 ]
1724
1725 mock_output_api = MockOutputApi()
1726
Saagar Sanghavifceeaae2020-08-12 16:40:361727 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061728 mock_input_api, mock_output_api)
1729 self.assertEqual(0, len(errors))
1730
1731 def testPythonFileIgnored(self):
1732 mock_input_api = MockInputApi()
1733 mock_input_api.files = [
1734 MockAffectedFile('test.py', '#include "file.cc"'),
1735 ]
1736
1737 mock_output_api = MockOutputApi()
1738
Saagar Sanghavifceeaae2020-08-12 16:40:361739 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061740 mock_input_api, mock_output_api)
1741 self.assertEqual(0, len(errors))
1742
1743 def testIncFilesAccepted(self):
1744 mock_input_api = MockInputApi()
1745 mock_input_api.files = [
1746 MockAffectedFile('test.py', '#include "file.inc"'),
1747 ]
1748
1749 mock_output_api = MockOutputApi()
1750
Saagar Sanghavifceeaae2020-08-12 16:40:361751 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061752 mock_input_api, mock_output_api)
1753 self.assertEqual(0, len(errors))
1754
1755 def testInnocuousChangesAllowed(self):
1756 mock_input_api = MockInputApi()
1757 mock_input_api.files = [
1758 MockAffectedFile('test.cpp', '#include "header.h"'),
1759 MockAffectedFile('test2.cpp', 'Something "file.cc"'),
1760 ]
1761
1762 mock_output_api = MockOutputApi()
1763
Saagar Sanghavifceeaae2020-08-12 16:40:361764 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061765 mock_input_api, mock_output_api)
1766 self.assertEqual(0, len(errors))
1767
1768 def testCcIncludeNonBlinkProducesError(self):
1769 mock_input_api = MockInputApi()
1770 mock_input_api.files = [
1771 MockAffectedFile('test.cpp', ['#include "file.cc"']),
1772 ]
1773
1774 mock_output_api = MockOutputApi()
1775
Saagar Sanghavifceeaae2020-08-12 16:40:361776 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061777 mock_input_api, mock_output_api)
1778 self.assertEqual(1, len(errors))
1779
1780 def testCppIncludeBlinkProducesError(self):
1781 mock_input_api = MockInputApi()
1782 mock_input_api.files = [
1783 MockAffectedFile('third_party/blink/test.cpp',
1784 ['#include "foo/file.cpp"']),
1785 ]
1786
1787 mock_output_api = MockOutputApi()
1788
Saagar Sanghavifceeaae2020-08-12 16:40:361789 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061790 mock_input_api, mock_output_api)
1791 self.assertEqual(1, len(errors))
1792
1793
Andrew Grieve1b290e4a22020-11-24 20:07:011794class GnGlobForwardTest(unittest.TestCase):
1795 def testAddBareGlobs(self):
1796 mock_input_api = MockInputApi()
1797 mock_input_api.files = [
1798 MockAffectedFile('base/stuff.gni', [
1799 'forward_variables_from(invoker, "*")']),
1800 MockAffectedFile('base/BUILD.gn', [
1801 'forward_variables_from(invoker, "*")']),
1802 ]
1803 warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
1804 self.assertEqual(1, len(warnings))
1805 msg = '\n'.join(warnings[0].items)
1806 self.assertIn('base/stuff.gni', msg)
1807 # Should not check .gn files. Local templates don't need to care about
1808 # visibility / testonly.
1809 self.assertNotIn('base/BUILD.gn', msg)
1810
1811 def testValidUses(self):
1812 mock_input_api = MockInputApi()
1813 mock_input_api.files = [
1814 MockAffectedFile('base/stuff.gni', [
1815 'forward_variables_from(invoker, "*", [])']),
1816 MockAffectedFile('base/stuff2.gni', [
1817 'forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)']),
1818 MockAffectedFile('base/stuff3.gni', [
1819 'forward_variables_from(invoker, [ "testonly" ])']),
1820 ]
1821 warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
1822 self.assertEqual([], warnings)
1823
1824
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191825class NewHeaderWithoutGnChangeTest(unittest.TestCase):
1826 def testAddHeaderWithoutGn(self):
1827 mock_input_api = MockInputApi()
1828 mock_input_api.files = [
1829 MockAffectedFile('base/stuff.h', ''),
1830 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361831 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191832 mock_input_api, MockOutputApi())
1833 self.assertEqual(1, len(warnings))
1834 self.assertTrue('base/stuff.h' in warnings[0].items)
1835
1836 def testModifyHeader(self):
1837 mock_input_api = MockInputApi()
1838 mock_input_api.files = [
1839 MockAffectedFile('base/stuff.h', '', action='M'),
1840 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361841 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191842 mock_input_api, MockOutputApi())
1843 self.assertEqual(0, len(warnings))
1844
1845 def testDeleteHeader(self):
1846 mock_input_api = MockInputApi()
1847 mock_input_api.files = [
1848 MockAffectedFile('base/stuff.h', '', action='D'),
1849 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361850 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191851 mock_input_api, MockOutputApi())
1852 self.assertEqual(0, len(warnings))
1853
1854 def testAddHeaderWithGn(self):
1855 mock_input_api = MockInputApi()
1856 mock_input_api.files = [
1857 MockAffectedFile('base/stuff.h', ''),
1858 MockAffectedFile('base/BUILD.gn', 'stuff.h'),
1859 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361860 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191861 mock_input_api, MockOutputApi())
1862 self.assertEqual(0, len(warnings))
1863
1864 def testAddHeaderWithGni(self):
1865 mock_input_api = MockInputApi()
1866 mock_input_api.files = [
1867 MockAffectedFile('base/stuff.h', ''),
1868 MockAffectedFile('base/files.gni', 'stuff.h'),
1869 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361870 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191871 mock_input_api, MockOutputApi())
1872 self.assertEqual(0, len(warnings))
1873
1874 def testAddHeaderWithOther(self):
1875 mock_input_api = MockInputApi()
1876 mock_input_api.files = [
1877 MockAffectedFile('base/stuff.h', ''),
1878 MockAffectedFile('base/stuff.cc', 'stuff.h'),
1879 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361880 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191881 mock_input_api, MockOutputApi())
1882 self.assertEqual(1, len(warnings))
1883
1884 def testAddHeaderWithWrongGn(self):
1885 mock_input_api = MockInputApi()
1886 mock_input_api.files = [
1887 MockAffectedFile('base/stuff.h', ''),
1888 MockAffectedFile('base/BUILD.gn', 'stuff_h'),
1889 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361890 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191891 mock_input_api, MockOutputApi())
1892 self.assertEqual(1, len(warnings))
1893
1894 def testAddHeadersWithGn(self):
1895 mock_input_api = MockInputApi()
1896 mock_input_api.files = [
1897 MockAffectedFile('base/stuff.h', ''),
1898 MockAffectedFile('base/another.h', ''),
1899 MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'),
1900 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361901 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191902 mock_input_api, MockOutputApi())
1903 self.assertEqual(0, len(warnings))
1904
1905 def testAddHeadersWithWrongGn(self):
1906 mock_input_api = MockInputApi()
1907 mock_input_api.files = [
1908 MockAffectedFile('base/stuff.h', ''),
1909 MockAffectedFile('base/another.h', ''),
1910 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'),
1911 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361912 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191913 mock_input_api, MockOutputApi())
1914 self.assertEqual(1, len(warnings))
1915 self.assertFalse('base/stuff.h' in warnings[0].items)
1916 self.assertTrue('base/another.h' in warnings[0].items)
1917
1918 def testAddHeadersWithWrongGn2(self):
1919 mock_input_api = MockInputApi()
1920 mock_input_api.files = [
1921 MockAffectedFile('base/stuff.h', ''),
1922 MockAffectedFile('base/another.h', ''),
1923 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'),
1924 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361925 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191926 mock_input_api, MockOutputApi())
1927 self.assertEqual(1, len(warnings))
1928 self.assertTrue('base/stuff.h' in warnings[0].items)
1929 self.assertTrue('base/another.h' in warnings[0].items)
1930
1931
Michael Giuffridad3bc8672018-10-25 22:48:021932class CorrectProductNameInMessagesTest(unittest.TestCase):
1933 def testProductNameInDesc(self):
1934 mock_input_api = MockInputApi()
1935 mock_input_api.files = [
1936 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1937 '<message name="Foo" desc="Welcome to Chrome">',
1938 ' Welcome to Chrome!',
1939 '</message>',
1940 ]),
1941 MockAffectedFile('chrome/app/chromium_strings.grd', [
1942 '<message name="Bar" desc="Welcome to Chrome">',
1943 ' Welcome to Chromium!',
1944 '</message>',
1945 ]),
1946 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361947 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021948 mock_input_api, MockOutputApi())
1949 self.assertEqual(0, len(warnings))
1950
1951 def testChromeInChromium(self):
1952 mock_input_api = MockInputApi()
1953 mock_input_api.files = [
1954 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1955 '<message name="Foo" desc="Welcome to Chrome">',
1956 ' Welcome to Chrome!',
1957 '</message>',
1958 ]),
1959 MockAffectedFile('chrome/app/chromium_strings.grd', [
1960 '<message name="Bar" desc="Welcome to Chrome">',
1961 ' Welcome to Chrome!',
1962 '</message>',
1963 ]),
1964 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361965 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021966 mock_input_api, MockOutputApi())
1967 self.assertEqual(1, len(warnings))
1968 self.assertTrue('chrome/app/chromium_strings.grd' in warnings[0].items[0])
1969
1970 def testChromiumInChrome(self):
1971 mock_input_api = MockInputApi()
1972 mock_input_api.files = [
1973 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1974 '<message name="Foo" desc="Welcome to Chrome">',
1975 ' Welcome to Chromium!',
1976 '</message>',
1977 ]),
1978 MockAffectedFile('chrome/app/chromium_strings.grd', [
1979 '<message name="Bar" desc="Welcome to Chrome">',
1980 ' Welcome to Chromium!',
1981 '</message>',
1982 ]),
1983 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361984 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021985 mock_input_api, MockOutputApi())
1986 self.assertEqual(1, len(warnings))
1987 self.assertTrue(
1988 'chrome/app/google_chrome_strings.grd:2' in warnings[0].items[0])
1989
1990 def testMultipleInstances(self):
1991 mock_input_api = MockInputApi()
1992 mock_input_api.files = [
1993 MockAffectedFile('chrome/app/chromium_strings.grd', [
1994 '<message name="Bar" desc="Welcome to Chrome">',
1995 ' Welcome to Chrome!',
1996 '</message>',
1997 '<message name="Baz" desc="A correct message">',
1998 ' Chromium is the software you are using.',
1999 '</message>',
2000 '<message name="Bat" desc="An incorrect message">',
2001 ' Google Chrome is the software you are using.',
2002 '</message>',
2003 ]),
2004 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362005 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022006 mock_input_api, MockOutputApi())
2007 self.assertEqual(1, len(warnings))
2008 self.assertTrue(
2009 'chrome/app/chromium_strings.grd:2' in warnings[0].items[0])
2010 self.assertTrue(
2011 'chrome/app/chromium_strings.grd:8' in warnings[0].items[1])
2012
2013 def testMultipleWarnings(self):
2014 mock_input_api = MockInputApi()
2015 mock_input_api.files = [
2016 MockAffectedFile('chrome/app/chromium_strings.grd', [
2017 '<message name="Bar" desc="Welcome to Chrome">',
2018 ' Welcome to Chrome!',
2019 '</message>',
2020 '<message name="Baz" desc="A correct message">',
2021 ' Chromium is the software you are using.',
2022 '</message>',
2023 '<message name="Bat" desc="An incorrect message">',
2024 ' Google Chrome is the software you are using.',
2025 '</message>',
2026 ]),
2027 MockAffectedFile('components/components_google_chrome_strings.grd', [
2028 '<message name="Bar" desc="Welcome to Chrome">',
2029 ' Welcome to Chrome!',
2030 '</message>',
2031 '<message name="Baz" desc="A correct message">',
2032 ' Chromium is the software you are using.',
2033 '</message>',
2034 '<message name="Bat" desc="An incorrect message">',
2035 ' Google Chrome is the software you are using.',
2036 '</message>',
2037 ]),
2038 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362039 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022040 mock_input_api, MockOutputApi())
2041 self.assertEqual(2, len(warnings))
2042 self.assertTrue(
2043 'components/components_google_chrome_strings.grd:5'
2044 in warnings[0].items[0])
2045 self.assertTrue(
2046 'chrome/app/chromium_strings.grd:2' in warnings[1].items[0])
2047 self.assertTrue(
2048 'chrome/app/chromium_strings.grd:8' in warnings[1].items[1])
2049
2050
Ken Rockot9f668262018-12-21 18:56:362051class ServiceManifestOwnerTest(unittest.TestCase):
Ken Rockot9f668262018-12-21 18:56:362052 def testServiceManifestChangeNeedsSecurityOwner(self):
2053 mock_input_api = MockInputApi()
2054 mock_input_api.files = [
2055 MockAffectedFile('services/goat/public/cpp/manifest.cc',
2056 [
2057 '#include "services/goat/public/cpp/manifest.h"',
2058 'const service_manager::Manifest& GetManifest() {}',
2059 ])]
2060 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362061 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362062 mock_input_api, mock_output_api)
2063 self.assertEqual(1, len(errors))
2064 self.assertEqual(
2065 'Found OWNERS files that need to be updated for IPC security review ' +
2066 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2067
2068 def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
2069 mock_input_api = MockInputApi()
2070 mock_input_api.files = [
2071 MockAffectedFile('some/non/service/thing/foo_manifest.cc',
2072 [
2073 'const char kNoEnforcement[] = "not a manifest!";',
2074 ])]
2075 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362076 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032077 mock_input_api, mock_output_api)
2078 self.assertEqual([], errors)
2079
2080
2081class FuchsiaSecurityOwnerTest(unittest.TestCase):
2082 def testFidlChangeNeedsSecurityOwner(self):
2083 mock_input_api = MockInputApi()
2084 mock_input_api.files = [
2085 MockAffectedFile('potentially/scary/ipc.fidl',
2086 [
2087 'library test.fidl'
2088 ])]
2089 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362090 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032091 mock_input_api, mock_output_api)
2092 self.assertEqual(1, len(errors))
2093 self.assertEqual(
2094 'Found OWNERS files that need to be updated for IPC security review ' +
2095 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2096
2097 def testComponentManifestV1ChangeNeedsSecurityOwner(self):
2098 mock_input_api = MockInputApi()
2099 mock_input_api.files = [
2100 MockAffectedFile('potentially/scary/v2_manifest.cmx',
2101 [
2102 '{ "that is no": "manifest!" }'
2103 ])]
2104 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362105 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032106 mock_input_api, mock_output_api)
2107 self.assertEqual(1, len(errors))
2108 self.assertEqual(
2109 'Found OWNERS files that need to be updated for IPC security review ' +
2110 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2111
2112 def testComponentManifestV2NeedsSecurityOwner(self):
2113 mock_input_api = MockInputApi()
2114 mock_input_api.files = [
2115 MockAffectedFile('potentially/scary/v2_manifest.cml',
2116 [
2117 '{ "that is no": "manifest!" }'
2118 ])]
2119 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362120 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032121 mock_input_api, mock_output_api)
2122 self.assertEqual(1, len(errors))
2123 self.assertEqual(
2124 'Found OWNERS files that need to be updated for IPC security review ' +
2125 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2126
Joshua Peraza1ca6d392020-12-08 00:14:092127 def testThirdPartyTestsDoNotRequireSecurityOwner(self):
2128 mock_input_api = MockInputApi()
2129 mock_input_api.files = [
2130 MockAffectedFile('third_party/crashpad/test/tests.cmx',
2131 [
2132 'const char kNoEnforcement[] = "Security?!? Pah!";',
2133 ])]
2134 mock_output_api = MockOutputApi()
2135 errors = PRESUBMIT.CheckSecurityOwners(
2136 mock_input_api, mock_output_api)
2137 self.assertEqual([], errors)
2138
Wez17c66962020-04-29 15:26:032139 def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2140 mock_input_api = MockInputApi()
2141 mock_input_api.files = [
2142 MockAffectedFile('some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',
2143 [
2144 'const char kNoEnforcement[] = "Security?!? Pah!";',
2145 ])]
2146 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362147 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362148 mock_input_api, mock_output_api)
2149 self.assertEqual([], errors)
2150
Daniel Cheng13ca61a882017-08-25 15:11:252151
Robert Sesek2c905332020-05-06 23:17:132152class SecurityChangeTest(unittest.TestCase):
Edward Lesmes1e9fade2021-02-08 20:31:122153 class _MockOwnersClient(object):
2154 def ListOwners(self, f):
Robert Sesek2c905332020-05-06 23:17:132155 return ['[email protected]', '[email protected]']
2156
2157 def _mockChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2158 def __MockOwnerAndReviewers(input_api, email_regexp, approval_needed=False):
2159 return [owner, reviewers]
2160 input_api.canned_checks.GetCodereviewOwnerAndReviewers = \
2161 __MockOwnerAndReviewers
2162
Alex Goughbc964dd2020-06-15 17:52:372163 def testDiffGetServiceSandboxType(self):
Robert Sesek2c905332020-05-06 23:17:132164 mock_input_api = MockInputApi()
2165 mock_input_api.files = [
2166 MockAffectedFile(
2167 'services/goat/teleporter_host.cc',
2168 [
Alex Goughbc964dd2020-06-15 17:52:372169 'template <>',
2170 'inline content::SandboxType',
2171 'content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {',
2172 '#if defined(OS_WIN)',
2173 ' return SandboxType::kGoaty;',
2174 '#else',
2175 ' return SandboxType::kNoSandbox;',
2176 '#endif // !defined(OS_WIN)',
2177 '}'
Robert Sesek2c905332020-05-06 23:17:132178 ]
2179 ),
2180 ]
2181 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2182 mock_input_api)
2183 self.assertEqual({
2184 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372185 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132186 ])},
2187 files_to_functions)
2188
2189 def testDiffRemovingLine(self):
2190 mock_input_api = MockInputApi()
2191 mock_file = MockAffectedFile('services/goat/teleporter_host.cc', '')
2192 mock_file._scm_diff = """--- old 2020-05-04 14:08:25.000000000 -0400
2193+++ new 2020-05-04 14:08:32.000000000 -0400
2194@@ -1,5 +1,4 @@
Alex Goughbc964dd2020-06-15 17:52:372195 template <>
2196 inline content::SandboxType
2197-content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {
2198 #if defined(OS_WIN)
2199 return SandboxType::kGoaty;
Robert Sesek2c905332020-05-06 23:17:132200"""
2201 mock_input_api.files = [mock_file]
2202 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2203 mock_input_api)
2204 self.assertEqual({
2205 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372206 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132207 ])},
2208 files_to_functions)
2209
2210 def testChangeOwnersMissing(self):
2211 mock_input_api = MockInputApi()
Edward Lesmes1e9fade2021-02-08 20:31:122212 mock_input_api.owners_client = self._MockOwnersClient()
Robert Sesek2c905332020-05-06 23:17:132213 mock_input_api.is_committing = False
2214 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372215 MockAffectedFile('file.cc', ['GetServiceSandboxType<Goat>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132216 ]
2217 mock_output_api = MockOutputApi()
2218 self._mockChangeOwnerAndReviewers(
2219 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362220 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592221 self.assertEqual(1, len(result))
2222 self.assertEqual(result[0].type, 'notify')
2223 self.assertEqual(result[0].message,
Robert Sesek2c905332020-05-06 23:17:132224 'The following files change calls to security-sensive functions\n' \
2225 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2226 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372227 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132228
2229 def testChangeOwnersMissingAtCommit(self):
2230 mock_input_api = MockInputApi()
Edward Lesmes1e9fade2021-02-08 20:31:122231 mock_input_api.owners_client = self._MockOwnersClient()
Robert Sesek2c905332020-05-06 23:17:132232 mock_input_api.is_committing = True
2233 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372234 MockAffectedFile('file.cc', ['GetServiceSandboxType<mojom::Goat>()'])
Robert Sesek2c905332020-05-06 23:17:132235 ]
2236 mock_output_api = MockOutputApi()
2237 self._mockChangeOwnerAndReviewers(
2238 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362239 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592240 self.assertEqual(1, len(result))
2241 self.assertEqual(result[0].type, 'error')
2242 self.assertEqual(result[0].message,
Robert Sesek2c905332020-05-06 23:17:132243 'The following files change calls to security-sensive functions\n' \
2244 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2245 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372246 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132247
2248 def testChangeOwnersPresent(self):
2249 mock_input_api = MockInputApi()
Edward Lesmes1e9fade2021-02-08 20:31:122250 mock_input_api.owners_client = self._MockOwnersClient()
Robert Sesek2c905332020-05-06 23:17:132251 mock_input_api.files = [
2252 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2253 ]
2254 mock_output_api = MockOutputApi()
2255 self._mockChangeOwnerAndReviewers(
2256 mock_input_api, '[email protected]',
2257 ['[email protected]', '[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362258 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592259 self.assertEqual(0, len(result))
Robert Sesek2c905332020-05-06 23:17:132260
2261 def testChangeOwnerIsSecurityOwner(self):
2262 mock_input_api = MockInputApi()
Edward Lesmes1e9fade2021-02-08 20:31:122263 mock_input_api.owners_client = self._MockOwnersClient()
Robert Sesek2c905332020-05-06 23:17:132264 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372265 MockAffectedFile('file.cc', ['GetServiceSandboxType<T>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132266 ]
2267 mock_output_api = MockOutputApi()
2268 self._mockChangeOwnerAndReviewers(
2269 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362270 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592271 self.assertEqual(1, len(result))
Robert Sesek2c905332020-05-06 23:17:132272
2273
Mario Sanchez Prada2472cab2019-09-18 10:58:312274class BannedTypeCheckTest(unittest.TestCase):
Sylvain Defresnea8b73d252018-02-28 15:45:542275
Peter Kasting94a56c42019-10-25 21:54:042276 def testBannedCppFunctions(self):
2277 input_api = MockInputApi()
2278 input_api.files = [
2279 MockFile('some/cpp/problematic/file.cc',
2280 ['using namespace std;']),
Oksana Zhuravlovac8222d22019-12-19 19:21:162281 MockFile('third_party/blink/problematic/file.cc',
2282 ['GetInterfaceProvider()']),
Peter Kasting94a56c42019-10-25 21:54:042283 MockFile('some/cpp/ok/file.cc',
2284 ['using std::string;']),
Allen Bauer53b43fb12020-03-12 17:21:472285 MockFile('some/cpp/problematic/file2.cc',
2286 ['set_owned_by_client()']),
danakjd18e8892020-12-17 17:42:012287 MockFile('some/cpp/nocheck/file.cc',
2288 ['using namespace std; // nocheck']),
2289 MockFile('some/cpp/comment/file.cc',
2290 [' // A comment about `using namespace std;`']),
Peter Kasting94a56c42019-10-25 21:54:042291 ]
2292
Saagar Sanghavifceeaae2020-08-12 16:40:362293 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlovac8222d22019-12-19 19:21:162294
2295 # warnings are results[0], errors are results[1]
2296 self.assertEqual(2, len(results))
2297 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2298 self.assertTrue(
2299 'third_party/blink/problematic/file.cc' in results[0].message)
2300 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
Allen Bauer53b43fb12020-03-12 17:21:472301 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
danakjd18e8892020-12-17 17:42:012302 self.assertFalse('some/cpp/nocheck/file.cc' in results[0].message)
2303 self.assertFalse('some/cpp/nocheck/file.cc' in results[1].message)
2304 self.assertFalse('some/cpp/comment/file.cc' in results[0].message)
2305 self.assertFalse('some/cpp/comment/file.cc' in results[1].message)
Peter Kasting94a56c42019-10-25 21:54:042306
Peter K. Lee6c03ccff2019-07-15 14:40:052307 def testBannedIosObjcFunctions(self):
Sylvain Defresnea8b73d252018-02-28 15:45:542308 input_api = MockInputApi()
2309 input_api.files = [
2310 MockFile('some/ios/file.mm',
2311 ['TEST(SomeClassTest, SomeInteraction) {',
2312 '}']),
2313 MockFile('some/mac/file.mm',
2314 ['TEST(SomeClassTest, SomeInteraction) {',
2315 '}']),
2316 MockFile('another/ios_file.mm',
2317 ['class SomeTest : public testing::Test {};']),
Peter K. Lee6c03ccff2019-07-15 14:40:052318 MockFile('some/ios/file_egtest.mm',
2319 ['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
2320 MockFile('some/ios/file_unittest.mm',
2321 ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']),
Sylvain Defresnea8b73d252018-02-28 15:45:542322 ]
2323
Saagar Sanghavifceeaae2020-08-12 16:40:362324 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Sylvain Defresnea8b73d252018-02-28 15:45:542325 self.assertEqual(1, len(errors))
2326 self.assertTrue('some/ios/file.mm' in errors[0].message)
2327 self.assertTrue('another/ios_file.mm' in errors[0].message)
2328 self.assertTrue('some/mac/file.mm' not in errors[0].message)
Peter K. Lee6c03ccff2019-07-15 14:40:052329 self.assertTrue('some/ios/file_egtest.mm' in errors[0].message)
2330 self.assertTrue('some/ios/file_unittest.mm' not in errors[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542331
Carlos Knippschildab192b8c2019-04-08 20:02:382332 def testBannedMojoFunctions(self):
2333 input_api = MockInputApi()
2334 input_api.files = [
Oksana Zhuravlovafd247772019-05-16 16:57:292335 MockFile('some/cpp/problematic/file2.cc',
2336 ['mojo::ConvertTo<>']),
Oksana Zhuravlovafd247772019-05-16 16:57:292337 MockFile('third_party/blink/ok/file3.cc',
2338 ['mojo::ConvertTo<>']),
2339 MockFile('content/renderer/ok/file3.cc',
2340 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382341 ]
2342
Saagar Sanghavifceeaae2020-08-12 16:40:362343 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222344
2345 # warnings are results[0], errors are results[1]
Robert Sesek351d2d52021-02-02 01:47:072346 self.assertEqual(1, len(results))
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222347 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222348 self.assertTrue('third_party/blink/ok/file3.cc' not in results[0].message)
2349 self.assertTrue('content/renderer/ok/file3.cc' not in results[0].message)
Carlos Knippschildab192b8c2019-04-08 20:02:382350
Mario Sanchez Prada2472cab2019-09-18 10:58:312351 def testDeprecatedMojoTypes(self):
Mario Sanchez Pradacec9cef2019-12-15 11:54:572352 ok_paths = ['components/arc']
2353 warning_paths = ['some/cpp']
Mario Sanchez Pradaaab91382019-12-19 08:57:092354 error_paths = ['third_party/blink', 'content']
Mario Sanchez Prada2472cab2019-09-18 10:58:312355 test_cases = [
2356 {
Mario Sanchez Prada2472cab2019-09-18 10:58:312357 'type': 'mojo::AssociatedInterfacePtrInfo<>',
2358 'file': 'file4.cc'
2359 },
2360 {
2361 'type': 'mojo::AssociatedInterfaceRequest<>',
2362 'file': 'file5.cc'
2363 },
2364 {
Mario Sanchez Prada2472cab2019-09-18 10:58:312365 'type': 'mojo::InterfacePtr<>',
2366 'file': 'file8.cc'
2367 },
2368 {
2369 'type': 'mojo::InterfacePtrInfo<>',
2370 'file': 'file9.cc'
2371 },
2372 {
2373 'type': 'mojo::InterfaceRequest<>',
2374 'file': 'file10.cc'
2375 },
2376 {
2377 'type': 'mojo::MakeRequest()',
2378 'file': 'file11.cc'
2379 },
Mario Sanchez Prada2472cab2019-09-18 10:58:312380 ]
2381
2382 # Build the list of MockFiles considering paths that should trigger warnings
Mario Sanchez Pradacec9cef2019-12-15 11:54:572383 # as well as paths that should trigger errors.
Mario Sanchez Prada2472cab2019-09-18 10:58:312384 input_api = MockInputApi()
2385 input_api.files = []
2386 for test_case in test_cases:
2387 for path in ok_paths:
2388 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2389 [test_case['type']]))
2390 for path in warning_paths:
2391 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2392 [test_case['type']]))
Mario Sanchez Pradacec9cef2019-12-15 11:54:572393 for path in error_paths:
2394 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2395 [test_case['type']]))
Mario Sanchez Prada2472cab2019-09-18 10:58:312396
Saagar Sanghavifceeaae2020-08-12 16:40:362397 results = PRESUBMIT.CheckNoDeprecatedMojoTypes(input_api, MockOutputApi())
Mario Sanchez Prada2472cab2019-09-18 10:58:312398
Mario Sanchez Pradacec9cef2019-12-15 11:54:572399 # warnings are results[0], errors are results[1]
2400 self.assertEqual(2, len(results))
Mario Sanchez Prada2472cab2019-09-18 10:58:312401
2402 for test_case in test_cases:
Mario Sanchez Pradacec9cef2019-12-15 11:54:572403 # Check that no warnings nor errors have been triggered for these paths.
Mario Sanchez Prada2472cab2019-09-18 10:58:312404 for path in ok_paths:
2405 self.assertFalse(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572406 self.assertFalse(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312407
2408 # Check warnings have been triggered for these paths.
2409 for path in warning_paths:
2410 self.assertTrue(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572411 self.assertFalse(path in results[1].message)
2412
2413 # Check errors have been triggered for these paths.
2414 for path in error_paths:
2415 self.assertFalse(path in results[0].message)
2416 self.assertTrue(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312417
Sylvain Defresnea8b73d252018-02-28 15:45:542418
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272419class NoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:242420 def testTruePositives(self):
2421 mock_input_api = MockInputApi()
2422 mock_input_api.files = [
2423 MockFile('some/path/foo.cc', ['foo_for_testing();']),
2424 MockFile('some/path/foo.mm', ['FooForTesting();']),
2425 MockFile('some/path/foo.cxx', ['FooForTests();']),
2426 MockFile('some/path/foo.cpp', ['foo_for_test();']),
2427 ]
2428
Saagar Sanghavifceeaae2020-08-12 16:40:362429 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242430 mock_input_api, MockOutputApi())
2431 self.assertEqual(1, len(results))
2432 self.assertEqual(4, len(results[0].items))
2433 self.assertTrue('foo.cc' in results[0].items[0])
2434 self.assertTrue('foo.mm' in results[0].items[1])
2435 self.assertTrue('foo.cxx' in results[0].items[2])
2436 self.assertTrue('foo.cpp' in results[0].items[3])
2437
2438 def testFalsePositives(self):
2439 mock_input_api = MockInputApi()
2440 mock_input_api.files = [
2441 MockFile('some/path/foo.h', ['foo_for_testing();']),
2442 MockFile('some/path/foo.mm', ['FooForTesting() {']),
2443 MockFile('some/path/foo.cc', ['::FooForTests();']),
2444 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
2445 ]
2446
Saagar Sanghavifceeaae2020-08-12 16:40:362447 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242448 mock_input_api, MockOutputApi())
2449 self.assertEqual(0, len(results))
2450
James Cook1b4dc132021-03-09 22:45:132451 def testAllowedFiles(self):
2452 mock_input_api = MockInputApi()
2453 mock_input_api.files = [
2454 MockFile('path/foo_unittest.cc', ['foo_for_testing();']),
2455 MockFile('path/bar_unittest_mac.cc', ['foo_for_testing();']),
2456 MockFile('path/baz_unittests.cc', ['foo_for_testing();']),
2457 ]
2458
2459 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
2460 mock_input_api, MockOutputApi())
2461 self.assertEqual(0, len(results))
2462
Vaclav Brozekf01ed502018-03-16 19:38:242463
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272464class NoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:232465 def testTruePositives(self):
2466 mock_input_api = MockInputApi()
2467 mock_input_api.files = [
2468 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
2469 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392470 MockFile('dir/java/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232471 MockFile('dir/java/src/mult.java', [
2472 'int x = SomethingLongHere()',
2473 ' * SomethingLongHereForTesting();'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392474 ])
Vaclav Brozek7dbc28c2018-03-27 08:35:232475 ]
2476
Saagar Sanghavifceeaae2020-08-12 16:40:362477 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232478 mock_input_api, MockOutputApi())
2479 self.assertEqual(1, len(results))
2480 self.assertEqual(4, len(results[0].items))
2481 self.assertTrue('foo.java' in results[0].items[0])
2482 self.assertTrue('bar.java' in results[0].items[1])
2483 self.assertTrue('baz.java' in results[0].items[2])
2484 self.assertTrue('mult.java' in results[0].items[3])
2485
2486 def testFalsePositives(self):
2487 mock_input_api = MockInputApi()
2488 mock_input_api.files = [
2489 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
2490 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
2491 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
2492 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
Sky Malice9e6d6032020-10-15 22:49:552493 MockFile('dir/java/src/bar3.java', ['@VisibleForTesting']),
2494 MockFile('dir/java/src/bar4.java', ['@VisibleForTesting()']),
2495 MockFile('dir/java/src/bar5.java', [
2496 '@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)'
2497 ]),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392498 MockFile('dir/javatests/src/baz.java', ['FooForTest(', 'y', ');']),
2499 MockFile('dir/junit/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232500 MockFile('dir/junit/src/javadoc.java', [
2501 '/** Use FooForTest(); to obtain foo in tests.'
2502 ' */'
2503 ]),
2504 MockFile('dir/junit/src/javadoc2.java', [
2505 '/** ',
2506 ' * Use FooForTest(); to obtain foo in tests.'
2507 ' */'
2508 ]),
2509 ]
2510
Saagar Sanghavifceeaae2020-08-12 16:40:362511 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232512 mock_input_api, MockOutputApi())
2513 self.assertEqual(0, len(results))
2514
2515
Mohamed Heikald048240a2019-11-12 16:57:372516class NewImagesWarningTest(unittest.TestCase):
2517 def testTruePositives(self):
2518 mock_input_api = MockInputApi()
2519 mock_input_api.files = [
2520 MockFile('dir/android/res/drawable/foo.png', []),
2521 MockFile('dir/android/res/drawable-v21/bar.svg', []),
2522 MockFile('dir/android/res/mipmap-v21-en/baz.webp', []),
2523 MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png', []),
2524 ]
2525
2526 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2527 self.assertEqual(1, len(results))
2528 self.assertEqual(4, len(results[0].items))
2529 self.assertTrue('foo.png' in results[0].items[0].LocalPath())
2530 self.assertTrue('bar.svg' in results[0].items[1].LocalPath())
2531 self.assertTrue('baz.webp' in results[0].items[2].LocalPath())
2532 self.assertTrue('foobar.png' in results[0].items[3].LocalPath())
2533
2534 def testFalsePositives(self):
2535 mock_input_api = MockInputApi()
2536 mock_input_api.files = [
2537 MockFile('dir/pngs/README.md', []),
2538 MockFile('java/test/res/drawable/foo.png', []),
2539 MockFile('third_party/blink/foo.png', []),
2540 MockFile('dir/third_party/libpng/src/foo.cc', ['foobar']),
2541 MockFile('dir/resources.webp/.gitignore', ['foo.png']),
2542 ]
2543
2544 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2545 self.assertEqual(0, len(results))
2546
2547
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272548class CheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:052549 def testTruePositivesNullptr(self):
2550 mock_input_api = MockInputApi()
2551 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162552 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
2553 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
Vaclav Brozek851d9602018-04-04 16:13:052554 ]
2555
Saagar Sanghavifceeaae2020-08-12 16:40:362556 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052557 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162558 self.assertTrue('nullptr' in results[0].message)
Vaclav Brozek851d9602018-04-04 16:13:052559 self.assertEqual(2, len(results[0].items))
2560 self.assertTrue('baz.cc' in results[0].items[0])
2561 self.assertTrue('baz-p.cc' in results[0].items[1])
2562
2563 def testTruePositivesConstructor(self):
Vaclav Brozek52e18bf2018-04-03 07:05:242564 mock_input_api = MockInputApi()
2565 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162566 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
2567 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
2568 MockFile('dir/mult.cc', [
Vaclav Brozek95face62018-04-04 14:15:112569 'return',
2570 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
2571 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162572 MockFile('dir/mult2.cc', [
Vaclav Brozek95face62018-04-04 14:15:112573 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
2574 ' std::unique_ptr<T>(foo);'
2575 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162576 MockFile('dir/mult3.cc', [
Vaclav Brozek95face62018-04-04 14:15:112577 'bar = std::unique_ptr<T>(',
2578 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
2579 ]),
Vaclav Brozekb7fadb692018-08-30 06:39:532580 MockFile('dir/multi_arg.cc', [
2581 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']),
Vaclav Brozek52e18bf2018-04-03 07:05:242582 ]
2583
Saagar Sanghavifceeaae2020-08-12 16:40:362584 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052585 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162586 self.assertTrue('std::make_unique' in results[0].message)
Vaclav Brozekb7fadb692018-08-30 06:39:532587 self.assertEqual(6, len(results[0].items))
Vaclav Brozek851d9602018-04-04 16:13:052588 self.assertTrue('foo.cc' in results[0].items[0])
2589 self.assertTrue('bar.mm' in results[0].items[1])
2590 self.assertTrue('mult.cc' in results[0].items[2])
2591 self.assertTrue('mult2.cc' in results[0].items[3])
2592 self.assertTrue('mult3.cc' in results[0].items[4])
Vaclav Brozekb7fadb692018-08-30 06:39:532593 self.assertTrue('multi_arg.cc' in results[0].items[5])
Vaclav Brozek52e18bf2018-04-03 07:05:242594
2595 def testFalsePositives(self):
2596 mock_input_api = MockInputApi()
2597 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162598 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
2599 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
2600 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
2601 MockFile('dir/baz.cc', [
Vaclav Brozek52e18bf2018-04-03 07:05:242602 'std::unique_ptr<T> result = std::make_unique<T>();'
2603 ]),
Vaclav Brozeka54c528b2018-04-06 19:23:552604 MockFile('dir/baz2.cc', [
2605 'std::unique_ptr<T> result = std::make_unique<T>('
2606 ]),
2607 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
2608 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
Vaclav Brozekb7fadb692018-08-30 06:39:532609
2610 # Two-argument invocation of std::unique_ptr is exempt because there is
2611 # no equivalent using std::make_unique.
2612 MockFile('dir/multi_arg.cc', [
2613 'auto p = std::unique_ptr<T, D>(new T(), D());']),
Vaclav Brozek52e18bf2018-04-03 07:05:242614 ]
2615
Saagar Sanghavifceeaae2020-08-12 16:40:362616 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek52e18bf2018-04-03 07:05:242617 self.assertEqual(0, len(results))
2618
Danil Chapovalov3518f362018-08-11 16:13:432619class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
2620 def testBlocksDirectIncludes(self):
2621 mock_input_api = MockInputApi()
2622 mock_input_api.files = [
2623 MockFile('dir/foo_win.cc', ['#include "shlwapi.h"']),
2624 MockFile('dir/bar.h', ['#include <propvarutil.h>']),
2625 MockFile('dir/baz.h', ['#include <atlbase.h>']),
2626 MockFile('dir/jumbo.h', ['#include "sphelper.h"']),
2627 ]
2628 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:592629 self.assertEqual(1, len(results))
2630 self.assertEqual(4, len(results[0].items))
Danil Chapovalov3518f362018-08-11 16:13:432631 self.assertTrue('StrCat' in results[0].message)
2632 self.assertTrue('foo_win.cc' in results[0].items[0])
2633 self.assertTrue('bar.h' in results[0].items[1])
2634 self.assertTrue('baz.h' in results[0].items[2])
2635 self.assertTrue('jumbo.h' in results[0].items[3])
2636
2637 def testAllowsToIncludeWrapper(self):
2638 mock_input_api = MockInputApi()
2639 mock_input_api.files = [
2640 MockFile('dir/baz_win.cc', ['#include "base/win/shlwapi.h"']),
2641 MockFile('dir/baz-win.h', ['#include "base/win/atl.h"']),
2642 ]
2643 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:592644 self.assertEqual(0, len(results))
Danil Chapovalov3518f362018-08-11 16:13:432645
2646 def testAllowsToCreateWrapper(self):
2647 mock_input_api = MockInputApi()
2648 mock_input_api.files = [
2649 MockFile('base/win/shlwapi.h', [
2650 '#include <shlwapi.h>',
2651 '#include "base/win/windows_defines.inc"']),
2652 ]
2653 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:592654 self.assertEqual(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:242655
Mustafa Emre Acer51f2f742020-03-09 19:41:122656
Rainhard Findlingfc31844c52020-05-15 09:58:262657class StringTest(unittest.TestCase):
2658 """Tests ICU syntax check and translation screenshots check."""
2659
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142660 # An empty grd file.
2661 OLD_GRD_CONTENTS = """<?xml version="1.0" encoding="UTF-8"?>
2662 <grit latest_public_release="1" current_release="1">
2663 <release seq="1">
2664 <messages></messages>
2665 </release>
2666 </grit>
2667 """.splitlines()
2668 # A grd file with a single message.
2669 NEW_GRD_CONTENTS1 = """<?xml version="1.0" encoding="UTF-8"?>
2670 <grit latest_public_release="1" current_release="1">
2671 <release seq="1">
2672 <messages>
2673 <message name="IDS_TEST1">
2674 Test string 1
2675 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482676 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE1"
2677 translateable="false">
2678 Non translateable message 1, should be ignored
2679 </message>
Mustafa Emre Acered1a48962020-06-30 19:15:392680 <message name="IDS_TEST_STRING_ACCESSIBILITY"
Mustafa Emre Acerd3ca8be2020-07-07 22:35:342681 is_accessibility_with_no_ui="true">
Mustafa Emre Acered1a48962020-06-30 19:15:392682 Accessibility label 1, should be ignored
2683 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142684 </messages>
2685 </release>
2686 </grit>
2687 """.splitlines()
2688 # A grd file with two messages.
2689 NEW_GRD_CONTENTS2 = """<?xml version="1.0" encoding="UTF-8"?>
2690 <grit latest_public_release="1" current_release="1">
2691 <release seq="1">
2692 <messages>
2693 <message name="IDS_TEST1">
2694 Test string 1
2695 </message>
2696 <message name="IDS_TEST2">
2697 Test string 2
2698 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482699 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE2"
2700 translateable="false">
2701 Non translateable message 2, should be ignored
2702 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142703 </messages>
2704 </release>
2705 </grit>
2706 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:262707 # A grd file with one ICU syntax message without syntax errors.
2708 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1 = """<?xml version="1.0" encoding="UTF-8"?>
2709 <grit latest_public_release="1" current_release="1">
2710 <release seq="1">
2711 <messages>
2712 <message name="IDS_TEST1">
2713 {NUM, plural,
2714 =1 {Test text for numeric one}
2715 other {Test text for plural with {NUM} as number}}
2716 </message>
2717 </messages>
2718 </release>
2719 </grit>
2720 """.splitlines()
2721 # A grd file with one ICU syntax message without syntax errors.
2722 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2 = """<?xml version="1.0" encoding="UTF-8"?>
2723 <grit latest_public_release="1" current_release="1">
2724 <release seq="1">
2725 <messages>
2726 <message name="IDS_TEST1">
2727 {NUM, plural,
2728 =1 {Different test text for numeric one}
2729 other {Different test text for plural with {NUM} as number}}
2730 </message>
2731 </messages>
2732 </release>
2733 </grit>
2734 """.splitlines()
2735 # A grd file with one ICU syntax message with syntax errors (misses a comma).
2736 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
2737 <grit latest_public_release="1" current_release="1">
2738 <release seq="1">
2739 <messages>
2740 <message name="IDS_TEST1">
2741 {NUM, plural
2742 =1 {Test text for numeric one}
2743 other {Test text for plural with {NUM} as number}}
2744 </message>
2745 </messages>
2746 </release>
2747 </grit>
2748 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142749
meacerff8a9b62019-12-10 19:43:582750 OLD_GRDP_CONTENTS = (
2751 '<?xml version="1.0" encoding="utf-8"?>',
2752 '<grit-part>',
2753 '</grit-part>'
2754 )
2755
2756 NEW_GRDP_CONTENTS1 = (
2757 '<?xml version="1.0" encoding="utf-8"?>',
2758 '<grit-part>',
2759 '<message name="IDS_PART_TEST1">',
2760 'Part string 1',
2761 '</message>',
2762 '</grit-part>')
2763
2764 NEW_GRDP_CONTENTS2 = (
2765 '<?xml version="1.0" encoding="utf-8"?>',
2766 '<grit-part>',
2767 '<message name="IDS_PART_TEST1">',
2768 'Part string 1',
2769 '</message>',
2770 '<message name="IDS_PART_TEST2">',
2771 'Part string 2',
2772 '</message>',
2773 '</grit-part>')
2774
Rainhard Findlingd8d04372020-08-13 13:30:092775 NEW_GRDP_CONTENTS3 = (
2776 '<?xml version="1.0" encoding="utf-8"?>',
2777 '<grit-part>',
2778 '<message name="IDS_PART_TEST1" desc="Description with typo.">',
2779 'Part string 1',
2780 '</message>',
2781 '</grit-part>')
2782
2783 NEW_GRDP_CONTENTS4 = (
2784 '<?xml version="1.0" encoding="utf-8"?>',
2785 '<grit-part>',
2786 '<message name="IDS_PART_TEST1" desc="Description with typo fixed.">',
2787 'Part string 1',
2788 '</message>',
2789 '</grit-part>')
2790
Rainhard Findling1a3e71e2020-09-21 07:33:352791 NEW_GRDP_CONTENTS5 = (
2792 '<?xml version="1.0" encoding="utf-8"?>',
2793 '<grit-part>',
2794 '<message name="IDS_PART_TEST1" meaning="Meaning with typo.">',
2795 'Part string 1',
2796 '</message>',
2797 '</grit-part>')
2798
2799 NEW_GRDP_CONTENTS6 = (
2800 '<?xml version="1.0" encoding="utf-8"?>',
2801 '<grit-part>',
2802 '<message name="IDS_PART_TEST1" meaning="Meaning with typo fixed.">',
2803 'Part string 1',
2804 '</message>',
2805 '</grit-part>')
2806
Rainhard Findlingfc31844c52020-05-15 09:58:262807 # A grdp file with one ICU syntax message without syntax errors.
2808 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = (
2809 '<?xml version="1.0" encoding="utf-8"?>',
2810 '<grit-part>',
2811 '<message name="IDS_PART_TEST1">',
2812 '{NUM, plural,',
2813 '=1 {Test text for numeric one}',
2814 'other {Test text for plural with {NUM} as number}}',
2815 '</message>',
2816 '</grit-part>')
2817 # A grdp file with one ICU syntax message without syntax errors.
2818 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2 = (
2819 '<?xml version="1.0" encoding="utf-8"?>',
2820 '<grit-part>',
2821 '<message name="IDS_PART_TEST1">',
2822 '{NUM, plural,',
2823 '=1 {Different test text for numeric one}',
2824 'other {Different test text for plural with {NUM} as number}}',
2825 '</message>',
2826 '</grit-part>')
2827
2828 # A grdp file with one ICU syntax message with syntax errors (superfluent
2829 # whitespace).
2830 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR = (
2831 '<?xml version="1.0" encoding="utf-8"?>',
2832 '<grit-part>',
2833 '<message name="IDS_PART_TEST1">',
2834 '{NUM, plural,',
2835 '= 1 {Test text for numeric one}',
2836 'other {Test text for plural with {NUM} as number}}',
2837 '</message>',
2838 '</grit-part>')
2839
Mustafa Emre Acerc8a012d2018-07-31 00:00:392840 DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
2841 'changelist. Run '
2842 'tools/translate/upload_screenshots.py to '
2843 'upload them instead:')
2844 GENERATE_SIGNATURES_MESSAGE = ('You are adding or modifying UI strings.\n'
2845 'To ensure the best translations, take '
2846 'screenshots of the relevant UI '
2847 '(https://g.co/chrome/translation) and add '
2848 'these files to your changelist:')
2849 REMOVE_SIGNATURES_MESSAGE = ('You removed strings associated with these '
2850 'files. Remove:')
Rainhard Findlingfc31844c52020-05-15 09:58:262851 ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
2852 'strings (problems or feedback? Contact '
2853 '[email protected]):')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142854
2855 def makeInputApi(self, files):
2856 input_api = MockInputApi()
2857 input_api.files = files
meacere7be7532019-10-02 17:41:032858 # Override os_path.exists because the presubmit uses the actual
2859 # os.path.exists.
2860 input_api.CreateMockFileInPath(
2861 [x.LocalPath() for x in input_api.AffectedFiles(include_deletes=True)])
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142862 return input_api
2863
meacerff8a9b62019-12-10 19:43:582864 """ CL modified and added messages, but didn't add any screenshots."""
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142865 def testNoScreenshots(self):
meacerff8a9b62019-12-10 19:43:582866 # No new strings (file contents same). Should not warn.
2867 input_api = self.makeInputApi([
2868 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
2869 self.NEW_GRD_CONTENTS1, action='M'),
2870 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1,
2871 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362872 warnings = PRESUBMIT.CheckStrings(input_api,
meacerff8a9b62019-12-10 19:43:582873 MockOutputApi())
2874 self.assertEqual(0, len(warnings))
2875
2876 # Add two new strings. Should have two warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142877 input_api = self.makeInputApi([
2878 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582879 self.NEW_GRD_CONTENTS1, action='M'),
2880 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2881 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362882 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142883 MockOutputApi())
2884 self.assertEqual(1, len(warnings))
2885 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerc6ed2682020-07-07 07:24:002886 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012887 self.assertEqual([
meacerff8a9b62019-12-10 19:43:582888 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2889 os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
2890 warnings[0].items)
Mustafa Emre Acer36eaad52019-11-12 23:03:342891
meacerff8a9b62019-12-10 19:43:582892 # Add four new strings. Should have four warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:212893 input_api = self.makeInputApi([
2894 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582895 self.OLD_GRD_CONTENTS, action='M'),
2896 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2897 self.OLD_GRDP_CONTENTS, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362898 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:212899 MockOutputApi())
2900 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:002901 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:212902 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:582903 self.assertEqual([
2904 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2905 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2906 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
2907 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
2908 ], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:212909
Rainhard Findlingd8d04372020-08-13 13:30:092910 def testModifiedMessageDescription(self):
2911 # CL modified a message description for a message that does not yet have a
Rainhard Findling1a3e71e2020-09-21 07:33:352912 # screenshot. Should not warn.
Rainhard Findlingd8d04372020-08-13 13:30:092913 input_api = self.makeInputApi([
2914 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
2915 self.NEW_GRDP_CONTENTS4, action='M')])
2916 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findling1a3e71e2020-09-21 07:33:352917 self.assertEqual(0, len(warnings))
Rainhard Findlingd8d04372020-08-13 13:30:092918
2919 # CL modified a message description for a message that already has a
2920 # screenshot. Should not warn.
2921 input_api = self.makeInputApi([
2922 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
2923 self.NEW_GRDP_CONTENTS4, action='M'),
2924 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2925 'binary', action='A')])
2926 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
2927 self.assertEqual(0, len(warnings))
2928
Rainhard Findling1a3e71e2020-09-21 07:33:352929 def testModifiedMessageMeaning(self):
2930 # CL modified a message meaning for a message that does not yet have a
2931 # screenshot. Should warn.
2932 input_api = self.makeInputApi([
2933 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
2934 self.NEW_GRDP_CONTENTS6, action='M')])
2935 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
2936 self.assertEqual(1, len(warnings))
2937
2938 # CL modified a message meaning for a message that already has a
2939 # screenshot. Should not warn.
2940 input_api = self.makeInputApi([
2941 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
2942 self.NEW_GRDP_CONTENTS6, action='M'),
2943 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2944 'binary', action='A')])
2945 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
2946 self.assertEqual(0, len(warnings))
2947
meacerff8a9b62019-12-10 19:43:582948 def testPngAddedSha1NotAdded(self):
2949 # CL added one new message in a grd file and added the png file associated
2950 # with it, but did not add the corresponding sha1 file. This should warn
2951 # twice:
2952 # - Once for the added png file (because we don't want developers to upload
2953 # actual images)
2954 # - Once for the missing .sha1 file
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142955 input_api = self.makeInputApi([
Mustafa Emre Acerea3e57a2018-12-17 23:51:012956 MockAffectedFile(
2957 'test.grd',
2958 self.NEW_GRD_CONTENTS1,
2959 self.OLD_GRD_CONTENTS,
2960 action='M'),
2961 MockAffectedFile(
2962 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
2963 ])
Saagar Sanghavifceeaae2020-08-12 16:40:362964 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142965 MockOutputApi())
2966 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:002967 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142968 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012969 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
2970 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:002971 self.assertEqual('error', warnings[1].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142972 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012973 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
2974 warnings[1].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142975
meacerff8a9b62019-12-10 19:43:582976 # CL added two messages (one in grd, one in grdp) and added the png files
2977 # associated with the messages, but did not add the corresponding sha1
2978 # files. This should warn twice:
2979 # - Once for the added png files (because we don't want developers to upload
2980 # actual images)
2981 # - Once for the missing .sha1 files
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142982 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:582983 # Modified files:
Mustafa Emre Acer36eaad52019-11-12 23:03:342984 MockAffectedFile(
2985 'test.grd',
meacerff8a9b62019-12-10 19:43:582986 self.NEW_GRD_CONTENTS1,
Mustafa Emre Acer36eaad52019-11-12 23:03:342987 self.OLD_GRD_CONTENTS,
meacer2308d0742019-11-12 18:15:422988 action='M'),
Mustafa Emre Acer12e7fee2019-11-18 18:49:552989 MockAffectedFile(
meacerff8a9b62019-12-10 19:43:582990 'part.grdp',
2991 self.NEW_GRDP_CONTENTS1,
2992 self.OLD_GRDP_CONTENTS,
2993 action='M'),
2994 # Added files:
2995 MockAffectedFile(
2996 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A'),
2997 MockAffectedFile(
2998 os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary',
2999 action='A')
Mustafa Emre Acerad8fb082019-11-19 04:24:213000 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363001 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213002 MockOutputApi())
3003 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003004 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213005 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583006 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png'),
3007 os.path.join('test_grd', 'IDS_TEST1.png')],
Mustafa Emre Acerad8fb082019-11-19 04:24:213008 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003009 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213010 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
meacerff8a9b62019-12-10 19:43:583011 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3012 os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3013 warnings[1].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213014
3015 def testScreenshotsWithSha1(self):
meacerff8a9b62019-12-10 19:43:583016 # CL added four messages (two each in a grd and grdp) and their
3017 # corresponding .sha1 files. No warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213018 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583019 # Modified files:
Mustafa Emre Acerad8fb082019-11-19 04:24:213020 MockAffectedFile(
3021 'test.grd',
3022 self.NEW_GRD_CONTENTS2,
3023 self.OLD_GRD_CONTENTS,
Mustafa Emre Acer12e7fee2019-11-18 18:49:553024 action='M'),
meacerff8a9b62019-12-10 19:43:583025 MockAffectedFile(
3026 'part.grdp',
3027 self.NEW_GRDP_CONTENTS2,
3028 self.OLD_GRDP_CONTENTS,
3029 action='M'),
3030 # Added files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013031 MockFile(
3032 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3033 'binary',
3034 action='A'),
3035 MockFile(
3036 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3037 'binary',
meacerff8a9b62019-12-10 19:43:583038 action='A'),
3039 MockFile(
3040 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3041 'binary',
3042 action='A'),
3043 MockFile(
3044 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3045 'binary',
3046 action='A'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013047 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363048 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143049 MockOutputApi())
3050 self.assertEqual([], warnings)
3051
3052 def testScreenshotsRemovedWithSha1(self):
meacerff8a9b62019-12-10 19:43:583053 # Replace new contents with old contents in grd and grp files, removing
3054 # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3055 # Should warn to remove the sha1 files associated with these strings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143056 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583057 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013058 MockAffectedFile(
3059 'test.grd',
meacerff8a9b62019-12-10 19:43:583060 self.OLD_GRD_CONTENTS, # new_contents
3061 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013062 action='M'),
meacerff8a9b62019-12-10 19:43:583063 MockAffectedFile(
3064 'part.grdp',
3065 self.OLD_GRDP_CONTENTS, # new_contents
3066 self.NEW_GRDP_CONTENTS2, # old_contents
3067 action='M'),
3068 # Unmodified files:
3069 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
3070 MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', ''),
3071 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3072 'binary', ''),
3073 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3074 'binary', '')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013075 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363076 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143077 MockOutputApi())
3078 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003079 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143080 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013081 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583082 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3083 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013084 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3085 os.path.join('test_grd', 'IDS_TEST2.png.sha1')
3086 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143087
meacerff8a9b62019-12-10 19:43:583088 # Same as above, but this time one of the .sha1 files is also removed.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143089 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583090 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013091 MockAffectedFile(
3092 'test.grd',
meacerff8a9b62019-12-10 19:43:583093 self.OLD_GRD_CONTENTS, # new_contents
3094 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013095 action='M'),
meacerff8a9b62019-12-10 19:43:583096 MockAffectedFile(
3097 'part.grdp',
3098 self.OLD_GRDP_CONTENTS, # new_contents
3099 self.NEW_GRDP_CONTENTS2, # old_contents
3100 action='M'),
3101 # Unmodified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013102 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
meacerff8a9b62019-12-10 19:43:583103 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3104 'binary', ''),
3105 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013106 MockAffectedFile(
3107 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3108 '',
3109 'old_contents',
meacerff8a9b62019-12-10 19:43:583110 action='D'),
3111 MockAffectedFile(
3112 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3113 '',
3114 'old_contents',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013115 action='D')
3116 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363117 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143118 MockOutputApi())
3119 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003120 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143121 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583122 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3123 os.path.join('test_grd', 'IDS_TEST1.png.sha1')
3124 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143125
meacerff8a9b62019-12-10 19:43:583126 # Remove all sha1 files. There should be no warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143127 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583128 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013129 MockAffectedFile(
3130 'test.grd',
3131 self.OLD_GRD_CONTENTS,
3132 self.NEW_GRD_CONTENTS2,
3133 action='M'),
meacerff8a9b62019-12-10 19:43:583134 MockAffectedFile(
3135 'part.grdp',
3136 self.OLD_GRDP_CONTENTS,
3137 self.NEW_GRDP_CONTENTS2,
3138 action='M'),
3139 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013140 MockFile(
3141 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3142 'binary',
3143 action='D'),
3144 MockFile(
3145 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3146 'binary',
meacerff8a9b62019-12-10 19:43:583147 action='D'),
3148 MockFile(
3149 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3150 'binary',
3151 action='D'),
3152 MockFile(
3153 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3154 'binary',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013155 action='D')
3156 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363157 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143158 MockOutputApi())
3159 self.assertEqual([], warnings)
3160
Rainhard Findlingfc31844c52020-05-15 09:58:263161 def testIcuSyntax(self):
3162 # Add valid ICU syntax string. Should not raise an error.
3163 input_api = self.makeInputApi([
3164 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3165 self.NEW_GRD_CONTENTS1, action='M'),
3166 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3167 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363168 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263169 # We expect no ICU syntax errors.
3170 icu_errors = [e for e in results
3171 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3172 self.assertEqual(0, len(icu_errors))
3173
3174 # Valid changes in ICU syntax. Should not raise an error.
3175 input_api = self.makeInputApi([
3176 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3177 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3178 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3179 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363180 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263181 # We expect no ICU syntax errors.
3182 icu_errors = [e for e in results
3183 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3184 self.assertEqual(0, len(icu_errors))
3185
3186 # Add invalid ICU syntax strings. Should raise two errors.
3187 input_api = self.makeInputApi([
3188 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3189 self.NEW_GRD_CONTENTS1, action='M'),
3190 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3191 self.NEW_GRD_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363192 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263193 # We expect 2 ICU syntax errors.
3194 icu_errors = [e for e in results
3195 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3196 self.assertEqual(1, len(icu_errors))
3197 self.assertEqual([
3198 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3199 'ICU syntax.',
3200 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3201 ], icu_errors[0].items)
3202
3203 # Change two strings to have ICU syntax errors. Should raise two errors.
3204 input_api = self.makeInputApi([
3205 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3206 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3207 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3208 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363209 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263210 # We expect 2 ICU syntax errors.
3211 icu_errors = [e for e in results
3212 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3213 self.assertEqual(1, len(icu_errors))
3214 self.assertEqual([
3215 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3216 'ICU syntax.',
3217 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3218 ], icu_errors[0].items)
3219
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143220
Mustafa Emre Acer51f2f742020-03-09 19:41:123221class TranslationExpectationsTest(unittest.TestCase):
3222 ERROR_MESSAGE_FORMAT = (
3223 "Failed to get a list of translatable grd files. "
3224 "This happens when:\n"
3225 " - One of the modified grd or grdp files cannot be parsed or\n"
3226 " - %s is not updated.\n"
3227 "Stack:\n"
3228 )
3229 REPO_ROOT = os.path.join('tools', 'translation', 'testdata')
3230 # This lists all .grd files under REPO_ROOT.
3231 EXPECTATIONS = os.path.join(REPO_ROOT,
3232 "translation_expectations.pyl")
3233 # This lists all .grd files under REPO_ROOT except unlisted.grd.
3234 EXPECTATIONS_WITHOUT_UNLISTED_FILE = os.path.join(
3235 REPO_ROOT, "translation_expectations_without_unlisted_file.pyl")
3236
3237 # Tests that the presubmit doesn't return when no grd or grdp files are
3238 # modified.
3239 def testExpectationsNoModifiedGrd(self):
3240 input_api = MockInputApi()
3241 input_api.files = [
3242 MockAffectedFile('not_used.txt', 'not used', 'not used', action='M')
3243 ]
3244 # Fake list of all grd files in the repo. This list is missing all grd/grdps
3245 # under tools/translation/testdata. This is OK because the presubmit won't
3246 # run in the first place since there are no modified grd/grps in input_api.
3247 grd_files = ['doesnt_exist_doesnt_matter.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363248 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123249 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3250 grd_files)
3251 self.assertEqual(0, len(warnings))
3252
3253
3254 # Tests that the list of files passed to the presubmit matches the list of
3255 # files in the expectations.
3256 def testExpectationsSuccess(self):
3257 # Mock input file list needs a grd or grdp file in order to run the
3258 # presubmit. The file itself doesn't matter.
3259 input_api = MockInputApi()
3260 input_api.files = [
3261 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3262 ]
3263 # List of all grd files in the repo.
3264 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3265 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363266 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123267 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3268 grd_files)
3269 self.assertEqual(0, len(warnings))
3270
3271 # Tests that the presubmit warns when a file is listed in expectations, but
3272 # does not actually exist.
3273 def testExpectationsMissingFile(self):
3274 # Mock input file list needs a grd or grdp file in order to run the
3275 # presubmit.
3276 input_api = MockInputApi()
3277 input_api.files = [
3278 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3279 ]
3280 # unlisted.grd is listed under tools/translation/testdata but is not
3281 # included in translation expectations.
3282 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363283 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123284 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3285 grd_files)
3286 self.assertEqual(1, len(warnings))
3287 self.assertTrue(warnings[0].message.startswith(
3288 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS))
3289 self.assertTrue(
3290 ("test.grd is listed in the translation expectations, "
3291 "but this grd file does not exist")
3292 in warnings[0].message)
3293
3294 # Tests that the presubmit warns when a file is not listed in expectations but
3295 # does actually exist.
3296 def testExpectationsUnlistedFile(self):
3297 # Mock input file list needs a grd or grdp file in order to run the
3298 # presubmit.
3299 input_api = MockInputApi()
3300 input_api.files = [
3301 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3302 ]
3303 # unlisted.grd is listed under tools/translation/testdata but is not
3304 # included in translation expectations.
3305 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3306 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363307 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123308 input_api, MockOutputApi(), self.REPO_ROOT,
3309 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3310 self.assertEqual(1, len(warnings))
3311 self.assertTrue(warnings[0].message.startswith(
3312 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3313 self.assertTrue(
3314 ("unlisted.grd appears to be translatable "
3315 "(because it contains <file> or <message> elements), "
3316 "but is not listed in the translation expectations.")
3317 in warnings[0].message)
3318
3319 # Tests that the presubmit warns twice:
3320 # - for a non-existing file listed in expectations
3321 # - for an existing file not listed in expectations
3322 def testMultipleWarnings(self):
3323 # Mock input file list needs a grd or grdp file in order to run the
3324 # presubmit.
3325 input_api = MockInputApi()
3326 input_api.files = [
3327 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3328 ]
3329 # unlisted.grd is listed under tools/translation/testdata but is not
3330 # included in translation expectations.
3331 # test.grd is not listed under tools/translation/testdata but is included
3332 # in translation expectations.
3333 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363334 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123335 input_api, MockOutputApi(), self.REPO_ROOT,
3336 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3337 self.assertEqual(1, len(warnings))
3338 self.assertTrue(warnings[0].message.startswith(
3339 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3340 self.assertTrue(
3341 ("unlisted.grd appears to be translatable "
3342 "(because it contains <file> or <message> elements), "
3343 "but is not listed in the translation expectations.")
3344 in warnings[0].message)
3345 self.assertTrue(
3346 ("test.grd is listed in the translation expectations, "
3347 "but this grd file does not exist")
3348 in warnings[0].message)
3349
3350
Dominic Battre033531052018-09-24 15:45:343351class DISABLETypoInTest(unittest.TestCase):
3352
3353 def testPositive(self):
3354 # Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
3355 # where the desire is to disable a test.
3356 tests = [
3357 # Disabled on one platform:
3358 '#if defined(OS_WIN)\n'
3359 '#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
3360 '#else\n'
3361 '#define MAYBE_FoobarTest FoobarTest\n'
3362 '#endif\n',
3363 # Disabled on one platform spread cross lines:
3364 '#if defined(OS_WIN)\n'
3365 '#define MAYBE_FoobarTest \\\n'
3366 ' DISABLE_FoobarTest\n'
3367 '#else\n'
3368 '#define MAYBE_FoobarTest FoobarTest\n'
3369 '#endif\n',
3370 # Disabled on all platforms:
3371 ' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
3372 # Disabled on all platforms but multiple lines
3373 ' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
3374 ]
3375
3376 for test in tests:
3377 mock_input_api = MockInputApi()
3378 mock_input_api.files = [
3379 MockFile('some/path/foo_unittest.cc', test.splitlines()),
3380 ]
3381
Saagar Sanghavifceeaae2020-08-12 16:40:363382 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343383 MockOutputApi())
3384 self.assertEqual(
3385 1,
3386 len(results),
3387 msg=('expected len(results) == 1 but got %d in test: %s' %
3388 (len(results), test)))
3389 self.assertTrue(
3390 'foo_unittest.cc' in results[0].message,
3391 msg=('expected foo_unittest.cc in message but got %s in test %s' %
3392 (results[0].message, test)))
3393
3394 def testIngoreNotTestFiles(self):
3395 mock_input_api = MockInputApi()
3396 mock_input_api.files = [
3397 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'),
3398 ]
3399
Saagar Sanghavifceeaae2020-08-12 16:40:363400 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343401 MockOutputApi())
3402 self.assertEqual(0, len(results))
3403
Katie Df13948e2018-09-25 07:33:443404 def testIngoreDeletedFiles(self):
3405 mock_input_api = MockInputApi()
3406 mock_input_api.files = [
3407 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'),
3408 ]
3409
Saagar Sanghavifceeaae2020-08-12 16:40:363410 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Katie Df13948e2018-09-25 07:33:443411 MockOutputApi())
3412 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:343413
Nina Satragnof7660532021-09-20 18:03:353414class ForgettingMAYBEInTests(unittest.TestCase):
3415 def testPositive(self):
3416 test = (
3417 '#if defined(HAS_ENERGY)\n'
3418 '#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
3419 '#else\n'
3420 '#define MAYBE_CastExplosion CastExplosion\n'
3421 '#endif\n'
3422 'TEST_F(ArchWizard, CastExplosion) {\n'
3423 '#if defined(ARCH_PRIEST_IN_PARTY)\n'
3424 '#define MAYBE_ArchPriest ArchPriest\n'
3425 '#else\n'
3426 '#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
3427 '#endif\n'
3428 'TEST_F(ArchPriest, CastNaturesBounty) {\n'
3429 '#if !defined(CRUSADER_IN_PARTY)\n'
3430 '#define MAYBE_Crusader \\\n'
3431 ' DISABLED_Crusader \n'
3432 '#else\n'
3433 '#define MAYBE_Crusader \\\n'
3434 ' Crusader\n'
3435 '#endif\n'
3436 ' TEST_F(\n'
3437 ' Crusader,\n'
3438 ' CastTaunt) { }\n'
3439 '#if defined(LEARNED_BASIC_SKILLS)\n'
3440 '#define MAYBE_CastSteal \\\n'
3441 ' DISABLED_CastSteal \n'
3442 '#else\n'
3443 '#define MAYBE_CastSteal \\\n'
3444 ' CastSteal\n'
3445 '#endif\n'
3446 ' TEST_F(\n'
3447 ' ThiefClass,\n'
3448 ' CastSteal) { }\n'
3449 )
3450 mock_input_api = MockInputApi()
3451 mock_input_api.files = [
3452 MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
3453 ]
3454 results = PRESUBMIT.CheckForgettingMAYBEInTests(mock_input_api,
3455 MockOutputApi())
3456 self.assertEqual(4, len(results))
3457 self.assertTrue('CastExplosion' in results[0].message)
3458 self.assertTrue('fantasyworld/classes_unittest.cc:2' in results[0].message)
3459 self.assertTrue('ArchPriest' in results[1].message)
3460 self.assertTrue('fantasyworld/classes_unittest.cc:8' in results[1].message)
3461 self.assertTrue('Crusader' in results[2].message)
3462 self.assertTrue('fantasyworld/classes_unittest.cc:14' in results[2].message)
3463 self.assertTrue('CastSteal' in results[3].message)
3464 self.assertTrue('fantasyworld/classes_unittest.cc:24' in results[3].message)
3465
3466 def testNegative(self):
3467 test = (
3468 '#if defined(HAS_ENERGY)\n'
3469 '#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
3470 '#else\n'
3471 '#define MAYBE_CastExplosion CastExplosion\n'
3472 '#endif\n'
3473 'TEST_F(ArchWizard, MAYBE_CastExplosion) {\n'
3474 '#if defined(ARCH_PRIEST_IN_PARTY)\n'
3475 '#define MAYBE_ArchPriest ArchPriest\n'
3476 '#else\n'
3477 '#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
3478 '#endif\n'
3479 'TEST_F(MAYBE_ArchPriest, CastNaturesBounty) {\n'
3480 '#if !defined(CRUSADER_IN_PARTY)\n'
3481 '#define MAYBE_Crusader \\\n'
3482 ' DISABLED_Crusader \n'
3483 '#else\n'
3484 '#define MAYBE_Crusader \\\n'
3485 ' Crusader\n'
3486 '#endif\n'
3487 ' TEST_F(\n'
3488 ' MAYBE_Crusader,\n'
3489 ' CastTaunt) { }\n'
3490 '#if defined(LEARNED_BASIC_SKILLS)\n'
3491 '#define MAYBE_CastSteal \\\n'
3492 ' DISABLED_CastSteal \n'
3493 '#else\n'
3494 '#define MAYBE_CastSteal \\\n'
3495 ' CastSteal\n'
3496 '#endif\n'
3497 ' TEST_F(\n'
3498 ' ThiefClass,\n'
3499 ' MAYBE_CastSteal) { }\n'
3500 )
3501
3502 mock_input_api = MockInputApi()
3503 mock_input_api.files = [
3504 MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
3505 ]
3506 results = PRESUBMIT.CheckForgettingMAYBEInTests(mock_input_api,
3507 MockOutputApi())
3508 self.assertEqual(0, len(results))
Dirk Pranke3c18a382019-03-15 01:07:513509
Max Morozb47503b2019-08-08 21:03:273510class CheckFuzzTargetsTest(unittest.TestCase):
3511
3512 def _check(self, files):
3513 mock_input_api = MockInputApi()
3514 mock_input_api.files = []
3515 for fname, contents in files.items():
3516 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363517 return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api, MockOutputApi())
Max Morozb47503b2019-08-08 21:03:273518
3519 def testLibFuzzerSourcesIgnored(self):
3520 results = self._check({
3521 "third_party/lib/Fuzzer/FuzzerDriver.cpp": "LLVMFuzzerInitialize",
3522 })
3523 self.assertEqual(results, [])
3524
3525 def testNonCodeFilesIgnored(self):
3526 results = self._check({
3527 "README.md": "LLVMFuzzerInitialize",
3528 })
3529 self.assertEqual(results, [])
3530
3531 def testNoErrorHeaderPresent(self):
3532 results = self._check({
3533 "fuzzer.cc": (
3534 "#include \"testing/libfuzzer/libfuzzer_exports.h\"\n" +
3535 "LLVMFuzzerInitialize"
3536 )
3537 })
3538 self.assertEqual(results, [])
3539
3540 def testErrorMissingHeader(self):
3541 results = self._check({
3542 "fuzzer.cc": "LLVMFuzzerInitialize"
3543 })
3544 self.assertEqual(len(results), 1)
3545 self.assertEqual(results[0].items, ['fuzzer.cc'])
3546
3547
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263548class SetNoParentTest(unittest.TestCase):
John Abd-El-Malekdfd1edc2021-02-24 22:22:403549 def testSetNoParentTopLevelAllowed(self):
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263550 mock_input_api = MockInputApi()
3551 mock_input_api.files = [
3552 MockAffectedFile('goat/OWNERS',
3553 [
3554 'set noparent',
3555 '[email protected]',
John Abd-El-Malekdfd1edc2021-02-24 22:22:403556 ])
3557 ]
3558 mock_output_api = MockOutputApi()
3559 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
3560 self.assertEqual([], errors)
3561
3562 def testSetNoParentMissing(self):
3563 mock_input_api = MockInputApi()
3564 mock_input_api.files = [
3565 MockAffectedFile('services/goat/OWNERS',
3566 [
3567 'set noparent',
3568 '[email protected]',
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263569 'per-file *.json=set noparent',
3570 'per-file *[email protected]',
3571 ])
3572 ]
3573 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363574 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263575 self.assertEqual(1, len(errors))
3576 self.assertTrue('goat/OWNERS:1' in errors[0].long_text)
3577 self.assertTrue('goat/OWNERS:3' in errors[0].long_text)
3578
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263579 def testSetNoParentWithCorrectRule(self):
3580 mock_input_api = MockInputApi()
3581 mock_input_api.files = [
John Abd-El-Malekdfd1edc2021-02-24 22:22:403582 MockAffectedFile('services/goat/OWNERS',
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263583 [
3584 'set noparent',
3585 'file://ipc/SECURITY_OWNERS',
3586 'per-file *.json=set noparent',
3587 'per-file *.json=file://ipc/SECURITY_OWNERS',
3588 ])
3589 ]
3590 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363591 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263592 self.assertEqual([], errors)
3593
3594
Ken Rockotc31f4832020-05-29 18:58:513595class MojomStabilityCheckTest(unittest.TestCase):
3596 def runTestWithAffectedFiles(self, affected_files):
3597 mock_input_api = MockInputApi()
3598 mock_input_api.files = affected_files
3599 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363600 return PRESUBMIT.CheckStableMojomChanges(
Ken Rockotc31f4832020-05-29 18:58:513601 mock_input_api, mock_output_api)
3602
3603 def testSafeChangePasses(self):
3604 errors = self.runTestWithAffectedFiles([
3605 MockAffectedFile('foo/foo.mojom',
3606 ['[Stable] struct S { [MinVersion=1] int32 x; };'],
3607 old_contents=['[Stable] struct S {};'])
3608 ])
3609 self.assertEqual([], errors)
3610
3611 def testBadChangeFails(self):
3612 errors = self.runTestWithAffectedFiles([
3613 MockAffectedFile('foo/foo.mojom',
3614 ['[Stable] struct S { int32 x; };'],
3615 old_contents=['[Stable] struct S {};'])
3616 ])
3617 self.assertEqual(1, len(errors))
3618 self.assertTrue('not backward-compatible' in errors[0].message)
3619
Ken Rockotad7901f942020-06-04 20:17:093620 def testDeletedFile(self):
3621 """Regression test for https://crbug.com/1091407."""
3622 errors = self.runTestWithAffectedFiles([
3623 MockAffectedFile('a.mojom', [], old_contents=['struct S {};'],
3624 action='D'),
3625 MockAffectedFile('b.mojom',
3626 ['struct S {}; struct T { S s; };'],
3627 old_contents=['import "a.mojom"; struct T { S s; };'])
3628 ])
3629 self.assertEqual([], errors)
3630
Jose Magana2b456f22021-03-09 23:26:403631class CheckForUseOfChromeAppsDeprecationsTest(unittest.TestCase):
3632
3633 ERROR_MSG_PIECE = 'technologies which will soon be deprecated'
3634
3635 # Each positive test is also a naive negative test for the other cases.
3636
3637 def testWarningNMF(self):
3638 mock_input_api = MockInputApi()
3639 mock_input_api.files = [
3640 MockAffectedFile(
3641 'foo.NMF',
3642 ['"program"', '"Z":"content"', 'B'],
3643 ['"program"', 'B'],
3644 scm_diff='\n'.join([
3645 '--- foo.NMF.old 2020-12-02 20:40:54.430676385 +0100',
3646 '+++ foo.NMF.new 2020-12-02 20:41:02.086700197 +0100',
3647 '@@ -1,2 +1,3 @@',
3648 ' "program"',
3649 '+"Z":"content"',
3650 ' B']),
3651 action='M')
3652 ]
3653 mock_output_api = MockOutputApi()
3654 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3655 mock_output_api)
3656 self.assertEqual(1, len(errors))
3657 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
3658 self.assertTrue( 'foo.NMF' in errors[0].message)
3659
3660 def testWarningManifest(self):
3661 mock_input_api = MockInputApi()
3662 mock_input_api.files = [
3663 MockAffectedFile(
3664 'manifest.json',
3665 ['"app":', '"Z":"content"', 'B'],
3666 ['"app":"', 'B'],
3667 scm_diff='\n'.join([
3668 '--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
3669 '+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
3670 '@@ -1,2 +1,3 @@',
3671 ' "app"',
3672 '+"Z":"content"',
3673 ' B']),
3674 action='M')
3675 ]
3676 mock_output_api = MockOutputApi()
3677 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3678 mock_output_api)
3679 self.assertEqual(1, len(errors))
3680 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
3681 self.assertTrue( 'manifest.json' in errors[0].message)
3682
3683 def testOKWarningManifestWithoutApp(self):
3684 mock_input_api = MockInputApi()
3685 mock_input_api.files = [
3686 MockAffectedFile(
3687 'manifest.json',
3688 ['"name":', '"Z":"content"', 'B'],
3689 ['"name":"', 'B'],
3690 scm_diff='\n'.join([
3691 '--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
3692 '+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
3693 '@@ -1,2 +1,3 @@',
3694 ' "app"',
3695 '+"Z":"content"',
3696 ' B']),
3697 action='M')
3698 ]
3699 mock_output_api = MockOutputApi()
3700 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3701 mock_output_api)
3702 self.assertEqual(0, len(errors))
3703
3704 def testWarningPPAPI(self):
3705 mock_input_api = MockInputApi()
3706 mock_input_api.files = [
3707 MockAffectedFile(
3708 'foo.hpp',
3709 ['A', '#include <ppapi.h>', 'B'],
3710 ['A', 'B'],
3711 scm_diff='\n'.join([
3712 '--- foo.hpp.old 2020-12-02 20:40:54.430676385 +0100',
3713 '+++ foo.hpp.new 2020-12-02 20:41:02.086700197 +0100',
3714 '@@ -1,2 +1,3 @@',
3715 ' A',
3716 '+#include <ppapi.h>',
3717 ' B']),
3718 action='M')
3719 ]
3720 mock_output_api = MockOutputApi()
3721 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3722 mock_output_api)
3723 self.assertEqual(1, len(errors))
3724 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
3725 self.assertTrue( 'foo.hpp' in errors[0].message)
3726
3727 def testNoWarningPPAPI(self):
3728 mock_input_api = MockInputApi()
3729 mock_input_api.files = [
3730 MockAffectedFile(
3731 'foo.txt',
3732 ['A', 'Peppapig', 'B'],
3733 ['A', 'B'],
3734 scm_diff='\n'.join([
3735 '--- foo.txt.old 2020-12-02 20:40:54.430676385 +0100',
3736 '+++ foo.txt.new 2020-12-02 20:41:02.086700197 +0100',
3737 '@@ -1,2 +1,3 @@',
3738 ' A',
3739 '+Peppapig',
3740 ' B']),
3741 action='M')
3742 ]
3743 mock_output_api = MockOutputApi()
3744 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3745 mock_output_api)
3746 self.assertEqual(0, len(errors))
3747
Dominic Battre645d42342020-12-04 16:14:103748class CheckDeprecationOfPreferencesTest(unittest.TestCase):
3749 # Test that a warning is generated if a preference registration is removed
3750 # from a random file.
3751 def testWarning(self):
3752 mock_input_api = MockInputApi()
3753 mock_input_api.files = [
3754 MockAffectedFile(
3755 'foo.cc',
3756 ['A', 'B'],
3757 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
3758 scm_diff='\n'.join([
3759 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
3760 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
3761 '@@ -1,3 +1,2 @@',
3762 ' A',
3763 '-prefs->RegisterStringPref("foo", "default");',
3764 ' B']),
3765 action='M')
3766 ]
3767 mock_output_api = MockOutputApi()
3768 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3769 mock_output_api)
3770 self.assertEqual(1, len(errors))
3771 self.assertTrue(
3772 'Discovered possible removal of preference registrations' in
3773 errors[0].message)
3774
3775 # Test that a warning is inhibited if the preference registration was moved
3776 # to the deprecation functions in browser prefs.
3777 def testNoWarningForMigration(self):
3778 mock_input_api = MockInputApi()
3779 mock_input_api.files = [
3780 # RegisterStringPref was removed from foo.cc.
3781 MockAffectedFile(
3782 'foo.cc',
3783 ['A', 'B'],
3784 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
3785 scm_diff='\n'.join([
3786 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
3787 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
3788 '@@ -1,3 +1,2 @@',
3789 ' A',
3790 '-prefs->RegisterStringPref("foo", "default");',
3791 ' B']),
3792 action='M'),
3793 # But the preference was properly migrated.
3794 MockAffectedFile(
3795 'chrome/browser/prefs/browser_prefs.cc',
3796 [
3797 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3798 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3799 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3800 'prefs->RegisterStringPref("foo", "default");',
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 '@@ -2,3 +2,4 @@',
3813 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3814 ' // BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3815 '+prefs->RegisterStringPref("foo", "default");',
3816 ' // END_MIGRATE_OBSOLETE_PROFILE_PREFS']),
3817 action='M'),
3818 ]
3819 mock_output_api = MockOutputApi()
3820 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3821 mock_output_api)
3822 self.assertEqual(0, len(errors))
3823
3824 # Test that a warning is NOT inhibited if the preference registration was
3825 # moved to a place outside of the migration functions in browser_prefs.cc
3826 def testWarningForImproperMigration(self):
3827 mock_input_api = MockInputApi()
3828 mock_input_api.files = [
3829 # RegisterStringPref was removed from foo.cc.
3830 MockAffectedFile(
3831 'foo.cc',
3832 ['A', 'B'],
3833 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
3834 scm_diff='\n'.join([
3835 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
3836 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
3837 '@@ -1,3 +1,2 @@',
3838 ' A',
3839 '-prefs->RegisterStringPref("foo", "default");',
3840 ' B']),
3841 action='M'),
3842 # The registration call was moved to a place in browser_prefs.cc that
3843 # is outside the migration functions.
3844 MockAffectedFile(
3845 'chrome/browser/prefs/browser_prefs.cc',
3846 [
3847 'prefs->RegisterStringPref("foo", "default");',
3848 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3849 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3850 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3851 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3852 ],
3853 [
3854 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3855 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3856 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3857 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3858 ],
3859 scm_diff='\n'.join([
3860 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
3861 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
3862 '@@ -1,2 +1,3 @@',
3863 '+prefs->RegisterStringPref("foo", "default");',
3864 ' // BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3865 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS']),
3866 action='M'),
3867 ]
3868 mock_output_api = MockOutputApi()
3869 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3870 mock_output_api)
3871 self.assertEqual(1, len(errors))
3872 self.assertTrue(
3873 'Discovered possible removal of preference registrations' in
3874 errors[0].message)
3875
3876 # Check that the presubmit fails if a marker line in brower_prefs.cc is
3877 # deleted.
3878 def testDeletedMarkerRaisesError(self):
3879 mock_input_api = MockInputApi()
3880 mock_input_api.files = [
3881 MockAffectedFile('chrome/browser/prefs/browser_prefs.cc',
3882 [
3883 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3884 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3885 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3886 # The following line is deleted for this test
3887 # '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3888 ])
3889 ]
3890 mock_output_api = MockOutputApi()
3891 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3892 mock_output_api)
3893 self.assertEqual(1, len(errors))
3894 self.assertEqual(
3895 'Broken .*MIGRATE_OBSOLETE_.*_PREFS markers in browser_prefs.cc.',
3896 errors[0].message)
3897
Kevin McNee967dd2d22021-11-15 16:09:293898class MPArchApiUsage(unittest.TestCase):
3899 def _assert_notify(self, expect_cc, msg, local_path, new_contents):
3900 mock_input_api = MockInputApi()
3901 mock_output_api = MockOutputApi()
3902 mock_input_api.files = [
3903 MockFile(local_path, new_contents),
3904 ]
3905 PRESUBMIT.CheckMPArchApiUsage(mock_input_api, mock_output_api)
3906 self.assertEqual(
3907 expect_cc,
3908 '[email protected]' in mock_output_api.more_cc,
3909 msg)
3910
3911 def testNotify(self):
3912 self._assert_notify(
3913 True,
3914 'Introduce WCO and WCUD',
3915 'chrome/my_feature.h',
3916 ['class MyFeature',
3917 ' : public content::WebContentsObserver,',
3918 ' public content::WebContentsUserData<MyFeature> {};',
3919 ])
3920 self._assert_notify(
3921 True,
3922 'Introduce WCO override',
3923 'chrome/my_feature.h',
3924 ['void DidFinishNavigation(',
3925 ' content::NavigationHandle* navigation_handle) override;',
3926 ])
3927 self._assert_notify(
3928 True,
3929 'Introduce IsInMainFrame',
3930 'chrome/my_feature.cc',
3931 ['void DoSomething(content::NavigationHandle* navigation_handle) {',
3932 ' if (navigation_handle->IsInMainFrame())',
3933 ' all_of_our_page_state.reset();',
3934 '}',
3935 ])
3936 self._assert_notify(
3937 True,
3938 'Introduce WC::FromRenderFrameHost',
3939 'chrome/my_feature.cc',
3940 ['void DoSomething(content::RenderFrameHost* rfh) {',
3941 ' auto* wc = content::WebContents::FromRenderFrameHost(rfh);',
3942 ' ChangeTabState(wc);',
3943 '}',
3944 ])
3945
3946 def testNoNotify(self):
3947 self._assert_notify(
3948 False,
3949 'No API usage',
3950 'chrome/my_feature.cc',
3951 ['void DoSomething() {',
3952 ' // TODO: Something',
3953 '}',
3954 ])
3955 # Something under a top level directory we're not concerned about happens
3956 # to share a name with a content API.
3957 self._assert_notify(
3958 False,
3959 'Uninteresting top level directory',
3960 'third_party/my_dep/my_code.cc',
3961 ['bool HasParent(Node* node) {',
3962 ' return node->GetParent();',
3963 '}',
3964 ])
3965 # We're not concerned with usage in test code.
3966 self._assert_notify(
3967 False,
3968 'Usage in test code',
3969 'chrome/my_feature_unittest.cc',
3970 ['TEST_F(MyFeatureTest, DoesSomething) {',
3971 ' EXPECT_TRUE(web_contents()->GetMainFrame());',
3972 '}',
3973 ])
3974
Dominic Battre645d42342020-12-04 16:14:103975
[email protected]2299dcf2012-11-15 19:56:243976if __name__ == '__main__':
3977 unittest.main()