blob: ce3aacd6e29813592c99498e4388fc68ae9a43e9 [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):
Henrique Ferreiro2e1aa1092021-11-29 22:22:121526 files = [
James Cook6b6597c2019-11-06 22:05:291527 MockFile('ash/file.cc',
1528 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1529 MockFile('chrome/browser/chromeos/file.cc',
1530 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1531 MockFile('chromeos/file.cc',
1532 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1533 MockFile('components/arc/file.cc',
1534 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1535 MockFile('components/exo/file.cc',
1536 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1537 ]
Henrique Ferreiro2e1aa1092021-11-29 22:22:121538 input_api = MockInputApi()
1539 for file in files:
1540 input_api.files = [file]
1541 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
1542 input_api, MockOutputApi())
1543 self.assertEqual(1, len(warnings))
James Cook6b6597c2019-11-06 22:05:291544
1545 def testDoesNotWarnOnSyncOsPref(self):
1546 input_api = MockInputApi()
1547 input_api.files = [
1548 MockFile('chromeos/file.cc',
1549 ['PrefRegistrySyncable::SYNCABLE_OS_PREF']),
1550 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361551 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291552 input_api, MockOutputApi())
1553 self.assertEqual(0, len(warnings))
1554
Henrique Ferreiro2e1aa1092021-11-29 22:22:121555 def testDoesNotWarnOnOtherDirectories(self):
James Cook6b6597c2019-11-06 22:05:291556 input_api = MockInputApi()
1557 input_api.files = [
1558 MockFile('chrome/browser/ui/file.cc',
1559 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1560 MockFile('components/sync/file.cc',
1561 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1562 MockFile('content/browser/file.cc',
1563 ['PrefRegistrySyncable::SYNCABLE_PREF']),
Henrique Ferreiro2e1aa1092021-11-29 22:22:121564 MockFile('a/notchromeos/file.cc',
1565 ['PrefRegistrySyncable::SYNCABLE_PREF']),
James Cook6b6597c2019-11-06 22:05:291566 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361567 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291568 input_api, MockOutputApi())
1569 self.assertEqual(0, len(warnings))
1570
1571 def testSeparateWarningForPriorityPrefs(self):
1572 input_api = MockInputApi()
1573 input_api.files = [
1574 MockFile('chromeos/file.cc',
1575 ['PrefRegistrySyncable::SYNCABLE_PREF',
1576 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']),
1577 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361578 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291579 input_api, MockOutputApi())
1580 self.assertEqual(2, len(warnings))
1581
1582
jbriance9e12f162016-11-25 07:57:501583class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311584 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501585 mock_input_api = MockInputApi()
1586 mock_input_api.files = [
1587 MockAffectedFile('somewhere/file.cc', [
1588 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311589 ]),
1590 MockAffectedFile('third_party/header.h', [
1591 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501592 ])
1593 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361594 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391595 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501596 self.assertEqual(0, len(warnings))
1597
1598 def testNoNestedDeclaration(self):
1599 mock_input_api = MockInputApi()
1600 mock_input_api.files = [
1601 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311602 'class SomeClass {',
1603 ' protected:',
1604 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501605 '};'
1606 ])
1607 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361608 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391609 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501610 self.assertEqual(0, len(warnings))
1611
1612 def testSubStrings(self):
1613 mock_input_api = MockInputApi()
1614 mock_input_api.files = [
1615 MockAffectedFile('somewhere/header.h', [
1616 'class NotUsefulClass;',
1617 'struct SomeStruct;',
1618 'UsefulClass *p1;',
1619 'SomeStructPtr *p2;'
1620 ])
1621 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361622 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391623 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501624 self.assertEqual(2, len(warnings))
1625
1626 def testUselessForwardDeclaration(self):
1627 mock_input_api = MockInputApi()
1628 mock_input_api.files = [
1629 MockAffectedFile('somewhere/header.h', [
1630 'class DummyClass;',
1631 'struct DummyStruct;',
1632 'class UsefulClass;',
1633 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311634 ])
jbriance9e12f162016-11-25 07:57:501635 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361636 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391637 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501638 self.assertEqual(2, len(warnings))
1639
jbriance2c51e821a2016-12-12 08:24:311640 def testBlinkHeaders(self):
1641 mock_input_api = MockInputApi()
1642 mock_input_api.files = [
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 ]),
Kent Tamura32dbbcb2018-11-30 12:28:491647 MockAffectedFile('third_party\\blink\\header.h', [
jbriance2c51e821a2016-12-12 08:24:311648 'class DummyClass;',
1649 'struct DummyStruct;',
1650 ])
1651 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361652 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391653 MockOutputApi())
jbriance2c51e821a2016-12-12 08:24:311654 self.assertEqual(4, len(warnings))
1655
jbriance9e12f162016-11-25 07:57:501656
rlanday6802cf632017-05-30 17:48:361657class RelativeIncludesTest(unittest.TestCase):
1658 def testThirdPartyNotWebKitIgnored(self):
1659 mock_input_api = MockInputApi()
1660 mock_input_api.files = [
1661 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1662 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1663 ]
1664
1665 mock_output_api = MockOutputApi()
1666
Saagar Sanghavifceeaae2020-08-12 16:40:361667 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361668 mock_input_api, mock_output_api)
1669 self.assertEqual(0, len(errors))
1670
1671 def testNonCppFileIgnored(self):
1672 mock_input_api = MockInputApi()
1673 mock_input_api.files = [
1674 MockAffectedFile('test.py', '#include "../header.h"'),
1675 ]
1676
1677 mock_output_api = MockOutputApi()
1678
Saagar Sanghavifceeaae2020-08-12 16:40:361679 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361680 mock_input_api, mock_output_api)
1681 self.assertEqual(0, len(errors))
1682
1683 def testInnocuousChangesAllowed(self):
1684 mock_input_api = MockInputApi()
1685 mock_input_api.files = [
1686 MockAffectedFile('test.cpp', '#include "header.h"'),
1687 MockAffectedFile('test2.cpp', '../'),
1688 ]
1689
1690 mock_output_api = MockOutputApi()
1691
Saagar Sanghavifceeaae2020-08-12 16:40:361692 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361693 mock_input_api, mock_output_api)
1694 self.assertEqual(0, len(errors))
1695
1696 def testRelativeIncludeNonWebKitProducesError(self):
1697 mock_input_api = MockInputApi()
1698 mock_input_api.files = [
1699 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1700 ]
1701
1702 mock_output_api = MockOutputApi()
1703
Saagar Sanghavifceeaae2020-08-12 16:40:361704 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361705 mock_input_api, mock_output_api)
1706 self.assertEqual(1, len(errors))
1707
1708 def testRelativeIncludeWebKitProducesError(self):
1709 mock_input_api = MockInputApi()
1710 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491711 MockAffectedFile('third_party/blink/test.cpp',
rlanday6802cf632017-05-30 17:48:361712 ['#include "../header.h']),
1713 ]
1714
1715 mock_output_api = MockOutputApi()
1716
Saagar Sanghavifceeaae2020-08-12 16:40:361717 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361718 mock_input_api, mock_output_api)
1719 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241720
Daniel Cheng13ca61a882017-08-25 15:11:251721
Daniel Bratell65b033262019-04-23 08:17:061722class CCIncludeTest(unittest.TestCase):
1723 def testThirdPartyNotBlinkIgnored(self):
1724 mock_input_api = MockInputApi()
1725 mock_input_api.files = [
1726 MockAffectedFile('third_party/test.cpp', '#include "file.cc"'),
1727 ]
1728
1729 mock_output_api = MockOutputApi()
1730
Saagar Sanghavifceeaae2020-08-12 16:40:361731 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061732 mock_input_api, mock_output_api)
1733 self.assertEqual(0, len(errors))
1734
1735 def testPythonFileIgnored(self):
1736 mock_input_api = MockInputApi()
1737 mock_input_api.files = [
1738 MockAffectedFile('test.py', '#include "file.cc"'),
1739 ]
1740
1741 mock_output_api = MockOutputApi()
1742
Saagar Sanghavifceeaae2020-08-12 16:40:361743 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061744 mock_input_api, mock_output_api)
1745 self.assertEqual(0, len(errors))
1746
1747 def testIncFilesAccepted(self):
1748 mock_input_api = MockInputApi()
1749 mock_input_api.files = [
1750 MockAffectedFile('test.py', '#include "file.inc"'),
1751 ]
1752
1753 mock_output_api = MockOutputApi()
1754
Saagar Sanghavifceeaae2020-08-12 16:40:361755 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061756 mock_input_api, mock_output_api)
1757 self.assertEqual(0, len(errors))
1758
1759 def testInnocuousChangesAllowed(self):
1760 mock_input_api = MockInputApi()
1761 mock_input_api.files = [
1762 MockAffectedFile('test.cpp', '#include "header.h"'),
1763 MockAffectedFile('test2.cpp', 'Something "file.cc"'),
1764 ]
1765
1766 mock_output_api = MockOutputApi()
1767
Saagar Sanghavifceeaae2020-08-12 16:40:361768 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061769 mock_input_api, mock_output_api)
1770 self.assertEqual(0, len(errors))
1771
1772 def testCcIncludeNonBlinkProducesError(self):
1773 mock_input_api = MockInputApi()
1774 mock_input_api.files = [
1775 MockAffectedFile('test.cpp', ['#include "file.cc"']),
1776 ]
1777
1778 mock_output_api = MockOutputApi()
1779
Saagar Sanghavifceeaae2020-08-12 16:40:361780 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061781 mock_input_api, mock_output_api)
1782 self.assertEqual(1, len(errors))
1783
1784 def testCppIncludeBlinkProducesError(self):
1785 mock_input_api = MockInputApi()
1786 mock_input_api.files = [
1787 MockAffectedFile('third_party/blink/test.cpp',
1788 ['#include "foo/file.cpp"']),
1789 ]
1790
1791 mock_output_api = MockOutputApi()
1792
Saagar Sanghavifceeaae2020-08-12 16:40:361793 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061794 mock_input_api, mock_output_api)
1795 self.assertEqual(1, len(errors))
1796
1797
Andrew Grieve1b290e4a22020-11-24 20:07:011798class GnGlobForwardTest(unittest.TestCase):
1799 def testAddBareGlobs(self):
1800 mock_input_api = MockInputApi()
1801 mock_input_api.files = [
1802 MockAffectedFile('base/stuff.gni', [
1803 'forward_variables_from(invoker, "*")']),
1804 MockAffectedFile('base/BUILD.gn', [
1805 'forward_variables_from(invoker, "*")']),
1806 ]
1807 warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
1808 self.assertEqual(1, len(warnings))
1809 msg = '\n'.join(warnings[0].items)
1810 self.assertIn('base/stuff.gni', msg)
1811 # Should not check .gn files. Local templates don't need to care about
1812 # visibility / testonly.
1813 self.assertNotIn('base/BUILD.gn', msg)
1814
1815 def testValidUses(self):
1816 mock_input_api = MockInputApi()
1817 mock_input_api.files = [
1818 MockAffectedFile('base/stuff.gni', [
1819 'forward_variables_from(invoker, "*", [])']),
1820 MockAffectedFile('base/stuff2.gni', [
1821 'forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)']),
1822 MockAffectedFile('base/stuff3.gni', [
1823 'forward_variables_from(invoker, [ "testonly" ])']),
1824 ]
1825 warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
1826 self.assertEqual([], warnings)
1827
1828
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191829class NewHeaderWithoutGnChangeTest(unittest.TestCase):
1830 def testAddHeaderWithoutGn(self):
1831 mock_input_api = MockInputApi()
1832 mock_input_api.files = [
1833 MockAffectedFile('base/stuff.h', ''),
1834 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361835 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191836 mock_input_api, MockOutputApi())
1837 self.assertEqual(1, len(warnings))
1838 self.assertTrue('base/stuff.h' in warnings[0].items)
1839
1840 def testModifyHeader(self):
1841 mock_input_api = MockInputApi()
1842 mock_input_api.files = [
1843 MockAffectedFile('base/stuff.h', '', action='M'),
1844 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361845 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191846 mock_input_api, MockOutputApi())
1847 self.assertEqual(0, len(warnings))
1848
1849 def testDeleteHeader(self):
1850 mock_input_api = MockInputApi()
1851 mock_input_api.files = [
1852 MockAffectedFile('base/stuff.h', '', action='D'),
1853 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361854 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191855 mock_input_api, MockOutputApi())
1856 self.assertEqual(0, len(warnings))
1857
1858 def testAddHeaderWithGn(self):
1859 mock_input_api = MockInputApi()
1860 mock_input_api.files = [
1861 MockAffectedFile('base/stuff.h', ''),
1862 MockAffectedFile('base/BUILD.gn', 'stuff.h'),
1863 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361864 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191865 mock_input_api, MockOutputApi())
1866 self.assertEqual(0, len(warnings))
1867
1868 def testAddHeaderWithGni(self):
1869 mock_input_api = MockInputApi()
1870 mock_input_api.files = [
1871 MockAffectedFile('base/stuff.h', ''),
1872 MockAffectedFile('base/files.gni', 'stuff.h'),
1873 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361874 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191875 mock_input_api, MockOutputApi())
1876 self.assertEqual(0, len(warnings))
1877
1878 def testAddHeaderWithOther(self):
1879 mock_input_api = MockInputApi()
1880 mock_input_api.files = [
1881 MockAffectedFile('base/stuff.h', ''),
1882 MockAffectedFile('base/stuff.cc', 'stuff.h'),
1883 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361884 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191885 mock_input_api, MockOutputApi())
1886 self.assertEqual(1, len(warnings))
1887
1888 def testAddHeaderWithWrongGn(self):
1889 mock_input_api = MockInputApi()
1890 mock_input_api.files = [
1891 MockAffectedFile('base/stuff.h', ''),
1892 MockAffectedFile('base/BUILD.gn', 'stuff_h'),
1893 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361894 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191895 mock_input_api, MockOutputApi())
1896 self.assertEqual(1, len(warnings))
1897
1898 def testAddHeadersWithGn(self):
1899 mock_input_api = MockInputApi()
1900 mock_input_api.files = [
1901 MockAffectedFile('base/stuff.h', ''),
1902 MockAffectedFile('base/another.h', ''),
1903 MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'),
1904 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361905 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191906 mock_input_api, MockOutputApi())
1907 self.assertEqual(0, len(warnings))
1908
1909 def testAddHeadersWithWrongGn(self):
1910 mock_input_api = MockInputApi()
1911 mock_input_api.files = [
1912 MockAffectedFile('base/stuff.h', ''),
1913 MockAffectedFile('base/another.h', ''),
1914 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'),
1915 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361916 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191917 mock_input_api, MockOutputApi())
1918 self.assertEqual(1, len(warnings))
1919 self.assertFalse('base/stuff.h' in warnings[0].items)
1920 self.assertTrue('base/another.h' in warnings[0].items)
1921
1922 def testAddHeadersWithWrongGn2(self):
1923 mock_input_api = MockInputApi()
1924 mock_input_api.files = [
1925 MockAffectedFile('base/stuff.h', ''),
1926 MockAffectedFile('base/another.h', ''),
1927 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'),
1928 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361929 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191930 mock_input_api, MockOutputApi())
1931 self.assertEqual(1, len(warnings))
1932 self.assertTrue('base/stuff.h' in warnings[0].items)
1933 self.assertTrue('base/another.h' in warnings[0].items)
1934
1935
Michael Giuffridad3bc8672018-10-25 22:48:021936class CorrectProductNameInMessagesTest(unittest.TestCase):
1937 def testProductNameInDesc(self):
1938 mock_input_api = MockInputApi()
1939 mock_input_api.files = [
1940 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1941 '<message name="Foo" desc="Welcome to Chrome">',
1942 ' Welcome to Chrome!',
1943 '</message>',
1944 ]),
1945 MockAffectedFile('chrome/app/chromium_strings.grd', [
1946 '<message name="Bar" desc="Welcome to Chrome">',
1947 ' Welcome to Chromium!',
1948 '</message>',
1949 ]),
1950 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361951 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021952 mock_input_api, MockOutputApi())
1953 self.assertEqual(0, len(warnings))
1954
1955 def testChromeInChromium(self):
1956 mock_input_api = MockInputApi()
1957 mock_input_api.files = [
1958 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1959 '<message name="Foo" desc="Welcome to Chrome">',
1960 ' Welcome to Chrome!',
1961 '</message>',
1962 ]),
1963 MockAffectedFile('chrome/app/chromium_strings.grd', [
1964 '<message name="Bar" desc="Welcome to Chrome">',
1965 ' Welcome to Chrome!',
1966 '</message>',
1967 ]),
1968 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361969 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021970 mock_input_api, MockOutputApi())
1971 self.assertEqual(1, len(warnings))
1972 self.assertTrue('chrome/app/chromium_strings.grd' in warnings[0].items[0])
1973
1974 def testChromiumInChrome(self):
1975 mock_input_api = MockInputApi()
1976 mock_input_api.files = [
1977 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1978 '<message name="Foo" desc="Welcome to Chrome">',
1979 ' Welcome to Chromium!',
1980 '</message>',
1981 ]),
1982 MockAffectedFile('chrome/app/chromium_strings.grd', [
1983 '<message name="Bar" desc="Welcome to Chrome">',
1984 ' Welcome to Chromium!',
1985 '</message>',
1986 ]),
1987 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361988 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021989 mock_input_api, MockOutputApi())
1990 self.assertEqual(1, len(warnings))
1991 self.assertTrue(
1992 'chrome/app/google_chrome_strings.grd:2' in warnings[0].items[0])
1993
1994 def testMultipleInstances(self):
1995 mock_input_api = MockInputApi()
1996 mock_input_api.files = [
1997 MockAffectedFile('chrome/app/chromium_strings.grd', [
1998 '<message name="Bar" desc="Welcome to Chrome">',
1999 ' Welcome to Chrome!',
2000 '</message>',
2001 '<message name="Baz" desc="A correct message">',
2002 ' Chromium is the software you are using.',
2003 '</message>',
2004 '<message name="Bat" desc="An incorrect message">',
2005 ' Google Chrome is the software you are using.',
2006 '</message>',
2007 ]),
2008 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362009 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022010 mock_input_api, MockOutputApi())
2011 self.assertEqual(1, len(warnings))
2012 self.assertTrue(
2013 'chrome/app/chromium_strings.grd:2' in warnings[0].items[0])
2014 self.assertTrue(
2015 'chrome/app/chromium_strings.grd:8' in warnings[0].items[1])
2016
2017 def testMultipleWarnings(self):
2018 mock_input_api = MockInputApi()
2019 mock_input_api.files = [
2020 MockAffectedFile('chrome/app/chromium_strings.grd', [
2021 '<message name="Bar" desc="Welcome to Chrome">',
2022 ' Welcome to Chrome!',
2023 '</message>',
2024 '<message name="Baz" desc="A correct message">',
2025 ' Chromium is the software you are using.',
2026 '</message>',
2027 '<message name="Bat" desc="An incorrect message">',
2028 ' Google Chrome is the software you are using.',
2029 '</message>',
2030 ]),
2031 MockAffectedFile('components/components_google_chrome_strings.grd', [
2032 '<message name="Bar" desc="Welcome to Chrome">',
2033 ' Welcome to Chrome!',
2034 '</message>',
2035 '<message name="Baz" desc="A correct message">',
2036 ' Chromium is the software you are using.',
2037 '</message>',
2038 '<message name="Bat" desc="An incorrect message">',
2039 ' Google Chrome is the software you are using.',
2040 '</message>',
2041 ]),
2042 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362043 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022044 mock_input_api, MockOutputApi())
2045 self.assertEqual(2, len(warnings))
2046 self.assertTrue(
2047 'components/components_google_chrome_strings.grd:5'
2048 in warnings[0].items[0])
2049 self.assertTrue(
2050 'chrome/app/chromium_strings.grd:2' in warnings[1].items[0])
2051 self.assertTrue(
2052 'chrome/app/chromium_strings.grd:8' in warnings[1].items[1])
2053
2054
Ken Rockot9f668262018-12-21 18:56:362055class ServiceManifestOwnerTest(unittest.TestCase):
Ken Rockot9f668262018-12-21 18:56:362056 def testServiceManifestChangeNeedsSecurityOwner(self):
2057 mock_input_api = MockInputApi()
2058 mock_input_api.files = [
2059 MockAffectedFile('services/goat/public/cpp/manifest.cc',
2060 [
2061 '#include "services/goat/public/cpp/manifest.h"',
2062 'const service_manager::Manifest& GetManifest() {}',
2063 ])]
2064 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362065 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362066 mock_input_api, mock_output_api)
2067 self.assertEqual(1, len(errors))
2068 self.assertEqual(
2069 'Found OWNERS files that need to be updated for IPC security review ' +
2070 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2071
2072 def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
2073 mock_input_api = MockInputApi()
2074 mock_input_api.files = [
2075 MockAffectedFile('some/non/service/thing/foo_manifest.cc',
2076 [
2077 'const char kNoEnforcement[] = "not a manifest!";',
2078 ])]
2079 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362080 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032081 mock_input_api, mock_output_api)
2082 self.assertEqual([], errors)
2083
2084
2085class FuchsiaSecurityOwnerTest(unittest.TestCase):
2086 def testFidlChangeNeedsSecurityOwner(self):
2087 mock_input_api = MockInputApi()
2088 mock_input_api.files = [
2089 MockAffectedFile('potentially/scary/ipc.fidl',
2090 [
2091 'library test.fidl'
2092 ])]
2093 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362094 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032095 mock_input_api, mock_output_api)
2096 self.assertEqual(1, len(errors))
2097 self.assertEqual(
2098 'Found OWNERS files that need to be updated for IPC security review ' +
2099 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2100
2101 def testComponentManifestV1ChangeNeedsSecurityOwner(self):
2102 mock_input_api = MockInputApi()
2103 mock_input_api.files = [
2104 MockAffectedFile('potentially/scary/v2_manifest.cmx',
2105 [
2106 '{ "that is no": "manifest!" }'
2107 ])]
2108 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362109 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032110 mock_input_api, mock_output_api)
2111 self.assertEqual(1, len(errors))
2112 self.assertEqual(
2113 'Found OWNERS files that need to be updated for IPC security review ' +
2114 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2115
2116 def testComponentManifestV2NeedsSecurityOwner(self):
2117 mock_input_api = MockInputApi()
2118 mock_input_api.files = [
2119 MockAffectedFile('potentially/scary/v2_manifest.cml',
2120 [
2121 '{ "that is no": "manifest!" }'
2122 ])]
2123 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362124 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032125 mock_input_api, mock_output_api)
2126 self.assertEqual(1, len(errors))
2127 self.assertEqual(
2128 'Found OWNERS files that need to be updated for IPC security review ' +
2129 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2130
Joshua Peraza1ca6d392020-12-08 00:14:092131 def testThirdPartyTestsDoNotRequireSecurityOwner(self):
2132 mock_input_api = MockInputApi()
2133 mock_input_api.files = [
2134 MockAffectedFile('third_party/crashpad/test/tests.cmx',
2135 [
2136 'const char kNoEnforcement[] = "Security?!? Pah!";',
2137 ])]
2138 mock_output_api = MockOutputApi()
2139 errors = PRESUBMIT.CheckSecurityOwners(
2140 mock_input_api, mock_output_api)
2141 self.assertEqual([], errors)
2142
Wez17c66962020-04-29 15:26:032143 def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2144 mock_input_api = MockInputApi()
2145 mock_input_api.files = [
2146 MockAffectedFile('some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',
2147 [
2148 'const char kNoEnforcement[] = "Security?!? Pah!";',
2149 ])]
2150 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362151 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362152 mock_input_api, mock_output_api)
2153 self.assertEqual([], errors)
2154
Daniel Cheng13ca61a882017-08-25 15:11:252155
Robert Sesek2c905332020-05-06 23:17:132156class SecurityChangeTest(unittest.TestCase):
Edward Lesmes1e9fade2021-02-08 20:31:122157 class _MockOwnersClient(object):
2158 def ListOwners(self, f):
Robert Sesek2c905332020-05-06 23:17:132159 return ['[email protected]', '[email protected]']
2160
2161 def _mockChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2162 def __MockOwnerAndReviewers(input_api, email_regexp, approval_needed=False):
2163 return [owner, reviewers]
2164 input_api.canned_checks.GetCodereviewOwnerAndReviewers = \
2165 __MockOwnerAndReviewers
2166
Alex Goughbc964dd2020-06-15 17:52:372167 def testDiffGetServiceSandboxType(self):
Robert Sesek2c905332020-05-06 23:17:132168 mock_input_api = MockInputApi()
2169 mock_input_api.files = [
2170 MockAffectedFile(
2171 'services/goat/teleporter_host.cc',
2172 [
Alex Goughbc964dd2020-06-15 17:52:372173 'template <>',
2174 'inline content::SandboxType',
2175 'content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {',
2176 '#if defined(OS_WIN)',
2177 ' return SandboxType::kGoaty;',
2178 '#else',
2179 ' return SandboxType::kNoSandbox;',
2180 '#endif // !defined(OS_WIN)',
2181 '}'
Robert Sesek2c905332020-05-06 23:17:132182 ]
2183 ),
2184 ]
2185 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2186 mock_input_api)
2187 self.assertEqual({
2188 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372189 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132190 ])},
2191 files_to_functions)
2192
2193 def testDiffRemovingLine(self):
2194 mock_input_api = MockInputApi()
2195 mock_file = MockAffectedFile('services/goat/teleporter_host.cc', '')
2196 mock_file._scm_diff = """--- old 2020-05-04 14:08:25.000000000 -0400
2197+++ new 2020-05-04 14:08:32.000000000 -0400
2198@@ -1,5 +1,4 @@
Alex Goughbc964dd2020-06-15 17:52:372199 template <>
2200 inline content::SandboxType
2201-content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {
2202 #if defined(OS_WIN)
2203 return SandboxType::kGoaty;
Robert Sesek2c905332020-05-06 23:17:132204"""
2205 mock_input_api.files = [mock_file]
2206 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2207 mock_input_api)
2208 self.assertEqual({
2209 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372210 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132211 ])},
2212 files_to_functions)
2213
2214 def testChangeOwnersMissing(self):
2215 mock_input_api = MockInputApi()
Edward Lesmes1e9fade2021-02-08 20:31:122216 mock_input_api.owners_client = self._MockOwnersClient()
Robert Sesek2c905332020-05-06 23:17:132217 mock_input_api.is_committing = False
2218 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372219 MockAffectedFile('file.cc', ['GetServiceSandboxType<Goat>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132220 ]
2221 mock_output_api = MockOutputApi()
2222 self._mockChangeOwnerAndReviewers(
2223 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362224 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592225 self.assertEqual(1, len(result))
2226 self.assertEqual(result[0].type, 'notify')
2227 self.assertEqual(result[0].message,
Robert Sesek2c905332020-05-06 23:17:132228 'The following files change calls to security-sensive functions\n' \
2229 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2230 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372231 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132232
2233 def testChangeOwnersMissingAtCommit(self):
2234 mock_input_api = MockInputApi()
Edward Lesmes1e9fade2021-02-08 20:31:122235 mock_input_api.owners_client = self._MockOwnersClient()
Robert Sesek2c905332020-05-06 23:17:132236 mock_input_api.is_committing = True
2237 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372238 MockAffectedFile('file.cc', ['GetServiceSandboxType<mojom::Goat>()'])
Robert Sesek2c905332020-05-06 23:17:132239 ]
2240 mock_output_api = MockOutputApi()
2241 self._mockChangeOwnerAndReviewers(
2242 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362243 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592244 self.assertEqual(1, len(result))
2245 self.assertEqual(result[0].type, 'error')
2246 self.assertEqual(result[0].message,
Robert Sesek2c905332020-05-06 23:17:132247 'The following files change calls to security-sensive functions\n' \
2248 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2249 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372250 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132251
2252 def testChangeOwnersPresent(self):
2253 mock_input_api = MockInputApi()
Edward Lesmes1e9fade2021-02-08 20:31:122254 mock_input_api.owners_client = self._MockOwnersClient()
Robert Sesek2c905332020-05-06 23:17:132255 mock_input_api.files = [
2256 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2257 ]
2258 mock_output_api = MockOutputApi()
2259 self._mockChangeOwnerAndReviewers(
2260 mock_input_api, '[email protected]',
2261 ['[email protected]', '[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362262 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592263 self.assertEqual(0, len(result))
Robert Sesek2c905332020-05-06 23:17:132264
2265 def testChangeOwnerIsSecurityOwner(self):
2266 mock_input_api = MockInputApi()
Edward Lesmes1e9fade2021-02-08 20:31:122267 mock_input_api.owners_client = self._MockOwnersClient()
Robert Sesek2c905332020-05-06 23:17:132268 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372269 MockAffectedFile('file.cc', ['GetServiceSandboxType<T>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132270 ]
2271 mock_output_api = MockOutputApi()
2272 self._mockChangeOwnerAndReviewers(
2273 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362274 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Dirk Prankee3c9c62d2021-05-18 18:35:592275 self.assertEqual(1, len(result))
Robert Sesek2c905332020-05-06 23:17:132276
2277
Mario Sanchez Prada2472cab2019-09-18 10:58:312278class BannedTypeCheckTest(unittest.TestCase):
Sylvain Defresnea8b73d252018-02-28 15:45:542279
Peter Kasting94a56c42019-10-25 21:54:042280 def testBannedCppFunctions(self):
2281 input_api = MockInputApi()
2282 input_api.files = [
2283 MockFile('some/cpp/problematic/file.cc',
2284 ['using namespace std;']),
Oksana Zhuravlovac8222d22019-12-19 19:21:162285 MockFile('third_party/blink/problematic/file.cc',
2286 ['GetInterfaceProvider()']),
Peter Kasting94a56c42019-10-25 21:54:042287 MockFile('some/cpp/ok/file.cc',
2288 ['using std::string;']),
Allen Bauer53b43fb12020-03-12 17:21:472289 MockFile('some/cpp/problematic/file2.cc',
2290 ['set_owned_by_client()']),
danakjd18e8892020-12-17 17:42:012291 MockFile('some/cpp/nocheck/file.cc',
2292 ['using namespace std; // nocheck']),
2293 MockFile('some/cpp/comment/file.cc',
2294 [' // A comment about `using namespace std;`']),
Peter Kasting94a56c42019-10-25 21:54:042295 ]
2296
Saagar Sanghavifceeaae2020-08-12 16:40:362297 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlovac8222d22019-12-19 19:21:162298
2299 # warnings are results[0], errors are results[1]
2300 self.assertEqual(2, len(results))
2301 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2302 self.assertTrue(
2303 'third_party/blink/problematic/file.cc' in results[0].message)
2304 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
Allen Bauer53b43fb12020-03-12 17:21:472305 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
danakjd18e8892020-12-17 17:42:012306 self.assertFalse('some/cpp/nocheck/file.cc' in results[0].message)
2307 self.assertFalse('some/cpp/nocheck/file.cc' in results[1].message)
2308 self.assertFalse('some/cpp/comment/file.cc' in results[0].message)
2309 self.assertFalse('some/cpp/comment/file.cc' in results[1].message)
Peter Kasting94a56c42019-10-25 21:54:042310
Peter K. Lee6c03ccff2019-07-15 14:40:052311 def testBannedIosObjcFunctions(self):
Sylvain Defresnea8b73d252018-02-28 15:45:542312 input_api = MockInputApi()
2313 input_api.files = [
2314 MockFile('some/ios/file.mm',
2315 ['TEST(SomeClassTest, SomeInteraction) {',
2316 '}']),
2317 MockFile('some/mac/file.mm',
2318 ['TEST(SomeClassTest, SomeInteraction) {',
2319 '}']),
2320 MockFile('another/ios_file.mm',
2321 ['class SomeTest : public testing::Test {};']),
Peter K. Lee6c03ccff2019-07-15 14:40:052322 MockFile('some/ios/file_egtest.mm',
2323 ['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
2324 MockFile('some/ios/file_unittest.mm',
2325 ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']),
Sylvain Defresnea8b73d252018-02-28 15:45:542326 ]
2327
Saagar Sanghavifceeaae2020-08-12 16:40:362328 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Sylvain Defresnea8b73d252018-02-28 15:45:542329 self.assertEqual(1, len(errors))
2330 self.assertTrue('some/ios/file.mm' in errors[0].message)
2331 self.assertTrue('another/ios_file.mm' in errors[0].message)
2332 self.assertTrue('some/mac/file.mm' not in errors[0].message)
Peter K. Lee6c03ccff2019-07-15 14:40:052333 self.assertTrue('some/ios/file_egtest.mm' in errors[0].message)
2334 self.assertTrue('some/ios/file_unittest.mm' not in errors[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542335
Carlos Knippschildab192b8c2019-04-08 20:02:382336 def testBannedMojoFunctions(self):
2337 input_api = MockInputApi()
2338 input_api.files = [
Oksana Zhuravlovafd247772019-05-16 16:57:292339 MockFile('some/cpp/problematic/file2.cc',
2340 ['mojo::ConvertTo<>']),
Oksana Zhuravlovafd247772019-05-16 16:57:292341 MockFile('third_party/blink/ok/file3.cc',
2342 ['mojo::ConvertTo<>']),
2343 MockFile('content/renderer/ok/file3.cc',
2344 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382345 ]
2346
Saagar Sanghavifceeaae2020-08-12 16:40:362347 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222348
2349 # warnings are results[0], errors are results[1]
Robert Sesek351d2d52021-02-02 01:47:072350 self.assertEqual(1, len(results))
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222351 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222352 self.assertTrue('third_party/blink/ok/file3.cc' not in results[0].message)
2353 self.assertTrue('content/renderer/ok/file3.cc' not in results[0].message)
Carlos Knippschildab192b8c2019-04-08 20:02:382354
Mario Sanchez Prada2472cab2019-09-18 10:58:312355 def testDeprecatedMojoTypes(self):
Mario Sanchez Pradacec9cef2019-12-15 11:54:572356 ok_paths = ['components/arc']
2357 warning_paths = ['some/cpp']
Mario Sanchez Pradaaab91382019-12-19 08:57:092358 error_paths = ['third_party/blink', 'content']
Mario Sanchez Prada2472cab2019-09-18 10:58:312359 test_cases = [
2360 {
Mario Sanchez Prada2472cab2019-09-18 10:58:312361 'type': 'mojo::AssociatedInterfacePtrInfo<>',
2362 'file': 'file4.cc'
2363 },
2364 {
2365 'type': 'mojo::AssociatedInterfaceRequest<>',
2366 'file': 'file5.cc'
2367 },
2368 {
Mario Sanchez Prada2472cab2019-09-18 10:58:312369 'type': 'mojo::InterfacePtr<>',
2370 'file': 'file8.cc'
2371 },
2372 {
2373 'type': 'mojo::InterfacePtrInfo<>',
2374 'file': 'file9.cc'
2375 },
2376 {
2377 'type': 'mojo::InterfaceRequest<>',
2378 'file': 'file10.cc'
2379 },
2380 {
2381 'type': 'mojo::MakeRequest()',
2382 'file': 'file11.cc'
2383 },
Mario Sanchez Prada2472cab2019-09-18 10:58:312384 ]
2385
2386 # Build the list of MockFiles considering paths that should trigger warnings
Mario Sanchez Pradacec9cef2019-12-15 11:54:572387 # as well as paths that should trigger errors.
Mario Sanchez Prada2472cab2019-09-18 10:58:312388 input_api = MockInputApi()
2389 input_api.files = []
2390 for test_case in test_cases:
2391 for path in ok_paths:
2392 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2393 [test_case['type']]))
2394 for path in warning_paths:
2395 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2396 [test_case['type']]))
Mario Sanchez Pradacec9cef2019-12-15 11:54:572397 for path in error_paths:
2398 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2399 [test_case['type']]))
Mario Sanchez Prada2472cab2019-09-18 10:58:312400
Saagar Sanghavifceeaae2020-08-12 16:40:362401 results = PRESUBMIT.CheckNoDeprecatedMojoTypes(input_api, MockOutputApi())
Mario Sanchez Prada2472cab2019-09-18 10:58:312402
Mario Sanchez Pradacec9cef2019-12-15 11:54:572403 # warnings are results[0], errors are results[1]
2404 self.assertEqual(2, len(results))
Mario Sanchez Prada2472cab2019-09-18 10:58:312405
2406 for test_case in test_cases:
Mario Sanchez Pradacec9cef2019-12-15 11:54:572407 # Check that no warnings nor errors have been triggered for these paths.
Mario Sanchez Prada2472cab2019-09-18 10:58:312408 for path in ok_paths:
2409 self.assertFalse(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572410 self.assertFalse(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312411
2412 # Check warnings have been triggered for these paths.
2413 for path in warning_paths:
2414 self.assertTrue(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572415 self.assertFalse(path in results[1].message)
2416
2417 # Check errors have been triggered for these paths.
2418 for path in error_paths:
2419 self.assertFalse(path in results[0].message)
2420 self.assertTrue(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312421
Sylvain Defresnea8b73d252018-02-28 15:45:542422
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272423class NoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:242424 def testTruePositives(self):
2425 mock_input_api = MockInputApi()
2426 mock_input_api.files = [
2427 MockFile('some/path/foo.cc', ['foo_for_testing();']),
2428 MockFile('some/path/foo.mm', ['FooForTesting();']),
2429 MockFile('some/path/foo.cxx', ['FooForTests();']),
2430 MockFile('some/path/foo.cpp', ['foo_for_test();']),
2431 ]
2432
Saagar Sanghavifceeaae2020-08-12 16:40:362433 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242434 mock_input_api, MockOutputApi())
2435 self.assertEqual(1, len(results))
2436 self.assertEqual(4, len(results[0].items))
2437 self.assertTrue('foo.cc' in results[0].items[0])
2438 self.assertTrue('foo.mm' in results[0].items[1])
2439 self.assertTrue('foo.cxx' in results[0].items[2])
2440 self.assertTrue('foo.cpp' in results[0].items[3])
2441
2442 def testFalsePositives(self):
2443 mock_input_api = MockInputApi()
2444 mock_input_api.files = [
2445 MockFile('some/path/foo.h', ['foo_for_testing();']),
2446 MockFile('some/path/foo.mm', ['FooForTesting() {']),
2447 MockFile('some/path/foo.cc', ['::FooForTests();']),
2448 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
2449 ]
2450
Saagar Sanghavifceeaae2020-08-12 16:40:362451 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242452 mock_input_api, MockOutputApi())
2453 self.assertEqual(0, len(results))
2454
James Cook1b4dc132021-03-09 22:45:132455 def testAllowedFiles(self):
2456 mock_input_api = MockInputApi()
2457 mock_input_api.files = [
2458 MockFile('path/foo_unittest.cc', ['foo_for_testing();']),
2459 MockFile('path/bar_unittest_mac.cc', ['foo_for_testing();']),
2460 MockFile('path/baz_unittests.cc', ['foo_for_testing();']),
2461 ]
2462
2463 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
2464 mock_input_api, MockOutputApi())
2465 self.assertEqual(0, len(results))
2466
Vaclav Brozekf01ed502018-03-16 19:38:242467
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272468class NoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:232469 def testTruePositives(self):
2470 mock_input_api = MockInputApi()
2471 mock_input_api.files = [
2472 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
2473 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392474 MockFile('dir/java/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232475 MockFile('dir/java/src/mult.java', [
2476 'int x = SomethingLongHere()',
2477 ' * SomethingLongHereForTesting();'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392478 ])
Vaclav Brozek7dbc28c2018-03-27 08:35:232479 ]
2480
Saagar Sanghavifceeaae2020-08-12 16:40:362481 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232482 mock_input_api, MockOutputApi())
2483 self.assertEqual(1, len(results))
2484 self.assertEqual(4, len(results[0].items))
2485 self.assertTrue('foo.java' in results[0].items[0])
2486 self.assertTrue('bar.java' in results[0].items[1])
2487 self.assertTrue('baz.java' in results[0].items[2])
2488 self.assertTrue('mult.java' in results[0].items[3])
2489
2490 def testFalsePositives(self):
2491 mock_input_api = MockInputApi()
2492 mock_input_api.files = [
2493 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
2494 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
2495 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
2496 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
Sky Malice9e6d6032020-10-15 22:49:552497 MockFile('dir/java/src/bar3.java', ['@VisibleForTesting']),
2498 MockFile('dir/java/src/bar4.java', ['@VisibleForTesting()']),
2499 MockFile('dir/java/src/bar5.java', [
2500 '@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)'
2501 ]),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392502 MockFile('dir/javatests/src/baz.java', ['FooForTest(', 'y', ');']),
2503 MockFile('dir/junit/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232504 MockFile('dir/junit/src/javadoc.java', [
2505 '/** Use FooForTest(); to obtain foo in tests.'
2506 ' */'
2507 ]),
2508 MockFile('dir/junit/src/javadoc2.java', [
2509 '/** ',
2510 ' * Use FooForTest(); to obtain foo in tests.'
2511 ' */'
2512 ]),
2513 ]
2514
Saagar Sanghavifceeaae2020-08-12 16:40:362515 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232516 mock_input_api, MockOutputApi())
2517 self.assertEqual(0, len(results))
2518
2519
Mohamed Heikald048240a2019-11-12 16:57:372520class NewImagesWarningTest(unittest.TestCase):
2521 def testTruePositives(self):
2522 mock_input_api = MockInputApi()
2523 mock_input_api.files = [
2524 MockFile('dir/android/res/drawable/foo.png', []),
2525 MockFile('dir/android/res/drawable-v21/bar.svg', []),
2526 MockFile('dir/android/res/mipmap-v21-en/baz.webp', []),
2527 MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png', []),
2528 ]
2529
2530 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2531 self.assertEqual(1, len(results))
2532 self.assertEqual(4, len(results[0].items))
2533 self.assertTrue('foo.png' in results[0].items[0].LocalPath())
2534 self.assertTrue('bar.svg' in results[0].items[1].LocalPath())
2535 self.assertTrue('baz.webp' in results[0].items[2].LocalPath())
2536 self.assertTrue('foobar.png' in results[0].items[3].LocalPath())
2537
2538 def testFalsePositives(self):
2539 mock_input_api = MockInputApi()
2540 mock_input_api.files = [
2541 MockFile('dir/pngs/README.md', []),
2542 MockFile('java/test/res/drawable/foo.png', []),
2543 MockFile('third_party/blink/foo.png', []),
2544 MockFile('dir/third_party/libpng/src/foo.cc', ['foobar']),
2545 MockFile('dir/resources.webp/.gitignore', ['foo.png']),
2546 ]
2547
2548 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2549 self.assertEqual(0, len(results))
2550
2551
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272552class CheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:052553 def testTruePositivesNullptr(self):
2554 mock_input_api = MockInputApi()
2555 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162556 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
2557 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
Vaclav Brozek851d9602018-04-04 16:13:052558 ]
2559
Saagar Sanghavifceeaae2020-08-12 16:40:362560 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052561 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162562 self.assertTrue('nullptr' in results[0].message)
Vaclav Brozek851d9602018-04-04 16:13:052563 self.assertEqual(2, len(results[0].items))
2564 self.assertTrue('baz.cc' in results[0].items[0])
2565 self.assertTrue('baz-p.cc' in results[0].items[1])
2566
2567 def testTruePositivesConstructor(self):
Vaclav Brozek52e18bf2018-04-03 07:05:242568 mock_input_api = MockInputApi()
2569 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162570 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
2571 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
2572 MockFile('dir/mult.cc', [
Vaclav Brozek95face62018-04-04 14:15:112573 'return',
2574 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
2575 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162576 MockFile('dir/mult2.cc', [
Vaclav Brozek95face62018-04-04 14:15:112577 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
2578 ' std::unique_ptr<T>(foo);'
2579 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162580 MockFile('dir/mult3.cc', [
Vaclav Brozek95face62018-04-04 14:15:112581 'bar = std::unique_ptr<T>(',
2582 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
2583 ]),
Vaclav Brozekb7fadb692018-08-30 06:39:532584 MockFile('dir/multi_arg.cc', [
2585 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']),
Vaclav Brozek52e18bf2018-04-03 07:05:242586 ]
2587
Saagar Sanghavifceeaae2020-08-12 16:40:362588 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052589 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162590 self.assertTrue('std::make_unique' in results[0].message)
Vaclav Brozekb7fadb692018-08-30 06:39:532591 self.assertEqual(6, len(results[0].items))
Vaclav Brozek851d9602018-04-04 16:13:052592 self.assertTrue('foo.cc' in results[0].items[0])
2593 self.assertTrue('bar.mm' in results[0].items[1])
2594 self.assertTrue('mult.cc' in results[0].items[2])
2595 self.assertTrue('mult2.cc' in results[0].items[3])
2596 self.assertTrue('mult3.cc' in results[0].items[4])
Vaclav Brozekb7fadb692018-08-30 06:39:532597 self.assertTrue('multi_arg.cc' in results[0].items[5])
Vaclav Brozek52e18bf2018-04-03 07:05:242598
2599 def testFalsePositives(self):
2600 mock_input_api = MockInputApi()
2601 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162602 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
2603 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
2604 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
2605 MockFile('dir/baz.cc', [
Vaclav Brozek52e18bf2018-04-03 07:05:242606 'std::unique_ptr<T> result = std::make_unique<T>();'
2607 ]),
Vaclav Brozeka54c528b2018-04-06 19:23:552608 MockFile('dir/baz2.cc', [
2609 'std::unique_ptr<T> result = std::make_unique<T>('
2610 ]),
2611 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
2612 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
Vaclav Brozekb7fadb692018-08-30 06:39:532613
2614 # Two-argument invocation of std::unique_ptr is exempt because there is
2615 # no equivalent using std::make_unique.
2616 MockFile('dir/multi_arg.cc', [
2617 'auto p = std::unique_ptr<T, D>(new T(), D());']),
Vaclav Brozek52e18bf2018-04-03 07:05:242618 ]
2619
Saagar Sanghavifceeaae2020-08-12 16:40:362620 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek52e18bf2018-04-03 07:05:242621 self.assertEqual(0, len(results))
2622
Danil Chapovalov3518f362018-08-11 16:13:432623class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
2624 def testBlocksDirectIncludes(self):
2625 mock_input_api = MockInputApi()
2626 mock_input_api.files = [
2627 MockFile('dir/foo_win.cc', ['#include "shlwapi.h"']),
2628 MockFile('dir/bar.h', ['#include <propvarutil.h>']),
2629 MockFile('dir/baz.h', ['#include <atlbase.h>']),
2630 MockFile('dir/jumbo.h', ['#include "sphelper.h"']),
2631 ]
2632 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:592633 self.assertEqual(1, len(results))
2634 self.assertEqual(4, len(results[0].items))
Danil Chapovalov3518f362018-08-11 16:13:432635 self.assertTrue('StrCat' in results[0].message)
2636 self.assertTrue('foo_win.cc' in results[0].items[0])
2637 self.assertTrue('bar.h' in results[0].items[1])
2638 self.assertTrue('baz.h' in results[0].items[2])
2639 self.assertTrue('jumbo.h' in results[0].items[3])
2640
2641 def testAllowsToIncludeWrapper(self):
2642 mock_input_api = MockInputApi()
2643 mock_input_api.files = [
2644 MockFile('dir/baz_win.cc', ['#include "base/win/shlwapi.h"']),
2645 MockFile('dir/baz-win.h', ['#include "base/win/atl.h"']),
2646 ]
2647 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:592648 self.assertEqual(0, len(results))
Danil Chapovalov3518f362018-08-11 16:13:432649
2650 def testAllowsToCreateWrapper(self):
2651 mock_input_api = MockInputApi()
2652 mock_input_api.files = [
2653 MockFile('base/win/shlwapi.h', [
2654 '#include <shlwapi.h>',
2655 '#include "base/win/windows_defines.inc"']),
2656 ]
2657 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
Dirk Prankee3c9c62d2021-05-18 18:35:592658 self.assertEqual(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:242659
Mustafa Emre Acer51f2f742020-03-09 19:41:122660
Rainhard Findlingfc31844c52020-05-15 09:58:262661class StringTest(unittest.TestCase):
2662 """Tests ICU syntax check and translation screenshots check."""
2663
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142664 # An empty grd file.
2665 OLD_GRD_CONTENTS = """<?xml version="1.0" encoding="UTF-8"?>
2666 <grit latest_public_release="1" current_release="1">
2667 <release seq="1">
2668 <messages></messages>
2669 </release>
2670 </grit>
2671 """.splitlines()
2672 # A grd file with a single message.
2673 NEW_GRD_CONTENTS1 = """<?xml version="1.0" encoding="UTF-8"?>
2674 <grit latest_public_release="1" current_release="1">
2675 <release seq="1">
2676 <messages>
2677 <message name="IDS_TEST1">
2678 Test string 1
2679 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482680 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE1"
2681 translateable="false">
2682 Non translateable message 1, should be ignored
2683 </message>
Mustafa Emre Acered1a48962020-06-30 19:15:392684 <message name="IDS_TEST_STRING_ACCESSIBILITY"
Mustafa Emre Acerd3ca8be2020-07-07 22:35:342685 is_accessibility_with_no_ui="true">
Mustafa Emre Acered1a48962020-06-30 19:15:392686 Accessibility label 1, should be ignored
2687 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142688 </messages>
2689 </release>
2690 </grit>
2691 """.splitlines()
2692 # A grd file with two messages.
2693 NEW_GRD_CONTENTS2 = """<?xml version="1.0" encoding="UTF-8"?>
2694 <grit latest_public_release="1" current_release="1">
2695 <release seq="1">
2696 <messages>
2697 <message name="IDS_TEST1">
2698 Test string 1
2699 </message>
2700 <message name="IDS_TEST2">
2701 Test string 2
2702 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482703 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE2"
2704 translateable="false">
2705 Non translateable message 2, should be ignored
2706 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142707 </messages>
2708 </release>
2709 </grit>
2710 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:262711 # A grd file with one ICU syntax message without syntax errors.
2712 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1 = """<?xml version="1.0" encoding="UTF-8"?>
2713 <grit latest_public_release="1" current_release="1">
2714 <release seq="1">
2715 <messages>
2716 <message name="IDS_TEST1">
2717 {NUM, plural,
2718 =1 {Test text for numeric one}
2719 other {Test text for plural with {NUM} as number}}
2720 </message>
2721 </messages>
2722 </release>
2723 </grit>
2724 """.splitlines()
2725 # A grd file with one ICU syntax message without syntax errors.
2726 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2 = """<?xml version="1.0" encoding="UTF-8"?>
2727 <grit latest_public_release="1" current_release="1">
2728 <release seq="1">
2729 <messages>
2730 <message name="IDS_TEST1">
2731 {NUM, plural,
2732 =1 {Different test text for numeric one}
2733 other {Different test text for plural with {NUM} as number}}
2734 </message>
2735 </messages>
2736 </release>
2737 </grit>
2738 """.splitlines()
2739 # A grd file with one ICU syntax message with syntax errors (misses a comma).
2740 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
2741 <grit latest_public_release="1" current_release="1">
2742 <release seq="1">
2743 <messages>
2744 <message name="IDS_TEST1">
2745 {NUM, plural
2746 =1 {Test text for numeric one}
2747 other {Test text for plural with {NUM} as number}}
2748 </message>
2749 </messages>
2750 </release>
2751 </grit>
2752 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142753
meacerff8a9b62019-12-10 19:43:582754 OLD_GRDP_CONTENTS = (
2755 '<?xml version="1.0" encoding="utf-8"?>',
2756 '<grit-part>',
2757 '</grit-part>'
2758 )
2759
2760 NEW_GRDP_CONTENTS1 = (
2761 '<?xml version="1.0" encoding="utf-8"?>',
2762 '<grit-part>',
2763 '<message name="IDS_PART_TEST1">',
2764 'Part string 1',
2765 '</message>',
2766 '</grit-part>')
2767
2768 NEW_GRDP_CONTENTS2 = (
2769 '<?xml version="1.0" encoding="utf-8"?>',
2770 '<grit-part>',
2771 '<message name="IDS_PART_TEST1">',
2772 'Part string 1',
2773 '</message>',
2774 '<message name="IDS_PART_TEST2">',
2775 'Part string 2',
2776 '</message>',
2777 '</grit-part>')
2778
Rainhard Findlingd8d04372020-08-13 13:30:092779 NEW_GRDP_CONTENTS3 = (
2780 '<?xml version="1.0" encoding="utf-8"?>',
2781 '<grit-part>',
2782 '<message name="IDS_PART_TEST1" desc="Description with typo.">',
2783 'Part string 1',
2784 '</message>',
2785 '</grit-part>')
2786
2787 NEW_GRDP_CONTENTS4 = (
2788 '<?xml version="1.0" encoding="utf-8"?>',
2789 '<grit-part>',
2790 '<message name="IDS_PART_TEST1" desc="Description with typo fixed.">',
2791 'Part string 1',
2792 '</message>',
2793 '</grit-part>')
2794
Rainhard Findling1a3e71e2020-09-21 07:33:352795 NEW_GRDP_CONTENTS5 = (
2796 '<?xml version="1.0" encoding="utf-8"?>',
2797 '<grit-part>',
2798 '<message name="IDS_PART_TEST1" meaning="Meaning with typo.">',
2799 'Part string 1',
2800 '</message>',
2801 '</grit-part>')
2802
2803 NEW_GRDP_CONTENTS6 = (
2804 '<?xml version="1.0" encoding="utf-8"?>',
2805 '<grit-part>',
2806 '<message name="IDS_PART_TEST1" meaning="Meaning with typo fixed.">',
2807 'Part string 1',
2808 '</message>',
2809 '</grit-part>')
2810
Rainhard Findlingfc31844c52020-05-15 09:58:262811 # A grdp file with one ICU syntax message without syntax errors.
2812 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = (
2813 '<?xml version="1.0" encoding="utf-8"?>',
2814 '<grit-part>',
2815 '<message name="IDS_PART_TEST1">',
2816 '{NUM, plural,',
2817 '=1 {Test text for numeric one}',
2818 'other {Test text for plural with {NUM} as number}}',
2819 '</message>',
2820 '</grit-part>')
2821 # A grdp file with one ICU syntax message without syntax errors.
2822 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2 = (
2823 '<?xml version="1.0" encoding="utf-8"?>',
2824 '<grit-part>',
2825 '<message name="IDS_PART_TEST1">',
2826 '{NUM, plural,',
2827 '=1 {Different test text for numeric one}',
2828 'other {Different test text for plural with {NUM} as number}}',
2829 '</message>',
2830 '</grit-part>')
2831
2832 # A grdp file with one ICU syntax message with syntax errors (superfluent
2833 # whitespace).
2834 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR = (
2835 '<?xml version="1.0" encoding="utf-8"?>',
2836 '<grit-part>',
2837 '<message name="IDS_PART_TEST1">',
2838 '{NUM, plural,',
2839 '= 1 {Test text for numeric one}',
2840 'other {Test text for plural with {NUM} as number}}',
2841 '</message>',
2842 '</grit-part>')
2843
Mustafa Emre Acerc8a012d2018-07-31 00:00:392844 DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
2845 'changelist. Run '
2846 'tools/translate/upload_screenshots.py to '
2847 'upload them instead:')
2848 GENERATE_SIGNATURES_MESSAGE = ('You are adding or modifying UI strings.\n'
2849 'To ensure the best translations, take '
2850 'screenshots of the relevant UI '
2851 '(https://g.co/chrome/translation) and add '
2852 'these files to your changelist:')
2853 REMOVE_SIGNATURES_MESSAGE = ('You removed strings associated with these '
2854 'files. Remove:')
Rainhard Findlingfc31844c52020-05-15 09:58:262855 ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
2856 'strings (problems or feedback? Contact '
2857 '[email protected]):')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142858
2859 def makeInputApi(self, files):
2860 input_api = MockInputApi()
2861 input_api.files = files
meacere7be7532019-10-02 17:41:032862 # Override os_path.exists because the presubmit uses the actual
2863 # os.path.exists.
2864 input_api.CreateMockFileInPath(
2865 [x.LocalPath() for x in input_api.AffectedFiles(include_deletes=True)])
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142866 return input_api
2867
meacerff8a9b62019-12-10 19:43:582868 """ CL modified and added messages, but didn't add any screenshots."""
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142869 def testNoScreenshots(self):
meacerff8a9b62019-12-10 19:43:582870 # No new strings (file contents same). Should not warn.
2871 input_api = self.makeInputApi([
2872 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
2873 self.NEW_GRD_CONTENTS1, action='M'),
2874 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1,
2875 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362876 warnings = PRESUBMIT.CheckStrings(input_api,
meacerff8a9b62019-12-10 19:43:582877 MockOutputApi())
2878 self.assertEqual(0, len(warnings))
2879
2880 # Add two new strings. Should have two warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142881 input_api = self.makeInputApi([
2882 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582883 self.NEW_GRD_CONTENTS1, action='M'),
2884 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2885 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362886 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142887 MockOutputApi())
2888 self.assertEqual(1, len(warnings))
2889 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerc6ed2682020-07-07 07:24:002890 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012891 self.assertEqual([
meacerff8a9b62019-12-10 19:43:582892 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2893 os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
2894 warnings[0].items)
Mustafa Emre Acer36eaad52019-11-12 23:03:342895
meacerff8a9b62019-12-10 19:43:582896 # Add four new strings. Should have four warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:212897 input_api = self.makeInputApi([
2898 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582899 self.OLD_GRD_CONTENTS, action='M'),
2900 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2901 self.OLD_GRDP_CONTENTS, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362902 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:212903 MockOutputApi())
2904 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:002905 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:212906 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:582907 self.assertEqual([
2908 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2909 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2910 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
2911 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
2912 ], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:212913
Rainhard Findlingd8d04372020-08-13 13:30:092914 def testModifiedMessageDescription(self):
2915 # CL modified a message description for a message that does not yet have a
Rainhard Findling1a3e71e2020-09-21 07:33:352916 # screenshot. Should not warn.
Rainhard Findlingd8d04372020-08-13 13:30:092917 input_api = self.makeInputApi([
2918 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
2919 self.NEW_GRDP_CONTENTS4, action='M')])
2920 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findling1a3e71e2020-09-21 07:33:352921 self.assertEqual(0, len(warnings))
Rainhard Findlingd8d04372020-08-13 13:30:092922
2923 # CL modified a message description for a message that already has a
2924 # screenshot. Should not warn.
2925 input_api = self.makeInputApi([
2926 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
2927 self.NEW_GRDP_CONTENTS4, action='M'),
2928 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2929 'binary', action='A')])
2930 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
2931 self.assertEqual(0, len(warnings))
2932
Rainhard Findling1a3e71e2020-09-21 07:33:352933 def testModifiedMessageMeaning(self):
2934 # CL modified a message meaning for a message that does not yet have a
2935 # screenshot. Should warn.
2936 input_api = self.makeInputApi([
2937 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
2938 self.NEW_GRDP_CONTENTS6, action='M')])
2939 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
2940 self.assertEqual(1, len(warnings))
2941
2942 # CL modified a message meaning for a message that already has a
2943 # screenshot. Should not warn.
2944 input_api = self.makeInputApi([
2945 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
2946 self.NEW_GRDP_CONTENTS6, action='M'),
2947 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2948 'binary', action='A')])
2949 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
2950 self.assertEqual(0, len(warnings))
2951
meacerff8a9b62019-12-10 19:43:582952 def testPngAddedSha1NotAdded(self):
2953 # CL added one new message in a grd file and added the png file associated
2954 # with it, but did not add the corresponding sha1 file. This should warn
2955 # twice:
2956 # - Once for the added png file (because we don't want developers to upload
2957 # actual images)
2958 # - Once for the missing .sha1 file
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142959 input_api = self.makeInputApi([
Mustafa Emre Acerea3e57a2018-12-17 23:51:012960 MockAffectedFile(
2961 'test.grd',
2962 self.NEW_GRD_CONTENTS1,
2963 self.OLD_GRD_CONTENTS,
2964 action='M'),
2965 MockAffectedFile(
2966 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
2967 ])
Saagar Sanghavifceeaae2020-08-12 16:40:362968 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142969 MockOutputApi())
2970 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:002971 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142972 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012973 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
2974 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:002975 self.assertEqual('error', warnings[1].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142976 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012977 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
2978 warnings[1].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142979
meacerff8a9b62019-12-10 19:43:582980 # CL added two messages (one in grd, one in grdp) and added the png files
2981 # associated with the messages, but did not add the corresponding sha1
2982 # files. This should warn twice:
2983 # - Once for the added png files (because we don't want developers to upload
2984 # actual images)
2985 # - Once for the missing .sha1 files
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142986 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:582987 # Modified files:
Mustafa Emre Acer36eaad52019-11-12 23:03:342988 MockAffectedFile(
2989 'test.grd',
meacerff8a9b62019-12-10 19:43:582990 self.NEW_GRD_CONTENTS1,
Mustafa Emre Acer36eaad52019-11-12 23:03:342991 self.OLD_GRD_CONTENTS,
meacer2308d0742019-11-12 18:15:422992 action='M'),
Mustafa Emre Acer12e7fee2019-11-18 18:49:552993 MockAffectedFile(
meacerff8a9b62019-12-10 19:43:582994 'part.grdp',
2995 self.NEW_GRDP_CONTENTS1,
2996 self.OLD_GRDP_CONTENTS,
2997 action='M'),
2998 # Added files:
2999 MockAffectedFile(
3000 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A'),
3001 MockAffectedFile(
3002 os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary',
3003 action='A')
Mustafa Emre Acerad8fb082019-11-19 04:24:213004 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363005 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213006 MockOutputApi())
3007 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003008 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213009 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583010 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png'),
3011 os.path.join('test_grd', 'IDS_TEST1.png')],
Mustafa Emre Acerad8fb082019-11-19 04:24:213012 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003013 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213014 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
meacerff8a9b62019-12-10 19:43:583015 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3016 os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3017 warnings[1].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213018
3019 def testScreenshotsWithSha1(self):
meacerff8a9b62019-12-10 19:43:583020 # CL added four messages (two each in a grd and grdp) and their
3021 # corresponding .sha1 files. No warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213022 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583023 # Modified files:
Mustafa Emre Acerad8fb082019-11-19 04:24:213024 MockAffectedFile(
3025 'test.grd',
3026 self.NEW_GRD_CONTENTS2,
3027 self.OLD_GRD_CONTENTS,
Mustafa Emre Acer12e7fee2019-11-18 18:49:553028 action='M'),
meacerff8a9b62019-12-10 19:43:583029 MockAffectedFile(
3030 'part.grdp',
3031 self.NEW_GRDP_CONTENTS2,
3032 self.OLD_GRDP_CONTENTS,
3033 action='M'),
3034 # Added files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013035 MockFile(
3036 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3037 'binary',
3038 action='A'),
3039 MockFile(
3040 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3041 'binary',
meacerff8a9b62019-12-10 19:43:583042 action='A'),
3043 MockFile(
3044 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3045 'binary',
3046 action='A'),
3047 MockFile(
3048 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3049 'binary',
3050 action='A'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013051 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363052 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143053 MockOutputApi())
3054 self.assertEqual([], warnings)
3055
3056 def testScreenshotsRemovedWithSha1(self):
meacerff8a9b62019-12-10 19:43:583057 # Replace new contents with old contents in grd and grp files, removing
3058 # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3059 # Should warn to remove the sha1 files associated with these strings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143060 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583061 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013062 MockAffectedFile(
3063 'test.grd',
meacerff8a9b62019-12-10 19:43:583064 self.OLD_GRD_CONTENTS, # new_contents
3065 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013066 action='M'),
meacerff8a9b62019-12-10 19:43:583067 MockAffectedFile(
3068 'part.grdp',
3069 self.OLD_GRDP_CONTENTS, # new_contents
3070 self.NEW_GRDP_CONTENTS2, # old_contents
3071 action='M'),
3072 # Unmodified files:
3073 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
3074 MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', ''),
3075 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3076 'binary', ''),
3077 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3078 'binary', '')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013079 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363080 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143081 MockOutputApi())
3082 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003083 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143084 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013085 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583086 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3087 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013088 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3089 os.path.join('test_grd', 'IDS_TEST2.png.sha1')
3090 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143091
meacerff8a9b62019-12-10 19:43:583092 # Same as above, but this time one of the .sha1 files is also removed.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143093 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583094 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013095 MockAffectedFile(
3096 'test.grd',
meacerff8a9b62019-12-10 19:43:583097 self.OLD_GRD_CONTENTS, # new_contents
3098 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013099 action='M'),
meacerff8a9b62019-12-10 19:43:583100 MockAffectedFile(
3101 'part.grdp',
3102 self.OLD_GRDP_CONTENTS, # new_contents
3103 self.NEW_GRDP_CONTENTS2, # old_contents
3104 action='M'),
3105 # Unmodified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013106 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
meacerff8a9b62019-12-10 19:43:583107 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3108 'binary', ''),
3109 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013110 MockAffectedFile(
3111 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3112 '',
3113 'old_contents',
meacerff8a9b62019-12-10 19:43:583114 action='D'),
3115 MockAffectedFile(
3116 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3117 '',
3118 'old_contents',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013119 action='D')
3120 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363121 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143122 MockOutputApi())
3123 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003124 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143125 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583126 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3127 os.path.join('test_grd', 'IDS_TEST1.png.sha1')
3128 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143129
meacerff8a9b62019-12-10 19:43:583130 # Remove all sha1 files. There should be no warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143131 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583132 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013133 MockAffectedFile(
3134 'test.grd',
3135 self.OLD_GRD_CONTENTS,
3136 self.NEW_GRD_CONTENTS2,
3137 action='M'),
meacerff8a9b62019-12-10 19:43:583138 MockAffectedFile(
3139 'part.grdp',
3140 self.OLD_GRDP_CONTENTS,
3141 self.NEW_GRDP_CONTENTS2,
3142 action='M'),
3143 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013144 MockFile(
3145 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3146 'binary',
3147 action='D'),
3148 MockFile(
3149 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3150 'binary',
meacerff8a9b62019-12-10 19:43:583151 action='D'),
3152 MockFile(
3153 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3154 'binary',
3155 action='D'),
3156 MockFile(
3157 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3158 'binary',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013159 action='D')
3160 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363161 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143162 MockOutputApi())
3163 self.assertEqual([], warnings)
3164
Rainhard Findlingfc31844c52020-05-15 09:58:263165 def testIcuSyntax(self):
3166 # Add valid ICU syntax string. Should not raise an error.
3167 input_api = self.makeInputApi([
3168 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3169 self.NEW_GRD_CONTENTS1, action='M'),
3170 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3171 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363172 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263173 # We expect no ICU syntax errors.
3174 icu_errors = [e for e in results
3175 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3176 self.assertEqual(0, len(icu_errors))
3177
3178 # Valid changes in ICU syntax. Should not raise an error.
3179 input_api = self.makeInputApi([
3180 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3181 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3182 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3183 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363184 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263185 # We expect no ICU syntax errors.
3186 icu_errors = [e for e in results
3187 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3188 self.assertEqual(0, len(icu_errors))
3189
3190 # Add invalid ICU syntax strings. Should raise two errors.
3191 input_api = self.makeInputApi([
3192 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3193 self.NEW_GRD_CONTENTS1, action='M'),
3194 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3195 self.NEW_GRD_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363196 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263197 # We expect 2 ICU syntax errors.
3198 icu_errors = [e for e in results
3199 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3200 self.assertEqual(1, len(icu_errors))
3201 self.assertEqual([
3202 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3203 'ICU syntax.',
3204 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3205 ], icu_errors[0].items)
3206
3207 # Change two strings to have ICU syntax errors. Should raise two errors.
3208 input_api = self.makeInputApi([
3209 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3210 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3211 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3212 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363213 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263214 # We expect 2 ICU syntax errors.
3215 icu_errors = [e for e in results
3216 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3217 self.assertEqual(1, len(icu_errors))
3218 self.assertEqual([
3219 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3220 'ICU syntax.',
3221 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3222 ], icu_errors[0].items)
3223
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143224
Mustafa Emre Acer51f2f742020-03-09 19:41:123225class TranslationExpectationsTest(unittest.TestCase):
3226 ERROR_MESSAGE_FORMAT = (
3227 "Failed to get a list of translatable grd files. "
3228 "This happens when:\n"
3229 " - One of the modified grd or grdp files cannot be parsed or\n"
3230 " - %s is not updated.\n"
3231 "Stack:\n"
3232 )
3233 REPO_ROOT = os.path.join('tools', 'translation', 'testdata')
3234 # This lists all .grd files under REPO_ROOT.
3235 EXPECTATIONS = os.path.join(REPO_ROOT,
3236 "translation_expectations.pyl")
3237 # This lists all .grd files under REPO_ROOT except unlisted.grd.
3238 EXPECTATIONS_WITHOUT_UNLISTED_FILE = os.path.join(
3239 REPO_ROOT, "translation_expectations_without_unlisted_file.pyl")
3240
3241 # Tests that the presubmit doesn't return when no grd or grdp files are
3242 # modified.
3243 def testExpectationsNoModifiedGrd(self):
3244 input_api = MockInputApi()
3245 input_api.files = [
3246 MockAffectedFile('not_used.txt', 'not used', 'not used', action='M')
3247 ]
3248 # Fake list of all grd files in the repo. This list is missing all grd/grdps
3249 # under tools/translation/testdata. This is OK because the presubmit won't
3250 # run in the first place since there are no modified grd/grps in input_api.
3251 grd_files = ['doesnt_exist_doesnt_matter.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363252 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123253 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3254 grd_files)
3255 self.assertEqual(0, len(warnings))
3256
3257
3258 # Tests that the list of files passed to the presubmit matches the list of
3259 # files in the expectations.
3260 def testExpectationsSuccess(self):
3261 # Mock input file list needs a grd or grdp file in order to run the
3262 # presubmit. The file itself doesn't matter.
3263 input_api = MockInputApi()
3264 input_api.files = [
3265 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3266 ]
3267 # List of all grd files in the repo.
3268 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3269 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363270 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123271 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3272 grd_files)
3273 self.assertEqual(0, len(warnings))
3274
3275 # Tests that the presubmit warns when a file is listed in expectations, but
3276 # does not actually exist.
3277 def testExpectationsMissingFile(self):
3278 # Mock input file list needs a grd or grdp file in order to run the
3279 # presubmit.
3280 input_api = MockInputApi()
3281 input_api.files = [
3282 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3283 ]
3284 # unlisted.grd is listed under tools/translation/testdata but is not
3285 # included in translation expectations.
3286 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363287 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123288 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3289 grd_files)
3290 self.assertEqual(1, len(warnings))
3291 self.assertTrue(warnings[0].message.startswith(
3292 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS))
3293 self.assertTrue(
3294 ("test.grd is listed in the translation expectations, "
3295 "but this grd file does not exist")
3296 in warnings[0].message)
3297
3298 # Tests that the presubmit warns when a file is not listed in expectations but
3299 # does actually exist.
3300 def testExpectationsUnlistedFile(self):
3301 # Mock input file list needs a grd or grdp file in order to run the
3302 # presubmit.
3303 input_api = MockInputApi()
3304 input_api.files = [
3305 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3306 ]
3307 # unlisted.grd is listed under tools/translation/testdata but is not
3308 # included in translation expectations.
3309 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3310 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363311 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123312 input_api, MockOutputApi(), self.REPO_ROOT,
3313 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3314 self.assertEqual(1, len(warnings))
3315 self.assertTrue(warnings[0].message.startswith(
3316 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3317 self.assertTrue(
3318 ("unlisted.grd appears to be translatable "
3319 "(because it contains <file> or <message> elements), "
3320 "but is not listed in the translation expectations.")
3321 in warnings[0].message)
3322
3323 # Tests that the presubmit warns twice:
3324 # - for a non-existing file listed in expectations
3325 # - for an existing file not listed in expectations
3326 def testMultipleWarnings(self):
3327 # Mock input file list needs a grd or grdp file in order to run the
3328 # presubmit.
3329 input_api = MockInputApi()
3330 input_api.files = [
3331 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3332 ]
3333 # unlisted.grd is listed under tools/translation/testdata but is not
3334 # included in translation expectations.
3335 # test.grd is not listed under tools/translation/testdata but is included
3336 # in translation expectations.
3337 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363338 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123339 input_api, MockOutputApi(), self.REPO_ROOT,
3340 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3341 self.assertEqual(1, len(warnings))
3342 self.assertTrue(warnings[0].message.startswith(
3343 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3344 self.assertTrue(
3345 ("unlisted.grd appears to be translatable "
3346 "(because it contains <file> or <message> elements), "
3347 "but is not listed in the translation expectations.")
3348 in warnings[0].message)
3349 self.assertTrue(
3350 ("test.grd is listed in the translation expectations, "
3351 "but this grd file does not exist")
3352 in warnings[0].message)
3353
3354
Dominic Battre033531052018-09-24 15:45:343355class DISABLETypoInTest(unittest.TestCase):
3356
3357 def testPositive(self):
3358 # Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
3359 # where the desire is to disable a test.
3360 tests = [
3361 # Disabled on one platform:
3362 '#if defined(OS_WIN)\n'
3363 '#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
3364 '#else\n'
3365 '#define MAYBE_FoobarTest FoobarTest\n'
3366 '#endif\n',
3367 # Disabled on one platform spread cross lines:
3368 '#if defined(OS_WIN)\n'
3369 '#define MAYBE_FoobarTest \\\n'
3370 ' DISABLE_FoobarTest\n'
3371 '#else\n'
3372 '#define MAYBE_FoobarTest FoobarTest\n'
3373 '#endif\n',
3374 # Disabled on all platforms:
3375 ' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
3376 # Disabled on all platforms but multiple lines
3377 ' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
3378 ]
3379
3380 for test in tests:
3381 mock_input_api = MockInputApi()
3382 mock_input_api.files = [
3383 MockFile('some/path/foo_unittest.cc', test.splitlines()),
3384 ]
3385
Saagar Sanghavifceeaae2020-08-12 16:40:363386 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343387 MockOutputApi())
3388 self.assertEqual(
3389 1,
3390 len(results),
3391 msg=('expected len(results) == 1 but got %d in test: %s' %
3392 (len(results), test)))
3393 self.assertTrue(
3394 'foo_unittest.cc' in results[0].message,
3395 msg=('expected foo_unittest.cc in message but got %s in test %s' %
3396 (results[0].message, test)))
3397
3398 def testIngoreNotTestFiles(self):
3399 mock_input_api = MockInputApi()
3400 mock_input_api.files = [
3401 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'),
3402 ]
3403
Saagar Sanghavifceeaae2020-08-12 16:40:363404 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343405 MockOutputApi())
3406 self.assertEqual(0, len(results))
3407
Katie Df13948e2018-09-25 07:33:443408 def testIngoreDeletedFiles(self):
3409 mock_input_api = MockInputApi()
3410 mock_input_api.files = [
3411 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'),
3412 ]
3413
Saagar Sanghavifceeaae2020-08-12 16:40:363414 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Katie Df13948e2018-09-25 07:33:443415 MockOutputApi())
3416 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:343417
Nina Satragnof7660532021-09-20 18:03:353418class ForgettingMAYBEInTests(unittest.TestCase):
3419 def testPositive(self):
3420 test = (
3421 '#if defined(HAS_ENERGY)\n'
3422 '#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
3423 '#else\n'
3424 '#define MAYBE_CastExplosion CastExplosion\n'
3425 '#endif\n'
3426 'TEST_F(ArchWizard, CastExplosion) {\n'
3427 '#if defined(ARCH_PRIEST_IN_PARTY)\n'
3428 '#define MAYBE_ArchPriest ArchPriest\n'
3429 '#else\n'
3430 '#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
3431 '#endif\n'
3432 'TEST_F(ArchPriest, CastNaturesBounty) {\n'
3433 '#if !defined(CRUSADER_IN_PARTY)\n'
3434 '#define MAYBE_Crusader \\\n'
3435 ' DISABLED_Crusader \n'
3436 '#else\n'
3437 '#define MAYBE_Crusader \\\n'
3438 ' Crusader\n'
3439 '#endif\n'
3440 ' TEST_F(\n'
3441 ' Crusader,\n'
3442 ' CastTaunt) { }\n'
3443 '#if defined(LEARNED_BASIC_SKILLS)\n'
3444 '#define MAYBE_CastSteal \\\n'
3445 ' DISABLED_CastSteal \n'
3446 '#else\n'
3447 '#define MAYBE_CastSteal \\\n'
3448 ' CastSteal\n'
3449 '#endif\n'
3450 ' TEST_F(\n'
3451 ' ThiefClass,\n'
3452 ' CastSteal) { }\n'
3453 )
3454 mock_input_api = MockInputApi()
3455 mock_input_api.files = [
3456 MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
3457 ]
3458 results = PRESUBMIT.CheckForgettingMAYBEInTests(mock_input_api,
3459 MockOutputApi())
3460 self.assertEqual(4, len(results))
3461 self.assertTrue('CastExplosion' in results[0].message)
3462 self.assertTrue('fantasyworld/classes_unittest.cc:2' in results[0].message)
3463 self.assertTrue('ArchPriest' in results[1].message)
3464 self.assertTrue('fantasyworld/classes_unittest.cc:8' in results[1].message)
3465 self.assertTrue('Crusader' in results[2].message)
3466 self.assertTrue('fantasyworld/classes_unittest.cc:14' in results[2].message)
3467 self.assertTrue('CastSteal' in results[3].message)
3468 self.assertTrue('fantasyworld/classes_unittest.cc:24' in results[3].message)
3469
3470 def testNegative(self):
3471 test = (
3472 '#if defined(HAS_ENERGY)\n'
3473 '#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
3474 '#else\n'
3475 '#define MAYBE_CastExplosion CastExplosion\n'
3476 '#endif\n'
3477 'TEST_F(ArchWizard, MAYBE_CastExplosion) {\n'
3478 '#if defined(ARCH_PRIEST_IN_PARTY)\n'
3479 '#define MAYBE_ArchPriest ArchPriest\n'
3480 '#else\n'
3481 '#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
3482 '#endif\n'
3483 'TEST_F(MAYBE_ArchPriest, CastNaturesBounty) {\n'
3484 '#if !defined(CRUSADER_IN_PARTY)\n'
3485 '#define MAYBE_Crusader \\\n'
3486 ' DISABLED_Crusader \n'
3487 '#else\n'
3488 '#define MAYBE_Crusader \\\n'
3489 ' Crusader\n'
3490 '#endif\n'
3491 ' TEST_F(\n'
3492 ' MAYBE_Crusader,\n'
3493 ' CastTaunt) { }\n'
3494 '#if defined(LEARNED_BASIC_SKILLS)\n'
3495 '#define MAYBE_CastSteal \\\n'
3496 ' DISABLED_CastSteal \n'
3497 '#else\n'
3498 '#define MAYBE_CastSteal \\\n'
3499 ' CastSteal\n'
3500 '#endif\n'
3501 ' TEST_F(\n'
3502 ' ThiefClass,\n'
3503 ' MAYBE_CastSteal) { }\n'
3504 )
3505
3506 mock_input_api = MockInputApi()
3507 mock_input_api.files = [
3508 MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
3509 ]
3510 results = PRESUBMIT.CheckForgettingMAYBEInTests(mock_input_api,
3511 MockOutputApi())
3512 self.assertEqual(0, len(results))
Dirk Pranke3c18a382019-03-15 01:07:513513
Max Morozb47503b2019-08-08 21:03:273514class CheckFuzzTargetsTest(unittest.TestCase):
3515
3516 def _check(self, files):
3517 mock_input_api = MockInputApi()
3518 mock_input_api.files = []
3519 for fname, contents in files.items():
3520 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363521 return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api, MockOutputApi())
Max Morozb47503b2019-08-08 21:03:273522
3523 def testLibFuzzerSourcesIgnored(self):
3524 results = self._check({
3525 "third_party/lib/Fuzzer/FuzzerDriver.cpp": "LLVMFuzzerInitialize",
3526 })
3527 self.assertEqual(results, [])
3528
3529 def testNonCodeFilesIgnored(self):
3530 results = self._check({
3531 "README.md": "LLVMFuzzerInitialize",
3532 })
3533 self.assertEqual(results, [])
3534
3535 def testNoErrorHeaderPresent(self):
3536 results = self._check({
3537 "fuzzer.cc": (
3538 "#include \"testing/libfuzzer/libfuzzer_exports.h\"\n" +
3539 "LLVMFuzzerInitialize"
3540 )
3541 })
3542 self.assertEqual(results, [])
3543
3544 def testErrorMissingHeader(self):
3545 results = self._check({
3546 "fuzzer.cc": "LLVMFuzzerInitialize"
3547 })
3548 self.assertEqual(len(results), 1)
3549 self.assertEqual(results[0].items, ['fuzzer.cc'])
3550
3551
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263552class SetNoParentTest(unittest.TestCase):
John Abd-El-Malekdfd1edc2021-02-24 22:22:403553 def testSetNoParentTopLevelAllowed(self):
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263554 mock_input_api = MockInputApi()
3555 mock_input_api.files = [
3556 MockAffectedFile('goat/OWNERS',
3557 [
3558 'set noparent',
3559 '[email protected]',
John Abd-El-Malekdfd1edc2021-02-24 22:22:403560 ])
3561 ]
3562 mock_output_api = MockOutputApi()
3563 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
3564 self.assertEqual([], errors)
3565
3566 def testSetNoParentMissing(self):
3567 mock_input_api = MockInputApi()
3568 mock_input_api.files = [
3569 MockAffectedFile('services/goat/OWNERS',
3570 [
3571 'set noparent',
3572 '[email protected]',
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263573 'per-file *.json=set noparent',
3574 'per-file *[email protected]',
3575 ])
3576 ]
3577 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363578 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263579 self.assertEqual(1, len(errors))
3580 self.assertTrue('goat/OWNERS:1' in errors[0].long_text)
3581 self.assertTrue('goat/OWNERS:3' in errors[0].long_text)
3582
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263583 def testSetNoParentWithCorrectRule(self):
3584 mock_input_api = MockInputApi()
3585 mock_input_api.files = [
John Abd-El-Malekdfd1edc2021-02-24 22:22:403586 MockAffectedFile('services/goat/OWNERS',
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263587 [
3588 'set noparent',
3589 'file://ipc/SECURITY_OWNERS',
3590 'per-file *.json=set noparent',
3591 'per-file *.json=file://ipc/SECURITY_OWNERS',
3592 ])
3593 ]
3594 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363595 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263596 self.assertEqual([], errors)
3597
3598
Ken Rockotc31f4832020-05-29 18:58:513599class MojomStabilityCheckTest(unittest.TestCase):
3600 def runTestWithAffectedFiles(self, affected_files):
3601 mock_input_api = MockInputApi()
3602 mock_input_api.files = affected_files
3603 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363604 return PRESUBMIT.CheckStableMojomChanges(
Ken Rockotc31f4832020-05-29 18:58:513605 mock_input_api, mock_output_api)
3606
3607 def testSafeChangePasses(self):
3608 errors = self.runTestWithAffectedFiles([
3609 MockAffectedFile('foo/foo.mojom',
3610 ['[Stable] struct S { [MinVersion=1] int32 x; };'],
3611 old_contents=['[Stable] struct S {};'])
3612 ])
3613 self.assertEqual([], errors)
3614
3615 def testBadChangeFails(self):
3616 errors = self.runTestWithAffectedFiles([
3617 MockAffectedFile('foo/foo.mojom',
3618 ['[Stable] struct S { int32 x; };'],
3619 old_contents=['[Stable] struct S {};'])
3620 ])
3621 self.assertEqual(1, len(errors))
3622 self.assertTrue('not backward-compatible' in errors[0].message)
3623
Ken Rockotad7901f942020-06-04 20:17:093624 def testDeletedFile(self):
3625 """Regression test for https://crbug.com/1091407."""
3626 errors = self.runTestWithAffectedFiles([
3627 MockAffectedFile('a.mojom', [], old_contents=['struct S {};'],
3628 action='D'),
3629 MockAffectedFile('b.mojom',
3630 ['struct S {}; struct T { S s; };'],
3631 old_contents=['import "a.mojom"; struct T { S s; };'])
3632 ])
3633 self.assertEqual([], errors)
3634
Jose Magana2b456f22021-03-09 23:26:403635class CheckForUseOfChromeAppsDeprecationsTest(unittest.TestCase):
3636
3637 ERROR_MSG_PIECE = 'technologies which will soon be deprecated'
3638
3639 # Each positive test is also a naive negative test for the other cases.
3640
3641 def testWarningNMF(self):
3642 mock_input_api = MockInputApi()
3643 mock_input_api.files = [
3644 MockAffectedFile(
3645 'foo.NMF',
3646 ['"program"', '"Z":"content"', 'B'],
3647 ['"program"', 'B'],
3648 scm_diff='\n'.join([
3649 '--- foo.NMF.old 2020-12-02 20:40:54.430676385 +0100',
3650 '+++ foo.NMF.new 2020-12-02 20:41:02.086700197 +0100',
3651 '@@ -1,2 +1,3 @@',
3652 ' "program"',
3653 '+"Z":"content"',
3654 ' B']),
3655 action='M')
3656 ]
3657 mock_output_api = MockOutputApi()
3658 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3659 mock_output_api)
3660 self.assertEqual(1, len(errors))
3661 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
3662 self.assertTrue( 'foo.NMF' in errors[0].message)
3663
3664 def testWarningManifest(self):
3665 mock_input_api = MockInputApi()
3666 mock_input_api.files = [
3667 MockAffectedFile(
3668 'manifest.json',
3669 ['"app":', '"Z":"content"', 'B'],
3670 ['"app":"', 'B'],
3671 scm_diff='\n'.join([
3672 '--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
3673 '+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
3674 '@@ -1,2 +1,3 @@',
3675 ' "app"',
3676 '+"Z":"content"',
3677 ' B']),
3678 action='M')
3679 ]
3680 mock_output_api = MockOutputApi()
3681 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3682 mock_output_api)
3683 self.assertEqual(1, len(errors))
3684 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
3685 self.assertTrue( 'manifest.json' in errors[0].message)
3686
3687 def testOKWarningManifestWithoutApp(self):
3688 mock_input_api = MockInputApi()
3689 mock_input_api.files = [
3690 MockAffectedFile(
3691 'manifest.json',
3692 ['"name":', '"Z":"content"', 'B'],
3693 ['"name":"', 'B'],
3694 scm_diff='\n'.join([
3695 '--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
3696 '+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
3697 '@@ -1,2 +1,3 @@',
3698 ' "app"',
3699 '+"Z":"content"',
3700 ' B']),
3701 action='M')
3702 ]
3703 mock_output_api = MockOutputApi()
3704 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3705 mock_output_api)
3706 self.assertEqual(0, len(errors))
3707
3708 def testWarningPPAPI(self):
3709 mock_input_api = MockInputApi()
3710 mock_input_api.files = [
3711 MockAffectedFile(
3712 'foo.hpp',
3713 ['A', '#include <ppapi.h>', 'B'],
3714 ['A', 'B'],
3715 scm_diff='\n'.join([
3716 '--- foo.hpp.old 2020-12-02 20:40:54.430676385 +0100',
3717 '+++ foo.hpp.new 2020-12-02 20:41:02.086700197 +0100',
3718 '@@ -1,2 +1,3 @@',
3719 ' A',
3720 '+#include <ppapi.h>',
3721 ' B']),
3722 action='M')
3723 ]
3724 mock_output_api = MockOutputApi()
3725 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3726 mock_output_api)
3727 self.assertEqual(1, len(errors))
3728 self.assertTrue( self.ERROR_MSG_PIECE in errors[0].message)
3729 self.assertTrue( 'foo.hpp' in errors[0].message)
3730
3731 def testNoWarningPPAPI(self):
3732 mock_input_api = MockInputApi()
3733 mock_input_api.files = [
3734 MockAffectedFile(
3735 'foo.txt',
3736 ['A', 'Peppapig', 'B'],
3737 ['A', 'B'],
3738 scm_diff='\n'.join([
3739 '--- foo.txt.old 2020-12-02 20:40:54.430676385 +0100',
3740 '+++ foo.txt.new 2020-12-02 20:41:02.086700197 +0100',
3741 '@@ -1,2 +1,3 @@',
3742 ' A',
3743 '+Peppapig',
3744 ' B']),
3745 action='M')
3746 ]
3747 mock_output_api = MockOutputApi()
3748 errors = PRESUBMIT.CheckForUseOfChromeAppsDeprecations(mock_input_api,
3749 mock_output_api)
3750 self.assertEqual(0, len(errors))
3751
Dominic Battre645d42342020-12-04 16:14:103752class CheckDeprecationOfPreferencesTest(unittest.TestCase):
3753 # Test that a warning is generated if a preference registration is removed
3754 # from a random file.
3755 def testWarning(self):
3756 mock_input_api = MockInputApi()
3757 mock_input_api.files = [
3758 MockAffectedFile(
3759 'foo.cc',
3760 ['A', 'B'],
3761 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
3762 scm_diff='\n'.join([
3763 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
3764 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
3765 '@@ -1,3 +1,2 @@',
3766 ' A',
3767 '-prefs->RegisterStringPref("foo", "default");',
3768 ' B']),
3769 action='M')
3770 ]
3771 mock_output_api = MockOutputApi()
3772 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3773 mock_output_api)
3774 self.assertEqual(1, len(errors))
3775 self.assertTrue(
3776 'Discovered possible removal of preference registrations' in
3777 errors[0].message)
3778
3779 # Test that a warning is inhibited if the preference registration was moved
3780 # to the deprecation functions in browser prefs.
3781 def testNoWarningForMigration(self):
3782 mock_input_api = MockInputApi()
3783 mock_input_api.files = [
3784 # RegisterStringPref was removed from foo.cc.
3785 MockAffectedFile(
3786 'foo.cc',
3787 ['A', 'B'],
3788 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
3789 scm_diff='\n'.join([
3790 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
3791 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
3792 '@@ -1,3 +1,2 @@',
3793 ' A',
3794 '-prefs->RegisterStringPref("foo", "default");',
3795 ' B']),
3796 action='M'),
3797 # But the preference was properly migrated.
3798 MockAffectedFile(
3799 'chrome/browser/prefs/browser_prefs.cc',
3800 [
3801 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3802 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3803 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3804 'prefs->RegisterStringPref("foo", "default");',
3805 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3806 ],
3807 [
3808 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3809 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3810 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3811 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3812 ],
3813 scm_diff='\n'.join([
3814 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
3815 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
3816 '@@ -2,3 +2,4 @@',
3817 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3818 ' // BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3819 '+prefs->RegisterStringPref("foo", "default");',
3820 ' // END_MIGRATE_OBSOLETE_PROFILE_PREFS']),
3821 action='M'),
3822 ]
3823 mock_output_api = MockOutputApi()
3824 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3825 mock_output_api)
3826 self.assertEqual(0, len(errors))
3827
3828 # Test that a warning is NOT inhibited if the preference registration was
3829 # moved to a place outside of the migration functions in browser_prefs.cc
3830 def testWarningForImproperMigration(self):
3831 mock_input_api = MockInputApi()
3832 mock_input_api.files = [
3833 # RegisterStringPref was removed from foo.cc.
3834 MockAffectedFile(
3835 'foo.cc',
3836 ['A', 'B'],
3837 ['A', 'prefs->RegisterStringPref("foo", "default");', 'B'],
3838 scm_diff='\n'.join([
3839 '--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
3840 '+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
3841 '@@ -1,3 +1,2 @@',
3842 ' A',
3843 '-prefs->RegisterStringPref("foo", "default");',
3844 ' B']),
3845 action='M'),
3846 # The registration call was moved to a place in browser_prefs.cc that
3847 # is outside the migration functions.
3848 MockAffectedFile(
3849 'chrome/browser/prefs/browser_prefs.cc',
3850 [
3851 'prefs->RegisterStringPref("foo", "default");',
3852 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3853 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3854 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3855 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3856 ],
3857 [
3858 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3859 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3860 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3861 '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3862 ],
3863 scm_diff='\n'.join([
3864 '--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
3865 '+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
3866 '@@ -1,2 +1,3 @@',
3867 '+prefs->RegisterStringPref("foo", "default");',
3868 ' // BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3869 ' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS']),
3870 action='M'),
3871 ]
3872 mock_output_api = MockOutputApi()
3873 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3874 mock_output_api)
3875 self.assertEqual(1, len(errors))
3876 self.assertTrue(
3877 'Discovered possible removal of preference registrations' in
3878 errors[0].message)
3879
3880 # Check that the presubmit fails if a marker line in brower_prefs.cc is
3881 # deleted.
3882 def testDeletedMarkerRaisesError(self):
3883 mock_input_api = MockInputApi()
3884 mock_input_api.files = [
3885 MockAffectedFile('chrome/browser/prefs/browser_prefs.cc',
3886 [
3887 '// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3888 '// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
3889 '// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
3890 # The following line is deleted for this test
3891 # '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
3892 ])
3893 ]
3894 mock_output_api = MockOutputApi()
3895 errors = PRESUBMIT.CheckDeprecationOfPreferences(mock_input_api,
3896 mock_output_api)
3897 self.assertEqual(1, len(errors))
3898 self.assertEqual(
3899 'Broken .*MIGRATE_OBSOLETE_.*_PREFS markers in browser_prefs.cc.',
3900 errors[0].message)
3901
Kevin McNee967dd2d22021-11-15 16:09:293902class MPArchApiUsage(unittest.TestCase):
3903 def _assert_notify(self, expect_cc, msg, local_path, new_contents):
3904 mock_input_api = MockInputApi()
3905 mock_output_api = MockOutputApi()
3906 mock_input_api.files = [
3907 MockFile(local_path, new_contents),
3908 ]
3909 PRESUBMIT.CheckMPArchApiUsage(mock_input_api, mock_output_api)
3910 self.assertEqual(
3911 expect_cc,
3912 '[email protected]' in mock_output_api.more_cc,
3913 msg)
3914
3915 def testNotify(self):
3916 self._assert_notify(
3917 True,
3918 'Introduce WCO and WCUD',
3919 'chrome/my_feature.h',
3920 ['class MyFeature',
3921 ' : public content::WebContentsObserver,',
3922 ' public content::WebContentsUserData<MyFeature> {};',
3923 ])
3924 self._assert_notify(
3925 True,
3926 'Introduce WCO override',
3927 'chrome/my_feature.h',
3928 ['void DidFinishNavigation(',
3929 ' content::NavigationHandle* navigation_handle) override;',
3930 ])
3931 self._assert_notify(
3932 True,
3933 'Introduce IsInMainFrame',
3934 'chrome/my_feature.cc',
3935 ['void DoSomething(content::NavigationHandle* navigation_handle) {',
3936 ' if (navigation_handle->IsInMainFrame())',
3937 ' all_of_our_page_state.reset();',
3938 '}',
3939 ])
3940 self._assert_notify(
3941 True,
3942 'Introduce WC::FromRenderFrameHost',
3943 'chrome/my_feature.cc',
3944 ['void DoSomething(content::RenderFrameHost* rfh) {',
3945 ' auto* wc = content::WebContents::FromRenderFrameHost(rfh);',
3946 ' ChangeTabState(wc);',
3947 '}',
3948 ])
3949
3950 def testNoNotify(self):
3951 self._assert_notify(
3952 False,
3953 'No API usage',
3954 'chrome/my_feature.cc',
3955 ['void DoSomething() {',
3956 ' // TODO: Something',
3957 '}',
3958 ])
3959 # Something under a top level directory we're not concerned about happens
3960 # to share a name with a content API.
3961 self._assert_notify(
3962 False,
3963 'Uninteresting top level directory',
3964 'third_party/my_dep/my_code.cc',
3965 ['bool HasParent(Node* node) {',
3966 ' return node->GetParent();',
3967 '}',
3968 ])
3969 # We're not concerned with usage in test code.
3970 self._assert_notify(
3971 False,
3972 'Usage in test code',
3973 'chrome/my_feature_unittest.cc',
3974 ['TEST_F(MyFeatureTest, DoesSomething) {',
3975 ' EXPECT_TRUE(web_contents()->GetMainFrame());',
3976 '}',
3977 ])
3978
Dominic Battre645d42342020-12-04 16:14:103979
Henrique Ferreiro2a4b55942021-11-29 23:45:363980class AssertAshOnlyCodeTest(unittest.TestCase):
3981 def testErrorsOnlyOnAshDirectories(self):
3982 files_in_ash = [
3983 MockFile('ash/BUILD.gn', []),
3984 MockFile('chrome/browser/ash/BUILD.gn', []),
3985 ]
3986 other_files = [
3987 MockFile('chrome/browser/BUILD.gn', []),
3988 MockFile('chrome/browser/BUILD.gn', ['assert(is_chromeos_ash)']),
3989 ]
3990 input_api = MockInputApi()
3991 input_api.files = files_in_ash
3992 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
3993 self.assertEqual(2, len(errors))
3994
3995 input_api.files = other_files
3996 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
3997 self.assertEqual(0, len(errors))
3998
3999 def testDoesNotErrorOnNonGNFiles(self):
4000 input_api = MockInputApi()
4001 input_api.files = [
4002 MockFile('ash/test.h', ['assert(is_chromeos_ash)']),
4003 MockFile('chrome/browser/ash/test.cc',
4004 ['assert(is_chromeos_ash)']),
4005 ]
4006 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4007 self.assertEqual(0, len(errors))
4008
Giovanni Ortuño Urquidiab84da62021-12-10 00:53:214009 def testDeletedFile(self):
4010 input_api = MockInputApi()
4011 input_api.files = [
4012 MockFile('ash/BUILD.gn', []),
4013 MockFile('ash/foo/BUILD.gn', [], action='D'),
4014 ]
4015 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4016 self.assertEqual(1, len(errors))
4017
Henrique Ferreiro2a4b55942021-11-29 23:45:364018 def testDoesNotErrorWithAssertion(self):
4019 input_api = MockInputApi()
4020 input_api.files = [
4021 MockFile('ash/BUILD.gn', ['assert(is_chromeos_ash)']),
4022 MockFile('chrome/browser/ash/BUILD.gn',
4023 ['assert(is_chromeos_ash)']),
4024 MockFile('chrome/browser/ash/BUILD.gn',
4025 ['assert(is_chromeos_ash, "test")']),
4026 ]
4027 errors = PRESUBMIT.CheckAssertAshOnlyCode(input_api, MockOutputApi())
4028 self.assertEqual(0, len(errors))
4029
4030
Lukasz Anforowicz7016d05e2021-11-30 03:56:274031class CheckRawPtrUsageTest(unittest.TestCase):
4032 def testAllowedCases(self):
4033 mock_input_api = MockInputApi()
4034 mock_input_api.files = [
4035 # Browser-side files are allowed.
4036 MockAffectedFile('test10/browser/foo.h', ['raw_ptr<int>']),
4037 MockAffectedFile('test11/browser/foo.cc', ['raw_ptr<int>']),
4038 MockAffectedFile('test12/blink/common/foo.cc', ['raw_ptr<int>']),
4039 MockAffectedFile('test13/blink/public/common/foo.cc', ['raw_ptr<int>']),
4040 MockAffectedFile('test14/blink/public/platform/foo.cc',
4041 ['raw_ptr<int>']),
4042
4043 # Non-C++ files are allowed.
4044 MockAffectedFile('test20/renderer/foo.md', ['raw_ptr<int>']),
4045
4046 # Mentions in a comment are allowed.
4047 MockAffectedFile('test30/renderer/foo.cc', ['//raw_ptr<int>']),
4048 ]
4049 mock_output_api = MockOutputApi()
4050 errors = PRESUBMIT.CheckRawPtrUsage(mock_input_api, mock_output_api)
4051 self.assertFalse(errors)
4052
4053 def testDisallowedCases(self):
4054 mock_input_api = MockInputApi()
4055 mock_input_api.files = [
4056 MockAffectedFile('test1/renderer/foo.h', ['raw_ptr<int>']),
4057 MockAffectedFile('test2/renderer/foo.cc', ['raw_ptr<int>']),
4058 MockAffectedFile('test3/blink/public/web/foo.cc', ['raw_ptr<int>']),
4059 ]
4060 mock_output_api = MockOutputApi()
4061 errors = PRESUBMIT.CheckRawPtrUsage(mock_input_api, mock_output_api)
4062 self.assertEqual(len(mock_input_api.files), len(errors))
4063 for error in errors:
4064 self.assertTrue(
4065 'raw_ptr<T> should not be used in Renderer-only code' in
4066 error.message)
4067
4068
Henrique Ferreirof9819f2e32021-11-30 13:31:564069class AssertPythonShebangTest(unittest.TestCase):
4070 def testError(self):
4071 input_api = MockInputApi()
4072 input_api.files = [
4073 MockFile('ash/test.py', ['#!/usr/bin/python']),
4074 MockFile('chrome/test.py', ['#!/usr/bin/python2']),
4075 MockFile('third_party/blink/test.py', ['#!/usr/bin/python3']),
Takuto Ikuta36976512021-11-30 23:15:274076 MockFile('empty.py', []),
Henrique Ferreirof9819f2e32021-11-30 13:31:564077 ]
4078 errors = PRESUBMIT.CheckPythonShebang(input_api, MockOutputApi())
4079 self.assertEqual(3, len(errors))
4080
4081 def testNonError(self):
4082 input_api = MockInputApi()
4083 input_api.files = [
4084 MockFile('chrome/browser/BUILD.gn', ['#!/usr/bin/python']),
4085 MockFile('third_party/blink/web_tests/external/test.py',
4086 ['#!/usr/bin/python2']),
4087 MockFile('third_party/test/test.py', ['#!/usr/bin/python3']),
4088 ]
4089 errors = PRESUBMIT.CheckPythonShebang(input_api, MockOutputApi())
4090 self.assertEqual(0, len(errors))
4091
4092
[email protected]2299dcf2012-11-15 19:56:244093if __name__ == '__main__':
4094 unittest.main()