blob: dd98461a054c5b38b442f065eeb21d5ac8174143 [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)',
277 ' # if defined(OS_MACOSX) || defined(OS_CHROME)',
278 '# else // defined(OS_MAC)',
279 '#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
716 def setUp(self):
717 mock_all_pydeps = ['A.pydeps', 'B.pydeps']
718 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
719 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
720 self.mock_input_api = MockInputApi()
721 self.mock_output_api = MockOutputApi()
722 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
723 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
724 self.checker._file_cache = {
725 'A.pydeps': '# Generated by:\n# CMD A\nA.py\nC.py\n',
726 'B.pydeps': '# Generated by:\n# CMD B\nB.py\nC.py\n',
727 }
728
729 def tearDown(self):
730 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
731
732 def _RunCheck(self):
733 return PRESUBMIT._CheckPydepsNeedsUpdating(self.mock_input_api,
734 self.mock_output_api,
735 checker_for_tests=self.checker)
736
737 def testAddedPydep(self):
pastarmovj89f7ee12016-09-20 14:58:13738 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
739 if self.mock_input_api.platform != 'linux2':
740 return []
741
agrievef32bcc72016-04-04 14:57:40742 self.mock_input_api.files = [
743 MockAffectedFile('new.pydeps', [], action='A'),
744 ]
745
Zhiling Huang45cabf32018-03-10 00:50:03746 self.mock_input_api.CreateMockFileInPath(
747 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
748 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40749 results = self._RunCheck()
750 self.assertEqual(1, len(results))
751 self.assertTrue('PYDEPS_FILES' in str(results[0]))
752
Zhiling Huang45cabf32018-03-10 00:50:03753 def testPydepNotInSrc(self):
754 self.mock_input_api.files = [
755 MockAffectedFile('new.pydeps', [], action='A'),
756 ]
757 self.mock_input_api.CreateMockFileInPath([])
758 results = self._RunCheck()
759 self.assertEqual(0, len(results))
760
agrievef32bcc72016-04-04 14:57:40761 def testRemovedPydep(self):
pastarmovj89f7ee12016-09-20 14:58:13762 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
763 if self.mock_input_api.platform != 'linux2':
764 return []
765
agrievef32bcc72016-04-04 14:57:40766 self.mock_input_api.files = [
767 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
768 ]
Zhiling Huang45cabf32018-03-10 00:50:03769 self.mock_input_api.CreateMockFileInPath(
770 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
771 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40772 results = self._RunCheck()
773 self.assertEqual(1, len(results))
774 self.assertTrue('PYDEPS_FILES' in str(results[0]))
775
776 def testRandomPyIgnored(self):
pastarmovj89f7ee12016-09-20 14:58:13777 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
778 if self.mock_input_api.platform != 'linux2':
779 return []
780
agrievef32bcc72016-04-04 14:57:40781 self.mock_input_api.files = [
782 MockAffectedFile('random.py', []),
783 ]
784
785 results = self._RunCheck()
786 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
787
788 def testRelevantPyNoChange(self):
pastarmovj89f7ee12016-09-20 14:58:13789 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
790 if self.mock_input_api.platform != 'linux2':
791 return []
792
agrievef32bcc72016-04-04 14:57:40793 self.mock_input_api.files = [
794 MockAffectedFile('A.py', []),
795 ]
796
John Budorickab2fa102017-10-06 16:59:49797 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40798 self.assertEqual('CMD A --output ""', cmd)
799 return self.checker._file_cache['A.pydeps']
800
801 self.mock_input_api.subprocess.check_output = mock_check_output
802
803 results = self._RunCheck()
804 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
805
806 def testRelevantPyOneChange(self):
pastarmovj89f7ee12016-09-20 14:58:13807 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
808 if self.mock_input_api.platform != 'linux2':
809 return []
810
agrievef32bcc72016-04-04 14:57:40811 self.mock_input_api.files = [
812 MockAffectedFile('A.py', []),
813 ]
814
John Budorickab2fa102017-10-06 16:59:49815 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40816 self.assertEqual('CMD A --output ""', cmd)
817 return 'changed data'
818
819 self.mock_input_api.subprocess.check_output = mock_check_output
820
821 results = self._RunCheck()
822 self.assertEqual(1, len(results))
823 self.assertTrue('File is stale' in str(results[0]))
824
825 def testRelevantPyTwoChanges(self):
pastarmovj89f7ee12016-09-20 14:58:13826 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
827 if self.mock_input_api.platform != 'linux2':
828 return []
829
agrievef32bcc72016-04-04 14:57:40830 self.mock_input_api.files = [
831 MockAffectedFile('C.py', []),
832 ]
833
John Budorickab2fa102017-10-06 16:59:49834 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40835 return 'changed data'
836
837 self.mock_input_api.subprocess.check_output = mock_check_output
838
839 results = self._RunCheck()
840 self.assertEqual(2, len(results))
841 self.assertTrue('File is stale' in str(results[0]))
842 self.assertTrue('File is stale' in str(results[1]))
843
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39844
Daniel Bratell8ba52722018-03-02 16:06:14845class IncludeGuardTest(unittest.TestCase):
846 def testIncludeGuardChecks(self):
847 mock_input_api = MockInputApi()
848 mock_output_api = MockOutputApi()
849 mock_input_api.files = [
850 MockAffectedFile('content/browser/thing/foo.h', [
851 '// Comment',
852 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
853 '#define CONTENT_BROWSER_THING_FOO_H_',
854 'struct McBoatFace;',
855 '#endif // CONTENT_BROWSER_THING_FOO_H_',
856 ]),
857 MockAffectedFile('content/browser/thing/bar.h', [
858 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
859 '#define CONTENT_BROWSER_THING_BAR_H_',
860 'namespace content {',
861 '#endif // CONTENT_BROWSER_THING_BAR_H_',
862 '} // namespace content',
863 ]),
864 MockAffectedFile('content/browser/test1.h', [
865 'namespace content {',
866 '} // namespace content',
867 ]),
868 MockAffectedFile('content\\browser\\win.h', [
869 '#ifndef CONTENT_BROWSER_WIN_H_',
870 '#define CONTENT_BROWSER_WIN_H_',
871 'struct McBoatFace;',
872 '#endif // CONTENT_BROWSER_WIN_H_',
873 ]),
874 MockAffectedFile('content/browser/test2.h', [
875 '// Comment',
876 '#ifndef CONTENT_BROWSER_TEST2_H_',
877 'struct McBoatFace;',
878 '#endif // CONTENT_BROWSER_TEST2_H_',
879 ]),
880 MockAffectedFile('content/browser/internal.h', [
881 '// Comment',
882 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
883 '#define CONTENT_BROWSER_INTERNAL_H_',
884 '// Comment',
885 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
886 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
887 'namespace internal {',
888 '} // namespace internal',
889 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
890 'namespace content {',
891 '} // namespace content',
892 '#endif // CONTENT_BROWSER_THING_BAR_H_',
893 ]),
894 MockAffectedFile('content/browser/thing/foo.cc', [
895 '// This is a non-header.',
896 ]),
897 MockAffectedFile('content/browser/disabled.h', [
898 '// no-include-guard-because-multiply-included',
899 'struct McBoatFace;',
900 ]),
901 # New files don't allow misspelled include guards.
902 MockAffectedFile('content/browser/spleling.h', [
903 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
904 '#define CONTENT_BROWSER_SPLLEING_H_',
905 'struct McBoatFace;',
906 '#endif // CONTENT_BROWSER_SPLLEING_H_',
907 ]),
Olivier Robinbba137492018-07-30 11:31:34908 # New files don't allow + in include guards.
909 MockAffectedFile('content/browser/foo+bar.h', [
910 '#ifndef CONTENT_BROWSER_FOO+BAR_H_',
911 '#define CONTENT_BROWSER_FOO+BAR_H_',
912 'struct McBoatFace;',
913 '#endif // CONTENT_BROWSER_FOO+BAR_H_',
914 ]),
Daniel Bratell8ba52722018-03-02 16:06:14915 # Old files allow misspelled include guards (for now).
916 MockAffectedFile('chrome/old.h', [
917 '// New contents',
918 '#ifndef CHROME_ODL_H_',
919 '#define CHROME_ODL_H_',
920 '#endif // CHROME_ODL_H_',
921 ], [
922 '// Old contents',
923 '#ifndef CHROME_ODL_H_',
924 '#define CHROME_ODL_H_',
925 '#endif // CHROME_ODL_H_',
926 ]),
927 # Using a Blink style include guard outside Blink is wrong.
928 MockAffectedFile('content/NotInBlink.h', [
929 '#ifndef NotInBlink_h',
930 '#define NotInBlink_h',
931 'struct McBoatFace;',
932 '#endif // NotInBlink_h',
933 ]),
Daniel Bratell39b5b062018-05-16 18:09:57934 # Using a Blink style include guard in Blink is no longer ok.
935 MockAffectedFile('third_party/blink/InBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14936 '#ifndef InBlink_h',
937 '#define InBlink_h',
938 'struct McBoatFace;',
939 '#endif // InBlink_h',
940 ]),
941 # Using a bad include guard in Blink is not ok.
Daniel Bratell39b5b062018-05-16 18:09:57942 MockAffectedFile('third_party/blink/AlsoInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14943 '#ifndef WrongInBlink_h',
944 '#define WrongInBlink_h',
945 'struct McBoatFace;',
946 '#endif // WrongInBlink_h',
947 ]),
Daniel Bratell39b5b062018-05-16 18:09:57948 # Using a bad include guard in Blink is not accepted even if
949 # it's an old file.
950 MockAffectedFile('third_party/blink/StillInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14951 '// New contents',
952 '#ifndef AcceptedInBlink_h',
953 '#define AcceptedInBlink_h',
954 'struct McBoatFace;',
955 '#endif // AcceptedInBlink_h',
956 ], [
957 '// Old contents',
958 '#ifndef AcceptedInBlink_h',
959 '#define AcceptedInBlink_h',
960 'struct McBoatFace;',
961 '#endif // AcceptedInBlink_h',
962 ]),
Daniel Bratell39b5b062018-05-16 18:09:57963 # Using a non-Chromium include guard in third_party
964 # (outside blink) is accepted.
965 MockAffectedFile('third_party/foo/some_file.h', [
966 '#ifndef REQUIRED_RPCNDR_H_',
967 '#define REQUIRED_RPCNDR_H_',
968 'struct SomeFileFoo;',
969 '#endif // REQUIRED_RPCNDR_H_',
970 ]),
Kinuko Yasuda0cdb3da2019-07-31 21:50:32971 # Not having proper include guard in *_message_generator.h
972 # for old IPC messages is allowed.
973 MockAffectedFile('content/common/content_message_generator.h', [
974 '#undef CONTENT_COMMON_FOO_MESSAGES_H_',
975 '#include "content/common/foo_messages.h"',
976 '#ifndef CONTENT_COMMON_FOO_MESSAGES_H_',
977 '#error "Failed to include content/common/foo_messages.h"',
978 '#endif',
979 ]),
Daniel Bratell8ba52722018-03-02 16:06:14980 ]
981 msgs = PRESUBMIT._CheckForIncludeGuards(
982 mock_input_api, mock_output_api)
Olivier Robinbba137492018-07-30 11:31:34983 expected_fail_count = 8
Daniel Bratell8ba52722018-03-02 16:06:14984 self.assertEqual(expected_fail_count, len(msgs),
985 'Expected %d items, found %d: %s'
986 % (expected_fail_count, len(msgs), msgs))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39987 self.assertEqual(msgs[0].items, ['content/browser/thing/bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:14988 self.assertEqual(msgs[0].message,
989 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
990 'not covering the whole file')
991
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39992 self.assertEqual(msgs[1].items, ['content/browser/test1.h'])
Daniel Bratell8ba52722018-03-02 16:06:14993 self.assertEqual(msgs[1].message,
994 'Missing include guard CONTENT_BROWSER_TEST1_H_')
995
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39996 self.assertEqual(msgs[2].items, ['content/browser/test2.h:3'])
Daniel Bratell8ba52722018-03-02 16:06:14997 self.assertEqual(msgs[2].message,
998 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
999 'include guard')
1000
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391001 self.assertEqual(msgs[3].items, ['content/browser/spleling.h:1'])
Daniel Bratell8ba52722018-03-02 16:06:141002 self.assertEqual(msgs[3].message,
1003 'Header using the wrong include guard name '
1004 'CONTENT_BROWSER_SPLLEING_H_')
1005
Olivier Robinbba137492018-07-30 11:31:341006 self.assertEqual(msgs[4].items, ['content/browser/foo+bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:141007 self.assertEqual(msgs[4].message,
Olivier Robinbba137492018-07-30 11:31:341008 'Missing include guard CONTENT_BROWSER_FOO_BAR_H_')
1009
1010 self.assertEqual(msgs[5].items, ['content/NotInBlink.h:1'])
1011 self.assertEqual(msgs[5].message,
Daniel Bratell8ba52722018-03-02 16:06:141012 'Header using the wrong include guard name '
1013 'NotInBlink_h')
1014
Olivier Robinbba137492018-07-30 11:31:341015 self.assertEqual(msgs[6].items, ['third_party/blink/InBlink.h:1'])
1016 self.assertEqual(msgs[6].message,
Daniel Bratell8ba52722018-03-02 16:06:141017 'Header using the wrong include guard name '
Daniel Bratell39b5b062018-05-16 18:09:571018 'InBlink_h')
1019
Olivier Robinbba137492018-07-30 11:31:341020 self.assertEqual(msgs[7].items, ['third_party/blink/AlsoInBlink.h:1'])
1021 self.assertEqual(msgs[7].message,
Daniel Bratell39b5b062018-05-16 18:09:571022 'Header using the wrong include guard name '
Daniel Bratell8ba52722018-03-02 16:06:141023 'WrongInBlink_h')
1024
Chris Hall59f8d0c72020-05-01 07:31:191025class AccessibilityRelnotesFieldTest(unittest.TestCase):
1026 def testRelnotesPresent(self):
1027 mock_input_api = MockInputApi()
1028 mock_output_api = MockOutputApi()
1029
1030 mock_input_api.files = [MockAffectedFile('ui/accessibility/foo.bar', [''])]
Akihiro Ota08108e542020-05-20 15:30:531031 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191032 mock_input_api.change.footers['AX-Relnotes'] = [
1033 'Important user facing change']
1034
1035 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1036 mock_input_api, mock_output_api)
1037 self.assertEqual(0, len(msgs),
1038 'Expected %d messages, found %d: %s'
1039 % (0, len(msgs), msgs))
1040
1041 def testRelnotesMissingFromAccessibilityChange(self):
1042 mock_input_api = MockInputApi()
1043 mock_output_api = MockOutputApi()
1044
1045 mock_input_api.files = [
1046 MockAffectedFile('some/file', ['']),
1047 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1048 MockAffectedFile('some/other/file', [''])
1049 ]
Akihiro Ota08108e542020-05-20 15:30:531050 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191051
1052 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1053 mock_input_api, mock_output_api)
1054 self.assertEqual(1, len(msgs),
1055 'Expected %d messages, found %d: %s'
1056 % (1, len(msgs), msgs))
1057 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1058 'Missing AX-Relnotes field message not found in errors')
1059
1060 # The relnotes footer is not required for changes which do not touch any
1061 # accessibility directories.
1062 def testIgnoresNonAccesssibilityCode(self):
1063 mock_input_api = MockInputApi()
1064 mock_output_api = MockOutputApi()
1065
1066 mock_input_api.files = [
1067 MockAffectedFile('some/file', ['']),
1068 MockAffectedFile('some/other/file', [''])
1069 ]
Akihiro Ota08108e542020-05-20 15:30:531070 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191071
1072 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1073 mock_input_api, mock_output_api)
1074 self.assertEqual(0, len(msgs),
1075 'Expected %d messages, found %d: %s'
1076 % (0, len(msgs), msgs))
1077
1078 # Test that our presubmit correctly raises an error for a set of known paths.
1079 def testExpectedPaths(self):
1080 filesToTest = [
1081 "chrome/browser/accessibility/foo.py",
1082 "chrome/browser/chromeos/arc/accessibility/foo.cc",
1083 "chrome/browser/ui/views/accessibility/foo.h",
1084 "chrome/browser/extensions/api/automation/foo.h",
1085 "chrome/browser/extensions/api/automation_internal/foo.cc",
1086 "chrome/renderer/extensions/accessibility_foo.h",
1087 "chrome/tests/data/accessibility/foo.html",
1088 "content/browser/accessibility/foo.cc",
1089 "content/renderer/accessibility/foo.h",
1090 "content/tests/data/accessibility/foo.cc",
1091 "extensions/renderer/api/automation/foo.h",
1092 "ui/accessibility/foo/bar/baz.cc",
1093 "ui/views/accessibility/foo/bar/baz.h",
1094 ]
1095
1096 for testFile in filesToTest:
1097 mock_input_api = MockInputApi()
1098 mock_output_api = MockOutputApi()
1099
1100 mock_input_api.files = [
1101 MockAffectedFile(testFile, [''])
1102 ]
Akihiro Ota08108e542020-05-20 15:30:531103 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191104
1105 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1106 mock_input_api, mock_output_api)
1107 self.assertEqual(1, len(msgs),
1108 'Expected %d messages, found %d: %s, for file %s'
1109 % (1, len(msgs), msgs, testFile))
1110 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1111 ('Missing AX-Relnotes field message not found in errors '
1112 ' for file %s' % (testFile)))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391113
Akihiro Ota08108e542020-05-20 15:30:531114 # Test that AX-Relnotes field can appear in the commit description (as long
1115 # as it appears at the beginning of a line).
1116 def testRelnotesInCommitDescription(self):
1117 mock_input_api = MockInputApi()
1118 mock_output_api = MockOutputApi()
1119
1120 mock_input_api.files = [
1121 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1122 ]
1123 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1124 'AX-Relnotes: solves all accessibility issues forever')
1125
1126 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1127 mock_input_api, mock_output_api)
1128 self.assertEqual(0, len(msgs),
1129 'Expected %d messages, found %d: %s'
1130 % (0, len(msgs), msgs))
1131
1132 # Test that we don't match AX-Relnotes if it appears in the middle of a line.
1133 def testRelnotesMustAppearAtBeginningOfLine(self):
1134 mock_input_api = MockInputApi()
1135 mock_output_api = MockOutputApi()
1136
1137 mock_input_api.files = [
1138 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1139 ]
1140 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1141 'This change has no AX-Relnotes: we should print a warning')
1142
1143 msgs = PRESUBMIT._CheckAccessibilityRelnotesField(
1144 mock_input_api, mock_output_api)
1145 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1146 'Missing AX-Relnotes field message not found in errors')
1147
1148 # Tests that the AX-Relnotes field can be lowercase and use a '=' in place
1149 # of a ':'.
1150 def testRelnotesLowercaseWithEqualSign(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= this is a valid format for accessibiliy relnotes')
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
yolandyan45001472016-12-21 21:12:421166class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
1167 def testCheckAndroidTestAnnotationUsage(self):
1168 mock_input_api = MockInputApi()
1169 mock_output_api = MockOutputApi()
1170
1171 mock_input_api.files = [
1172 MockAffectedFile('LalaLand.java', [
1173 'random stuff'
1174 ]),
1175 MockAffectedFile('CorrectUsage.java', [
1176 'import android.support.test.filters.LargeTest;',
1177 'import android.support.test.filters.MediumTest;',
1178 'import android.support.test.filters.SmallTest;',
1179 ]),
1180 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
1181 'import android.test.suitebuilder.annotation.LargeTest;',
1182 ]),
1183 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
1184 'import android.test.suitebuilder.annotation.MediumTest;',
1185 ]),
1186 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
1187 'import android.test.suitebuilder.annotation.SmallTest;',
1188 ]),
1189 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
1190 'import android.test.suitebuilder.annotation.Smoke;',
1191 ])
1192 ]
1193 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
1194 mock_input_api, mock_output_api)
1195 self.assertEqual(1, len(msgs),
1196 'Expected %d items, found %d: %s'
1197 % (1, len(msgs), msgs))
1198 self.assertEqual(4, len(msgs[0].items),
1199 'Expected %d items, found %d: %s'
1200 % (4, len(msgs[0].items), msgs[0].items))
1201 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
1202 'UsedDeprecatedLargeTestAnnotation not found in errors')
1203 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
1204 in msgs[0].items,
1205 'UsedDeprecatedMediumTestAnnotation not found in errors')
1206 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
1207 'UsedDeprecatedSmallTestAnnotation not found in errors')
1208 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
1209 'UsedDeprecatedSmokeAnnotation not found in errors')
1210
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391211
Yoland Yanb92fa522017-08-28 17:37:061212class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271213 def testCheckAndroidTestJUnitFramework(self):
Yoland Yanb92fa522017-08-28 17:37:061214 mock_input_api = MockInputApi()
1215 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:421216
Yoland Yanb92fa522017-08-28 17:37:061217 mock_input_api.files = [
1218 MockAffectedFile('LalaLand.java', [
1219 'random stuff'
1220 ]),
1221 MockAffectedFile('CorrectUsage.java', [
1222 'import org.junit.ABC',
1223 'import org.junit.XYZ;',
1224 ]),
1225 MockAffectedFile('UsedDeprecatedJUnit.java', [
1226 'import junit.framework.*;',
1227 ]),
1228 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
1229 'import junit.framework.Assert;',
1230 ]),
1231 ]
1232 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
1233 mock_input_api, mock_output_api)
1234 self.assertEqual(1, len(msgs),
1235 'Expected %d items, found %d: %s'
1236 % (1, len(msgs), msgs))
1237 self.assertEqual(2, len(msgs[0].items),
1238 'Expected %d items, found %d: %s'
1239 % (2, len(msgs[0].items), msgs[0].items))
1240 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
1241 'UsedDeprecatedJUnit.java not found in errors')
1242 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
1243 in msgs[0].items,
1244 'UsedDeprecatedJUnitAssert not found in errors')
1245
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391246
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271247class AndroidJUnitBaseClassTest(unittest.TestCase):
1248 def testCheckAndroidTestJUnitBaseClass(self):
Yoland Yanb92fa522017-08-28 17:37:061249 mock_input_api = MockInputApi()
1250 mock_output_api = MockOutputApi()
1251
1252 mock_input_api.files = [
1253 MockAffectedFile('LalaLand.java', [
1254 'random stuff'
1255 ]),
1256 MockAffectedFile('CorrectTest.java', [
1257 '@RunWith(ABC.class);'
1258 'public class CorrectTest {',
1259 '}',
1260 ]),
1261 MockAffectedFile('HistoricallyIncorrectTest.java', [
1262 'public class Test extends BaseCaseA {',
1263 '}',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391264 ], old_contents=[
Yoland Yanb92fa522017-08-28 17:37:061265 'public class Test extends BaseCaseB {',
1266 '}',
1267 ]),
1268 MockAffectedFile('CorrectTestWithInterface.java', [
1269 '@RunWith(ABC.class);'
1270 'public class CorrectTest implement Interface {',
1271 '}',
1272 ]),
1273 MockAffectedFile('IncorrectTest.java', [
1274 'public class IncorrectTest extends TestCase {',
1275 '}',
1276 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241277 MockAffectedFile('IncorrectWithInterfaceTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061278 'public class Test implements X extends BaseClass {',
1279 '}',
1280 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241281 MockAffectedFile('IncorrectMultiLineTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061282 'public class Test implements X, Y, Z',
1283 ' extends TestBase {',
1284 '}',
1285 ]),
1286 ]
1287 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1288 mock_input_api, mock_output_api)
1289 self.assertEqual(1, len(msgs),
1290 'Expected %d items, found %d: %s'
1291 % (1, len(msgs), msgs))
1292 self.assertEqual(3, len(msgs[0].items),
1293 'Expected %d items, found %d: %s'
1294 % (3, len(msgs[0].items), msgs[0].items))
1295 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1296 'IncorrectTest not found in errors')
Vaclav Brozekf01ed502018-03-16 19:38:241297 self.assertTrue('IncorrectWithInterfaceTest.java:1'
Yoland Yanb92fa522017-08-28 17:37:061298 in msgs[0].items,
Vaclav Brozekf01ed502018-03-16 19:38:241299 'IncorrectWithInterfaceTest not found in errors')
1300 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1301 'IncorrectMultiLineTest not found in errors')
yolandyan45001472016-12-21 21:12:421302
Jinsong Fan91ebbbd2019-04-16 14:57:171303class AndroidDebuggableBuildTest(unittest.TestCase):
1304
1305 def testCheckAndroidDebuggableBuild(self):
1306 mock_input_api = MockInputApi()
1307 mock_output_api = MockOutputApi()
1308
1309 mock_input_api.files = [
1310 MockAffectedFile('RandomStuff.java', [
1311 'random stuff'
1312 ]),
1313 MockAffectedFile('CorrectUsage.java', [
1314 'import org.chromium.base.BuildInfo;',
1315 'some random stuff',
1316 'boolean isOsDebuggable = BuildInfo.isDebugAndroid();',
1317 ]),
1318 MockAffectedFile('JustCheckUserdebugBuild.java', [
1319 'import android.os.Build;',
1320 'some random stuff',
1321 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")',
1322 ]),
1323 MockAffectedFile('JustCheckEngineeringBuild.java', [
1324 'import android.os.Build;',
1325 'some random stuff',
1326 'boolean isOsDebuggable = "eng".equals(Build.TYPE)',
1327 ]),
1328 MockAffectedFile('UsedBuildType.java', [
1329 'import android.os.Build;',
1330 'some random stuff',
1331 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")'
1332 '|| "eng".equals(Build.TYPE)',
1333 ]),
1334 MockAffectedFile('UsedExplicitBuildType.java', [
1335 'some random stuff',
1336 'boolean isOsDebuggable = android.os.Build.TYPE.equals("userdebug")'
1337 '|| "eng".equals(android.os.Build.TYPE)',
1338 ]),
1339 ]
1340
1341 msgs = PRESUBMIT._CheckAndroidDebuggableBuild(
1342 mock_input_api, mock_output_api)
1343 self.assertEqual(1, len(msgs),
1344 'Expected %d items, found %d: %s'
1345 % (1, len(msgs), msgs))
1346 self.assertEqual(4, len(msgs[0].items),
1347 'Expected %d items, found %d: %s'
1348 % (4, len(msgs[0].items), msgs[0].items))
1349 self.assertTrue('JustCheckUserdebugBuild.java:3' in msgs[0].items)
1350 self.assertTrue('JustCheckEngineeringBuild.java:3' in msgs[0].items)
1351 self.assertTrue('UsedBuildType.java:3' in msgs[0].items)
1352 self.assertTrue('UsedExplicitBuildType.java:2' in msgs[0].items)
1353
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391354
dgn4401aa52015-04-29 16:26:171355class LogUsageTest(unittest.TestCase):
1356
dgnaa68d5e2015-06-10 10:08:221357 def testCheckAndroidCrLogUsage(self):
1358 mock_input_api = MockInputApi()
1359 mock_output_api = MockOutputApi()
1360
1361 mock_input_api.files = [
1362 MockAffectedFile('RandomStuff.java', [
1363 'random stuff'
1364 ]),
dgn87d9fb62015-06-12 09:15:121365 MockAffectedFile('HasAndroidLog.java', [
1366 'import android.util.Log;',
1367 'some random stuff',
1368 'Log.d("TAG", "foo");',
1369 ]),
1370 MockAffectedFile('HasExplicitUtilLog.java', [
1371 'some random stuff',
1372 'android.util.Log.d("TAG", "foo");',
1373 ]),
1374 MockAffectedFile('IsInBasePackage.java', [
1375 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511376 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121377 'Log.d(TAG, "foo");',
1378 ]),
1379 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1380 'package org.chromium.base;',
1381 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511382 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121383 'Log.d(TAG, "foo");',
1384 ]),
1385 MockAffectedFile('HasBothLog.java', [
1386 'import org.chromium.base.Log;',
1387 'some random stuff',
dgn38736db2015-09-18 19:20:511388 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121389 'Log.d(TAG, "foo");',
1390 'android.util.Log.d("TAG", "foo");',
1391 ]),
dgnaa68d5e2015-06-10 10:08:221392 MockAffectedFile('HasCorrectTag.java', [
1393 'import org.chromium.base.Log;',
1394 'some random stuff',
dgn38736db2015-09-18 19:20:511395 'private static final String TAG = "cr_Foo";',
1396 'Log.d(TAG, "foo");',
1397 ]),
1398 MockAffectedFile('HasOldTag.java', [
1399 'import org.chromium.base.Log;',
1400 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221401 'private static final String TAG = "cr.Foo";',
1402 'Log.d(TAG, "foo");',
1403 ]),
dgn38736db2015-09-18 19:20:511404 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221405 'import org.chromium.base.Log;',
1406 'some random stuff',
dgn38736db2015-09-18 19:20:511407 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221408 'Log.d(TAG, "foo");',
1409 ]),
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461410 MockAffectedFile('HasDottedTagPublic.java', [
1411 'import org.chromium.base.Log;',
1412 'some random stuff',
1413 'public static final String TAG = "cr_foo.bar";',
1414 'Log.d(TAG, "foo");',
1415 ]),
dgnaa68d5e2015-06-10 10:08:221416 MockAffectedFile('HasNoTagDecl.java', [
1417 'import org.chromium.base.Log;',
1418 'some random stuff',
1419 'Log.d(TAG, "foo");',
1420 ]),
1421 MockAffectedFile('HasIncorrectTagDecl.java', [
1422 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511423 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221424 'some random stuff',
1425 'Log.d(TAG, "foo");',
1426 ]),
1427 MockAffectedFile('HasInlineTag.java', [
1428 'import org.chromium.base.Log;',
1429 'some random stuff',
dgn38736db2015-09-18 19:20:511430 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221431 'Log.d("TAG", "foo");',
1432 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551433 MockAffectedFile('HasInlineTagWithSpace.java', [
1434 'import org.chromium.base.Log;',
1435 'some random stuff',
1436 'private static final String TAG = "cr_Foo";',
1437 'Log.d("log message", "foo");',
1438 ]),
dgn38736db2015-09-18 19:20:511439 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221440 'import org.chromium.base.Log;',
1441 'some random stuff',
1442 'private static final String TAG = "rubbish";',
1443 'Log.d(TAG, "foo");',
1444 ]),
1445 MockAffectedFile('HasTooLongTag.java', [
1446 'import org.chromium.base.Log;',
1447 'some random stuff',
dgn38736db2015-09-18 19:20:511448 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:221449 'Log.d(TAG, "foo");',
1450 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551451 MockAffectedFile('HasTooLongTagWithNoLogCallsInDiff.java', [
1452 'import org.chromium.base.Log;',
1453 'some random stuff',
1454 'private static final String TAG = "21_charachers_long___";',
1455 ]),
dgnaa68d5e2015-06-10 10:08:221456 ]
1457
1458 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1459 mock_input_api, mock_output_api)
1460
dgn38736db2015-09-18 19:20:511461 self.assertEqual(5, len(msgs),
1462 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221463
1464 # Declaration format
dgn38736db2015-09-18 19:20:511465 nb = len(msgs[0].items)
1466 self.assertEqual(2, nb,
1467 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221468 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1469 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221470
1471 # Tag length
dgn38736db2015-09-18 19:20:511472 nb = len(msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551473 self.assertEqual(2, nb,
1474 'Expected %d items, found %d: %s' % (2, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:221475 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551476 self.assertTrue('HasTooLongTagWithNoLogCallsInDiff.java' in msgs[1].items)
dgnaa68d5e2015-06-10 10:08:221477
1478 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511479 nb = len(msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551480 self.assertEqual(3, nb,
1481 'Expected %d items, found %d: %s' % (3, nb, msgs[2].items))
1482 self.assertTrue('HasBothLog.java:5' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221483 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551484 self.assertTrue('HasInlineTagWithSpace.java:4' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221485
dgn87d9fb62015-06-12 09:15:121486 # Util Log usage
dgn38736db2015-09-18 19:20:511487 nb = len(msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551488 self.assertEqual(3, nb,
1489 'Expected %d items, found %d: %s' % (3, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:121490 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551491 self.assertTrue('HasExplicitUtilLog.java:2' in msgs[3].items)
dgn87d9fb62015-06-12 09:15:121492 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:221493
dgn38736db2015-09-18 19:20:511494 # Tag must not contain
1495 nb = len(msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461496 self.assertEqual(3, nb,
dgn38736db2015-09-18 19:20:511497 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1498 self.assertTrue('HasDottedTag.java' in msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461499 self.assertTrue('HasDottedTagPublic.java' in msgs[4].items)
dgn38736db2015-09-18 19:20:511500 self.assertTrue('HasOldTag.java' in msgs[4].items)
1501
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391502
estadee17314a02017-01-12 16:22:161503class GoogleAnswerUrlFormatTest(unittest.TestCase):
1504
1505 def testCatchAnswerUrlId(self):
1506 input_api = MockInputApi()
1507 input_api.files = [
1508 MockFile('somewhere/file.cc',
1509 ['char* host = '
1510 ' "https://support.google.com/chrome/answer/123456";']),
1511 MockFile('somewhere_else/file.cc',
1512 ['char* host = '
1513 ' "https://support.google.com/chrome/a/answer/123456";']),
1514 ]
1515
1516 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1517 input_api, MockOutputApi())
1518 self.assertEqual(1, len(warnings))
1519 self.assertEqual(2, len(warnings[0].items))
1520
1521 def testAllowAnswerUrlParam(self):
1522 input_api = MockInputApi()
1523 input_api.files = [
1524 MockFile('somewhere/file.cc',
1525 ['char* host = '
1526 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1527 ]
1528
1529 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1530 input_api, MockOutputApi())
1531 self.assertEqual(0, len(warnings))
1532
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391533
reillyi38965732015-11-16 18:27:331534class HardcodedGoogleHostsTest(unittest.TestCase):
1535
1536 def testWarnOnAssignedLiterals(self):
1537 input_api = MockInputApi()
1538 input_api.files = [
1539 MockFile('content/file.cc',
1540 ['char* host = "https://www.google.com";']),
1541 MockFile('content/file.cc',
1542 ['char* host = "https://www.googleapis.com";']),
1543 MockFile('content/file.cc',
1544 ['char* host = "https://clients1.google.com";']),
1545 ]
1546
1547 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1548 input_api, MockOutputApi())
1549 self.assertEqual(1, len(warnings))
1550 self.assertEqual(3, len(warnings[0].items))
1551
1552 def testAllowInComment(self):
1553 input_api = MockInputApi()
1554 input_api.files = [
1555 MockFile('content/file.cc',
1556 ['char* host = "https://www.aol.com"; // google.com'])
1557 ]
1558
1559 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1560 input_api, MockOutputApi())
1561 self.assertEqual(0, len(warnings))
1562
dgn4401aa52015-04-29 16:26:171563
James Cook6b6597c2019-11-06 22:05:291564class ChromeOsSyncedPrefRegistrationTest(unittest.TestCase):
1565
1566 def testWarnsOnChromeOsDirectories(self):
1567 input_api = MockInputApi()
1568 input_api.files = [
1569 MockFile('ash/file.cc',
1570 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1571 MockFile('chrome/browser/chromeos/file.cc',
1572 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1573 MockFile('chromeos/file.cc',
1574 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1575 MockFile('components/arc/file.cc',
1576 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1577 MockFile('components/exo/file.cc',
1578 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1579 ]
1580 warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration(
1581 input_api, MockOutputApi())
1582 self.assertEqual(1, len(warnings))
1583
1584 def testDoesNotWarnOnSyncOsPref(self):
1585 input_api = MockInputApi()
1586 input_api.files = [
1587 MockFile('chromeos/file.cc',
1588 ['PrefRegistrySyncable::SYNCABLE_OS_PREF']),
1589 ]
1590 warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration(
1591 input_api, MockOutputApi())
1592 self.assertEqual(0, len(warnings))
1593
1594 def testDoesNotWarnOnCrossPlatformDirectories(self):
1595 input_api = MockInputApi()
1596 input_api.files = [
1597 MockFile('chrome/browser/ui/file.cc',
1598 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1599 MockFile('components/sync/file.cc',
1600 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1601 MockFile('content/browser/file.cc',
1602 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1603 ]
1604 warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration(
1605 input_api, MockOutputApi())
1606 self.assertEqual(0, len(warnings))
1607
1608 def testSeparateWarningForPriorityPrefs(self):
1609 input_api = MockInputApi()
1610 input_api.files = [
1611 MockFile('chromeos/file.cc',
1612 ['PrefRegistrySyncable::SYNCABLE_PREF',
1613 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']),
1614 ]
1615 warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration(
1616 input_api, MockOutputApi())
1617 self.assertEqual(2, len(warnings))
1618
1619
jbriance9e12f162016-11-25 07:57:501620class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311621 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501622 mock_input_api = MockInputApi()
1623 mock_input_api.files = [
1624 MockAffectedFile('somewhere/file.cc', [
1625 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311626 ]),
1627 MockAffectedFile('third_party/header.h', [
1628 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501629 ])
1630 ]
1631 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391632 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501633 self.assertEqual(0, len(warnings))
1634
1635 def testNoNestedDeclaration(self):
1636 mock_input_api = MockInputApi()
1637 mock_input_api.files = [
1638 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311639 'class SomeClass {',
1640 ' protected:',
1641 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501642 '};'
1643 ])
1644 ]
1645 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391646 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501647 self.assertEqual(0, len(warnings))
1648
1649 def testSubStrings(self):
1650 mock_input_api = MockInputApi()
1651 mock_input_api.files = [
1652 MockAffectedFile('somewhere/header.h', [
1653 'class NotUsefulClass;',
1654 'struct SomeStruct;',
1655 'UsefulClass *p1;',
1656 'SomeStructPtr *p2;'
1657 ])
1658 ]
1659 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391660 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501661 self.assertEqual(2, len(warnings))
1662
1663 def testUselessForwardDeclaration(self):
1664 mock_input_api = MockInputApi()
1665 mock_input_api.files = [
1666 MockAffectedFile('somewhere/header.h', [
1667 'class DummyClass;',
1668 'struct DummyStruct;',
1669 'class UsefulClass;',
1670 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311671 ])
jbriance9e12f162016-11-25 07:57:501672 ]
1673 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391674 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501675 self.assertEqual(2, len(warnings))
1676
jbriance2c51e821a2016-12-12 08:24:311677 def testBlinkHeaders(self):
1678 mock_input_api = MockInputApi()
1679 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491680 MockAffectedFile('third_party/blink/header.h', [
jbriance2c51e821a2016-12-12 08:24:311681 'class DummyClass;',
1682 'struct DummyStruct;',
1683 ]),
Kent Tamura32dbbcb2018-11-30 12:28:491684 MockAffectedFile('third_party\\blink\\header.h', [
jbriance2c51e821a2016-12-12 08:24:311685 'class DummyClass;',
1686 'struct DummyStruct;',
1687 ])
1688 ]
1689 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391690 MockOutputApi())
jbriance2c51e821a2016-12-12 08:24:311691 self.assertEqual(4, len(warnings))
1692
jbriance9e12f162016-11-25 07:57:501693
rlanday6802cf632017-05-30 17:48:361694class RelativeIncludesTest(unittest.TestCase):
1695 def testThirdPartyNotWebKitIgnored(self):
1696 mock_input_api = MockInputApi()
1697 mock_input_api.files = [
1698 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1699 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1700 ]
1701
1702 mock_output_api = MockOutputApi()
1703
1704 errors = PRESUBMIT._CheckForRelativeIncludes(
1705 mock_input_api, mock_output_api)
1706 self.assertEqual(0, len(errors))
1707
1708 def testNonCppFileIgnored(self):
1709 mock_input_api = MockInputApi()
1710 mock_input_api.files = [
1711 MockAffectedFile('test.py', '#include "../header.h"'),
1712 ]
1713
1714 mock_output_api = MockOutputApi()
1715
1716 errors = PRESUBMIT._CheckForRelativeIncludes(
1717 mock_input_api, mock_output_api)
1718 self.assertEqual(0, len(errors))
1719
1720 def testInnocuousChangesAllowed(self):
1721 mock_input_api = MockInputApi()
1722 mock_input_api.files = [
1723 MockAffectedFile('test.cpp', '#include "header.h"'),
1724 MockAffectedFile('test2.cpp', '../'),
1725 ]
1726
1727 mock_output_api = MockOutputApi()
1728
1729 errors = PRESUBMIT._CheckForRelativeIncludes(
1730 mock_input_api, mock_output_api)
1731 self.assertEqual(0, len(errors))
1732
1733 def testRelativeIncludeNonWebKitProducesError(self):
1734 mock_input_api = MockInputApi()
1735 mock_input_api.files = [
1736 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1737 ]
1738
1739 mock_output_api = MockOutputApi()
1740
1741 errors = PRESUBMIT._CheckForRelativeIncludes(
1742 mock_input_api, mock_output_api)
1743 self.assertEqual(1, len(errors))
1744
1745 def testRelativeIncludeWebKitProducesError(self):
1746 mock_input_api = MockInputApi()
1747 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491748 MockAffectedFile('third_party/blink/test.cpp',
rlanday6802cf632017-05-30 17:48:361749 ['#include "../header.h']),
1750 ]
1751
1752 mock_output_api = MockOutputApi()
1753
1754 errors = PRESUBMIT._CheckForRelativeIncludes(
1755 mock_input_api, mock_output_api)
1756 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241757
Daniel Cheng13ca61a882017-08-25 15:11:251758
Daniel Bratell65b033262019-04-23 08:17:061759class CCIncludeTest(unittest.TestCase):
1760 def testThirdPartyNotBlinkIgnored(self):
1761 mock_input_api = MockInputApi()
1762 mock_input_api.files = [
1763 MockAffectedFile('third_party/test.cpp', '#include "file.cc"'),
1764 ]
1765
1766 mock_output_api = MockOutputApi()
1767
1768 errors = PRESUBMIT._CheckForCcIncludes(
1769 mock_input_api, mock_output_api)
1770 self.assertEqual(0, len(errors))
1771
1772 def testPythonFileIgnored(self):
1773 mock_input_api = MockInputApi()
1774 mock_input_api.files = [
1775 MockAffectedFile('test.py', '#include "file.cc"'),
1776 ]
1777
1778 mock_output_api = MockOutputApi()
1779
1780 errors = PRESUBMIT._CheckForCcIncludes(
1781 mock_input_api, mock_output_api)
1782 self.assertEqual(0, len(errors))
1783
1784 def testIncFilesAccepted(self):
1785 mock_input_api = MockInputApi()
1786 mock_input_api.files = [
1787 MockAffectedFile('test.py', '#include "file.inc"'),
1788 ]
1789
1790 mock_output_api = MockOutputApi()
1791
1792 errors = PRESUBMIT._CheckForCcIncludes(
1793 mock_input_api, mock_output_api)
1794 self.assertEqual(0, len(errors))
1795
1796 def testInnocuousChangesAllowed(self):
1797 mock_input_api = MockInputApi()
1798 mock_input_api.files = [
1799 MockAffectedFile('test.cpp', '#include "header.h"'),
1800 MockAffectedFile('test2.cpp', 'Something "file.cc"'),
1801 ]
1802
1803 mock_output_api = MockOutputApi()
1804
1805 errors = PRESUBMIT._CheckForCcIncludes(
1806 mock_input_api, mock_output_api)
1807 self.assertEqual(0, len(errors))
1808
1809 def testCcIncludeNonBlinkProducesError(self):
1810 mock_input_api = MockInputApi()
1811 mock_input_api.files = [
1812 MockAffectedFile('test.cpp', ['#include "file.cc"']),
1813 ]
1814
1815 mock_output_api = MockOutputApi()
1816
1817 errors = PRESUBMIT._CheckForCcIncludes(
1818 mock_input_api, mock_output_api)
1819 self.assertEqual(1, len(errors))
1820
1821 def testCppIncludeBlinkProducesError(self):
1822 mock_input_api = MockInputApi()
1823 mock_input_api.files = [
1824 MockAffectedFile('third_party/blink/test.cpp',
1825 ['#include "foo/file.cpp"']),
1826 ]
1827
1828 mock_output_api = MockOutputApi()
1829
1830 errors = PRESUBMIT._CheckForCcIncludes(
1831 mock_input_api, mock_output_api)
1832 self.assertEqual(1, len(errors))
1833
1834
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191835class NewHeaderWithoutGnChangeTest(unittest.TestCase):
1836 def testAddHeaderWithoutGn(self):
1837 mock_input_api = MockInputApi()
1838 mock_input_api.files = [
1839 MockAffectedFile('base/stuff.h', ''),
1840 ]
1841 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1842 mock_input_api, MockOutputApi())
1843 self.assertEqual(1, len(warnings))
1844 self.assertTrue('base/stuff.h' in warnings[0].items)
1845
1846 def testModifyHeader(self):
1847 mock_input_api = MockInputApi()
1848 mock_input_api.files = [
1849 MockAffectedFile('base/stuff.h', '', action='M'),
1850 ]
1851 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1852 mock_input_api, MockOutputApi())
1853 self.assertEqual(0, len(warnings))
1854
1855 def testDeleteHeader(self):
1856 mock_input_api = MockInputApi()
1857 mock_input_api.files = [
1858 MockAffectedFile('base/stuff.h', '', action='D'),
1859 ]
1860 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1861 mock_input_api, MockOutputApi())
1862 self.assertEqual(0, len(warnings))
1863
1864 def testAddHeaderWithGn(self):
1865 mock_input_api = MockInputApi()
1866 mock_input_api.files = [
1867 MockAffectedFile('base/stuff.h', ''),
1868 MockAffectedFile('base/BUILD.gn', 'stuff.h'),
1869 ]
1870 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1871 mock_input_api, MockOutputApi())
1872 self.assertEqual(0, len(warnings))
1873
1874 def testAddHeaderWithGni(self):
1875 mock_input_api = MockInputApi()
1876 mock_input_api.files = [
1877 MockAffectedFile('base/stuff.h', ''),
1878 MockAffectedFile('base/files.gni', 'stuff.h'),
1879 ]
1880 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1881 mock_input_api, MockOutputApi())
1882 self.assertEqual(0, len(warnings))
1883
1884 def testAddHeaderWithOther(self):
1885 mock_input_api = MockInputApi()
1886 mock_input_api.files = [
1887 MockAffectedFile('base/stuff.h', ''),
1888 MockAffectedFile('base/stuff.cc', 'stuff.h'),
1889 ]
1890 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1891 mock_input_api, MockOutputApi())
1892 self.assertEqual(1, len(warnings))
1893
1894 def testAddHeaderWithWrongGn(self):
1895 mock_input_api = MockInputApi()
1896 mock_input_api.files = [
1897 MockAffectedFile('base/stuff.h', ''),
1898 MockAffectedFile('base/BUILD.gn', 'stuff_h'),
1899 ]
1900 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1901 mock_input_api, MockOutputApi())
1902 self.assertEqual(1, len(warnings))
1903
1904 def testAddHeadersWithGn(self):
1905 mock_input_api = MockInputApi()
1906 mock_input_api.files = [
1907 MockAffectedFile('base/stuff.h', ''),
1908 MockAffectedFile('base/another.h', ''),
1909 MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'),
1910 ]
1911 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1912 mock_input_api, MockOutputApi())
1913 self.assertEqual(0, len(warnings))
1914
1915 def testAddHeadersWithWrongGn(self):
1916 mock_input_api = MockInputApi()
1917 mock_input_api.files = [
1918 MockAffectedFile('base/stuff.h', ''),
1919 MockAffectedFile('base/another.h', ''),
1920 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'),
1921 ]
1922 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1923 mock_input_api, MockOutputApi())
1924 self.assertEqual(1, len(warnings))
1925 self.assertFalse('base/stuff.h' in warnings[0].items)
1926 self.assertTrue('base/another.h' in warnings[0].items)
1927
1928 def testAddHeadersWithWrongGn2(self):
1929 mock_input_api = MockInputApi()
1930 mock_input_api.files = [
1931 MockAffectedFile('base/stuff.h', ''),
1932 MockAffectedFile('base/another.h', ''),
1933 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'),
1934 ]
1935 warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange(
1936 mock_input_api, MockOutputApi())
1937 self.assertEqual(1, len(warnings))
1938 self.assertTrue('base/stuff.h' in warnings[0].items)
1939 self.assertTrue('base/another.h' in warnings[0].items)
1940
1941
Michael Giuffridad3bc8672018-10-25 22:48:021942class CorrectProductNameInMessagesTest(unittest.TestCase):
1943 def testProductNameInDesc(self):
1944 mock_input_api = MockInputApi()
1945 mock_input_api.files = [
1946 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1947 '<message name="Foo" desc="Welcome to Chrome">',
1948 ' Welcome to Chrome!',
1949 '</message>',
1950 ]),
1951 MockAffectedFile('chrome/app/chromium_strings.grd', [
1952 '<message name="Bar" desc="Welcome to Chrome">',
1953 ' Welcome to Chromium!',
1954 '</message>',
1955 ]),
1956 ]
1957 warnings = PRESUBMIT._CheckCorrectProductNameInMessages(
1958 mock_input_api, MockOutputApi())
1959 self.assertEqual(0, len(warnings))
1960
1961 def testChromeInChromium(self):
1962 mock_input_api = MockInputApi()
1963 mock_input_api.files = [
1964 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1965 '<message name="Foo" desc="Welcome to Chrome">',
1966 ' Welcome to Chrome!',
1967 '</message>',
1968 ]),
1969 MockAffectedFile('chrome/app/chromium_strings.grd', [
1970 '<message name="Bar" desc="Welcome to Chrome">',
1971 ' Welcome to Chrome!',
1972 '</message>',
1973 ]),
1974 ]
1975 warnings = PRESUBMIT._CheckCorrectProductNameInMessages(
1976 mock_input_api, MockOutputApi())
1977 self.assertEqual(1, len(warnings))
1978 self.assertTrue('chrome/app/chromium_strings.grd' in warnings[0].items[0])
1979
1980 def testChromiumInChrome(self):
1981 mock_input_api = MockInputApi()
1982 mock_input_api.files = [
1983 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1984 '<message name="Foo" desc="Welcome to Chrome">',
1985 ' Welcome to Chromium!',
1986 '</message>',
1987 ]),
1988 MockAffectedFile('chrome/app/chromium_strings.grd', [
1989 '<message name="Bar" desc="Welcome to Chrome">',
1990 ' Welcome to Chromium!',
1991 '</message>',
1992 ]),
1993 ]
1994 warnings = PRESUBMIT._CheckCorrectProductNameInMessages(
1995 mock_input_api, MockOutputApi())
1996 self.assertEqual(1, len(warnings))
1997 self.assertTrue(
1998 'chrome/app/google_chrome_strings.grd:2' in warnings[0].items[0])
1999
2000 def testMultipleInstances(self):
2001 mock_input_api = MockInputApi()
2002 mock_input_api.files = [
2003 MockAffectedFile('chrome/app/chromium_strings.grd', [
2004 '<message name="Bar" desc="Welcome to Chrome">',
2005 ' Welcome to Chrome!',
2006 '</message>',
2007 '<message name="Baz" desc="A correct message">',
2008 ' Chromium is the software you are using.',
2009 '</message>',
2010 '<message name="Bat" desc="An incorrect message">',
2011 ' Google Chrome is the software you are using.',
2012 '</message>',
2013 ]),
2014 ]
2015 warnings = PRESUBMIT._CheckCorrectProductNameInMessages(
2016 mock_input_api, MockOutputApi())
2017 self.assertEqual(1, len(warnings))
2018 self.assertTrue(
2019 'chrome/app/chromium_strings.grd:2' in warnings[0].items[0])
2020 self.assertTrue(
2021 'chrome/app/chromium_strings.grd:8' in warnings[0].items[1])
2022
2023 def testMultipleWarnings(self):
2024 mock_input_api = MockInputApi()
2025 mock_input_api.files = [
2026 MockAffectedFile('chrome/app/chromium_strings.grd', [
2027 '<message name="Bar" desc="Welcome to Chrome">',
2028 ' Welcome to Chrome!',
2029 '</message>',
2030 '<message name="Baz" desc="A correct message">',
2031 ' Chromium is the software you are using.',
2032 '</message>',
2033 '<message name="Bat" desc="An incorrect message">',
2034 ' Google Chrome is the software you are using.',
2035 '</message>',
2036 ]),
2037 MockAffectedFile('components/components_google_chrome_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(2, len(warnings))
2052 self.assertTrue(
2053 'components/components_google_chrome_strings.grd:5'
2054 in warnings[0].items[0])
2055 self.assertTrue(
2056 'chrome/app/chromium_strings.grd:2' in warnings[1].items[0])
2057 self.assertTrue(
2058 'chrome/app/chromium_strings.grd:8' in warnings[1].items[1])
2059
2060
Ken Rockot9f668262018-12-21 18:56:362061class ServiceManifestOwnerTest(unittest.TestCase):
Ken Rockot9f668262018-12-21 18:56:362062 def testServiceManifestChangeNeedsSecurityOwner(self):
2063 mock_input_api = MockInputApi()
2064 mock_input_api.files = [
2065 MockAffectedFile('services/goat/public/cpp/manifest.cc',
2066 [
2067 '#include "services/goat/public/cpp/manifest.h"',
2068 'const service_manager::Manifest& GetManifest() {}',
2069 ])]
2070 mock_output_api = MockOutputApi()
Wez17c66962020-04-29 15:26:032071 errors = PRESUBMIT._CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362072 mock_input_api, mock_output_api)
2073 self.assertEqual(1, len(errors))
2074 self.assertEqual(
2075 'Found OWNERS files that need to be updated for IPC security review ' +
2076 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2077
2078 def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
2079 mock_input_api = MockInputApi()
2080 mock_input_api.files = [
2081 MockAffectedFile('some/non/service/thing/foo_manifest.cc',
2082 [
2083 'const char kNoEnforcement[] = "not a manifest!";',
2084 ])]
2085 mock_output_api = MockOutputApi()
Wez17c66962020-04-29 15:26:032086 errors = PRESUBMIT._CheckSecurityOwners(
2087 mock_input_api, mock_output_api)
2088 self.assertEqual([], errors)
2089
2090
2091class FuchsiaSecurityOwnerTest(unittest.TestCase):
2092 def testFidlChangeNeedsSecurityOwner(self):
2093 mock_input_api = MockInputApi()
2094 mock_input_api.files = [
2095 MockAffectedFile('potentially/scary/ipc.fidl',
2096 [
2097 'library test.fidl'
2098 ])]
2099 mock_output_api = MockOutputApi()
2100 errors = PRESUBMIT._CheckSecurityOwners(
2101 mock_input_api, mock_output_api)
2102 self.assertEqual(1, len(errors))
2103 self.assertEqual(
2104 'Found OWNERS files that need to be updated for IPC security review ' +
2105 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2106
2107 def testComponentManifestV1ChangeNeedsSecurityOwner(self):
2108 mock_input_api = MockInputApi()
2109 mock_input_api.files = [
2110 MockAffectedFile('potentially/scary/v2_manifest.cmx',
2111 [
2112 '{ "that is no": "manifest!" }'
2113 ])]
2114 mock_output_api = MockOutputApi()
2115 errors = PRESUBMIT._CheckSecurityOwners(
2116 mock_input_api, mock_output_api)
2117 self.assertEqual(1, len(errors))
2118 self.assertEqual(
2119 'Found OWNERS files that need to be updated for IPC security review ' +
2120 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2121
2122 def testComponentManifestV2NeedsSecurityOwner(self):
2123 mock_input_api = MockInputApi()
2124 mock_input_api.files = [
2125 MockAffectedFile('potentially/scary/v2_manifest.cml',
2126 [
2127 '{ "that is no": "manifest!" }'
2128 ])]
2129 mock_output_api = MockOutputApi()
2130 errors = PRESUBMIT._CheckSecurityOwners(
2131 mock_input_api, mock_output_api)
2132 self.assertEqual(1, len(errors))
2133 self.assertEqual(
2134 'Found OWNERS files that need to be updated for IPC security review ' +
2135 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2136
2137 def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2138 mock_input_api = MockInputApi()
2139 mock_input_api.files = [
2140 MockAffectedFile('some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',
2141 [
2142 'const char kNoEnforcement[] = "Security?!? Pah!";',
2143 ])]
2144 mock_output_api = MockOutputApi()
2145 errors = PRESUBMIT._CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362146 mock_input_api, mock_output_api)
2147 self.assertEqual([], errors)
2148
Daniel Cheng13ca61a882017-08-25 15:11:252149
Robert Sesek2c905332020-05-06 23:17:132150class SecurityChangeTest(unittest.TestCase):
2151 class _MockOwnersDB(object):
2152 def __init__(self):
2153 self.email_regexp = '.*'
2154
2155 def owners_rooted_at_file(self, f):
2156 return ['[email protected]', '[email protected]']
2157
2158 def _mockChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2159 def __MockOwnerAndReviewers(input_api, email_regexp, approval_needed=False):
2160 return [owner, reviewers]
2161 input_api.canned_checks.GetCodereviewOwnerAndReviewers = \
2162 __MockOwnerAndReviewers
2163
2164 def testDiffWithSandboxType(self):
2165 mock_input_api = MockInputApi()
2166 mock_input_api.files = [
2167 MockAffectedFile(
2168 'services/goat/teleporter_host.cc',
2169 [
2170 'content::ServiceProcessHost::Launch<mojom::GoatTeleporter>(',
2171 ' content::ServiceProcessHost::LaunchOptions()',
2172 ' .WithSandboxType(content::SandboxType::kGoaty)',
2173 ' .WithDisplayName("goat_teleporter")',
2174 ' .Build())'
2175 ]
2176 ),
2177 ]
2178 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2179 mock_input_api)
2180 self.assertEqual({
2181 'services/goat/teleporter_host.cc': set([
2182 'content::ServiceProcessHost::LaunchOptions::WithSandboxType'
2183 ])},
2184 files_to_functions)
2185
2186 def testDiffRemovingLine(self):
2187 mock_input_api = MockInputApi()
2188 mock_file = MockAffectedFile('services/goat/teleporter_host.cc', '')
2189 mock_file._scm_diff = """--- old 2020-05-04 14:08:25.000000000 -0400
2190+++ new 2020-05-04 14:08:32.000000000 -0400
2191@@ -1,5 +1,4 @@
2192 content::ServiceProcessHost::Launch<mojom::GoatTeleporter>(
2193 content::ServiceProcessHost::LaunchOptions()
2194- .WithSandboxType(content::SandboxType::kGoaty)
2195 .WithDisplayName("goat_teleporter")
2196 .Build())
2197"""
2198 mock_input_api.files = [mock_file]
2199 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2200 mock_input_api)
2201 self.assertEqual({
2202 'services/goat/teleporter_host.cc': set([
2203 'content::ServiceProcessHost::LaunchOptions::WithSandboxType'
2204 ])},
2205 files_to_functions)
2206
2207 def testChangeOwnersMissing(self):
2208 mock_input_api = MockInputApi()
2209 mock_input_api.owners_db = self._MockOwnersDB()
2210 mock_input_api.is_committing = False
2211 mock_input_api.files = [
2212 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2213 ]
2214 mock_output_api = MockOutputApi()
2215 self._mockChangeOwnerAndReviewers(
2216 mock_input_api, '[email protected]', ['[email protected]'])
2217 result = PRESUBMIT._CheckSecurityChanges(mock_input_api, mock_output_api)
2218 self.assertEquals(1, len(result))
2219 self.assertEquals(result[0].type, 'notify')
2220 self.assertEquals(result[0].message,
2221 'The following files change calls to security-sensive functions\n' \
2222 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2223 ' file.cc\n'
2224 ' content::ServiceProcessHost::LaunchOptions::WithSandboxType\n\n')
2225
2226 def testChangeOwnersMissingAtCommit(self):
2227 mock_input_api = MockInputApi()
2228 mock_input_api.owners_db = self._MockOwnersDB()
2229 mock_input_api.is_committing = True
2230 mock_input_api.files = [
2231 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2232 ]
2233 mock_output_api = MockOutputApi()
2234 self._mockChangeOwnerAndReviewers(
2235 mock_input_api, '[email protected]', ['[email protected]'])
2236 result = PRESUBMIT._CheckSecurityChanges(mock_input_api, mock_output_api)
2237 self.assertEquals(1, len(result))
2238 self.assertEquals(result[0].type, 'error')
2239 self.assertEquals(result[0].message,
2240 'The following files change calls to security-sensive functions\n' \
2241 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2242 ' file.cc\n'
2243 ' content::ServiceProcessHost::LaunchOptions::WithSandboxType\n\n')
2244
2245 def testChangeOwnersPresent(self):
2246 mock_input_api = MockInputApi()
2247 mock_input_api.owners_db = self._MockOwnersDB()
2248 mock_input_api.files = [
2249 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2250 ]
2251 mock_output_api = MockOutputApi()
2252 self._mockChangeOwnerAndReviewers(
2253 mock_input_api, '[email protected]',
2254 ['[email protected]', '[email protected]'])
2255 result = PRESUBMIT._CheckSecurityChanges(mock_input_api, mock_output_api)
2256 self.assertEquals(0, len(result))
2257
2258 def testChangeOwnerIsSecurityOwner(self):
2259 mock_input_api = MockInputApi()
2260 mock_input_api.owners_db = self._MockOwnersDB()
2261 mock_input_api.files = [
2262 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2263 ]
2264 mock_output_api = MockOutputApi()
2265 self._mockChangeOwnerAndReviewers(
2266 mock_input_api, '[email protected]', ['[email protected]'])
2267 result = PRESUBMIT._CheckSecurityChanges(mock_input_api, mock_output_api)
2268 self.assertEquals(1, len(result))
2269
2270
Mario Sanchez Prada2472cab2019-09-18 10:58:312271class BannedTypeCheckTest(unittest.TestCase):
Sylvain Defresnea8b73d252018-02-28 15:45:542272
Peter Kasting94a56c42019-10-25 21:54:042273 def testBannedCppFunctions(self):
2274 input_api = MockInputApi()
2275 input_api.files = [
2276 MockFile('some/cpp/problematic/file.cc',
2277 ['using namespace std;']),
Oksana Zhuravlovac8222d22019-12-19 19:21:162278 MockFile('third_party/blink/problematic/file.cc',
2279 ['GetInterfaceProvider()']),
Peter Kasting94a56c42019-10-25 21:54:042280 MockFile('some/cpp/ok/file.cc',
2281 ['using std::string;']),
Allen Bauer53b43fb12020-03-12 17:21:472282 MockFile('some/cpp/problematic/file2.cc',
2283 ['set_owned_by_client()']),
Peter Kasting94a56c42019-10-25 21:54:042284 ]
2285
Oksana Zhuravlovac8222d22019-12-19 19:21:162286 results = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi())
2287
2288 # warnings are results[0], errors are results[1]
2289 self.assertEqual(2, len(results))
2290 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2291 self.assertTrue(
2292 'third_party/blink/problematic/file.cc' in results[0].message)
2293 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
Allen Bauer53b43fb12020-03-12 17:21:472294 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
Peter Kasting94a56c42019-10-25 21:54:042295
Abhijeet Kandalkar1e7c2502019-10-29 15:05:452296 def testBannedBlinkDowncastHelpers(self):
2297 input_api = MockInputApi()
2298 input_api.files = [
2299 MockFile('some/cpp/problematic/file1.cc',
2300 ['DEFINE_TYPE_CASTS(ToType, FromType, from_argument,'
2301 'PointerPredicate(), ReferencePredicate());']),
2302 MockFile('some/cpp/problematic/file2.cc',
2303 ['bool is_test_ele = IsHTMLTestElement(n);']),
2304 MockFile('some/cpp/problematic/file3.cc',
2305 ['auto* html_test_ele = ToHTMLTestElement(n);']),
2306 MockFile('some/cpp/problematic/file4.cc',
2307 ['auto* html_test_ele_or_null = ToHTMLTestElementOrNull(n);']),
2308 MockFile('some/cpp/ok/file1.cc',
2309 ['bool is_test_ele = IsA<HTMLTestElement>(n);']),
2310 MockFile('some/cpp/ok/file2.cc',
2311 ['auto* html_test_ele = To<HTMLTestElement>(n);']),
2312 MockFile('some/cpp/ok/file3.cc',
2313 ['auto* html_test_ele_or_null = ',
2314 'DynamicTo<HTMLTestElement>(n);']),
2315 ]
2316
2317 # warnings are errors[0], errors are errors[1]
2318 errors = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi())
2319 self.assertEqual(2, len(errors))
2320 self.assertTrue('some/cpp/problematic/file1.cc' in errors[1].message)
2321 self.assertTrue('some/cpp/problematic/file2.cc' in errors[0].message)
2322 self.assertTrue('some/cpp/problematic/file3.cc' in errors[0].message)
2323 self.assertTrue('some/cpp/problematic/file4.cc' in errors[0].message)
2324 self.assertTrue('some/cpp/ok/file1.cc' not in errors[0].message)
2325 self.assertTrue('some/cpp/ok/file2.cc' not in errors[0].message)
2326 self.assertTrue('some/cpp/ok/file3.cc' not in errors[0].message)
2327
Peter K. Lee6c03ccff2019-07-15 14:40:052328 def testBannedIosObjcFunctions(self):
Sylvain Defresnea8b73d252018-02-28 15:45:542329 input_api = MockInputApi()
2330 input_api.files = [
2331 MockFile('some/ios/file.mm',
2332 ['TEST(SomeClassTest, SomeInteraction) {',
2333 '}']),
2334 MockFile('some/mac/file.mm',
2335 ['TEST(SomeClassTest, SomeInteraction) {',
2336 '}']),
2337 MockFile('another/ios_file.mm',
2338 ['class SomeTest : public testing::Test {};']),
Peter K. Lee6c03ccff2019-07-15 14:40:052339 MockFile('some/ios/file_egtest.mm',
2340 ['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
2341 MockFile('some/ios/file_unittest.mm',
2342 ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']),
Sylvain Defresnea8b73d252018-02-28 15:45:542343 ]
2344
2345 errors = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi())
2346 self.assertEqual(1, len(errors))
2347 self.assertTrue('some/ios/file.mm' in errors[0].message)
2348 self.assertTrue('another/ios_file.mm' in errors[0].message)
2349 self.assertTrue('some/mac/file.mm' not in errors[0].message)
Peter K. Lee6c03ccff2019-07-15 14:40:052350 self.assertTrue('some/ios/file_egtest.mm' in errors[0].message)
2351 self.assertTrue('some/ios/file_unittest.mm' not in errors[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542352
Carlos Knippschildab192b8c2019-04-08 20:02:382353 def testBannedMojoFunctions(self):
2354 input_api = MockInputApi()
2355 input_api.files = [
2356 MockFile('some/cpp/problematic/file.cc',
2357 ['mojo::DataPipe();']),
Oksana Zhuravlovafd247772019-05-16 16:57:292358 MockFile('some/cpp/problematic/file2.cc',
2359 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382360 MockFile('some/cpp/ok/file.cc',
2361 ['CreateDataPipe();']),
Kinuko Yasuda376c2ce12019-04-16 01:20:372362 MockFile('some/cpp/ok/file2.cc',
2363 ['mojo::DataPipeDrainer();']),
Oksana Zhuravlovafd247772019-05-16 16:57:292364 MockFile('third_party/blink/ok/file3.cc',
2365 ['mojo::ConvertTo<>']),
2366 MockFile('content/renderer/ok/file3.cc',
2367 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382368 ]
2369
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222370 results = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi())
2371
2372 # warnings are results[0], errors are results[1]
2373 self.assertEqual(2, len(results))
2374 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2375 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
2376 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
2377 self.assertTrue('some/cpp/ok/file2.cc' not in results[1].message)
2378 self.assertTrue('third_party/blink/ok/file3.cc' not in results[0].message)
2379 self.assertTrue('content/renderer/ok/file3.cc' not in results[0].message)
Carlos Knippschildab192b8c2019-04-08 20:02:382380
Mario Sanchez Prada2472cab2019-09-18 10:58:312381 def testDeprecatedMojoTypes(self):
Mario Sanchez Pradacec9cef2019-12-15 11:54:572382 ok_paths = ['components/arc']
2383 warning_paths = ['some/cpp']
Mario Sanchez Pradaaab91382019-12-19 08:57:092384 error_paths = ['third_party/blink', 'content']
Mario Sanchez Prada2472cab2019-09-18 10:58:312385 test_cases = [
2386 {
2387 'type': 'mojo::AssociatedBinding<>;',
2388 'file': 'file1.c'
2389 },
2390 {
2391 'type': 'mojo::AssociatedBindingSet<>;',
2392 'file': 'file2.c'
2393 },
2394 {
2395 'type': 'mojo::AssociatedInterfacePtr<>',
2396 'file': 'file3.cc'
2397 },
2398 {
2399 'type': 'mojo::AssociatedInterfacePtrInfo<>',
2400 'file': 'file4.cc'
2401 },
2402 {
2403 'type': 'mojo::AssociatedInterfaceRequest<>',
2404 'file': 'file5.cc'
2405 },
2406 {
2407 'type': 'mojo::Binding<>',
2408 'file': 'file6.cc'
2409 },
2410 {
2411 'type': 'mojo::BindingSet<>',
2412 'file': 'file7.cc'
2413 },
2414 {
2415 'type': 'mojo::InterfacePtr<>',
2416 'file': 'file8.cc'
2417 },
2418 {
2419 'type': 'mojo::InterfacePtrInfo<>',
2420 'file': 'file9.cc'
2421 },
2422 {
2423 'type': 'mojo::InterfaceRequest<>',
2424 'file': 'file10.cc'
2425 },
2426 {
2427 'type': 'mojo::MakeRequest()',
2428 'file': 'file11.cc'
2429 },
2430 {
2431 'type': 'mojo::MakeRequestAssociatedWithDedicatedPipe()',
2432 'file': 'file12.cc'
2433 },
2434 {
2435 'type': 'mojo::MakeStrongBinding()<>',
2436 'file': 'file13.cc'
2437 },
2438 {
2439 'type': 'mojo::MakeStrongAssociatedBinding()<>',
2440 'file': 'file14.cc'
2441 },
2442 {
2443 'type': 'mojo::StrongAssociatedBindingSet<>',
2444 'file': 'file15.cc'
2445 },
2446 {
2447 'type': 'mojo::StrongBindingSet<>',
2448 'file': 'file16.cc'
2449 },
2450 ]
2451
2452 # Build the list of MockFiles considering paths that should trigger warnings
Mario Sanchez Pradacec9cef2019-12-15 11:54:572453 # as well as paths that should trigger errors.
Mario Sanchez Prada2472cab2019-09-18 10:58:312454 input_api = MockInputApi()
2455 input_api.files = []
2456 for test_case in test_cases:
2457 for path in ok_paths:
2458 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2459 [test_case['type']]))
2460 for path in warning_paths:
2461 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2462 [test_case['type']]))
Mario Sanchez Pradacec9cef2019-12-15 11:54:572463 for path in error_paths:
2464 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2465 [test_case['type']]))
Mario Sanchez Prada2472cab2019-09-18 10:58:312466
2467 results = PRESUBMIT._CheckNoDeprecatedMojoTypes(input_api, MockOutputApi())
2468
Mario Sanchez Pradacec9cef2019-12-15 11:54:572469 # warnings are results[0], errors are results[1]
2470 self.assertEqual(2, len(results))
Mario Sanchez Prada2472cab2019-09-18 10:58:312471
2472 for test_case in test_cases:
Mario Sanchez Pradacec9cef2019-12-15 11:54:572473 # Check that no warnings nor errors have been triggered for these paths.
Mario Sanchez Prada2472cab2019-09-18 10:58:312474 for path in ok_paths:
2475 self.assertFalse(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572476 self.assertFalse(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312477
2478 # Check warnings have been triggered for these paths.
2479 for path in warning_paths:
2480 self.assertTrue(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572481 self.assertFalse(path in results[1].message)
2482
2483 # Check errors have been triggered for these paths.
2484 for path in error_paths:
2485 self.assertFalse(path in results[0].message)
2486 self.assertTrue(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312487
Sylvain Defresnea8b73d252018-02-28 15:45:542488
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272489class NoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:242490 def testTruePositives(self):
2491 mock_input_api = MockInputApi()
2492 mock_input_api.files = [
2493 MockFile('some/path/foo.cc', ['foo_for_testing();']),
2494 MockFile('some/path/foo.mm', ['FooForTesting();']),
2495 MockFile('some/path/foo.cxx', ['FooForTests();']),
2496 MockFile('some/path/foo.cpp', ['foo_for_test();']),
2497 ]
2498
2499 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
2500 mock_input_api, MockOutputApi())
2501 self.assertEqual(1, len(results))
2502 self.assertEqual(4, len(results[0].items))
2503 self.assertTrue('foo.cc' in results[0].items[0])
2504 self.assertTrue('foo.mm' in results[0].items[1])
2505 self.assertTrue('foo.cxx' in results[0].items[2])
2506 self.assertTrue('foo.cpp' in results[0].items[3])
2507
2508 def testFalsePositives(self):
2509 mock_input_api = MockInputApi()
2510 mock_input_api.files = [
2511 MockFile('some/path/foo.h', ['foo_for_testing();']),
2512 MockFile('some/path/foo.mm', ['FooForTesting() {']),
2513 MockFile('some/path/foo.cc', ['::FooForTests();']),
2514 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
2515 ]
2516
2517 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
2518 mock_input_api, MockOutputApi())
2519 self.assertEqual(0, len(results))
2520
2521
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272522class NoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:232523 def testTruePositives(self):
2524 mock_input_api = MockInputApi()
2525 mock_input_api.files = [
2526 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
2527 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392528 MockFile('dir/java/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232529 MockFile('dir/java/src/mult.java', [
2530 'int x = SomethingLongHere()',
2531 ' * SomethingLongHereForTesting();'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392532 ])
Vaclav Brozek7dbc28c2018-03-27 08:35:232533 ]
2534
2535 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctionsJava(
2536 mock_input_api, MockOutputApi())
2537 self.assertEqual(1, len(results))
2538 self.assertEqual(4, len(results[0].items))
2539 self.assertTrue('foo.java' in results[0].items[0])
2540 self.assertTrue('bar.java' in results[0].items[1])
2541 self.assertTrue('baz.java' in results[0].items[2])
2542 self.assertTrue('mult.java' in results[0].items[3])
2543
2544 def testFalsePositives(self):
2545 mock_input_api = MockInputApi()
2546 mock_input_api.files = [
2547 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
2548 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
2549 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
2550 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392551 MockFile('dir/javatests/src/baz.java', ['FooForTest(', 'y', ');']),
2552 MockFile('dir/junit/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232553 MockFile('dir/junit/src/javadoc.java', [
2554 '/** Use FooForTest(); to obtain foo in tests.'
2555 ' */'
2556 ]),
2557 MockFile('dir/junit/src/javadoc2.java', [
2558 '/** ',
2559 ' * Use FooForTest(); to obtain foo in tests.'
2560 ' */'
2561 ]),
2562 ]
2563
2564 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctionsJava(
2565 mock_input_api, MockOutputApi())
2566 self.assertEqual(0, len(results))
2567
2568
Mohamed Heikald048240a2019-11-12 16:57:372569class NewImagesWarningTest(unittest.TestCase):
2570 def testTruePositives(self):
2571 mock_input_api = MockInputApi()
2572 mock_input_api.files = [
2573 MockFile('dir/android/res/drawable/foo.png', []),
2574 MockFile('dir/android/res/drawable-v21/bar.svg', []),
2575 MockFile('dir/android/res/mipmap-v21-en/baz.webp', []),
2576 MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png', []),
2577 ]
2578
2579 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2580 self.assertEqual(1, len(results))
2581 self.assertEqual(4, len(results[0].items))
2582 self.assertTrue('foo.png' in results[0].items[0].LocalPath())
2583 self.assertTrue('bar.svg' in results[0].items[1].LocalPath())
2584 self.assertTrue('baz.webp' in results[0].items[2].LocalPath())
2585 self.assertTrue('foobar.png' in results[0].items[3].LocalPath())
2586
2587 def testFalsePositives(self):
2588 mock_input_api = MockInputApi()
2589 mock_input_api.files = [
2590 MockFile('dir/pngs/README.md', []),
2591 MockFile('java/test/res/drawable/foo.png', []),
2592 MockFile('third_party/blink/foo.png', []),
2593 MockFile('dir/third_party/libpng/src/foo.cc', ['foobar']),
2594 MockFile('dir/resources.webp/.gitignore', ['foo.png']),
2595 ]
2596
2597 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2598 self.assertEqual(0, len(results))
2599
2600
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272601class CheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:052602 def testTruePositivesNullptr(self):
2603 mock_input_api = MockInputApi()
2604 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162605 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
2606 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
Vaclav Brozek851d9602018-04-04 16:13:052607 ]
2608
2609 results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi())
2610 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162611 self.assertTrue('nullptr' in results[0].message)
Vaclav Brozek851d9602018-04-04 16:13:052612 self.assertEqual(2, len(results[0].items))
2613 self.assertTrue('baz.cc' in results[0].items[0])
2614 self.assertTrue('baz-p.cc' in results[0].items[1])
2615
2616 def testTruePositivesConstructor(self):
Vaclav Brozek52e18bf2018-04-03 07:05:242617 mock_input_api = MockInputApi()
2618 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162619 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
2620 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
2621 MockFile('dir/mult.cc', [
Vaclav Brozek95face62018-04-04 14:15:112622 'return',
2623 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
2624 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162625 MockFile('dir/mult2.cc', [
Vaclav Brozek95face62018-04-04 14:15:112626 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
2627 ' std::unique_ptr<T>(foo);'
2628 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162629 MockFile('dir/mult3.cc', [
Vaclav Brozek95face62018-04-04 14:15:112630 'bar = std::unique_ptr<T>(',
2631 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
2632 ]),
Vaclav Brozekb7fadb692018-08-30 06:39:532633 MockFile('dir/multi_arg.cc', [
2634 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']),
Vaclav Brozek52e18bf2018-04-03 07:05:242635 ]
2636
2637 results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052638 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162639 self.assertTrue('std::make_unique' in results[0].message)
Vaclav Brozekb7fadb692018-08-30 06:39:532640 self.assertEqual(6, len(results[0].items))
Vaclav Brozek851d9602018-04-04 16:13:052641 self.assertTrue('foo.cc' in results[0].items[0])
2642 self.assertTrue('bar.mm' in results[0].items[1])
2643 self.assertTrue('mult.cc' in results[0].items[2])
2644 self.assertTrue('mult2.cc' in results[0].items[3])
2645 self.assertTrue('mult3.cc' in results[0].items[4])
Vaclav Brozekb7fadb692018-08-30 06:39:532646 self.assertTrue('multi_arg.cc' in results[0].items[5])
Vaclav Brozek52e18bf2018-04-03 07:05:242647
2648 def testFalsePositives(self):
2649 mock_input_api = MockInputApi()
2650 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162651 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
2652 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
2653 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
2654 MockFile('dir/baz.cc', [
Vaclav Brozek52e18bf2018-04-03 07:05:242655 'std::unique_ptr<T> result = std::make_unique<T>();'
2656 ]),
Vaclav Brozeka54c528b2018-04-06 19:23:552657 MockFile('dir/baz2.cc', [
2658 'std::unique_ptr<T> result = std::make_unique<T>('
2659 ]),
2660 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
2661 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
Vaclav Brozekb7fadb692018-08-30 06:39:532662
2663 # Two-argument invocation of std::unique_ptr is exempt because there is
2664 # no equivalent using std::make_unique.
2665 MockFile('dir/multi_arg.cc', [
2666 'auto p = std::unique_ptr<T, D>(new T(), D());']),
Vaclav Brozek52e18bf2018-04-03 07:05:242667 ]
2668
2669 results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi())
2670 self.assertEqual(0, len(results))
2671
Danil Chapovalov3518f362018-08-11 16:13:432672class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
2673 def testBlocksDirectIncludes(self):
2674 mock_input_api = MockInputApi()
2675 mock_input_api.files = [
2676 MockFile('dir/foo_win.cc', ['#include "shlwapi.h"']),
2677 MockFile('dir/bar.h', ['#include <propvarutil.h>']),
2678 MockFile('dir/baz.h', ['#include <atlbase.h>']),
2679 MockFile('dir/jumbo.h', ['#include "sphelper.h"']),
2680 ]
2681 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2682 self.assertEquals(1, len(results))
2683 self.assertEquals(4, len(results[0].items))
2684 self.assertTrue('StrCat' in results[0].message)
2685 self.assertTrue('foo_win.cc' in results[0].items[0])
2686 self.assertTrue('bar.h' in results[0].items[1])
2687 self.assertTrue('baz.h' in results[0].items[2])
2688 self.assertTrue('jumbo.h' in results[0].items[3])
2689
2690 def testAllowsToIncludeWrapper(self):
2691 mock_input_api = MockInputApi()
2692 mock_input_api.files = [
2693 MockFile('dir/baz_win.cc', ['#include "base/win/shlwapi.h"']),
2694 MockFile('dir/baz-win.h', ['#include "base/win/atl.h"']),
2695 ]
2696 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2697 self.assertEquals(0, len(results))
2698
2699 def testAllowsToCreateWrapper(self):
2700 mock_input_api = MockInputApi()
2701 mock_input_api.files = [
2702 MockFile('base/win/shlwapi.h', [
2703 '#include <shlwapi.h>',
2704 '#include "base/win/windows_defines.inc"']),
2705 ]
2706 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2707 self.assertEquals(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:242708
Mustafa Emre Acer51f2f742020-03-09 19:41:122709
Rainhard Findlingfc31844c52020-05-15 09:58:262710class StringTest(unittest.TestCase):
2711 """Tests ICU syntax check and translation screenshots check."""
2712
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142713 # An empty grd file.
2714 OLD_GRD_CONTENTS = """<?xml version="1.0" encoding="UTF-8"?>
2715 <grit latest_public_release="1" current_release="1">
2716 <release seq="1">
2717 <messages></messages>
2718 </release>
2719 </grit>
2720 """.splitlines()
2721 # A grd file with a single message.
2722 NEW_GRD_CONTENTS1 = """<?xml version="1.0" encoding="UTF-8"?>
2723 <grit latest_public_release="1" current_release="1">
2724 <release seq="1">
2725 <messages>
2726 <message name="IDS_TEST1">
2727 Test string 1
2728 </message>
2729 </messages>
2730 </release>
2731 </grit>
2732 """.splitlines()
2733 # A grd file with two messages.
2734 NEW_GRD_CONTENTS2 = """<?xml version="1.0" encoding="UTF-8"?>
2735 <grit latest_public_release="1" current_release="1">
2736 <release seq="1">
2737 <messages>
2738 <message name="IDS_TEST1">
2739 Test string 1
2740 </message>
2741 <message name="IDS_TEST2">
2742 Test string 2
2743 </message>
2744 </messages>
2745 </release>
2746 </grit>
2747 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:262748 # A grd file with one ICU syntax message without syntax errors.
2749 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1 = """<?xml version="1.0" encoding="UTF-8"?>
2750 <grit latest_public_release="1" current_release="1">
2751 <release seq="1">
2752 <messages>
2753 <message name="IDS_TEST1">
2754 {NUM, plural,
2755 =1 {Test text for numeric one}
2756 other {Test text for plural with {NUM} as number}}
2757 </message>
2758 </messages>
2759 </release>
2760 </grit>
2761 """.splitlines()
2762 # A grd file with one ICU syntax message without syntax errors.
2763 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2 = """<?xml version="1.0" encoding="UTF-8"?>
2764 <grit latest_public_release="1" current_release="1">
2765 <release seq="1">
2766 <messages>
2767 <message name="IDS_TEST1">
2768 {NUM, plural,
2769 =1 {Different test text for numeric one}
2770 other {Different test text for plural with {NUM} as number}}
2771 </message>
2772 </messages>
2773 </release>
2774 </grit>
2775 """.splitlines()
2776 # A grd file with one ICU syntax message with syntax errors (misses a comma).
2777 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
2778 <grit latest_public_release="1" current_release="1">
2779 <release seq="1">
2780 <messages>
2781 <message name="IDS_TEST1">
2782 {NUM, plural
2783 =1 {Test text for numeric one}
2784 other {Test text for plural with {NUM} as number}}
2785 </message>
2786 </messages>
2787 </release>
2788 </grit>
2789 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142790
meacerff8a9b62019-12-10 19:43:582791 OLD_GRDP_CONTENTS = (
2792 '<?xml version="1.0" encoding="utf-8"?>',
2793 '<grit-part>',
2794 '</grit-part>'
2795 )
2796
2797 NEW_GRDP_CONTENTS1 = (
2798 '<?xml version="1.0" encoding="utf-8"?>',
2799 '<grit-part>',
2800 '<message name="IDS_PART_TEST1">',
2801 'Part string 1',
2802 '</message>',
2803 '</grit-part>')
2804
2805 NEW_GRDP_CONTENTS2 = (
2806 '<?xml version="1.0" encoding="utf-8"?>',
2807 '<grit-part>',
2808 '<message name="IDS_PART_TEST1">',
2809 'Part string 1',
2810 '</message>',
2811 '<message name="IDS_PART_TEST2">',
2812 'Part string 2',
2813 '</message>',
2814 '</grit-part>')
2815
Rainhard Findlingfc31844c52020-05-15 09:58:262816 # A grdp file with one ICU syntax message without syntax errors.
2817 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = (
2818 '<?xml version="1.0" encoding="utf-8"?>',
2819 '<grit-part>',
2820 '<message name="IDS_PART_TEST1">',
2821 '{NUM, plural,',
2822 '=1 {Test text for numeric one}',
2823 'other {Test text for plural with {NUM} as number}}',
2824 '</message>',
2825 '</grit-part>')
2826 # A grdp file with one ICU syntax message without syntax errors.
2827 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2 = (
2828 '<?xml version="1.0" encoding="utf-8"?>',
2829 '<grit-part>',
2830 '<message name="IDS_PART_TEST1">',
2831 '{NUM, plural,',
2832 '=1 {Different test text for numeric one}',
2833 'other {Different test text for plural with {NUM} as number}}',
2834 '</message>',
2835 '</grit-part>')
2836
2837 # A grdp file with one ICU syntax message with syntax errors (superfluent
2838 # whitespace).
2839 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR = (
2840 '<?xml version="1.0" encoding="utf-8"?>',
2841 '<grit-part>',
2842 '<message name="IDS_PART_TEST1">',
2843 '{NUM, plural,',
2844 '= 1 {Test text for numeric one}',
2845 'other {Test text for plural with {NUM} as number}}',
2846 '</message>',
2847 '</grit-part>')
2848
Mustafa Emre Acerc8a012d2018-07-31 00:00:392849 DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
2850 'changelist. Run '
2851 'tools/translate/upload_screenshots.py to '
2852 'upload them instead:')
2853 GENERATE_SIGNATURES_MESSAGE = ('You are adding or modifying UI strings.\n'
2854 'To ensure the best translations, take '
2855 'screenshots of the relevant UI '
2856 '(https://g.co/chrome/translation) and add '
2857 'these files to your changelist:')
2858 REMOVE_SIGNATURES_MESSAGE = ('You removed strings associated with these '
2859 'files. Remove:')
Rainhard Findlingfc31844c52020-05-15 09:58:262860 ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
2861 'strings (problems or feedback? Contact '
2862 '[email protected]):')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142863
2864 def makeInputApi(self, files):
2865 input_api = MockInputApi()
2866 input_api.files = files
meacere7be7532019-10-02 17:41:032867 # Override os_path.exists because the presubmit uses the actual
2868 # os.path.exists.
2869 input_api.CreateMockFileInPath(
2870 [x.LocalPath() for x in input_api.AffectedFiles(include_deletes=True)])
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142871 return input_api
2872
meacerff8a9b62019-12-10 19:43:582873 """ CL modified and added messages, but didn't add any screenshots."""
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142874 def testNoScreenshots(self):
meacerff8a9b62019-12-10 19:43:582875 # No new strings (file contents same). Should not warn.
2876 input_api = self.makeInputApi([
2877 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
2878 self.NEW_GRD_CONTENTS1, action='M'),
2879 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1,
2880 self.NEW_GRDP_CONTENTS1, action='M')])
Rainhard Findlingfc31844c52020-05-15 09:58:262881 warnings = PRESUBMIT._CheckStrings(input_api,
meacerff8a9b62019-12-10 19:43:582882 MockOutputApi())
2883 self.assertEqual(0, len(warnings))
2884
2885 # Add two new strings. Should have two warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142886 input_api = self.makeInputApi([
2887 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582888 self.NEW_GRD_CONTENTS1, action='M'),
2889 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2890 self.NEW_GRDP_CONTENTS1, action='M')])
Rainhard Findlingfc31844c52020-05-15 09:58:262891 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142892 MockOutputApi())
2893 self.assertEqual(1, len(warnings))
2894 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012895 self.assertEqual([
meacerff8a9b62019-12-10 19:43:582896 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2897 os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
2898 warnings[0].items)
Mustafa Emre Acer36eaad52019-11-12 23:03:342899
meacerff8a9b62019-12-10 19:43:582900 # Add four new strings. Should have four warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:212901 input_api = self.makeInputApi([
2902 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582903 self.OLD_GRD_CONTENTS, action='M'),
2904 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2905 self.OLD_GRDP_CONTENTS, action='M')])
Rainhard Findlingfc31844c52020-05-15 09:58:262906 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:212907 MockOutputApi())
2908 self.assertEqual(1, len(warnings))
2909 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:582910 self.assertEqual([
2911 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2912 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2913 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
2914 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
2915 ], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:212916
meacerff8a9b62019-12-10 19:43:582917 def testPngAddedSha1NotAdded(self):
2918 # CL added one new message in a grd file and added the png file associated
2919 # with it, but did not add the corresponding sha1 file. This should warn
2920 # twice:
2921 # - Once for the added png file (because we don't want developers to upload
2922 # actual images)
2923 # - Once for the missing .sha1 file
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142924 input_api = self.makeInputApi([
Mustafa Emre Acerea3e57a2018-12-17 23:51:012925 MockAffectedFile(
2926 'test.grd',
2927 self.NEW_GRD_CONTENTS1,
2928 self.OLD_GRD_CONTENTS,
2929 action='M'),
2930 MockAffectedFile(
2931 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
2932 ])
Rainhard Findlingfc31844c52020-05-15 09:58:262933 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142934 MockOutputApi())
2935 self.assertEqual(2, len(warnings))
2936 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012937 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
2938 warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142939 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012940 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
2941 warnings[1].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142942
meacerff8a9b62019-12-10 19:43:582943 # CL added two messages (one in grd, one in grdp) and added the png files
2944 # associated with the messages, but did not add the corresponding sha1
2945 # files. This should warn twice:
2946 # - Once for the added png files (because we don't want developers to upload
2947 # actual images)
2948 # - Once for the missing .sha1 files
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142949 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:582950 # Modified files:
Mustafa Emre Acer36eaad52019-11-12 23:03:342951 MockAffectedFile(
2952 'test.grd',
meacerff8a9b62019-12-10 19:43:582953 self.NEW_GRD_CONTENTS1,
Mustafa Emre Acer36eaad52019-11-12 23:03:342954 self.OLD_GRD_CONTENTS,
meacer2308d0742019-11-12 18:15:422955 action='M'),
Mustafa Emre Acer12e7fee2019-11-18 18:49:552956 MockAffectedFile(
meacerff8a9b62019-12-10 19:43:582957 'part.grdp',
2958 self.NEW_GRDP_CONTENTS1,
2959 self.OLD_GRDP_CONTENTS,
2960 action='M'),
2961 # Added files:
2962 MockAffectedFile(
2963 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A'),
2964 MockAffectedFile(
2965 os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary',
2966 action='A')
Mustafa Emre Acerad8fb082019-11-19 04:24:212967 ])
Rainhard Findlingfc31844c52020-05-15 09:58:262968 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:212969 MockOutputApi())
2970 self.assertEqual(2, len(warnings))
2971 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:582972 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png'),
2973 os.path.join('test_grd', 'IDS_TEST1.png')],
Mustafa Emre Acerad8fb082019-11-19 04:24:212974 warnings[0].items)
2975 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
meacerff8a9b62019-12-10 19:43:582976 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
2977 os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
2978 warnings[1].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:212979
2980 def testScreenshotsWithSha1(self):
meacerff8a9b62019-12-10 19:43:582981 # CL added four messages (two each in a grd and grdp) and their
2982 # corresponding .sha1 files. No warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:212983 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:582984 # Modified files:
Mustafa Emre Acerad8fb082019-11-19 04:24:212985 MockAffectedFile(
2986 'test.grd',
2987 self.NEW_GRD_CONTENTS2,
2988 self.OLD_GRD_CONTENTS,
Mustafa Emre Acer12e7fee2019-11-18 18:49:552989 action='M'),
meacerff8a9b62019-12-10 19:43:582990 MockAffectedFile(
2991 'part.grdp',
2992 self.NEW_GRDP_CONTENTS2,
2993 self.OLD_GRDP_CONTENTS,
2994 action='M'),
2995 # Added files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:012996 MockFile(
2997 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
2998 'binary',
2999 action='A'),
3000 MockFile(
3001 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3002 'binary',
meacerff8a9b62019-12-10 19:43:583003 action='A'),
3004 MockFile(
3005 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3006 'binary',
3007 action='A'),
3008 MockFile(
3009 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3010 'binary',
3011 action='A'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013012 ])
Rainhard Findlingfc31844c52020-05-15 09:58:263013 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143014 MockOutputApi())
3015 self.assertEqual([], warnings)
3016
3017 def testScreenshotsRemovedWithSha1(self):
meacerff8a9b62019-12-10 19:43:583018 # Replace new contents with old contents in grd and grp files, removing
3019 # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3020 # Should warn to remove the sha1 files associated with these strings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143021 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583022 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013023 MockAffectedFile(
3024 'test.grd',
meacerff8a9b62019-12-10 19:43:583025 self.OLD_GRD_CONTENTS, # new_contents
3026 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013027 action='M'),
meacerff8a9b62019-12-10 19:43:583028 MockAffectedFile(
3029 'part.grdp',
3030 self.OLD_GRDP_CONTENTS, # new_contents
3031 self.NEW_GRDP_CONTENTS2, # old_contents
3032 action='M'),
3033 # Unmodified files:
3034 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
3035 MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', ''),
3036 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3037 'binary', ''),
3038 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3039 'binary', '')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013040 ])
Rainhard Findlingfc31844c52020-05-15 09:58:263041 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143042 MockOutputApi())
3043 self.assertEqual(1, len(warnings))
3044 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013045 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583046 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3047 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013048 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3049 os.path.join('test_grd', 'IDS_TEST2.png.sha1')
3050 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143051
meacerff8a9b62019-12-10 19:43:583052 # Same as above, but this time one of the .sha1 files is also removed.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143053 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583054 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013055 MockAffectedFile(
3056 'test.grd',
meacerff8a9b62019-12-10 19:43:583057 self.OLD_GRD_CONTENTS, # new_contents
3058 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013059 action='M'),
meacerff8a9b62019-12-10 19:43:583060 MockAffectedFile(
3061 'part.grdp',
3062 self.OLD_GRDP_CONTENTS, # new_contents
3063 self.NEW_GRDP_CONTENTS2, # old_contents
3064 action='M'),
3065 # Unmodified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013066 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
meacerff8a9b62019-12-10 19:43:583067 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3068 'binary', ''),
3069 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013070 MockAffectedFile(
3071 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3072 '',
3073 'old_contents',
meacerff8a9b62019-12-10 19:43:583074 action='D'),
3075 MockAffectedFile(
3076 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3077 '',
3078 'old_contents',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013079 action='D')
3080 ])
Rainhard Findlingfc31844c52020-05-15 09:58:263081 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143082 MockOutputApi())
3083 self.assertEqual(1, len(warnings))
3084 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583085 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3086 os.path.join('test_grd', 'IDS_TEST1.png.sha1')
3087 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143088
meacerff8a9b62019-12-10 19:43:583089 # Remove all sha1 files. There should be no warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143090 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583091 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013092 MockAffectedFile(
3093 'test.grd',
3094 self.OLD_GRD_CONTENTS,
3095 self.NEW_GRD_CONTENTS2,
3096 action='M'),
meacerff8a9b62019-12-10 19:43:583097 MockAffectedFile(
3098 'part.grdp',
3099 self.OLD_GRDP_CONTENTS,
3100 self.NEW_GRDP_CONTENTS2,
3101 action='M'),
3102 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013103 MockFile(
3104 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3105 'binary',
3106 action='D'),
3107 MockFile(
3108 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3109 'binary',
meacerff8a9b62019-12-10 19:43:583110 action='D'),
3111 MockFile(
3112 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3113 'binary',
3114 action='D'),
3115 MockFile(
3116 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3117 'binary',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013118 action='D')
3119 ])
Rainhard Findlingfc31844c52020-05-15 09:58:263120 warnings = PRESUBMIT._CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143121 MockOutputApi())
3122 self.assertEqual([], warnings)
3123
Rainhard Findlingfc31844c52020-05-15 09:58:263124 def testIcuSyntax(self):
3125 # Add valid ICU syntax string. Should not raise an error.
3126 input_api = self.makeInputApi([
3127 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3128 self.NEW_GRD_CONTENTS1, action='M'),
3129 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3130 self.NEW_GRDP_CONTENTS1, action='M')])
3131 results = PRESUBMIT._CheckStrings(input_api, MockOutputApi())
3132 # We expect no ICU syntax errors.
3133 icu_errors = [e for e in results
3134 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3135 self.assertEqual(0, len(icu_errors))
3136
3137 # Valid changes in ICU syntax. Should not raise an error.
3138 input_api = self.makeInputApi([
3139 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3140 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3141 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3142 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
3143 results = PRESUBMIT._CheckStrings(input_api, MockOutputApi())
3144 # We expect no ICU syntax errors.
3145 icu_errors = [e for e in results
3146 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3147 self.assertEqual(0, len(icu_errors))
3148
3149 # Add invalid ICU syntax strings. Should raise two errors.
3150 input_api = self.makeInputApi([
3151 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3152 self.NEW_GRD_CONTENTS1, action='M'),
3153 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3154 self.NEW_GRD_CONTENTS1, action='M')])
3155 results = PRESUBMIT._CheckStrings(input_api, MockOutputApi())
3156 # We expect 2 ICU syntax errors.
3157 icu_errors = [e for e in results
3158 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3159 self.assertEqual(1, len(icu_errors))
3160 self.assertEqual([
3161 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3162 'ICU syntax.',
3163 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3164 ], icu_errors[0].items)
3165
3166 # Change two strings to have ICU syntax errors. Should raise two errors.
3167 input_api = self.makeInputApi([
3168 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3169 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3170 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3171 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
3172 results = PRESUBMIT._CheckStrings(input_api, MockOutputApi())
3173 # We expect 2 ICU syntax errors.
3174 icu_errors = [e for e in results
3175 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3176 self.assertEqual(1, len(icu_errors))
3177 self.assertEqual([
3178 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3179 'ICU syntax.',
3180 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3181 ], icu_errors[0].items)
3182
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143183
Mustafa Emre Acer51f2f742020-03-09 19:41:123184class TranslationExpectationsTest(unittest.TestCase):
3185 ERROR_MESSAGE_FORMAT = (
3186 "Failed to get a list of translatable grd files. "
3187 "This happens when:\n"
3188 " - One of the modified grd or grdp files cannot be parsed or\n"
3189 " - %s is not updated.\n"
3190 "Stack:\n"
3191 )
3192 REPO_ROOT = os.path.join('tools', 'translation', 'testdata')
3193 # This lists all .grd files under REPO_ROOT.
3194 EXPECTATIONS = os.path.join(REPO_ROOT,
3195 "translation_expectations.pyl")
3196 # This lists all .grd files under REPO_ROOT except unlisted.grd.
3197 EXPECTATIONS_WITHOUT_UNLISTED_FILE = os.path.join(
3198 REPO_ROOT, "translation_expectations_without_unlisted_file.pyl")
3199
3200 # Tests that the presubmit doesn't return when no grd or grdp files are
3201 # modified.
3202 def testExpectationsNoModifiedGrd(self):
3203 input_api = MockInputApi()
3204 input_api.files = [
3205 MockAffectedFile('not_used.txt', 'not used', 'not used', action='M')
3206 ]
3207 # Fake list of all grd files in the repo. This list is missing all grd/grdps
3208 # under tools/translation/testdata. This is OK because the presubmit won't
3209 # run in the first place since there are no modified grd/grps in input_api.
3210 grd_files = ['doesnt_exist_doesnt_matter.grd']
3211 warnings = PRESUBMIT._CheckTranslationExpectations(
3212 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3213 grd_files)
3214 self.assertEqual(0, len(warnings))
3215
3216
3217 # Tests that the list of files passed to the presubmit matches the list of
3218 # files in the expectations.
3219 def testExpectationsSuccess(self):
3220 # Mock input file list needs a grd or grdp file in order to run the
3221 # presubmit. The file itself doesn't matter.
3222 input_api = MockInputApi()
3223 input_api.files = [
3224 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3225 ]
3226 # List of all grd files in the repo.
3227 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3228 'internal.grd']
3229 warnings = PRESUBMIT._CheckTranslationExpectations(
3230 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3231 grd_files)
3232 self.assertEqual(0, len(warnings))
3233
3234 # Tests that the presubmit warns when a file is listed in expectations, but
3235 # does not actually exist.
3236 def testExpectationsMissingFile(self):
3237 # Mock input file list needs a grd or grdp file in order to run the
3238 # presubmit.
3239 input_api = MockInputApi()
3240 input_api.files = [
3241 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3242 ]
3243 # unlisted.grd is listed under tools/translation/testdata but is not
3244 # included in translation expectations.
3245 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
3246 warnings = PRESUBMIT._CheckTranslationExpectations(
3247 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3248 grd_files)
3249 self.assertEqual(1, len(warnings))
3250 self.assertTrue(warnings[0].message.startswith(
3251 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS))
3252 self.assertTrue(
3253 ("test.grd is listed in the translation expectations, "
3254 "but this grd file does not exist")
3255 in warnings[0].message)
3256
3257 # Tests that the presubmit warns when a file is not listed in expectations but
3258 # does actually exist.
3259 def testExpectationsUnlistedFile(self):
3260 # Mock input file list needs a grd or grdp file in order to run the
3261 # presubmit.
3262 input_api = MockInputApi()
3263 input_api.files = [
3264 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3265 ]
3266 # unlisted.grd is listed under tools/translation/testdata but is not
3267 # included in translation expectations.
3268 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3269 'internal.grd']
3270 warnings = PRESUBMIT._CheckTranslationExpectations(
3271 input_api, MockOutputApi(), self.REPO_ROOT,
3272 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3273 self.assertEqual(1, len(warnings))
3274 self.assertTrue(warnings[0].message.startswith(
3275 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3276 self.assertTrue(
3277 ("unlisted.grd appears to be translatable "
3278 "(because it contains <file> or <message> elements), "
3279 "but is not listed in the translation expectations.")
3280 in warnings[0].message)
3281
3282 # Tests that the presubmit warns twice:
3283 # - for a non-existing file listed in expectations
3284 # - for an existing file not listed in expectations
3285 def testMultipleWarnings(self):
3286 # Mock input file list needs a grd or grdp file in order to run the
3287 # presubmit.
3288 input_api = MockInputApi()
3289 input_api.files = [
3290 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3291 ]
3292 # unlisted.grd is listed under tools/translation/testdata but is not
3293 # included in translation expectations.
3294 # test.grd is not listed under tools/translation/testdata but is included
3295 # in translation expectations.
3296 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
3297 warnings = PRESUBMIT._CheckTranslationExpectations(
3298 input_api, MockOutputApi(), self.REPO_ROOT,
3299 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3300 self.assertEqual(1, len(warnings))
3301 self.assertTrue(warnings[0].message.startswith(
3302 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3303 self.assertTrue(
3304 ("unlisted.grd appears to be translatable "
3305 "(because it contains <file> or <message> elements), "
3306 "but is not listed in the translation expectations.")
3307 in warnings[0].message)
3308 self.assertTrue(
3309 ("test.grd is listed in the translation expectations, "
3310 "but this grd file does not exist")
3311 in warnings[0].message)
3312
3313
Dominic Battre033531052018-09-24 15:45:343314class DISABLETypoInTest(unittest.TestCase):
3315
3316 def testPositive(self):
3317 # Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
3318 # where the desire is to disable a test.
3319 tests = [
3320 # Disabled on one platform:
3321 '#if defined(OS_WIN)\n'
3322 '#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
3323 '#else\n'
3324 '#define MAYBE_FoobarTest FoobarTest\n'
3325 '#endif\n',
3326 # Disabled on one platform spread cross lines:
3327 '#if defined(OS_WIN)\n'
3328 '#define MAYBE_FoobarTest \\\n'
3329 ' DISABLE_FoobarTest\n'
3330 '#else\n'
3331 '#define MAYBE_FoobarTest FoobarTest\n'
3332 '#endif\n',
3333 # Disabled on all platforms:
3334 ' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
3335 # Disabled on all platforms but multiple lines
3336 ' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
3337 ]
3338
3339 for test in tests:
3340 mock_input_api = MockInputApi()
3341 mock_input_api.files = [
3342 MockFile('some/path/foo_unittest.cc', test.splitlines()),
3343 ]
3344
3345 results = PRESUBMIT._CheckNoDISABLETypoInTests(mock_input_api,
3346 MockOutputApi())
3347 self.assertEqual(
3348 1,
3349 len(results),
3350 msg=('expected len(results) == 1 but got %d in test: %s' %
3351 (len(results), test)))
3352 self.assertTrue(
3353 'foo_unittest.cc' in results[0].message,
3354 msg=('expected foo_unittest.cc in message but got %s in test %s' %
3355 (results[0].message, test)))
3356
3357 def testIngoreNotTestFiles(self):
3358 mock_input_api = MockInputApi()
3359 mock_input_api.files = [
3360 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'),
3361 ]
3362
3363 results = PRESUBMIT._CheckNoDISABLETypoInTests(mock_input_api,
3364 MockOutputApi())
3365 self.assertEqual(0, len(results))
3366
Katie Df13948e2018-09-25 07:33:443367 def testIngoreDeletedFiles(self):
3368 mock_input_api = MockInputApi()
3369 mock_input_api.files = [
3370 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'),
3371 ]
3372
3373 results = PRESUBMIT._CheckNoDISABLETypoInTests(mock_input_api,
3374 MockOutputApi())
3375 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:343376
Dirk Pranke3c18a382019-03-15 01:07:513377
3378class BuildtoolsRevisionsAreInSyncTest(unittest.TestCase):
3379 # TODO(crbug.com/941824): We need to make sure the entries in
3380 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3381 # so that users of //buildtools in other projects get the same tooling
3382 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3383 # support to gclient, we can eliminate the duplication and delete
3384 # these tests for the corresponding presubmit check.
3385
3386 def _check(self, files):
3387 mock_input_api = MockInputApi()
3388 mock_input_api.files = []
3389 for fname, contents in files.items():
3390 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
3391 return PRESUBMIT._CheckBuildtoolsRevisionsAreInSync(mock_input_api,
3392 MockOutputApi())
3393
3394 def testOneFileChangedButNotTheOther(self):
3395 results = self._check({
3396 "DEPS": "'libunwind_revision': 'onerev'",
3397 })
3398 self.assertNotEqual(results, [])
3399
3400 def testNeitherFileChanged(self):
3401 results = self._check({
3402 "OWNERS": "[email protected]",
3403 })
3404 self.assertEqual(results, [])
3405
3406 def testBothFilesChangedAndMatch(self):
3407 results = self._check({
3408 "DEPS": "'libunwind_revision': 'onerev'",
3409 "buildtools/DEPS": "'libunwind_revision': 'onerev'",
3410 })
3411 self.assertEqual(results, [])
3412
3413 def testBothFilesWereChangedAndDontMatch(self):
3414 results = self._check({
3415 "DEPS": "'libunwind_revision': 'onerev'",
3416 "buildtools/DEPS": "'libunwind_revision': 'anotherrev'",
3417 })
3418 self.assertNotEqual(results, [])
3419
3420
Max Morozb47503b2019-08-08 21:03:273421class CheckFuzzTargetsTest(unittest.TestCase):
3422
3423 def _check(self, files):
3424 mock_input_api = MockInputApi()
3425 mock_input_api.files = []
3426 for fname, contents in files.items():
3427 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
3428 return PRESUBMIT._CheckFuzzTargets(mock_input_api, MockOutputApi())
3429
3430 def testLibFuzzerSourcesIgnored(self):
3431 results = self._check({
3432 "third_party/lib/Fuzzer/FuzzerDriver.cpp": "LLVMFuzzerInitialize",
3433 })
3434 self.assertEqual(results, [])
3435
3436 def testNonCodeFilesIgnored(self):
3437 results = self._check({
3438 "README.md": "LLVMFuzzerInitialize",
3439 })
3440 self.assertEqual(results, [])
3441
3442 def testNoErrorHeaderPresent(self):
3443 results = self._check({
3444 "fuzzer.cc": (
3445 "#include \"testing/libfuzzer/libfuzzer_exports.h\"\n" +
3446 "LLVMFuzzerInitialize"
3447 )
3448 })
3449 self.assertEqual(results, [])
3450
3451 def testErrorMissingHeader(self):
3452 results = self._check({
3453 "fuzzer.cc": "LLVMFuzzerInitialize"
3454 })
3455 self.assertEqual(len(results), 1)
3456 self.assertEqual(results[0].items, ['fuzzer.cc'])
3457
3458
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263459class SetNoParentTest(unittest.TestCase):
3460 def testSetNoParentMissing(self):
3461 mock_input_api = MockInputApi()
3462 mock_input_api.files = [
3463 MockAffectedFile('goat/OWNERS',
3464 [
3465 'set noparent',
3466 '[email protected]',
3467 'per-file *.json=set noparent',
3468 'per-file *[email protected]',
3469 ])
3470 ]
3471 mock_output_api = MockOutputApi()
3472 errors = PRESUBMIT._CheckSetNoParent(mock_input_api, mock_output_api)
3473 self.assertEqual(1, len(errors))
3474 self.assertTrue('goat/OWNERS:1' in errors[0].long_text)
3475 self.assertTrue('goat/OWNERS:3' in errors[0].long_text)
3476
3477
3478 def testSetNoParentWithCorrectRule(self):
3479 mock_input_api = MockInputApi()
3480 mock_input_api.files = [
3481 MockAffectedFile('goat/OWNERS',
3482 [
3483 'set noparent',
3484 'file://ipc/SECURITY_OWNERS',
3485 'per-file *.json=set noparent',
3486 'per-file *.json=file://ipc/SECURITY_OWNERS',
3487 ])
3488 ]
3489 mock_output_api = MockOutputApi()
3490 errors = PRESUBMIT._CheckSetNoParent(mock_input_api, mock_output_api)
3491 self.assertEqual([], errors)
3492
3493
[email protected]2299dcf2012-11-15 19:56:243494if __name__ == '__main__':
3495 unittest.main()