blob: 5c52d08996eefef9e0d224437c70fe7e702d95b6 [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 = {
735 'A.pydeps': '# Generated by:\n# CMD A\nA.py\nC.py\n',
736 'B.pydeps': '# Generated by:\n# CMD B\nB.py\nC.py\n',
Mohamed Heikal7cd4d8312020-06-16 16:49:40737 'D.pydeps': '# Generated by:\n# CMD 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))
765 self.assertTrue('PYDEPS_FILES' in str(results[0]))
766
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))
788 self.assertTrue('PYDEPS_FILES' in str(results[0]))
789
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):
agrievef32bcc72016-04-04 14:57:40812 self.assertEqual('CMD A --output ""', cmd)
813 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):
agrievef32bcc72016-04-04 14:57:40830 self.assertEqual('CMD A --output ""', cmd)
831 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))
837 self.assertTrue('File is stale' in str(results[0]))
838
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))
855 self.assertTrue('File is stale' in str(results[0]))
856 self.assertTrue('File is stale' in str(results[1]))
857
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):
868 self.assertEqual('CMD D --output ""', cmd)
869 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))
876 self.assertTrue('Android' in str(results[0]))
877 self.assertTrue('D.pydeps' in str(results[0]))
878
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39879
Daniel Bratell8ba52722018-03-02 16:06:14880class IncludeGuardTest(unittest.TestCase):
881 def testIncludeGuardChecks(self):
882 mock_input_api = MockInputApi()
883 mock_output_api = MockOutputApi()
884 mock_input_api.files = [
885 MockAffectedFile('content/browser/thing/foo.h', [
886 '// Comment',
887 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
888 '#define CONTENT_BROWSER_THING_FOO_H_',
889 'struct McBoatFace;',
890 '#endif // CONTENT_BROWSER_THING_FOO_H_',
891 ]),
892 MockAffectedFile('content/browser/thing/bar.h', [
893 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
894 '#define CONTENT_BROWSER_THING_BAR_H_',
895 'namespace content {',
896 '#endif // CONTENT_BROWSER_THING_BAR_H_',
897 '} // namespace content',
898 ]),
899 MockAffectedFile('content/browser/test1.h', [
900 'namespace content {',
901 '} // namespace content',
902 ]),
903 MockAffectedFile('content\\browser\\win.h', [
904 '#ifndef CONTENT_BROWSER_WIN_H_',
905 '#define CONTENT_BROWSER_WIN_H_',
906 'struct McBoatFace;',
907 '#endif // CONTENT_BROWSER_WIN_H_',
908 ]),
909 MockAffectedFile('content/browser/test2.h', [
910 '// Comment',
911 '#ifndef CONTENT_BROWSER_TEST2_H_',
912 'struct McBoatFace;',
913 '#endif // CONTENT_BROWSER_TEST2_H_',
914 ]),
915 MockAffectedFile('content/browser/internal.h', [
916 '// Comment',
917 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
918 '#define CONTENT_BROWSER_INTERNAL_H_',
919 '// Comment',
920 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
921 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
922 'namespace internal {',
923 '} // namespace internal',
924 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
925 'namespace content {',
926 '} // namespace content',
927 '#endif // CONTENT_BROWSER_THING_BAR_H_',
928 ]),
929 MockAffectedFile('content/browser/thing/foo.cc', [
930 '// This is a non-header.',
931 ]),
932 MockAffectedFile('content/browser/disabled.h', [
933 '// no-include-guard-because-multiply-included',
934 'struct McBoatFace;',
935 ]),
936 # New files don't allow misspelled include guards.
937 MockAffectedFile('content/browser/spleling.h', [
938 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
939 '#define CONTENT_BROWSER_SPLLEING_H_',
940 'struct McBoatFace;',
941 '#endif // CONTENT_BROWSER_SPLLEING_H_',
942 ]),
Olivier Robinbba137492018-07-30 11:31:34943 # New files don't allow + in include guards.
944 MockAffectedFile('content/browser/foo+bar.h', [
945 '#ifndef CONTENT_BROWSER_FOO+BAR_H_',
946 '#define CONTENT_BROWSER_FOO+BAR_H_',
947 'struct McBoatFace;',
948 '#endif // CONTENT_BROWSER_FOO+BAR_H_',
949 ]),
Daniel Bratell8ba52722018-03-02 16:06:14950 # Old files allow misspelled include guards (for now).
951 MockAffectedFile('chrome/old.h', [
952 '// New contents',
953 '#ifndef CHROME_ODL_H_',
954 '#define CHROME_ODL_H_',
955 '#endif // CHROME_ODL_H_',
956 ], [
957 '// Old contents',
958 '#ifndef CHROME_ODL_H_',
959 '#define CHROME_ODL_H_',
960 '#endif // CHROME_ODL_H_',
961 ]),
962 # Using a Blink style include guard outside Blink is wrong.
963 MockAffectedFile('content/NotInBlink.h', [
964 '#ifndef NotInBlink_h',
965 '#define NotInBlink_h',
966 'struct McBoatFace;',
967 '#endif // NotInBlink_h',
968 ]),
Daniel Bratell39b5b062018-05-16 18:09:57969 # Using a Blink style include guard in Blink is no longer ok.
970 MockAffectedFile('third_party/blink/InBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14971 '#ifndef InBlink_h',
972 '#define InBlink_h',
973 'struct McBoatFace;',
974 '#endif // InBlink_h',
975 ]),
976 # Using a bad include guard in Blink is not ok.
Daniel Bratell39b5b062018-05-16 18:09:57977 MockAffectedFile('third_party/blink/AlsoInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14978 '#ifndef WrongInBlink_h',
979 '#define WrongInBlink_h',
980 'struct McBoatFace;',
981 '#endif // WrongInBlink_h',
982 ]),
Daniel Bratell39b5b062018-05-16 18:09:57983 # Using a bad include guard in Blink is not accepted even if
984 # it's an old file.
985 MockAffectedFile('third_party/blink/StillInBlink.h', [
Daniel Bratell8ba52722018-03-02 16:06:14986 '// New contents',
987 '#ifndef AcceptedInBlink_h',
988 '#define AcceptedInBlink_h',
989 'struct McBoatFace;',
990 '#endif // AcceptedInBlink_h',
991 ], [
992 '// Old contents',
993 '#ifndef AcceptedInBlink_h',
994 '#define AcceptedInBlink_h',
995 'struct McBoatFace;',
996 '#endif // AcceptedInBlink_h',
997 ]),
Daniel Bratell39b5b062018-05-16 18:09:57998 # Using a non-Chromium include guard in third_party
999 # (outside blink) is accepted.
1000 MockAffectedFile('third_party/foo/some_file.h', [
1001 '#ifndef REQUIRED_RPCNDR_H_',
1002 '#define REQUIRED_RPCNDR_H_',
1003 'struct SomeFileFoo;',
1004 '#endif // REQUIRED_RPCNDR_H_',
1005 ]),
Kinuko Yasuda0cdb3da2019-07-31 21:50:321006 # Not having proper include guard in *_message_generator.h
1007 # for old IPC messages is allowed.
1008 MockAffectedFile('content/common/content_message_generator.h', [
1009 '#undef CONTENT_COMMON_FOO_MESSAGES_H_',
1010 '#include "content/common/foo_messages.h"',
1011 '#ifndef CONTENT_COMMON_FOO_MESSAGES_H_',
1012 '#error "Failed to include content/common/foo_messages.h"',
1013 '#endif',
1014 ]),
Daniel Bratell8ba52722018-03-02 16:06:141015 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361016 msgs = PRESUBMIT.CheckForIncludeGuards(
Daniel Bratell8ba52722018-03-02 16:06:141017 mock_input_api, mock_output_api)
Olivier Robinbba137492018-07-30 11:31:341018 expected_fail_count = 8
Daniel Bratell8ba52722018-03-02 16:06:141019 self.assertEqual(expected_fail_count, len(msgs),
1020 'Expected %d items, found %d: %s'
1021 % (expected_fail_count, len(msgs), msgs))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391022 self.assertEqual(msgs[0].items, ['content/browser/thing/bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:141023 self.assertEqual(msgs[0].message,
1024 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
1025 'not covering the whole file')
1026
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391027 self.assertEqual(msgs[1].items, ['content/browser/test1.h'])
Daniel Bratell8ba52722018-03-02 16:06:141028 self.assertEqual(msgs[1].message,
1029 'Missing include guard CONTENT_BROWSER_TEST1_H_')
1030
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391031 self.assertEqual(msgs[2].items, ['content/browser/test2.h:3'])
Daniel Bratell8ba52722018-03-02 16:06:141032 self.assertEqual(msgs[2].message,
1033 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
1034 'include guard')
1035
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391036 self.assertEqual(msgs[3].items, ['content/browser/spleling.h:1'])
Daniel Bratell8ba52722018-03-02 16:06:141037 self.assertEqual(msgs[3].message,
1038 'Header using the wrong include guard name '
1039 'CONTENT_BROWSER_SPLLEING_H_')
1040
Olivier Robinbba137492018-07-30 11:31:341041 self.assertEqual(msgs[4].items, ['content/browser/foo+bar.h'])
Daniel Bratell8ba52722018-03-02 16:06:141042 self.assertEqual(msgs[4].message,
Olivier Robinbba137492018-07-30 11:31:341043 'Missing include guard CONTENT_BROWSER_FOO_BAR_H_')
1044
1045 self.assertEqual(msgs[5].items, ['content/NotInBlink.h:1'])
1046 self.assertEqual(msgs[5].message,
Daniel Bratell8ba52722018-03-02 16:06:141047 'Header using the wrong include guard name '
1048 'NotInBlink_h')
1049
Olivier Robinbba137492018-07-30 11:31:341050 self.assertEqual(msgs[6].items, ['third_party/blink/InBlink.h:1'])
1051 self.assertEqual(msgs[6].message,
Daniel Bratell8ba52722018-03-02 16:06:141052 'Header using the wrong include guard name '
Daniel Bratell39b5b062018-05-16 18:09:571053 'InBlink_h')
1054
Olivier Robinbba137492018-07-30 11:31:341055 self.assertEqual(msgs[7].items, ['third_party/blink/AlsoInBlink.h:1'])
1056 self.assertEqual(msgs[7].message,
Daniel Bratell39b5b062018-05-16 18:09:571057 'Header using the wrong include guard name '
Daniel Bratell8ba52722018-03-02 16:06:141058 'WrongInBlink_h')
1059
Chris Hall59f8d0c72020-05-01 07:31:191060class AccessibilityRelnotesFieldTest(unittest.TestCase):
1061 def testRelnotesPresent(self):
1062 mock_input_api = MockInputApi()
1063 mock_output_api = MockOutputApi()
1064
1065 mock_input_api.files = [MockAffectedFile('ui/accessibility/foo.bar', [''])]
Akihiro Ota08108e542020-05-20 15:30:531066 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191067 mock_input_api.change.footers['AX-Relnotes'] = [
1068 'Important user facing change']
1069
Saagar Sanghavifceeaae2020-08-12 16:40:361070 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:191071 mock_input_api, mock_output_api)
1072 self.assertEqual(0, len(msgs),
1073 'Expected %d messages, found %d: %s'
1074 % (0, len(msgs), msgs))
1075
1076 def testRelnotesMissingFromAccessibilityChange(self):
1077 mock_input_api = MockInputApi()
1078 mock_output_api = MockOutputApi()
1079
1080 mock_input_api.files = [
1081 MockAffectedFile('some/file', ['']),
1082 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1083 MockAffectedFile('some/other/file', [''])
1084 ]
Akihiro Ota08108e542020-05-20 15:30:531085 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191086
Saagar Sanghavifceeaae2020-08-12 16:40:361087 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:191088 mock_input_api, mock_output_api)
1089 self.assertEqual(1, len(msgs),
1090 'Expected %d messages, found %d: %s'
1091 % (1, len(msgs), msgs))
1092 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1093 'Missing AX-Relnotes field message not found in errors')
1094
1095 # The relnotes footer is not required for changes which do not touch any
1096 # accessibility directories.
1097 def testIgnoresNonAccesssibilityCode(self):
1098 mock_input_api = MockInputApi()
1099 mock_output_api = MockOutputApi()
1100
1101 mock_input_api.files = [
1102 MockAffectedFile('some/file', ['']),
1103 MockAffectedFile('some/other/file', [''])
1104 ]
Akihiro Ota08108e542020-05-20 15:30:531105 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191106
Saagar Sanghavifceeaae2020-08-12 16:40:361107 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:191108 mock_input_api, mock_output_api)
1109 self.assertEqual(0, len(msgs),
1110 'Expected %d messages, found %d: %s'
1111 % (0, len(msgs), msgs))
1112
1113 # Test that our presubmit correctly raises an error for a set of known paths.
1114 def testExpectedPaths(self):
1115 filesToTest = [
1116 "chrome/browser/accessibility/foo.py",
1117 "chrome/browser/chromeos/arc/accessibility/foo.cc",
1118 "chrome/browser/ui/views/accessibility/foo.h",
1119 "chrome/browser/extensions/api/automation/foo.h",
1120 "chrome/browser/extensions/api/automation_internal/foo.cc",
1121 "chrome/renderer/extensions/accessibility_foo.h",
1122 "chrome/tests/data/accessibility/foo.html",
1123 "content/browser/accessibility/foo.cc",
1124 "content/renderer/accessibility/foo.h",
1125 "content/tests/data/accessibility/foo.cc",
1126 "extensions/renderer/api/automation/foo.h",
1127 "ui/accessibility/foo/bar/baz.cc",
1128 "ui/views/accessibility/foo/bar/baz.h",
1129 ]
1130
1131 for testFile in filesToTest:
1132 mock_input_api = MockInputApi()
1133 mock_output_api = MockOutputApi()
1134
1135 mock_input_api.files = [
1136 MockAffectedFile(testFile, [''])
1137 ]
Akihiro Ota08108e542020-05-20 15:30:531138 mock_input_api.change.DescriptionText = lambda : 'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:191139
Saagar Sanghavifceeaae2020-08-12 16:40:361140 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Chris Hall59f8d0c72020-05-01 07:31:191141 mock_input_api, mock_output_api)
1142 self.assertEqual(1, len(msgs),
1143 'Expected %d messages, found %d: %s, for file %s'
1144 % (1, len(msgs), msgs, testFile))
1145 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1146 ('Missing AX-Relnotes field message not found in errors '
1147 ' for file %s' % (testFile)))
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391148
Akihiro Ota08108e542020-05-20 15:30:531149 # Test that AX-Relnotes field can appear in the commit description (as long
1150 # as it appears at the beginning of a line).
1151 def testRelnotesInCommitDescription(self):
1152 mock_input_api = MockInputApi()
1153 mock_output_api = MockOutputApi()
1154
1155 mock_input_api.files = [
1156 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1157 ]
1158 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1159 'AX-Relnotes: solves all accessibility issues forever')
1160
Saagar Sanghavifceeaae2020-08-12 16:40:361161 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531162 mock_input_api, mock_output_api)
1163 self.assertEqual(0, len(msgs),
1164 'Expected %d messages, found %d: %s'
1165 % (0, len(msgs), msgs))
1166
1167 # Test that we don't match AX-Relnotes if it appears in the middle of a line.
1168 def testRelnotesMustAppearAtBeginningOfLine(self):
1169 mock_input_api = MockInputApi()
1170 mock_output_api = MockOutputApi()
1171
1172 mock_input_api.files = [
1173 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1174 ]
1175 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1176 'This change has no AX-Relnotes: we should print a warning')
1177
Saagar Sanghavifceeaae2020-08-12 16:40:361178 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531179 mock_input_api, mock_output_api)
1180 self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message,
1181 'Missing AX-Relnotes field message not found in errors')
1182
1183 # Tests that the AX-Relnotes field can be lowercase and use a '=' in place
1184 # of a ':'.
1185 def testRelnotesLowercaseWithEqualSign(self):
1186 mock_input_api = MockInputApi()
1187 mock_output_api = MockOutputApi()
1188
1189 mock_input_api.files = [
1190 MockAffectedFile('ui/accessibility/foo.bar', ['']),
1191 ]
1192 mock_input_api.change.DescriptionText = lambda : ('Description:\n' +
1193 'ax-relnotes= this is a valid format for accessibiliy relnotes')
1194
Saagar Sanghavifceeaae2020-08-12 16:40:361195 msgs = PRESUBMIT.CheckAccessibilityRelnotesField(
Akihiro Ota08108e542020-05-20 15:30:531196 mock_input_api, mock_output_api)
1197 self.assertEqual(0, len(msgs),
1198 'Expected %d messages, found %d: %s'
1199 % (0, len(msgs), msgs))
1200
yolandyan45001472016-12-21 21:12:421201class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
1202 def testCheckAndroidTestAnnotationUsage(self):
1203 mock_input_api = MockInputApi()
1204 mock_output_api = MockOutputApi()
1205
1206 mock_input_api.files = [
1207 MockAffectedFile('LalaLand.java', [
1208 'random stuff'
1209 ]),
1210 MockAffectedFile('CorrectUsage.java', [
1211 'import android.support.test.filters.LargeTest;',
1212 'import android.support.test.filters.MediumTest;',
1213 'import android.support.test.filters.SmallTest;',
1214 ]),
1215 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
1216 'import android.test.suitebuilder.annotation.LargeTest;',
1217 ]),
1218 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
1219 'import android.test.suitebuilder.annotation.MediumTest;',
1220 ]),
1221 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
1222 'import android.test.suitebuilder.annotation.SmallTest;',
1223 ]),
1224 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
1225 'import android.test.suitebuilder.annotation.Smoke;',
1226 ])
1227 ]
1228 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
1229 mock_input_api, mock_output_api)
1230 self.assertEqual(1, len(msgs),
1231 'Expected %d items, found %d: %s'
1232 % (1, len(msgs), msgs))
1233 self.assertEqual(4, len(msgs[0].items),
1234 'Expected %d items, found %d: %s'
1235 % (4, len(msgs[0].items), msgs[0].items))
1236 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
1237 'UsedDeprecatedLargeTestAnnotation not found in errors')
1238 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
1239 in msgs[0].items,
1240 'UsedDeprecatedMediumTestAnnotation not found in errors')
1241 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
1242 'UsedDeprecatedSmallTestAnnotation not found in errors')
1243 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
1244 'UsedDeprecatedSmokeAnnotation not found in errors')
1245
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391246
Yoland Yanb92fa522017-08-28 17:37:061247class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271248 def testCheckAndroidTestJUnitFramework(self):
Yoland Yanb92fa522017-08-28 17:37:061249 mock_input_api = MockInputApi()
1250 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:421251
Yoland Yanb92fa522017-08-28 17:37:061252 mock_input_api.files = [
1253 MockAffectedFile('LalaLand.java', [
1254 'random stuff'
1255 ]),
1256 MockAffectedFile('CorrectUsage.java', [
1257 'import org.junit.ABC',
1258 'import org.junit.XYZ;',
1259 ]),
1260 MockAffectedFile('UsedDeprecatedJUnit.java', [
1261 'import junit.framework.*;',
1262 ]),
1263 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
1264 'import junit.framework.Assert;',
1265 ]),
1266 ]
1267 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
1268 mock_input_api, mock_output_api)
1269 self.assertEqual(1, len(msgs),
1270 'Expected %d items, found %d: %s'
1271 % (1, len(msgs), msgs))
1272 self.assertEqual(2, len(msgs[0].items),
1273 'Expected %d items, found %d: %s'
1274 % (2, len(msgs[0].items), msgs[0].items))
1275 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
1276 'UsedDeprecatedJUnit.java not found in errors')
1277 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
1278 in msgs[0].items,
1279 'UsedDeprecatedJUnitAssert not found in errors')
1280
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391281
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:271282class AndroidJUnitBaseClassTest(unittest.TestCase):
1283 def testCheckAndroidTestJUnitBaseClass(self):
Yoland Yanb92fa522017-08-28 17:37:061284 mock_input_api = MockInputApi()
1285 mock_output_api = MockOutputApi()
1286
1287 mock_input_api.files = [
1288 MockAffectedFile('LalaLand.java', [
1289 'random stuff'
1290 ]),
1291 MockAffectedFile('CorrectTest.java', [
1292 '@RunWith(ABC.class);'
1293 'public class CorrectTest {',
1294 '}',
1295 ]),
1296 MockAffectedFile('HistoricallyIncorrectTest.java', [
1297 'public class Test extends BaseCaseA {',
1298 '}',
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391299 ], old_contents=[
Yoland Yanb92fa522017-08-28 17:37:061300 'public class Test extends BaseCaseB {',
1301 '}',
1302 ]),
1303 MockAffectedFile('CorrectTestWithInterface.java', [
1304 '@RunWith(ABC.class);'
1305 'public class CorrectTest implement Interface {',
1306 '}',
1307 ]),
1308 MockAffectedFile('IncorrectTest.java', [
1309 'public class IncorrectTest extends TestCase {',
1310 '}',
1311 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241312 MockAffectedFile('IncorrectWithInterfaceTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061313 'public class Test implements X extends BaseClass {',
1314 '}',
1315 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241316 MockAffectedFile('IncorrectMultiLineTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061317 'public class Test implements X, Y, Z',
1318 ' extends TestBase {',
1319 '}',
1320 ]),
1321 ]
1322 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1323 mock_input_api, mock_output_api)
1324 self.assertEqual(1, len(msgs),
1325 'Expected %d items, found %d: %s'
1326 % (1, len(msgs), msgs))
1327 self.assertEqual(3, len(msgs[0].items),
1328 'Expected %d items, found %d: %s'
1329 % (3, len(msgs[0].items), msgs[0].items))
1330 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1331 'IncorrectTest not found in errors')
Vaclav Brozekf01ed502018-03-16 19:38:241332 self.assertTrue('IncorrectWithInterfaceTest.java:1'
Yoland Yanb92fa522017-08-28 17:37:061333 in msgs[0].items,
Vaclav Brozekf01ed502018-03-16 19:38:241334 'IncorrectWithInterfaceTest not found in errors')
1335 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1336 'IncorrectMultiLineTest not found in errors')
yolandyan45001472016-12-21 21:12:421337
Jinsong Fan91ebbbd2019-04-16 14:57:171338class AndroidDebuggableBuildTest(unittest.TestCase):
1339
1340 def testCheckAndroidDebuggableBuild(self):
1341 mock_input_api = MockInputApi()
1342 mock_output_api = MockOutputApi()
1343
1344 mock_input_api.files = [
1345 MockAffectedFile('RandomStuff.java', [
1346 'random stuff'
1347 ]),
1348 MockAffectedFile('CorrectUsage.java', [
1349 'import org.chromium.base.BuildInfo;',
1350 'some random stuff',
1351 'boolean isOsDebuggable = BuildInfo.isDebugAndroid();',
1352 ]),
1353 MockAffectedFile('JustCheckUserdebugBuild.java', [
1354 'import android.os.Build;',
1355 'some random stuff',
1356 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")',
1357 ]),
1358 MockAffectedFile('JustCheckEngineeringBuild.java', [
1359 'import android.os.Build;',
1360 'some random stuff',
1361 'boolean isOsDebuggable = "eng".equals(Build.TYPE)',
1362 ]),
1363 MockAffectedFile('UsedBuildType.java', [
1364 'import android.os.Build;',
1365 'some random stuff',
1366 'boolean isOsDebuggable = Build.TYPE.equals("userdebug")'
1367 '|| "eng".equals(Build.TYPE)',
1368 ]),
1369 MockAffectedFile('UsedExplicitBuildType.java', [
1370 'some random stuff',
1371 'boolean isOsDebuggable = android.os.Build.TYPE.equals("userdebug")'
1372 '|| "eng".equals(android.os.Build.TYPE)',
1373 ]),
1374 ]
1375
1376 msgs = PRESUBMIT._CheckAndroidDebuggableBuild(
1377 mock_input_api, mock_output_api)
1378 self.assertEqual(1, len(msgs),
1379 'Expected %d items, found %d: %s'
1380 % (1, len(msgs), msgs))
1381 self.assertEqual(4, len(msgs[0].items),
1382 'Expected %d items, found %d: %s'
1383 % (4, len(msgs[0].items), msgs[0].items))
1384 self.assertTrue('JustCheckUserdebugBuild.java:3' in msgs[0].items)
1385 self.assertTrue('JustCheckEngineeringBuild.java:3' in msgs[0].items)
1386 self.assertTrue('UsedBuildType.java:3' in msgs[0].items)
1387 self.assertTrue('UsedExplicitBuildType.java:2' in msgs[0].items)
1388
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391389
dgn4401aa52015-04-29 16:26:171390class LogUsageTest(unittest.TestCase):
1391
dgnaa68d5e2015-06-10 10:08:221392 def testCheckAndroidCrLogUsage(self):
1393 mock_input_api = MockInputApi()
1394 mock_output_api = MockOutputApi()
1395
1396 mock_input_api.files = [
1397 MockAffectedFile('RandomStuff.java', [
1398 'random stuff'
1399 ]),
dgn87d9fb62015-06-12 09:15:121400 MockAffectedFile('HasAndroidLog.java', [
1401 'import android.util.Log;',
1402 'some random stuff',
1403 'Log.d("TAG", "foo");',
1404 ]),
1405 MockAffectedFile('HasExplicitUtilLog.java', [
1406 'some random stuff',
1407 'android.util.Log.d("TAG", "foo");',
1408 ]),
1409 MockAffectedFile('IsInBasePackage.java', [
1410 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511411 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121412 'Log.d(TAG, "foo");',
1413 ]),
1414 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1415 'package org.chromium.base;',
1416 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511417 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121418 'Log.d(TAG, "foo");',
1419 ]),
1420 MockAffectedFile('HasBothLog.java', [
1421 'import org.chromium.base.Log;',
1422 'some random stuff',
dgn38736db2015-09-18 19:20:511423 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121424 'Log.d(TAG, "foo");',
1425 'android.util.Log.d("TAG", "foo");',
1426 ]),
dgnaa68d5e2015-06-10 10:08:221427 MockAffectedFile('HasCorrectTag.java', [
1428 'import org.chromium.base.Log;',
1429 'some random stuff',
dgn38736db2015-09-18 19:20:511430 'private static final String TAG = "cr_Foo";',
1431 'Log.d(TAG, "foo");',
1432 ]),
1433 MockAffectedFile('HasOldTag.java', [
1434 'import org.chromium.base.Log;',
1435 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221436 'private static final String TAG = "cr.Foo";',
1437 'Log.d(TAG, "foo");',
1438 ]),
dgn38736db2015-09-18 19:20:511439 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221440 'import org.chromium.base.Log;',
1441 'some random stuff',
dgn38736db2015-09-18 19:20:511442 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221443 'Log.d(TAG, "foo");',
1444 ]),
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461445 MockAffectedFile('HasDottedTagPublic.java', [
1446 'import org.chromium.base.Log;',
1447 'some random stuff',
1448 'public static final String TAG = "cr_foo.bar";',
1449 'Log.d(TAG, "foo");',
1450 ]),
dgnaa68d5e2015-06-10 10:08:221451 MockAffectedFile('HasNoTagDecl.java', [
1452 'import org.chromium.base.Log;',
1453 'some random stuff',
1454 'Log.d(TAG, "foo");',
1455 ]),
1456 MockAffectedFile('HasIncorrectTagDecl.java', [
1457 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511458 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221459 'some random stuff',
1460 'Log.d(TAG, "foo");',
1461 ]),
1462 MockAffectedFile('HasInlineTag.java', [
1463 'import org.chromium.base.Log;',
1464 'some random stuff',
dgn38736db2015-09-18 19:20:511465 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221466 'Log.d("TAG", "foo");',
1467 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551468 MockAffectedFile('HasInlineTagWithSpace.java', [
1469 'import org.chromium.base.Log;',
1470 'some random stuff',
1471 'private static final String TAG = "cr_Foo";',
1472 'Log.d("log message", "foo");',
1473 ]),
dgn38736db2015-09-18 19:20:511474 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221475 'import org.chromium.base.Log;',
1476 'some random stuff',
1477 'private static final String TAG = "rubbish";',
1478 'Log.d(TAG, "foo");',
1479 ]),
1480 MockAffectedFile('HasTooLongTag.java', [
1481 'import org.chromium.base.Log;',
1482 'some random stuff',
dgn38736db2015-09-18 19:20:511483 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:221484 'Log.d(TAG, "foo");',
1485 ]),
Tomasz Śniatowski3ae2f102020-03-23 15:35:551486 MockAffectedFile('HasTooLongTagWithNoLogCallsInDiff.java', [
1487 'import org.chromium.base.Log;',
1488 'some random stuff',
1489 'private static final String TAG = "21_charachers_long___";',
1490 ]),
dgnaa68d5e2015-06-10 10:08:221491 ]
1492
1493 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1494 mock_input_api, mock_output_api)
1495
dgn38736db2015-09-18 19:20:511496 self.assertEqual(5, len(msgs),
1497 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221498
1499 # Declaration format
dgn38736db2015-09-18 19:20:511500 nb = len(msgs[0].items)
1501 self.assertEqual(2, nb,
1502 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221503 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1504 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221505
1506 # Tag length
dgn38736db2015-09-18 19:20:511507 nb = len(msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551508 self.assertEqual(2, nb,
1509 'Expected %d items, found %d: %s' % (2, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:221510 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551511 self.assertTrue('HasTooLongTagWithNoLogCallsInDiff.java' in msgs[1].items)
dgnaa68d5e2015-06-10 10:08:221512
1513 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511514 nb = len(msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551515 self.assertEqual(3, nb,
1516 'Expected %d items, found %d: %s' % (3, nb, msgs[2].items))
1517 self.assertTrue('HasBothLog.java:5' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221518 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551519 self.assertTrue('HasInlineTagWithSpace.java:4' in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:221520
dgn87d9fb62015-06-12 09:15:121521 # Util Log usage
dgn38736db2015-09-18 19:20:511522 nb = len(msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551523 self.assertEqual(3, nb,
1524 'Expected %d items, found %d: %s' % (3, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:121525 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
Tomasz Śniatowski3ae2f102020-03-23 15:35:551526 self.assertTrue('HasExplicitUtilLog.java:2' in msgs[3].items)
dgn87d9fb62015-06-12 09:15:121527 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:221528
dgn38736db2015-09-18 19:20:511529 # Tag must not contain
1530 nb = len(msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461531 self.assertEqual(3, nb,
dgn38736db2015-09-18 19:20:511532 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1533 self.assertTrue('HasDottedTag.java' in msgs[4].items)
Torne (Richard Coles)3bd7ad02019-10-22 21:20:461534 self.assertTrue('HasDottedTagPublic.java' in msgs[4].items)
dgn38736db2015-09-18 19:20:511535 self.assertTrue('HasOldTag.java' in msgs[4].items)
1536
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391537
estadee17314a02017-01-12 16:22:161538class GoogleAnswerUrlFormatTest(unittest.TestCase):
1539
1540 def testCatchAnswerUrlId(self):
1541 input_api = MockInputApi()
1542 input_api.files = [
1543 MockFile('somewhere/file.cc',
1544 ['char* host = '
1545 ' "https://support.google.com/chrome/answer/123456";']),
1546 MockFile('somewhere_else/file.cc',
1547 ['char* host = '
1548 ' "https://support.google.com/chrome/a/answer/123456";']),
1549 ]
1550
Saagar Sanghavifceeaae2020-08-12 16:40:361551 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161552 input_api, MockOutputApi())
1553 self.assertEqual(1, len(warnings))
1554 self.assertEqual(2, len(warnings[0].items))
1555
1556 def testAllowAnswerUrlParam(self):
1557 input_api = MockInputApi()
1558 input_api.files = [
1559 MockFile('somewhere/file.cc',
1560 ['char* host = '
1561 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1562 ]
1563
Saagar Sanghavifceeaae2020-08-12 16:40:361564 warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
estadee17314a02017-01-12 16:22:161565 input_api, MockOutputApi())
1566 self.assertEqual(0, len(warnings))
1567
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391568
reillyi38965732015-11-16 18:27:331569class HardcodedGoogleHostsTest(unittest.TestCase):
1570
1571 def testWarnOnAssignedLiterals(self):
1572 input_api = MockInputApi()
1573 input_api.files = [
1574 MockFile('content/file.cc',
1575 ['char* host = "https://www.google.com";']),
1576 MockFile('content/file.cc',
1577 ['char* host = "https://www.googleapis.com";']),
1578 MockFile('content/file.cc',
1579 ['char* host = "https://clients1.google.com";']),
1580 ]
1581
Saagar Sanghavifceeaae2020-08-12 16:40:361582 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331583 input_api, MockOutputApi())
1584 self.assertEqual(1, len(warnings))
1585 self.assertEqual(3, len(warnings[0].items))
1586
1587 def testAllowInComment(self):
1588 input_api = MockInputApi()
1589 input_api.files = [
1590 MockFile('content/file.cc',
1591 ['char* host = "https://www.aol.com"; // google.com'])
1592 ]
1593
Saagar Sanghavifceeaae2020-08-12 16:40:361594 warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
reillyi38965732015-11-16 18:27:331595 input_api, MockOutputApi())
1596 self.assertEqual(0, len(warnings))
1597
dgn4401aa52015-04-29 16:26:171598
James Cook6b6597c2019-11-06 22:05:291599class ChromeOsSyncedPrefRegistrationTest(unittest.TestCase):
1600
1601 def testWarnsOnChromeOsDirectories(self):
1602 input_api = MockInputApi()
1603 input_api.files = [
1604 MockFile('ash/file.cc',
1605 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1606 MockFile('chrome/browser/chromeos/file.cc',
1607 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1608 MockFile('chromeos/file.cc',
1609 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1610 MockFile('components/arc/file.cc',
1611 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1612 MockFile('components/exo/file.cc',
1613 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1614 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361615 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291616 input_api, MockOutputApi())
1617 self.assertEqual(1, len(warnings))
1618
1619 def testDoesNotWarnOnSyncOsPref(self):
1620 input_api = MockInputApi()
1621 input_api.files = [
1622 MockFile('chromeos/file.cc',
1623 ['PrefRegistrySyncable::SYNCABLE_OS_PREF']),
1624 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361625 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291626 input_api, MockOutputApi())
1627 self.assertEqual(0, len(warnings))
1628
1629 def testDoesNotWarnOnCrossPlatformDirectories(self):
1630 input_api = MockInputApi()
1631 input_api.files = [
1632 MockFile('chrome/browser/ui/file.cc',
1633 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1634 MockFile('components/sync/file.cc',
1635 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1636 MockFile('content/browser/file.cc',
1637 ['PrefRegistrySyncable::SYNCABLE_PREF']),
1638 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361639 warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
James Cook6b6597c2019-11-06 22:05:291640 input_api, MockOutputApi())
1641 self.assertEqual(0, len(warnings))
1642
1643 def testSeparateWarningForPriorityPrefs(self):
1644 input_api = MockInputApi()
1645 input_api.files = [
1646 MockFile('chromeos/file.cc',
1647 ['PrefRegistrySyncable::SYNCABLE_PREF',
1648 'PrefRegistrySyncable::SYNCABLE_PRIORITY_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(2, len(warnings))
1653
1654
jbriance9e12f162016-11-25 07:57:501655class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311656 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501657 mock_input_api = MockInputApi()
1658 mock_input_api.files = [
1659 MockAffectedFile('somewhere/file.cc', [
1660 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311661 ]),
1662 MockAffectedFile('third_party/header.h', [
1663 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501664 ])
1665 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361666 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391667 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501668 self.assertEqual(0, len(warnings))
1669
1670 def testNoNestedDeclaration(self):
1671 mock_input_api = MockInputApi()
1672 mock_input_api.files = [
1673 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311674 'class SomeClass {',
1675 ' protected:',
1676 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501677 '};'
1678 ])
1679 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361680 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391681 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501682 self.assertEqual(0, len(warnings))
1683
1684 def testSubStrings(self):
1685 mock_input_api = MockInputApi()
1686 mock_input_api.files = [
1687 MockAffectedFile('somewhere/header.h', [
1688 'class NotUsefulClass;',
1689 'struct SomeStruct;',
1690 'UsefulClass *p1;',
1691 'SomeStructPtr *p2;'
1692 ])
1693 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361694 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391695 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501696 self.assertEqual(2, len(warnings))
1697
1698 def testUselessForwardDeclaration(self):
1699 mock_input_api = MockInputApi()
1700 mock_input_api.files = [
1701 MockAffectedFile('somewhere/header.h', [
1702 'class DummyClass;',
1703 'struct DummyStruct;',
1704 'class UsefulClass;',
1705 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311706 ])
jbriance9e12f162016-11-25 07:57:501707 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361708 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391709 MockOutputApi())
jbriance9e12f162016-11-25 07:57:501710 self.assertEqual(2, len(warnings))
1711
jbriance2c51e821a2016-12-12 08:24:311712 def testBlinkHeaders(self):
1713 mock_input_api = MockInputApi()
1714 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491715 MockAffectedFile('third_party/blink/header.h', [
jbriance2c51e821a2016-12-12 08:24:311716 'class DummyClass;',
1717 'struct DummyStruct;',
1718 ]),
Kent Tamura32dbbcb2018-11-30 12:28:491719 MockAffectedFile('third_party\\blink\\header.h', [
jbriance2c51e821a2016-12-12 08:24:311720 'class DummyClass;',
1721 'struct DummyStruct;',
1722 ])
1723 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361724 warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api,
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:391725 MockOutputApi())
jbriance2c51e821a2016-12-12 08:24:311726 self.assertEqual(4, len(warnings))
1727
jbriance9e12f162016-11-25 07:57:501728
rlanday6802cf632017-05-30 17:48:361729class RelativeIncludesTest(unittest.TestCase):
1730 def testThirdPartyNotWebKitIgnored(self):
1731 mock_input_api = MockInputApi()
1732 mock_input_api.files = [
1733 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1734 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1735 ]
1736
1737 mock_output_api = MockOutputApi()
1738
Saagar Sanghavifceeaae2020-08-12 16:40:361739 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361740 mock_input_api, mock_output_api)
1741 self.assertEqual(0, len(errors))
1742
1743 def testNonCppFileIgnored(self):
1744 mock_input_api = MockInputApi()
1745 mock_input_api.files = [
1746 MockAffectedFile('test.py', '#include "../header.h"'),
1747 ]
1748
1749 mock_output_api = MockOutputApi()
1750
Saagar Sanghavifceeaae2020-08-12 16:40:361751 errors = PRESUBMIT.CheckForRelativeIncludes(
rlanday6802cf632017-05-30 17:48:361752 mock_input_api, mock_output_api)
1753 self.assertEqual(0, len(errors))
1754
1755 def testInnocuousChangesAllowed(self):
1756 mock_input_api = MockInputApi()
1757 mock_input_api.files = [
1758 MockAffectedFile('test.cpp', '#include "header.h"'),
1759 MockAffectedFile('test2.cpp', '../'),
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 testRelativeIncludeNonWebKitProducesError(self):
1769 mock_input_api = MockInputApi()
1770 mock_input_api.files = [
1771 MockAffectedFile('test.cpp', ['#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(1, len(errors))
1779
1780 def testRelativeIncludeWebKitProducesError(self):
1781 mock_input_api = MockInputApi()
1782 mock_input_api.files = [
Kent Tamura32dbbcb2018-11-30 12:28:491783 MockAffectedFile('third_party/blink/test.cpp',
rlanday6802cf632017-05-30 17:48:361784 ['#include "../header.h']),
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(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241792
Daniel Cheng13ca61a882017-08-25 15:11:251793
Daniel Bratell65b033262019-04-23 08:17:061794class CCIncludeTest(unittest.TestCase):
1795 def testThirdPartyNotBlinkIgnored(self):
1796 mock_input_api = MockInputApi()
1797 mock_input_api.files = [
1798 MockAffectedFile('third_party/test.cpp', '#include "file.cc"'),
1799 ]
1800
1801 mock_output_api = MockOutputApi()
1802
Saagar Sanghavifceeaae2020-08-12 16:40:361803 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061804 mock_input_api, mock_output_api)
1805 self.assertEqual(0, len(errors))
1806
1807 def testPythonFileIgnored(self):
1808 mock_input_api = MockInputApi()
1809 mock_input_api.files = [
1810 MockAffectedFile('test.py', '#include "file.cc"'),
1811 ]
1812
1813 mock_output_api = MockOutputApi()
1814
Saagar Sanghavifceeaae2020-08-12 16:40:361815 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061816 mock_input_api, mock_output_api)
1817 self.assertEqual(0, len(errors))
1818
1819 def testIncFilesAccepted(self):
1820 mock_input_api = MockInputApi()
1821 mock_input_api.files = [
1822 MockAffectedFile('test.py', '#include "file.inc"'),
1823 ]
1824
1825 mock_output_api = MockOutputApi()
1826
Saagar Sanghavifceeaae2020-08-12 16:40:361827 errors = PRESUBMIT.CheckForCcIncludes(
Daniel Bratell65b033262019-04-23 08:17:061828 mock_input_api, mock_output_api)
1829 self.assertEqual(0, len(errors))
1830
1831 def testInnocuousChangesAllowed(self):
1832 mock_input_api = MockInputApi()
1833 mock_input_api.files = [
1834 MockAffectedFile('test.cpp', '#include "header.h"'),
1835 MockAffectedFile('test2.cpp', 'Something "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 testCcIncludeNonBlinkProducesError(self):
1845 mock_input_api = MockInputApi()
1846 mock_input_api.files = [
1847 MockAffectedFile('test.cpp', ['#include "file.cc"']),
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(1, len(errors))
1855
1856 def testCppIncludeBlinkProducesError(self):
1857 mock_input_api = MockInputApi()
1858 mock_input_api.files = [
1859 MockAffectedFile('third_party/blink/test.cpp',
1860 ['#include "foo/file.cpp"']),
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(1, len(errors))
1868
1869
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191870class NewHeaderWithoutGnChangeTest(unittest.TestCase):
1871 def testAddHeaderWithoutGn(self):
1872 mock_input_api = MockInputApi()
1873 mock_input_api.files = [
1874 MockAffectedFile('base/stuff.h', ''),
1875 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361876 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191877 mock_input_api, MockOutputApi())
1878 self.assertEqual(1, len(warnings))
1879 self.assertTrue('base/stuff.h' in warnings[0].items)
1880
1881 def testModifyHeader(self):
1882 mock_input_api = MockInputApi()
1883 mock_input_api.files = [
1884 MockAffectedFile('base/stuff.h', '', action='M'),
1885 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361886 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191887 mock_input_api, MockOutputApi())
1888 self.assertEqual(0, len(warnings))
1889
1890 def testDeleteHeader(self):
1891 mock_input_api = MockInputApi()
1892 mock_input_api.files = [
1893 MockAffectedFile('base/stuff.h', '', action='D'),
1894 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361895 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191896 mock_input_api, MockOutputApi())
1897 self.assertEqual(0, len(warnings))
1898
1899 def testAddHeaderWithGn(self):
1900 mock_input_api = MockInputApi()
1901 mock_input_api.files = [
1902 MockAffectedFile('base/stuff.h', ''),
1903 MockAffectedFile('base/BUILD.gn', 'stuff.h'),
1904 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361905 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191906 mock_input_api, MockOutputApi())
1907 self.assertEqual(0, len(warnings))
1908
1909 def testAddHeaderWithGni(self):
1910 mock_input_api = MockInputApi()
1911 mock_input_api.files = [
1912 MockAffectedFile('base/stuff.h', ''),
1913 MockAffectedFile('base/files.gni', 'stuff.h'),
1914 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361915 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191916 mock_input_api, MockOutputApi())
1917 self.assertEqual(0, len(warnings))
1918
1919 def testAddHeaderWithOther(self):
1920 mock_input_api = MockInputApi()
1921 mock_input_api.files = [
1922 MockAffectedFile('base/stuff.h', ''),
1923 MockAffectedFile('base/stuff.cc', 'stuff.h'),
1924 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361925 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191926 mock_input_api, MockOutputApi())
1927 self.assertEqual(1, len(warnings))
1928
1929 def testAddHeaderWithWrongGn(self):
1930 mock_input_api = MockInputApi()
1931 mock_input_api.files = [
1932 MockAffectedFile('base/stuff.h', ''),
1933 MockAffectedFile('base/BUILD.gn', 'stuff_h'),
1934 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361935 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191936 mock_input_api, MockOutputApi())
1937 self.assertEqual(1, len(warnings))
1938
1939 def testAddHeadersWithGn(self):
1940 mock_input_api = MockInputApi()
1941 mock_input_api.files = [
1942 MockAffectedFile('base/stuff.h', ''),
1943 MockAffectedFile('base/another.h', ''),
1944 MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'),
1945 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361946 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191947 mock_input_api, MockOutputApi())
1948 self.assertEqual(0, len(warnings))
1949
1950 def testAddHeadersWithWrongGn(self):
1951 mock_input_api = MockInputApi()
1952 mock_input_api.files = [
1953 MockAffectedFile('base/stuff.h', ''),
1954 MockAffectedFile('base/another.h', ''),
1955 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'),
1956 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361957 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191958 mock_input_api, MockOutputApi())
1959 self.assertEqual(1, len(warnings))
1960 self.assertFalse('base/stuff.h' in warnings[0].items)
1961 self.assertTrue('base/another.h' in warnings[0].items)
1962
1963 def testAddHeadersWithWrongGn2(self):
1964 mock_input_api = MockInputApi()
1965 mock_input_api.files = [
1966 MockAffectedFile('base/stuff.h', ''),
1967 MockAffectedFile('base/another.h', ''),
1968 MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'),
1969 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361970 warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:191971 mock_input_api, MockOutputApi())
1972 self.assertEqual(1, len(warnings))
1973 self.assertTrue('base/stuff.h' in warnings[0].items)
1974 self.assertTrue('base/another.h' in warnings[0].items)
1975
1976
Michael Giuffridad3bc8672018-10-25 22:48:021977class CorrectProductNameInMessagesTest(unittest.TestCase):
1978 def testProductNameInDesc(self):
1979 mock_input_api = MockInputApi()
1980 mock_input_api.files = [
1981 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
1982 '<message name="Foo" desc="Welcome to Chrome">',
1983 ' Welcome to Chrome!',
1984 '</message>',
1985 ]),
1986 MockAffectedFile('chrome/app/chromium_strings.grd', [
1987 '<message name="Bar" desc="Welcome to Chrome">',
1988 ' Welcome to Chromium!',
1989 '</message>',
1990 ]),
1991 ]
Saagar Sanghavifceeaae2020-08-12 16:40:361992 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:021993 mock_input_api, MockOutputApi())
1994 self.assertEqual(0, len(warnings))
1995
1996 def testChromeInChromium(self):
1997 mock_input_api = MockInputApi()
1998 mock_input_api.files = [
1999 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2000 '<message name="Foo" desc="Welcome to Chrome">',
2001 ' Welcome to Chrome!',
2002 '</message>',
2003 ]),
2004 MockAffectedFile('chrome/app/chromium_strings.grd', [
2005 '<message name="Bar" desc="Welcome to Chrome">',
2006 ' Welcome to Chrome!',
2007 '</message>',
2008 ]),
2009 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362010 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022011 mock_input_api, MockOutputApi())
2012 self.assertEqual(1, len(warnings))
2013 self.assertTrue('chrome/app/chromium_strings.grd' in warnings[0].items[0])
2014
2015 def testChromiumInChrome(self):
2016 mock_input_api = MockInputApi()
2017 mock_input_api.files = [
2018 MockAffectedFile('chrome/app/google_chrome_strings.grd', [
2019 '<message name="Foo" desc="Welcome to Chrome">',
2020 ' Welcome to Chromium!',
2021 '</message>',
2022 ]),
2023 MockAffectedFile('chrome/app/chromium_strings.grd', [
2024 '<message name="Bar" desc="Welcome to Chrome">',
2025 ' Welcome to Chromium!',
2026 '</message>',
2027 ]),
2028 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362029 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022030 mock_input_api, MockOutputApi())
2031 self.assertEqual(1, len(warnings))
2032 self.assertTrue(
2033 'chrome/app/google_chrome_strings.grd:2' in warnings[0].items[0])
2034
2035 def testMultipleInstances(self):
2036 mock_input_api = MockInputApi()
2037 mock_input_api.files = [
2038 MockAffectedFile('chrome/app/chromium_strings.grd', [
2039 '<message name="Bar" desc="Welcome to Chrome">',
2040 ' Welcome to Chrome!',
2041 '</message>',
2042 '<message name="Baz" desc="A correct message">',
2043 ' Chromium is the software you are using.',
2044 '</message>',
2045 '<message name="Bat" desc="An incorrect message">',
2046 ' Google Chrome is the software you are using.',
2047 '</message>',
2048 ]),
2049 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362050 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022051 mock_input_api, MockOutputApi())
2052 self.assertEqual(1, len(warnings))
2053 self.assertTrue(
2054 'chrome/app/chromium_strings.grd:2' in warnings[0].items[0])
2055 self.assertTrue(
2056 'chrome/app/chromium_strings.grd:8' in warnings[0].items[1])
2057
2058 def testMultipleWarnings(self):
2059 mock_input_api = MockInputApi()
2060 mock_input_api.files = [
2061 MockAffectedFile('chrome/app/chromium_strings.grd', [
2062 '<message name="Bar" desc="Welcome to Chrome">',
2063 ' Welcome to Chrome!',
2064 '</message>',
2065 '<message name="Baz" desc="A correct message">',
2066 ' Chromium is the software you are using.',
2067 '</message>',
2068 '<message name="Bat" desc="An incorrect message">',
2069 ' Google Chrome is the software you are using.',
2070 '</message>',
2071 ]),
2072 MockAffectedFile('components/components_google_chrome_strings.grd', [
2073 '<message name="Bar" desc="Welcome to Chrome">',
2074 ' Welcome to Chrome!',
2075 '</message>',
2076 '<message name="Baz" desc="A correct message">',
2077 ' Chromium is the software you are using.',
2078 '</message>',
2079 '<message name="Bat" desc="An incorrect message">',
2080 ' Google Chrome is the software you are using.',
2081 '</message>',
2082 ]),
2083 ]
Saagar Sanghavifceeaae2020-08-12 16:40:362084 warnings = PRESUBMIT.CheckCorrectProductNameInMessages(
Michael Giuffridad3bc8672018-10-25 22:48:022085 mock_input_api, MockOutputApi())
2086 self.assertEqual(2, len(warnings))
2087 self.assertTrue(
2088 'components/components_google_chrome_strings.grd:5'
2089 in warnings[0].items[0])
2090 self.assertTrue(
2091 'chrome/app/chromium_strings.grd:2' in warnings[1].items[0])
2092 self.assertTrue(
2093 'chrome/app/chromium_strings.grd:8' in warnings[1].items[1])
2094
2095
Ken Rockot9f668262018-12-21 18:56:362096class ServiceManifestOwnerTest(unittest.TestCase):
Ken Rockot9f668262018-12-21 18:56:362097 def testServiceManifestChangeNeedsSecurityOwner(self):
2098 mock_input_api = MockInputApi()
2099 mock_input_api.files = [
2100 MockAffectedFile('services/goat/public/cpp/manifest.cc',
2101 [
2102 '#include "services/goat/public/cpp/manifest.h"',
2103 'const service_manager::Manifest& GetManifest() {}',
2104 ])]
2105 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362106 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362107 mock_input_api, mock_output_api)
2108 self.assertEqual(1, len(errors))
2109 self.assertEqual(
2110 'Found OWNERS files that need to be updated for IPC security review ' +
2111 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2112
2113 def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
2114 mock_input_api = MockInputApi()
2115 mock_input_api.files = [
2116 MockAffectedFile('some/non/service/thing/foo_manifest.cc',
2117 [
2118 'const char kNoEnforcement[] = "not a manifest!";',
2119 ])]
2120 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362121 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032122 mock_input_api, mock_output_api)
2123 self.assertEqual([], errors)
2124
2125
2126class FuchsiaSecurityOwnerTest(unittest.TestCase):
2127 def testFidlChangeNeedsSecurityOwner(self):
2128 mock_input_api = MockInputApi()
2129 mock_input_api.files = [
2130 MockAffectedFile('potentially/scary/ipc.fidl',
2131 [
2132 'library test.fidl'
2133 ])]
2134 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362135 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032136 mock_input_api, mock_output_api)
2137 self.assertEqual(1, len(errors))
2138 self.assertEqual(
2139 'Found OWNERS files that need to be updated for IPC security review ' +
2140 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2141
2142 def testComponentManifestV1ChangeNeedsSecurityOwner(self):
2143 mock_input_api = MockInputApi()
2144 mock_input_api.files = [
2145 MockAffectedFile('potentially/scary/v2_manifest.cmx',
2146 [
2147 '{ "that is no": "manifest!" }'
2148 ])]
2149 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362150 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032151 mock_input_api, mock_output_api)
2152 self.assertEqual(1, len(errors))
2153 self.assertEqual(
2154 'Found OWNERS files that need to be updated for IPC security review ' +
2155 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2156
2157 def testComponentManifestV2NeedsSecurityOwner(self):
2158 mock_input_api = MockInputApi()
2159 mock_input_api.files = [
2160 MockAffectedFile('potentially/scary/v2_manifest.cml',
2161 [
2162 '{ "that is no": "manifest!" }'
2163 ])]
2164 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362165 errors = PRESUBMIT.CheckSecurityOwners(
Wez17c66962020-04-29 15:26:032166 mock_input_api, mock_output_api)
2167 self.assertEqual(1, len(errors))
2168 self.assertEqual(
2169 'Found OWNERS files that need to be updated for IPC security review ' +
2170 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
2171
2172 def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2173 mock_input_api = MockInputApi()
2174 mock_input_api.files = [
2175 MockAffectedFile('some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',
2176 [
2177 'const char kNoEnforcement[] = "Security?!? Pah!";',
2178 ])]
2179 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:362180 errors = PRESUBMIT.CheckSecurityOwners(
Ken Rockot9f668262018-12-21 18:56:362181 mock_input_api, mock_output_api)
2182 self.assertEqual([], errors)
2183
Daniel Cheng13ca61a882017-08-25 15:11:252184
Robert Sesek2c905332020-05-06 23:17:132185class SecurityChangeTest(unittest.TestCase):
2186 class _MockOwnersDB(object):
2187 def __init__(self):
2188 self.email_regexp = '.*'
2189
2190 def owners_rooted_at_file(self, f):
2191 return ['[email protected]', '[email protected]']
2192
2193 def _mockChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2194 def __MockOwnerAndReviewers(input_api, email_regexp, approval_needed=False):
2195 return [owner, reviewers]
2196 input_api.canned_checks.GetCodereviewOwnerAndReviewers = \
2197 __MockOwnerAndReviewers
2198
Alex Goughbc964dd2020-06-15 17:52:372199 def testDiffGetServiceSandboxType(self):
Robert Sesek2c905332020-05-06 23:17:132200 mock_input_api = MockInputApi()
2201 mock_input_api.files = [
2202 MockAffectedFile(
2203 'services/goat/teleporter_host.cc',
2204 [
Alex Goughbc964dd2020-06-15 17:52:372205 'template <>',
2206 'inline content::SandboxType',
2207 'content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {',
2208 '#if defined(OS_WIN)',
2209 ' return SandboxType::kGoaty;',
2210 '#else',
2211 ' return SandboxType::kNoSandbox;',
2212 '#endif // !defined(OS_WIN)',
2213 '}'
Robert Sesek2c905332020-05-06 23:17:132214 ]
2215 ),
2216 ]
2217 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2218 mock_input_api)
2219 self.assertEqual({
2220 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372221 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132222 ])},
2223 files_to_functions)
2224
2225 def testDiffRemovingLine(self):
2226 mock_input_api = MockInputApi()
2227 mock_file = MockAffectedFile('services/goat/teleporter_host.cc', '')
2228 mock_file._scm_diff = """--- old 2020-05-04 14:08:25.000000000 -0400
2229+++ new 2020-05-04 14:08:32.000000000 -0400
2230@@ -1,5 +1,4 @@
Alex Goughbc964dd2020-06-15 17:52:372231 template <>
2232 inline content::SandboxType
2233-content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {
2234 #if defined(OS_WIN)
2235 return SandboxType::kGoaty;
Robert Sesek2c905332020-05-06 23:17:132236"""
2237 mock_input_api.files = [mock_file]
2238 files_to_functions = PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2239 mock_input_api)
2240 self.assertEqual({
2241 'services/goat/teleporter_host.cc': set([
Alex Goughbc964dd2020-06-15 17:52:372242 'content::GetServiceSandboxType<>()'
Robert Sesek2c905332020-05-06 23:17:132243 ])},
2244 files_to_functions)
2245
2246 def testChangeOwnersMissing(self):
2247 mock_input_api = MockInputApi()
2248 mock_input_api.owners_db = self._MockOwnersDB()
2249 mock_input_api.is_committing = False
2250 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372251 MockAffectedFile('file.cc', ['GetServiceSandboxType<Goat>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132252 ]
2253 mock_output_api = MockOutputApi()
2254 self._mockChangeOwnerAndReviewers(
2255 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362256 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132257 self.assertEquals(1, len(result))
2258 self.assertEquals(result[0].type, 'notify')
2259 self.assertEquals(result[0].message,
2260 'The following files change calls to security-sensive functions\n' \
2261 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2262 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372263 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132264
2265 def testChangeOwnersMissingAtCommit(self):
2266 mock_input_api = MockInputApi()
2267 mock_input_api.owners_db = self._MockOwnersDB()
2268 mock_input_api.is_committing = True
2269 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372270 MockAffectedFile('file.cc', ['GetServiceSandboxType<mojom::Goat>()'])
Robert Sesek2c905332020-05-06 23:17:132271 ]
2272 mock_output_api = MockOutputApi()
2273 self._mockChangeOwnerAndReviewers(
2274 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362275 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132276 self.assertEquals(1, len(result))
2277 self.assertEquals(result[0].type, 'error')
2278 self.assertEquals(result[0].message,
2279 'The following files change calls to security-sensive functions\n' \
2280 'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2281 ' file.cc\n'
Alex Goughbc964dd2020-06-15 17:52:372282 ' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:132283
2284 def testChangeOwnersPresent(self):
2285 mock_input_api = MockInputApi()
2286 mock_input_api.owners_db = self._MockOwnersDB()
2287 mock_input_api.files = [
2288 MockAffectedFile('file.cc', ['WithSandboxType(Sandbox)'])
2289 ]
2290 mock_output_api = MockOutputApi()
2291 self._mockChangeOwnerAndReviewers(
2292 mock_input_api, '[email protected]',
2293 ['[email protected]', '[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362294 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132295 self.assertEquals(0, len(result))
2296
2297 def testChangeOwnerIsSecurityOwner(self):
2298 mock_input_api = MockInputApi()
2299 mock_input_api.owners_db = self._MockOwnersDB()
2300 mock_input_api.files = [
Alex Goughbc964dd2020-06-15 17:52:372301 MockAffectedFile('file.cc', ['GetServiceSandboxType<T>(Sandbox)'])
Robert Sesek2c905332020-05-06 23:17:132302 ]
2303 mock_output_api = MockOutputApi()
2304 self._mockChangeOwnerAndReviewers(
2305 mock_input_api, '[email protected]', ['[email protected]'])
Saagar Sanghavifceeaae2020-08-12 16:40:362306 result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api)
Robert Sesek2c905332020-05-06 23:17:132307 self.assertEquals(1, len(result))
2308
2309
Mario Sanchez Prada2472cab2019-09-18 10:58:312310class BannedTypeCheckTest(unittest.TestCase):
Sylvain Defresnea8b73d252018-02-28 15:45:542311
Peter Kasting94a56c42019-10-25 21:54:042312 def testBannedCppFunctions(self):
2313 input_api = MockInputApi()
2314 input_api.files = [
2315 MockFile('some/cpp/problematic/file.cc',
2316 ['using namespace std;']),
Oksana Zhuravlovac8222d22019-12-19 19:21:162317 MockFile('third_party/blink/problematic/file.cc',
2318 ['GetInterfaceProvider()']),
Peter Kasting94a56c42019-10-25 21:54:042319 MockFile('some/cpp/ok/file.cc',
2320 ['using std::string;']),
Allen Bauer53b43fb12020-03-12 17:21:472321 MockFile('some/cpp/problematic/file2.cc',
2322 ['set_owned_by_client()']),
Peter Kasting94a56c42019-10-25 21:54:042323 ]
2324
Saagar Sanghavifceeaae2020-08-12 16:40:362325 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlovac8222d22019-12-19 19:21:162326
2327 # warnings are results[0], errors are results[1]
2328 self.assertEqual(2, len(results))
2329 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2330 self.assertTrue(
2331 'third_party/blink/problematic/file.cc' in results[0].message)
2332 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
Allen Bauer53b43fb12020-03-12 17:21:472333 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
Peter Kasting94a56c42019-10-25 21:54:042334
Abhijeet Kandalkar1e7c2502019-10-29 15:05:452335 def testBannedBlinkDowncastHelpers(self):
2336 input_api = MockInputApi()
2337 input_api.files = [
2338 MockFile('some/cpp/problematic/file1.cc',
2339 ['DEFINE_TYPE_CASTS(ToType, FromType, from_argument,'
2340 'PointerPredicate(), ReferencePredicate());']),
2341 MockFile('some/cpp/problematic/file2.cc',
2342 ['bool is_test_ele = IsHTMLTestElement(n);']),
2343 MockFile('some/cpp/problematic/file3.cc',
2344 ['auto* html_test_ele = ToHTMLTestElement(n);']),
2345 MockFile('some/cpp/problematic/file4.cc',
2346 ['auto* html_test_ele_or_null = ToHTMLTestElementOrNull(n);']),
2347 MockFile('some/cpp/ok/file1.cc',
2348 ['bool is_test_ele = IsA<HTMLTestElement>(n);']),
2349 MockFile('some/cpp/ok/file2.cc',
2350 ['auto* html_test_ele = To<HTMLTestElement>(n);']),
2351 MockFile('some/cpp/ok/file3.cc',
2352 ['auto* html_test_ele_or_null = ',
2353 'DynamicTo<HTMLTestElement>(n);']),
2354 ]
2355
2356 # warnings are errors[0], errors are errors[1]
Saagar Sanghavifceeaae2020-08-12 16:40:362357 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Abhijeet Kandalkar1e7c2502019-10-29 15:05:452358 self.assertEqual(2, len(errors))
2359 self.assertTrue('some/cpp/problematic/file1.cc' in errors[1].message)
2360 self.assertTrue('some/cpp/problematic/file2.cc' in errors[0].message)
2361 self.assertTrue('some/cpp/problematic/file3.cc' in errors[0].message)
2362 self.assertTrue('some/cpp/problematic/file4.cc' in errors[0].message)
2363 self.assertTrue('some/cpp/ok/file1.cc' not in errors[0].message)
2364 self.assertTrue('some/cpp/ok/file2.cc' not in errors[0].message)
2365 self.assertTrue('some/cpp/ok/file3.cc' not in errors[0].message)
2366
Peter K. Lee6c03ccff2019-07-15 14:40:052367 def testBannedIosObjcFunctions(self):
Sylvain Defresnea8b73d252018-02-28 15:45:542368 input_api = MockInputApi()
2369 input_api.files = [
2370 MockFile('some/ios/file.mm',
2371 ['TEST(SomeClassTest, SomeInteraction) {',
2372 '}']),
2373 MockFile('some/mac/file.mm',
2374 ['TEST(SomeClassTest, SomeInteraction) {',
2375 '}']),
2376 MockFile('another/ios_file.mm',
2377 ['class SomeTest : public testing::Test {};']),
Peter K. Lee6c03ccff2019-07-15 14:40:052378 MockFile('some/ios/file_egtest.mm',
2379 ['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
2380 MockFile('some/ios/file_unittest.mm',
2381 ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']),
Sylvain Defresnea8b73d252018-02-28 15:45:542382 ]
2383
Saagar Sanghavifceeaae2020-08-12 16:40:362384 errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Sylvain Defresnea8b73d252018-02-28 15:45:542385 self.assertEqual(1, len(errors))
2386 self.assertTrue('some/ios/file.mm' in errors[0].message)
2387 self.assertTrue('another/ios_file.mm' in errors[0].message)
2388 self.assertTrue('some/mac/file.mm' not in errors[0].message)
Peter K. Lee6c03ccff2019-07-15 14:40:052389 self.assertTrue('some/ios/file_egtest.mm' in errors[0].message)
2390 self.assertTrue('some/ios/file_unittest.mm' not in errors[0].message)
Sylvain Defresnea8b73d252018-02-28 15:45:542391
Carlos Knippschildab192b8c2019-04-08 20:02:382392 def testBannedMojoFunctions(self):
2393 input_api = MockInputApi()
2394 input_api.files = [
2395 MockFile('some/cpp/problematic/file.cc',
2396 ['mojo::DataPipe();']),
Oksana Zhuravlovafd247772019-05-16 16:57:292397 MockFile('some/cpp/problematic/file2.cc',
2398 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382399 MockFile('some/cpp/ok/file.cc',
2400 ['CreateDataPipe();']),
Kinuko Yasuda376c2ce12019-04-16 01:20:372401 MockFile('some/cpp/ok/file2.cc',
2402 ['mojo::DataPipeDrainer();']),
Oksana Zhuravlovafd247772019-05-16 16:57:292403 MockFile('third_party/blink/ok/file3.cc',
2404 ['mojo::ConvertTo<>']),
2405 MockFile('content/renderer/ok/file3.cc',
2406 ['mojo::ConvertTo<>']),
Carlos Knippschildab192b8c2019-04-08 20:02:382407 ]
2408
Saagar Sanghavifceeaae2020-08-12 16:40:362409 results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi())
Oksana Zhuravlova1d3b59de2019-05-17 00:08:222410
2411 # warnings are results[0], errors are results[1]
2412 self.assertEqual(2, len(results))
2413 self.assertTrue('some/cpp/problematic/file.cc' in results[1].message)
2414 self.assertTrue('some/cpp/problematic/file2.cc' in results[0].message)
2415 self.assertTrue('some/cpp/ok/file.cc' not in results[1].message)
2416 self.assertTrue('some/cpp/ok/file2.cc' not in results[1].message)
2417 self.assertTrue('third_party/blink/ok/file3.cc' not in results[0].message)
2418 self.assertTrue('content/renderer/ok/file3.cc' not in results[0].message)
Carlos Knippschildab192b8c2019-04-08 20:02:382419
Mario Sanchez Prada2472cab2019-09-18 10:58:312420 def testDeprecatedMojoTypes(self):
Mario Sanchez Pradacec9cef2019-12-15 11:54:572421 ok_paths = ['components/arc']
2422 warning_paths = ['some/cpp']
Mario Sanchez Pradaaab91382019-12-19 08:57:092423 error_paths = ['third_party/blink', 'content']
Mario Sanchez Prada2472cab2019-09-18 10:58:312424 test_cases = [
2425 {
2426 'type': 'mojo::AssociatedBinding<>;',
2427 'file': 'file1.c'
2428 },
2429 {
2430 'type': 'mojo::AssociatedBindingSet<>;',
2431 'file': 'file2.c'
2432 },
2433 {
2434 'type': 'mojo::AssociatedInterfacePtr<>',
2435 'file': 'file3.cc'
2436 },
2437 {
2438 'type': 'mojo::AssociatedInterfacePtrInfo<>',
2439 'file': 'file4.cc'
2440 },
2441 {
2442 'type': 'mojo::AssociatedInterfaceRequest<>',
2443 'file': 'file5.cc'
2444 },
2445 {
2446 'type': 'mojo::Binding<>',
2447 'file': 'file6.cc'
2448 },
2449 {
2450 'type': 'mojo::BindingSet<>',
2451 'file': 'file7.cc'
2452 },
2453 {
2454 'type': 'mojo::InterfacePtr<>',
2455 'file': 'file8.cc'
2456 },
2457 {
2458 'type': 'mojo::InterfacePtrInfo<>',
2459 'file': 'file9.cc'
2460 },
2461 {
2462 'type': 'mojo::InterfaceRequest<>',
2463 'file': 'file10.cc'
2464 },
2465 {
2466 'type': 'mojo::MakeRequest()',
2467 'file': 'file11.cc'
2468 },
2469 {
2470 'type': 'mojo::MakeRequestAssociatedWithDedicatedPipe()',
2471 'file': 'file12.cc'
2472 },
2473 {
2474 'type': 'mojo::MakeStrongBinding()<>',
2475 'file': 'file13.cc'
2476 },
2477 {
2478 'type': 'mojo::MakeStrongAssociatedBinding()<>',
2479 'file': 'file14.cc'
2480 },
2481 {
Gyuyoung Kim4952ba62020-07-07 07:33:442482 'type': 'mojo::StrongAssociatedBinding<>',
Mario Sanchez Prada2472cab2019-09-18 10:58:312483 'file': 'file15.cc'
2484 },
2485 {
Gyuyoung Kim4952ba62020-07-07 07:33:442486 'type': 'mojo::StrongBinding<>',
Mario Sanchez Prada2472cab2019-09-18 10:58:312487 'file': 'file16.cc'
2488 },
Gyuyoung Kim4952ba62020-07-07 07:33:442489 {
2490 'type': 'mojo::StrongAssociatedBindingSet<>',
2491 'file': 'file17.cc'
2492 },
2493 {
2494 'type': 'mojo::StrongBindingSet<>',
2495 'file': 'file18.cc'
2496 },
Mario Sanchez Prada2472cab2019-09-18 10:58:312497 ]
2498
2499 # Build the list of MockFiles considering paths that should trigger warnings
Mario Sanchez Pradacec9cef2019-12-15 11:54:572500 # as well as paths that should trigger errors.
Mario Sanchez Prada2472cab2019-09-18 10:58:312501 input_api = MockInputApi()
2502 input_api.files = []
2503 for test_case in test_cases:
2504 for path in ok_paths:
2505 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2506 [test_case['type']]))
2507 for path in warning_paths:
2508 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2509 [test_case['type']]))
Mario Sanchez Pradacec9cef2019-12-15 11:54:572510 for path in error_paths:
2511 input_api.files.append(MockFile(os.path.join(path, test_case['file']),
2512 [test_case['type']]))
Mario Sanchez Prada2472cab2019-09-18 10:58:312513
Saagar Sanghavifceeaae2020-08-12 16:40:362514 results = PRESUBMIT.CheckNoDeprecatedMojoTypes(input_api, MockOutputApi())
Mario Sanchez Prada2472cab2019-09-18 10:58:312515
Mario Sanchez Pradacec9cef2019-12-15 11:54:572516 # warnings are results[0], errors are results[1]
2517 self.assertEqual(2, len(results))
Mario Sanchez Prada2472cab2019-09-18 10:58:312518
2519 for test_case in test_cases:
Mario Sanchez Pradacec9cef2019-12-15 11:54:572520 # Check that no warnings nor errors have been triggered for these paths.
Mario Sanchez Prada2472cab2019-09-18 10:58:312521 for path in ok_paths:
2522 self.assertFalse(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572523 self.assertFalse(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312524
2525 # Check warnings have been triggered for these paths.
2526 for path in warning_paths:
2527 self.assertTrue(path in results[0].message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:572528 self.assertFalse(path in results[1].message)
2529
2530 # Check errors have been triggered for these paths.
2531 for path in error_paths:
2532 self.assertFalse(path in results[0].message)
2533 self.assertTrue(path in results[1].message)
Mario Sanchez Prada2472cab2019-09-18 10:58:312534
Sylvain Defresnea8b73d252018-02-28 15:45:542535
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272536class NoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:242537 def testTruePositives(self):
2538 mock_input_api = MockInputApi()
2539 mock_input_api.files = [
2540 MockFile('some/path/foo.cc', ['foo_for_testing();']),
2541 MockFile('some/path/foo.mm', ['FooForTesting();']),
2542 MockFile('some/path/foo.cxx', ['FooForTests();']),
2543 MockFile('some/path/foo.cpp', ['foo_for_test();']),
2544 ]
2545
Saagar Sanghavifceeaae2020-08-12 16:40:362546 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242547 mock_input_api, MockOutputApi())
2548 self.assertEqual(1, len(results))
2549 self.assertEqual(4, len(results[0].items))
2550 self.assertTrue('foo.cc' in results[0].items[0])
2551 self.assertTrue('foo.mm' in results[0].items[1])
2552 self.assertTrue('foo.cxx' in results[0].items[2])
2553 self.assertTrue('foo.cpp' in results[0].items[3])
2554
2555 def testFalsePositives(self):
2556 mock_input_api = MockInputApi()
2557 mock_input_api.files = [
2558 MockFile('some/path/foo.h', ['foo_for_testing();']),
2559 MockFile('some/path/foo.mm', ['FooForTesting() {']),
2560 MockFile('some/path/foo.cc', ['::FooForTests();']),
2561 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
2562 ]
2563
Saagar Sanghavifceeaae2020-08-12 16:40:362564 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
Vaclav Brozekf01ed502018-03-16 19:38:242565 mock_input_api, MockOutputApi())
2566 self.assertEqual(0, len(results))
2567
2568
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272569class NoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:232570 def testTruePositives(self):
2571 mock_input_api = MockInputApi()
2572 mock_input_api.files = [
2573 MockFile('dir/java/src/foo.java', ['FooForTesting();']),
2574 MockFile('dir/java/src/bar.java', ['FooForTests(x);']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392575 MockFile('dir/java/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232576 MockFile('dir/java/src/mult.java', [
2577 'int x = SomethingLongHere()',
2578 ' * SomethingLongHereForTesting();'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392579 ])
Vaclav Brozek7dbc28c2018-03-27 08:35:232580 ]
2581
Saagar Sanghavifceeaae2020-08-12 16:40:362582 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232583 mock_input_api, MockOutputApi())
2584 self.assertEqual(1, len(results))
2585 self.assertEqual(4, len(results[0].items))
2586 self.assertTrue('foo.java' in results[0].items[0])
2587 self.assertTrue('bar.java' in results[0].items[1])
2588 self.assertTrue('baz.java' in results[0].items[2])
2589 self.assertTrue('mult.java' in results[0].items[3])
2590
2591 def testFalsePositives(self):
2592 mock_input_api = MockInputApi()
2593 mock_input_api.files = [
2594 MockFile('dir/java/src/foo.xml', ['FooForTesting();']),
2595 MockFile('dir/java/src/foo.java', ['FooForTests() {']),
2596 MockFile('dir/java/src/bar.java', ['// FooForTest();']),
2597 MockFile('dir/java/src/bar2.java', ['x = 1; // FooForTest();']),
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:392598 MockFile('dir/javatests/src/baz.java', ['FooForTest(', 'y', ');']),
2599 MockFile('dir/junit/src/baz.java', ['FooForTest(', 'y', ');']),
Vaclav Brozek7dbc28c2018-03-27 08:35:232600 MockFile('dir/junit/src/javadoc.java', [
2601 '/** Use FooForTest(); to obtain foo in tests.'
2602 ' */'
2603 ]),
2604 MockFile('dir/junit/src/javadoc2.java', [
2605 '/** ',
2606 ' * Use FooForTest(); to obtain foo in tests.'
2607 ' */'
2608 ]),
2609 ]
2610
Saagar Sanghavifceeaae2020-08-12 16:40:362611 results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
Vaclav Brozek7dbc28c2018-03-27 08:35:232612 mock_input_api, MockOutputApi())
2613 self.assertEqual(0, len(results))
2614
2615
Mohamed Heikald048240a2019-11-12 16:57:372616class NewImagesWarningTest(unittest.TestCase):
2617 def testTruePositives(self):
2618 mock_input_api = MockInputApi()
2619 mock_input_api.files = [
2620 MockFile('dir/android/res/drawable/foo.png', []),
2621 MockFile('dir/android/res/drawable-v21/bar.svg', []),
2622 MockFile('dir/android/res/mipmap-v21-en/baz.webp', []),
2623 MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png', []),
2624 ]
2625
2626 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2627 self.assertEqual(1, len(results))
2628 self.assertEqual(4, len(results[0].items))
2629 self.assertTrue('foo.png' in results[0].items[0].LocalPath())
2630 self.assertTrue('bar.svg' in results[0].items[1].LocalPath())
2631 self.assertTrue('baz.webp' in results[0].items[2].LocalPath())
2632 self.assertTrue('foobar.png' in results[0].items[3].LocalPath())
2633
2634 def testFalsePositives(self):
2635 mock_input_api = MockInputApi()
2636 mock_input_api.files = [
2637 MockFile('dir/pngs/README.md', []),
2638 MockFile('java/test/res/drawable/foo.png', []),
2639 MockFile('third_party/blink/foo.png', []),
2640 MockFile('dir/third_party/libpng/src/foo.cc', ['foobar']),
2641 MockFile('dir/resources.webp/.gitignore', ['foo.png']),
2642 ]
2643
2644 results = PRESUBMIT._CheckNewImagesWarning(mock_input_api, MockOutputApi())
2645 self.assertEqual(0, len(results))
2646
2647
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:272648class CheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:052649 def testTruePositivesNullptr(self):
2650 mock_input_api = MockInputApi()
2651 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162652 MockFile('dir/baz.cc', ['std::unique_ptr<T>()']),
2653 MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']),
Vaclav Brozek851d9602018-04-04 16:13:052654 ]
2655
Saagar Sanghavifceeaae2020-08-12 16:40:362656 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052657 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162658 self.assertTrue('nullptr' in results[0].message)
Vaclav Brozek851d9602018-04-04 16:13:052659 self.assertEqual(2, len(results[0].items))
2660 self.assertTrue('baz.cc' in results[0].items[0])
2661 self.assertTrue('baz-p.cc' in results[0].items[1])
2662
2663 def testTruePositivesConstructor(self):
Vaclav Brozek52e18bf2018-04-03 07:05:242664 mock_input_api = MockInputApi()
2665 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162666 MockFile('dir/foo.cc', ['return std::unique_ptr<T>(foo);']),
2667 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T>(foo)']),
2668 MockFile('dir/mult.cc', [
Vaclav Brozek95face62018-04-04 14:15:112669 'return',
2670 ' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
2671 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162672 MockFile('dir/mult2.cc', [
Vaclav Brozek95face62018-04-04 14:15:112673 'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
2674 ' std::unique_ptr<T>(foo);'
2675 ]),
Vaclav Brozekc2fecf42018-04-06 16:40:162676 MockFile('dir/mult3.cc', [
Vaclav Brozek95face62018-04-04 14:15:112677 'bar = std::unique_ptr<T>(',
2678 ' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
2679 ]),
Vaclav Brozekb7fadb692018-08-30 06:39:532680 MockFile('dir/multi_arg.cc', [
2681 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']),
Vaclav Brozek52e18bf2018-04-03 07:05:242682 ]
2683
Saagar Sanghavifceeaae2020-08-12 16:40:362684 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek851d9602018-04-04 16:13:052685 self.assertEqual(1, len(results))
Vaclav Brozekc2fecf42018-04-06 16:40:162686 self.assertTrue('std::make_unique' in results[0].message)
Vaclav Brozekb7fadb692018-08-30 06:39:532687 self.assertEqual(6, len(results[0].items))
Vaclav Brozek851d9602018-04-04 16:13:052688 self.assertTrue('foo.cc' in results[0].items[0])
2689 self.assertTrue('bar.mm' in results[0].items[1])
2690 self.assertTrue('mult.cc' in results[0].items[2])
2691 self.assertTrue('mult2.cc' in results[0].items[3])
2692 self.assertTrue('mult3.cc' in results[0].items[4])
Vaclav Brozekb7fadb692018-08-30 06:39:532693 self.assertTrue('multi_arg.cc' in results[0].items[5])
Vaclav Brozek52e18bf2018-04-03 07:05:242694
2695 def testFalsePositives(self):
2696 mock_input_api = MockInputApi()
2697 mock_input_api.files = [
Vaclav Brozekc2fecf42018-04-06 16:40:162698 MockFile('dir/foo.cc', ['return std::unique_ptr<T[]>(foo);']),
2699 MockFile('dir/bar.mm', ['bar = std::unique_ptr<T[]>(foo)']),
2700 MockFile('dir/file.cc', ['std::unique_ptr<T> p = Foo();']),
2701 MockFile('dir/baz.cc', [
Vaclav Brozek52e18bf2018-04-03 07:05:242702 'std::unique_ptr<T> result = std::make_unique<T>();'
2703 ]),
Vaclav Brozeka54c528b2018-04-06 19:23:552704 MockFile('dir/baz2.cc', [
2705 'std::unique_ptr<T> result = std::make_unique<T>('
2706 ]),
2707 MockFile('dir/nested.cc', ['set<std::unique_ptr<T>>();']),
2708 MockFile('dir/nested2.cc', ['map<U, std::unique_ptr<T>>();']),
Vaclav Brozekb7fadb692018-08-30 06:39:532709
2710 # Two-argument invocation of std::unique_ptr is exempt because there is
2711 # no equivalent using std::make_unique.
2712 MockFile('dir/multi_arg.cc', [
2713 'auto p = std::unique_ptr<T, D>(new T(), D());']),
Vaclav Brozek52e18bf2018-04-03 07:05:242714 ]
2715
Saagar Sanghavifceeaae2020-08-12 16:40:362716 results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi())
Vaclav Brozek52e18bf2018-04-03 07:05:242717 self.assertEqual(0, len(results))
2718
Danil Chapovalov3518f362018-08-11 16:13:432719class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
2720 def testBlocksDirectIncludes(self):
2721 mock_input_api = MockInputApi()
2722 mock_input_api.files = [
2723 MockFile('dir/foo_win.cc', ['#include "shlwapi.h"']),
2724 MockFile('dir/bar.h', ['#include <propvarutil.h>']),
2725 MockFile('dir/baz.h', ['#include <atlbase.h>']),
2726 MockFile('dir/jumbo.h', ['#include "sphelper.h"']),
2727 ]
2728 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2729 self.assertEquals(1, len(results))
2730 self.assertEquals(4, len(results[0].items))
2731 self.assertTrue('StrCat' in results[0].message)
2732 self.assertTrue('foo_win.cc' in results[0].items[0])
2733 self.assertTrue('bar.h' in results[0].items[1])
2734 self.assertTrue('baz.h' in results[0].items[2])
2735 self.assertTrue('jumbo.h' in results[0].items[3])
2736
2737 def testAllowsToIncludeWrapper(self):
2738 mock_input_api = MockInputApi()
2739 mock_input_api.files = [
2740 MockFile('dir/baz_win.cc', ['#include "base/win/shlwapi.h"']),
2741 MockFile('dir/baz-win.h', ['#include "base/win/atl.h"']),
2742 ]
2743 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2744 self.assertEquals(0, len(results))
2745
2746 def testAllowsToCreateWrapper(self):
2747 mock_input_api = MockInputApi()
2748 mock_input_api.files = [
2749 MockFile('base/win/shlwapi.h', [
2750 '#include <shlwapi.h>',
2751 '#include "base/win/windows_defines.inc"']),
2752 ]
2753 results = PRESUBMIT._CheckNoStrCatRedefines(mock_input_api, MockOutputApi())
2754 self.assertEquals(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:242755
Mustafa Emre Acer51f2f742020-03-09 19:41:122756
Rainhard Findlingfc31844c52020-05-15 09:58:262757class StringTest(unittest.TestCase):
2758 """Tests ICU syntax check and translation screenshots check."""
2759
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142760 # An empty grd file.
2761 OLD_GRD_CONTENTS = """<?xml version="1.0" encoding="UTF-8"?>
2762 <grit latest_public_release="1" current_release="1">
2763 <release seq="1">
2764 <messages></messages>
2765 </release>
2766 </grit>
2767 """.splitlines()
2768 # A grd file with a single message.
2769 NEW_GRD_CONTENTS1 = """<?xml version="1.0" encoding="UTF-8"?>
2770 <grit latest_public_release="1" current_release="1">
2771 <release seq="1">
2772 <messages>
2773 <message name="IDS_TEST1">
2774 Test string 1
2775 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482776 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE1"
2777 translateable="false">
2778 Non translateable message 1, should be ignored
2779 </message>
Mustafa Emre Acered1a48962020-06-30 19:15:392780 <message name="IDS_TEST_STRING_ACCESSIBILITY"
Mustafa Emre Acerd3ca8be2020-07-07 22:35:342781 is_accessibility_with_no_ui="true">
Mustafa Emre Acered1a48962020-06-30 19:15:392782 Accessibility label 1, should be ignored
2783 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142784 </messages>
2785 </release>
2786 </grit>
2787 """.splitlines()
2788 # A grd file with two messages.
2789 NEW_GRD_CONTENTS2 = """<?xml version="1.0" encoding="UTF-8"?>
2790 <grit latest_public_release="1" current_release="1">
2791 <release seq="1">
2792 <messages>
2793 <message name="IDS_TEST1">
2794 Test string 1
2795 </message>
2796 <message name="IDS_TEST2">
2797 Test string 2
2798 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:482799 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE2"
2800 translateable="false">
2801 Non translateable message 2, should be ignored
2802 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142803 </messages>
2804 </release>
2805 </grit>
2806 """.splitlines()
Rainhard Findlingfc31844c52020-05-15 09:58:262807 # A grd file with one ICU syntax message without syntax errors.
2808 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1 = """<?xml version="1.0" encoding="UTF-8"?>
2809 <grit latest_public_release="1" current_release="1">
2810 <release seq="1">
2811 <messages>
2812 <message name="IDS_TEST1">
2813 {NUM, plural,
2814 =1 {Test text for numeric one}
2815 other {Test text for plural with {NUM} as number}}
2816 </message>
2817 </messages>
2818 </release>
2819 </grit>
2820 """.splitlines()
2821 # A grd file with one ICU syntax message without syntax errors.
2822 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2 = """<?xml version="1.0" encoding="UTF-8"?>
2823 <grit latest_public_release="1" current_release="1">
2824 <release seq="1">
2825 <messages>
2826 <message name="IDS_TEST1">
2827 {NUM, plural,
2828 =1 {Different test text for numeric one}
2829 other {Different test text for plural with {NUM} as number}}
2830 </message>
2831 </messages>
2832 </release>
2833 </grit>
2834 """.splitlines()
2835 # A grd file with one ICU syntax message with syntax errors (misses a comma).
2836 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
2837 <grit latest_public_release="1" current_release="1">
2838 <release seq="1">
2839 <messages>
2840 <message name="IDS_TEST1">
2841 {NUM, plural
2842 =1 {Test text for numeric one}
2843 other {Test text for plural with {NUM} as number}}
2844 </message>
2845 </messages>
2846 </release>
2847 </grit>
2848 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142849
meacerff8a9b62019-12-10 19:43:582850 OLD_GRDP_CONTENTS = (
2851 '<?xml version="1.0" encoding="utf-8"?>',
2852 '<grit-part>',
2853 '</grit-part>'
2854 )
2855
2856 NEW_GRDP_CONTENTS1 = (
2857 '<?xml version="1.0" encoding="utf-8"?>',
2858 '<grit-part>',
2859 '<message name="IDS_PART_TEST1">',
2860 'Part string 1',
2861 '</message>',
2862 '</grit-part>')
2863
2864 NEW_GRDP_CONTENTS2 = (
2865 '<?xml version="1.0" encoding="utf-8"?>',
2866 '<grit-part>',
2867 '<message name="IDS_PART_TEST1">',
2868 'Part string 1',
2869 '</message>',
2870 '<message name="IDS_PART_TEST2">',
2871 'Part string 2',
2872 '</message>',
2873 '</grit-part>')
2874
Rainhard Findlingd8d04372020-08-13 13:30:092875 NEW_GRDP_CONTENTS3 = (
2876 '<?xml version="1.0" encoding="utf-8"?>',
2877 '<grit-part>',
2878 '<message name="IDS_PART_TEST1" desc="Description with typo.">',
2879 'Part string 1',
2880 '</message>',
2881 '</grit-part>')
2882
2883 NEW_GRDP_CONTENTS4 = (
2884 '<?xml version="1.0" encoding="utf-8"?>',
2885 '<grit-part>',
2886 '<message name="IDS_PART_TEST1" desc="Description with typo fixed.">',
2887 'Part string 1',
2888 '</message>',
2889 '</grit-part>')
2890
Rainhard Findling1a3e71e2020-09-21 07:33:352891 NEW_GRDP_CONTENTS5 = (
2892 '<?xml version="1.0" encoding="utf-8"?>',
2893 '<grit-part>',
2894 '<message name="IDS_PART_TEST1" meaning="Meaning with typo.">',
2895 'Part string 1',
2896 '</message>',
2897 '</grit-part>')
2898
2899 NEW_GRDP_CONTENTS6 = (
2900 '<?xml version="1.0" encoding="utf-8"?>',
2901 '<grit-part>',
2902 '<message name="IDS_PART_TEST1" meaning="Meaning with typo fixed.">',
2903 'Part string 1',
2904 '</message>',
2905 '</grit-part>')
2906
Rainhard Findlingfc31844c52020-05-15 09:58:262907 # A grdp file with one ICU syntax message without syntax errors.
2908 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = (
2909 '<?xml version="1.0" encoding="utf-8"?>',
2910 '<grit-part>',
2911 '<message name="IDS_PART_TEST1">',
2912 '{NUM, plural,',
2913 '=1 {Test text for numeric one}',
2914 'other {Test text for plural with {NUM} as number}}',
2915 '</message>',
2916 '</grit-part>')
2917 # A grdp file with one ICU syntax message without syntax errors.
2918 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2 = (
2919 '<?xml version="1.0" encoding="utf-8"?>',
2920 '<grit-part>',
2921 '<message name="IDS_PART_TEST1">',
2922 '{NUM, plural,',
2923 '=1 {Different test text for numeric one}',
2924 'other {Different test text for plural with {NUM} as number}}',
2925 '</message>',
2926 '</grit-part>')
2927
2928 # A grdp file with one ICU syntax message with syntax errors (superfluent
2929 # whitespace).
2930 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR = (
2931 '<?xml version="1.0" encoding="utf-8"?>',
2932 '<grit-part>',
2933 '<message name="IDS_PART_TEST1">',
2934 '{NUM, plural,',
2935 '= 1 {Test text for numeric one}',
2936 'other {Test text for plural with {NUM} as number}}',
2937 '</message>',
2938 '</grit-part>')
2939
Mustafa Emre Acerc8a012d2018-07-31 00:00:392940 DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
2941 'changelist. Run '
2942 'tools/translate/upload_screenshots.py to '
2943 'upload them instead:')
2944 GENERATE_SIGNATURES_MESSAGE = ('You are adding or modifying UI strings.\n'
2945 'To ensure the best translations, take '
2946 'screenshots of the relevant UI '
2947 '(https://g.co/chrome/translation) and add '
2948 'these files to your changelist:')
2949 REMOVE_SIGNATURES_MESSAGE = ('You removed strings associated with these '
2950 'files. Remove:')
Rainhard Findlingfc31844c52020-05-15 09:58:262951 ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
2952 'strings (problems or feedback? Contact '
2953 '[email protected]):')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142954
2955 def makeInputApi(self, files):
2956 input_api = MockInputApi()
2957 input_api.files = files
meacere7be7532019-10-02 17:41:032958 # Override os_path.exists because the presubmit uses the actual
2959 # os.path.exists.
2960 input_api.CreateMockFileInPath(
2961 [x.LocalPath() for x in input_api.AffectedFiles(include_deletes=True)])
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142962 return input_api
2963
meacerff8a9b62019-12-10 19:43:582964 """ CL modified and added messages, but didn't add any screenshots."""
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142965 def testNoScreenshots(self):
meacerff8a9b62019-12-10 19:43:582966 # No new strings (file contents same). Should not warn.
2967 input_api = self.makeInputApi([
2968 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
2969 self.NEW_GRD_CONTENTS1, action='M'),
2970 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1,
2971 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362972 warnings = PRESUBMIT.CheckStrings(input_api,
meacerff8a9b62019-12-10 19:43:582973 MockOutputApi())
2974 self.assertEqual(0, len(warnings))
2975
2976 # Add two new strings. Should have two warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142977 input_api = self.makeInputApi([
2978 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582979 self.NEW_GRD_CONTENTS1, action='M'),
2980 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2981 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362982 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:142983 MockOutputApi())
2984 self.assertEqual(1, len(warnings))
2985 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerc6ed2682020-07-07 07:24:002986 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerea3e57a2018-12-17 23:51:012987 self.assertEqual([
meacerff8a9b62019-12-10 19:43:582988 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
2989 os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
2990 warnings[0].items)
Mustafa Emre Acer36eaad52019-11-12 23:03:342991
meacerff8a9b62019-12-10 19:43:582992 # Add four new strings. Should have four warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:212993 input_api = self.makeInputApi([
2994 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
meacerff8a9b62019-12-10 19:43:582995 self.OLD_GRD_CONTENTS, action='M'),
2996 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2,
2997 self.OLD_GRDP_CONTENTS, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:362998 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:212999 MockOutputApi())
3000 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003001 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213002 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583003 self.assertEqual([
3004 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3005 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3006 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3007 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3008 ], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213009
Rainhard Findlingd8d04372020-08-13 13:30:093010 def testModifiedMessageDescription(self):
3011 # CL modified a message description for a message that does not yet have a
Rainhard Findling1a3e71e2020-09-21 07:33:353012 # screenshot. Should not warn.
Rainhard Findlingd8d04372020-08-13 13:30:093013 input_api = self.makeInputApi([
3014 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
3015 self.NEW_GRDP_CONTENTS4, action='M')])
3016 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findling1a3e71e2020-09-21 07:33:353017 self.assertEqual(0, len(warnings))
Rainhard Findlingd8d04372020-08-13 13:30:093018
3019 # CL modified a message description for a message that already has a
3020 # screenshot. Should not warn.
3021 input_api = self.makeInputApi([
3022 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
3023 self.NEW_GRDP_CONTENTS4, action='M'),
3024 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3025 'binary', action='A')])
3026 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3027 self.assertEqual(0, len(warnings))
3028
Rainhard Findling1a3e71e2020-09-21 07:33:353029 def testModifiedMessageMeaning(self):
3030 # CL modified a message meaning for a message that does not yet have a
3031 # screenshot. Should warn.
3032 input_api = self.makeInputApi([
3033 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3034 self.NEW_GRDP_CONTENTS6, action='M')])
3035 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3036 self.assertEqual(1, len(warnings))
3037
3038 # CL modified a message meaning for a message that already has a
3039 # screenshot. Should not warn.
3040 input_api = self.makeInputApi([
3041 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
3042 self.NEW_GRDP_CONTENTS6, action='M'),
3043 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3044 'binary', action='A')])
3045 warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
3046 self.assertEqual(0, len(warnings))
3047
meacerff8a9b62019-12-10 19:43:583048 def testPngAddedSha1NotAdded(self):
3049 # CL added one new message in a grd file and added the png file associated
3050 # with it, but did not add the corresponding sha1 file. This should warn
3051 # twice:
3052 # - Once for the added png file (because we don't want developers to upload
3053 # actual images)
3054 # - Once for the missing .sha1 file
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143055 input_api = self.makeInputApi([
Mustafa Emre Acerea3e57a2018-12-17 23:51:013056 MockAffectedFile(
3057 'test.grd',
3058 self.NEW_GRD_CONTENTS1,
3059 self.OLD_GRD_CONTENTS,
3060 action='M'),
3061 MockAffectedFile(
3062 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
3063 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363064 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143065 MockOutputApi())
3066 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003067 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143068 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013069 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
3070 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003071 self.assertEqual('error', warnings[1].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143072 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013073 self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3074 warnings[1].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143075
meacerff8a9b62019-12-10 19:43:583076 # CL added two messages (one in grd, one in grdp) and added the png files
3077 # associated with the messages, but did not add the corresponding sha1
3078 # files. This should warn twice:
3079 # - Once for the added png files (because we don't want developers to upload
3080 # actual images)
3081 # - Once for the missing .sha1 files
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143082 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583083 # Modified files:
Mustafa Emre Acer36eaad52019-11-12 23:03:343084 MockAffectedFile(
3085 'test.grd',
meacerff8a9b62019-12-10 19:43:583086 self.NEW_GRD_CONTENTS1,
Mustafa Emre Acer36eaad52019-11-12 23:03:343087 self.OLD_GRD_CONTENTS,
meacer2308d0742019-11-12 18:15:423088 action='M'),
Mustafa Emre Acer12e7fee2019-11-18 18:49:553089 MockAffectedFile(
meacerff8a9b62019-12-10 19:43:583090 'part.grdp',
3091 self.NEW_GRDP_CONTENTS1,
3092 self.OLD_GRDP_CONTENTS,
3093 action='M'),
3094 # Added files:
3095 MockAffectedFile(
3096 os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A'),
3097 MockAffectedFile(
3098 os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary',
3099 action='A')
Mustafa Emre Acerad8fb082019-11-19 04:24:213100 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363101 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acerad8fb082019-11-19 04:24:213102 MockOutputApi())
3103 self.assertEqual(2, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003104 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213105 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583106 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png'),
3107 os.path.join('test_grd', 'IDS_TEST1.png')],
Mustafa Emre Acerad8fb082019-11-19 04:24:213108 warnings[0].items)
Mustafa Emre Acerc6ed2682020-07-07 07:24:003109 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acerad8fb082019-11-19 04:24:213110 self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
meacerff8a9b62019-12-10 19:43:583111 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3112 os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
3113 warnings[1].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:213114
3115 def testScreenshotsWithSha1(self):
meacerff8a9b62019-12-10 19:43:583116 # CL added four messages (two each in a grd and grdp) and their
3117 # corresponding .sha1 files. No warnings.
Mustafa Emre Acerad8fb082019-11-19 04:24:213118 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583119 # Modified files:
Mustafa Emre Acerad8fb082019-11-19 04:24:213120 MockAffectedFile(
3121 'test.grd',
3122 self.NEW_GRD_CONTENTS2,
3123 self.OLD_GRD_CONTENTS,
Mustafa Emre Acer12e7fee2019-11-18 18:49:553124 action='M'),
meacerff8a9b62019-12-10 19:43:583125 MockAffectedFile(
3126 'part.grdp',
3127 self.NEW_GRDP_CONTENTS2,
3128 self.OLD_GRDP_CONTENTS,
3129 action='M'),
3130 # Added files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013131 MockFile(
3132 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3133 'binary',
3134 action='A'),
3135 MockFile(
3136 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3137 'binary',
meacerff8a9b62019-12-10 19:43:583138 action='A'),
3139 MockFile(
3140 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3141 'binary',
3142 action='A'),
3143 MockFile(
3144 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3145 'binary',
3146 action='A'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013147 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363148 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143149 MockOutputApi())
3150 self.assertEqual([], warnings)
3151
3152 def testScreenshotsRemovedWithSha1(self):
meacerff8a9b62019-12-10 19:43:583153 # Replace new contents with old contents in grd and grp files, removing
3154 # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3155 # Should warn to remove the sha1 files associated with these strings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143156 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583157 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013158 MockAffectedFile(
3159 'test.grd',
meacerff8a9b62019-12-10 19:43:583160 self.OLD_GRD_CONTENTS, # new_contents
3161 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013162 action='M'),
meacerff8a9b62019-12-10 19:43:583163 MockAffectedFile(
3164 'part.grdp',
3165 self.OLD_GRDP_CONTENTS, # new_contents
3166 self.NEW_GRDP_CONTENTS2, # old_contents
3167 action='M'),
3168 # Unmodified files:
3169 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
3170 MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', ''),
3171 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3172 'binary', ''),
3173 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3174 'binary', '')
Mustafa Emre Acerea3e57a2018-12-17 23:51:013175 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363176 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143177 MockOutputApi())
3178 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003179 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143180 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
Mustafa Emre Acerea3e57a2018-12-17 23:51:013181 self.assertEqual([
meacerff8a9b62019-12-10 19:43:583182 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3183 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:013184 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3185 os.path.join('test_grd', 'IDS_TEST2.png.sha1')
3186 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143187
meacerff8a9b62019-12-10 19:43:583188 # Same as above, but this time one of the .sha1 files is also removed.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143189 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583190 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013191 MockAffectedFile(
3192 'test.grd',
meacerff8a9b62019-12-10 19:43:583193 self.OLD_GRD_CONTENTS, # new_contents
3194 self.NEW_GRD_CONTENTS2, # old_contents
Mustafa Emre Acerea3e57a2018-12-17 23:51:013195 action='M'),
meacerff8a9b62019-12-10 19:43:583196 MockAffectedFile(
3197 'part.grdp',
3198 self.OLD_GRDP_CONTENTS, # new_contents
3199 self.NEW_GRDP_CONTENTS2, # old_contents
3200 action='M'),
3201 # Unmodified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013202 MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
meacerff8a9b62019-12-10 19:43:583203 MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3204 'binary', ''),
3205 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013206 MockAffectedFile(
3207 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3208 '',
3209 'old_contents',
meacerff8a9b62019-12-10 19:43:583210 action='D'),
3211 MockAffectedFile(
3212 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3213 '',
3214 'old_contents',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013215 action='D')
3216 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363217 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143218 MockOutputApi())
3219 self.assertEqual(1, len(warnings))
Mustafa Emre Acerc6ed2682020-07-07 07:24:003220 self.assertEqual('error', warnings[0].type)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143221 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
meacerff8a9b62019-12-10 19:43:583222 self.assertEqual([os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3223 os.path.join('test_grd', 'IDS_TEST1.png.sha1')
3224 ], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143225
meacerff8a9b62019-12-10 19:43:583226 # Remove all sha1 files. There should be no warnings.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143227 input_api = self.makeInputApi([
meacerff8a9b62019-12-10 19:43:583228 # Modified files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013229 MockAffectedFile(
3230 'test.grd',
3231 self.OLD_GRD_CONTENTS,
3232 self.NEW_GRD_CONTENTS2,
3233 action='M'),
meacerff8a9b62019-12-10 19:43:583234 MockAffectedFile(
3235 'part.grdp',
3236 self.OLD_GRDP_CONTENTS,
3237 self.NEW_GRDP_CONTENTS2,
3238 action='M'),
3239 # Deleted files:
Mustafa Emre Acerea3e57a2018-12-17 23:51:013240 MockFile(
3241 os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
3242 'binary',
3243 action='D'),
3244 MockFile(
3245 os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
3246 'binary',
meacerff8a9b62019-12-10 19:43:583247 action='D'),
3248 MockFile(
3249 os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
3250 'binary',
3251 action='D'),
3252 MockFile(
3253 os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
3254 'binary',
Mustafa Emre Acerea3e57a2018-12-17 23:51:013255 action='D')
3256 ])
Saagar Sanghavifceeaae2020-08-12 16:40:363257 warnings = PRESUBMIT.CheckStrings(input_api,
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143258 MockOutputApi())
3259 self.assertEqual([], warnings)
3260
Rainhard Findlingfc31844c52020-05-15 09:58:263261 def testIcuSyntax(self):
3262 # Add valid ICU syntax string. Should not raise an error.
3263 input_api = self.makeInputApi([
3264 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3265 self.NEW_GRD_CONTENTS1, action='M'),
3266 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3267 self.NEW_GRDP_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363268 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263269 # We expect no ICU syntax errors.
3270 icu_errors = [e for e in results
3271 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3272 self.assertEqual(0, len(icu_errors))
3273
3274 # Valid changes in ICU syntax. Should not raise an error.
3275 input_api = self.makeInputApi([
3276 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
3277 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3278 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
3279 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363280 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263281 # We expect no ICU syntax errors.
3282 icu_errors = [e for e in results
3283 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3284 self.assertEqual(0, len(icu_errors))
3285
3286 # Add invalid ICU syntax strings. Should raise two errors.
3287 input_api = self.makeInputApi([
3288 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3289 self.NEW_GRD_CONTENTS1, action='M'),
3290 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3291 self.NEW_GRD_CONTENTS1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363292 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263293 # We expect 2 ICU syntax errors.
3294 icu_errors = [e for e in results
3295 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3296 self.assertEqual(1, len(icu_errors))
3297 self.assertEqual([
3298 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3299 'ICU syntax.',
3300 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3301 ], icu_errors[0].items)
3302
3303 # Change two strings to have ICU syntax errors. Should raise two errors.
3304 input_api = self.makeInputApi([
3305 MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
3306 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'),
3307 MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
3308 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')])
Saagar Sanghavifceeaae2020-08-12 16:40:363309 results = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
Rainhard Findlingfc31844c52020-05-15 09:58:263310 # We expect 2 ICU syntax errors.
3311 icu_errors = [e for e in results
3312 if e.message == self.ICU_SYNTAX_ERROR_MESSAGE]
3313 self.assertEqual(1, len(icu_errors))
3314 self.assertEqual([
3315 'IDS_TEST1: This message looks like an ICU plural, but does not follow '
3316 'ICU syntax.',
3317 'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
3318 ], icu_errors[0].items)
3319
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143320
Mustafa Emre Acer51f2f742020-03-09 19:41:123321class TranslationExpectationsTest(unittest.TestCase):
3322 ERROR_MESSAGE_FORMAT = (
3323 "Failed to get a list of translatable grd files. "
3324 "This happens when:\n"
3325 " - One of the modified grd or grdp files cannot be parsed or\n"
3326 " - %s is not updated.\n"
3327 "Stack:\n"
3328 )
3329 REPO_ROOT = os.path.join('tools', 'translation', 'testdata')
3330 # This lists all .grd files under REPO_ROOT.
3331 EXPECTATIONS = os.path.join(REPO_ROOT,
3332 "translation_expectations.pyl")
3333 # This lists all .grd files under REPO_ROOT except unlisted.grd.
3334 EXPECTATIONS_WITHOUT_UNLISTED_FILE = os.path.join(
3335 REPO_ROOT, "translation_expectations_without_unlisted_file.pyl")
3336
3337 # Tests that the presubmit doesn't return when no grd or grdp files are
3338 # modified.
3339 def testExpectationsNoModifiedGrd(self):
3340 input_api = MockInputApi()
3341 input_api.files = [
3342 MockAffectedFile('not_used.txt', 'not used', 'not used', action='M')
3343 ]
3344 # Fake list of all grd files in the repo. This list is missing all grd/grdps
3345 # under tools/translation/testdata. This is OK because the presubmit won't
3346 # run in the first place since there are no modified grd/grps in input_api.
3347 grd_files = ['doesnt_exist_doesnt_matter.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363348 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123349 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3350 grd_files)
3351 self.assertEqual(0, len(warnings))
3352
3353
3354 # Tests that the list of files passed to the presubmit matches the list of
3355 # files in the expectations.
3356 def testExpectationsSuccess(self):
3357 # Mock input file list needs a grd or grdp file in order to run the
3358 # presubmit. The file itself doesn't matter.
3359 input_api = MockInputApi()
3360 input_api.files = [
3361 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3362 ]
3363 # List of all grd files in the repo.
3364 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3365 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363366 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123367 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3368 grd_files)
3369 self.assertEqual(0, len(warnings))
3370
3371 # Tests that the presubmit warns when a file is listed in expectations, but
3372 # does not actually exist.
3373 def testExpectationsMissingFile(self):
3374 # Mock input file list needs a grd or grdp file in order to run the
3375 # presubmit.
3376 input_api = MockInputApi()
3377 input_api.files = [
3378 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3379 ]
3380 # unlisted.grd is listed under tools/translation/testdata but is not
3381 # included in translation expectations.
3382 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363383 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123384 input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
3385 grd_files)
3386 self.assertEqual(1, len(warnings))
3387 self.assertTrue(warnings[0].message.startswith(
3388 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS))
3389 self.assertTrue(
3390 ("test.grd is listed in the translation expectations, "
3391 "but this grd file does not exist")
3392 in warnings[0].message)
3393
3394 # Tests that the presubmit warns when a file is not listed in expectations but
3395 # does actually exist.
3396 def testExpectationsUnlistedFile(self):
3397 # Mock input file list needs a grd or grdp file in order to run the
3398 # presubmit.
3399 input_api = MockInputApi()
3400 input_api.files = [
3401 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3402 ]
3403 # unlisted.grd is listed under tools/translation/testdata but is not
3404 # included in translation expectations.
3405 grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd',
3406 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363407 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123408 input_api, MockOutputApi(), self.REPO_ROOT,
3409 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3410 self.assertEqual(1, len(warnings))
3411 self.assertTrue(warnings[0].message.startswith(
3412 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3413 self.assertTrue(
3414 ("unlisted.grd appears to be translatable "
3415 "(because it contains <file> or <message> elements), "
3416 "but is not listed in the translation expectations.")
3417 in warnings[0].message)
3418
3419 # Tests that the presubmit warns twice:
3420 # - for a non-existing file listed in expectations
3421 # - for an existing file not listed in expectations
3422 def testMultipleWarnings(self):
3423 # Mock input file list needs a grd or grdp file in order to run the
3424 # presubmit.
3425 input_api = MockInputApi()
3426 input_api.files = [
3427 MockAffectedFile('dummy.grd', 'not used', 'not used', action='M')
3428 ]
3429 # unlisted.grd is listed under tools/translation/testdata but is not
3430 # included in translation expectations.
3431 # test.grd is not listed under tools/translation/testdata but is included
3432 # in translation expectations.
3433 grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd']
Saagar Sanghavifceeaae2020-08-12 16:40:363434 warnings = PRESUBMIT.CheckTranslationExpectations(
Mustafa Emre Acer51f2f742020-03-09 19:41:123435 input_api, MockOutputApi(), self.REPO_ROOT,
3436 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
3437 self.assertEqual(1, len(warnings))
3438 self.assertTrue(warnings[0].message.startswith(
3439 self.ERROR_MESSAGE_FORMAT % self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
3440 self.assertTrue(
3441 ("unlisted.grd appears to be translatable "
3442 "(because it contains <file> or <message> elements), "
3443 "but is not listed in the translation expectations.")
3444 in warnings[0].message)
3445 self.assertTrue(
3446 ("test.grd is listed in the translation expectations, "
3447 "but this grd file does not exist")
3448 in warnings[0].message)
3449
3450
Dominic Battre033531052018-09-24 15:45:343451class DISABLETypoInTest(unittest.TestCase):
3452
3453 def testPositive(self):
3454 # Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
3455 # where the desire is to disable a test.
3456 tests = [
3457 # Disabled on one platform:
3458 '#if defined(OS_WIN)\n'
3459 '#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
3460 '#else\n'
3461 '#define MAYBE_FoobarTest FoobarTest\n'
3462 '#endif\n',
3463 # Disabled on one platform spread cross lines:
3464 '#if defined(OS_WIN)\n'
3465 '#define MAYBE_FoobarTest \\\n'
3466 ' DISABLE_FoobarTest\n'
3467 '#else\n'
3468 '#define MAYBE_FoobarTest FoobarTest\n'
3469 '#endif\n',
3470 # Disabled on all platforms:
3471 ' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
3472 # Disabled on all platforms but multiple lines
3473 ' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
3474 ]
3475
3476 for test in tests:
3477 mock_input_api = MockInputApi()
3478 mock_input_api.files = [
3479 MockFile('some/path/foo_unittest.cc', test.splitlines()),
3480 ]
3481
Saagar Sanghavifceeaae2020-08-12 16:40:363482 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343483 MockOutputApi())
3484 self.assertEqual(
3485 1,
3486 len(results),
3487 msg=('expected len(results) == 1 but got %d in test: %s' %
3488 (len(results), test)))
3489 self.assertTrue(
3490 'foo_unittest.cc' in results[0].message,
3491 msg=('expected foo_unittest.cc in message but got %s in test %s' %
3492 (results[0].message, test)))
3493
3494 def testIngoreNotTestFiles(self):
3495 mock_input_api = MockInputApi()
3496 mock_input_api.files = [
3497 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'),
3498 ]
3499
Saagar Sanghavifceeaae2020-08-12 16:40:363500 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Dominic Battre033531052018-09-24 15:45:343501 MockOutputApi())
3502 self.assertEqual(0, len(results))
3503
Katie Df13948e2018-09-25 07:33:443504 def testIngoreDeletedFiles(self):
3505 mock_input_api = MockInputApi()
3506 mock_input_api.files = [
3507 MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'),
3508 ]
3509
Saagar Sanghavifceeaae2020-08-12 16:40:363510 results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
Katie Df13948e2018-09-25 07:33:443511 MockOutputApi())
3512 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:343513
Dirk Pranke3c18a382019-03-15 01:07:513514
3515class BuildtoolsRevisionsAreInSyncTest(unittest.TestCase):
3516 # TODO(crbug.com/941824): We need to make sure the entries in
3517 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3518 # so that users of //buildtools in other projects get the same tooling
3519 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3520 # support to gclient, we can eliminate the duplication and delete
3521 # these tests for the corresponding presubmit check.
3522
3523 def _check(self, files):
3524 mock_input_api = MockInputApi()
3525 mock_input_api.files = []
3526 for fname, contents in files.items():
3527 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363528 return PRESUBMIT.CheckBuildtoolsRevisionsAreInSync(mock_input_api,
Dirk Pranke3c18a382019-03-15 01:07:513529 MockOutputApi())
3530
3531 def testOneFileChangedButNotTheOther(self):
3532 results = self._check({
3533 "DEPS": "'libunwind_revision': 'onerev'",
3534 })
3535 self.assertNotEqual(results, [])
3536
3537 def testNeitherFileChanged(self):
3538 results = self._check({
3539 "OWNERS": "[email protected]",
3540 })
3541 self.assertEqual(results, [])
3542
3543 def testBothFilesChangedAndMatch(self):
3544 results = self._check({
3545 "DEPS": "'libunwind_revision': 'onerev'",
3546 "buildtools/DEPS": "'libunwind_revision': 'onerev'",
3547 })
3548 self.assertEqual(results, [])
3549
3550 def testBothFilesWereChangedAndDontMatch(self):
3551 results = self._check({
3552 "DEPS": "'libunwind_revision': 'onerev'",
3553 "buildtools/DEPS": "'libunwind_revision': 'anotherrev'",
3554 })
3555 self.assertNotEqual(results, [])
3556
3557
Max Morozb47503b2019-08-08 21:03:273558class CheckFuzzTargetsTest(unittest.TestCase):
3559
3560 def _check(self, files):
3561 mock_input_api = MockInputApi()
3562 mock_input_api.files = []
3563 for fname, contents in files.items():
3564 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
Saagar Sanghavifceeaae2020-08-12 16:40:363565 return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api, MockOutputApi())
Max Morozb47503b2019-08-08 21:03:273566
3567 def testLibFuzzerSourcesIgnored(self):
3568 results = self._check({
3569 "third_party/lib/Fuzzer/FuzzerDriver.cpp": "LLVMFuzzerInitialize",
3570 })
3571 self.assertEqual(results, [])
3572
3573 def testNonCodeFilesIgnored(self):
3574 results = self._check({
3575 "README.md": "LLVMFuzzerInitialize",
3576 })
3577 self.assertEqual(results, [])
3578
3579 def testNoErrorHeaderPresent(self):
3580 results = self._check({
3581 "fuzzer.cc": (
3582 "#include \"testing/libfuzzer/libfuzzer_exports.h\"\n" +
3583 "LLVMFuzzerInitialize"
3584 )
3585 })
3586 self.assertEqual(results, [])
3587
3588 def testErrorMissingHeader(self):
3589 results = self._check({
3590 "fuzzer.cc": "LLVMFuzzerInitialize"
3591 })
3592 self.assertEqual(len(results), 1)
3593 self.assertEqual(results[0].items, ['fuzzer.cc'])
3594
3595
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263596class SetNoParentTest(unittest.TestCase):
3597 def testSetNoParentMissing(self):
3598 mock_input_api = MockInputApi()
3599 mock_input_api.files = [
3600 MockAffectedFile('goat/OWNERS',
3601 [
3602 'set noparent',
3603 '[email protected]',
3604 'per-file *.json=set noparent',
3605 'per-file *[email protected]',
3606 ])
3607 ]
3608 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363609 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263610 self.assertEqual(1, len(errors))
3611 self.assertTrue('goat/OWNERS:1' in errors[0].long_text)
3612 self.assertTrue('goat/OWNERS:3' in errors[0].long_text)
3613
3614
3615 def testSetNoParentWithCorrectRule(self):
3616 mock_input_api = MockInputApi()
3617 mock_input_api.files = [
3618 MockAffectedFile('goat/OWNERS',
3619 [
3620 'set noparent',
3621 'file://ipc/SECURITY_OWNERS',
3622 'per-file *.json=set noparent',
3623 'per-file *.json=file://ipc/SECURITY_OWNERS',
3624 ])
3625 ]
3626 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363627 errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263628 self.assertEqual([], errors)
3629
3630
Ken Rockotc31f4832020-05-29 18:58:513631class MojomStabilityCheckTest(unittest.TestCase):
3632 def runTestWithAffectedFiles(self, affected_files):
3633 mock_input_api = MockInputApi()
3634 mock_input_api.files = affected_files
3635 mock_output_api = MockOutputApi()
Saagar Sanghavifceeaae2020-08-12 16:40:363636 return PRESUBMIT.CheckStableMojomChanges(
Ken Rockotc31f4832020-05-29 18:58:513637 mock_input_api, mock_output_api)
3638
3639 def testSafeChangePasses(self):
3640 errors = self.runTestWithAffectedFiles([
3641 MockAffectedFile('foo/foo.mojom',
3642 ['[Stable] struct S { [MinVersion=1] int32 x; };'],
3643 old_contents=['[Stable] struct S {};'])
3644 ])
3645 self.assertEqual([], errors)
3646
3647 def testBadChangeFails(self):
3648 errors = self.runTestWithAffectedFiles([
3649 MockAffectedFile('foo/foo.mojom',
3650 ['[Stable] struct S { int32 x; };'],
3651 old_contents=['[Stable] struct S {};'])
3652 ])
3653 self.assertEqual(1, len(errors))
3654 self.assertTrue('not backward-compatible' in errors[0].message)
3655
Ken Rockotad7901f942020-06-04 20:17:093656 def testDeletedFile(self):
3657 """Regression test for https://crbug.com/1091407."""
3658 errors = self.runTestWithAffectedFiles([
3659 MockAffectedFile('a.mojom', [], old_contents=['struct S {};'],
3660 action='D'),
3661 MockAffectedFile('b.mojom',
3662 ['struct S {}; struct T { S s; };'],
3663 old_contents=['import "a.mojom"; struct T { S s; };'])
3664 ])
3665 self.assertEqual([], errors)
3666
Ken Rockotc31f4832020-05-29 18:58:513667
[email protected]2299dcf2012-11-15 19:56:243668if __name__ == '__main__':
3669 unittest.main()