blob: 111f2b21e432e437777857a6bfbbd8beef9b52f6 [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
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3911from PRESUBMIT_test_mocks import MockFile, MockAffectedFile
gayane3dff8c22014-12-04 17:09:5112from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi
[email protected]2299dcf2012-11-15 19:56:2413
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3914
[email protected]99171a92014-06-03 08:44:4715_TEST_DATA_DIR = 'base/test/data/presubmit'
16
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3917
[email protected]b00342e7f2013-03-26 16:21:5418class VersionControlConflictsTest(unittest.TestCase):
[email protected]70ca77752012-11-20 03:45:0319 def testTypicalConflict(self):
20 lines = ['<<<<<<< HEAD',
21 ' base::ScopedTempDir temp_dir_;',
22 '=======',
23 ' ScopedTempDir temp_dir_;',
24 '>>>>>>> master']
25 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
26 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
27 self.assertEqual(3, len(errors))
28 self.assertTrue('1' in errors[0])
29 self.assertTrue('3' in errors[1])
30 self.assertTrue('5' in errors[2])
31
dbeam95c35a2f2015-06-02 01:40:2332 def testIgnoresReadmes(self):
33 lines = ['A First Level Header',
34 '====================',
35 '',
36 'A Second Level Header',
37 '---------------------']
38 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
39 MockInputApi(), MockFile('some/polymer/README.md', lines))
40 self.assertEqual(0, len(errors))
41
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3942
mcasasb7440c282015-02-04 14:52:1943class UmaHistogramChangeMatchedOrNotTest(unittest.TestCase):
44 def testTypicalCorrectlyMatchedChange(self):
45 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:4746 diff_java = [
47 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
mcasasb7440c282015-02-04 14:52:1948 diff_xml = ['<histogram name="Bla.Foo.Dummy"> </histogram>']
49 mock_input_api = MockInputApi()
50 mock_input_api.files = [
51 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:4752 MockFile('some/path/foo.java', diff_java),
mcasasb7440c282015-02-04 14:52:1953 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
54 ]
55 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
56 MockOutputApi())
57 self.assertEqual(0, len(warnings))
58
59 def testTypicalNotMatchedChange(self):
60 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:4761 diff_java = [
62 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
mcasasb7440c282015-02-04 14:52:1963 mock_input_api = MockInputApi()
Vaclav Brozekbdac817c2018-03-24 06:30:4764 mock_input_api.files = [
65 MockFile('some/path/foo.cc', diff_cc),
66 MockFile('some/path/foo.java', diff_java),
67 ]
mcasasb7440c282015-02-04 14:52:1968 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
69 MockOutputApi())
70 self.assertEqual(1, len(warnings))
71 self.assertEqual('warning', warnings[0].type)
Vaclav Brozekbdac817c2018-03-24 06:30:4772 self.assertTrue('foo.cc' in warnings[0].items[0])
73 self.assertTrue('foo.java' in warnings[0].items[1])
mcasasb7440c282015-02-04 14:52:1974
75 def testTypicalNotMatchedChangeViaSuffixes(self):
76 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:4777 diff_java = [
78 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
mcasasb7440c282015-02-04 14:52:1979 diff_xml = ['<histogram_suffixes name="SuperHistogram">',
80 ' <suffix name="Dummy"/>',
81 ' <affected-histogram name="Snafu.Dummy"/>',
82 '</histogram>']
83 mock_input_api = MockInputApi()
84 mock_input_api.files = [
85 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:4786 MockFile('some/path/foo.java', diff_java),
mcasasb7440c282015-02-04 14:52:1987 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
88 ]
89 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
90 MockOutputApi())
91 self.assertEqual(1, len(warnings))
92 self.assertEqual('warning', warnings[0].type)
Vaclav Brozekbdac817c2018-03-24 06:30:4793 self.assertTrue('foo.cc' in warnings[0].items[0])
94 self.assertTrue('foo.java' in warnings[0].items[1])
mcasasb7440c282015-02-04 14:52:1995
96 def testTypicalCorrectlyMatchedChangeViaSuffixes(self):
97 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:4798 diff_java = [
99 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
mcasasb7440c282015-02-04 14:52:19100 diff_xml = ['<histogram_suffixes name="SuperHistogram">',
101 ' <suffix name="Dummy"/>',
102 ' <affected-histogram name="Bla.Foo"/>',
103 '</histogram>']
104 mock_input_api = MockInputApi()
105 mock_input_api.files = [
106 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:47107 MockFile('some/path/foo.java', diff_java),
mcasasb7440c282015-02-04 14:52:19108 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
109 ]
110 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
111 MockOutputApi())
112 self.assertEqual(0, len(warnings))
113
114 def testTypicalCorrectlyMatchedChangeViaSuffixesWithSeparator(self):
115 diff_cc = ['UMA_HISTOGRAM_BOOL("Snafu_Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:47116 diff_java = ['RecordHistogram.recordBooleanHistogram("Snafu_Dummy", true)']
mcasasb7440c282015-02-04 14:52:19117 diff_xml = ['<histogram_suffixes name="SuperHistogram" separator="_">',
118 ' <suffix name="Dummy"/>',
119 ' <affected-histogram name="Snafu"/>',
120 '</histogram>']
121 mock_input_api = MockInputApi()
122 mock_input_api.files = [
123 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:47124 MockFile('some/path/foo.java', diff_java),
mcasasb7440c282015-02-04 14:52:19125 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
126 ]
127 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
128 MockOutputApi())
129 self.assertEqual(0, len(warnings))
[email protected]70ca77752012-11-20 03:45:03130
Makoto Shimazu3ad422cd2019-05-08 02:35:14131 def testCorrectlyMatchedChangeViaSuffixesWithLineWrapping(self):
132 diff_cc = [
133 'UMA_HISTOGRAM_BOOL("LongHistogramNameNeedsLineWrapping.Dummy", true)']
134 diff_java = ['RecordHistogram.recordBooleanHistogram(' +
135 '"LongHistogramNameNeedsLineWrapping.Dummy", true)']
136 diff_xml = ['<histogram_suffixes',
137 ' name="LongHistogramNameNeedsLineWrapping"',
138 ' separator=".">',
139 ' <suffix name="Dummy"/>',
140 ' <affected-histogram',
141 ' name="LongHistogramNameNeedsLineWrapping"/>',
142 '</histogram>']
143 mock_input_api = MockInputApi()
144 mock_input_api.files = [
145 MockFile('some/path/foo.cc', diff_cc),
146 MockFile('some/path/foo.java', diff_java),
147 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
148 ]
149 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
150 MockOutputApi())
151 self.assertEqual(0, len(warnings))
152
Vaclav Brozek8a8e2e202018-03-23 22:01:06153 def testNameMatch(self):
154 # Check that the detected histogram name is "Dummy" and not, e.g.,
155 # "Dummy\", true); // The \"correct"
156 diff_cc = ['UMA_HISTOGRAM_BOOL("Dummy", true); // The "correct" histogram']
Vaclav Brozekbdac817c2018-03-24 06:30:47157 diff_java = [
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39158 'RecordHistogram.recordBooleanHistogram("Dummy", true);' +
159 ' // The "correct" histogram']
Vaclav Brozek8a8e2e202018-03-23 22:01:06160 diff_xml = ['<histogram name="Dummy"> </histogram>']
161 mock_input_api = MockInputApi()
162 mock_input_api.files = [
163 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:47164 MockFile('some/path/foo.java', diff_java),
Vaclav Brozek8a8e2e202018-03-23 22:01:06165 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
166 ]
167 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
168 MockOutputApi())
169 self.assertEqual(0, len(warnings))
170
171 def testSimilarMacroNames(self):
Vaclav Brozekbdac817c2018-03-24 06:30:47172 diff_cc = ['PUMA_HISTOGRAM_COOL("Mountain Lion", 42)']
173 diff_java = [
174 'FakeRecordHistogram.recordFakeHistogram("Mountain Lion", 42)']
Vaclav Brozek8a8e2e202018-03-23 22:01:06175 mock_input_api = MockInputApi()
176 mock_input_api.files = [
177 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:47178 MockFile('some/path/foo.java', diff_java),
Vaclav Brozek8a8e2e202018-03-23 22:01:06179 ]
180 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
181 MockOutputApi())
182 self.assertEqual(0, len(warnings))
183
Vaclav Brozek0e730cbd2018-03-24 06:18:17184 def testMultiLine(self):
185 diff_cc = ['UMA_HISTOGRAM_BOOLEAN(', ' "Multi.Line", true)']
186 diff_cc2 = ['UMA_HISTOGRAM_BOOLEAN(', ' "Multi.Line"', ' , true)']
Vaclav Brozekbdac817c2018-03-24 06:30:47187 diff_java = [
188 'RecordHistogram.recordBooleanHistogram(',
189 ' "Multi.Line", true);',
190 ]
Vaclav Brozek0e730cbd2018-03-24 06:18:17191 mock_input_api = MockInputApi()
192 mock_input_api.files = [
193 MockFile('some/path/foo.cc', diff_cc),
194 MockFile('some/path/foo2.cc', diff_cc2),
Vaclav Brozekbdac817c2018-03-24 06:30:47195 MockFile('some/path/foo.java', diff_java),
Vaclav Brozek0e730cbd2018-03-24 06:18:17196 ]
197 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
198 MockOutputApi())
199 self.assertEqual(1, len(warnings))
200 self.assertEqual('warning', warnings[0].type)
201 self.assertTrue('foo.cc' in warnings[0].items[0])
202 self.assertTrue('foo2.cc' in warnings[0].items[1])
203
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39204
[email protected]b8079ae4a2012-12-05 19:56:49205class BadExtensionsTest(unittest.TestCase):
206 def testBadRejFile(self):
207 mock_input_api = MockInputApi()
208 mock_input_api.files = [
209 MockFile('some/path/foo.cc', ''),
210 MockFile('some/path/foo.cc.rej', ''),
211 MockFile('some/path2/bar.h.rej', ''),
212 ]
213
214 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
215 self.assertEqual(1, len(results))
216 self.assertEqual(2, len(results[0].items))
217 self.assertTrue('foo.cc.rej' in results[0].items[0])
218 self.assertTrue('bar.h.rej' in results[0].items[1])
219
220 def testBadOrigFile(self):
221 mock_input_api = MockInputApi()
222 mock_input_api.files = [
223 MockFile('other/path/qux.h.orig', ''),
224 MockFile('other/path/qux.h', ''),
225 MockFile('other/path/qux.cc', ''),
226 ]
227
228 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
229 self.assertEqual(1, len(results))
230 self.assertEqual(1, len(results[0].items))
231 self.assertTrue('qux.h.orig' in results[0].items[0])
232
233 def testGoodFiles(self):
234 mock_input_api = MockInputApi()
235 mock_input_api.files = [
236 MockFile('other/path/qux.h', ''),
237 MockFile('other/path/qux.cc', ''),
238 ]
239 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
240 self.assertEqual(0, len(results))
241
242
glidere61efad2015-02-18 17:39:43243class CheckSingletonInHeadersTest(unittest.TestCase):
244 def testSingletonInArbitraryHeader(self):
245 diff_singleton_h = ['base::subtle::AtomicWord '
olli.raula36aa8be2015-09-10 11:14:22246 'base::Singleton<Type, Traits, DifferentiatingType>::']
247 diff_foo_h = ['// base::Singleton<Foo> in comment.',
248 'friend class base::Singleton<Foo>']
oysteinec430ad42015-10-22 20:55:24249 diff_foo2_h = [' //Foo* bar = base::Singleton<Foo>::get();']
olli.raula36aa8be2015-09-10 11:14:22250 diff_bad_h = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43251 mock_input_api = MockInputApi()
252 mock_input_api.files = [MockAffectedFile('base/memory/singleton.h',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39253 diff_singleton_h),
glidere61efad2015-02-18 17:39:43254 MockAffectedFile('foo.h', diff_foo_h),
oysteinec430ad42015-10-22 20:55:24255 MockAffectedFile('foo2.h', diff_foo2_h),
glidere61efad2015-02-18 17:39:43256 MockAffectedFile('bad.h', diff_bad_h)]
257 warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api,
258 MockOutputApi())
259 self.assertEqual(1, len(warnings))
Sylvain Defresnea8b73d252018-02-28 15:45:54260 self.assertEqual(1, len(warnings[0].items))
glidere61efad2015-02-18 17:39:43261 self.assertEqual('error', warnings[0].type)
olli.raula36aa8be2015-09-10 11:14:22262 self.assertTrue('Found base::Singleton<T>' in warnings[0].message)
glidere61efad2015-02-18 17:39:43263
264 def testSingletonInCC(self):
olli.raula36aa8be2015-09-10 11:14:22265 diff_cc = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43266 mock_input_api = MockInputApi()
267 mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)]
268 warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api,
269 MockOutputApi())
270 self.assertEqual(0, len(warnings))
271
272
[email protected]b00342e7f2013-03-26 16:21:54273class InvalidOSMacroNamesTest(unittest.TestCase):
274 def testInvalidOSMacroNames(self):
275 lines = ['#if defined(OS_WINDOWS)',
276 ' #elif defined(OS_WINDOW)',
Avi Drissman34594e902020-07-25 05:35:44277 ' # if defined(OS_MAC) || defined(OS_CHROME)',
Avi Drissman32967a9e2020-07-30 04:10:32278 '# else // defined(OS_MACOSX)',
[email protected]b00342e7f2013-03-26 16:21:54279 '#endif // defined(OS_MACOS)']
280 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
281 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
282 self.assertEqual(len(lines), len(errors))
283 self.assertTrue(':1 OS_WINDOWS' in errors[0])
284 self.assertTrue('(did you mean OS_WIN?)' in errors[0])
285
286 def testValidOSMacroNames(self):
287 lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS]
288 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
289 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
290 self.assertEqual(0, len(errors))
291
292
lliabraa35bab3932014-10-01 12:16:44293class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
294 def testInvalidIfDefinedMacroNames(self):
295 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
296 '#if !defined(TARGET_IPHONE_SIMULATOR)',
297 '#elif defined(TARGET_IPHONE_SIMULATOR)',
298 '#ifdef TARGET_IPHONE_SIMULATOR',
299 ' # ifdef TARGET_IPHONE_SIMULATOR',
300 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
301 '# else // defined(TARGET_IPHONE_SIMULATOR)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39302 '#endif // defined(TARGET_IPHONE_SIMULATOR)']
lliabraa35bab3932014-10-01 12:16:44303 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
304 MockInputApi(), MockFile('some/path/source.mm', lines))
305 self.assertEqual(len(lines), len(errors))
306
307 def testValidIfDefinedMacroNames(self):
308 lines = ['#if defined(FOO)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39309 '#ifdef BAR']
lliabraa35bab3932014-10-01 12:16:44310 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
311 MockInputApi(), MockFile('some/path/source.cc', lines))
312 self.assertEqual(0, len(errors))
313
314
Samuel Huang0db2ea22019-12-09 16:42:47315class CheckAddedDepsHaveTestApprovalsTest(unittest.TestCase):
Daniel Cheng4dcdb6b2017-04-13 08:30:17316
317 def calculate(self, old_include_rules, old_specific_include_rules,
318 new_include_rules, new_specific_include_rules):
319 return PRESUBMIT._CalculateAddedDeps(
320 os.path, 'include_rules = %r\nspecific_include_rules = %r' % (
321 old_include_rules, old_specific_include_rules),
322 'include_rules = %r\nspecific_include_rules = %r' % (
323 new_include_rules, new_specific_include_rules))
324
325 def testCalculateAddedDeps(self):
326 old_include_rules = [
327 '+base',
328 '-chrome',
329 '+content',
330 '-grit',
331 '-grit/",',
332 '+jni/fooblat.h',
333 '!sandbox',
[email protected]f32e2d1e2013-07-26 21:39:08334 ]
Daniel Cheng4dcdb6b2017-04-13 08:30:17335 old_specific_include_rules = {
336 'compositor\.*': {
337 '+cc',
338 },
339 }
340
341 new_include_rules = [
342 '-ash',
343 '+base',
344 '+chrome',
345 '+components',
346 '+content',
347 '+grit',
348 '+grit/generated_resources.h",',
349 '+grit/",',
350 '+jni/fooblat.h',
351 '+policy',
manzagop85e629e2017-05-09 22:11:48352 '+' + os.path.join('third_party', 'WebKit'),
Daniel Cheng4dcdb6b2017-04-13 08:30:17353 ]
354 new_specific_include_rules = {
355 'compositor\.*': {
356 '+cc',
357 },
358 'widget\.*': {
359 '+gpu',
360 },
361 }
362
[email protected]f32e2d1e2013-07-26 21:39:08363 expected = set([
manzagop85e629e2017-05-09 22:11:48364 os.path.join('chrome', 'DEPS'),
365 os.path.join('gpu', 'DEPS'),
366 os.path.join('components', 'DEPS'),
367 os.path.join('policy', 'DEPS'),
368 os.path.join('third_party', 'WebKit', 'DEPS'),
[email protected]f32e2d1e2013-07-26 21:39:08369 ])
Daniel Cheng4dcdb6b2017-04-13 08:30:17370 self.assertEqual(
371 expected,
372 self.calculate(old_include_rules, old_specific_include_rules,
373 new_include_rules, new_specific_include_rules))
374
375 def testCalculateAddedDepsIgnoresPermutations(self):
376 old_include_rules = [
377 '+base',
378 '+chrome',
379 ]
380 new_include_rules = [
381 '+chrome',
382 '+base',
383 ]
384 self.assertEqual(set(),
385 self.calculate(old_include_rules, {}, new_include_rules,
386 {}))
[email protected]f32e2d1e2013-07-26 21:39:08387
388
[email protected]99171a92014-06-03 08:44:47389class JSONParsingTest(unittest.TestCase):
390 def testSuccess(self):
391 input_api = MockInputApi()
392 filename = 'valid_json.json'
393 contents = ['// This is a comment.',
394 '{',
395 ' "key1": ["value1", "value2"],',
396 ' "key2": 3 // This is an inline comment.',
397 '}'
398 ]
399 input_api.files = [MockFile(filename, contents)]
400 self.assertEqual(None,
401 PRESUBMIT._GetJSONParseError(input_api, filename))
402
403 def testFailure(self):
404 input_api = MockInputApi()
405 test_data = [
406 ('invalid_json_1.json',
407 ['{ x }'],
[email protected]a3343272014-06-17 11:41:53408 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47409 ('invalid_json_2.json',
410 ['// Hello world!',
411 '{ "hello": "world }'],
[email protected]a3343272014-06-17 11:41:53412 'Unterminated string starting at:'),
[email protected]99171a92014-06-03 08:44:47413 ('invalid_json_3.json',
414 ['{ "a": "b", "c": "d", }'],
[email protected]a3343272014-06-17 11:41:53415 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47416 ('invalid_json_4.json',
417 ['{ "a": "b" "c": "d" }'],
[email protected]a3343272014-06-17 11:41:53418 'Expecting , delimiter:'),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39419 ]
[email protected]99171a92014-06-03 08:44:47420
421 input_api.files = [MockFile(filename, contents)
422 for (filename, contents, _) in test_data]
423
424 for (filename, _, expected_error) in test_data:
425 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
[email protected]a3343272014-06-17 11:41:53426 self.assertTrue(expected_error in str(actual_error),
427 "'%s' not found in '%s'" % (expected_error, actual_error))
[email protected]99171a92014-06-03 08:44:47428
429 def testNoEatComments(self):
430 input_api = MockInputApi()
431 file_with_comments = 'file_with_comments.json'
432 contents_with_comments = ['// This is a comment.',
433 '{',
434 ' "key1": ["value1", "value2"],',
435 ' "key2": 3 // This is an inline comment.',
436 '}'
437 ]
438 file_without_comments = 'file_without_comments.json'
439 contents_without_comments = ['{',
440 ' "key1": ["value1", "value2"],',
441 ' "key2": 3',
442 '}'
443 ]
444 input_api.files = [MockFile(file_with_comments, contents_with_comments),
445 MockFile(file_without_comments,
446 contents_without_comments)]
447
448 self.assertEqual('No JSON object could be decoded',
449 str(PRESUBMIT._GetJSONParseError(input_api,
450 file_with_comments,
451 eat_comments=False)))
452 self.assertEqual(None,
453 PRESUBMIT._GetJSONParseError(input_api,
454 file_without_comments,
455 eat_comments=False))
456
457
458class IDLParsingTest(unittest.TestCase):
459 def testSuccess(self):
460 input_api = MockInputApi()
461 filename = 'valid_idl_basics.idl'
462 contents = ['// Tests a valid IDL file.',
463 'namespace idl_basics {',
464 ' enum EnumType {',
465 ' name1,',
466 ' name2',
467 ' };',
468 '',
469 ' dictionary MyType1 {',
470 ' DOMString a;',
471 ' };',
472 '',
473 ' callback Callback1 = void();',
474 ' callback Callback2 = void(long x);',
475 ' callback Callback3 = void(MyType1 arg);',
476 ' callback Callback4 = void(EnumType type);',
477 '',
478 ' interface Functions {',
479 ' static void function1();',
480 ' static void function2(long x);',
481 ' static void function3(MyType1 arg);',
482 ' static void function4(Callback1 cb);',
483 ' static void function5(Callback2 cb);',
484 ' static void function6(Callback3 cb);',
485 ' static void function7(Callback4 cb);',
486 ' };',
487 '',
488 ' interface Events {',
489 ' static void onFoo1();',
490 ' static void onFoo2(long x);',
491 ' static void onFoo2(MyType1 arg);',
492 ' static void onFoo3(EnumType type);',
493 ' };',
494 '};'
495 ]
496 input_api.files = [MockFile(filename, contents)]
497 self.assertEqual(None,
498 PRESUBMIT._GetIDLParseError(input_api, filename))
499
500 def testFailure(self):
501 input_api = MockInputApi()
502 test_data = [
503 ('invalid_idl_1.idl',
504 ['//',
505 'namespace test {',
506 ' dictionary {',
507 ' DOMString s;',
508 ' };',
509 '};'],
510 'Unexpected "{" after keyword "dictionary".\n'),
511 # TODO(yoz): Disabled because it causes the IDL parser to hang.
512 # See crbug.com/363830.
513 # ('invalid_idl_2.idl',
514 # (['namespace test {',
515 # ' dictionary MissingSemicolon {',
516 # ' DOMString a',
517 # ' DOMString b;',
518 # ' };',
519 # '};'],
520 # 'Unexpected symbol DOMString after symbol a.'),
521 ('invalid_idl_3.idl',
522 ['//',
523 'namespace test {',
524 ' enum MissingComma {',
525 ' name1',
526 ' name2',
527 ' };',
528 '};'],
529 'Unexpected symbol name2 after symbol name1.'),
530 ('invalid_idl_4.idl',
531 ['//',
532 'namespace test {',
533 ' enum TrailingComma {',
534 ' name1,',
535 ' name2,',
536 ' };',
537 '};'],
538 'Trailing comma in block.'),
539 ('invalid_idl_5.idl',
540 ['//',
541 'namespace test {',
542 ' callback Callback1 = void(;',
543 '};'],
544 'Unexpected ";" after "(".'),
545 ('invalid_idl_6.idl',
546 ['//',
547 'namespace test {',
548 ' callback Callback1 = void(long );',
549 '};'],
550 'Unexpected ")" after symbol long.'),
551 ('invalid_idl_7.idl',
552 ['//',
553 'namespace test {',
554 ' interace Events {',
555 ' static void onFoo1();',
556 ' };',
557 '};'],
558 'Unexpected symbol Events after symbol interace.'),
559 ('invalid_idl_8.idl',
560 ['//',
561 'namespace test {',
562 ' interface NotEvent {',
563 ' static void onFoo1();',
564 ' };',
565 '};'],
566 'Did not process Interface Interface(NotEvent)'),
567 ('invalid_idl_9.idl',
568 ['//',
569 'namespace test {',
570 ' interface {',
571 ' static void function1();',
572 ' };',
573 '};'],
574 'Interface missing name.'),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39575 ]
[email protected]99171a92014-06-03 08:44:47576
577 input_api.files = [MockFile(filename, contents)
578 for (filename, contents, _) in test_data]
579
580 for (filename, _, expected_error) in test_data:
581 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
582 self.assertTrue(expected_error in str(actual_error),
583 "'%s' not found in '%s'" % (expected_error, actual_error))
584
585
[email protected]0bb112362014-07-26 04:38:32586class TryServerMasterTest(unittest.TestCase):
587 def testTryServerMasters(self):
588 bots = {
tandriie5587792016-07-14 00:34:50589 'master.tryserver.chromium.android': [
jbudorick3ae7a772016-05-20 02:36:04590 'android_archive_rel_ng',
591 'android_arm64_dbg_recipe',
592 'android_blink_rel',
jbudorick3ae7a772016-05-20 02:36:04593 'android_clang_dbg_recipe',
594 'android_compile_dbg',
jbudorick3ae7a772016-05-20 02:36:04595 'android_compile_x64_dbg',
596 'android_compile_x86_dbg',
597 'android_coverage',
598 'android_cronet_tester'
599 'android_swarming_rel',
600 'cast_shell_android',
601 'linux_android_dbg_ng',
602 'linux_android_rel_ng',
603 ],
tandriie5587792016-07-14 00:34:50604 'master.tryserver.chromium.mac': [
[email protected]0bb112362014-07-26 04:38:32605 'ios_dbg_simulator',
606 'ios_rel_device',
607 'ios_rel_device_ninja',
608 'mac_asan',
609 'mac_asan_64',
610 'mac_chromium_compile_dbg',
611 'mac_chromium_compile_rel',
612 'mac_chromium_dbg',
613 'mac_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32614 'mac_nacl_sdk',
615 'mac_nacl_sdk_build',
616 'mac_rel_naclmore',
[email protected]0bb112362014-07-26 04:38:32617 'mac_x64_rel',
618 'mac_xcodebuild',
619 ],
tandriie5587792016-07-14 00:34:50620 'master.tryserver.chromium.linux': [
[email protected]0bb112362014-07-26 04:38:32621 'chromium_presubmit',
622 'linux_arm_cross_compile',
623 'linux_arm_tester',
[email protected]0bb112362014-07-26 04:38:32624 'linux_chromeos_asan',
625 'linux_chromeos_browser_asan',
626 'linux_chromeos_valgrind',
[email protected]0bb112362014-07-26 04:38:32627 'linux_chromium_chromeos_dbg',
628 'linux_chromium_chromeos_rel',
[email protected]0bb112362014-07-26 04:38:32629 'linux_chromium_compile_dbg',
630 'linux_chromium_compile_rel',
631 'linux_chromium_dbg',
632 'linux_chromium_gn_dbg',
633 'linux_chromium_gn_rel',
634 'linux_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32635 'linux_chromium_trusty32_dbg',
636 'linux_chromium_trusty32_rel',
637 'linux_chromium_trusty_dbg',
638 'linux_chromium_trusty_rel',
639 'linux_clang_tsan',
640 'linux_ecs_ozone',
641 'linux_layout',
642 'linux_layout_asan',
643 'linux_layout_rel',
644 'linux_layout_rel_32',
645 'linux_nacl_sdk',
646 'linux_nacl_sdk_bionic',
647 'linux_nacl_sdk_bionic_build',
648 'linux_nacl_sdk_build',
649 'linux_redux',
650 'linux_rel_naclmore',
651 'linux_rel_precise32',
652 'linux_valgrind',
653 'tools_build_presubmit',
654 ],
tandriie5587792016-07-14 00:34:50655 'master.tryserver.chromium.win': [
[email protected]0bb112362014-07-26 04:38:32656 'win8_aura',
657 'win8_chromium_dbg',
658 'win8_chromium_rel',
659 'win_chromium_compile_dbg',
660 'win_chromium_compile_rel',
661 'win_chromium_dbg',
662 'win_chromium_rel',
663 'win_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32664 'win_chromium_x64_dbg',
665 'win_chromium_x64_rel',
[email protected]0bb112362014-07-26 04:38:32666 'win_nacl_sdk',
667 'win_nacl_sdk_build',
668 'win_rel_naclmore',
669 ],
670 }
671 for master, bots in bots.iteritems():
672 for bot in bots:
673 self.assertEqual(master, PRESUBMIT.GetTryServerMasterForBot(bot),
674 'bot=%s: expected %s, computed %s' % (
675 bot, master, PRESUBMIT.GetTryServerMasterForBot(bot)))
676
677
davileene0426252015-03-02 21:10:41678class UserMetricsActionTest(unittest.TestCase):
679 def testUserMetricsActionInActions(self):
680 input_api = MockInputApi()
681 file_with_user_action = 'file_with_user_action.cc'
682 contents_with_user_action = [
683 'base::UserMetricsAction("AboutChrome")'
684 ]
685
686 input_api.files = [MockFile(file_with_user_action,
687 contents_with_user_action)]
688
689 self.assertEqual(
690 [], PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi()))
691
davileene0426252015-03-02 21:10:41692 def testUserMetricsActionNotAddedToActions(self):
693 input_api = MockInputApi()
694 file_with_user_action = 'file_with_user_action.cc'
695 contents_with_user_action = [
696 'base::UserMetricsAction("NotInActionsXml")'
697 ]
698
699 input_api.files = [MockFile(file_with_user_action,
700 contents_with_user_action)]
701
702 output = PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi())
703 self.assertEqual(
704 ('File %s line %d: %s is missing in '
705 'tools/metrics/actions/actions.xml. Please run '
706 'tools/metrics/actions/extract_actions.py to update.'
707 % (file_with_user_action, 1, 'NotInActionsXml')),
708 output[0].message)
709
710
agrievef32bcc72016-04-04 14:57:40711class PydepsNeedsUpdatingTest(unittest.TestCase):
712
713 class MockSubprocess(object):
714 CalledProcessError = subprocess.CalledProcessError
715
Mohamed Heikal7cd4d8312020-06-16 16:49:40716 def _MockParseGclientArgs(self, is_android=True):
717 return lambda: {'checkout_android': 'true' if is_android else 'false' }
718
agrievef32bcc72016-04-04 14:57:40719 def setUp(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40720 mock_all_pydeps = ['A.pydeps', 'B.pydeps', 'D.pydeps']
agrievef32bcc72016-04-04 14:57:40721 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
722 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
Mohamed Heikal7cd4d8312020-06-16 16:49:40723 mock_android_pydeps = ['D.pydeps']
724 self.old_ANDROID_SPECIFIC_PYDEPS_FILES = (
725 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES)
726 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = mock_android_pydeps
727 self.old_ParseGclientArgs = PRESUBMIT._ParseGclientArgs
728 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs()
agrievef32bcc72016-04-04 14:57:40729 self.mock_input_api = MockInputApi()
730 self.mock_output_api = MockOutputApi()
731 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
732 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
733 self.checker._file_cache = {
734 'A.pydeps': '# Generated by:\n# CMD A\nA.py\nC.py\n',
735 'B.pydeps': '# Generated by:\n# CMD B\nB.py\nC.py\n',
Mohamed Heikal7cd4d8312020-06-16 16:49:40736 'D.pydeps': '# Generated by:\n# CMD D\nD.py\n',
agrievef32bcc72016-04-04 14:57:40737 }
738
739 def tearDown(self):
740 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
Mohamed Heikal7cd4d8312020-06-16 16:49:40741 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = (
742 self.old_ANDROID_SPECIFIC_PYDEPS_FILES)
743 PRESUBMIT._ParseGclientArgs = self.old_ParseGclientArgs
agrievef32bcc72016-04-04 14:57:40744
745 def _RunCheck(self):
746 return PRESUBMIT._CheckPydepsNeedsUpdating(self.mock_input_api,
747 self.mock_output_api,
748 checker_for_tests=self.checker)
749
750 def testAddedPydep(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40751 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13752 if self.mock_input_api.platform != 'linux2':
753 return []
754
agrievef32bcc72016-04-04 14:57:40755 self.mock_input_api.files = [
756 MockAffectedFile('new.pydeps', [], action='A'),
757 ]
758
Zhiling Huang45cabf32018-03-10 00:50:03759 self.mock_input_api.CreateMockFileInPath(
760 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
761 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40762 results = self._RunCheck()
763 self.assertEqual(1, len(results))
764 self.assertTrue('PYDEPS_FILES' in str(results[0]))
765
Zhiling Huang45cabf32018-03-10 00:50:03766 def testPydepNotInSrc(self):
767 self.mock_input_api.files = [
768 MockAffectedFile('new.pydeps', [], action='A'),
769 ]
770 self.mock_input_api.CreateMockFileInPath([])
771 results = self._RunCheck()
772 self.assertEqual(0, len(results))
773
agrievef32bcc72016-04-04 14:57:40774 def testRemovedPydep(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40775 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13776 if self.mock_input_api.platform != 'linux2':
777 return []
778
agrievef32bcc72016-04-04 14:57:40779 self.mock_input_api.files = [
780 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
781 ]
Zhiling Huang45cabf32018-03-10 00:50:03782 self.mock_input_api.CreateMockFileInPath(
783 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
784 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40785 results = self._RunCheck()
786 self.assertEqual(1, len(results))
787 self.assertTrue('PYDEPS_FILES' in str(results[0]))
788
789 def testRandomPyIgnored(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40790 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13791 if self.mock_input_api.platform != 'linux2':
792 return []
793
agrievef32bcc72016-04-04 14:57:40794 self.mock_input_api.files = [
795 MockAffectedFile('random.py', []),
796 ]
797
798 results = self._RunCheck()
799 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
800
801 def testRelevantPyNoChange(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40802 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13803 if self.mock_input_api.platform != 'linux2':
804 return []
805
agrievef32bcc72016-04-04 14:57:40806 self.mock_input_api.files = [
807 MockAffectedFile('A.py', []),
808 ]
809
John Budorickab2fa102017-10-06 16:59:49810 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40811 self.assertEqual('CMD A --output ""', cmd)
812 return self.checker._file_cache['A.pydeps']
813
814 self.mock_input_api.subprocess.check_output = mock_check_output
815
816 results = self._RunCheck()
817 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
818
819 def testRelevantPyOneChange(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40820 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13821 if self.mock_input_api.platform != 'linux2':
822 return []
823
agrievef32bcc72016-04-04 14:57:40824 self.mock_input_api.files = [
825 MockAffectedFile('A.py', []),
826 ]
827
John Budorickab2fa102017-10-06 16:59:49828 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40829 self.assertEqual('CMD A --output ""', cmd)
830 return 'changed data'
831
832 self.mock_input_api.subprocess.check_output = mock_check_output
833
834 results = self._RunCheck()
835 self.assertEqual(1, len(results))
836 self.assertTrue('File is stale' in str(results[0]))
837
838 def testRelevantPyTwoChanges(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40839 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13840 if self.mock_input_api.platform != 'linux2':
841 return []
842
agrievef32bcc72016-04-04 14:57:40843 self.mock_input_api.files = [
844 MockAffectedFile('C.py', []),
845 ]
846
John Budorickab2fa102017-10-06 16:59:49847 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40848 return 'changed data'
849
850 self.mock_input_api.subprocess.check_output = mock_check_output
851
852 results = self._RunCheck()
853 self.assertEqual(2, len(results))
854 self.assertTrue('File is stale' in str(results[0]))
855 self.assertTrue('File is stale' in str(results[1]))
856
Mohamed Heikal7cd4d8312020-06-16 16:49:40857 def testRelevantAndroidPyInNonAndroidCheckout(self):
858 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux.
859 if self.mock_input_api.platform != 'linux2':
860 return []
861
862 self.mock_input_api.files = [
863 MockAffectedFile('D.py', []),
864 ]
865
866 def mock_check_output(cmd, shell=False, env=None):
867 self.assertEqual('CMD D --output ""', cmd)
868 return 'changed data'
869
870 self.mock_input_api.subprocess.check_output = mock_check_output
871 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs(is_android=False)
872
873 results = self._RunCheck()
874 self.assertEqual(1, len(results))
875 self.assertTrue('Android' in str(results[0]))
876 self.assertTrue('D.pydeps' in str(results[0]))
877
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39878
Daniel Bratell8ba52722018-03-02 16:06:14879class IncludeGuardTest(unittest.TestCase):
880 def testIncludeGuardChecks(self):
881 mock_input_api = MockInputApi()
882 mock_output_api = MockOutputApi()
883 mock_input_api.files = [
884 MockAffectedFile('content/browser/thing/foo.h', [
885 '// Comment',
886 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
887 '#define CONTENT_BROWSER_THING_FOO_H_',
888 'struct McBoatFace;',
889 '#endif // CONTENT_BROWSER_THING_FOO_H_',
890 ]),
891 MockAffectedFile('content/browser/thing/bar.h', [
892 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
893 '#define CONTENT_BROWSER_THING_BAR_H_',
894 'namespace content {',
895 '#endif // CONTENT_BROWSER_THING_BAR_H_',
896 '} // namespace content',
897 ]),
898 MockAffectedFile('content/browser/test1.h', [
899 'namespace content {',
900 '} // namespace content',
901 ]),
902 MockAffectedFile('content\\browser\\win.h', [
903 '#ifndef CONTENT_BROWSER_WIN_H_',
904 '#define CONTENT_BROWSER_WIN_H_',
905 'struct McBoatFace;',
906 '#endif // CONTENT_BROWSER_WIN_H_',
907 ]),
908 MockAffectedFile('content/browser/test2.h', [
909 '// Comment',
910 '#ifndef CONTENT_BROWSER_TEST2_H_',
911 'struct McBoatFace;',
912 '#endif // CONTENT_BROWSER_TEST2_H_',
913 ]),
914 MockAffectedFile('content/browser/internal.h', [
915 '// Comment',
916 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
917 '#define CONTENT_BROWSER_INTERNAL_H_',
918 '// Comment',
919 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
920 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
921 'namespace internal {',
922 '} // namespace internal',
923 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
924 'namespace content {',
925 '} // namespace content',
926 '#endif // CONTENT_BROWSER_THING_BAR_H_',
927 ]),
928 MockAffectedFile('content/browser/thing/foo.cc', [
929 '// This is a non-header.',
930 ]),
931 MockAffectedFile('content/browser/disabled.h', [
932 '// no-include-guard-because-multiply-included',
933 'struct McBoatFace;',
934 ]),
935 # New files don't allow misspelled include guards.
936 MockAffectedFile('content/browser/spleling.h', [
937 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
938 '#define CONTENT_BROWSER_SPLLEING_H_',
939 'struct McBoatFace;',
940 '#endif // CONTENT_BROWSER_SPLLEING_H_',
941 ]),
Olivier Robinbba137492018-07-30 11:31:34942 # New files don't allow + in include guards.
943 MockAffectedFile('content/browser/foo+bar.h', [
944 '#ifndef CONTENT_BROWSER_FOO+BAR_H_',
945 '#define CONTENT_BROWSER_FOO+BAR_H_',
946 'struct McBoatFace;',
947 '#endif // CONTENT_BROWSER_FOO+BAR_H_',
948 ]),
Daniel Bratell8ba52722018-03-02 16:06:14949 # Old files allow misspelled include guards (for now).
950 MockAffectedFile('chrome/old.h', [
951 '// New contents',
952 '#ifndef CHROME_ODL_H_',
953 '#define CHROME_ODL_H_',
954 '#endif // CHROME_ODL_H_',
955 ], [
956 '// Old contents',
957 '#ifndef CHROME_ODL_H_',
958 '#define CHROME_ODL_H_',
959 '#endif // CHROME_ODL_H_',
960 ]),
961 # Using a Blink style include guard outside Blink is wrong.
962 MockAffectedFile('content/NotInBlink.h', [
963 '#ifndef NotInBlink_h',
964 '#define NotInBlink_h',
965 'struct McBoatFace;',
966 '#endif // NotInBlink_h',
967 ]),
Daniel Bratell39b5b062018-05-16 18:09:57968 # Using a Blink style include guard in Blink is no longer ok.
969 MockAffectedFile('third_party/blink/InBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14970 '#ifndef InBlink_h',
971 '#define InBlink_h',
972 'struct McBoatFace;',
973 '#endif // InBlink_h',
974 ]),
975 # Using a bad include guard in Blink is not ok.
Daniel Bratell39b5b062018-05-16 18:09:57976 MockAffectedFile('third_party/blink/AlsoInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14977 '#ifndef WrongInBlink_h',
978 '#define WrongInBlink_h',
979 'struct McBoatFace;',
980 '#endif // WrongInBlink_h',
981 ]),
Daniel Bratell39b5b062018-05-16 18:09:57982 # Using a bad include guard in Blink is not accepted even if
983 # it's an old file.
984 MockAffectedFile('third_party/blink/StillInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14985 '// New contents',
986 '#ifndef AcceptedInBlink_h',
987 '#define AcceptedInBlink_h',
988 'struct McBoatFace;',
989 '#endif // AcceptedInBlink_h',
990 ], [
991 '// Old contents',
992 '#ifndef AcceptedInBlink_h',
993 '#define AcceptedInBlink_h',
994 'struct McBoatFace;',
995 '#endif // AcceptedInBlink_h',
996 ]),
Daniel Bratell39b5b062018-05-16 18:09:57997 # Using a non-Chromium include guard in third_party
998 # (outside blink) is accepted.
999 MockAffectedFile('third_party/foo/some_file.h', [
1000 '#ifndef REQUIRED_RPCNDR_H_',
1001 '#define REQUIRED_RPCNDR_H_',
1002 'struct SomeFileFoo;',
1003 '#endif // REQUIRED_RPCNDR_H_',
1004 ]),
Kinuko Yasuda0cdb3da2019-07-31 21:50:321005 # Not having proper include guard in *_message_generator.h
1006 # for old IPC messages is allowed.
1007 MockAffectedFile('content/common/content_message_generator.h', [
1008 '#undef CONTENT_COMMON_FOO_MESSAGES_H_',
1009 '#include "content/common/foo_messages.h"',
1010 '#ifndef CONTENT_COMMON_FOO_MESSAGES_H_',
1011 '#error "Failed to include content/common/foo_messages.h"',
1012 '#endif',
1013 ]),
Daniel Bratell8ba52722018-03-02 16:06:141014 ]
1015 msgs = PRESUBMIT._CheckForIncludeGuards(
1016 mock_input_api, mock_output_api)
Olivier Robinbba137492018-07-30 11:31:341017 expected_fail_count = 8
Daniel Bratell8ba52722018-03-02 16:06:141018 self.assertEqual(expected_fail_count, len(msgs),
1019 'Expected %d items, found %d: %s'
1020 % (expected_fail_count, len(msgs), msgs))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391021 self.assertEqual(msgs[0].items, ['content/browser/thing/bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:141022 self.assertEqual(msgs[0].message,
1023 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
1024 'not covering the whole file')
1025
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391026 self.assertEqual(msgs[1].items, ['content/browser/test1.h'])
Daniel Bratell8ba52722018-03-02 16:06:141027 self.assertEqual(msgs[1].message,
1028 'Missing include guard CONTENT_BROWSER_TEST1_H_')
1029
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391030 self.assertEqual(msgs[2].items, ['content/browser/test2.h:3'])
Daniel Bratell8ba52722018-03-02 16:06:141031 self.assertEqual(msgs[2].message,
1032 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
1033 'include guard')
1034
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391035 self.assertEqual(msgs[3].items, ['content/browser/spleling.h:1'])
Daniel Bratell8ba52722018-03-02 16:06:141036 self.assertEqual(msgs[3].message,
1037 'Header using the wrong include guard name '
1038 'CONTENT_BROWSER_SPLLEING_H_')
1039
Olivier Robinbba137492018-07-30 11:31:341040 self.assertEqual(msgs[4].items, ['content/browser/foo+bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:141041 self.assertEqual(msgs[4].message,
Olivier Robinbba137492018-07-30 11:31:341042 'Missing include guard CONTENT_BROWSER_FOO_BAR_H_')
1043
1044 self.assertEqual(msgs[5].items, ['content/NotInBlink.h:1'])
1045 self.assertEqual(msgs[5].message,
Daniel Bratell8ba52722018-03-02 16:06:141046 'Header using the wrong include guard name '
1047 'NotInBlink_h')
1048
Olivier Robinbba137492018-07-30 11:31:341049 self.assertEqual(msgs[6].items, ['third_party/blink/InBlink.h:1'])
1050 self.assertEqual(msgs[6].message,
Daniel Bratell8ba52722018-03-02 16:06:141051 'Header using the wrong include guard name '
Daniel Bratell39b5b062018-05-16 18:09:571052 'InBlink_h')
1053
Olivier Robinbba137492018-07-30 11:31:341054 self.assertEqual(msgs[7].items, ['third_party/blink/AlsoInBlink.h:1'])
1055 self.assertEqual(msgs[7].message,
Daniel Bratell39b5b062018-05-16 18:09:571056 'Header using the wrong include guard name '
Daniel Bratell8ba52722018-03-02 16:06:141057 'WrongInBlink_h')
1058
Chris Hall59f8d0c72020-05-01 07:31:191059class AccessibilityRelnotesFieldTest(unittest.TestCase):
1060 def testRelnotesPresent(self):
1061 mock_input_api = MockInputApi()
1062 mock_output_api = MockOutputApi()
1063
1064 mock_input_api.files = [MockAffectedFile('ui/accessibility/foo.bar', [''])]
Akihiro Ota08108e542020-05-20 15:30:531065 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191066 mock_input_api.change.footers['AX-Relnotes'] = [
1067 'Important user facing change']
1068
1069 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1070 mock_input_api, mock_output_api)
1071 self.assertEqual(0, len(msgs),
1072 'Expected %d messages, found %d: %s'
1073 % (0, len(msgs), msgs))
1074
1075 def testRelnotesMissingFromAccessibilityChange(self):
1076 mock_input_api = MockInputApi()
1077 mock_output_api = MockOutputApi()
1078
1079 mock_input_api.files = [
1080 MockAffectedFile('some/file', ['']),
1081 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1082 MockAffectedFile('some/other/file', [''])
1083 ]
Akihiro Ota08108e542020-05-20 15:30:531084 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191085
1086 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1087 mock_input_api, mock_output_api)
1088 self.assertEqual(1, len(msgs),
1089 'Expected %d messages, found %d: %s'
1090 % (1, len(msgs), msgs))
1091 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1092 'Missing AX-Relnotes field message not found in errors')
1093
1094 # The relnotes footer is not required for changes which do not touch any
1095 # accessibility directories.
1096 def testIgnoresNonAccesssibilityCode(self):
1097 mock_input_api = MockInputApi()
1098 mock_output_api = MockOutputApi()
1099
1100 mock_input_api.files = [
1101 MockAffectedFile('some/file', ['']),
1102 MockAffectedFile('some/other/file', [''])
1103 ]
Akihiro Ota08108e542020-05-20 15:30:531104 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191105
1106 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1107 mock_input_api, mock_output_api)
1108 self.assertEqual(0, len(msgs),
1109 'Expected %d messages, found %d: %s'
1110 % (0, len(msgs), msgs))
1111
1112 # Test that our presubmit correctly raises an error for a set of known paths.
1113 def testExpectedPaths(self):
1114 filesToTest = [
1115 "chrome/browser/accessibility/foo.py",
1116 "chrome/browser/chromeos/arc/accessibility/foo.cc",
1117 "chrome/browser/ui/views/accessibility/foo.h",
1118 "chrome/browser/extensions/api/automation/foo.h",
1119 "chrome/browser/extensions/api/automation_internal/foo.cc",
1120 "chrome/renderer/extensions/accessibility_foo.h",
1121 "chrome/tests/data/accessibility/foo.html",
1122 "content/browser/accessibility/foo.cc",
1123 "content/renderer/accessibility/foo.h",
1124 "content/tests/data/accessibility/foo.cc",
1125 "extensions/renderer/api/automation/foo.h",
1126 "ui/accessibility/foo/bar/baz.cc",
1127 "ui/views/accessibility/foo/bar/baz.h",
1128 ]
1129
1130 for testFile in filesToTest:
1131 mock_input_api = MockInputApi()
1132 mock_output_api = MockOutputApi()
1133
1134 mock_input_api.files = [
1135 MockAffectedFile(testFile, [''])
1136 ]
Akihiro Ota08108e542020-05-20 15:30:531137 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191138
1139 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1140 mock_input_api, mock_output_api)
1141 self.assertEqual(1, len(msgs),
1142 'Expected %d messages, found %d: %s, for file %s'
1143 % (1, len(msgs), msgs, testFile))
1144 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1145 ('Missing AX-Relnotes field message not found in errors '
1146 ' for file %s' % (testFile)))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391147
Akihiro Ota08108e542020-05-20 15:30:531148 # Test that AX-Relnotes field can appear in the commit description (as long
1149 # as it appears at the beginning of a line).
1150 def testRelnotesInCommitDescription(self):
1151 mock_input_api = MockInputApi()
1152 mock_output_api = MockOutputApi()
1153
1154 mock_input_api.files = [
1155 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1156 ]
1157 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1158 'AX-Relnotes: solves all accessibility issues forever')
1159
1160 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1161 mock_input_api, mock_output_api)
1162 self.assertEqual(0, len(msgs),
1163 'Expected %d messages, found %d: %s'
1164 % (0, len(msgs), msgs))
1165
1166 # Test that we don't match AX-Relnotes if it appears in the middle of a line.
1167 def testRelnotesMustAppearAtBeginningOfLine(self):
1168 mock_input_api = MockInputApi()
1169 mock_output_api = MockOutputApi()
1170
1171 mock_input_api.files = [
1172 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1173 ]
1174 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1175 'This change has no AX-Relnotes: we should print a warning')
1176
1177 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1178 mock_input_api, mock_output_api)
1179 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1180 'Missing AX-Relnotes field message not found in errors')
1181
1182 # Tests that the AX-Relnotes field can be lowercase and use a '=' in place
1183 # of a ':'.
1184 def testRelnotesLowercaseWithEqualSign(self):
1185 mock_input_api = MockInputApi()
1186 mock_output_api = MockOutputApi()
1187
1188 mock_input_api.files = [
1189 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1190 ]
1191 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1192 'ax-relnotes= this is a valid format for accessibiliy relnotes')
1193
1194 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1195 mock_input_api, mock_output_api)
1196 self.assertEqual(0, len(msgs),
1197 'Expected %d messages, found %d: %s'
1198 % (0, len(msgs), msgs))
1199
yolandyan45001472016-12-21 21:12:421200class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
1201 def testCheckAndroidTestAnnotationUsage(self):
1202 mock_input_api = MockInputApi()
1203 mock_output_api = MockOutputApi()
1204
1205 mock_input_api.files = [
1206 MockAffectedFile('LalaLand.java', [
1207 'random stuff'
1208 ]),
1209 MockAffectedFile('CorrectUsage.java', [
1210 'import android.support.test.filters.LargeTest;',
1211 'import android.support.test.filters.MediumTest;',
1212 'import android.support.test.filters.SmallTest;',
1213 ]),
1214 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
1215 'import android.test.suitebuilder.annotation.LargeTest;',
1216 ]),
1217 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
1218 'import android.test.suitebuilder.annotation.MediumTest;',
1219 ]),
1220 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
1221 'import android.test.suitebuilder.annotation.SmallTest;',
1222 ]),
1223 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
1224 'import android.test.suitebuilder.annotation.Smoke;',
1225 ])
1226 ]
1227 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
1228 mock_input_api, mock_output_api)
1229 self.assertEqual(1, len(msgs),
1230 'Expected %d items, found %d: %s'
1231 % (1, len(msgs), msgs))
1232 self.assertEqual(4, len(msgs[0].items),
1233 'Expected %d items, found %d: %s'
1234 % (4, len(msgs[0].items), msgs[0].items))
1235 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
1236 'UsedDeprecatedLargeTestAnnotation not found in errors')
1237 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
1238 in msgs[0].items,
1239 'UsedDeprecatedMediumTestAnnotation not found in errors')
1240 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
1241 'UsedDeprecatedSmallTestAnnotation not found in errors')
1242 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
1243 'UsedDeprecatedSmokeAnnotation not found in errors')
1244
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391245
Yoland Yanb92fa522017-08-28 17:37:061246class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271247 def testCheckAndroidTestJUnitFramework(self):
Yoland Yanb92fa522017-08-28 17:37:061248 mock_input_api = MockInputApi()
1249 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:421250
Yoland Yanb92fa522017-08-28 17:37:061251 mock_input_api.files = [
1252 MockAffectedFile('LalaLand.java', [
1253 'random stuff'
1254 ]),
1255 MockAffectedFile('CorrectUsage.java', [
1256 'import org.junit.ABC',
1257 'import org.junit.XYZ;',
1258 ]),
1259 MockAffectedFile('UsedDeprecatedJUnit.java', [
1260 'import junit.framework.*;',
1261 ]),
1262 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
1263 'import junit.framework.Assert;',
1264 ]),
1265 ]
1266 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
1267 mock_input_api, mock_output_api)
1268 self.assertEqual(1, len(msgs),
1269 'Expected %d items, found %d: %s'
1270 % (1, len(msgs), msgs))
1271 self.assertEqual(2, len(msgs[0].items),
1272 'Expected %d items, found %d: %s'
1273 % (2, len(msgs[0].items), msgs[0].items))
1274 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
1275 'UsedDeprecatedJUnit.java not found in errors')
1276 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
1277 in msgs[0].items,
1278 'UsedDeprecatedJUnitAssert not found in errors')
1279
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391280
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271281class AndroidJUnitBaseClassTest(unittest.TestCase):
1282 def testCheckAndroidTestJUnitBaseClass(self):
Yoland Yanb92fa522017-08-28 17:37:061283 mock_input_api = MockInputApi()
1284 mock_output_api = MockOutputApi()
1285
1286 mock_input_api.files = [
1287 MockAffectedFile('LalaLand.java', [
1288 'random stuff'
1289 ]),
1290 MockAffectedFile('CorrectTest.java', [
1291 '@RunWith(ABC.class);'
1292 'public class CorrectTest {',
1293 '}',
1294 ]),
1295 MockAffectedFile('HistoricallyIncorrectTest.java', [
1296 'public class Test extends BaseCaseA {',
1297 '}',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391298 ], old_contents=[
Yoland Yanb92fa522017-08-28 17:37:061299 'public class Test extends BaseCaseB {',
1300 '}',
1301 ]),
1302 MockAffectedFile('CorrectTestWithInterface.java', [
1303 '@RunWith(ABC.class);'
1304 'public class CorrectTest implement Interface {',
1305 '}',
1306 ]),
1307 MockAffectedFile('IncorrectTest.java', [
1308 'public class IncorrectTest extends TestCase {',
1309 '}',
1310 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241311 MockAffectedFile('IncorrectWithInterfaceTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061312 'public class Test implements X extends BaseClass {',
1313 '}',
1314 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241315 MockAffectedFile('IncorrectMultiLineTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061316 'public class Test implements X, Y, Z',
1317 ' extends TestBase {',
1318 '}',
1319 ]),
1320 ]
1321 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1322 mock_input_api, mock_output_api)
1323 self.assertEqual(1, len(msgs),
1324 'Expected %d items, found %d: %s'
1325 % (1, len(msgs), msgs))
1326 self.assertEqual(3, len(msgs[0].items),
1327 'Expected %d items, found %d: %s'
1328 % (3, len(msgs[0].items), msgs[0].items))
1329 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1330 'IncorrectTest not found in errors')
Vaclav Brozekf01ed502018-03-16 19:38:241331 self.assertTrue('IncorrectWithInterfaceTest.java:1'
Yoland Yanb92fa522017-08-28 17:37:061332 in msgs[0].items,
Vaclav Brozekf01ed502018-03-16 19:38:241333 'IncorrectWithInterfaceTest not found in errors')
1334 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1335 'IncorrectMultiLineTest not found in errors')
yolandyan45001472016-12-21 21:12:421336
Jinsong Fan91ebbbd2019-04-16 14:57:171337class AndroidDebuggableBuildTest(unittest.TestCase):
1338
1339 def testCheckAndroidDebuggableBuild(self):
1340 mock_input_api = MockInputApi()
1341 mock_output_api = MockOutputApi()
1342
1343 mock_input_api.files = [
1344 MockAffectedFile('RandomStuff.java', [
1345 'random stuff'
1346 ]),
1347 MockAffectedFile('CorrectUsage.java', [
1348 'import org.chromium.base.BuildInfo;',
1349 'some random stuff',
1350 'boolean isOsDebuggable = BuildInfo.isDebugAndroid();',
1351 ]),
1352 MockAffectedFile('JustCheckUserdebugBuild.java', [
1353 'import android.os.Build;',
1354 'some random stuff',
1355 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")',
1356 ]),
1357 MockAffectedFile('JustCheckEngineeringBuild.java', [
1358 'import android.os.Build;',
1359 'some random stuff',
1360 'boolean isOsDebuggable = "eng".equals(Build.TYPE)',
1361 ]),
1362 MockAffectedFile('UsedBuildType.java', [
1363 'import android.os.Build;',
1364 'some random stuff',
1365 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")'
1366 '|| "eng".equals(Build.TYPE)',
1367 ]),
1368 MockAffectedFile('UsedExplicitBuildType.java', [
1369 'some random stuff',
1370 'boolean isOsDebuggable = android.os.Build.TYPE.equals("userdebug")'
1371 '|| "eng".equals(android.os.Build.TYPE)',
1372 ]),
1373 ]
1374
1375 msgs = PRESUBMIT._CheckAndroidDebuggableBuild(
1376 mock_input_api, mock_output_api)
1377 self.assertEqual(1, len(msgs),
1378 'Expected %d items, found %d: %s'
1379 % (1, len(msgs), msgs))
1380 self.assertEqual(4, len(msgs[0].items),
1381 'Expected %d items, found %d: %s'
1382 % (4, len(msgs[0].items), msgs[0].items))
1383 self.assertTrue('JustCheckUserdebugBuild.java:3' in msgs[0].items)
1384 self.assertTrue('JustCheckEngineeringBuild.java:3' in msgs[0].items)
1385 self.assertTrue('UsedBuildType.java:3' in msgs[0].items)
1386 self.assertTrue('UsedExplicitBuildType.java:2' in msgs[0].items)
1387
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391388
dgn4401aa52015-04-29 16:26:171389class LogUsageTest(unittest.TestCase):
1390
dgnaa68d5e2015-06-10 10:08:221391 def testCheckAndroidCrLogUsage(self):
1392 mock_input_api = MockInputApi()
1393 mock_output_api = MockOutputApi()
1394
1395 mock_input_api.files = [
1396 MockAffectedFile('RandomStuff.java', [
1397 'random stuff'
1398 ]),
dgn87d9fb62015-06-12 09:15:121399 MockAffectedFile('HasAndroidLog.java', [
1400 'import android.util.Log;',
1401 'some random stuff',
1402 'Log.d("TAG", "foo");',
1403 ]),
1404 MockAffectedFile('HasExplicitUtilLog.java', [
1405 'some random stuff',
1406 'android.util.Log.d("TAG", "foo");',
1407 ]),
1408 MockAffectedFile('IsInBasePackage.java', [
1409 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511410 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121411 'Log.d(TAG, "foo");',
1412 ]),
1413 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1414 'package org.chromium.base;',
1415 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511416 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121417 'Log.d(TAG, "foo");',
1418 ]),
1419 MockAffectedFile('HasBothLog.java', [
1420 'import org.chromium.base.Log;',
1421 'some random stuff',
dgn38736db2015-09-18 19:20:511422 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121423 'Log.d(TAG, "foo");',
1424 'android.util.Log.d("TAG", "foo");',
1425 ]),
dgnaa68d5e2015-06-10 10:08:221426 MockAffectedFile('HasCorrectTag.java', [
1427 'import org.chromium.base.Log;',
1428 'some random stuff',
dgn38736db2015-09-18 19:20:511429 'private static final String TAG = "cr_Foo";',
1430 'Log.d(TAG, "foo");',
1431 ]),
1432 MockAffectedFile('HasOldTag.java', [
1433 'import org.chromium.base.Log;',
1434 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221435 'private static final String TAG = "cr.Foo";',
1436 'Log.d(TAG, "foo");',
1437 ]),
dgn38736db2015-09-18 19:20:511438 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221439 'import org.chromium.base.Log;',
1440 'some random stuff',
dgn38736db2015-09-18 19:20:511441 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221442 'Log.d(TAG, "foo");',
1443 ]),
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461444 MockAffectedFile('HasDottedTagPublic.java', [
1445 'import org.chromium.base.Log;',
1446 'some random stuff',
1447 'public static final String TAG = "cr_foo.bar";',
1448 'Log.d(TAG, "foo");',
1449 ]),
dgnaa68d5e2015-06-10 10:08:221450 MockAffectedFile('HasNoTagDecl.java', [
1451 'import org.chromium.base.Log;',
1452 'some random stuff',
1453 'Log.d(TAG, "foo");',
1454 ]),
1455 MockAffectedFile('HasIncorrectTagDecl.java', [
1456 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511457 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221458 'some random stuff',
1459 'Log.d(TAG, "foo");',
1460 ]),
1461 MockAffectedFile('HasInlineTag.java', [
1462 'import org.chromium.base.Log;',
1463 'some random stuff',
dgn38736db2015-09-18 19:20:511464 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221465 'Log.d("TAG", "foo");',
1466 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551467 MockAffectedFile('HasInlineTagWithSpace.java', [
1468 'import org.chromium.base.Log;',
1469 'some random stuff',
1470 'private static final String TAG = "cr_Foo";',
1471 'Log.d("log message", "foo");',
1472 ]),
dgn38736db2015-09-18 19:20:511473 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221474 'import org.chromium.base.Log;',
1475 'some random stuff',
1476 'private static final String TAG = "rubbish";',
1477 'Log.d(TAG, "foo");',
1478 ]),
1479 MockAffectedFile('HasTooLongTag.java', [
1480 'import org.chromium.base.Log;',
1481 'some random stuff',
dgn38736db2015-09-18 19:20:511482 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:221483 'Log.d(TAG, "foo");',
1484 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551485 MockAffectedFile('HasTooLongTagWithNoLogCallsInDiff.java', [
1486 'import org.chromium.base.Log;',
1487 'some random stuff',
1488 'private static final String TAG = "21_charachers_long___";',
1489 ]),
dgnaa68d5e2015-06-10 10:08:221490 ]
1491
1492 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1493 mock_input_api, mock_output_api)
1494
dgn38736db2015-09-18 19:20:511495 self.assertEqual(5, len(msgs),
1496 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221497
1498 # Declaration format
dgn38736db2015-09-18 19:20:511499 nb = len(msgs[0].items)
1500 self.assertEqual(2, nb,
1501 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221502 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1503 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221504
1505 # Tag length
dgn38736db2015-09-18 19:20:511506 nb = len(msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551507 self.assertEqual(2, nb,
1508 'Expected %d items, found %d: %s' % (2, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:221509 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551510 self.assertTrue('HasTooLongTagWithNoLogCallsInDiff.java' in msgs[1].items)
dgnaa68d5e2015-06-10 10:08:221511
1512 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511513 nb = len(msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551514 self.assertEqual(3, nb,
1515 'Expected %d items, found %d: %s' % (3, nb, msgs[2].items))
1516 self.assertTrue('HasBothLog.java:5' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221517 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551518 self.assertTrue('HasInlineTagWithSpace.java:4' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221519
dgn87d9fb62015-06-12 09:15:121520 # Util Log usage
dgn38736db2015-09-18 19:20:511521 nb = len(msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551522 self.assertEqual(3, nb,
1523 'Expected %d items, found %d: %s' % (3, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:121524 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551525 self.assertTrue('HasExplicitUtilLog.java:2' in msgs[3].items)
dgn87d9fb62015-06-12 09:15:121526 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:221527
dgn38736db2015-09-18 19:20:511528 # Tag must not contain
1529 nb = len(msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461530 self.assertEqual(3, nb,
dgn38736db2015-09-18 19:20:511531 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1532 self.assertTrue('HasDottedTag.java' in msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461533 self.assertTrue('HasDottedTagPublic.java' in msgs[4].items)
dgn38736db2015-09-18 19:20:511534 self.assertTrue('HasOldTag.java' in msgs[4].items)
1535
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391536
estadee17314a02017-01-12 16:22:161537class GoogleAnswerUrlFormatTest(unittest.TestCase):
1538
1539 def testCatchAnswerUrlId(self):
1540 input_api = MockInputApi()
1541 input_api.files = [
1542 MockFile('somewhere/file.cc',
1543 ['char* host = '
1544 ' "https://support.google.com/chrome/answer/123456";']),
1545 MockFile('somewhere_else/file.cc',
1546 ['char* host = '
1547 ' "https://support.google.com/chrome/a/answer/123456";']),
1548 ]
1549
1550 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1551 input_api, MockOutputApi())
1552 self.assertEqual(1, len(warnings))
1553 self.assertEqual(2, len(warnings[0].items))
1554
1555 def testAllowAnswerUrlParam(self):
1556 input_api = MockInputApi()
1557 input_api.files = [
1558 MockFile('somewhere/file.cc',
1559 ['char* host = '
1560 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1561 ]
1562
1563 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1564 input_api, MockOutputApi())
1565 self.assertEqual(0, len(warnings))
1566
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391567
reillyi38965732015-11-16 18:27:331568class HardcodedGoogleHostsTest(unittest.TestCase):
1569
1570 def testWarnOnAssignedLiterals(self):
1571 input_api = MockInputApi()
1572 input_api.files = [
1573 MockFile('content/file.cc',
1574 ['char* host = "https://www.google.com";']),
1575 MockFile('content/file.cc',
1576 ['char* host = "https://www.googleapis.com";']),
1577 MockFile('content/file.cc',
1578 ['char* host = "https://clients1.google.com";']),
1579 ]
1580
1581 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1582 input_api, MockOutputApi())
1583 self.assertEqual(1, len(warnings))
1584 self.assertEqual(3, len(warnings[0].items))
1585
1586 def testAllowInComment(self):
1587 input_api = MockInputApi()
1588 input_api.files = [
1589 MockFile('content/file.cc',
1590 ['char* host = "https://www.aol.com"; // google.com'])
1591 ]
1592
1593 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1594 input_api, MockOutputApi())
1595 self.assertEqual(0, len(warnings))
1596
dgn4401aa52015-04-29 16:26:171597
James Cook6b6597c2019-11-06 22:05:291598class ChromeOsSyncedPrefRegistrationTest(unittest.TestCase):
1599
1600 def testWarnsOnChromeOsDirectories(self):
1601 input_api = MockInputApi()
1602 input_api.files = [
1603 MockFile('ash/file.cc',
1604 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1605 MockFile('chrome/browser/chromeos/file.cc',
1606 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1607 MockFile('chromeos/file.cc',
1608 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1609 MockFile('components/arc/file.cc',
1610 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1611 MockFile('components/exo/file.cc',
1612 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1613 ]
1614 warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration(
1615 input_api, MockOutputApi())
1616 self.assertEqual(1, len(warnings))
1617
1618 def testDoesNotWarnOnSyncOsPref(self):
1619 input_api = MockInputApi()
1620 input_api.files = [
1621 MockFile('chromeos/file.cc',
1622 ['PrefRegistrySyncable::SYNCABLE_OS_PREF']),
1623 ]
1624 warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration(
1625 input_api, MockOutputApi())
1626 self.assertEqual(0, len(warnings))
1627
1628 def testDoesNotWarnOnCrossPlatformDirectories(self):
1629 input_api = MockInputApi()
1630 input_api.files = [
1631 MockFile('chrome/browser/ui/file.cc',
1632 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1633 MockFile('components/sync/file.cc',
1634 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1635 MockFile('content/browser/file.cc',
1636 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1637 ]
1638 warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration(
1639 input_api, MockOutputApi())
1640 self.assertEqual(0, len(warnings))
1641
1642 def testSeparateWarningForPriorityPrefs(self):
1643 input_api = MockInputApi()
1644 input_api.files = [
1645 MockFile('chromeos/file.cc',
1646 ['PrefRegistrySyncable::SYNCABLE_PREF',
1647 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']),
1648 ]
1649 warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration(
1650 input_api, MockOutputApi())
1651 self.assertEqual(2, len(warnings))
1652
1653
jbriance9e12f162016-11-25 07:57:501654class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311655 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501656 mock_input_api = MockInputApi()
1657 mock_input_api.files = [
1658 MockAffectedFile('somewhere/file.cc', [
1659 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311660 ]),
1661 MockAffectedFile('third_party/header.h', [
1662 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501663 ])
1664 ]
1665 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391666 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501667 self.assertEqual(0, len(warnings))
1668
1669 def testNoNestedDeclaration(self):
1670 mock_input_api = MockInputApi()
1671 mock_input_api.files = [
1672 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311673 'class SomeClass {',
1674 ' protected:',
1675 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501676 '};'
1677 ])
1678 ]
1679 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391680 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501681 self.assertEqual(0, len(warnings))
1682
1683 def testSubStrings(self):
1684 mock_input_api = MockInputApi()
1685 mock_input_api.files = [
1686 MockAffectedFile('somewhere/header.h', [
1687 'class NotUsefulClass;',
1688 'struct SomeStruct;',
1689 'UsefulClass *p1;',
1690 'SomeStructPtr *p2;'
1691 ])
1692 ]
1693 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391694 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501695 self.assertEqual(2, len(warnings))
1696
1697 def testUselessForwardDeclaration(self):
1698 mock_input_api = MockInputApi()
1699 mock_input_api.files = [
1700 MockAffectedFile('somewhere/header.h', [
1701 'class DummyClass;',
1702 'struct DummyStruct;',
1703 'class UsefulClass;',
1704 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311705 ])
jbriance9e12f162016-11-25 07:57:501706 ]
1707 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391708 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501709 self.assertEqual(2, len(warnings))
1710
jbriance2c51e821a2016-12-12 08:24:311711 def testBlinkHeaders(self):
1712 mock_input_api = MockInputApi()
1713 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491714 MockAffectedFile('third_party/blink/header.h', [
jbriance2c51e821a2016-12-12 08:24:311715 'class DummyClass;',
1716 'struct DummyStruct;',
1717 ]),
Kent Tamura32dbbcb2018-11-30 12:28:491718 MockAffectedFile('third_party\\blink\\header.h', [
jbriance2c51e821a2016-12-12 08:24:311719 'class DummyClass;',
1720 'struct DummyStruct;',
1721 ])
1722 ]
1723 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391724 MockOutputApi())
jbriance2c51e821a2016-12-12 08:24:311725 self.assertEqual(4, len(warnings))
1726
jbriance9e12f162016-11-25 07:57:501727
rlanday6802cf632017-05-30 17:48:361728class RelativeIncludesTest(unittest.TestCase):
1729 def testThirdPartyNotWebKitIgnored(self):
1730 mock_input_api = MockInputApi()
1731 mock_input_api.files = [
1732 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1733 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1734 ]
1735
1736 mock_output_api = MockOutputApi()
1737
1738 errors = PRESUBMIT._CheckForRelativeIncludes(
1739 mock_input_api, mock_output_api)
1740 self.assertEqual(0, len(errors))
1741
1742 def testNonCppFileIgnored(self):
1743 mock_input_api = MockInputApi()
1744 mock_input_api.files = [
1745 MockAffectedFile('test.py', '#include "../header.h"'),
1746 ]
1747
1748 mock_output_api = MockOutputApi()
1749
1750 errors = PRESUBMIT._CheckForRelativeIncludes(
1751 mock_input_api, mock_output_api)
1752 self.assertEqual(0, len(errors))
1753
1754 def testInnocuousChangesAllowed(self):
1755 mock_input_api = MockInputApi()
1756 mock_input_api.files = [
1757 MockAffectedFile('test.cpp', '#include "header.h"'),
1758 MockAffectedFile('test2.cpp', '../'),
1759 ]
1760
1761 mock_output_api = MockOutputApi()
1762
1763 errors = PRESUBMIT._CheckForRelativeIncludes(
1764 mock_input_api, mock_output_api)
1765 self.assertEqual(0, len(errors))
1766
1767 def testRelativeIncludeNonWebKitProducesError(self):
1768 mock_input_api = MockInputApi()
1769 mock_input_api.files = [
1770 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1771 ]
1772
1773 mock_output_api = MockOutputApi()
1774
1775 errors = PRESUBMIT._CheckForRelativeIncludes(
1776 mock_input_api, mock_output_api)
1777 self.assertEqual(1, len(errors))
1778
1779 def testRelativeIncludeWebKitProducesError(self):
1780 mock_input_api = MockInputApi()
1781 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491782 MockAffectedFile('third_party/blink/test.cpp',
rlanday6802cf632017-05-30 17:48:361783 ['#include "../header.h']),
1784 ]
1785
1786 mock_output_api = MockOutputApi()
1787
1788 errors = PRESUBMIT._CheckForRelativeIncludes(
1789 mock_input_api, mock_output_api)
1790 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241791
Daniel Cheng13ca61a882017-08-25 15:11:251792
Daniel Bratell65b033262019-04-23 08:17:061793class CCIncludeTest(unittest.TestCase):
1794 def testThirdPartyNotBlinkIgnored(self):
1795 mock_input_api = MockInputApi()
1796 mock_input_api.files = [
1797 MockAffectedFile('third_party/test.cpp', '#include "file.cc"'),
1798 ]
1799
1800 mock_output_api = MockOutputApi()
1801
1802 errors = PRESUBMIT._CheckForCcIncludes(
1803 mock_input_api, mock_output_api)
1804 self.assertEqual(0, len(errors))
1805
1806 def testPythonFileIgnored(self):
1807 mock_input_api = MockInputApi()
1808 mock_input_api.files = [
1809 MockAffectedFile('test.py', '#include "file.cc"'),
1810 ]
1811
1812 mock_output_api = MockOutputApi()
1813
1814 errors = PRESUBMIT._CheckForCcIncludes(
1815 mock_input_api, mock_output_api)
1816 self.assertEqual(0, len(errors))
1817
1818 def testIncFilesAccepted(self):
1819 mock_input_api = MockInputApi()
1820 mock_input_api.files = [
1821 MockAffectedFile('test.py', '#include "file.inc"'),
1822 ]
1823
1824 mock_output_api = MockOutputApi()
1825
1826 errors = PRESUBMIT._CheckForCcIncludes(
1827 mock_input_api, mock_output_api)
1828 self.assertEqual(0, len(errors))
1829
1830 def testInnocuousChangesAllowed(self):
1831 mock_input_api = MockInputApi()
1832 mock_input_api.files = [
1833 MockAffectedFile('test.cpp', '#include "header.h"'),
1834 MockAffectedFile('test2.cpp', 'Something "file.cc"'),
1835 ]
1836
1837 mock_output_api = MockOutputApi()
1838
1839 errors = PRESUBMIT._CheckForCcIncludes(
1840 mock_input_api, mock_output_api)
1841 self.assertEqual(0, len(errors))
1842
1843 def testCcIncludeNonBlinkProducesError(self):
1844 mock_input_api = MockInputApi()
1845 mock_input_api.files = [
1846 MockAffectedFile('test.cpp', ['#include "file.cc"']),
1847 ]
1848
1849 mock_output_api = MockOutputApi()
1850
1851 errors = PRESUBMIT._CheckForCcIncludes(
1852 mock_input_api, mock_output_api)
1853 self.assertEqual(1, len(errors))
1854
1855 def testCppIncludeBlinkProducesError(self):
1856 mock_input_api = MockInputApi()
1857 mock_input_api.files = [
1858 MockAffectedFile('third_party/blink/test.cpp',
1859 ['#include "foo/file.cpp"']),
1860 ]
1861
1862 mock_output_api = MockOutputApi()
1863
1864 errors = PRESUBMIT._CheckForCcIncludes(
1865 mock_input_api, mock_output_api)
1866 self.assertEqual(1, len(errors))
1867
1868
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191869class NewHeaderWithoutGnChangeTest(unittest.TestCase):
1870 def testAddHeaderWithoutGn(self):
1871 mock_input_api = MockInputApi()
1872 mock_input_api.files = [
1873 MockAffectedFile('base/stuff.h', ''),
1874 ]
1875 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1876 mock_input_api, MockOutputApi())
1877 self.assertEqual(1, len(warnings))
1878 self.assertTrue('base/stuff.h' in warnings[0].items)
1879
1880 def testModifyHeader(self):
1881 mock_input_api = MockInputApi()
1882 mock_input_api.files = [
1883 MockAffectedFile('base/stuff.h', '', action='M'),
1884 ]
1885 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1886 mock_input_api, MockOutputApi())
1887 self.assertEqual(0, len(warnings))
1888
1889 def testDeleteHeader(self):
1890 mock_input_api = MockInputApi()
1891 mock_input_api.files = [
1892 MockAffectedFile('base/stuff.h', '', action='D'),
1893 ]
1894 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1895 mock_input_api, MockOutputApi())
1896 self.assertEqual(0, len(warnings))
1897
1898 def testAddHeaderWithGn(self):
1899 mock_input_api = MockInputApi()
1900 mock_input_api.files = [
1901 MockAffectedFile('base/stuff.h', ''),
1902 MockAffectedFile('base/BUILD.gn', 'stuff.h'),
1903 ]
1904 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1905 mock_input_api, MockOutputApi())
1906 self.assertEqual(0, len(warnings))
1907
1908 def testAddHeaderWithGni(self):
1909 mock_input_api = MockInputApi()
1910 mock_input_api.files = [
1911 MockAffectedFile('base/stuff.h', ''),
1912 MockAffectedFile('base/files.gni', 'stuff.h'),
1913 ]
1914 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1915 mock_input_api, MockOutputApi())
1916 self.assertEqual(0, len(warnings))
1917
1918 def testAddHeaderWithOther(self):
1919 mock_input_api = MockInputApi()
1920 mock_input_api.files = [
1921 MockAffectedFile('base/stuff.h', ''),
1922 MockAffectedFile('base/stuff.cc', 'stuff.h'),
1923 ]
1924 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1925 mock_input_api, MockOutputApi())
1926 self.assertEqual(1, len(warnings))
1927
1928 def testAddHeaderWithWrongGn(self):
1929 mock_input_api = MockInputApi()
1930 mock_input_api.files = [
1931 MockAffectedFile('base/stuff.h', ''),
1932 MockAffectedFile('base/BUILD.gn', 'stuff_h'),
1933 ]
1934 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1935 mock_input_api, MockOutputApi())
1936 self.assertEqual(1, len(warnings))
1937
1938 def testAddHeadersWithGn(self):
1939 mock_input_api = MockInputApi()
1940 mock_input_api.files = [
1941 MockAffectedFile('base/stuff.h', ''),
1942 MockAffectedFile('base/another.h', ''),
1943 MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'),
1944 ]
1945 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1946 mock_input_api, MockOutputApi())
1947 self.assertEqual(0, len(warnings))
1948
1949 def testAddHeadersWithWrongGn(self):
1950 mock_input_api = MockInputApi()
1951 mock_input_api.files = [
1952 MockAffectedFile('base/stuff.h', ''),
1953 MockAffectedFile('base/another.h', ''),
1954 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'),
1955 ]
1956 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1957 mock_input_api, MockOutputApi())
1958 self.assertEqual(1, len(warnings))
1959 self.assertFalse('base/stuff.h' in warnings[0].items)
1960 self.assertTrue('base/another.h' in warnings[0].items)
1961
1962 def testAddHeadersWithWrongGn2(self):
1963 mock_input_api = MockInputApi()
1964 mock_input_api.files = [
1965 MockAffectedFile('base/stuff.h', ''),
1966 MockAffectedFile('base/another.h', ''),
1967 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'),
1968 ]
1969 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1970 mock_input_api, MockOutputApi())
1971 self.assertEqual(1, len(warnings))
1972 self.assertTrue('base/stuff.h' in warnings[0].items)
1973 self.assertTrue('base/another.h' in warnings[0].items)
1974
1975
Michael Giuffridad3bc8672018-10-25 22:48:021976class CorrectProductNameInMessagesTest(unittest.TestCase):
1977 def testProductNameInDesc(self):
1978 mock_input_api = MockInputApi()
1979 mock_input_api.files = [
1980 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1981 '<message name="Foo" desc="Welcome to Chrome">',
1982 ' Welcome to Chrome!',
1983 '</message>',
1984 ]),
1985 MockAffectedFile('chrome/app/chromium_strings.grd', [
1986 '<message name="Bar" desc="Welcome to Chrome">',
1987 ' Welcome to Chromium!',
1988 '</message>',
1989 ]),
1990 ]
1991 warnings = PRESUBMIT._CheckCorrectProductNameInMessages(
1992 mock_input_api, MockOutputApi())
1993 self.assertEqual(0, len(warnings))
1994
1995 def testChromeInChromium(self):
1996 mock_input_api = MockInputApi()
1997 mock_input_api.files = [
1998 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1999 '<message name="Foo" desc="Welcome to Chrome">',
2000 ' Welcome to Chrome!',
2001 '</message>',
2002 ]),
2003 MockAffectedFile('chrome/app/chromium_strings.grd', [
2004 '<message name="Bar" desc="Welcome to Chrome">',
2005 ' Welcome to Chrome!',
2006 '</message>',
2007 ]),
2008 ]
2009 warnings = PRESUBMIT._CheckCorrectProductNameInMessages(
2010 mock_input_api, MockOutputApi())
2011 self.assertEqual(1, len(warnings))
2012 self.assertTrue('chrome/app/chromium_strings.grd' in warnings[0].items[0])
2013
2014 def testChromiumInChrome(self):
2015 mock_input_api = MockInputApi()
2016 mock_input_api.files = [
2017 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2018 '<message name="Foo" desc="Welcome to Chrome">',
2019 ' Welcome to Chromium!',
2020 '</message>',
2021 ]),
2022 MockAffectedFile('chrome/app/chromium_strings.grd', [
2023 '<message name="Bar" desc="Welcome to Chrome">',
2024 ' Welcome to Chromium!',
2025 '</message>',
2026 ]),
2027 ]
2028 warnings = PRESUBMIT._CheckCorrectProductNameInMessages(
2029 mock_input_api, MockOutputApi())
2030 self.assertEqual(1, len(warnings))
2031 self.assertTrue(
2032 'chrome/app/google_chrome_strings.grd:2' in warnings[0].items[0])
2033
2034 def testMultipleInstances(self):
2035 mock_input_api = MockInputApi()
2036 mock_input_api.files = [
2037 MockAffectedFile('chrome/app/chromium_strings.grd', [
2038 '<message name="Bar" desc="Welcome to Chrome">',
2039 ' Welcome to Chrome!',
2040 '</message>',
2041 '<message name="Baz" desc="A correct message">',
2042 ' Chromium is the software you are using.',
2043 '</message>',
2044 '<message name="Bat" desc="An incorrect message">',
2045 ' Google Chrome is the software you are using.',
2046 '</message>',
2047 ]),
2048 ]
2049 warnings = PRESUBMIT._CheckCorrectProductNameInMessages(
2050 mock_input_api, MockOutputApi())
2051 self.assertEqual(1, len(warnings))
2052 self.assertTrue(
2053 'chrome/app/chromium_strings.grd:2' in warnings[0].items[0])
2054 self.assertTrue(
2055 'chrome/app/chromium_strings.grd:8' in warnings[0].items[1])
2056
2057 def testMultipleWarnings(self):
2058 mock_input_api = MockInputApi()
2059 mock_input_api.files = [
2060 MockAffectedFile('chrome/app/chromium_strings.grd', [
2061 '<message name="Bar" desc="Welcome to Chrome">',
2062 ' Welcome to Chrome!',
2063 '</message>',
2064 '<message name="Baz" desc="A correct message">',
2065 ' Chromium is the software you are using.',
2066 '</message>',
2067 '<message name="Bat" desc="An incorrect message">',
2068 ' Google Chrome is the software you are using.',
2069 '</message>',
2070 ]),
2071 MockAffectedFile('components/components_google_chrome_strings.grd', [
2072 '<message name="Bar" desc="Welcome to Chrome">',
2073 ' Welcome to Chrome!',
2074 '</message>',
2075 '<message name="Baz" desc="A correct message">',
2076 ' Chromium is the software you are using.',
2077 '</message>',
2078 '<message name="Bat" desc="An incorrect message">',
2079 ' Google Chrome is the software you are using.',
2080 '</message>',
2081 ]),
2082 ]
2083 warnings = PRESUBMIT._CheckCorrectProductNameInMessages(
2084 mock_input_api, MockOutputApi())
2085 self.assertEqual(2, len(warnings))
2086 self.assertTrue(
2087 'components/components_google_chrome_strings.grd:5'
2088 in warnings[0].items[0])
2089 self.assertTrue(
2090 'chrome/app/chromium_strings.grd:2' in warnings[1].items[0])
2091 self.assertTrue(
2092 'chrome/app/chromium_strings.grd:8' in warnings[1].items[1])
2093
2094
Ken Rockot9f668262018-12-21 18:56:362095class ServiceManifestOwnerTest(unittest.TestCase):
Ken Rockot9f668262018-12-21 18:56:362096 def testServiceManifestChangeNeedsSecurityOwner(self):
2097 mock_input_api = MockInputApi()
2098 mock_input_api.files = [
2099 MockAffectedFile('services/goat/public/cpp/manifest.cc',
2100 [
2101 '#include "services/goat/public/cpp/manifest.h"',
2102 'const service_manager::Manifest& GetManifest() {}',
2103 ])]
2104 mock_output_api = MockOutputApi()
Wez17c66962020-04-29 15:26:032105 errors = PRESUBMIT._CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362106 mock_input_api, mock_output_api)
2107 self.assertEqual(1, len(errors))
2108 self.assertEqual(
2109 'Found OWNERS files that need to be updated for IPC security review ' +
2110 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2111
2112 def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
2113 mock_input_api = MockInputApi()
2114 mock_input_api.files = [
2115 MockAffectedFile('some/non/service/thing/foo_manifest.cc',
2116 [
2117 'const char kNoEnforcement[] = "not a manifest!";',
2118 ])]
2119 mock_output_api = MockOutputApi()
Wez17c66962020-04-29 15:26:032120 errors = PRESUBMIT._CheckSecurityOwners(
2121 mock_input_api, mock_output_api)
2122 self.assertEqual([], errors)
2123
2124
2125class FuchsiaSecurityOwnerTest(unittest.TestCase):
2126 def testFidlChangeNeedsSecurityOwner(self):
2127 mock_input_api = MockInputApi()
2128 mock_input_api.files = [
2129 MockAffectedFile('potentially/scary/ipc.fidl',
2130 [
2131 'library test.fidl'
2132 ])]
2133 mock_output_api = MockOutputApi()
2134 errors = PRESUBMIT._CheckSecurityOwners(
2135 mock_input_api, mock_output_api)
2136 self.assertEqual(1, len(errors))
2137 self.assertEqual(
2138 'Found OWNERS files that need to be updated for IPC security review ' +
2139 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2140
2141 def testComponentManifestV1ChangeNeedsSecurityOwner(self):
2142 mock_input_api = MockInputApi()
2143 mock_input_api.files = [
2144 MockAffectedFile('potentially/scary/v2_manifest.cmx',
2145 [
2146 '{ "that is no": "manifest!" }'
2147 ])]
2148 mock_output_api = MockOutputApi()
2149 errors = PRESUBMIT._CheckSecurityOwners(
2150 mock_input_api, mock_output_api)
2151 self.assertEqual(1, len(errors))
2152 self.assertEqual(
2153 'Found OWNERS files that need to be updated for IPC security review ' +
2154 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2155
2156 def testComponentManifestV2NeedsSecurityOwner(self):
2157 mock_input_api = MockInputApi()
2158 mock_input_api.files = [
2159 MockAffectedFile('potentially/scary/v2_manifest.cml',
2160 [
2161 '{ "that is no": "manifest!" }'
2162 ])]
2163 mock_output_api = MockOutputApi()
2164 errors = PRESUBMIT._CheckSecurityOwners(
2165 mock_input_api, mock_output_api)
2166 self.assertEqual(1, len(errors))
2167 self.assertEqual(
2168 'Found OWNERS files that need to be updated for IPC security review ' +
2169 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2170
2171 def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2172 mock_input_api = MockInputApi()
2173 mock_input_api.files = [
2174 MockAffectedFile('some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',
2175 [
2176 'const char kNoEnforcement[] = "Security?!? Pah!";',
2177 ])]
2178 mock_output_api = MockOutputApi()
2179 errors = PRESUBMIT._CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362180 mock_input_api, mock_output_api)
2181 self.assertEqual([], errors)
2182
Daniel Cheng13ca61a882017-08-25 15:11:252183
Robert Sesek2c905332020-05-06 23:17:132184class SecurityChangeTest(unittest.TestCase):
2185 class _MockOwnersDB(object):
2186 def __init__(self):
2187 self.email_regexp = '.*'
2188
2189 def owners_rooted_at_file(self, f):
2190 return ['[email protected]', '[email protected]']
2191
2192 def _mockChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2193 def __MockOwnerAndReviewers(input_api, email_regexp, approval_needed=False):
2194 return [owner, reviewers]
2195 input_api.canned_checks.GetCodereviewOwnerAndReviewers = \
2196 __MockOwnerAndReviewers
2197
Alex Goughbc964dd2020-06-15 17:52:372198 def testDiffGetServiceSandboxType(self):
Robert Sesek2c905332020-05-06 23:17:132199 mock_input_api = MockInputApi()
2200 mock_input_api.files = [
2201 MockAffectedFile(
2202 'services/goat/teleporter_host.cc',
2203 [
Alex Goughbc964dd2020-06-15 17:52:372204 'template <>',
2205 'inline content::SandboxType',
2206 'content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {',
2207 '#if defined(OS_WIN)',
2208 ' return SandboxType::kGoaty;',
2209 '#else',
2210 ' return SandboxType::kNoSandbox;',
2211 '#endif // !defined(OS_WIN)',
2212 '}'
Robert Sesek2c905332020-05-06 23:17:132213 ]
2214 ),
2215 ]
2216 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2217 mock_input_api)
2218 self.assertEqual({
2219 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372220 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132221 ])},
2222 files_to_functions)
2223
2224 def testDiffRemovingLine(self):
2225 mock_input_api = MockInputApi()
2226 mock_file = MockAffectedFile('services/goat/teleporter_host.cc', '')
2227 mock_file._scm_diff = """--- old 2020-05-04 14:08:25.000000000 -0400
2228+++ new 2020-05-04 14:08:32.000000000 -0400
2229@@ -1,5 +1,4 @@
Alex Goughbc964dd2020-06-15 17:52:372230 template <>
2231 inline content::SandboxType
2232-content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {
2233 #if defined(OS_WIN)
2234 return SandboxType::kGoaty;
Robert Sesek2c905332020-05-06 23:17:132235"""
2236 mock_input_api.files = [mock_file]
2237 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2238 mock_input_api)
2239 self.assertEqual({
2240 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372241 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132242 ])},
2243 files_to_functions)
2244
2245 def testChangeOwnersMissing(self):
2246 mock_input_api = MockInputApi()
2247 mock_input_api.owners_db = self._MockOwnersDB()
2248 mock_input_api.is_committing = False
2249 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372250 MockAffectedFile('file.cc', ['GetServiceSandboxType<Goat>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132251 ]
2252 mock_output_api = MockOutputApi()
2253 self._mockChangeOwnerAndReviewers(
2254 mock_input_api, '[email protected]', ['[email protected]'])
2255 result = PRESUBMIT._CheckSecurityChanges(mock_input_api, mock_output_api)
2256 self.assertEquals(1, len(result))
2257 self.assertEquals(result[0].type, 'notify')
2258 self.assertEquals(result[0].message,
2259 'The following files change calls to security-sensive functions\n' \
2260 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2261 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372262 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132263
2264 def testChangeOwnersMissingAtCommit(self):
2265 mock_input_api = MockInputApi()
2266 mock_input_api.owners_db = self._MockOwnersDB()
2267 mock_input_api.is_committing = True
2268 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372269 MockAffectedFile('file.cc', ['GetServiceSandboxType<mojom::Goat>()'])
Robert Sesek2c905332020-05-06 23:17:132270 ]
2271 mock_output_api = MockOutputApi()
2272 self._mockChangeOwnerAndReviewers(
2273 mock_input_api, '[email protected]', ['[email protected]'])
2274 result = PRESUBMIT._CheckSecurityChanges(mock_input_api, mock_output_api)
2275 self.assertEquals(1, len(result))
2276 self.assertEquals(result[0].type, 'error')
2277 self.assertEquals(result[0].message,
2278 'The following files change calls to security-sensive functions\n' \
2279 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2280 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372281 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132282
2283 def testChangeOwnersPresent(self):
2284 mock_input_api = MockInputApi()
2285 mock_input_api.owners_db = self._MockOwnersDB()
2286 mock_input_api.files = [
2287 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2288 ]
2289 mock_output_api = MockOutputApi()
2290 self._mockChangeOwnerAndReviewers(
2291 mock_input_api, '[email protected]',
2292 ['[email protected]', '[email protected]'])
2293 result = PRESUBMIT._CheckSecurityChanges(mock_input_api, mock_output_api)
2294 self.assertEquals(0, len(result))
2295
2296 def testChangeOwnerIsSecurityOwner(self):
2297 mock_input_api = MockInputApi()
2298 mock_input_api.owners_db = self._MockOwnersDB()
2299 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372300 MockAffectedFile('file.cc', ['GetServiceSandboxType<T>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132301 ]
2302 mock_output_api = MockOutputApi()
2303 self._mockChangeOwnerAndReviewers(
2304 mock_input_api, '[email protected]', ['[email protected]'])
2305 result = PRESUBMIT._CheckSecurityChanges(mock_input_api, mock_output_api)
2306 self.assertEquals(1, len(result))
2307
2308
Mario Sanchez Prada2472cab2019-09-18 10:58:312309class BannedTypeCheckTest(unittest.TestCase):
Sylvain Defresnea8b73d252018-02-28 15:45:542310
Peter Kasting94a56c42019-10-25 21:54:042311 def testBannedCppFunctions(self):
2312 input_api = MockInputApi()
2313 input_api.files = [
2314 MockFile('some/cpp/problematic/file.cc',
2315 ['using namespace std;']),
Oksana Zhuravlovac8222d22019-12-19 19:21:162316 MockFile('third_party/blink/problematic/file.cc',
2317 ['GetInterfaceProvider()']),
Peter Kasting94a56c42019-10-25 21:54:042318 MockFile('some/cpp/ok/file.cc',
2319 ['using std::string;']),
Allen Bauer53b43fb12020-03-12 17:21:472320 MockFile('some/cpp/problematic/file2.cc',
2321 ['set_owned_by_client()']),
Peter Kasting94a56c42019-10-25 21:54:042322 ]
2323
Oksana Zhuravlovac8222d22019-12-19 19:21:162324 results = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi())
2325
2326 # warnings are results[0], errors are results[1]
2327 self.assertEqual(2, len(results))
2328 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2329 self.assertTrue(
2330 'third_party/blink/problematic/file.cc' in results[0].message)
2331 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
Allen Bauer53b43fb12020-03-12 17:21:472332 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
Peter Kasting94a56c42019-10-25 21:54:042333
Abhijeet Kandalkar1e7c2502019-10-29 15:05:452334 def testBannedBlinkDowncastHelpers(self):
2335 input_api = MockInputApi()
2336 input_api.files = [
2337 MockFile('some/cpp/problematic/file1.cc',
2338 ['DEFINE_TYPE_CASTS(ToType, FromType, from_argument,'
2339 'PointerPredicate(), ReferencePredicate());']),
2340 MockFile('some/cpp/problematic/file2.cc',
2341 ['bool is_test_ele = IsHTMLTestElement(n);']),
2342 MockFile('some/cpp/problematic/file3.cc',
2343 ['auto* html_test_ele = ToHTMLTestElement(n);']),
2344 MockFile('some/cpp/problematic/file4.cc',
2345 ['auto* html_test_ele_or_null = ToHTMLTestElementOrNull(n);']),
2346 MockFile('some/cpp/ok/file1.cc',
2347 ['bool is_test_ele = IsA<HTMLTestElement>(n);']),
2348 MockFile('some/cpp/ok/file2.cc',
2349 ['auto* html_test_ele = To<HTMLTestElement>(n);']),
2350 MockFile('some/cpp/ok/file3.cc',
2351 ['auto* html_test_ele_or_null = ',
2352 'DynamicTo<HTMLTestElement>(n);']),
2353 ]
2354
2355 # warnings are errors[0], errors are errors[1]
2356 errors = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi())
2357 self.assertEqual(2, len(errors))
2358 self.assertTrue('some/cpp/problematic/file1.cc' in errors[1].message)
2359 self.assertTrue('some/cpp/problematic/file2.cc' in errors[0].message)
2360 self.assertTrue('some/cpp/problematic/file3.cc' in errors[0].message)
2361 self.assertTrue('some/cpp/problematic/file4.cc' in errors[0].message)
2362 self.assertTrue('some/cpp/ok/file1.cc' not in errors[0].message)
2363 self.assertTrue('some/cpp/ok/file2.cc' not in errors[0].message)
2364 self.assertTrue('some/cpp/ok/file3.cc' not in errors[0].message)
2365
Peter K. Lee6c03ccff2019-07-15 14:40:052366 def testBannedIosObjcFunctions(self):
Sylvain Defresnea8b73d252018-02-28 15:45:542367 input_api = MockInputApi()
2368 input_api.files = [
2369 MockFile('some/ios/file.mm',
2370 ['TEST(SomeClassTest, SomeInteraction) {',
2371 '}']),
2372 MockFile('some/mac/file.mm',
2373 ['TEST(SomeClassTest, SomeInteraction) {',
2374 '}']),
2375 MockFile('another/ios_file.mm',
2376 ['class SomeTest : public testing::Test {};']),
Peter K. Lee6c03ccff2019-07-15 14:40:052377 MockFile('some/ios/file_egtest.mm',
2378 ['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
2379 MockFile('some/ios/file_unittest.mm',
2380 ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']),
Sylvain Defresnea8b73d252018-02-28 15:45:542381 ]
2382
2383 errors = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi())
2384 self.assertEqual(1, len(errors))
2385 self.assertTrue('some/ios/file.mm' in errors[0].message)
2386 self.assertTrue('another/ios_file.mm' in errors[0].message)
2387 self.assertTrue('some/mac/file.mm' not in errors[0].message)
Peter K. Lee6c03ccff2019-07-15 14:40:052388 self.assertTrue('some/ios/file_egtest.mm' in errors[0].message)
2389 self.assertTrue('some/ios/file_unittest.mm' not in errors[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542390
Carlos Knippschildab192b8c2019-04-08 20:02:382391 def testBannedMojoFunctions(self):
2392 input_api = MockInputApi()
2393 input_api.files = [
2394 MockFile('some/cpp/problematic/file.cc',
2395 ['mojo::DataPipe();']),
Oksana Zhuravlovafd247772019-05-16 16:57:292396 MockFile('some/cpp/problematic/file2.cc',
2397 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382398 MockFile('some/cpp/ok/file.cc',
2399 ['CreateDataPipe();']),
Kinuko Yasuda376c2ce12019-04-16 01:20:372400 MockFile('some/cpp/ok/file2.cc',
2401 ['mojo::DataPipeDrainer();']),
Oksana Zhuravlovafd247772019-05-16 16:57:292402 MockFile('third_party/blink/ok/file3.cc',
2403 ['mojo::ConvertTo<>']),
2404 MockFile('content/renderer/ok/file3.cc',
2405 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382406 ]
2407
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222408 results = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi())
2409
2410 # warnings are results[0], errors are results[1]
2411 self.assertEqual(2, len(results))
2412 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2413 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
2414 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
2415 self.assertTrue('some/cpp/ok/file2.cc' not in results[1].message)
2416 self.assertTrue('third_party/blink/ok/file3.cc' not in results[0].message)
2417 self.assertTrue('content/renderer/ok/file3.cc' not in results[0].message)
Carlos Knippschildab192b8c2019-04-08 20:02:382418
Mario Sanchez Prada2472cab2019-09-18 10:58:312419 def testDeprecatedMojoTypes(self):
Mario Sanchez Pradacec9cef2019-12-15 11:54:572420 ok_paths = ['components/arc']
2421 warning_paths = ['some/cpp']
Mario Sanchez Pradaaab91382019-12-19 08:57:092422 error_paths = ['third_party/blink', 'content']
Mario Sanchez Prada2472cab2019-09-18 10:58:312423 test_cases = [
2424 {
2425 'type': 'mojo::AssociatedBinding<>;',
2426 'file': 'file1.c'
2427 },
2428 {
2429 'type': 'mojo::AssociatedBindingSet<>;',
2430 'file': 'file2.c'
2431 },
2432 {
2433 'type': 'mojo::AssociatedInterfacePtr<>',
2434 'file': 'file3.cc'
2435 },
2436 {
2437 'type': 'mojo::AssociatedInterfacePtrInfo<>',
2438 'file': 'file4.cc'
2439 },
2440 {
2441 'type': 'mojo::AssociatedInterfaceRequest<>',
2442 'file': 'file5.cc'
2443 },
2444 {
2445 'type': 'mojo::Binding<>',
2446 'file': 'file6.cc'
2447 },
2448 {
2449 'type': 'mojo::BindingSet<>',
2450 'file': 'file7.cc'
2451 },
2452 {
2453 'type': 'mojo::InterfacePtr<>',
2454 'file': 'file8.cc'
2455 },
2456 {
2457 'type': 'mojo::InterfacePtrInfo<>',
2458 'file': 'file9.cc'
2459 },
2460 {
2461 'type': 'mojo::InterfaceRequest<>',
2462 'file': 'file10.cc'
2463 },
2464 {
2465 'type': 'mojo::MakeRequest()',
2466 'file': 'file11.cc'
2467 },
2468 {
2469 'type': 'mojo::MakeRequestAssociatedWithDedicatedPipe()',
2470 'file': 'file12.cc'
2471 },
2472 {
2473 'type': 'mojo::MakeStrongBinding()<>',
2474 'file': 'file13.cc'
2475 },
2476 {
2477 'type': 'mojo::MakeStrongAssociatedBinding()<>',
2478 'file': 'file14.cc'
2479 },
2480 {
Gyuyoung Kim4952ba62020-07-07 07:33:442481 'type': 'mojo::StrongAssociatedBinding<>',
Mario Sanchez Prada2472cab2019-09-18 10:58:312482 'file': 'file15.cc'
2483 },
2484 {
Gyuyoung Kim4952ba62020-07-07 07:33:442485 'type': 'mojo::StrongBinding<>',
Mario Sanchez Prada2472cab2019-09-18 10:58:312486 'file': 'file16.cc'
2487 },
Gyuyoung Kim4952ba62020-07-07 07:33:442488 {
2489 'type': 'mojo::StrongAssociatedBindingSet<>',
2490 'file': 'file17.cc'
2491 },
2492 {
2493 'type': 'mojo::StrongBindingSet<>',
2494 'file': 'file18.cc'
2495 },
Mario Sanchez Prada2472cab2019-09-18 10:58:312496 ]
2497
2498 # Build the list of MockFiles considering paths that should trigger warnings
Mario Sanchez Pradacec9cef2019-12-15 11:54:572499 # as well as paths that should trigger errors.
Mario Sanchez Prada2472cab2019-09-18 10:58:312500 input_api = MockInputApi()
2501 input_api.files = []
2502 for test_case in test_cases:
2503 for path in ok_paths:
2504 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2505 [test_case['type']]))
2506 for path in warning_paths:
2507 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2508 [test_case['type']]))
Mario Sanchez Pradacec9cef2019-12-15 11:54:572509 for path in error_paths:
2510 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2511 [test_case['type']]))
Mario Sanchez Prada2472cab2019-09-18 10:58:312512
2513 results = PRESUBMIT._CheckNoDeprecatedMojoTypes(input_api, MockOutputApi())
2514
Mario Sanchez Pradacec9cef2019-12-15 11:54:572515 # warnings are results[0], errors are results[1]
2516 self.assertEqual(2, len(results))
Mario Sanchez Prada2472cab2019-09-18 10:58:312517
2518 for test_case in test_cases:
Mario Sanchez Pradacec9cef2019-12-15 11:54:572519 # Check that no warnings nor errors have been triggered for these paths.
Mario Sanchez Prada2472cab2019-09-18 10:58:312520 for path in ok_paths:
2521 self.assertFalse(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572522 self.assertFalse(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312523
2524 # Check warnings have been triggered for these paths.
2525 for path in warning_paths:
2526 self.assertTrue(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572527 self.assertFalse(path in results[1].message)
2528
2529 # Check errors have been triggered for these paths.
2530 for path in error_paths:
2531 self.assertFalse(path in results[0].message)
2532 self.assertTrue(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312533
Sylvain Defresnea8b73d252018-02-28 15:45:542534
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272535class NoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:242536 def testTruePositives(self):
2537 mock_input_api = MockInputApi()
2538 mock_input_api.files = [
2539 MockFile('some/path/foo.cc', ['foo_for_testing();']),
2540 MockFile('some/path/foo.mm', ['FooForTesting();']),
2541 MockFile('some/path/foo.cxx', ['FooForTests();']),
2542 MockFile('some/path/foo.cpp', ['foo_for_test();']),
2543 ]
2544
2545 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
2546 mock_input_api, MockOutputApi())
2547 self.assertEqual(1, len(results))
2548 self.assertEqual(4, len(results[0].items))
2549 self.assertTrue('foo.cc' in results[0].items[0])
2550 self.assertTrue('foo.mm' in results[0].items[1])
2551 self.assertTrue('foo.cxx' in results[0].items[2])
2552 self.assertTrue('foo.cpp' in results[0].items[3])
2553
2554 def testFalsePositives(self):
2555 mock_input_api = MockInputApi()
2556 mock_input_api.files = [
2557 MockFile('some/path/foo.h', ['foo_for_testing();']),
2558 MockFile('some/path/foo.mm', ['FooForTesting() {']),
2559 MockFile('some/path/foo.cc', ['::FooForTests();']),
2560 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
2561 ]
2562
2563 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
2564 mock_input_api, MockOutputApi())
2565 self.assertEqual(0, len(results))
2566
2567
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272568class NoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:232569 def testTruePositives(self):
2570 mock_input_api = MockInputApi()
2571 mock_input_api.files = [
2572 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
2573 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392574 MockFile('dir/java/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232575 MockFile('dir/java/src/mult.java', [
2576 'int x = SomethingLongHere()',
2577 ' * SomethingLongHereForTesting();'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392578 ])
Vaclav Brozek7dbc28c2018-03-27 08:35:232579 ]
2580
2581 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctionsJava(
2582 mock_input_api, MockOutputApi())
2583 self.assertEqual(1, len(results))
2584 self.assertEqual(4, len(results[0].items))
2585 self.assertTrue('foo.java' in results[0].items[0])
2586 self.assertTrue('bar.java' in results[0].items[1])
2587 self.assertTrue('baz.java' in results[0].items[2])
2588 self.assertTrue('mult.java' in results[0].items[3])
2589
2590 def testFalsePositives(self):
2591 mock_input_api = MockInputApi()
2592 mock_input_api.files = [
2593 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
2594 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
2595 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
2596 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392597 MockFile('dir/javatests/src/baz.java', ['FooForTest(', 'y', ');']),
2598 MockFile('dir/junit/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232599 MockFile('dir/junit/src/javadoc.java', [
2600 '/** Use FooForTest(); to obtain foo in tests.'
2601 ' */'
2602 ]),
2603 MockFile('dir/junit/src/javadoc2.java', [
2604 '/** ',
2605 ' * Use FooForTest(); to obtain foo in tests.'
2606 ' */'
2607 ]),
2608 ]
2609
2610 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctionsJava(
2611 mock_input_api, MockOutputApi())
2612 self.assertEqual(0, len(results))
2613
2614
Mohamed Heikald048240a2019-11-12 16:57:372615class NewImagesWarningTest(unittest.TestCase):
2616 def testTruePositives(self):
2617 mock_input_api = MockInputApi()
2618 mock_input_api.files = [
2619 MockFile('dir/android/res/drawable/foo.png', []),
2620 MockFile('dir/android/res/drawable-v21/bar.svg', []),
2621 MockFile('dir/android/res/mipmap-v21-en/baz.webp', []),
2622 MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png', []),
2623 ]
2624
2625 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2626 self.assertEqual(1, len(results))
2627 self.assertEqual(4, len(results[0].items))
2628 self.assertTrue('foo.png' in results[0].items[0].LocalPath())
2629 self.assertTrue('bar.svg' in results[0].items[1].LocalPath())
2630 self.assertTrue('baz.webp' in results[0].items[2].LocalPath())
2631 self.assertTrue('foobar.png' in results[0].items[3].LocalPath())
2632
2633 def testFalsePositives(self):
2634 mock_input_api = MockInputApi()
2635 mock_input_api.files = [
2636 MockFile('dir/pngs/README.md', []),
2637 MockFile('java/test/res/drawable/foo.png', []),
2638 MockFile('third_party/blink/foo.png', []),
2639 MockFile('dir/third_party/libpng/src/foo.cc', ['foobar']),
2640 MockFile('dir/resources.webp/.gitignore', ['foo.png']),
2641 ]
2642
2643 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2644 self.assertEqual(0, len(results))
2645
2646
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272647class CheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:052648 def testTruePositivesNullptr(self):
2649 mock_input_api = MockInputApi()
2650 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162651 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
2652 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
Vaclav Brozek851d9602018-04-04 16:13:052653 ]
2654
2655 results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi())
2656 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162657 self.assertTrue('nullptr' in results[0].message)
Vaclav Brozek851d9602018-04-04 16:13:052658 self.assertEqual(2, len(results[0].items))
2659 self.assertTrue('baz.cc' in results[0].items[0])
2660 self.assertTrue('baz-p.cc' in results[0].items[1])
2661
2662 def testTruePositivesConstructor(self):
Vaclav Brozek52e18bf2018-04-03 07:05:242663 mock_input_api = MockInputApi()
2664 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162665 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
2666 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
2667 MockFile('dir/mult.cc', [
Vaclav Brozek95face62018-04-04 14:15:112668 'return',
2669 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
2670 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162671 MockFile('dir/mult2.cc', [
Vaclav Brozek95face62018-04-04 14:15:112672 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
2673 ' std::unique_ptr<T>(foo);'
2674 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162675 MockFile('dir/mult3.cc', [
Vaclav Brozek95face62018-04-04 14:15:112676 'bar = std::unique_ptr<T>(',
2677 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
2678 ]),
Vaclav Brozekb7fadb692018-08-30 06:39:532679 MockFile('dir/multi_arg.cc', [
2680 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']),
Vaclav Brozek52e18bf2018-04-03 07:05:242681 ]
2682
2683 results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052684 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162685 self.assertTrue('std::make_unique' in results[0].message)
Vaclav Brozekb7fadb692018-08-30 06:39:532686 self.assertEqual(6, len(results[0].items))
Vaclav Brozek851d9602018-04-04 16:13:052687 self.assertTrue('foo.cc' in results[0].items[0])
2688 self.assertTrue('bar.mm' in results[0].items[1])
2689 self.assertTrue('mult.cc' in results[0].items[2])
2690 self.assertTrue('mult2.cc' in results[0].items[3])
2691 self.assertTrue('mult3.cc' in results[0].items[4])
Vaclav Brozekb7fadb692018-08-30 06:39:532692 self.assertTrue('multi_arg.cc' in results[0].items[5])
Vaclav Brozek52e18bf2018-04-03 07:05:242693
2694 def testFalsePositives(self):
2695 mock_input_api = MockInputApi()
2696 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162697 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
2698 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
2699 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
2700 MockFile('dir/baz.cc', [
Vaclav Brozek52e18bf2018-04-03 07:05:242701 'std::unique_ptr<T> result = std::make_unique<T>();'
2702 ]),
Vaclav Brozeka54c528b2018-04-06 19:23:552703 MockFile('dir/baz2.cc', [
2704 'std::unique_ptr<T> result = std::make_unique<T>('
2705 ]),
2706 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
2707 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
Vaclav Brozekb7fadb692018-08-30 06:39:532708
2709 # Two-argument invocation of std::unique_ptr is exempt because there is
2710 # no equivalent using std::make_unique.
2711 MockFile('dir/multi_arg.cc', [
2712 'auto p = std::unique_ptr<T, D>(new T(), D());']),
Vaclav Brozek52e18bf2018-04-03 07:05:242713 ]
2714
2715 results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi())
2716 self.assertEqual(0, len(results))
2717
Danil Chapovalov3518f362018-08-11 16:13:432718class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
2719 def testBlocksDirectIncludes(self):
2720 mock_input_api = MockInputApi()
2721 mock_input_api.files = [
2722 MockFile('dir/foo_win.cc', ['#include "shlwapi.h"']),
2723 MockFile('dir/bar.h', ['#include <propvarutil.h>']),
2724 MockFile('dir/baz.h', ['#include <atlbase.h>']),
2725 MockFile('dir/jumbo.h', ['#include "sphelper.h"']),
2726 ]
2727 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2728 self.assertEquals(1, len(results))
2729 self.assertEquals(4, len(results[0].items))
2730 self.assertTrue('StrCat' in results[0].message)
2731 self.assertTrue('foo_win.cc' in results[0].items[0])
2732 self.assertTrue('bar.h' in results[0].items[1])
2733 self.assertTrue('baz.h' in results[0].items[2])
2734 self.assertTrue('jumbo.h' in results[0].items[3])
2735
2736 def testAllowsToIncludeWrapper(self):
2737 mock_input_api = MockInputApi()
2738 mock_input_api.files = [
2739 MockFile('dir/baz_win.cc', ['#include "base/win/shlwapi.h"']),
2740 MockFile('dir/baz-win.h', ['#include "base/win/atl.h"']),
2741 ]
2742 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2743 self.assertEquals(0, len(results))
2744
2745 def testAllowsToCreateWrapper(self):
2746 mock_input_api = MockInputApi()
2747 mock_input_api.files = [
2748 MockFile('base/win/shlwapi.h', [
2749 '#include <shlwapi.h>',
2750 '#include "base/win/windows_defines.inc"']),
2751 ]
2752 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2753 self.assertEquals(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:242754
Mustafa Emre Acer51f2f742020-03-09 19:41:122755
Rainhard Findlingfc31844c52020-05-15 09:58:262756class StringTest(unittest.TestCase):
2757 """Tests ICU syntax check and translation screenshots check."""
2758
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142759 # An empty grd file.
2760 OLD_GRD_CONTENTS = """<?xml version="1.0" encoding="UTF-8"?>
2761 <grit latest_public_release="1" current_release="1">
2762 <release seq="1">
2763 <messages></messages>
2764 </release>
2765 </grit>
2766 """.splitlines()
2767 # A grd file with a single message.
2768 NEW_GRD_CONTENTS1 = """<?xml version="1.0" encoding="UTF-8"?>
2769 <grit latest_public_release="1" current_release="1">
2770 <release seq="1">
2771 <messages>
2772 <message name="IDS_TEST1">
2773 Test string 1
2774 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482775 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE1"
2776 translateable="false">
2777 Non translateable message 1, should be ignored
2778 </message>
Mustafa Emre Acered1a48962020-06-30 19:15:392779 <message name="IDS_TEST_STRING_ACCESSIBILITY"
Mustafa Emre Acerd3ca8be2020-07-07 22:35:342780 is_accessibility_with_no_ui="true">
Mustafa Emre Acered1a48962020-06-30 19:15:392781 Accessibility label 1, should be ignored
2782 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142783 </messages>
2784 </release>
2785 </grit>
2786 """.splitlines()
2787 # A grd file with two messages.
2788 NEW_GRD_CONTENTS2 = """<?xml version="1.0" encoding="UTF-8"?>
2789 <grit latest_public_release="1" current_release="1">
2790 <release seq="1">
2791 <messages>
2792 <message name="IDS_TEST1">
2793 Test string 1
2794 </message>
2795 <message name="IDS_TEST2">
2796 Test string 2
2797 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482798 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE2"
2799 translateable="false">
2800 Non translateable message 2, should be ignored
2801 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142802 </messages>
2803 </release>
2804 </grit>
2805 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:262806 # A grd file with one ICU syntax message without syntax errors.
2807 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1 = """<?xml version="1.0" encoding="UTF-8"?>
2808 <grit latest_public_release="1" current_release="1">
2809 <release seq="1">
2810 <messages>
2811 <message name="IDS_TEST1">
2812 {NUM, plural,
2813 =1 {Test text for numeric one}
2814 other {Test text for plural with {NUM} as number}}
2815 </message>
2816 </messages>
2817 </release>
2818 </grit>
2819 """.splitlines()
2820 # A grd file with one ICU syntax message without syntax errors.
2821 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2 = """<?xml version="1.0" encoding="UTF-8"?>
2822 <grit latest_public_release="1" current_release="1">
2823 <release seq="1">
2824 <messages>
2825 <message name="IDS_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 </messages>
2831 </release>
2832 </grit>
2833 """.splitlines()
2834 # A grd file with one ICU syntax message with syntax errors (misses a comma).
2835 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
2836 <grit latest_public_release="1" current_release="1">
2837 <release seq="1">
2838 <messages>
2839 <message name="IDS_TEST1">
2840 {NUM, plural
2841 =1 {Test text for numeric one}
2842 other {Test text for plural with {NUM} as number}}
2843 </message>
2844 </messages>
2845 </release>
2846 </grit>
2847 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142848
meacerff8a9b62019-12-10 19:43:582849 OLD_GRDP_CONTENTS = (
2850 '<?xml version="1.0" encoding="utf-8"?>',
2851 '<grit-part>',
2852 '</grit-part>'
2853 )
2854
2855 NEW_GRDP_CONTENTS1 = (
2856 '<?xml version="1.0" encoding="utf-8"?>',
2857 '<grit-part>',
2858 '<message name="IDS_PART_TEST1">',
2859 'Part string 1',
2860 '</message>',
2861 '</grit-part>')
2862
2863 NEW_GRDP_CONTENTS2 = (
2864 '<?xml version="1.0" encoding="utf-8"?>',
2865 '<grit-part>',
2866 '<message name="IDS_PART_TEST1">',
2867 'Part string 1',
2868 '</message>',
2869 '<message name="IDS_PART_TEST2">',
2870 'Part string 2',
2871 '</message>',
2872 '</grit-part>')
2873
Rainhard Findlingfc31844c52020-05-15 09:58:262874 # A grdp file with one ICU syntax message without syntax errors.
2875 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = (
2876 '<?xml version="1.0" encoding="utf-8"?>',
2877 '<grit-part>',
2878 '<message name="IDS_PART_TEST1">',
2879 '{NUM, plural,',
2880 '=1 {Test text for numeric one}',
2881 'other {Test text for plural with {NUM} as number}}',
2882 '</message>',
2883 '</grit-part>')
2884 # A grdp file with one ICU syntax message without syntax errors.
2885 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2 = (
2886 '<?xml version="1.0" encoding="utf-8"?>',
2887 '<grit-part>',
2888 '<message name="IDS_PART_TEST1">',
2889 '{NUM, plural,',
2890 '=1 {Different test text for numeric one}',
2891 'other {Different test text for plural with {NUM} as number}}',
2892 '</message>',
2893 '</grit-part>')
2894
2895 # A grdp file with one ICU syntax message with syntax errors (superfluent
2896 # whitespace).
2897 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR = (
2898 '<?xml version="1.0" encoding="utf-8"?>',
2899 '<grit-part>',
2900 '<message name="IDS_PART_TEST1">',
2901 '{NUM, plural,',
2902 '= 1 {Test text for numeric one}',
2903 'other {Test text for plural with {NUM} as number}}',
2904 '</message>',
2905 '</grit-part>')
2906
Mustafa Emre Acerc8a012d2018-07-31 00:00:392907 DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
2908 'changelist. Run '
2909 'tools/translate/upload_screenshots.py to '
2910 'upload them instead:')
2911 GENERATE_SIGNATURES_MESSAGE = ('You are adding or modifying UI strings.\n'
2912 'To ensure the best translations, take '
2913 'screenshots of the relevant UI '
2914 '(https://g.co/chrome/translation) and add '
2915 'these files to your changelist:')
2916 REMOVE_SIGNATURES_MESSAGE = ('You removed strings associated with these '
2917 'files. Remove:')
Rainhard Findlingfc31844c52020-05-15 09:58:262918 ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
2919 'strings (problems or feedback? Contact '
2920 '[email protected]):')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142921
2922 def makeInputApi(self, files):
2923 input_api = MockInputApi()
2924 input_api.files = files
meacere7be7532019-10-02 17:41:032925 # Override os_path.exists because the presubmit uses the actual
2926 # os.path.exists.
2927 input_api.CreateMockFileInPath(
2928 [x.LocalPath() for x in input_api.AffectedFiles(include_deletes=True)])
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142929 return input_api
2930
meacerff8a9b62019-12-10 19:43:582931 """ CL modified and added messages, but didn't add any screenshots."""
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142932 def testNoScreenshots(self):
meacerff8a9b62019-12-10 19:43:582933 # No new strings (file contents same). Should not warn.
2934 input_api = self.makeInputApi([
2935 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
2936 self.NEW_GRD_CONTENTS1, action='M'),
2937 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1,
2938 self.NEW_GRDP_CONTENTS1, action='M')])
Rainhard Findlingfc31844c52020-05-15 09:58:262939 warnings = PRESUBMIT._CheckStrings(input_api,
meacerff8a9b62019-12-10 19:43:582940 MockOutputApi())
2941 self.assertEqual(0, len(warnings))
2942
2943 # Add two new strings. Should have two warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142944 input_api = self.makeInputApi([
2945 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582946 self.NEW_GRD_CONTENTS1, action='M'),
2947 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2948 self.NEW_GRDP_CONTENTS1, action='M')])
Rainhard Findlingfc31844c52020-05-15 09:58:262949 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142950 MockOutputApi())
2951 self.assertEqual(1, len(warnings))
2952 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerc6ed2682020-07-07 07:24:002953 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012954 self.assertEqual([
meacerff8a9b62019-12-10 19:43:582955 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2956 os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
2957 warnings[0].items)
Mustafa Emre Acer36eaad52019-11-12 23:03:342958
meacerff8a9b62019-12-10 19:43:582959 # Add four new strings. Should have four warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:212960 input_api = self.makeInputApi([
2961 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582962 self.OLD_GRD_CONTENTS, action='M'),
2963 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2964 self.OLD_GRDP_CONTENTS, action='M')])
Rainhard Findlingfc31844c52020-05-15 09:58:262965 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:212966 MockOutputApi())
2967 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:002968 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:212969 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:582970 self.assertEqual([
2971 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2972 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2973 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
2974 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
2975 ], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:212976
meacerff8a9b62019-12-10 19:43:582977 def testPngAddedSha1NotAdded(self):
2978 # CL added one new message in a grd file and added the png file associated
2979 # with it, but did not add the corresponding sha1 file. This should warn
2980 # twice:
2981 # - Once for the added png file (because we don't want developers to upload
2982 # actual images)
2983 # - Once for the missing .sha1 file
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142984 input_api = self.makeInputApi([
Mustafa Emre Acerea3e57a2018-12-17 23:51:012985 MockAffectedFile(
2986 'test.grd',
2987 self.NEW_GRD_CONTENTS1,
2988 self.OLD_GRD_CONTENTS,
2989 action='M'),
2990 MockAffectedFile(
2991 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
2992 ])
Rainhard Findlingfc31844c52020-05-15 09:58:262993 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142994 MockOutputApi())
2995 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:002996 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142997 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012998 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
2999 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003000 self.assertEqual('error', warnings[1].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143001 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013002 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3003 warnings[1].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143004
meacerff8a9b62019-12-10 19:43:583005 # CL added two messages (one in grd, one in grdp) and added the png files
3006 # associated with the messages, but did not add the corresponding sha1
3007 # files. This should warn twice:
3008 # - Once for the added png files (because we don't want developers to upload
3009 # actual images)
3010 # - Once for the missing .sha1 files
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143011 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583012 # Modified files:
Mustafa Emre Acer36eaad52019-11-12 23:03:343013 MockAffectedFile(
3014 'test.grd',
meacerff8a9b62019-12-10 19:43:583015 self.NEW_GRD_CONTENTS1,
Mustafa Emre Acer36eaad52019-11-12 23:03:343016 self.OLD_GRD_CONTENTS,
meacer2308d0742019-11-12 18:15:423017 action='M'),
Mustafa Emre Acer12e7fee2019-11-18 18:49:553018 MockAffectedFile(
meacerff8a9b62019-12-10 19:43:583019 'part.grdp',
3020 self.NEW_GRDP_CONTENTS1,
3021 self.OLD_GRDP_CONTENTS,
3022 action='M'),
3023 # Added files:
3024 MockAffectedFile(
3025 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A'),
3026 MockAffectedFile(
3027 os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary',
3028 action='A')
Mustafa Emre Acerad8fb082019-11-19 04:24:213029 ])
Rainhard Findlingfc31844c52020-05-15 09:58:263030 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213031 MockOutputApi())
3032 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003033 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213034 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583035 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png'),
3036 os.path.join('test_grd', 'IDS_TEST1.png')],
Mustafa Emre Acerad8fb082019-11-19 04:24:213037 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003038 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213039 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
meacerff8a9b62019-12-10 19:43:583040 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3041 os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3042 warnings[1].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213043
3044 def testScreenshotsWithSha1(self):
meacerff8a9b62019-12-10 19:43:583045 # CL added four messages (two each in a grd and grdp) and their
3046 # corresponding .sha1 files. No warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213047 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583048 # Modified files:
Mustafa Emre Acerad8fb082019-11-19 04:24:213049 MockAffectedFile(
3050 'test.grd',
3051 self.NEW_GRD_CONTENTS2,
3052 self.OLD_GRD_CONTENTS,
Mustafa Emre Acer12e7fee2019-11-18 18:49:553053 action='M'),
meacerff8a9b62019-12-10 19:43:583054 MockAffectedFile(
3055 'part.grdp',
3056 self.NEW_GRDP_CONTENTS2,
3057 self.OLD_GRDP_CONTENTS,
3058 action='M'),
3059 # Added files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013060 MockFile(
3061 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3062 'binary',
3063 action='A'),
3064 MockFile(
3065 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3066 'binary',
meacerff8a9b62019-12-10 19:43:583067 action='A'),
3068 MockFile(
3069 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3070 'binary',
3071 action='A'),
3072 MockFile(
3073 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3074 'binary',
3075 action='A'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013076 ])
Rainhard Findlingfc31844c52020-05-15 09:58:263077 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143078 MockOutputApi())
3079 self.assertEqual([], warnings)
3080
3081 def testScreenshotsRemovedWithSha1(self):
meacerff8a9b62019-12-10 19:43:583082 # Replace new contents with old contents in grd and grp files, removing
3083 # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3084 # Should warn to remove the sha1 files associated with these strings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143085 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583086 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013087 MockAffectedFile(
3088 'test.grd',
meacerff8a9b62019-12-10 19:43:583089 self.OLD_GRD_CONTENTS, # new_contents
3090 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013091 action='M'),
meacerff8a9b62019-12-10 19:43:583092 MockAffectedFile(
3093 'part.grdp',
3094 self.OLD_GRDP_CONTENTS, # new_contents
3095 self.NEW_GRDP_CONTENTS2, # old_contents
3096 action='M'),
3097 # Unmodified files:
3098 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
3099 MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', ''),
3100 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3101 'binary', ''),
3102 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3103 'binary', '')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013104 ])
Rainhard Findlingfc31844c52020-05-15 09:58:263105 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143106 MockOutputApi())
3107 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003108 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143109 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013110 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583111 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3112 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013113 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3114 os.path.join('test_grd', 'IDS_TEST2.png.sha1')
3115 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143116
meacerff8a9b62019-12-10 19:43:583117 # Same as above, but this time one of the .sha1 files is also removed.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143118 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583119 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013120 MockAffectedFile(
3121 'test.grd',
meacerff8a9b62019-12-10 19:43:583122 self.OLD_GRD_CONTENTS, # new_contents
3123 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013124 action='M'),
meacerff8a9b62019-12-10 19:43:583125 MockAffectedFile(
3126 'part.grdp',
3127 self.OLD_GRDP_CONTENTS, # new_contents
3128 self.NEW_GRDP_CONTENTS2, # old_contents
3129 action='M'),
3130 # Unmodified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013131 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
meacerff8a9b62019-12-10 19:43:583132 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3133 'binary', ''),
3134 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013135 MockAffectedFile(
3136 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3137 '',
3138 'old_contents',
meacerff8a9b62019-12-10 19:43:583139 action='D'),
3140 MockAffectedFile(
3141 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3142 '',
3143 'old_contents',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013144 action='D')
3145 ])
Rainhard Findlingfc31844c52020-05-15 09:58:263146 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143147 MockOutputApi())
3148 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003149 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143150 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583151 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3152 os.path.join('test_grd', 'IDS_TEST1.png.sha1')
3153 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143154
meacerff8a9b62019-12-10 19:43:583155 # Remove all sha1 files. There should be no warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143156 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583157 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013158 MockAffectedFile(
3159 'test.grd',
3160 self.OLD_GRD_CONTENTS,
3161 self.NEW_GRD_CONTENTS2,
3162 action='M'),
meacerff8a9b62019-12-10 19:43:583163 MockAffectedFile(
3164 'part.grdp',
3165 self.OLD_GRDP_CONTENTS,
3166 self.NEW_GRDP_CONTENTS2,
3167 action='M'),
3168 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013169 MockFile(
3170 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3171 'binary',
3172 action='D'),
3173 MockFile(
3174 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3175 'binary',
meacerff8a9b62019-12-10 19:43:583176 action='D'),
3177 MockFile(
3178 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3179 'binary',
3180 action='D'),
3181 MockFile(
3182 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3183 'binary',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013184 action='D')
3185 ])
Rainhard Findlingfc31844c52020-05-15 09:58:263186 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143187 MockOutputApi())
3188 self.assertEqual([], warnings)
3189
Rainhard Findlingfc31844c52020-05-15 09:58:263190 def testIcuSyntax(self):
3191 # Add valid ICU syntax string. Should not raise an error.
3192 input_api = self.makeInputApi([
3193 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3194 self.NEW_GRD_CONTENTS1, action='M'),
3195 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3196 self.NEW_GRDP_CONTENTS1, action='M')])
3197 results = PRESUBMIT._CheckStrings(input_api, MockOutputApi())
3198 # We expect no ICU syntax errors.
3199 icu_errors = [e for e in results
3200 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3201 self.assertEqual(0, len(icu_errors))
3202
3203 # Valid changes in ICU syntax. Should not raise an error.
3204 input_api = self.makeInputApi([
3205 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3206 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3207 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3208 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
3209 results = PRESUBMIT._CheckStrings(input_api, MockOutputApi())
3210 # We expect no ICU syntax errors.
3211 icu_errors = [e for e in results
3212 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3213 self.assertEqual(0, len(icu_errors))
3214
3215 # Add invalid ICU syntax strings. Should raise two errors.
3216 input_api = self.makeInputApi([
3217 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3218 self.NEW_GRD_CONTENTS1, action='M'),
3219 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3220 self.NEW_GRD_CONTENTS1, action='M')])
3221 results = PRESUBMIT._CheckStrings(input_api, MockOutputApi())
3222 # We expect 2 ICU syntax errors.
3223 icu_errors = [e for e in results
3224 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3225 self.assertEqual(1, len(icu_errors))
3226 self.assertEqual([
3227 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3228 'ICU syntax.',
3229 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3230 ], icu_errors[0].items)
3231
3232 # Change two strings to have ICU syntax errors. Should raise two errors.
3233 input_api = self.makeInputApi([
3234 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3235 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3236 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3237 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
3238 results = PRESUBMIT._CheckStrings(input_api, MockOutputApi())
3239 # We expect 2 ICU syntax errors.
3240 icu_errors = [e for e in results
3241 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3242 self.assertEqual(1, len(icu_errors))
3243 self.assertEqual([
3244 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3245 'ICU syntax.',
3246 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3247 ], icu_errors[0].items)
3248
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143249
Mustafa Emre Acer51f2f742020-03-09 19:41:123250class TranslationExpectationsTest(unittest.TestCase):
3251 ERROR_MESSAGE_FORMAT = (
3252 "Failed to get a list of translatable grd files. "
3253 "This happens when:\n"
3254 " - One of the modified grd or grdp files cannot be parsed or\n"
3255 " - %s is not updated.\n"
3256 "Stack:\n"
3257 )
3258 REPO_ROOT = os.path.join('tools', 'translation', 'testdata')
3259 # This lists all .grd files under REPO_ROOT.
3260 EXPECTATIONS = os.path.join(REPO_ROOT,
3261 "translation_expectations.pyl")
3262 # This lists all .grd files under REPO_ROOT except unlisted.grd.
3263 EXPECTATIONS_WITHOUT_UNLISTED_FILE = os.path.join(
3264 REPO_ROOT, "translation_expectations_without_unlisted_file.pyl")
3265
3266 # Tests that the presubmit doesn't return when no grd or grdp files are
3267 # modified.
3268 def testExpectationsNoModifiedGrd(self):
3269 input_api = MockInputApi()
3270 input_api.files = [
3271 MockAffectedFile('not_used.txt', 'not used', 'not used', action='M')
3272 ]
3273 # Fake list of all grd files in the repo. This list is missing all grd/grdps
3274 # under tools/translation/testdata. This is OK because the presubmit won't
3275 # run in the first place since there are no modified grd/grps in input_api.
3276 grd_files = ['doesnt_exist_doesnt_matter.grd']
3277 warnings = PRESUBMIT._CheckTranslationExpectations(
3278 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3279 grd_files)
3280 self.assertEqual(0, len(warnings))
3281
3282
3283 # Tests that the list of files passed to the presubmit matches the list of
3284 # files in the expectations.
3285 def testExpectationsSuccess(self):
3286 # Mock input file list needs a grd or grdp file in order to run the
3287 # presubmit. The file itself doesn't matter.
3288 input_api = MockInputApi()
3289 input_api.files = [
3290 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3291 ]
3292 # List of all grd files in the repo.
3293 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3294 'internal.grd']
3295 warnings = PRESUBMIT._CheckTranslationExpectations(
3296 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3297 grd_files)
3298 self.assertEqual(0, len(warnings))
3299
3300 # Tests that the presubmit warns when a file is listed in expectations, but
3301 # does not actually exist.
3302 def testExpectationsMissingFile(self):
3303 # Mock input file list needs a grd or grdp file in order to run the
3304 # presubmit.
3305 input_api = MockInputApi()
3306 input_api.files = [
3307 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3308 ]
3309 # unlisted.grd is listed under tools/translation/testdata but is not
3310 # included in translation expectations.
3311 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
3312 warnings = PRESUBMIT._CheckTranslationExpectations(
3313 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3314 grd_files)
3315 self.assertEqual(1, len(warnings))
3316 self.assertTrue(warnings[0].message.startswith(
3317 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS))
3318 self.assertTrue(
3319 ("test.grd is listed in the translation expectations, "
3320 "but this grd file does not exist")
3321 in warnings[0].message)
3322
3323 # Tests that the presubmit warns when a file is not listed in expectations but
3324 # does actually exist.
3325 def testExpectationsUnlistedFile(self):
3326 # Mock input file list needs a grd or grdp file in order to run the
3327 # presubmit.
3328 input_api = MockInputApi()
3329 input_api.files = [
3330 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3331 ]
3332 # unlisted.grd is listed under tools/translation/testdata but is not
3333 # included in translation expectations.
3334 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3335 'internal.grd']
3336 warnings = PRESUBMIT._CheckTranslationExpectations(
3337 input_api, MockOutputApi(), self.REPO_ROOT,
3338 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3339 self.assertEqual(1, len(warnings))
3340 self.assertTrue(warnings[0].message.startswith(
3341 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3342 self.assertTrue(
3343 ("unlisted.grd appears to be translatable "
3344 "(because it contains <file> or <message> elements), "
3345 "but is not listed in the translation expectations.")
3346 in warnings[0].message)
3347
3348 # Tests that the presubmit warns twice:
3349 # - for a non-existing file listed in expectations
3350 # - for an existing file not listed in expectations
3351 def testMultipleWarnings(self):
3352 # Mock input file list needs a grd or grdp file in order to run the
3353 # presubmit.
3354 input_api = MockInputApi()
3355 input_api.files = [
3356 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3357 ]
3358 # unlisted.grd is listed under tools/translation/testdata but is not
3359 # included in translation expectations.
3360 # test.grd is not listed under tools/translation/testdata but is included
3361 # in translation expectations.
3362 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
3363 warnings = PRESUBMIT._CheckTranslationExpectations(
3364 input_api, MockOutputApi(), self.REPO_ROOT,
3365 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3366 self.assertEqual(1, len(warnings))
3367 self.assertTrue(warnings[0].message.startswith(
3368 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3369 self.assertTrue(
3370 ("unlisted.grd appears to be translatable "
3371 "(because it contains <file> or <message> elements), "
3372 "but is not listed in the translation expectations.")
3373 in warnings[0].message)
3374 self.assertTrue(
3375 ("test.grd is listed in the translation expectations, "
3376 "but this grd file does not exist")
3377 in warnings[0].message)
3378
3379
Dominic Battre033531052018-09-24 15:45:343380class DISABLETypoInTest(unittest.TestCase):
3381
3382 def testPositive(self):
3383 # Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
3384 # where the desire is to disable a test.
3385 tests = [
3386 # Disabled on one platform:
3387 '#if defined(OS_WIN)\n'
3388 '#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
3389 '#else\n'
3390 '#define MAYBE_FoobarTest FoobarTest\n'
3391 '#endif\n',
3392 # Disabled on one platform spread cross lines:
3393 '#if defined(OS_WIN)\n'
3394 '#define MAYBE_FoobarTest \\\n'
3395 ' DISABLE_FoobarTest\n'
3396 '#else\n'
3397 '#define MAYBE_FoobarTest FoobarTest\n'
3398 '#endif\n',
3399 # Disabled on all platforms:
3400 ' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
3401 # Disabled on all platforms but multiple lines
3402 ' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
3403 ]
3404
3405 for test in tests:
3406 mock_input_api = MockInputApi()
3407 mock_input_api.files = [
3408 MockFile('some/path/foo_unittest.cc', test.splitlines()),
3409 ]
3410
3411 results = PRESUBMIT._CheckNoDISABLETypoInTests(mock_input_api,
3412 MockOutputApi())
3413 self.assertEqual(
3414 1,
3415 len(results),
3416 msg=('expected len(results) == 1 but got %d in test: %s' %
3417 (len(results), test)))
3418 self.assertTrue(
3419 'foo_unittest.cc' in results[0].message,
3420 msg=('expected foo_unittest.cc in message but got %s in test %s' %
3421 (results[0].message, test)))
3422
3423 def testIngoreNotTestFiles(self):
3424 mock_input_api = MockInputApi()
3425 mock_input_api.files = [
3426 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'),
3427 ]
3428
3429 results = PRESUBMIT._CheckNoDISABLETypoInTests(mock_input_api,
3430 MockOutputApi())
3431 self.assertEqual(0, len(results))
3432
Katie Df13948e2018-09-25 07:33:443433 def testIngoreDeletedFiles(self):
3434 mock_input_api = MockInputApi()
3435 mock_input_api.files = [
3436 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'),
3437 ]
3438
3439 results = PRESUBMIT._CheckNoDISABLETypoInTests(mock_input_api,
3440 MockOutputApi())
3441 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:343442
Dirk Pranke3c18a382019-03-15 01:07:513443
3444class BuildtoolsRevisionsAreInSyncTest(unittest.TestCase):
3445 # TODO(crbug.com/941824): We need to make sure the entries in
3446 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3447 # so that users of //buildtools in other projects get the same tooling
3448 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3449 # support to gclient, we can eliminate the duplication and delete
3450 # these tests for the corresponding presubmit check.
3451
3452 def _check(self, files):
3453 mock_input_api = MockInputApi()
3454 mock_input_api.files = []
3455 for fname, contents in files.items():
3456 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
3457 return PRESUBMIT._CheckBuildtoolsRevisionsAreInSync(mock_input_api,
3458 MockOutputApi())
3459
3460 def testOneFileChangedButNotTheOther(self):
3461 results = self._check({
3462 "DEPS": "'libunwind_revision': 'onerev'",
3463 })
3464 self.assertNotEqual(results, [])
3465
3466 def testNeitherFileChanged(self):
3467 results = self._check({
3468 "OWNERS": "[email protected]",
3469 })
3470 self.assertEqual(results, [])
3471
3472 def testBothFilesChangedAndMatch(self):
3473 results = self._check({
3474 "DEPS": "'libunwind_revision': 'onerev'",
3475 "buildtools/DEPS": "'libunwind_revision': 'onerev'",
3476 })
3477 self.assertEqual(results, [])
3478
3479 def testBothFilesWereChangedAndDontMatch(self):
3480 results = self._check({
3481 "DEPS": "'libunwind_revision': 'onerev'",
3482 "buildtools/DEPS": "'libunwind_revision': 'anotherrev'",
3483 })
3484 self.assertNotEqual(results, [])
3485
3486
Max Morozb47503b2019-08-08 21:03:273487class CheckFuzzTargetsTest(unittest.TestCase):
3488
3489 def _check(self, files):
3490 mock_input_api = MockInputApi()
3491 mock_input_api.files = []
3492 for fname, contents in files.items():
3493 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
3494 return PRESUBMIT._CheckFuzzTargets(mock_input_api, MockOutputApi())
3495
3496 def testLibFuzzerSourcesIgnored(self):
3497 results = self._check({
3498 "third_party/lib/Fuzzer/FuzzerDriver.cpp": "LLVMFuzzerInitialize",
3499 })
3500 self.assertEqual(results, [])
3501
3502 def testNonCodeFilesIgnored(self):
3503 results = self._check({
3504 "README.md": "LLVMFuzzerInitialize",
3505 })
3506 self.assertEqual(results, [])
3507
3508 def testNoErrorHeaderPresent(self):
3509 results = self._check({
3510 "fuzzer.cc": (
3511 "#include \"testing/libfuzzer/libfuzzer_exports.h\"\n" +
3512 "LLVMFuzzerInitialize"
3513 )
3514 })
3515 self.assertEqual(results, [])
3516
3517 def testErrorMissingHeader(self):
3518 results = self._check({
3519 "fuzzer.cc": "LLVMFuzzerInitialize"
3520 })
3521 self.assertEqual(len(results), 1)
3522 self.assertEqual(results[0].items, ['fuzzer.cc'])
3523
3524
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263525class SetNoParentTest(unittest.TestCase):
3526 def testSetNoParentMissing(self):
3527 mock_input_api = MockInputApi()
3528 mock_input_api.files = [
3529 MockAffectedFile('goat/OWNERS',
3530 [
3531 'set noparent',
3532 '[email protected]',
3533 'per-file *.json=set noparent',
3534 'per-file *[email protected]',
3535 ])
3536 ]
3537 mock_output_api = MockOutputApi()
3538 errors = PRESUBMIT._CheckSetNoParent(mock_input_api, mock_output_api)
3539 self.assertEqual(1, len(errors))
3540 self.assertTrue('goat/OWNERS:1' in errors[0].long_text)
3541 self.assertTrue('goat/OWNERS:3' in errors[0].long_text)
3542
3543
3544 def testSetNoParentWithCorrectRule(self):
3545 mock_input_api = MockInputApi()
3546 mock_input_api.files = [
3547 MockAffectedFile('goat/OWNERS',
3548 [
3549 'set noparent',
3550 'file://ipc/SECURITY_OWNERS',
3551 'per-file *.json=set noparent',
3552 'per-file *.json=file://ipc/SECURITY_OWNERS',
3553 ])
3554 ]
3555 mock_output_api = MockOutputApi()
3556 errors = PRESUBMIT._CheckSetNoParent(mock_input_api, mock_output_api)
3557 self.assertEqual([], errors)
3558
3559
Ken Rockotc31f4832020-05-29 18:58:513560class MojomStabilityCheckTest(unittest.TestCase):
3561 def runTestWithAffectedFiles(self, affected_files):
3562 mock_input_api = MockInputApi()
3563 mock_input_api.files = affected_files
3564 mock_output_api = MockOutputApi()
3565 return PRESUBMIT._CheckStableMojomChanges(
3566 mock_input_api, mock_output_api)
3567
3568 def testSafeChangePasses(self):
3569 errors = self.runTestWithAffectedFiles([
3570 MockAffectedFile('foo/foo.mojom',
3571 ['[Stable] struct S { [MinVersion=1] int32 x; };'],
3572 old_contents=['[Stable] struct S {};'])
3573 ])
3574 self.assertEqual([], errors)
3575
3576 def testBadChangeFails(self):
3577 errors = self.runTestWithAffectedFiles([
3578 MockAffectedFile('foo/foo.mojom',
3579 ['[Stable] struct S { int32 x; };'],
3580 old_contents=['[Stable] struct S {};'])
3581 ])
3582 self.assertEqual(1, len(errors))
3583 self.assertTrue('not backward-compatible' in errors[0].message)
3584
Ken Rockotad7901f942020-06-04 20:17:093585 def testDeletedFile(self):
3586 """Regression test for https://crbug.com/1091407."""
3587 errors = self.runTestWithAffectedFiles([
3588 MockAffectedFile('a.mojom', [], old_contents=['struct S {};'],
3589 action='D'),
3590 MockAffectedFile('b.mojom',
3591 ['struct S {}; struct T { S s; };'],
3592 old_contents=['import "a.mojom"; struct T { S s; };'])
3593 ])
3594 self.assertEqual([], errors)
3595
Ken Rockotc31f4832020-05-29 18:58:513596
[email protected]2299dcf2012-11-15 19:56:243597if __name__ == '__main__':
3598 unittest.main()