blob: 90410a7cceb20d277ac77db7186b27157475f391 [file] [log] [blame]
[email protected]2299dcf2012-11-15 19:56:241#!/usr/bin/env python
2# Copyright (c) 2012 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
Daniel Cheng4dcdb6b2017-04-13 08:30:176import os.path
[email protected]99171a92014-06-03 08:44:477import subprocess
[email protected]2299dcf2012-11-15 19:56:248import unittest
9
10import PRESUBMIT
Saagar Sanghavifceeaae2020-08-12 16:40:3611
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3912from PRESUBMIT_test_mocks import MockFile, MockAffectedFile
gayane3dff8c22014-12-04 17:09:5113from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi
[email protected]2299dcf2012-11-15 19:56:2414
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3915
[email protected]99171a92014-06-03 08:44:4716_TEST_DATA_DIR = 'base/test/data/presubmit'
17
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3918
[email protected]b00342e7f2013-03-26 16:21:5419class VersionControlConflictsTest(unittest.TestCase):
[email protected]70ca77752012-11-20 03:45:0320 def testTypicalConflict(self):
21 lines = ['<<<<<<< HEAD',
22 ' base::ScopedTempDir temp_dir_;',
23 '=======',
24 ' ScopedTempDir temp_dir_;',
25 '>>>>>>> master']
26 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
27 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
28 self.assertEqual(3, len(errors))
29 self.assertTrue('1' in errors[0])
30 self.assertTrue('3' in errors[1])
31 self.assertTrue('5' in errors[2])
32
dbeam95c35a2f2015-06-02 01:40:2333 def testIgnoresReadmes(self):
34 lines = ['A First Level Header',
35 '====================',
36 '',
37 'A Second Level Header',
38 '---------------------']
39 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
40 MockInputApi(), MockFile('some/polymer/README.md', lines))
41 self.assertEqual(0, len(errors))
42
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:3943
mcasasb7440c282015-02-04 14:52:1944class UmaHistogramChangeMatchedOrNotTest(unittest.TestCase):
45 def testTypicalCorrectlyMatchedChange(self):
46 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:4747 diff_java = [
48 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
mcasasb7440c282015-02-04 14:52:1949 diff_xml = ['<histogram name="Bla.Foo.Dummy"> </histogram>']
50 mock_input_api = MockInputApi()
51 mock_input_api.files = [
52 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:4753 MockFile('some/path/foo.java', diff_java),
mcasasb7440c282015-02-04 14:52:1954 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
55 ]
Saagar Sanghavifceeaae2020-08-12 16:40:3656 warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api,
mcasasb7440c282015-02-04 14:52:1957 MockOutputApi())
58 self.assertEqual(0, len(warnings))
59
60 def testTypicalNotMatchedChange(self):
61 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:4762 diff_java = [
63 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
mcasasb7440c282015-02-04 14:52:1964 mock_input_api = MockInputApi()
Vaclav Brozekbdac817c2018-03-24 06:30:4765 mock_input_api.files = [
66 MockFile('some/path/foo.cc', diff_cc),
67 MockFile('some/path/foo.java', diff_java),
68 ]
Saagar Sanghavifceeaae2020-08-12 16:40:3669 warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api,
mcasasb7440c282015-02-04 14:52:1970 MockOutputApi())
71 self.assertEqual(1, len(warnings))
72 self.assertEqual('warning', warnings[0].type)
Vaclav Brozekbdac817c2018-03-24 06:30:4773 self.assertTrue('foo.cc' in warnings[0].items[0])
74 self.assertTrue('foo.java' in warnings[0].items[1])
mcasasb7440c282015-02-04 14:52:1975
76 def testTypicalNotMatchedChangeViaSuffixes(self):
77 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:4778 diff_java = [
79 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
mcasasb7440c282015-02-04 14:52:1980 diff_xml = ['<histogram_suffixes name="SuperHistogram">',
81 ' <suffix name="Dummy"/>',
82 ' <affected-histogram name="Snafu.Dummy"/>',
83 '</histogram>']
84 mock_input_api = MockInputApi()
85 mock_input_api.files = [
86 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:4787 MockFile('some/path/foo.java', diff_java),
mcasasb7440c282015-02-04 14:52:1988 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
89 ]
Saagar Sanghavifceeaae2020-08-12 16:40:3690 warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api,
mcasasb7440c282015-02-04 14:52:1991 MockOutputApi())
92 self.assertEqual(1, len(warnings))
93 self.assertEqual('warning', warnings[0].type)
Vaclav Brozekbdac817c2018-03-24 06:30:4794 self.assertTrue('foo.cc' in warnings[0].items[0])
95 self.assertTrue('foo.java' in warnings[0].items[1])
mcasasb7440c282015-02-04 14:52:1996
97 def testTypicalCorrectlyMatchedChangeViaSuffixes(self):
98 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:4799 diff_java = [
100 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
mcasasb7440c282015-02-04 14:52:19101 diff_xml = ['<histogram_suffixes name="SuperHistogram">',
102 ' <suffix name="Dummy"/>',
103 ' <affected-histogram name="Bla.Foo"/>',
104 '</histogram>']
105 mock_input_api = MockInputApi()
106 mock_input_api.files = [
107 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:47108 MockFile('some/path/foo.java', diff_java),
mcasasb7440c282015-02-04 14:52:19109 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
110 ]
Saagar Sanghavifceeaae2020-08-12 16:40:36111 warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api,
mcasasb7440c282015-02-04 14:52:19112 MockOutputApi())
113 self.assertEqual(0, len(warnings))
114
115 def testTypicalCorrectlyMatchedChangeViaSuffixesWithSeparator(self):
116 diff_cc = ['UMA_HISTOGRAM_BOOL("Snafu_Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:47117 diff_java = ['RecordHistogram.recordBooleanHistogram("Snafu_Dummy", true)']
mcasasb7440c282015-02-04 14:52:19118 diff_xml = ['<histogram_suffixes name="SuperHistogram" separator="_">',
119 ' <suffix name="Dummy"/>',
120 ' <affected-histogram name="Snafu"/>',
121 '</histogram>']
122 mock_input_api = MockInputApi()
123 mock_input_api.files = [
124 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:47125 MockFile('some/path/foo.java', diff_java),
mcasasb7440c282015-02-04 14:52:19126 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
127 ]
Saagar Sanghavifceeaae2020-08-12 16:40:36128 warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api,
mcasasb7440c282015-02-04 14:52:19129 MockOutputApi())
130 self.assertEqual(0, len(warnings))
[email protected]70ca77752012-11-20 03:45:03131
Makoto Shimazu3ad422cd2019-05-08 02:35:14132 def testCorrectlyMatchedChangeViaSuffixesWithLineWrapping(self):
133 diff_cc = [
134 'UMA_HISTOGRAM_BOOL("LongHistogramNameNeedsLineWrapping.Dummy", true)']
135 diff_java = ['RecordHistogram.recordBooleanHistogram(' +
136 '"LongHistogramNameNeedsLineWrapping.Dummy", true)']
137 diff_xml = ['<histogram_suffixes',
138 ' name="LongHistogramNameNeedsLineWrapping"',
139 ' separator=".">',
140 ' <suffix name="Dummy"/>',
141 ' <affected-histogram',
142 ' name="LongHistogramNameNeedsLineWrapping"/>',
143 '</histogram>']
144 mock_input_api = MockInputApi()
145 mock_input_api.files = [
146 MockFile('some/path/foo.cc', diff_cc),
147 MockFile('some/path/foo.java', diff_java),
148 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
149 ]
Saagar Sanghavifceeaae2020-08-12 16:40:36150 warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api,
Makoto Shimazu3ad422cd2019-05-08 02:35:14151 MockOutputApi())
152 self.assertEqual(0, len(warnings))
153
Vaclav Brozek8a8e2e202018-03-23 22:01:06154 def testNameMatch(self):
155 # Check that the detected histogram name is "Dummy" and not, e.g.,
156 # "Dummy\", true); // The \"correct"
157 diff_cc = ['UMA_HISTOGRAM_BOOL("Dummy", true); // The "correct" histogram']
Vaclav Brozekbdac817c2018-03-24 06:30:47158 diff_java = [
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39159 'RecordHistogram.recordBooleanHistogram("Dummy", true);' +
160 ' // The "correct" histogram']
Vaclav Brozek8a8e2e202018-03-23 22:01:06161 diff_xml = ['<histogram name="Dummy"> </histogram>']
162 mock_input_api = MockInputApi()
163 mock_input_api.files = [
164 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:47165 MockFile('some/path/foo.java', diff_java),
Vaclav Brozek8a8e2e202018-03-23 22:01:06166 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
167 ]
Saagar Sanghavifceeaae2020-08-12 16:40:36168 warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api,
Vaclav Brozek8a8e2e202018-03-23 22:01:06169 MockOutputApi())
170 self.assertEqual(0, len(warnings))
171
172 def testSimilarMacroNames(self):
Vaclav Brozekbdac817c2018-03-24 06:30:47173 diff_cc = ['PUMA_HISTOGRAM_COOL("Mountain Lion", 42)']
174 diff_java = [
175 'FakeRecordHistogram.recordFakeHistogram("Mountain Lion", 42)']
Vaclav Brozek8a8e2e202018-03-23 22:01:06176 mock_input_api = MockInputApi()
177 mock_input_api.files = [
178 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:47179 MockFile('some/path/foo.java', diff_java),
Vaclav Brozek8a8e2e202018-03-23 22:01:06180 ]
Saagar Sanghavifceeaae2020-08-12 16:40:36181 warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api,
Vaclav Brozek8a8e2e202018-03-23 22:01:06182 MockOutputApi())
183 self.assertEqual(0, len(warnings))
184
Vaclav Brozek0e730cbd2018-03-24 06:18:17185 def testMultiLine(self):
186 diff_cc = ['UMA_HISTOGRAM_BOOLEAN(', ' "Multi.Line", true)']
187 diff_cc2 = ['UMA_HISTOGRAM_BOOLEAN(', ' "Multi.Line"', ' , true)']
Vaclav Brozekbdac817c2018-03-24 06:30:47188 diff_java = [
189 'RecordHistogram.recordBooleanHistogram(',
190 ' "Multi.Line", true);',
191 ]
Vaclav Brozek0e730cbd2018-03-24 06:18:17192 mock_input_api = MockInputApi()
193 mock_input_api.files = [
194 MockFile('some/path/foo.cc', diff_cc),
195 MockFile('some/path/foo2.cc', diff_cc2),
Vaclav Brozekbdac817c2018-03-24 06:30:47196 MockFile('some/path/foo.java', diff_java),
Vaclav Brozek0e730cbd2018-03-24 06:18:17197 ]
Saagar Sanghavifceeaae2020-08-12 16:40:36198 warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api,
Vaclav Brozek0e730cbd2018-03-24 06:18:17199 MockOutputApi())
200 self.assertEqual(1, len(warnings))
201 self.assertEqual('warning', warnings[0].type)
202 self.assertTrue('foo.cc' in warnings[0].items[0])
203 self.assertTrue('foo2.cc' in warnings[0].items[1])
204
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39205
[email protected]b8079ae4a2012-12-05 19:56:49206class BadExtensionsTest(unittest.TestCase):
207 def testBadRejFile(self):
208 mock_input_api = MockInputApi()
209 mock_input_api.files = [
210 MockFile('some/path/foo.cc', ''),
211 MockFile('some/path/foo.cc.rej', ''),
212 MockFile('some/path2/bar.h.rej', ''),
213 ]
214
Saagar Sanghavifceeaae2020-08-12 16:40:36215 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:49216 self.assertEqual(1, len(results))
217 self.assertEqual(2, len(results[0].items))
218 self.assertTrue('foo.cc.rej' in results[0].items[0])
219 self.assertTrue('bar.h.rej' in results[0].items[1])
220
221 def testBadOrigFile(self):
222 mock_input_api = MockInputApi()
223 mock_input_api.files = [
224 MockFile('other/path/qux.h.orig', ''),
225 MockFile('other/path/qux.h', ''),
226 MockFile('other/path/qux.cc', ''),
227 ]
228
Saagar Sanghavifceeaae2020-08-12 16:40:36229 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:49230 self.assertEqual(1, len(results))
231 self.assertEqual(1, len(results[0].items))
232 self.assertTrue('qux.h.orig' in results[0].items[0])
233
234 def testGoodFiles(self):
235 mock_input_api = MockInputApi()
236 mock_input_api.files = [
237 MockFile('other/path/qux.h', ''),
238 MockFile('other/path/qux.cc', ''),
239 ]
Saagar Sanghavifceeaae2020-08-12 16:40:36240 results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi())
[email protected]b8079ae4a2012-12-05 19:56:49241 self.assertEqual(0, len(results))
242
243
glidere61efad2015-02-18 17:39:43244class CheckSingletonInHeadersTest(unittest.TestCase):
245 def testSingletonInArbitraryHeader(self):
246 diff_singleton_h = ['base::subtle::AtomicWord '
olli.raula36aa8be2015-09-10 11:14:22247 'base::Singleton<Type, Traits, DifferentiatingType>::']
248 diff_foo_h = ['// base::Singleton<Foo> in comment.',
249 'friend class base::Singleton<Foo>']
oysteinec430ad42015-10-22 20:55:24250 diff_foo2_h = [' //Foo* bar = base::Singleton<Foo>::get();']
olli.raula36aa8be2015-09-10 11:14:22251 diff_bad_h = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43252 mock_input_api = MockInputApi()
253 mock_input_api.files = [MockAffectedFile('base/memory/singleton.h',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39254 diff_singleton_h),
glidere61efad2015-02-18 17:39:43255 MockAffectedFile('foo.h', diff_foo_h),
oysteinec430ad42015-10-22 20:55:24256 MockAffectedFile('foo2.h', diff_foo2_h),
glidere61efad2015-02-18 17:39:43257 MockAffectedFile('bad.h', diff_bad_h)]
Saagar Sanghavifceeaae2020-08-12 16:40:36258 warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
glidere61efad2015-02-18 17:39:43259 MockOutputApi())
260 self.assertEqual(1, len(warnings))
Sylvain Defresnea8b73d252018-02-28 15:45:54261 self.assertEqual(1, len(warnings[0].items))
glidere61efad2015-02-18 17:39:43262 self.assertEqual('error', warnings[0].type)
olli.raula36aa8be2015-09-10 11:14:22263 self.assertTrue('Found base::Singleton<T>' in warnings[0].message)
glidere61efad2015-02-18 17:39:43264
265 def testSingletonInCC(self):
olli.raula36aa8be2015-09-10 11:14:22266 diff_cc = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43267 mock_input_api = MockInputApi()
268 mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)]
Saagar Sanghavifceeaae2020-08-12 16:40:36269 warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
glidere61efad2015-02-18 17:39:43270 MockOutputApi())
271 self.assertEqual(0, len(warnings))
272
273
[email protected]b00342e7f2013-03-26 16:21:54274class InvalidOSMacroNamesTest(unittest.TestCase):
275 def testInvalidOSMacroNames(self):
276 lines = ['#if defined(OS_WINDOWS)',
277 ' #elif defined(OS_WINDOW)',
Avi Drissman34594e902020-07-25 05:35:44278 ' # if defined(OS_MAC) || defined(OS_CHROME)',
Avi Drissman32967a9e2020-07-30 04:10:32279 '# else // defined(OS_MACOSX)',
[email protected]b00342e7f2013-03-26 16:21:54280 '#endif // defined(OS_MACOS)']
281 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
282 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
283 self.assertEqual(len(lines), len(errors))
284 self.assertTrue(':1 OS_WINDOWS' in errors[0])
285 self.assertTrue('(did you mean OS_WIN?)' in errors[0])
286
287 def testValidOSMacroNames(self):
288 lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS]
289 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
290 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
291 self.assertEqual(0, len(errors))
292
293
lliabraa35bab3932014-10-01 12:16:44294class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
295 def testInvalidIfDefinedMacroNames(self):
296 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
297 '#if !defined(TARGET_IPHONE_SIMULATOR)',
298 '#elif defined(TARGET_IPHONE_SIMULATOR)',
299 '#ifdef TARGET_IPHONE_SIMULATOR',
300 ' # ifdef TARGET_IPHONE_SIMULATOR',
301 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
302 '# else // defined(TARGET_IPHONE_SIMULATOR)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39303 '#endif // defined(TARGET_IPHONE_SIMULATOR)']
lliabraa35bab3932014-10-01 12:16:44304 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
305 MockInputApi(), MockFile('some/path/source.mm', lines))
306 self.assertEqual(len(lines), len(errors))
307
308 def testValidIfDefinedMacroNames(self):
309 lines = ['#if defined(FOO)',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39310 '#ifdef BAR']
lliabraa35bab3932014-10-01 12:16:44311 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
312 MockInputApi(), MockFile('some/path/source.cc', lines))
313 self.assertEqual(0, len(errors))
314
315
Samuel Huang0db2ea22019-12-09 16:42:47316class CheckAddedDepsHaveTestApprovalsTest(unittest.TestCase):
Daniel Cheng4dcdb6b2017-04-13 08:30:17317
318 def calculate(self, old_include_rules, old_specific_include_rules,
319 new_include_rules, new_specific_include_rules):
320 return PRESUBMIT._CalculateAddedDeps(
321 os.path, 'include_rules = %r\nspecific_include_rules = %r' % (
322 old_include_rules, old_specific_include_rules),
323 'include_rules = %r\nspecific_include_rules = %r' % (
324 new_include_rules, new_specific_include_rules))
325
326 def testCalculateAddedDeps(self):
327 old_include_rules = [
328 '+base',
329 '-chrome',
330 '+content',
331 '-grit',
332 '-grit/",',
333 '+jni/fooblat.h',
334 '!sandbox',
[email protected]f32e2d1e2013-07-26 21:39:08335 ]
Daniel Cheng4dcdb6b2017-04-13 08:30:17336 old_specific_include_rules = {
337 'compositor\.*': {
338 '+cc',
339 },
340 }
341
342 new_include_rules = [
343 '-ash',
344 '+base',
345 '+chrome',
346 '+components',
347 '+content',
348 '+grit',
349 '+grit/generated_resources.h",',
350 '+grit/",',
351 '+jni/fooblat.h',
352 '+policy',
manzagop85e629e2017-05-09 22:11:48353 '+' + os.path.join('third_party', 'WebKit'),
Daniel Cheng4dcdb6b2017-04-13 08:30:17354 ]
355 new_specific_include_rules = {
356 'compositor\.*': {
357 '+cc',
358 },
359 'widget\.*': {
360 '+gpu',
361 },
362 }
363
[email protected]f32e2d1e2013-07-26 21:39:08364 expected = set([
manzagop85e629e2017-05-09 22:11:48365 os.path.join('chrome', 'DEPS'),
366 os.path.join('gpu', 'DEPS'),
367 os.path.join('components', 'DEPS'),
368 os.path.join('policy', 'DEPS'),
369 os.path.join('third_party', 'WebKit', 'DEPS'),
[email protected]f32e2d1e2013-07-26 21:39:08370 ])
Daniel Cheng4dcdb6b2017-04-13 08:30:17371 self.assertEqual(
372 expected,
373 self.calculate(old_include_rules, old_specific_include_rules,
374 new_include_rules, new_specific_include_rules))
375
376 def testCalculateAddedDepsIgnoresPermutations(self):
377 old_include_rules = [
378 '+base',
379 '+chrome',
380 ]
381 new_include_rules = [
382 '+chrome',
383 '+base',
384 ]
385 self.assertEqual(set(),
386 self.calculate(old_include_rules, {}, new_include_rules,
387 {}))
[email protected]f32e2d1e2013-07-26 21:39:08388
389
[email protected]99171a92014-06-03 08:44:47390class JSONParsingTest(unittest.TestCase):
391 def testSuccess(self):
392 input_api = MockInputApi()
393 filename = 'valid_json.json'
394 contents = ['// This is a comment.',
395 '{',
396 ' "key1": ["value1", "value2"],',
397 ' "key2": 3 // This is an inline comment.',
398 '}'
399 ]
400 input_api.files = [MockFile(filename, contents)]
401 self.assertEqual(None,
402 PRESUBMIT._GetJSONParseError(input_api, filename))
403
404 def testFailure(self):
405 input_api = MockInputApi()
406 test_data = [
407 ('invalid_json_1.json',
408 ['{ x }'],
[email protected]a3343272014-06-17 11:41:53409 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47410 ('invalid_json_2.json',
411 ['// Hello world!',
412 '{ "hello": "world }'],
[email protected]a3343272014-06-17 11:41:53413 'Unterminated string starting at:'),
[email protected]99171a92014-06-03 08:44:47414 ('invalid_json_3.json',
415 ['{ "a": "b", "c": "d", }'],
[email protected]a3343272014-06-17 11:41:53416 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47417 ('invalid_json_4.json',
418 ['{ "a": "b" "c": "d" }'],
[email protected]a3343272014-06-17 11:41:53419 'Expecting , delimiter:'),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39420 ]
[email protected]99171a92014-06-03 08:44:47421
422 input_api.files = [MockFile(filename, contents)
423 for (filename, contents, _) in test_data]
424
425 for (filename, _, expected_error) in test_data:
426 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
[email protected]a3343272014-06-17 11:41:53427 self.assertTrue(expected_error in str(actual_error),
428 "'%s' not found in '%s'" % (expected_error, actual_error))
[email protected]99171a92014-06-03 08:44:47429
430 def testNoEatComments(self):
431 input_api = MockInputApi()
432 file_with_comments = 'file_with_comments.json'
433 contents_with_comments = ['// This is a comment.',
434 '{',
435 ' "key1": ["value1", "value2"],',
436 ' "key2": 3 // This is an inline comment.',
437 '}'
438 ]
439 file_without_comments = 'file_without_comments.json'
440 contents_without_comments = ['{',
441 ' "key1": ["value1", "value2"],',
442 ' "key2": 3',
443 '}'
444 ]
445 input_api.files = [MockFile(file_with_comments, contents_with_comments),
446 MockFile(file_without_comments,
447 contents_without_comments)]
448
449 self.assertEqual('No JSON object could be decoded',
450 str(PRESUBMIT._GetJSONParseError(input_api,
451 file_with_comments,
452 eat_comments=False)))
453 self.assertEqual(None,
454 PRESUBMIT._GetJSONParseError(input_api,
455 file_without_comments,
456 eat_comments=False))
457
458
459class IDLParsingTest(unittest.TestCase):
460 def testSuccess(self):
461 input_api = MockInputApi()
462 filename = 'valid_idl_basics.idl'
463 contents = ['// Tests a valid IDL file.',
464 'namespace idl_basics {',
465 ' enum EnumType {',
466 ' name1,',
467 ' name2',
468 ' };',
469 '',
470 ' dictionary MyType1 {',
471 ' DOMString a;',
472 ' };',
473 '',
474 ' callback Callback1 = void();',
475 ' callback Callback2 = void(long x);',
476 ' callback Callback3 = void(MyType1 arg);',
477 ' callback Callback4 = void(EnumType type);',
478 '',
479 ' interface Functions {',
480 ' static void function1();',
481 ' static void function2(long x);',
482 ' static void function3(MyType1 arg);',
483 ' static void function4(Callback1 cb);',
484 ' static void function5(Callback2 cb);',
485 ' static void function6(Callback3 cb);',
486 ' static void function7(Callback4 cb);',
487 ' };',
488 '',
489 ' interface Events {',
490 ' static void onFoo1();',
491 ' static void onFoo2(long x);',
492 ' static void onFoo2(MyType1 arg);',
493 ' static void onFoo3(EnumType type);',
494 ' };',
495 '};'
496 ]
497 input_api.files = [MockFile(filename, contents)]
498 self.assertEqual(None,
499 PRESUBMIT._GetIDLParseError(input_api, filename))
500
501 def testFailure(self):
502 input_api = MockInputApi()
503 test_data = [
504 ('invalid_idl_1.idl',
505 ['//',
506 'namespace test {',
507 ' dictionary {',
508 ' DOMString s;',
509 ' };',
510 '};'],
511 'Unexpected "{" after keyword "dictionary".\n'),
512 # TODO(yoz): Disabled because it causes the IDL parser to hang.
513 # See crbug.com/363830.
514 # ('invalid_idl_2.idl',
515 # (['namespace test {',
516 # ' dictionary MissingSemicolon {',
517 # ' DOMString a',
518 # ' DOMString b;',
519 # ' };',
520 # '};'],
521 # 'Unexpected symbol DOMString after symbol a.'),
522 ('invalid_idl_3.idl',
523 ['//',
524 'namespace test {',
525 ' enum MissingComma {',
526 ' name1',
527 ' name2',
528 ' };',
529 '};'],
530 'Unexpected symbol name2 after symbol name1.'),
531 ('invalid_idl_4.idl',
532 ['//',
533 'namespace test {',
534 ' enum TrailingComma {',
535 ' name1,',
536 ' name2,',
537 ' };',
538 '};'],
539 'Trailing comma in block.'),
540 ('invalid_idl_5.idl',
541 ['//',
542 'namespace test {',
543 ' callback Callback1 = void(;',
544 '};'],
545 'Unexpected ";" after "(".'),
546 ('invalid_idl_6.idl',
547 ['//',
548 'namespace test {',
549 ' callback Callback1 = void(long );',
550 '};'],
551 'Unexpected ")" after symbol long.'),
552 ('invalid_idl_7.idl',
553 ['//',
554 'namespace test {',
555 ' interace Events {',
556 ' static void onFoo1();',
557 ' };',
558 '};'],
559 'Unexpected symbol Events after symbol interace.'),
560 ('invalid_idl_8.idl',
561 ['//',
562 'namespace test {',
563 ' interface NotEvent {',
564 ' static void onFoo1();',
565 ' };',
566 '};'],
567 'Did not process Interface Interface(NotEvent)'),
568 ('invalid_idl_9.idl',
569 ['//',
570 'namespace test {',
571 ' interface {',
572 ' static void function1();',
573 ' };',
574 '};'],
575 'Interface missing name.'),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39576 ]
[email protected]99171a92014-06-03 08:44:47577
578 input_api.files = [MockFile(filename, contents)
579 for (filename, contents, _) in test_data]
580
581 for (filename, _, expected_error) in test_data:
582 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
583 self.assertTrue(expected_error in str(actual_error),
584 "'%s' not found in '%s'" % (expected_error, actual_error))
585
586
[email protected]0bb112362014-07-26 04:38:32587class TryServerMasterTest(unittest.TestCase):
588 def testTryServerMasters(self):
589 bots = {
tandriie5587792016-07-14 00:34:50590 'master.tryserver.chromium.android': [
jbudorick3ae7a772016-05-20 02:36:04591 'android_archive_rel_ng',
592 'android_arm64_dbg_recipe',
593 'android_blink_rel',
jbudorick3ae7a772016-05-20 02:36:04594 'android_clang_dbg_recipe',
595 'android_compile_dbg',
jbudorick3ae7a772016-05-20 02:36:04596 'android_compile_x64_dbg',
597 'android_compile_x86_dbg',
598 'android_coverage',
599 'android_cronet_tester'
600 'android_swarming_rel',
601 'cast_shell_android',
602 'linux_android_dbg_ng',
603 'linux_android_rel_ng',
604 ],
tandriie5587792016-07-14 00:34:50605 'master.tryserver.chromium.mac': [
[email protected]0bb112362014-07-26 04:38:32606 'ios_dbg_simulator',
607 'ios_rel_device',
608 'ios_rel_device_ninja',
609 'mac_asan',
610 'mac_asan_64',
611 'mac_chromium_compile_dbg',
612 'mac_chromium_compile_rel',
613 'mac_chromium_dbg',
614 'mac_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32615 'mac_nacl_sdk',
616 'mac_nacl_sdk_build',
617 'mac_rel_naclmore',
[email protected]0bb112362014-07-26 04:38:32618 'mac_x64_rel',
619 'mac_xcodebuild',
620 ],
tandriie5587792016-07-14 00:34:50621 'master.tryserver.chromium.linux': [
[email protected]0bb112362014-07-26 04:38:32622 'chromium_presubmit',
623 'linux_arm_cross_compile',
624 'linux_arm_tester',
[email protected]0bb112362014-07-26 04:38:32625 'linux_chromeos_asan',
626 'linux_chromeos_browser_asan',
627 'linux_chromeos_valgrind',
[email protected]0bb112362014-07-26 04:38:32628 'linux_chromium_chromeos_dbg',
629 'linux_chromium_chromeos_rel',
[email protected]0bb112362014-07-26 04:38:32630 'linux_chromium_compile_dbg',
631 'linux_chromium_compile_rel',
632 'linux_chromium_dbg',
633 'linux_chromium_gn_dbg',
634 'linux_chromium_gn_rel',
635 'linux_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32636 'linux_chromium_trusty32_dbg',
637 'linux_chromium_trusty32_rel',
638 'linux_chromium_trusty_dbg',
639 'linux_chromium_trusty_rel',
640 'linux_clang_tsan',
641 'linux_ecs_ozone',
642 'linux_layout',
643 'linux_layout_asan',
644 'linux_layout_rel',
645 'linux_layout_rel_32',
646 'linux_nacl_sdk',
647 'linux_nacl_sdk_bionic',
648 'linux_nacl_sdk_bionic_build',
649 'linux_nacl_sdk_build',
650 'linux_redux',
651 'linux_rel_naclmore',
652 'linux_rel_precise32',
653 'linux_valgrind',
654 'tools_build_presubmit',
655 ],
tandriie5587792016-07-14 00:34:50656 'master.tryserver.chromium.win': [
[email protected]0bb112362014-07-26 04:38:32657 'win8_aura',
658 'win8_chromium_dbg',
659 'win8_chromium_rel',
660 'win_chromium_compile_dbg',
661 'win_chromium_compile_rel',
662 'win_chromium_dbg',
663 'win_chromium_rel',
664 'win_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32665 'win_chromium_x64_dbg',
666 'win_chromium_x64_rel',
[email protected]0bb112362014-07-26 04:38:32667 'win_nacl_sdk',
668 'win_nacl_sdk_build',
669 'win_rel_naclmore',
670 ],
671 }
672 for master, bots in bots.iteritems():
673 for bot in bots:
674 self.assertEqual(master, PRESUBMIT.GetTryServerMasterForBot(bot),
675 'bot=%s: expected %s, computed %s' % (
676 bot, master, PRESUBMIT.GetTryServerMasterForBot(bot)))
677
678
davileene0426252015-03-02 21:10:41679class UserMetricsActionTest(unittest.TestCase):
680 def testUserMetricsActionInActions(self):
681 input_api = MockInputApi()
682 file_with_user_action = 'file_with_user_action.cc'
683 contents_with_user_action = [
684 'base::UserMetricsAction("AboutChrome")'
685 ]
686
687 input_api.files = [MockFile(file_with_user_action,
688 contents_with_user_action)]
689
690 self.assertEqual(
Saagar Sanghavifceeaae2020-08-12 16:40:36691 [], PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi()))
davileene0426252015-03-02 21:10:41692
davileene0426252015-03-02 21:10:41693 def testUserMetricsActionNotAddedToActions(self):
694 input_api = MockInputApi()
695 file_with_user_action = 'file_with_user_action.cc'
696 contents_with_user_action = [
697 'base::UserMetricsAction("NotInActionsXml")'
698 ]
699
700 input_api.files = [MockFile(file_with_user_action,
701 contents_with_user_action)]
702
Saagar Sanghavifceeaae2020-08-12 16:40:36703 output = PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi())
davileene0426252015-03-02 21:10:41704 self.assertEqual(
705 ('File %s line %d: %s is missing in '
706 'tools/metrics/actions/actions.xml. Please run '
707 'tools/metrics/actions/extract_actions.py to update.'
708 % (file_with_user_action, 1, 'NotInActionsXml')),
709 output[0].message)
710
711
agrievef32bcc72016-04-04 14:57:40712class PydepsNeedsUpdatingTest(unittest.TestCase):
713
714 class MockSubprocess(object):
715 CalledProcessError = subprocess.CalledProcessError
716
Mohamed Heikal7cd4d8312020-06-16 16:49:40717 def _MockParseGclientArgs(self, is_android=True):
718 return lambda: {'checkout_android': 'true' if is_android else 'false' }
719
agrievef32bcc72016-04-04 14:57:40720 def setUp(self):
Mohamed Heikal7cd4d8312020-06-16 16:49:40721 mock_all_pydeps = ['A.pydeps', 'B.pydeps', 'D.pydeps']
agrievef32bcc72016-04-04 14:57:40722 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
723 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
Mohamed Heikal7cd4d8312020-06-16 16:49:40724 mock_android_pydeps = ['D.pydeps']
725 self.old_ANDROID_SPECIFIC_PYDEPS_FILES = (
726 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES)
727 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = mock_android_pydeps
728 self.old_ParseGclientArgs = PRESUBMIT._ParseGclientArgs
729 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs()
agrievef32bcc72016-04-04 14:57:40730 self.mock_input_api = MockInputApi()
731 self.mock_output_api = MockOutputApi()
732 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
733 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
734 self.checker._file_cache = {
Andrew Grieve5bb4cf702020-10-22 20:21:39735 'A.pydeps': '# Generated by:\n# CMD --output A.pydeps A\nA.py\nC.py\n',
736 'B.pydeps': '# Generated by:\n# CMD --output B.pydeps B\nB.py\nC.py\n',
737 'D.pydeps': '# Generated by:\n# CMD --output D.pydeps D\nD.py\n',
agrievef32bcc72016-04-04 14:57:40738 }
739
740 def tearDown(self):
741 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
Mohamed Heikal7cd4d8312020-06-16 16:49:40742 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES = (
743 self.old_ANDROID_SPECIFIC_PYDEPS_FILES)
744 PRESUBMIT._ParseGclientArgs = self.old_ParseGclientArgs
agrievef32bcc72016-04-04 14:57:40745
746 def _RunCheck(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36747 return PRESUBMIT.CheckPydepsNeedsUpdating(self.mock_input_api,
agrievef32bcc72016-04-04 14:57:40748 self.mock_output_api,
749 checker_for_tests=self.checker)
750
751 def testAddedPydep(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36752 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13753 if self.mock_input_api.platform != 'linux2':
754 return []
755
agrievef32bcc72016-04-04 14:57:40756 self.mock_input_api.files = [
757 MockAffectedFile('new.pydeps', [], action='A'),
758 ]
759
Zhiling Huang45cabf32018-03-10 00:50:03760 self.mock_input_api.CreateMockFileInPath(
761 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
762 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40763 results = self._RunCheck()
764 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39765 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40766
Zhiling Huang45cabf32018-03-10 00:50:03767 def testPydepNotInSrc(self):
768 self.mock_input_api.files = [
769 MockAffectedFile('new.pydeps', [], action='A'),
770 ]
771 self.mock_input_api.CreateMockFileInPath([])
772 results = self._RunCheck()
773 self.assertEqual(0, len(results))
774
agrievef32bcc72016-04-04 14:57:40775 def testRemovedPydep(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36776 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13777 if self.mock_input_api.platform != 'linux2':
778 return []
779
agrievef32bcc72016-04-04 14:57:40780 self.mock_input_api.files = [
781 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
782 ]
Zhiling Huang45cabf32018-03-10 00:50:03783 self.mock_input_api.CreateMockFileInPath(
784 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
785 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40786 results = self._RunCheck()
787 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39788 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40789
790 def testRandomPyIgnored(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36791 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13792 if self.mock_input_api.platform != 'linux2':
793 return []
794
agrievef32bcc72016-04-04 14:57:40795 self.mock_input_api.files = [
796 MockAffectedFile('random.py', []),
797 ]
798
799 results = self._RunCheck()
800 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
801
802 def testRelevantPyNoChange(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36803 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13804 if self.mock_input_api.platform != 'linux2':
805 return []
806
agrievef32bcc72016-04-04 14:57:40807 self.mock_input_api.files = [
808 MockAffectedFile('A.py', []),
809 ]
810
John Budorickab2fa102017-10-06 16:59:49811 def mock_check_output(cmd, shell=False, env=None):
Andrew Grieve5bb4cf702020-10-22 20:21:39812 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
agrievef32bcc72016-04-04 14:57:40813 return self.checker._file_cache['A.pydeps']
814
815 self.mock_input_api.subprocess.check_output = mock_check_output
816
817 results = self._RunCheck()
818 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
819
820 def testRelevantPyOneChange(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36821 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13822 if self.mock_input_api.platform != 'linux2':
823 return []
824
agrievef32bcc72016-04-04 14:57:40825 self.mock_input_api.files = [
826 MockAffectedFile('A.py', []),
827 ]
828
John Budorickab2fa102017-10-06 16:59:49829 def mock_check_output(cmd, shell=False, env=None):
Andrew Grieve5bb4cf702020-10-22 20:21:39830 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
agrievef32bcc72016-04-04 14:57:40831 return 'changed data'
832
833 self.mock_input_api.subprocess.check_output = mock_check_output
834
835 results = self._RunCheck()
836 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39837 self.assertIn('File is stale', str(results[0]))
agrievef32bcc72016-04-04 14:57:40838
839 def testRelevantPyTwoChanges(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36840 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
pastarmovj89f7ee12016-09-20 14:58:13841 if self.mock_input_api.platform != 'linux2':
842 return []
843
agrievef32bcc72016-04-04 14:57:40844 self.mock_input_api.files = [
845 MockAffectedFile('C.py', []),
846 ]
847
John Budorickab2fa102017-10-06 16:59:49848 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40849 return 'changed data'
850
851 self.mock_input_api.subprocess.check_output = mock_check_output
852
853 results = self._RunCheck()
854 self.assertEqual(2, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39855 self.assertIn('File is stale', str(results[0]))
856 self.assertIn('File is stale', str(results[1]))
agrievef32bcc72016-04-04 14:57:40857
Mohamed Heikal7cd4d8312020-06-16 16:49:40858 def testRelevantAndroidPyInNonAndroidCheckout(self):
Saagar Sanghavifceeaae2020-08-12 16:40:36859 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
Mohamed Heikal7cd4d8312020-06-16 16:49:40860 if self.mock_input_api.platform != 'linux2':
861 return []
862
863 self.mock_input_api.files = [
864 MockAffectedFile('D.py', []),
865 ]
866
867 def mock_check_output(cmd, shell=False, env=None):
Andrew Grieve5bb4cf702020-10-22 20:21:39868 self.assertEqual('CMD --output D.pydeps D --output ""', cmd)
Mohamed Heikal7cd4d8312020-06-16 16:49:40869 return 'changed data'
870
871 self.mock_input_api.subprocess.check_output = mock_check_output
872 PRESUBMIT._ParseGclientArgs = self._MockParseGclientArgs(is_android=False)
873
874 results = self._RunCheck()
875 self.assertEqual(1, len(results))
Andrew Grieve5bb4cf702020-10-22 20:21:39876 self.assertIn('Android', str(results[0]))
877 self.assertIn('D.pydeps', str(results[0]))
878
879 def testGnPathsAndMissingOutputFlag(self):
880 # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
881 if self.mock_input_api.platform != 'linux2':
882 return []
883
884 self.checker._file_cache = {
885 'A.pydeps': '# Generated by:\n# CMD --gn-paths A\n//A.py\n//C.py\n',
886 'B.pydeps': '# Generated by:\n# CMD --gn-paths B\n//B.py\n//C.py\n',
887 'D.pydeps': '# Generated by:\n# CMD --gn-paths D\n//D.py\n',
888 }
889
890 self.mock_input_api.files = [
891 MockAffectedFile('A.py', []),
892 ]
893
894 def mock_check_output(cmd, shell=False, env=None):
895 self.assertEqual('CMD --gn-paths A --output A.pydeps --output ""', cmd)
896 return 'changed data'
897
898 self.mock_input_api.subprocess.check_output = mock_check_output
899
900 results = self._RunCheck()
901 self.assertEqual(1, len(results))
902 self.assertIn('File is stale', str(results[0]))
Mohamed Heikal7cd4d8312020-06-16 16:49:40903
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39904
Daniel Bratell8ba52722018-03-02 16:06:14905class IncludeGuardTest(unittest.TestCase):
906 def testIncludeGuardChecks(self):
907 mock_input_api = MockInputApi()
908 mock_output_api = MockOutputApi()
909 mock_input_api.files = [
910 MockAffectedFile('content/browser/thing/foo.h', [
911 '// Comment',
912 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
913 '#define CONTENT_BROWSER_THING_FOO_H_',
914 'struct McBoatFace;',
915 '#endif // CONTENT_BROWSER_THING_FOO_H_',
916 ]),
917 MockAffectedFile('content/browser/thing/bar.h', [
918 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
919 '#define CONTENT_BROWSER_THING_BAR_H_',
920 'namespace content {',
921 '#endif // CONTENT_BROWSER_THING_BAR_H_',
922 '} // namespace content',
923 ]),
924 MockAffectedFile('content/browser/test1.h', [
925 'namespace content {',
926 '} // namespace content',
927 ]),
928 MockAffectedFile('content\\browser\\win.h', [
929 '#ifndef CONTENT_BROWSER_WIN_H_',
930 '#define CONTENT_BROWSER_WIN_H_',
931 'struct McBoatFace;',
932 '#endif // CONTENT_BROWSER_WIN_H_',
933 ]),
934 MockAffectedFile('content/browser/test2.h', [
935 '// Comment',
936 '#ifndef CONTENT_BROWSER_TEST2_H_',
937 'struct McBoatFace;',
938 '#endif // CONTENT_BROWSER_TEST2_H_',
939 ]),
940 MockAffectedFile('content/browser/internal.h', [
941 '// Comment',
942 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
943 '#define CONTENT_BROWSER_INTERNAL_H_',
944 '// Comment',
945 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
946 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
947 'namespace internal {',
948 '} // namespace internal',
949 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
950 'namespace content {',
951 '} // namespace content',
952 '#endif // CONTENT_BROWSER_THING_BAR_H_',
953 ]),
954 MockAffectedFile('content/browser/thing/foo.cc', [
955 '// This is a non-header.',
956 ]),
957 MockAffectedFile('content/browser/disabled.h', [
958 '// no-include-guard-because-multiply-included',
959 'struct McBoatFace;',
960 ]),
961 # New files don't allow misspelled include guards.
962 MockAffectedFile('content/browser/spleling.h', [
963 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
964 '#define CONTENT_BROWSER_SPLLEING_H_',
965 'struct McBoatFace;',
966 '#endif // CONTENT_BROWSER_SPLLEING_H_',
967 ]),
Olivier Robinbba137492018-07-30 11:31:34968 # New files don't allow + in include guards.
969 MockAffectedFile('content/browser/foo+bar.h', [
970 '#ifndef CONTENT_BROWSER_FOO+BAR_H_',
971 '#define CONTENT_BROWSER_FOO+BAR_H_',
972 'struct McBoatFace;',
973 '#endif // CONTENT_BROWSER_FOO+BAR_H_',
974 ]),
Daniel Bratell8ba52722018-03-02 16:06:14975 # Old files allow misspelled include guards (for now).
976 MockAffectedFile('chrome/old.h', [
977 '// New contents',
978 '#ifndef CHROME_ODL_H_',
979 '#define CHROME_ODL_H_',
980 '#endif // CHROME_ODL_H_',
981 ], [
982 '// Old contents',
983 '#ifndef CHROME_ODL_H_',
984 '#define CHROME_ODL_H_',
985 '#endif // CHROME_ODL_H_',
986 ]),
987 # Using a Blink style include guard outside Blink is wrong.
988 MockAffectedFile('content/NotInBlink.h', [
989 '#ifndef NotInBlink_h',
990 '#define NotInBlink_h',
991 'struct McBoatFace;',
992 '#endif // NotInBlink_h',
993 ]),
Daniel Bratell39b5b062018-05-16 18:09:57994 # Using a Blink style include guard in Blink is no longer ok.
995 MockAffectedFile('third_party/blink/InBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14996 '#ifndef InBlink_h',
997 '#define InBlink_h',
998 'struct McBoatFace;',
999 '#endif // InBlink_h',
1000 ]),
1001 # Using a bad include guard in Blink is not ok.
Daniel Bratell39b5b062018-05-16 18:09:571002 MockAffectedFile('third_party/blink/AlsoInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:141003 '#ifndef WrongInBlink_h',
1004 '#define WrongInBlink_h',
1005 'struct McBoatFace;',
1006 '#endif // WrongInBlink_h',
1007 ]),
Daniel Bratell39b5b062018-05-16 18:09:571008 # Using a bad include guard in Blink is not accepted even if
1009 # it's an old file.
1010 MockAffectedFile('third_party/blink/StillInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:141011 '// New contents',
1012 '#ifndef AcceptedInBlink_h',
1013 '#define AcceptedInBlink_h',
1014 'struct McBoatFace;',
1015 '#endif // AcceptedInBlink_h',
1016 ], [
1017 '// Old contents',
1018 '#ifndef AcceptedInBlink_h',
1019 '#define AcceptedInBlink_h',
1020 'struct McBoatFace;',
1021 '#endif // AcceptedInBlink_h',
1022 ]),
Daniel Bratell39b5b062018-05-16 18:09:571023 # Using a non-Chromium include guard in third_party
1024 # (outside blink) is accepted.
1025 MockAffectedFile('third_party/foo/some_file.h', [
1026 '#ifndef REQUIRED_RPCNDR_H_',
1027 '#define REQUIRED_RPCNDR_H_',
1028 'struct SomeFileFoo;',
1029 '#endif // REQUIRED_RPCNDR_H_',
1030 ]),
Kinuko Yasuda0cdb3da2019-07-31 21:50:321031 # Not having proper include guard in *_message_generator.h
1032 # for old IPC messages is allowed.
1033 MockAffectedFile('content/common/content_message_generator.h', [
1034 '#undef CONTENT_COMMON_FOO_MESSAGES_H_',
1035 '#include "content/common/foo_messages.h"',
1036 '#ifndef CONTENT_COMMON_FOO_MESSAGES_H_',
1037 '#error "Failed to include content/common/foo_messages.h"',
1038 '#endif',
1039 ]),
Daniel Bratell8ba52722018-03-02 16:06:141040 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361041 msgs = PRESUBMIT.CheckForIncludeGuards(
Daniel Bratell8ba52722018-03-02 16:06:141042 mock_input_api, mock_output_api)
Olivier Robinbba137492018-07-30 11:31:341043 expected_fail_count = 8
Daniel Bratell8ba52722018-03-02 16:06:141044 self.assertEqual(expected_fail_count, len(msgs),
1045 'Expected %d items, found %d: %s'
1046 % (expected_fail_count, len(msgs), msgs))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391047 self.assertEqual(msgs[0].items, ['content/browser/thing/bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:141048 self.assertEqual(msgs[0].message,
1049 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
1050 'not covering the whole file')
1051
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391052 self.assertEqual(msgs[1].items, ['content/browser/test1.h'])
Daniel Bratell8ba52722018-03-02 16:06:141053 self.assertEqual(msgs[1].message,
1054 'Missing include guard CONTENT_BROWSER_TEST1_H_')
1055
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391056 self.assertEqual(msgs[2].items, ['content/browser/test2.h:3'])
Daniel Bratell8ba52722018-03-02 16:06:141057 self.assertEqual(msgs[2].message,
1058 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
1059 'include guard')
1060
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391061 self.assertEqual(msgs[3].items, ['content/browser/spleling.h:1'])
Daniel Bratell8ba52722018-03-02 16:06:141062 self.assertEqual(msgs[3].message,
1063 'Header using the wrong include guard name '
1064 'CONTENT_BROWSER_SPLLEING_H_')
1065
Olivier Robinbba137492018-07-30 11:31:341066 self.assertEqual(msgs[4].items, ['content/browser/foo+bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:141067 self.assertEqual(msgs[4].message,
Olivier Robinbba137492018-07-30 11:31:341068 'Missing include guard CONTENT_BROWSER_FOO_BAR_H_')
1069
1070 self.assertEqual(msgs[5].items, ['content/NotInBlink.h:1'])
1071 self.assertEqual(msgs[5].message,
Daniel Bratell8ba52722018-03-02 16:06:141072 'Header using the wrong include guard name '
1073 'NotInBlink_h')
1074
Olivier Robinbba137492018-07-30 11:31:341075 self.assertEqual(msgs[6].items, ['third_party/blink/InBlink.h:1'])
1076 self.assertEqual(msgs[6].message,
Daniel Bratell8ba52722018-03-02 16:06:141077 'Header using the wrong include guard name '
Daniel Bratell39b5b062018-05-16 18:09:571078 'InBlink_h')
1079
Olivier Robinbba137492018-07-30 11:31:341080 self.assertEqual(msgs[7].items, ['third_party/blink/AlsoInBlink.h:1'])
1081 self.assertEqual(msgs[7].message,
Daniel Bratell39b5b062018-05-16 18:09:571082 'Header using the wrong include guard name '
Daniel Bratell8ba52722018-03-02 16:06:141083 'WrongInBlink_h')
1084
Chris Hall59f8d0c72020-05-01 07:31:191085class AccessibilityRelnotesFieldTest(unittest.TestCase):
1086 def testRelnotesPresent(self):
1087 mock_input_api = MockInputApi()
1088 mock_output_api = MockOutputApi()
1089
1090 mock_input_api.files = [MockAffectedFile('ui/accessibility/foo.bar', [''])]
Akihiro Ota08108e542020-05-20 15:30:531091 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191092 mock_input_api.change.footers['AX-Relnotes'] = [
1093 'Important user facing change']
1094
Saagar Sanghavifceeaae2020-08-12 16:40:361095 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:191096 mock_input_api, mock_output_api)
1097 self.assertEqual(0, len(msgs),
1098 'Expected %d messages, found %d: %s'
1099 % (0, len(msgs), msgs))
1100
1101 def testRelnotesMissingFromAccessibilityChange(self):
1102 mock_input_api = MockInputApi()
1103 mock_output_api = MockOutputApi()
1104
1105 mock_input_api.files = [
1106 MockAffectedFile('some/file', ['']),
1107 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1108 MockAffectedFile('some/other/file', [''])
1109 ]
Akihiro Ota08108e542020-05-20 15:30:531110 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191111
Saagar Sanghavifceeaae2020-08-12 16:40:361112 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:191113 mock_input_api, mock_output_api)
1114 self.assertEqual(1, len(msgs),
1115 'Expected %d messages, found %d: %s'
1116 % (1, len(msgs), msgs))
1117 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1118 'Missing AX-Relnotes field message not found in errors')
1119
1120 # The relnotes footer is not required for changes which do not touch any
1121 # accessibility directories.
1122 def testIgnoresNonAccesssibilityCode(self):
1123 mock_input_api = MockInputApi()
1124 mock_output_api = MockOutputApi()
1125
1126 mock_input_api.files = [
1127 MockAffectedFile('some/file', ['']),
1128 MockAffectedFile('some/other/file', [''])
1129 ]
Akihiro Ota08108e542020-05-20 15:30:531130 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191131
Saagar Sanghavifceeaae2020-08-12 16:40:361132 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:191133 mock_input_api, mock_output_api)
1134 self.assertEqual(0, len(msgs),
1135 'Expected %d messages, found %d: %s'
1136 % (0, len(msgs), msgs))
1137
1138 # Test that our presubmit correctly raises an error for a set of known paths.
1139 def testExpectedPaths(self):
1140 filesToTest = [
1141 "chrome/browser/accessibility/foo.py",
1142 "chrome/browser/chromeos/arc/accessibility/foo.cc",
1143 "chrome/browser/ui/views/accessibility/foo.h",
1144 "chrome/browser/extensions/api/automation/foo.h",
1145 "chrome/browser/extensions/api/automation_internal/foo.cc",
1146 "chrome/renderer/extensions/accessibility_foo.h",
1147 "chrome/tests/data/accessibility/foo.html",
1148 "content/browser/accessibility/foo.cc",
1149 "content/renderer/accessibility/foo.h",
1150 "content/tests/data/accessibility/foo.cc",
1151 "extensions/renderer/api/automation/foo.h",
1152 "ui/accessibility/foo/bar/baz.cc",
1153 "ui/views/accessibility/foo/bar/baz.h",
1154 ]
1155
1156 for testFile in filesToTest:
1157 mock_input_api = MockInputApi()
1158 mock_output_api = MockOutputApi()
1159
1160 mock_input_api.files = [
1161 MockAffectedFile(testFile, [''])
1162 ]
Akihiro Ota08108e542020-05-20 15:30:531163 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191164
Saagar Sanghavifceeaae2020-08-12 16:40:361165 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:191166 mock_input_api, mock_output_api)
1167 self.assertEqual(1, len(msgs),
1168 'Expected %d messages, found %d: %s, for file %s'
1169 % (1, len(msgs), msgs, testFile))
1170 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1171 ('Missing AX-Relnotes field message not found in errors '
1172 ' for file %s' % (testFile)))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391173
Akihiro Ota08108e542020-05-20 15:30:531174 # Test that AX-Relnotes field can appear in the commit description (as long
1175 # as it appears at the beginning of a line).
1176 def testRelnotesInCommitDescription(self):
1177 mock_input_api = MockInputApi()
1178 mock_output_api = MockOutputApi()
1179
1180 mock_input_api.files = [
1181 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1182 ]
1183 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1184 'AX-Relnotes: solves all accessibility issues forever')
1185
Saagar Sanghavifceeaae2020-08-12 16:40:361186 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531187 mock_input_api, mock_output_api)
1188 self.assertEqual(0, len(msgs),
1189 'Expected %d messages, found %d: %s'
1190 % (0, len(msgs), msgs))
1191
1192 # Test that we don't match AX-Relnotes if it appears in the middle of a line.
1193 def testRelnotesMustAppearAtBeginningOfLine(self):
1194 mock_input_api = MockInputApi()
1195 mock_output_api = MockOutputApi()
1196
1197 mock_input_api.files = [
1198 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1199 ]
1200 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1201 'This change has no AX-Relnotes: we should print a warning')
1202
Saagar Sanghavifceeaae2020-08-12 16:40:361203 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531204 mock_input_api, mock_output_api)
1205 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1206 'Missing AX-Relnotes field message not found in errors')
1207
1208 # Tests that the AX-Relnotes field can be lowercase and use a '=' in place
1209 # of a ':'.
1210 def testRelnotesLowercaseWithEqualSign(self):
1211 mock_input_api = MockInputApi()
1212 mock_output_api = MockOutputApi()
1213
1214 mock_input_api.files = [
1215 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1216 ]
1217 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1218 'ax-relnotes= this is a valid format for accessibiliy relnotes')
1219
Saagar Sanghavifceeaae2020-08-12 16:40:361220 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531221 mock_input_api, mock_output_api)
1222 self.assertEqual(0, len(msgs),
1223 'Expected %d messages, found %d: %s'
1224 % (0, len(msgs), msgs))
1225
yolandyan45001472016-12-21 21:12:421226class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
1227 def testCheckAndroidTestAnnotationUsage(self):
1228 mock_input_api = MockInputApi()
1229 mock_output_api = MockOutputApi()
1230
1231 mock_input_api.files = [
1232 MockAffectedFile('LalaLand.java', [
1233 'random stuff'
1234 ]),
1235 MockAffectedFile('CorrectUsage.java', [
1236 'import android.support.test.filters.LargeTest;',
1237 'import android.support.test.filters.MediumTest;',
1238 'import android.support.test.filters.SmallTest;',
1239 ]),
1240 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
1241 'import android.test.suitebuilder.annotation.LargeTest;',
1242 ]),
1243 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
1244 'import android.test.suitebuilder.annotation.MediumTest;',
1245 ]),
1246 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
1247 'import android.test.suitebuilder.annotation.SmallTest;',
1248 ]),
1249 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
1250 'import android.test.suitebuilder.annotation.Smoke;',
1251 ])
1252 ]
1253 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
1254 mock_input_api, mock_output_api)
1255 self.assertEqual(1, len(msgs),
1256 'Expected %d items, found %d: %s'
1257 % (1, len(msgs), msgs))
1258 self.assertEqual(4, len(msgs[0].items),
1259 'Expected %d items, found %d: %s'
1260 % (4, len(msgs[0].items), msgs[0].items))
1261 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
1262 'UsedDeprecatedLargeTestAnnotation not found in errors')
1263 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
1264 in msgs[0].items,
1265 'UsedDeprecatedMediumTestAnnotation not found in errors')
1266 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
1267 'UsedDeprecatedSmallTestAnnotation not found in errors')
1268 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
1269 'UsedDeprecatedSmokeAnnotation not found in errors')
1270
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391271
Yoland Yanb92fa522017-08-28 17:37:061272class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271273 def testCheckAndroidTestJUnitFramework(self):
Yoland Yanb92fa522017-08-28 17:37:061274 mock_input_api = MockInputApi()
1275 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:421276
Yoland Yanb92fa522017-08-28 17:37:061277 mock_input_api.files = [
1278 MockAffectedFile('LalaLand.java', [
1279 'random stuff'
1280 ]),
1281 MockAffectedFile('CorrectUsage.java', [
1282 'import org.junit.ABC',
1283 'import org.junit.XYZ;',
1284 ]),
1285 MockAffectedFile('UsedDeprecatedJUnit.java', [
1286 'import junit.framework.*;',
1287 ]),
1288 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
1289 'import junit.framework.Assert;',
1290 ]),
1291 ]
1292 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
1293 mock_input_api, mock_output_api)
1294 self.assertEqual(1, len(msgs),
1295 'Expected %d items, found %d: %s'
1296 % (1, len(msgs), msgs))
1297 self.assertEqual(2, len(msgs[0].items),
1298 'Expected %d items, found %d: %s'
1299 % (2, len(msgs[0].items), msgs[0].items))
1300 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
1301 'UsedDeprecatedJUnit.java not found in errors')
1302 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
1303 in msgs[0].items,
1304 'UsedDeprecatedJUnitAssert not found in errors')
1305
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391306
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271307class AndroidJUnitBaseClassTest(unittest.TestCase):
1308 def testCheckAndroidTestJUnitBaseClass(self):
Yoland Yanb92fa522017-08-28 17:37:061309 mock_input_api = MockInputApi()
1310 mock_output_api = MockOutputApi()
1311
1312 mock_input_api.files = [
1313 MockAffectedFile('LalaLand.java', [
1314 'random stuff'
1315 ]),
1316 MockAffectedFile('CorrectTest.java', [
1317 '@RunWith(ABC.class);'
1318 'public class CorrectTest {',
1319 '}',
1320 ]),
1321 MockAffectedFile('HistoricallyIncorrectTest.java', [
1322 'public class Test extends BaseCaseA {',
1323 '}',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391324 ], old_contents=[
Yoland Yanb92fa522017-08-28 17:37:061325 'public class Test extends BaseCaseB {',
1326 '}',
1327 ]),
1328 MockAffectedFile('CorrectTestWithInterface.java', [
1329 '@RunWith(ABC.class);'
1330 'public class CorrectTest implement Interface {',
1331 '}',
1332 ]),
1333 MockAffectedFile('IncorrectTest.java', [
1334 'public class IncorrectTest extends TestCase {',
1335 '}',
1336 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241337 MockAffectedFile('IncorrectWithInterfaceTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061338 'public class Test implements X extends BaseClass {',
1339 '}',
1340 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241341 MockAffectedFile('IncorrectMultiLineTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061342 'public class Test implements X, Y, Z',
1343 ' extends TestBase {',
1344 '}',
1345 ]),
1346 ]
1347 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1348 mock_input_api, mock_output_api)
1349 self.assertEqual(1, len(msgs),
1350 'Expected %d items, found %d: %s'
1351 % (1, len(msgs), msgs))
1352 self.assertEqual(3, len(msgs[0].items),
1353 'Expected %d items, found %d: %s'
1354 % (3, len(msgs[0].items), msgs[0].items))
1355 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1356 'IncorrectTest not found in errors')
Vaclav Brozekf01ed502018-03-16 19:38:241357 self.assertTrue('IncorrectWithInterfaceTest.java:1'
Yoland Yanb92fa522017-08-28 17:37:061358 in msgs[0].items,
Vaclav Brozekf01ed502018-03-16 19:38:241359 'IncorrectWithInterfaceTest not found in errors')
1360 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1361 'IncorrectMultiLineTest not found in errors')
yolandyan45001472016-12-21 21:12:421362
Jinsong Fan91ebbbd2019-04-16 14:57:171363class AndroidDebuggableBuildTest(unittest.TestCase):
1364
1365 def testCheckAndroidDebuggableBuild(self):
1366 mock_input_api = MockInputApi()
1367 mock_output_api = MockOutputApi()
1368
1369 mock_input_api.files = [
1370 MockAffectedFile('RandomStuff.java', [
1371 'random stuff'
1372 ]),
1373 MockAffectedFile('CorrectUsage.java', [
1374 'import org.chromium.base.BuildInfo;',
1375 'some random stuff',
1376 'boolean isOsDebuggable = BuildInfo.isDebugAndroid();',
1377 ]),
1378 MockAffectedFile('JustCheckUserdebugBuild.java', [
1379 'import android.os.Build;',
1380 'some random stuff',
1381 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")',
1382 ]),
1383 MockAffectedFile('JustCheckEngineeringBuild.java', [
1384 'import android.os.Build;',
1385 'some random stuff',
1386 'boolean isOsDebuggable = "eng".equals(Build.TYPE)',
1387 ]),
1388 MockAffectedFile('UsedBuildType.java', [
1389 'import android.os.Build;',
1390 'some random stuff',
1391 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")'
1392 '|| "eng".equals(Build.TYPE)',
1393 ]),
1394 MockAffectedFile('UsedExplicitBuildType.java', [
1395 'some random stuff',
1396 'boolean isOsDebuggable = android.os.Build.TYPE.equals("userdebug")'
1397 '|| "eng".equals(android.os.Build.TYPE)',
1398 ]),
1399 ]
1400
1401 msgs = PRESUBMIT._CheckAndroidDebuggableBuild(
1402 mock_input_api, mock_output_api)
1403 self.assertEqual(1, len(msgs),
1404 'Expected %d items, found %d: %s'
1405 % (1, len(msgs), msgs))
1406 self.assertEqual(4, len(msgs[0].items),
1407 'Expected %d items, found %d: %s'
1408 % (4, len(msgs[0].items), msgs[0].items))
1409 self.assertTrue('JustCheckUserdebugBuild.java:3' in msgs[0].items)
1410 self.assertTrue('JustCheckEngineeringBuild.java:3' in msgs[0].items)
1411 self.assertTrue('UsedBuildType.java:3' in msgs[0].items)
1412 self.assertTrue('UsedExplicitBuildType.java:2' in msgs[0].items)
1413
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391414
dgn4401aa52015-04-29 16:26:171415class LogUsageTest(unittest.TestCase):
1416
dgnaa68d5e2015-06-10 10:08:221417 def testCheckAndroidCrLogUsage(self):
1418 mock_input_api = MockInputApi()
1419 mock_output_api = MockOutputApi()
1420
1421 mock_input_api.files = [
1422 MockAffectedFile('RandomStuff.java', [
1423 'random stuff'
1424 ]),
dgn87d9fb62015-06-12 09:15:121425 MockAffectedFile('HasAndroidLog.java', [
1426 'import android.util.Log;',
1427 'some random stuff',
1428 'Log.d("TAG", "foo");',
1429 ]),
1430 MockAffectedFile('HasExplicitUtilLog.java', [
1431 'some random stuff',
1432 'android.util.Log.d("TAG", "foo");',
1433 ]),
1434 MockAffectedFile('IsInBasePackage.java', [
1435 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511436 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121437 'Log.d(TAG, "foo");',
1438 ]),
1439 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1440 'package org.chromium.base;',
1441 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511442 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121443 'Log.d(TAG, "foo");',
1444 ]),
1445 MockAffectedFile('HasBothLog.java', [
1446 'import org.chromium.base.Log;',
1447 'some random stuff',
dgn38736db2015-09-18 19:20:511448 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121449 'Log.d(TAG, "foo");',
1450 'android.util.Log.d("TAG", "foo");',
1451 ]),
dgnaa68d5e2015-06-10 10:08:221452 MockAffectedFile('HasCorrectTag.java', [
1453 'import org.chromium.base.Log;',
1454 'some random stuff',
dgn38736db2015-09-18 19:20:511455 'private static final String TAG = "cr_Foo";',
1456 'Log.d(TAG, "foo");',
1457 ]),
1458 MockAffectedFile('HasOldTag.java', [
1459 'import org.chromium.base.Log;',
1460 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221461 'private static final String TAG = "cr.Foo";',
1462 'Log.d(TAG, "foo");',
1463 ]),
dgn38736db2015-09-18 19:20:511464 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221465 'import org.chromium.base.Log;',
1466 'some random stuff',
dgn38736db2015-09-18 19:20:511467 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221468 'Log.d(TAG, "foo");',
1469 ]),
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461470 MockAffectedFile('HasDottedTagPublic.java', [
1471 'import org.chromium.base.Log;',
1472 'some random stuff',
1473 'public static final String TAG = "cr_foo.bar";',
1474 'Log.d(TAG, "foo");',
1475 ]),
dgnaa68d5e2015-06-10 10:08:221476 MockAffectedFile('HasNoTagDecl.java', [
1477 'import org.chromium.base.Log;',
1478 'some random stuff',
1479 'Log.d(TAG, "foo");',
1480 ]),
1481 MockAffectedFile('HasIncorrectTagDecl.java', [
1482 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511483 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221484 'some random stuff',
1485 'Log.d(TAG, "foo");',
1486 ]),
1487 MockAffectedFile('HasInlineTag.java', [
1488 'import org.chromium.base.Log;',
1489 'some random stuff',
dgn38736db2015-09-18 19:20:511490 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221491 'Log.d("TAG", "foo");',
1492 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551493 MockAffectedFile('HasInlineTagWithSpace.java', [
1494 'import org.chromium.base.Log;',
1495 'some random stuff',
1496 'private static final String TAG = "cr_Foo";',
1497 'Log.d("log message", "foo");',
1498 ]),
dgn38736db2015-09-18 19:20:511499 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221500 'import org.chromium.base.Log;',
1501 'some random stuff',
1502 'private static final String TAG = "rubbish";',
1503 'Log.d(TAG, "foo");',
1504 ]),
1505 MockAffectedFile('HasTooLongTag.java', [
1506 'import org.chromium.base.Log;',
1507 'some random stuff',
dgn38736db2015-09-18 19:20:511508 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:221509 'Log.d(TAG, "foo");',
1510 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551511 MockAffectedFile('HasTooLongTagWithNoLogCallsInDiff.java', [
1512 'import org.chromium.base.Log;',
1513 'some random stuff',
1514 'private static final String TAG = "21_charachers_long___";',
1515 ]),
dgnaa68d5e2015-06-10 10:08:221516 ]
1517
1518 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1519 mock_input_api, mock_output_api)
1520
dgn38736db2015-09-18 19:20:511521 self.assertEqual(5, len(msgs),
1522 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221523
1524 # Declaration format
dgn38736db2015-09-18 19:20:511525 nb = len(msgs[0].items)
1526 self.assertEqual(2, nb,
1527 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221528 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1529 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221530
1531 # Tag length
dgn38736db2015-09-18 19:20:511532 nb = len(msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551533 self.assertEqual(2, nb,
1534 'Expected %d items, found %d: %s' % (2, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:221535 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551536 self.assertTrue('HasTooLongTagWithNoLogCallsInDiff.java' in msgs[1].items)
dgnaa68d5e2015-06-10 10:08:221537
1538 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511539 nb = len(msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551540 self.assertEqual(3, nb,
1541 'Expected %d items, found %d: %s' % (3, nb, msgs[2].items))
1542 self.assertTrue('HasBothLog.java:5' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221543 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551544 self.assertTrue('HasInlineTagWithSpace.java:4' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221545
dgn87d9fb62015-06-12 09:15:121546 # Util Log usage
dgn38736db2015-09-18 19:20:511547 nb = len(msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551548 self.assertEqual(3, nb,
1549 'Expected %d items, found %d: %s' % (3, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:121550 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551551 self.assertTrue('HasExplicitUtilLog.java:2' in msgs[3].items)
dgn87d9fb62015-06-12 09:15:121552 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:221553
dgn38736db2015-09-18 19:20:511554 # Tag must not contain
1555 nb = len(msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461556 self.assertEqual(3, nb,
dgn38736db2015-09-18 19:20:511557 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1558 self.assertTrue('HasDottedTag.java' in msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461559 self.assertTrue('HasDottedTagPublic.java' in msgs[4].items)
dgn38736db2015-09-18 19:20:511560 self.assertTrue('HasOldTag.java' in msgs[4].items)
1561
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391562
estadee17314a02017-01-12 16:22:161563class GoogleAnswerUrlFormatTest(unittest.TestCase):
1564
1565 def testCatchAnswerUrlId(self):
1566 input_api = MockInputApi()
1567 input_api.files = [
1568 MockFile('somewhere/file.cc',
1569 ['char* host = '
1570 ' "https://support.google.com/chrome/answer/123456";']),
1571 MockFile('somewhere_else/file.cc',
1572 ['char* host = '
1573 ' "https://support.google.com/chrome/a/answer/123456";']),
1574 ]
1575
Saagar Sanghavifceeaae2020-08-12 16:40:361576 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161577 input_api, MockOutputApi())
1578 self.assertEqual(1, len(warnings))
1579 self.assertEqual(2, len(warnings[0].items))
1580
1581 def testAllowAnswerUrlParam(self):
1582 input_api = MockInputApi()
1583 input_api.files = [
1584 MockFile('somewhere/file.cc',
1585 ['char* host = '
1586 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1587 ]
1588
Saagar Sanghavifceeaae2020-08-12 16:40:361589 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161590 input_api, MockOutputApi())
1591 self.assertEqual(0, len(warnings))
1592
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391593
reillyi38965732015-11-16 18:27:331594class HardcodedGoogleHostsTest(unittest.TestCase):
1595
1596 def testWarnOnAssignedLiterals(self):
1597 input_api = MockInputApi()
1598 input_api.files = [
1599 MockFile('content/file.cc',
1600 ['char* host = "https://www.google.com";']),
1601 MockFile('content/file.cc',
1602 ['char* host = "https://www.googleapis.com";']),
1603 MockFile('content/file.cc',
1604 ['char* host = "https://clients1.google.com";']),
1605 ]
1606
Saagar Sanghavifceeaae2020-08-12 16:40:361607 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331608 input_api, MockOutputApi())
1609 self.assertEqual(1, len(warnings))
1610 self.assertEqual(3, len(warnings[0].items))
1611
1612 def testAllowInComment(self):
1613 input_api = MockInputApi()
1614 input_api.files = [
1615 MockFile('content/file.cc',
1616 ['char* host = "https://www.aol.com"; // google.com'])
1617 ]
1618
Saagar Sanghavifceeaae2020-08-12 16:40:361619 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331620 input_api, MockOutputApi())
1621 self.assertEqual(0, len(warnings))
1622
dgn4401aa52015-04-29 16:26:171623
James Cook6b6597c2019-11-06 22:05:291624class ChromeOsSyncedPrefRegistrationTest(unittest.TestCase):
1625
1626 def testWarnsOnChromeOsDirectories(self):
1627 input_api = MockInputApi()
1628 input_api.files = [
1629 MockFile('ash/file.cc',
1630 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1631 MockFile('chrome/browser/chromeos/file.cc',
1632 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1633 MockFile('chromeos/file.cc',
1634 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1635 MockFile('components/arc/file.cc',
1636 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1637 MockFile('components/exo/file.cc',
1638 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1639 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361640 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291641 input_api, MockOutputApi())
1642 self.assertEqual(1, len(warnings))
1643
1644 def testDoesNotWarnOnSyncOsPref(self):
1645 input_api = MockInputApi()
1646 input_api.files = [
1647 MockFile('chromeos/file.cc',
1648 ['PrefRegistrySyncable::SYNCABLE_OS_PREF']),
1649 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361650 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291651 input_api, MockOutputApi())
1652 self.assertEqual(0, len(warnings))
1653
1654 def testDoesNotWarnOnCrossPlatformDirectories(self):
1655 input_api = MockInputApi()
1656 input_api.files = [
1657 MockFile('chrome/browser/ui/file.cc',
1658 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1659 MockFile('components/sync/file.cc',
1660 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1661 MockFile('content/browser/file.cc',
1662 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1663 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361664 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291665 input_api, MockOutputApi())
1666 self.assertEqual(0, len(warnings))
1667
1668 def testSeparateWarningForPriorityPrefs(self):
1669 input_api = MockInputApi()
1670 input_api.files = [
1671 MockFile('chromeos/file.cc',
1672 ['PrefRegistrySyncable::SYNCABLE_PREF',
1673 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']),
1674 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361675 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291676 input_api, MockOutputApi())
1677 self.assertEqual(2, len(warnings))
1678
1679
jbriance9e12f162016-11-25 07:57:501680class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311681 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501682 mock_input_api = MockInputApi()
1683 mock_input_api.files = [
1684 MockAffectedFile('somewhere/file.cc', [
1685 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311686 ]),
1687 MockAffectedFile('third_party/header.h', [
1688 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501689 ])
1690 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361691 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391692 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501693 self.assertEqual(0, len(warnings))
1694
1695 def testNoNestedDeclaration(self):
1696 mock_input_api = MockInputApi()
1697 mock_input_api.files = [
1698 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311699 'class SomeClass {',
1700 ' protected:',
1701 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501702 '};'
1703 ])
1704 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361705 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391706 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501707 self.assertEqual(0, len(warnings))
1708
1709 def testSubStrings(self):
1710 mock_input_api = MockInputApi()
1711 mock_input_api.files = [
1712 MockAffectedFile('somewhere/header.h', [
1713 'class NotUsefulClass;',
1714 'struct SomeStruct;',
1715 'UsefulClass *p1;',
1716 'SomeStructPtr *p2;'
1717 ])
1718 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361719 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391720 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501721 self.assertEqual(2, len(warnings))
1722
1723 def testUselessForwardDeclaration(self):
1724 mock_input_api = MockInputApi()
1725 mock_input_api.files = [
1726 MockAffectedFile('somewhere/header.h', [
1727 'class DummyClass;',
1728 'struct DummyStruct;',
1729 'class UsefulClass;',
1730 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311731 ])
jbriance9e12f162016-11-25 07:57:501732 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361733 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391734 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501735 self.assertEqual(2, len(warnings))
1736
jbriance2c51e821a2016-12-12 08:24:311737 def testBlinkHeaders(self):
1738 mock_input_api = MockInputApi()
1739 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491740 MockAffectedFile('third_party/blink/header.h', [
jbriance2c51e821a2016-12-12 08:24:311741 'class DummyClass;',
1742 'struct DummyStruct;',
1743 ]),
Kent Tamura32dbbcb2018-11-30 12:28:491744 MockAffectedFile('third_party\\blink\\header.h', [
jbriance2c51e821a2016-12-12 08:24:311745 'class DummyClass;',
1746 'struct DummyStruct;',
1747 ])
1748 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361749 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391750 MockOutputApi())
jbriance2c51e821a2016-12-12 08:24:311751 self.assertEqual(4, len(warnings))
1752
jbriance9e12f162016-11-25 07:57:501753
rlanday6802cf632017-05-30 17:48:361754class RelativeIncludesTest(unittest.TestCase):
1755 def testThirdPartyNotWebKitIgnored(self):
1756 mock_input_api = MockInputApi()
1757 mock_input_api.files = [
1758 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1759 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1760 ]
1761
1762 mock_output_api = MockOutputApi()
1763
Saagar Sanghavifceeaae2020-08-12 16:40:361764 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361765 mock_input_api, mock_output_api)
1766 self.assertEqual(0, len(errors))
1767
1768 def testNonCppFileIgnored(self):
1769 mock_input_api = MockInputApi()
1770 mock_input_api.files = [
1771 MockAffectedFile('test.py', '#include "../header.h"'),
1772 ]
1773
1774 mock_output_api = MockOutputApi()
1775
Saagar Sanghavifceeaae2020-08-12 16:40:361776 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361777 mock_input_api, mock_output_api)
1778 self.assertEqual(0, len(errors))
1779
1780 def testInnocuousChangesAllowed(self):
1781 mock_input_api = MockInputApi()
1782 mock_input_api.files = [
1783 MockAffectedFile('test.cpp', '#include "header.h"'),
1784 MockAffectedFile('test2.cpp', '../'),
1785 ]
1786
1787 mock_output_api = MockOutputApi()
1788
Saagar Sanghavifceeaae2020-08-12 16:40:361789 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361790 mock_input_api, mock_output_api)
1791 self.assertEqual(0, len(errors))
1792
1793 def testRelativeIncludeNonWebKitProducesError(self):
1794 mock_input_api = MockInputApi()
1795 mock_input_api.files = [
1796 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1797 ]
1798
1799 mock_output_api = MockOutputApi()
1800
Saagar Sanghavifceeaae2020-08-12 16:40:361801 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361802 mock_input_api, mock_output_api)
1803 self.assertEqual(1, len(errors))
1804
1805 def testRelativeIncludeWebKitProducesError(self):
1806 mock_input_api = MockInputApi()
1807 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491808 MockAffectedFile('third_party/blink/test.cpp',
rlanday6802cf632017-05-30 17:48:361809 ['#include "../header.h']),
1810 ]
1811
1812 mock_output_api = MockOutputApi()
1813
Saagar Sanghavifceeaae2020-08-12 16:40:361814 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361815 mock_input_api, mock_output_api)
1816 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241817
Daniel Cheng13ca61a882017-08-25 15:11:251818
Daniel Bratell65b033262019-04-23 08:17:061819class CCIncludeTest(unittest.TestCase):
1820 def testThirdPartyNotBlinkIgnored(self):
1821 mock_input_api = MockInputApi()
1822 mock_input_api.files = [
1823 MockAffectedFile('third_party/test.cpp', '#include "file.cc"'),
1824 ]
1825
1826 mock_output_api = MockOutputApi()
1827
Saagar Sanghavifceeaae2020-08-12 16:40:361828 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061829 mock_input_api, mock_output_api)
1830 self.assertEqual(0, len(errors))
1831
1832 def testPythonFileIgnored(self):
1833 mock_input_api = MockInputApi()
1834 mock_input_api.files = [
1835 MockAffectedFile('test.py', '#include "file.cc"'),
1836 ]
1837
1838 mock_output_api = MockOutputApi()
1839
Saagar Sanghavifceeaae2020-08-12 16:40:361840 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061841 mock_input_api, mock_output_api)
1842 self.assertEqual(0, len(errors))
1843
1844 def testIncFilesAccepted(self):
1845 mock_input_api = MockInputApi()
1846 mock_input_api.files = [
1847 MockAffectedFile('test.py', '#include "file.inc"'),
1848 ]
1849
1850 mock_output_api = MockOutputApi()
1851
Saagar Sanghavifceeaae2020-08-12 16:40:361852 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061853 mock_input_api, mock_output_api)
1854 self.assertEqual(0, len(errors))
1855
1856 def testInnocuousChangesAllowed(self):
1857 mock_input_api = MockInputApi()
1858 mock_input_api.files = [
1859 MockAffectedFile('test.cpp', '#include "header.h"'),
1860 MockAffectedFile('test2.cpp', 'Something "file.cc"'),
1861 ]
1862
1863 mock_output_api = MockOutputApi()
1864
Saagar Sanghavifceeaae2020-08-12 16:40:361865 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061866 mock_input_api, mock_output_api)
1867 self.assertEqual(0, len(errors))
1868
1869 def testCcIncludeNonBlinkProducesError(self):
1870 mock_input_api = MockInputApi()
1871 mock_input_api.files = [
1872 MockAffectedFile('test.cpp', ['#include "file.cc"']),
1873 ]
1874
1875 mock_output_api = MockOutputApi()
1876
Saagar Sanghavifceeaae2020-08-12 16:40:361877 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061878 mock_input_api, mock_output_api)
1879 self.assertEqual(1, len(errors))
1880
1881 def testCppIncludeBlinkProducesError(self):
1882 mock_input_api = MockInputApi()
1883 mock_input_api.files = [
1884 MockAffectedFile('third_party/blink/test.cpp',
1885 ['#include "foo/file.cpp"']),
1886 ]
1887
1888 mock_output_api = MockOutputApi()
1889
Saagar Sanghavifceeaae2020-08-12 16:40:361890 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061891 mock_input_api, mock_output_api)
1892 self.assertEqual(1, len(errors))
1893
1894
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191895class NewHeaderWithoutGnChangeTest(unittest.TestCase):
1896 def testAddHeaderWithoutGn(self):
1897 mock_input_api = MockInputApi()
1898 mock_input_api.files = [
1899 MockAffectedFile('base/stuff.h', ''),
1900 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361901 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191902 mock_input_api, MockOutputApi())
1903 self.assertEqual(1, len(warnings))
1904 self.assertTrue('base/stuff.h' in warnings[0].items)
1905
1906 def testModifyHeader(self):
1907 mock_input_api = MockInputApi()
1908 mock_input_api.files = [
1909 MockAffectedFile('base/stuff.h', '', action='M'),
1910 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361911 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191912 mock_input_api, MockOutputApi())
1913 self.assertEqual(0, len(warnings))
1914
1915 def testDeleteHeader(self):
1916 mock_input_api = MockInputApi()
1917 mock_input_api.files = [
1918 MockAffectedFile('base/stuff.h', '', action='D'),
1919 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361920 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191921 mock_input_api, MockOutputApi())
1922 self.assertEqual(0, len(warnings))
1923
1924 def testAddHeaderWithGn(self):
1925 mock_input_api = MockInputApi()
1926 mock_input_api.files = [
1927 MockAffectedFile('base/stuff.h', ''),
1928 MockAffectedFile('base/BUILD.gn', 'stuff.h'),
1929 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361930 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191931 mock_input_api, MockOutputApi())
1932 self.assertEqual(0, len(warnings))
1933
1934 def testAddHeaderWithGni(self):
1935 mock_input_api = MockInputApi()
1936 mock_input_api.files = [
1937 MockAffectedFile('base/stuff.h', ''),
1938 MockAffectedFile('base/files.gni', 'stuff.h'),
1939 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361940 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191941 mock_input_api, MockOutputApi())
1942 self.assertEqual(0, len(warnings))
1943
1944 def testAddHeaderWithOther(self):
1945 mock_input_api = MockInputApi()
1946 mock_input_api.files = [
1947 MockAffectedFile('base/stuff.h', ''),
1948 MockAffectedFile('base/stuff.cc', 'stuff.h'),
1949 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361950 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191951 mock_input_api, MockOutputApi())
1952 self.assertEqual(1, len(warnings))
1953
1954 def testAddHeaderWithWrongGn(self):
1955 mock_input_api = MockInputApi()
1956 mock_input_api.files = [
1957 MockAffectedFile('base/stuff.h', ''),
1958 MockAffectedFile('base/BUILD.gn', 'stuff_h'),
1959 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361960 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191961 mock_input_api, MockOutputApi())
1962 self.assertEqual(1, len(warnings))
1963
1964 def testAddHeadersWithGn(self):
1965 mock_input_api = MockInputApi()
1966 mock_input_api.files = [
1967 MockAffectedFile('base/stuff.h', ''),
1968 MockAffectedFile('base/another.h', ''),
1969 MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'),
1970 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361971 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191972 mock_input_api, MockOutputApi())
1973 self.assertEqual(0, len(warnings))
1974
1975 def testAddHeadersWithWrongGn(self):
1976 mock_input_api = MockInputApi()
1977 mock_input_api.files = [
1978 MockAffectedFile('base/stuff.h', ''),
1979 MockAffectedFile('base/another.h', ''),
1980 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'),
1981 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361982 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191983 mock_input_api, MockOutputApi())
1984 self.assertEqual(1, len(warnings))
1985 self.assertFalse('base/stuff.h' in warnings[0].items)
1986 self.assertTrue('base/another.h' in warnings[0].items)
1987
1988 def testAddHeadersWithWrongGn2(self):
1989 mock_input_api = MockInputApi()
1990 mock_input_api.files = [
1991 MockAffectedFile('base/stuff.h', ''),
1992 MockAffectedFile('base/another.h', ''),
1993 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'),
1994 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361995 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191996 mock_input_api, MockOutputApi())
1997 self.assertEqual(1, len(warnings))
1998 self.assertTrue('base/stuff.h' in warnings[0].items)
1999 self.assertTrue('base/another.h' in warnings[0].items)
2000
2001
Michael Giuffridad3bc8672018-10-25 22:48:022002class CorrectProductNameInMessagesTest(unittest.TestCase):
2003 def testProductNameInDesc(self):
2004 mock_input_api = MockInputApi()
2005 mock_input_api.files = [
2006 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2007 '<message name="Foo" desc="Welcome to Chrome">',
2008 ' Welcome to Chrome!',
2009 '</message>',
2010 ]),
2011 MockAffectedFile('chrome/app/chromium_strings.grd', [
2012 '<message name="Bar" desc="Welcome to Chrome">',
2013 ' Welcome to Chromium!',
2014 '</message>',
2015 ]),
2016 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362017 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022018 mock_input_api, MockOutputApi())
2019 self.assertEqual(0, len(warnings))
2020
2021 def testChromeInChromium(self):
2022 mock_input_api = MockInputApi()
2023 mock_input_api.files = [
2024 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2025 '<message name="Foo" desc="Welcome to Chrome">',
2026 ' Welcome to Chrome!',
2027 '</message>',
2028 ]),
2029 MockAffectedFile('chrome/app/chromium_strings.grd', [
2030 '<message name="Bar" desc="Welcome to Chrome">',
2031 ' Welcome to Chrome!',
2032 '</message>',
2033 ]),
2034 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362035 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022036 mock_input_api, MockOutputApi())
2037 self.assertEqual(1, len(warnings))
2038 self.assertTrue('chrome/app/chromium_strings.grd' in warnings[0].items[0])
2039
2040 def testChromiumInChrome(self):
2041 mock_input_api = MockInputApi()
2042 mock_input_api.files = [
2043 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2044 '<message name="Foo" desc="Welcome to Chrome">',
2045 ' Welcome to Chromium!',
2046 '</message>',
2047 ]),
2048 MockAffectedFile('chrome/app/chromium_strings.grd', [
2049 '<message name="Bar" desc="Welcome to Chrome">',
2050 ' Welcome to Chromium!',
2051 '</message>',
2052 ]),
2053 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362054 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022055 mock_input_api, MockOutputApi())
2056 self.assertEqual(1, len(warnings))
2057 self.assertTrue(
2058 'chrome/app/google_chrome_strings.grd:2' in warnings[0].items[0])
2059
2060 def testMultipleInstances(self):
2061 mock_input_api = MockInputApi()
2062 mock_input_api.files = [
2063 MockAffectedFile('chrome/app/chromium_strings.grd', [
2064 '<message name="Bar" desc="Welcome to Chrome">',
2065 ' Welcome to Chrome!',
2066 '</message>',
2067 '<message name="Baz" desc="A correct message">',
2068 ' Chromium is the software you are using.',
2069 '</message>',
2070 '<message name="Bat" desc="An incorrect message">',
2071 ' Google Chrome is the software you are using.',
2072 '</message>',
2073 ]),
2074 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362075 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022076 mock_input_api, MockOutputApi())
2077 self.assertEqual(1, len(warnings))
2078 self.assertTrue(
2079 'chrome/app/chromium_strings.grd:2' in warnings[0].items[0])
2080 self.assertTrue(
2081 'chrome/app/chromium_strings.grd:8' in warnings[0].items[1])
2082
2083 def testMultipleWarnings(self):
2084 mock_input_api = MockInputApi()
2085 mock_input_api.files = [
2086 MockAffectedFile('chrome/app/chromium_strings.grd', [
2087 '<message name="Bar" desc="Welcome to Chrome">',
2088 ' Welcome to Chrome!',
2089 '</message>',
2090 '<message name="Baz" desc="A correct message">',
2091 ' Chromium is the software you are using.',
2092 '</message>',
2093 '<message name="Bat" desc="An incorrect message">',
2094 ' Google Chrome is the software you are using.',
2095 '</message>',
2096 ]),
2097 MockAffectedFile('components/components_google_chrome_strings.grd', [
2098 '<message name="Bar" desc="Welcome to Chrome">',
2099 ' Welcome to Chrome!',
2100 '</message>',
2101 '<message name="Baz" desc="A correct message">',
2102 ' Chromium is the software you are using.',
2103 '</message>',
2104 '<message name="Bat" desc="An incorrect message">',
2105 ' Google Chrome is the software you are using.',
2106 '</message>',
2107 ]),
2108 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362109 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022110 mock_input_api, MockOutputApi())
2111 self.assertEqual(2, len(warnings))
2112 self.assertTrue(
2113 'components/components_google_chrome_strings.grd:5'
2114 in warnings[0].items[0])
2115 self.assertTrue(
2116 'chrome/app/chromium_strings.grd:2' in warnings[1].items[0])
2117 self.assertTrue(
2118 'chrome/app/chromium_strings.grd:8' in warnings[1].items[1])
2119
2120
Ken Rockot9f668262018-12-21 18:56:362121class ServiceManifestOwnerTest(unittest.TestCase):
Ken Rockot9f668262018-12-21 18:56:362122 def testServiceManifestChangeNeedsSecurityOwner(self):
2123 mock_input_api = MockInputApi()
2124 mock_input_api.files = [
2125 MockAffectedFile('services/goat/public/cpp/manifest.cc',
2126 [
2127 '#include "services/goat/public/cpp/manifest.h"',
2128 'const service_manager::Manifest& GetManifest() {}',
2129 ])]
2130 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362131 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362132 mock_input_api, mock_output_api)
2133 self.assertEqual(1, len(errors))
2134 self.assertEqual(
2135 'Found OWNERS files that need to be updated for IPC security review ' +
2136 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2137
2138 def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
2139 mock_input_api = MockInputApi()
2140 mock_input_api.files = [
2141 MockAffectedFile('some/non/service/thing/foo_manifest.cc',
2142 [
2143 'const char kNoEnforcement[] = "not a manifest!";',
2144 ])]
2145 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362146 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032147 mock_input_api, mock_output_api)
2148 self.assertEqual([], errors)
2149
2150
2151class FuchsiaSecurityOwnerTest(unittest.TestCase):
2152 def testFidlChangeNeedsSecurityOwner(self):
2153 mock_input_api = MockInputApi()
2154 mock_input_api.files = [
2155 MockAffectedFile('potentially/scary/ipc.fidl',
2156 [
2157 'library test.fidl'
2158 ])]
2159 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362160 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032161 mock_input_api, mock_output_api)
2162 self.assertEqual(1, len(errors))
2163 self.assertEqual(
2164 'Found OWNERS files that need to be updated for IPC security review ' +
2165 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2166
2167 def testComponentManifestV1ChangeNeedsSecurityOwner(self):
2168 mock_input_api = MockInputApi()
2169 mock_input_api.files = [
2170 MockAffectedFile('potentially/scary/v2_manifest.cmx',
2171 [
2172 '{ "that is no": "manifest!" }'
2173 ])]
2174 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362175 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032176 mock_input_api, mock_output_api)
2177 self.assertEqual(1, len(errors))
2178 self.assertEqual(
2179 'Found OWNERS files that need to be updated for IPC security review ' +
2180 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2181
2182 def testComponentManifestV2NeedsSecurityOwner(self):
2183 mock_input_api = MockInputApi()
2184 mock_input_api.files = [
2185 MockAffectedFile('potentially/scary/v2_manifest.cml',
2186 [
2187 '{ "that is no": "manifest!" }'
2188 ])]
2189 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362190 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032191 mock_input_api, mock_output_api)
2192 self.assertEqual(1, len(errors))
2193 self.assertEqual(
2194 'Found OWNERS files that need to be updated for IPC security review ' +
2195 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2196
2197 def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2198 mock_input_api = MockInputApi()
2199 mock_input_api.files = [
2200 MockAffectedFile('some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',
2201 [
2202 'const char kNoEnforcement[] = "Security?!? Pah!";',
2203 ])]
2204 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362205 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362206 mock_input_api, mock_output_api)
2207 self.assertEqual([], errors)
2208
Daniel Cheng13ca61a882017-08-25 15:11:252209
Robert Sesek2c905332020-05-06 23:17:132210class SecurityChangeTest(unittest.TestCase):
2211 class _MockOwnersDB(object):
2212 def __init__(self):
2213 self.email_regexp = '.*'
2214
2215 def owners_rooted_at_file(self, f):
2216 return ['[email protected]', '[email protected]']
2217
2218 def _mockChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2219 def __MockOwnerAndReviewers(input_api, email_regexp, approval_needed=False):
2220 return [owner, reviewers]
2221 input_api.canned_checks.GetCodereviewOwnerAndReviewers = \
2222 __MockOwnerAndReviewers
2223
Alex Goughbc964dd2020-06-15 17:52:372224 def testDiffGetServiceSandboxType(self):
Robert Sesek2c905332020-05-06 23:17:132225 mock_input_api = MockInputApi()
2226 mock_input_api.files = [
2227 MockAffectedFile(
2228 'services/goat/teleporter_host.cc',
2229 [
Alex Goughbc964dd2020-06-15 17:52:372230 'template <>',
2231 'inline content::SandboxType',
2232 'content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {',
2233 '#if defined(OS_WIN)',
2234 ' return SandboxType::kGoaty;',
2235 '#else',
2236 ' return SandboxType::kNoSandbox;',
2237 '#endif // !defined(OS_WIN)',
2238 '}'
Robert Sesek2c905332020-05-06 23:17:132239 ]
2240 ),
2241 ]
2242 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2243 mock_input_api)
2244 self.assertEqual({
2245 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372246 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132247 ])},
2248 files_to_functions)
2249
2250 def testDiffRemovingLine(self):
2251 mock_input_api = MockInputApi()
2252 mock_file = MockAffectedFile('services/goat/teleporter_host.cc', '')
2253 mock_file._scm_diff = """--- old 2020-05-04 14:08:25.000000000 -0400
2254+++ new 2020-05-04 14:08:32.000000000 -0400
2255@@ -1,5 +1,4 @@
Alex Goughbc964dd2020-06-15 17:52:372256 template <>
2257 inline content::SandboxType
2258-content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {
2259 #if defined(OS_WIN)
2260 return SandboxType::kGoaty;
Robert Sesek2c905332020-05-06 23:17:132261"""
2262 mock_input_api.files = [mock_file]
2263 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2264 mock_input_api)
2265 self.assertEqual({
2266 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372267 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132268 ])},
2269 files_to_functions)
2270
2271 def testChangeOwnersMissing(self):
2272 mock_input_api = MockInputApi()
2273 mock_input_api.owners_db = self._MockOwnersDB()
2274 mock_input_api.is_committing = False
2275 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372276 MockAffectedFile('file.cc', ['GetServiceSandboxType<Goat>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132277 ]
2278 mock_output_api = MockOutputApi()
2279 self._mockChangeOwnerAndReviewers(
2280 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362281 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132282 self.assertEquals(1, len(result))
2283 self.assertEquals(result[0].type, 'notify')
2284 self.assertEquals(result[0].message,
2285 'The following files change calls to security-sensive functions\n' \
2286 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2287 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372288 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132289
2290 def testChangeOwnersMissingAtCommit(self):
2291 mock_input_api = MockInputApi()
2292 mock_input_api.owners_db = self._MockOwnersDB()
2293 mock_input_api.is_committing = True
2294 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372295 MockAffectedFile('file.cc', ['GetServiceSandboxType<mojom::Goat>()'])
Robert Sesek2c905332020-05-06 23:17:132296 ]
2297 mock_output_api = MockOutputApi()
2298 self._mockChangeOwnerAndReviewers(
2299 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362300 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132301 self.assertEquals(1, len(result))
2302 self.assertEquals(result[0].type, 'error')
2303 self.assertEquals(result[0].message,
2304 'The following files change calls to security-sensive functions\n' \
2305 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2306 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372307 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132308
2309 def testChangeOwnersPresent(self):
2310 mock_input_api = MockInputApi()
2311 mock_input_api.owners_db = self._MockOwnersDB()
2312 mock_input_api.files = [
2313 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2314 ]
2315 mock_output_api = MockOutputApi()
2316 self._mockChangeOwnerAndReviewers(
2317 mock_input_api, '[email protected]',
2318 ['[email protected]', '[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362319 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132320 self.assertEquals(0, len(result))
2321
2322 def testChangeOwnerIsSecurityOwner(self):
2323 mock_input_api = MockInputApi()
2324 mock_input_api.owners_db = self._MockOwnersDB()
2325 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372326 MockAffectedFile('file.cc', ['GetServiceSandboxType<T>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132327 ]
2328 mock_output_api = MockOutputApi()
2329 self._mockChangeOwnerAndReviewers(
2330 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362331 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132332 self.assertEquals(1, len(result))
2333
2334
Mario Sanchez Prada2472cab2019-09-18 10:58:312335class BannedTypeCheckTest(unittest.TestCase):
Sylvain Defresnea8b73d252018-02-28 15:45:542336
Peter Kasting94a56c42019-10-25 21:54:042337 def testBannedCppFunctions(self):
2338 input_api = MockInputApi()
2339 input_api.files = [
2340 MockFile('some/cpp/problematic/file.cc',
2341 ['using namespace std;']),
Oksana Zhuravlovac8222d22019-12-19 19:21:162342 MockFile('third_party/blink/problematic/file.cc',
2343 ['GetInterfaceProvider()']),
Peter Kasting94a56c42019-10-25 21:54:042344 MockFile('some/cpp/ok/file.cc',
2345 ['using std::string;']),
Allen Bauer53b43fb12020-03-12 17:21:472346 MockFile('some/cpp/problematic/file2.cc',
2347 ['set_owned_by_client()']),
Peter Kasting94a56c42019-10-25 21:54:042348 ]
2349
Saagar Sanghavifceeaae2020-08-12 16:40:362350 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlovac8222d22019-12-19 19:21:162351
2352 # warnings are results[0], errors are results[1]
2353 self.assertEqual(2, len(results))
2354 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2355 self.assertTrue(
2356 'third_party/blink/problematic/file.cc' in results[0].message)
2357 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
Allen Bauer53b43fb12020-03-12 17:21:472358 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
Peter Kasting94a56c42019-10-25 21:54:042359
Abhijeet Kandalkar1e7c2502019-10-29 15:05:452360 def testBannedBlinkDowncastHelpers(self):
2361 input_api = MockInputApi()
2362 input_api.files = [
2363 MockFile('some/cpp/problematic/file1.cc',
2364 ['DEFINE_TYPE_CASTS(ToType, FromType, from_argument,'
2365 'PointerPredicate(), ReferencePredicate());']),
2366 MockFile('some/cpp/problematic/file2.cc',
2367 ['bool is_test_ele = IsHTMLTestElement(n);']),
2368 MockFile('some/cpp/problematic/file3.cc',
2369 ['auto* html_test_ele = ToHTMLTestElement(n);']),
2370 MockFile('some/cpp/problematic/file4.cc',
2371 ['auto* html_test_ele_or_null = ToHTMLTestElementOrNull(n);']),
2372 MockFile('some/cpp/ok/file1.cc',
2373 ['bool is_test_ele = IsA<HTMLTestElement>(n);']),
2374 MockFile('some/cpp/ok/file2.cc',
2375 ['auto* html_test_ele = To<HTMLTestElement>(n);']),
2376 MockFile('some/cpp/ok/file3.cc',
2377 ['auto* html_test_ele_or_null = ',
2378 'DynamicTo<HTMLTestElement>(n);']),
2379 ]
2380
2381 # warnings are errors[0], errors are errors[1]
Saagar Sanghavifceeaae2020-08-12 16:40:362382 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Abhijeet Kandalkar1e7c2502019-10-29 15:05:452383 self.assertEqual(2, len(errors))
2384 self.assertTrue('some/cpp/problematic/file1.cc' in errors[1].message)
2385 self.assertTrue('some/cpp/problematic/file2.cc' in errors[0].message)
2386 self.assertTrue('some/cpp/problematic/file3.cc' in errors[0].message)
2387 self.assertTrue('some/cpp/problematic/file4.cc' in errors[0].message)
2388 self.assertTrue('some/cpp/ok/file1.cc' not in errors[0].message)
2389 self.assertTrue('some/cpp/ok/file2.cc' not in errors[0].message)
2390 self.assertTrue('some/cpp/ok/file3.cc' not in errors[0].message)
2391
Peter K. Lee6c03ccff2019-07-15 14:40:052392 def testBannedIosObjcFunctions(self):
Sylvain Defresnea8b73d252018-02-28 15:45:542393 input_api = MockInputApi()
2394 input_api.files = [
2395 MockFile('some/ios/file.mm',
2396 ['TEST(SomeClassTest, SomeInteraction) {',
2397 '}']),
2398 MockFile('some/mac/file.mm',
2399 ['TEST(SomeClassTest, SomeInteraction) {',
2400 '}']),
2401 MockFile('another/ios_file.mm',
2402 ['class SomeTest : public testing::Test {};']),
Peter K. Lee6c03ccff2019-07-15 14:40:052403 MockFile('some/ios/file_egtest.mm',
2404 ['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
2405 MockFile('some/ios/file_unittest.mm',
2406 ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']),
Sylvain Defresnea8b73d252018-02-28 15:45:542407 ]
2408
Saagar Sanghavifceeaae2020-08-12 16:40:362409 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Sylvain Defresnea8b73d252018-02-28 15:45:542410 self.assertEqual(1, len(errors))
2411 self.assertTrue('some/ios/file.mm' in errors[0].message)
2412 self.assertTrue('another/ios_file.mm' in errors[0].message)
2413 self.assertTrue('some/mac/file.mm' not in errors[0].message)
Peter K. Lee6c03ccff2019-07-15 14:40:052414 self.assertTrue('some/ios/file_egtest.mm' in errors[0].message)
2415 self.assertTrue('some/ios/file_unittest.mm' not in errors[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542416
Carlos Knippschildab192b8c2019-04-08 20:02:382417 def testBannedMojoFunctions(self):
2418 input_api = MockInputApi()
2419 input_api.files = [
2420 MockFile('some/cpp/problematic/file.cc',
2421 ['mojo::DataPipe();']),
Oksana Zhuravlovafd247772019-05-16 16:57:292422 MockFile('some/cpp/problematic/file2.cc',
2423 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382424 MockFile('some/cpp/ok/file.cc',
2425 ['CreateDataPipe();']),
Kinuko Yasuda376c2ce12019-04-16 01:20:372426 MockFile('some/cpp/ok/file2.cc',
2427 ['mojo::DataPipeDrainer();']),
Oksana Zhuravlovafd247772019-05-16 16:57:292428 MockFile('third_party/blink/ok/file3.cc',
2429 ['mojo::ConvertTo<>']),
2430 MockFile('content/renderer/ok/file3.cc',
2431 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382432 ]
2433
Saagar Sanghavifceeaae2020-08-12 16:40:362434 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222435
2436 # warnings are results[0], errors are results[1]
2437 self.assertEqual(2, len(results))
2438 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2439 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
2440 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
2441 self.assertTrue('some/cpp/ok/file2.cc' not in results[1].message)
2442 self.assertTrue('third_party/blink/ok/file3.cc' not in results[0].message)
2443 self.assertTrue('content/renderer/ok/file3.cc' not in results[0].message)
Carlos Knippschildab192b8c2019-04-08 20:02:382444
Mario Sanchez Prada2472cab2019-09-18 10:58:312445 def testDeprecatedMojoTypes(self):
Mario Sanchez Pradacec9cef2019-12-15 11:54:572446 ok_paths = ['components/arc']
2447 warning_paths = ['some/cpp']
Mario Sanchez Pradaaab91382019-12-19 08:57:092448 error_paths = ['third_party/blink', 'content']
Mario Sanchez Prada2472cab2019-09-18 10:58:312449 test_cases = [
2450 {
2451 'type': 'mojo::AssociatedBinding<>;',
2452 'file': 'file1.c'
2453 },
2454 {
2455 'type': 'mojo::AssociatedBindingSet<>;',
2456 'file': 'file2.c'
2457 },
2458 {
2459 'type': 'mojo::AssociatedInterfacePtr<>',
2460 'file': 'file3.cc'
2461 },
2462 {
2463 'type': 'mojo::AssociatedInterfacePtrInfo<>',
2464 'file': 'file4.cc'
2465 },
2466 {
2467 'type': 'mojo::AssociatedInterfaceRequest<>',
2468 'file': 'file5.cc'
2469 },
2470 {
2471 'type': 'mojo::Binding<>',
2472 'file': 'file6.cc'
2473 },
2474 {
2475 'type': 'mojo::BindingSet<>',
2476 'file': 'file7.cc'
2477 },
2478 {
2479 'type': 'mojo::InterfacePtr<>',
2480 'file': 'file8.cc'
2481 },
2482 {
2483 'type': 'mojo::InterfacePtrInfo<>',
2484 'file': 'file9.cc'
2485 },
2486 {
2487 'type': 'mojo::InterfaceRequest<>',
2488 'file': 'file10.cc'
2489 },
2490 {
2491 'type': 'mojo::MakeRequest()',
2492 'file': 'file11.cc'
2493 },
2494 {
2495 'type': 'mojo::MakeRequestAssociatedWithDedicatedPipe()',
2496 'file': 'file12.cc'
2497 },
2498 {
2499 'type': 'mojo::MakeStrongBinding()<>',
2500 'file': 'file13.cc'
2501 },
2502 {
2503 'type': 'mojo::MakeStrongAssociatedBinding()<>',
2504 'file': 'file14.cc'
2505 },
2506 {
Gyuyoung Kim4952ba62020-07-07 07:33:442507 'type': 'mojo::StrongAssociatedBinding<>',
Mario Sanchez Prada2472cab2019-09-18 10:58:312508 'file': 'file15.cc'
2509 },
2510 {
Gyuyoung Kim4952ba62020-07-07 07:33:442511 'type': 'mojo::StrongBinding<>',
Mario Sanchez Prada2472cab2019-09-18 10:58:312512 'file': 'file16.cc'
2513 },
Gyuyoung Kim4952ba62020-07-07 07:33:442514 {
2515 'type': 'mojo::StrongAssociatedBindingSet<>',
2516 'file': 'file17.cc'
2517 },
2518 {
2519 'type': 'mojo::StrongBindingSet<>',
2520 'file': 'file18.cc'
2521 },
Mario Sanchez Prada2472cab2019-09-18 10:58:312522 ]
2523
2524 # Build the list of MockFiles considering paths that should trigger warnings
Mario Sanchez Pradacec9cef2019-12-15 11:54:572525 # as well as paths that should trigger errors.
Mario Sanchez Prada2472cab2019-09-18 10:58:312526 input_api = MockInputApi()
2527 input_api.files = []
2528 for test_case in test_cases:
2529 for path in ok_paths:
2530 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2531 [test_case['type']]))
2532 for path in warning_paths:
2533 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2534 [test_case['type']]))
Mario Sanchez Pradacec9cef2019-12-15 11:54:572535 for path in error_paths:
2536 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2537 [test_case['type']]))
Mario Sanchez Prada2472cab2019-09-18 10:58:312538
Saagar Sanghavifceeaae2020-08-12 16:40:362539 results = PRESUBMIT.CheckNoDeprecatedMojoTypes(input_api, MockOutputApi())
Mario Sanchez Prada2472cab2019-09-18 10:58:312540
Mario Sanchez Pradacec9cef2019-12-15 11:54:572541 # warnings are results[0], errors are results[1]
2542 self.assertEqual(2, len(results))
Mario Sanchez Prada2472cab2019-09-18 10:58:312543
2544 for test_case in test_cases:
Mario Sanchez Pradacec9cef2019-12-15 11:54:572545 # Check that no warnings nor errors have been triggered for these paths.
Mario Sanchez Prada2472cab2019-09-18 10:58:312546 for path in ok_paths:
2547 self.assertFalse(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572548 self.assertFalse(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312549
2550 # Check warnings have been triggered for these paths.
2551 for path in warning_paths:
2552 self.assertTrue(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572553 self.assertFalse(path in results[1].message)
2554
2555 # Check errors have been triggered for these paths.
2556 for path in error_paths:
2557 self.assertFalse(path in results[0].message)
2558 self.assertTrue(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312559
Sylvain Defresnea8b73d252018-02-28 15:45:542560
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272561class NoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:242562 def testTruePositives(self):
2563 mock_input_api = MockInputApi()
2564 mock_input_api.files = [
2565 MockFile('some/path/foo.cc', ['foo_for_testing();']),
2566 MockFile('some/path/foo.mm', ['FooForTesting();']),
2567 MockFile('some/path/foo.cxx', ['FooForTests();']),
2568 MockFile('some/path/foo.cpp', ['foo_for_test();']),
2569 ]
2570
Saagar Sanghavifceeaae2020-08-12 16:40:362571 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242572 mock_input_api, MockOutputApi())
2573 self.assertEqual(1, len(results))
2574 self.assertEqual(4, len(results[0].items))
2575 self.assertTrue('foo.cc' in results[0].items[0])
2576 self.assertTrue('foo.mm' in results[0].items[1])
2577 self.assertTrue('foo.cxx' in results[0].items[2])
2578 self.assertTrue('foo.cpp' in results[0].items[3])
2579
2580 def testFalsePositives(self):
2581 mock_input_api = MockInputApi()
2582 mock_input_api.files = [
2583 MockFile('some/path/foo.h', ['foo_for_testing();']),
2584 MockFile('some/path/foo.mm', ['FooForTesting() {']),
2585 MockFile('some/path/foo.cc', ['::FooForTests();']),
2586 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
2587 ]
2588
Saagar Sanghavifceeaae2020-08-12 16:40:362589 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242590 mock_input_api, MockOutputApi())
2591 self.assertEqual(0, len(results))
2592
2593
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272594class NoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:232595 def testTruePositives(self):
2596 mock_input_api = MockInputApi()
2597 mock_input_api.files = [
2598 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
2599 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392600 MockFile('dir/java/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232601 MockFile('dir/java/src/mult.java', [
2602 'int x = SomethingLongHere()',
2603 ' * SomethingLongHereForTesting();'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392604 ])
Vaclav Brozek7dbc28c2018-03-27 08:35:232605 ]
2606
Saagar Sanghavifceeaae2020-08-12 16:40:362607 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232608 mock_input_api, MockOutputApi())
2609 self.assertEqual(1, len(results))
2610 self.assertEqual(4, len(results[0].items))
2611 self.assertTrue('foo.java' in results[0].items[0])
2612 self.assertTrue('bar.java' in results[0].items[1])
2613 self.assertTrue('baz.java' in results[0].items[2])
2614 self.assertTrue('mult.java' in results[0].items[3])
2615
2616 def testFalsePositives(self):
2617 mock_input_api = MockInputApi()
2618 mock_input_api.files = [
2619 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
2620 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
2621 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
2622 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
Sky Malice9e6d6032020-10-15 22:49:552623 MockFile('dir/java/src/bar3.java', ['@VisibleForTesting']),
2624 MockFile('dir/java/src/bar4.java', ['@VisibleForTesting()']),
2625 MockFile('dir/java/src/bar5.java', [
2626 '@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)'
2627 ]),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392628 MockFile('dir/javatests/src/baz.java', ['FooForTest(', 'y', ');']),
2629 MockFile('dir/junit/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232630 MockFile('dir/junit/src/javadoc.java', [
2631 '/** Use FooForTest(); to obtain foo in tests.'
2632 ' */'
2633 ]),
2634 MockFile('dir/junit/src/javadoc2.java', [
2635 '/** ',
2636 ' * Use FooForTest(); to obtain foo in tests.'
2637 ' */'
2638 ]),
2639 ]
2640
Saagar Sanghavifceeaae2020-08-12 16:40:362641 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232642 mock_input_api, MockOutputApi())
2643 self.assertEqual(0, len(results))
2644
2645
Mohamed Heikald048240a2019-11-12 16:57:372646class NewImagesWarningTest(unittest.TestCase):
2647 def testTruePositives(self):
2648 mock_input_api = MockInputApi()
2649 mock_input_api.files = [
2650 MockFile('dir/android/res/drawable/foo.png', []),
2651 MockFile('dir/android/res/drawable-v21/bar.svg', []),
2652 MockFile('dir/android/res/mipmap-v21-en/baz.webp', []),
2653 MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png', []),
2654 ]
2655
2656 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2657 self.assertEqual(1, len(results))
2658 self.assertEqual(4, len(results[0].items))
2659 self.assertTrue('foo.png' in results[0].items[0].LocalPath())
2660 self.assertTrue('bar.svg' in results[0].items[1].LocalPath())
2661 self.assertTrue('baz.webp' in results[0].items[2].LocalPath())
2662 self.assertTrue('foobar.png' in results[0].items[3].LocalPath())
2663
2664 def testFalsePositives(self):
2665 mock_input_api = MockInputApi()
2666 mock_input_api.files = [
2667 MockFile('dir/pngs/README.md', []),
2668 MockFile('java/test/res/drawable/foo.png', []),
2669 MockFile('third_party/blink/foo.png', []),
2670 MockFile('dir/third_party/libpng/src/foo.cc', ['foobar']),
2671 MockFile('dir/resources.webp/.gitignore', ['foo.png']),
2672 ]
2673
2674 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2675 self.assertEqual(0, len(results))
2676
2677
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272678class CheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:052679 def testTruePositivesNullptr(self):
2680 mock_input_api = MockInputApi()
2681 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162682 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
2683 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
Vaclav Brozek851d9602018-04-04 16:13:052684 ]
2685
Saagar Sanghavifceeaae2020-08-12 16:40:362686 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052687 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162688 self.assertTrue('nullptr' in results[0].message)
Vaclav Brozek851d9602018-04-04 16:13:052689 self.assertEqual(2, len(results[0].items))
2690 self.assertTrue('baz.cc' in results[0].items[0])
2691 self.assertTrue('baz-p.cc' in results[0].items[1])
2692
2693 def testTruePositivesConstructor(self):
Vaclav Brozek52e18bf2018-04-03 07:05:242694 mock_input_api = MockInputApi()
2695 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162696 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
2697 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
2698 MockFile('dir/mult.cc', [
Vaclav Brozek95face62018-04-04 14:15:112699 'return',
2700 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
2701 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162702 MockFile('dir/mult2.cc', [
Vaclav Brozek95face62018-04-04 14:15:112703 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
2704 ' std::unique_ptr<T>(foo);'
2705 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162706 MockFile('dir/mult3.cc', [
Vaclav Brozek95face62018-04-04 14:15:112707 'bar = std::unique_ptr<T>(',
2708 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
2709 ]),
Vaclav Brozekb7fadb692018-08-30 06:39:532710 MockFile('dir/multi_arg.cc', [
2711 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']),
Vaclav Brozek52e18bf2018-04-03 07:05:242712 ]
2713
Saagar Sanghavifceeaae2020-08-12 16:40:362714 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052715 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162716 self.assertTrue('std::make_unique' in results[0].message)
Vaclav Brozekb7fadb692018-08-30 06:39:532717 self.assertEqual(6, len(results[0].items))
Vaclav Brozek851d9602018-04-04 16:13:052718 self.assertTrue('foo.cc' in results[0].items[0])
2719 self.assertTrue('bar.mm' in results[0].items[1])
2720 self.assertTrue('mult.cc' in results[0].items[2])
2721 self.assertTrue('mult2.cc' in results[0].items[3])
2722 self.assertTrue('mult3.cc' in results[0].items[4])
Vaclav Brozekb7fadb692018-08-30 06:39:532723 self.assertTrue('multi_arg.cc' in results[0].items[5])
Vaclav Brozek52e18bf2018-04-03 07:05:242724
2725 def testFalsePositives(self):
2726 mock_input_api = MockInputApi()
2727 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162728 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
2729 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
2730 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
2731 MockFile('dir/baz.cc', [
Vaclav Brozek52e18bf2018-04-03 07:05:242732 'std::unique_ptr<T> result = std::make_unique<T>();'
2733 ]),
Vaclav Brozeka54c528b2018-04-06 19:23:552734 MockFile('dir/baz2.cc', [
2735 'std::unique_ptr<T> result = std::make_unique<T>('
2736 ]),
2737 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
2738 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
Vaclav Brozekb7fadb692018-08-30 06:39:532739
2740 # Two-argument invocation of std::unique_ptr is exempt because there is
2741 # no equivalent using std::make_unique.
2742 MockFile('dir/multi_arg.cc', [
2743 'auto p = std::unique_ptr<T, D>(new T(), D());']),
Vaclav Brozek52e18bf2018-04-03 07:05:242744 ]
2745
Saagar Sanghavifceeaae2020-08-12 16:40:362746 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek52e18bf2018-04-03 07:05:242747 self.assertEqual(0, len(results))
2748
Danil Chapovalov3518f362018-08-11 16:13:432749class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
2750 def testBlocksDirectIncludes(self):
2751 mock_input_api = MockInputApi()
2752 mock_input_api.files = [
2753 MockFile('dir/foo_win.cc', ['#include "shlwapi.h"']),
2754 MockFile('dir/bar.h', ['#include <propvarutil.h>']),
2755 MockFile('dir/baz.h', ['#include <atlbase.h>']),
2756 MockFile('dir/jumbo.h', ['#include "sphelper.h"']),
2757 ]
2758 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2759 self.assertEquals(1, len(results))
2760 self.assertEquals(4, len(results[0].items))
2761 self.assertTrue('StrCat' in results[0].message)
2762 self.assertTrue('foo_win.cc' in results[0].items[0])
2763 self.assertTrue('bar.h' in results[0].items[1])
2764 self.assertTrue('baz.h' in results[0].items[2])
2765 self.assertTrue('jumbo.h' in results[0].items[3])
2766
2767 def testAllowsToIncludeWrapper(self):
2768 mock_input_api = MockInputApi()
2769 mock_input_api.files = [
2770 MockFile('dir/baz_win.cc', ['#include "base/win/shlwapi.h"']),
2771 MockFile('dir/baz-win.h', ['#include "base/win/atl.h"']),
2772 ]
2773 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2774 self.assertEquals(0, len(results))
2775
2776 def testAllowsToCreateWrapper(self):
2777 mock_input_api = MockInputApi()
2778 mock_input_api.files = [
2779 MockFile('base/win/shlwapi.h', [
2780 '#include <shlwapi.h>',
2781 '#include "base/win/windows_defines.inc"']),
2782 ]
2783 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2784 self.assertEquals(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:242785
Mustafa Emre Acer51f2f742020-03-09 19:41:122786
Rainhard Findlingfc31844c52020-05-15 09:58:262787class StringTest(unittest.TestCase):
2788 """Tests ICU syntax check and translation screenshots check."""
2789
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142790 # An empty grd file.
2791 OLD_GRD_CONTENTS = """<?xml version="1.0" encoding="UTF-8"?>
2792 <grit latest_public_release="1" current_release="1">
2793 <release seq="1">
2794 <messages></messages>
2795 </release>
2796 </grit>
2797 """.splitlines()
2798 # A grd file with a single message.
2799 NEW_GRD_CONTENTS1 = """<?xml version="1.0" encoding="UTF-8"?>
2800 <grit latest_public_release="1" current_release="1">
2801 <release seq="1">
2802 <messages>
2803 <message name="IDS_TEST1">
2804 Test string 1
2805 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482806 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE1"
2807 translateable="false">
2808 Non translateable message 1, should be ignored
2809 </message>
Mustafa Emre Acered1a48962020-06-30 19:15:392810 <message name="IDS_TEST_STRING_ACCESSIBILITY"
Mustafa Emre Acerd3ca8be2020-07-07 22:35:342811 is_accessibility_with_no_ui="true">
Mustafa Emre Acered1a48962020-06-30 19:15:392812 Accessibility label 1, should be ignored
2813 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142814 </messages>
2815 </release>
2816 </grit>
2817 """.splitlines()
2818 # A grd file with two messages.
2819 NEW_GRD_CONTENTS2 = """<?xml version="1.0" encoding="UTF-8"?>
2820 <grit latest_public_release="1" current_release="1">
2821 <release seq="1">
2822 <messages>
2823 <message name="IDS_TEST1">
2824 Test string 1
2825 </message>
2826 <message name="IDS_TEST2">
2827 Test string 2
2828 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482829 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE2"
2830 translateable="false">
2831 Non translateable message 2, should be ignored
2832 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142833 </messages>
2834 </release>
2835 </grit>
2836 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:262837 # A grd file with one ICU syntax message without syntax errors.
2838 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1 = """<?xml version="1.0" encoding="UTF-8"?>
2839 <grit latest_public_release="1" current_release="1">
2840 <release seq="1">
2841 <messages>
2842 <message name="IDS_TEST1">
2843 {NUM, plural,
2844 =1 {Test text for numeric one}
2845 other {Test text for plural with {NUM} as number}}
2846 </message>
2847 </messages>
2848 </release>
2849 </grit>
2850 """.splitlines()
2851 # A grd file with one ICU syntax message without syntax errors.
2852 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2 = """<?xml version="1.0" encoding="UTF-8"?>
2853 <grit latest_public_release="1" current_release="1">
2854 <release seq="1">
2855 <messages>
2856 <message name="IDS_TEST1">
2857 {NUM, plural,
2858 =1 {Different test text for numeric one}
2859 other {Different test text for plural with {NUM} as number}}
2860 </message>
2861 </messages>
2862 </release>
2863 </grit>
2864 """.splitlines()
2865 # A grd file with one ICU syntax message with syntax errors (misses a comma).
2866 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
2867 <grit latest_public_release="1" current_release="1">
2868 <release seq="1">
2869 <messages>
2870 <message name="IDS_TEST1">
2871 {NUM, plural
2872 =1 {Test text for numeric one}
2873 other {Test text for plural with {NUM} as number}}
2874 </message>
2875 </messages>
2876 </release>
2877 </grit>
2878 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142879
meacerff8a9b62019-12-10 19:43:582880 OLD_GRDP_CONTENTS = (
2881 '<?xml version="1.0" encoding="utf-8"?>',
2882 '<grit-part>',
2883 '</grit-part>'
2884 )
2885
2886 NEW_GRDP_CONTENTS1 = (
2887 '<?xml version="1.0" encoding="utf-8"?>',
2888 '<grit-part>',
2889 '<message name="IDS_PART_TEST1">',
2890 'Part string 1',
2891 '</message>',
2892 '</grit-part>')
2893
2894 NEW_GRDP_CONTENTS2 = (
2895 '<?xml version="1.0" encoding="utf-8"?>',
2896 '<grit-part>',
2897 '<message name="IDS_PART_TEST1">',
2898 'Part string 1',
2899 '</message>',
2900 '<message name="IDS_PART_TEST2">',
2901 'Part string 2',
2902 '</message>',
2903 '</grit-part>')
2904
Rainhard Findlingd8d04372020-08-13 13:30:092905 NEW_GRDP_CONTENTS3 = (
2906 '<?xml version="1.0" encoding="utf-8"?>',
2907 '<grit-part>',
2908 '<message name="IDS_PART_TEST1" desc="Description with typo.">',
2909 'Part string 1',
2910 '</message>',
2911 '</grit-part>')
2912
2913 NEW_GRDP_CONTENTS4 = (
2914 '<?xml version="1.0" encoding="utf-8"?>',
2915 '<grit-part>',
2916 '<message name="IDS_PART_TEST1" desc="Description with typo fixed.">',
2917 'Part string 1',
2918 '</message>',
2919 '</grit-part>')
2920
Rainhard Findling1a3e71e2020-09-21 07:33:352921 NEW_GRDP_CONTENTS5 = (
2922 '<?xml version="1.0" encoding="utf-8"?>',
2923 '<grit-part>',
2924 '<message name="IDS_PART_TEST1" meaning="Meaning with typo.">',
2925 'Part string 1',
2926 '</message>',
2927 '</grit-part>')
2928
2929 NEW_GRDP_CONTENTS6 = (
2930 '<?xml version="1.0" encoding="utf-8"?>',
2931 '<grit-part>',
2932 '<message name="IDS_PART_TEST1" meaning="Meaning with typo fixed.">',
2933 'Part string 1',
2934 '</message>',
2935 '</grit-part>')
2936
Rainhard Findlingfc31844c52020-05-15 09:58:262937 # A grdp file with one ICU syntax message without syntax errors.
2938 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = (
2939 '<?xml version="1.0" encoding="utf-8"?>',
2940 '<grit-part>',
2941 '<message name="IDS_PART_TEST1">',
2942 '{NUM, plural,',
2943 '=1 {Test text for numeric one}',
2944 'other {Test text for plural with {NUM} as number}}',
2945 '</message>',
2946 '</grit-part>')
2947 # A grdp file with one ICU syntax message without syntax errors.
2948 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2 = (
2949 '<?xml version="1.0" encoding="utf-8"?>',
2950 '<grit-part>',
2951 '<message name="IDS_PART_TEST1">',
2952 '{NUM, plural,',
2953 '=1 {Different test text for numeric one}',
2954 'other {Different test text for plural with {NUM} as number}}',
2955 '</message>',
2956 '</grit-part>')
2957
2958 # A grdp file with one ICU syntax message with syntax errors (superfluent
2959 # whitespace).
2960 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR = (
2961 '<?xml version="1.0" encoding="utf-8"?>',
2962 '<grit-part>',
2963 '<message name="IDS_PART_TEST1">',
2964 '{NUM, plural,',
2965 '= 1 {Test text for numeric one}',
2966 'other {Test text for plural with {NUM} as number}}',
2967 '</message>',
2968 '</grit-part>')
2969
Mustafa Emre Acerc8a012d2018-07-31 00:00:392970 DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
2971 'changelist. Run '
2972 'tools/translate/upload_screenshots.py to '
2973 'upload them instead:')
2974 GENERATE_SIGNATURES_MESSAGE = ('You are adding or modifying UI strings.\n'
2975 'To ensure the best translations, take '
2976 'screenshots of the relevant UI '
2977 '(https://g.co/chrome/translation) and add '
2978 'these files to your changelist:')
2979 REMOVE_SIGNATURES_MESSAGE = ('You removed strings associated with these '
2980 'files. Remove:')
Rainhard Findlingfc31844c52020-05-15 09:58:262981 ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
2982 'strings (problems or feedback? Contact '
2983 '[email protected]):')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142984
2985 def makeInputApi(self, files):
2986 input_api = MockInputApi()
2987 input_api.files = files
meacere7be7532019-10-02 17:41:032988 # Override os_path.exists because the presubmit uses the actual
2989 # os.path.exists.
2990 input_api.CreateMockFileInPath(
2991 [x.LocalPath() for x in input_api.AffectedFiles(include_deletes=True)])
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142992 return input_api
2993
meacerff8a9b62019-12-10 19:43:582994 """ CL modified and added messages, but didn't add any screenshots."""
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142995 def testNoScreenshots(self):
meacerff8a9b62019-12-10 19:43:582996 # No new strings (file contents same). Should not warn.
2997 input_api = self.makeInputApi([
2998 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
2999 self.NEW_GRD_CONTENTS1, action='M'),
3000 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1,
3001 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363002 warnings = PRESUBMIT.CheckStrings(input_api,
meacerff8a9b62019-12-10 19:43:583003 MockOutputApi())
3004 self.assertEqual(0, len(warnings))
3005
3006 # Add two new strings. Should have two warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143007 input_api = self.makeInputApi([
3008 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:583009 self.NEW_GRD_CONTENTS1, action='M'),
3010 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
3011 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363012 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143013 MockOutputApi())
3014 self.assertEqual(1, len(warnings))
3015 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003016 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013017 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583018 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3019 os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
3020 warnings[0].items)
Mustafa Emre Acer36eaad52019-11-12 23:03:343021
meacerff8a9b62019-12-10 19:43:583022 # Add four new strings. Should have four warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213023 input_api = self.makeInputApi([
3024 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:583025 self.OLD_GRD_CONTENTS, action='M'),
3026 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
3027 self.OLD_GRDP_CONTENTS, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363028 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213029 MockOutputApi())
3030 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003031 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213032 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583033 self.assertEqual([
3034 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3035 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3036 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3037 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3038 ], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213039
Rainhard Findlingd8d04372020-08-13 13:30:093040 def testModifiedMessageDescription(self):
3041 # CL modified a message description for a message that does not yet have a
Rainhard Findling1a3e71e2020-09-21 07:33:353042 # screenshot. Should not warn.
Rainhard Findlingd8d04372020-08-13 13:30:093043 input_api = self.makeInputApi([
3044 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
3045 self.NEW_GRDP_CONTENTS4, action='M')])
3046 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findling1a3e71e2020-09-21 07:33:353047 self.assertEqual(0, len(warnings))
Rainhard Findlingd8d04372020-08-13 13:30:093048
3049 # CL modified a message description for a message that already has a
3050 # screenshot. Should not warn.
3051 input_api = self.makeInputApi([
3052 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
3053 self.NEW_GRDP_CONTENTS4, action='M'),
3054 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3055 'binary', action='A')])
3056 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3057 self.assertEqual(0, len(warnings))
3058
Rainhard Findling1a3e71e2020-09-21 07:33:353059 def testModifiedMessageMeaning(self):
3060 # CL modified a message meaning for a message that does not yet have a
3061 # screenshot. Should warn.
3062 input_api = self.makeInputApi([
3063 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3064 self.NEW_GRDP_CONTENTS6, action='M')])
3065 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3066 self.assertEqual(1, len(warnings))
3067
3068 # CL modified a message meaning for a message that already has a
3069 # screenshot. Should not warn.
3070 input_api = self.makeInputApi([
3071 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3072 self.NEW_GRDP_CONTENTS6, action='M'),
3073 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3074 'binary', action='A')])
3075 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3076 self.assertEqual(0, len(warnings))
3077
meacerff8a9b62019-12-10 19:43:583078 def testPngAddedSha1NotAdded(self):
3079 # CL added one new message in a grd file and added the png file associated
3080 # with it, but did not add the corresponding sha1 file. This should warn
3081 # twice:
3082 # - Once for the added png file (because we don't want developers to upload
3083 # actual images)
3084 # - Once for the missing .sha1 file
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143085 input_api = self.makeInputApi([
Mustafa Emre Acerea3e57a2018-12-17 23:51:013086 MockAffectedFile(
3087 'test.grd',
3088 self.NEW_GRD_CONTENTS1,
3089 self.OLD_GRD_CONTENTS,
3090 action='M'),
3091 MockAffectedFile(
3092 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
3093 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363094 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143095 MockOutputApi())
3096 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003097 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143098 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013099 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
3100 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003101 self.assertEqual('error', warnings[1].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143102 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013103 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3104 warnings[1].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143105
meacerff8a9b62019-12-10 19:43:583106 # CL added two messages (one in grd, one in grdp) and added the png files
3107 # associated with the messages, but did not add the corresponding sha1
3108 # files. This should warn twice:
3109 # - Once for the added png files (because we don't want developers to upload
3110 # actual images)
3111 # - Once for the missing .sha1 files
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143112 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583113 # Modified files:
Mustafa Emre Acer36eaad52019-11-12 23:03:343114 MockAffectedFile(
3115 'test.grd',
meacerff8a9b62019-12-10 19:43:583116 self.NEW_GRD_CONTENTS1,
Mustafa Emre Acer36eaad52019-11-12 23:03:343117 self.OLD_GRD_CONTENTS,
meacer2308d0742019-11-12 18:15:423118 action='M'),
Mustafa Emre Acer12e7fee2019-11-18 18:49:553119 MockAffectedFile(
meacerff8a9b62019-12-10 19:43:583120 'part.grdp',
3121 self.NEW_GRDP_CONTENTS1,
3122 self.OLD_GRDP_CONTENTS,
3123 action='M'),
3124 # Added files:
3125 MockAffectedFile(
3126 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A'),
3127 MockAffectedFile(
3128 os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary',
3129 action='A')
Mustafa Emre Acerad8fb082019-11-19 04:24:213130 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363131 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213132 MockOutputApi())
3133 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003134 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213135 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583136 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png'),
3137 os.path.join('test_grd', 'IDS_TEST1.png')],
Mustafa Emre Acerad8fb082019-11-19 04:24:213138 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003139 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213140 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
meacerff8a9b62019-12-10 19:43:583141 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3142 os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3143 warnings[1].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213144
3145 def testScreenshotsWithSha1(self):
meacerff8a9b62019-12-10 19:43:583146 # CL added four messages (two each in a grd and grdp) and their
3147 # corresponding .sha1 files. No warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213148 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583149 # Modified files:
Mustafa Emre Acerad8fb082019-11-19 04:24:213150 MockAffectedFile(
3151 'test.grd',
3152 self.NEW_GRD_CONTENTS2,
3153 self.OLD_GRD_CONTENTS,
Mustafa Emre Acer12e7fee2019-11-18 18:49:553154 action='M'),
meacerff8a9b62019-12-10 19:43:583155 MockAffectedFile(
3156 'part.grdp',
3157 self.NEW_GRDP_CONTENTS2,
3158 self.OLD_GRDP_CONTENTS,
3159 action='M'),
3160 # Added files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013161 MockFile(
3162 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3163 'binary',
3164 action='A'),
3165 MockFile(
3166 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3167 'binary',
meacerff8a9b62019-12-10 19:43:583168 action='A'),
3169 MockFile(
3170 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3171 'binary',
3172 action='A'),
3173 MockFile(
3174 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3175 'binary',
3176 action='A'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013177 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363178 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143179 MockOutputApi())
3180 self.assertEqual([], warnings)
3181
3182 def testScreenshotsRemovedWithSha1(self):
meacerff8a9b62019-12-10 19:43:583183 # Replace new contents with old contents in grd and grp files, removing
3184 # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3185 # Should warn to remove the sha1 files associated with these strings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143186 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583187 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013188 MockAffectedFile(
3189 'test.grd',
meacerff8a9b62019-12-10 19:43:583190 self.OLD_GRD_CONTENTS, # new_contents
3191 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013192 action='M'),
meacerff8a9b62019-12-10 19:43:583193 MockAffectedFile(
3194 'part.grdp',
3195 self.OLD_GRDP_CONTENTS, # new_contents
3196 self.NEW_GRDP_CONTENTS2, # old_contents
3197 action='M'),
3198 # Unmodified files:
3199 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
3200 MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', ''),
3201 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3202 'binary', ''),
3203 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3204 'binary', '')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013205 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363206 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143207 MockOutputApi())
3208 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003209 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143210 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013211 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583212 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3213 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013214 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3215 os.path.join('test_grd', 'IDS_TEST2.png.sha1')
3216 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143217
meacerff8a9b62019-12-10 19:43:583218 # Same as above, but this time one of the .sha1 files is also removed.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143219 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583220 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013221 MockAffectedFile(
3222 'test.grd',
meacerff8a9b62019-12-10 19:43:583223 self.OLD_GRD_CONTENTS, # new_contents
3224 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013225 action='M'),
meacerff8a9b62019-12-10 19:43:583226 MockAffectedFile(
3227 'part.grdp',
3228 self.OLD_GRDP_CONTENTS, # new_contents
3229 self.NEW_GRDP_CONTENTS2, # old_contents
3230 action='M'),
3231 # Unmodified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013232 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
meacerff8a9b62019-12-10 19:43:583233 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3234 'binary', ''),
3235 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013236 MockAffectedFile(
3237 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3238 '',
3239 'old_contents',
meacerff8a9b62019-12-10 19:43:583240 action='D'),
3241 MockAffectedFile(
3242 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3243 '',
3244 'old_contents',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013245 action='D')
3246 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363247 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143248 MockOutputApi())
3249 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003250 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143251 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583252 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3253 os.path.join('test_grd', 'IDS_TEST1.png.sha1')
3254 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143255
meacerff8a9b62019-12-10 19:43:583256 # Remove all sha1 files. There should be no warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143257 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583258 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013259 MockAffectedFile(
3260 'test.grd',
3261 self.OLD_GRD_CONTENTS,
3262 self.NEW_GRD_CONTENTS2,
3263 action='M'),
meacerff8a9b62019-12-10 19:43:583264 MockAffectedFile(
3265 'part.grdp',
3266 self.OLD_GRDP_CONTENTS,
3267 self.NEW_GRDP_CONTENTS2,
3268 action='M'),
3269 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013270 MockFile(
3271 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3272 'binary',
3273 action='D'),
3274 MockFile(
3275 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3276 'binary',
meacerff8a9b62019-12-10 19:43:583277 action='D'),
3278 MockFile(
3279 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3280 'binary',
3281 action='D'),
3282 MockFile(
3283 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3284 'binary',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013285 action='D')
3286 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363287 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143288 MockOutputApi())
3289 self.assertEqual([], warnings)
3290
Rainhard Findlingfc31844c52020-05-15 09:58:263291 def testIcuSyntax(self):
3292 # Add valid ICU syntax string. Should not raise an error.
3293 input_api = self.makeInputApi([
3294 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3295 self.NEW_GRD_CONTENTS1, action='M'),
3296 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3297 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363298 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263299 # We expect no ICU syntax errors.
3300 icu_errors = [e for e in results
3301 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3302 self.assertEqual(0, len(icu_errors))
3303
3304 # Valid changes in ICU syntax. Should not raise an error.
3305 input_api = self.makeInputApi([
3306 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3307 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3308 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3309 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363310 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263311 # We expect no ICU syntax errors.
3312 icu_errors = [e for e in results
3313 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3314 self.assertEqual(0, len(icu_errors))
3315
3316 # Add invalid ICU syntax strings. Should raise two errors.
3317 input_api = self.makeInputApi([
3318 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3319 self.NEW_GRD_CONTENTS1, action='M'),
3320 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3321 self.NEW_GRD_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363322 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263323 # We expect 2 ICU syntax errors.
3324 icu_errors = [e for e in results
3325 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3326 self.assertEqual(1, len(icu_errors))
3327 self.assertEqual([
3328 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3329 'ICU syntax.',
3330 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3331 ], icu_errors[0].items)
3332
3333 # Change two strings to have ICU syntax errors. Should raise two errors.
3334 input_api = self.makeInputApi([
3335 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3336 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3337 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3338 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363339 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263340 # We expect 2 ICU syntax errors.
3341 icu_errors = [e for e in results
3342 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3343 self.assertEqual(1, len(icu_errors))
3344 self.assertEqual([
3345 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3346 'ICU syntax.',
3347 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3348 ], icu_errors[0].items)
3349
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143350
Mustafa Emre Acer51f2f742020-03-09 19:41:123351class TranslationExpectationsTest(unittest.TestCase):
3352 ERROR_MESSAGE_FORMAT = (
3353 "Failed to get a list of translatable grd files. "
3354 "This happens when:\n"
3355 " - One of the modified grd or grdp files cannot be parsed or\n"
3356 " - %s is not updated.\n"
3357 "Stack:\n"
3358 )
3359 REPO_ROOT = os.path.join('tools', 'translation', 'testdata')
3360 # This lists all .grd files under REPO_ROOT.
3361 EXPECTATIONS = os.path.join(REPO_ROOT,
3362 "translation_expectations.pyl")
3363 # This lists all .grd files under REPO_ROOT except unlisted.grd.
3364 EXPECTATIONS_WITHOUT_UNLISTED_FILE = os.path.join(
3365 REPO_ROOT, "translation_expectations_without_unlisted_file.pyl")
3366
3367 # Tests that the presubmit doesn't return when no grd or grdp files are
3368 # modified.
3369 def testExpectationsNoModifiedGrd(self):
3370 input_api = MockInputApi()
3371 input_api.files = [
3372 MockAffectedFile('not_used.txt', 'not used', 'not used', action='M')
3373 ]
3374 # Fake list of all grd files in the repo. This list is missing all grd/grdps
3375 # under tools/translation/testdata. This is OK because the presubmit won't
3376 # run in the first place since there are no modified grd/grps in input_api.
3377 grd_files = ['doesnt_exist_doesnt_matter.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363378 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123379 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3380 grd_files)
3381 self.assertEqual(0, len(warnings))
3382
3383
3384 # Tests that the list of files passed to the presubmit matches the list of
3385 # files in the expectations.
3386 def testExpectationsSuccess(self):
3387 # Mock input file list needs a grd or grdp file in order to run the
3388 # presubmit. The file itself doesn't matter.
3389 input_api = MockInputApi()
3390 input_api.files = [
3391 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3392 ]
3393 # List of all grd files in the repo.
3394 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3395 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363396 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123397 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3398 grd_files)
3399 self.assertEqual(0, len(warnings))
3400
3401 # Tests that the presubmit warns when a file is listed in expectations, but
3402 # does not actually exist.
3403 def testExpectationsMissingFile(self):
3404 # Mock input file list needs a grd or grdp file in order to run the
3405 # presubmit.
3406 input_api = MockInputApi()
3407 input_api.files = [
3408 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3409 ]
3410 # unlisted.grd is listed under tools/translation/testdata but is not
3411 # included in translation expectations.
3412 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363413 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123414 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3415 grd_files)
3416 self.assertEqual(1, len(warnings))
3417 self.assertTrue(warnings[0].message.startswith(
3418 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS))
3419 self.assertTrue(
3420 ("test.grd is listed in the translation expectations, "
3421 "but this grd file does not exist")
3422 in warnings[0].message)
3423
3424 # Tests that the presubmit warns when a file is not listed in expectations but
3425 # does actually exist.
3426 def testExpectationsUnlistedFile(self):
3427 # Mock input file list needs a grd or grdp file in order to run the
3428 # presubmit.
3429 input_api = MockInputApi()
3430 input_api.files = [
3431 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3432 ]
3433 # unlisted.grd is listed under tools/translation/testdata but is not
3434 # included in translation expectations.
3435 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3436 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363437 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123438 input_api, MockOutputApi(), self.REPO_ROOT,
3439 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3440 self.assertEqual(1, len(warnings))
3441 self.assertTrue(warnings[0].message.startswith(
3442 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3443 self.assertTrue(
3444 ("unlisted.grd appears to be translatable "
3445 "(because it contains <file> or <message> elements), "
3446 "but is not listed in the translation expectations.")
3447 in warnings[0].message)
3448
3449 # Tests that the presubmit warns twice:
3450 # - for a non-existing file listed in expectations
3451 # - for an existing file not listed in expectations
3452 def testMultipleWarnings(self):
3453 # Mock input file list needs a grd or grdp file in order to run the
3454 # presubmit.
3455 input_api = MockInputApi()
3456 input_api.files = [
3457 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3458 ]
3459 # unlisted.grd is listed under tools/translation/testdata but is not
3460 # included in translation expectations.
3461 # test.grd is not listed under tools/translation/testdata but is included
3462 # in translation expectations.
3463 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363464 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123465 input_api, MockOutputApi(), self.REPO_ROOT,
3466 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3467 self.assertEqual(1, len(warnings))
3468 self.assertTrue(warnings[0].message.startswith(
3469 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3470 self.assertTrue(
3471 ("unlisted.grd appears to be translatable "
3472 "(because it contains <file> or <message> elements), "
3473 "but is not listed in the translation expectations.")
3474 in warnings[0].message)
3475 self.assertTrue(
3476 ("test.grd is listed in the translation expectations, "
3477 "but this grd file does not exist")
3478 in warnings[0].message)
3479
3480
Dominic Battre033531052018-09-24 15:45:343481class DISABLETypoInTest(unittest.TestCase):
3482
3483 def testPositive(self):
3484 # Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
3485 # where the desire is to disable a test.
3486 tests = [
3487 # Disabled on one platform:
3488 '#if defined(OS_WIN)\n'
3489 '#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
3490 '#else\n'
3491 '#define MAYBE_FoobarTest FoobarTest\n'
3492 '#endif\n',
3493 # Disabled on one platform spread cross lines:
3494 '#if defined(OS_WIN)\n'
3495 '#define MAYBE_FoobarTest \\\n'
3496 ' DISABLE_FoobarTest\n'
3497 '#else\n'
3498 '#define MAYBE_FoobarTest FoobarTest\n'
3499 '#endif\n',
3500 # Disabled on all platforms:
3501 ' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
3502 # Disabled on all platforms but multiple lines
3503 ' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
3504 ]
3505
3506 for test in tests:
3507 mock_input_api = MockInputApi()
3508 mock_input_api.files = [
3509 MockFile('some/path/foo_unittest.cc', test.splitlines()),
3510 ]
3511
Saagar Sanghavifceeaae2020-08-12 16:40:363512 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343513 MockOutputApi())
3514 self.assertEqual(
3515 1,
3516 len(results),
3517 msg=('expected len(results) == 1 but got %d in test: %s' %
3518 (len(results), test)))
3519 self.assertTrue(
3520 'foo_unittest.cc' in results[0].message,
3521 msg=('expected foo_unittest.cc in message but got %s in test %s' %
3522 (results[0].message, test)))
3523
3524 def testIngoreNotTestFiles(self):
3525 mock_input_api = MockInputApi()
3526 mock_input_api.files = [
3527 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'),
3528 ]
3529
Saagar Sanghavifceeaae2020-08-12 16:40:363530 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343531 MockOutputApi())
3532 self.assertEqual(0, len(results))
3533
Katie Df13948e2018-09-25 07:33:443534 def testIngoreDeletedFiles(self):
3535 mock_input_api = MockInputApi()
3536 mock_input_api.files = [
3537 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'),
3538 ]
3539
Saagar Sanghavifceeaae2020-08-12 16:40:363540 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Katie Df13948e2018-09-25 07:33:443541 MockOutputApi())
3542 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:343543
Dirk Pranke3c18a382019-03-15 01:07:513544
3545class BuildtoolsRevisionsAreInSyncTest(unittest.TestCase):
3546 # TODO(crbug.com/941824): We need to make sure the entries in
3547 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3548 # so that users of //buildtools in other projects get the same tooling
3549 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3550 # support to gclient, we can eliminate the duplication and delete
3551 # these tests for the corresponding presubmit check.
3552
3553 def _check(self, files):
3554 mock_input_api = MockInputApi()
3555 mock_input_api.files = []
3556 for fname, contents in files.items():
3557 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363558 return PRESUBMIT.CheckBuildtoolsRevisionsAreInSync(mock_input_api,
Dirk Pranke3c18a382019-03-15 01:07:513559 MockOutputApi())
3560
3561 def testOneFileChangedButNotTheOther(self):
3562 results = self._check({
3563 "DEPS": "'libunwind_revision': 'onerev'",
3564 })
3565 self.assertNotEqual(results, [])
3566
3567 def testNeitherFileChanged(self):
3568 results = self._check({
3569 "OWNERS": "[email protected]",
3570 })
3571 self.assertEqual(results, [])
3572
3573 def testBothFilesChangedAndMatch(self):
3574 results = self._check({
3575 "DEPS": "'libunwind_revision': 'onerev'",
3576 "buildtools/DEPS": "'libunwind_revision': 'onerev'",
3577 })
3578 self.assertEqual(results, [])
3579
3580 def testBothFilesWereChangedAndDontMatch(self):
3581 results = self._check({
3582 "DEPS": "'libunwind_revision': 'onerev'",
3583 "buildtools/DEPS": "'libunwind_revision': 'anotherrev'",
3584 })
3585 self.assertNotEqual(results, [])
3586
3587
Max Morozb47503b2019-08-08 21:03:273588class CheckFuzzTargetsTest(unittest.TestCase):
3589
3590 def _check(self, files):
3591 mock_input_api = MockInputApi()
3592 mock_input_api.files = []
3593 for fname, contents in files.items():
3594 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363595 return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api, MockOutputApi())
Max Morozb47503b2019-08-08 21:03:273596
3597 def testLibFuzzerSourcesIgnored(self):
3598 results = self._check({
3599 "third_party/lib/Fuzzer/FuzzerDriver.cpp": "LLVMFuzzerInitialize",
3600 })
3601 self.assertEqual(results, [])
3602
3603 def testNonCodeFilesIgnored(self):
3604 results = self._check({
3605 "README.md": "LLVMFuzzerInitialize",
3606 })
3607 self.assertEqual(results, [])
3608
3609 def testNoErrorHeaderPresent(self):
3610 results = self._check({
3611 "fuzzer.cc": (
3612 "#include \"testing/libfuzzer/libfuzzer_exports.h\"\n" +
3613 "LLVMFuzzerInitialize"
3614 )
3615 })
3616 self.assertEqual(results, [])
3617
3618 def testErrorMissingHeader(self):
3619 results = self._check({
3620 "fuzzer.cc": "LLVMFuzzerInitialize"
3621 })
3622 self.assertEqual(len(results), 1)
3623 self.assertEqual(results[0].items, ['fuzzer.cc'])
3624
3625
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263626class SetNoParentTest(unittest.TestCase):
3627 def testSetNoParentMissing(self):
3628 mock_input_api = MockInputApi()
3629 mock_input_api.files = [
3630 MockAffectedFile('goat/OWNERS',
3631 [
3632 'set noparent',
3633 '[email protected]',
3634 'per-file *.json=set noparent',
3635 'per-file *[email protected]',
3636 ])
3637 ]
3638 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363639 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263640 self.assertEqual(1, len(errors))
3641 self.assertTrue('goat/OWNERS:1' in errors[0].long_text)
3642 self.assertTrue('goat/OWNERS:3' in errors[0].long_text)
3643
3644
3645 def testSetNoParentWithCorrectRule(self):
3646 mock_input_api = MockInputApi()
3647 mock_input_api.files = [
3648 MockAffectedFile('goat/OWNERS',
3649 [
3650 'set noparent',
3651 'file://ipc/SECURITY_OWNERS',
3652 'per-file *.json=set noparent',
3653 'per-file *.json=file://ipc/SECURITY_OWNERS',
3654 ])
3655 ]
3656 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363657 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263658 self.assertEqual([], errors)
3659
3660
Ken Rockotc31f4832020-05-29 18:58:513661class MojomStabilityCheckTest(unittest.TestCase):
3662 def runTestWithAffectedFiles(self, affected_files):
3663 mock_input_api = MockInputApi()
3664 mock_input_api.files = affected_files
3665 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363666 return PRESUBMIT.CheckStableMojomChanges(
Ken Rockotc31f4832020-05-29 18:58:513667 mock_input_api, mock_output_api)
3668
3669 def testSafeChangePasses(self):
3670 errors = self.runTestWithAffectedFiles([
3671 MockAffectedFile('foo/foo.mojom',
3672 ['[Stable] struct S { [MinVersion=1] int32 x; };'],
3673 old_contents=['[Stable] struct S {};'])
3674 ])
3675 self.assertEqual([], errors)
3676
3677 def testBadChangeFails(self):
3678 errors = self.runTestWithAffectedFiles([
3679 MockAffectedFile('foo/foo.mojom',
3680 ['[Stable] struct S { int32 x; };'],
3681 old_contents=['[Stable] struct S {};'])
3682 ])
3683 self.assertEqual(1, len(errors))
3684 self.assertTrue('not backward-compatible' in errors[0].message)
3685
Ken Rockotad7901f942020-06-04 20:17:093686 def testDeletedFile(self):
3687 """Regression test for https://crbug.com/1091407."""
3688 errors = self.runTestWithAffectedFiles([
3689 MockAffectedFile('a.mojom', [], old_contents=['struct S {};'],
3690 action='D'),
3691 MockAffectedFile('b.mojom',
3692 ['struct S {}; struct T { S s; };'],
3693 old_contents=['import "a.mojom"; struct T { S s; };'])
3694 ])
3695 self.assertEqual([], errors)
3696
Ken Rockotc31f4832020-05-29 18:58:513697
[email protected]2299dcf2012-11-15 19:56:243698if __name__ == '__main__':
3699 unittest.main()