blob: 7b8a5557e5249abe9a403f7eb7409558e905b26d [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]2299dcf2012-11-15 19:56:247import re
[email protected]99171a92014-06-03 08:44:478import subprocess
[email protected]2299dcf2012-11-15 19:56:249import unittest
10
11import PRESUBMIT
glidere61efad2015-02-18 17:39:4312from PRESUBMIT_test_mocks import MockChange, MockFile, MockAffectedFile
gayane3dff8c22014-12-04 17:09:5113from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi
[email protected]2299dcf2012-11-15 19:56:2414
[email protected]99171a92014-06-03 08:44:4715_TEST_DATA_DIR = 'base/test/data/presubmit'
16
[email protected]b00342e7f2013-03-26 16:21:5417class VersionControlConflictsTest(unittest.TestCase):
[email protected]70ca77752012-11-20 03:45:0318 def testTypicalConflict(self):
19 lines = ['<<<<<<< HEAD',
20 ' base::ScopedTempDir temp_dir_;',
21 '=======',
22 ' ScopedTempDir temp_dir_;',
23 '>>>>>>> master']
24 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
25 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
26 self.assertEqual(3, len(errors))
27 self.assertTrue('1' in errors[0])
28 self.assertTrue('3' in errors[1])
29 self.assertTrue('5' in errors[2])
30
dbeam95c35a2f2015-06-02 01:40:2331 def testIgnoresReadmes(self):
32 lines = ['A First Level Header',
33 '====================',
34 '',
35 'A Second Level Header',
36 '---------------------']
37 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
38 MockInputApi(), MockFile('some/polymer/README.md', lines))
39 self.assertEqual(0, len(errors))
40
mcasasb7440c282015-02-04 14:52:1941class UmaHistogramChangeMatchedOrNotTest(unittest.TestCase):
42 def testTypicalCorrectlyMatchedChange(self):
43 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:4744 diff_java = [
45 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
mcasasb7440c282015-02-04 14:52:1946 diff_xml = ['<histogram name="Bla.Foo.Dummy"> </histogram>']
47 mock_input_api = MockInputApi()
48 mock_input_api.files = [
49 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:4750 MockFile('some/path/foo.java', diff_java),
mcasasb7440c282015-02-04 14:52:1951 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
52 ]
53 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
54 MockOutputApi())
55 self.assertEqual(0, len(warnings))
56
57 def testTypicalNotMatchedChange(self):
58 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:4759 diff_java = [
60 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
mcasasb7440c282015-02-04 14:52:1961 mock_input_api = MockInputApi()
Vaclav Brozekbdac817c2018-03-24 06:30:4762 mock_input_api.files = [
63 MockFile('some/path/foo.cc', diff_cc),
64 MockFile('some/path/foo.java', diff_java),
65 ]
mcasasb7440c282015-02-04 14:52:1966 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
67 MockOutputApi())
68 self.assertEqual(1, len(warnings))
69 self.assertEqual('warning', warnings[0].type)
Vaclav Brozekbdac817c2018-03-24 06:30:4770 self.assertTrue('foo.cc' in warnings[0].items[0])
71 self.assertTrue('foo.java' in warnings[0].items[1])
mcasasb7440c282015-02-04 14:52:1972
73 def testTypicalNotMatchedChangeViaSuffixes(self):
74 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:4775 diff_java = [
76 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
mcasasb7440c282015-02-04 14:52:1977 diff_xml = ['<histogram_suffixes name="SuperHistogram">',
78 ' <suffix name="Dummy"/>',
79 ' <affected-histogram name="Snafu.Dummy"/>',
80 '</histogram>']
81 mock_input_api = MockInputApi()
82 mock_input_api.files = [
83 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:4784 MockFile('some/path/foo.java', diff_java),
mcasasb7440c282015-02-04 14:52:1985 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
86 ]
87 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
88 MockOutputApi())
89 self.assertEqual(1, len(warnings))
90 self.assertEqual('warning', warnings[0].type)
Vaclav Brozekbdac817c2018-03-24 06:30:4791 self.assertTrue('foo.cc' in warnings[0].items[0])
92 self.assertTrue('foo.java' in warnings[0].items[1])
mcasasb7440c282015-02-04 14:52:1993
94 def testTypicalCorrectlyMatchedChangeViaSuffixes(self):
95 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:4796 diff_java = [
97 'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
mcasasb7440c282015-02-04 14:52:1998 diff_xml = ['<histogram_suffixes name="SuperHistogram">',
99 ' <suffix name="Dummy"/>',
100 ' <affected-histogram name="Bla.Foo"/>',
101 '</histogram>']
102 mock_input_api = MockInputApi()
103 mock_input_api.files = [
104 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:47105 MockFile('some/path/foo.java', diff_java),
mcasasb7440c282015-02-04 14:52:19106 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
107 ]
108 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
109 MockOutputApi())
110 self.assertEqual(0, len(warnings))
111
112 def testTypicalCorrectlyMatchedChangeViaSuffixesWithSeparator(self):
113 diff_cc = ['UMA_HISTOGRAM_BOOL("Snafu_Dummy", true)']
Vaclav Brozekbdac817c2018-03-24 06:30:47114 diff_java = ['RecordHistogram.recordBooleanHistogram("Snafu_Dummy", true)']
mcasasb7440c282015-02-04 14:52:19115 diff_xml = ['<histogram_suffixes name="SuperHistogram" separator="_">',
116 ' <suffix name="Dummy"/>',
117 ' <affected-histogram name="Snafu"/>',
118 '</histogram>']
119 mock_input_api = MockInputApi()
120 mock_input_api.files = [
121 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:47122 MockFile('some/path/foo.java', diff_java),
mcasasb7440c282015-02-04 14:52:19123 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
124 ]
125 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
126 MockOutputApi())
127 self.assertEqual(0, len(warnings))
[email protected]70ca77752012-11-20 03:45:03128
Vaclav Brozek8a8e2e202018-03-23 22:01:06129 def testNameMatch(self):
130 # Check that the detected histogram name is "Dummy" and not, e.g.,
131 # "Dummy\", true); // The \"correct"
132 diff_cc = ['UMA_HISTOGRAM_BOOL("Dummy", true); // The "correct" histogram']
Vaclav Brozekbdac817c2018-03-24 06:30:47133 diff_java = [
134 'RecordHistogram.recordBooleanHistogram("Dummy", true);'
135 + ' // The "correct" histogram']
Vaclav Brozek8a8e2e202018-03-23 22:01:06136 diff_xml = ['<histogram name="Dummy"> </histogram>']
137 mock_input_api = MockInputApi()
138 mock_input_api.files = [
139 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:47140 MockFile('some/path/foo.java', diff_java),
Vaclav Brozek8a8e2e202018-03-23 22:01:06141 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
142 ]
143 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
144 MockOutputApi())
145 self.assertEqual(0, len(warnings))
146
147 def testSimilarMacroNames(self):
Vaclav Brozekbdac817c2018-03-24 06:30:47148 diff_cc = ['PUMA_HISTOGRAM_COOL("Mountain Lion", 42)']
149 diff_java = [
150 'FakeRecordHistogram.recordFakeHistogram("Mountain Lion", 42)']
Vaclav Brozek8a8e2e202018-03-23 22:01:06151 mock_input_api = MockInputApi()
152 mock_input_api.files = [
153 MockFile('some/path/foo.cc', diff_cc),
Vaclav Brozekbdac817c2018-03-24 06:30:47154 MockFile('some/path/foo.java', diff_java),
Vaclav Brozek8a8e2e202018-03-23 22:01:06155 ]
156 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
157 MockOutputApi())
158 self.assertEqual(0, len(warnings))
159
Vaclav Brozek0e730cbd2018-03-24 06:18:17160 def testMultiLine(self):
161 diff_cc = ['UMA_HISTOGRAM_BOOLEAN(', ' "Multi.Line", true)']
162 diff_cc2 = ['UMA_HISTOGRAM_BOOLEAN(', ' "Multi.Line"', ' , true)']
Vaclav Brozekbdac817c2018-03-24 06:30:47163 diff_java = [
164 'RecordHistogram.recordBooleanHistogram(',
165 ' "Multi.Line", true);',
166 ]
Vaclav Brozek0e730cbd2018-03-24 06:18:17167 mock_input_api = MockInputApi()
168 mock_input_api.files = [
169 MockFile('some/path/foo.cc', diff_cc),
170 MockFile('some/path/foo2.cc', diff_cc2),
Vaclav Brozekbdac817c2018-03-24 06:30:47171 MockFile('some/path/foo.java', diff_java),
Vaclav Brozek0e730cbd2018-03-24 06:18:17172 ]
173 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
174 MockOutputApi())
175 self.assertEqual(1, len(warnings))
176 self.assertEqual('warning', warnings[0].type)
177 self.assertTrue('foo.cc' in warnings[0].items[0])
178 self.assertTrue('foo2.cc' in warnings[0].items[1])
179
[email protected]b8079ae4a2012-12-05 19:56:49180class BadExtensionsTest(unittest.TestCase):
181 def testBadRejFile(self):
182 mock_input_api = MockInputApi()
183 mock_input_api.files = [
184 MockFile('some/path/foo.cc', ''),
185 MockFile('some/path/foo.cc.rej', ''),
186 MockFile('some/path2/bar.h.rej', ''),
187 ]
188
189 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
190 self.assertEqual(1, len(results))
191 self.assertEqual(2, len(results[0].items))
192 self.assertTrue('foo.cc.rej' in results[0].items[0])
193 self.assertTrue('bar.h.rej' in results[0].items[1])
194
195 def testBadOrigFile(self):
196 mock_input_api = MockInputApi()
197 mock_input_api.files = [
198 MockFile('other/path/qux.h.orig', ''),
199 MockFile('other/path/qux.h', ''),
200 MockFile('other/path/qux.cc', ''),
201 ]
202
203 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
204 self.assertEqual(1, len(results))
205 self.assertEqual(1, len(results[0].items))
206 self.assertTrue('qux.h.orig' in results[0].items[0])
207
208 def testGoodFiles(self):
209 mock_input_api = MockInputApi()
210 mock_input_api.files = [
211 MockFile('other/path/qux.h', ''),
212 MockFile('other/path/qux.cc', ''),
213 ]
214 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
215 self.assertEqual(0, len(results))
216
217
glidere61efad2015-02-18 17:39:43218class CheckSingletonInHeadersTest(unittest.TestCase):
219 def testSingletonInArbitraryHeader(self):
220 diff_singleton_h = ['base::subtle::AtomicWord '
olli.raula36aa8be2015-09-10 11:14:22221 'base::Singleton<Type, Traits, DifferentiatingType>::']
222 diff_foo_h = ['// base::Singleton<Foo> in comment.',
223 'friend class base::Singleton<Foo>']
oysteinec430ad42015-10-22 20:55:24224 diff_foo2_h = [' //Foo* bar = base::Singleton<Foo>::get();']
olli.raula36aa8be2015-09-10 11:14:22225 diff_bad_h = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43226 mock_input_api = MockInputApi()
227 mock_input_api.files = [MockAffectedFile('base/memory/singleton.h',
228 diff_singleton_h),
229 MockAffectedFile('foo.h', diff_foo_h),
oysteinec430ad42015-10-22 20:55:24230 MockAffectedFile('foo2.h', diff_foo2_h),
glidere61efad2015-02-18 17:39:43231 MockAffectedFile('bad.h', diff_bad_h)]
232 warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api,
233 MockOutputApi())
234 self.assertEqual(1, len(warnings))
Sylvain Defresnea8b73d252018-02-28 15:45:54235 self.assertEqual(1, len(warnings[0].items))
glidere61efad2015-02-18 17:39:43236 self.assertEqual('error', warnings[0].type)
olli.raula36aa8be2015-09-10 11:14:22237 self.assertTrue('Found base::Singleton<T>' in warnings[0].message)
glidere61efad2015-02-18 17:39:43238
239 def testSingletonInCC(self):
olli.raula36aa8be2015-09-10 11:14:22240 diff_cc = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43241 mock_input_api = MockInputApi()
242 mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)]
243 warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api,
244 MockOutputApi())
245 self.assertEqual(0, len(warnings))
246
247
[email protected]b00342e7f2013-03-26 16:21:54248class InvalidOSMacroNamesTest(unittest.TestCase):
249 def testInvalidOSMacroNames(self):
250 lines = ['#if defined(OS_WINDOWS)',
251 ' #elif defined(OS_WINDOW)',
252 ' # if defined(OS_MACOSX) || defined(OS_CHROME)',
253 '# else // defined(OS_MAC)',
254 '#endif // defined(OS_MACOS)']
255 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
256 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
257 self.assertEqual(len(lines), len(errors))
258 self.assertTrue(':1 OS_WINDOWS' in errors[0])
259 self.assertTrue('(did you mean OS_WIN?)' in errors[0])
260
261 def testValidOSMacroNames(self):
262 lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS]
263 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
264 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
265 self.assertEqual(0, len(errors))
266
267
lliabraa35bab3932014-10-01 12:16:44268class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
269 def testInvalidIfDefinedMacroNames(self):
270 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
271 '#if !defined(TARGET_IPHONE_SIMULATOR)',
272 '#elif defined(TARGET_IPHONE_SIMULATOR)',
273 '#ifdef TARGET_IPHONE_SIMULATOR',
274 ' # ifdef TARGET_IPHONE_SIMULATOR',
275 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
276 '# else // defined(TARGET_IPHONE_SIMULATOR)',
277 '#endif // defined(TARGET_IPHONE_SIMULATOR)',]
278 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
279 MockInputApi(), MockFile('some/path/source.mm', lines))
280 self.assertEqual(len(lines), len(errors))
281
282 def testValidIfDefinedMacroNames(self):
283 lines = ['#if defined(FOO)',
284 '#ifdef BAR',]
285 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
286 MockInputApi(), MockFile('some/path/source.cc', lines))
287 self.assertEqual(0, len(errors))
288
289
[email protected]f32e2d1e2013-07-26 21:39:08290class CheckAddedDepsHaveTetsApprovalsTest(unittest.TestCase):
Daniel Cheng4dcdb6b2017-04-13 08:30:17291
292 def calculate(self, old_include_rules, old_specific_include_rules,
293 new_include_rules, new_specific_include_rules):
294 return PRESUBMIT._CalculateAddedDeps(
295 os.path, 'include_rules = %r\nspecific_include_rules = %r' % (
296 old_include_rules, old_specific_include_rules),
297 'include_rules = %r\nspecific_include_rules = %r' % (
298 new_include_rules, new_specific_include_rules))
299
300 def testCalculateAddedDeps(self):
301 old_include_rules = [
302 '+base',
303 '-chrome',
304 '+content',
305 '-grit',
306 '-grit/",',
307 '+jni/fooblat.h',
308 '!sandbox',
[email protected]f32e2d1e2013-07-26 21:39:08309 ]
Daniel Cheng4dcdb6b2017-04-13 08:30:17310 old_specific_include_rules = {
311 'compositor\.*': {
312 '+cc',
313 },
314 }
315
316 new_include_rules = [
317 '-ash',
318 '+base',
319 '+chrome',
320 '+components',
321 '+content',
322 '+grit',
323 '+grit/generated_resources.h",',
324 '+grit/",',
325 '+jni/fooblat.h',
326 '+policy',
manzagop85e629e2017-05-09 22:11:48327 '+' + os.path.join('third_party', 'WebKit'),
Daniel Cheng4dcdb6b2017-04-13 08:30:17328 ]
329 new_specific_include_rules = {
330 'compositor\.*': {
331 '+cc',
332 },
333 'widget\.*': {
334 '+gpu',
335 },
336 }
337
[email protected]f32e2d1e2013-07-26 21:39:08338 expected = set([
manzagop85e629e2017-05-09 22:11:48339 os.path.join('chrome', 'DEPS'),
340 os.path.join('gpu', 'DEPS'),
341 os.path.join('components', 'DEPS'),
342 os.path.join('policy', 'DEPS'),
343 os.path.join('third_party', 'WebKit', 'DEPS'),
[email protected]f32e2d1e2013-07-26 21:39:08344 ])
Daniel Cheng4dcdb6b2017-04-13 08:30:17345 self.assertEqual(
346 expected,
347 self.calculate(old_include_rules, old_specific_include_rules,
348 new_include_rules, new_specific_include_rules))
349
350 def testCalculateAddedDepsIgnoresPermutations(self):
351 old_include_rules = [
352 '+base',
353 '+chrome',
354 ]
355 new_include_rules = [
356 '+chrome',
357 '+base',
358 ]
359 self.assertEqual(set(),
360 self.calculate(old_include_rules, {}, new_include_rules,
361 {}))
[email protected]f32e2d1e2013-07-26 21:39:08362
363
[email protected]99171a92014-06-03 08:44:47364class JSONParsingTest(unittest.TestCase):
365 def testSuccess(self):
366 input_api = MockInputApi()
367 filename = 'valid_json.json'
368 contents = ['// This is a comment.',
369 '{',
370 ' "key1": ["value1", "value2"],',
371 ' "key2": 3 // This is an inline comment.',
372 '}'
373 ]
374 input_api.files = [MockFile(filename, contents)]
375 self.assertEqual(None,
376 PRESUBMIT._GetJSONParseError(input_api, filename))
377
378 def testFailure(self):
379 input_api = MockInputApi()
380 test_data = [
381 ('invalid_json_1.json',
382 ['{ x }'],
[email protected]a3343272014-06-17 11:41:53383 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47384 ('invalid_json_2.json',
385 ['// Hello world!',
386 '{ "hello": "world }'],
[email protected]a3343272014-06-17 11:41:53387 'Unterminated string starting at:'),
[email protected]99171a92014-06-03 08:44:47388 ('invalid_json_3.json',
389 ['{ "a": "b", "c": "d", }'],
[email protected]a3343272014-06-17 11:41:53390 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47391 ('invalid_json_4.json',
392 ['{ "a": "b" "c": "d" }'],
[email protected]a3343272014-06-17 11:41:53393 'Expecting , delimiter:'),
[email protected]99171a92014-06-03 08:44:47394 ]
395
396 input_api.files = [MockFile(filename, contents)
397 for (filename, contents, _) in test_data]
398
399 for (filename, _, expected_error) in test_data:
400 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
[email protected]a3343272014-06-17 11:41:53401 self.assertTrue(expected_error in str(actual_error),
402 "'%s' not found in '%s'" % (expected_error, actual_error))
[email protected]99171a92014-06-03 08:44:47403
404 def testNoEatComments(self):
405 input_api = MockInputApi()
406 file_with_comments = 'file_with_comments.json'
407 contents_with_comments = ['// This is a comment.',
408 '{',
409 ' "key1": ["value1", "value2"],',
410 ' "key2": 3 // This is an inline comment.',
411 '}'
412 ]
413 file_without_comments = 'file_without_comments.json'
414 contents_without_comments = ['{',
415 ' "key1": ["value1", "value2"],',
416 ' "key2": 3',
417 '}'
418 ]
419 input_api.files = [MockFile(file_with_comments, contents_with_comments),
420 MockFile(file_without_comments,
421 contents_without_comments)]
422
423 self.assertEqual('No JSON object could be decoded',
424 str(PRESUBMIT._GetJSONParseError(input_api,
425 file_with_comments,
426 eat_comments=False)))
427 self.assertEqual(None,
428 PRESUBMIT._GetJSONParseError(input_api,
429 file_without_comments,
430 eat_comments=False))
431
432
433class IDLParsingTest(unittest.TestCase):
434 def testSuccess(self):
435 input_api = MockInputApi()
436 filename = 'valid_idl_basics.idl'
437 contents = ['// Tests a valid IDL file.',
438 'namespace idl_basics {',
439 ' enum EnumType {',
440 ' name1,',
441 ' name2',
442 ' };',
443 '',
444 ' dictionary MyType1 {',
445 ' DOMString a;',
446 ' };',
447 '',
448 ' callback Callback1 = void();',
449 ' callback Callback2 = void(long x);',
450 ' callback Callback3 = void(MyType1 arg);',
451 ' callback Callback4 = void(EnumType type);',
452 '',
453 ' interface Functions {',
454 ' static void function1();',
455 ' static void function2(long x);',
456 ' static void function3(MyType1 arg);',
457 ' static void function4(Callback1 cb);',
458 ' static void function5(Callback2 cb);',
459 ' static void function6(Callback3 cb);',
460 ' static void function7(Callback4 cb);',
461 ' };',
462 '',
463 ' interface Events {',
464 ' static void onFoo1();',
465 ' static void onFoo2(long x);',
466 ' static void onFoo2(MyType1 arg);',
467 ' static void onFoo3(EnumType type);',
468 ' };',
469 '};'
470 ]
471 input_api.files = [MockFile(filename, contents)]
472 self.assertEqual(None,
473 PRESUBMIT._GetIDLParseError(input_api, filename))
474
475 def testFailure(self):
476 input_api = MockInputApi()
477 test_data = [
478 ('invalid_idl_1.idl',
479 ['//',
480 'namespace test {',
481 ' dictionary {',
482 ' DOMString s;',
483 ' };',
484 '};'],
485 'Unexpected "{" after keyword "dictionary".\n'),
486 # TODO(yoz): Disabled because it causes the IDL parser to hang.
487 # See crbug.com/363830.
488 # ('invalid_idl_2.idl',
489 # (['namespace test {',
490 # ' dictionary MissingSemicolon {',
491 # ' DOMString a',
492 # ' DOMString b;',
493 # ' };',
494 # '};'],
495 # 'Unexpected symbol DOMString after symbol a.'),
496 ('invalid_idl_3.idl',
497 ['//',
498 'namespace test {',
499 ' enum MissingComma {',
500 ' name1',
501 ' name2',
502 ' };',
503 '};'],
504 'Unexpected symbol name2 after symbol name1.'),
505 ('invalid_idl_4.idl',
506 ['//',
507 'namespace test {',
508 ' enum TrailingComma {',
509 ' name1,',
510 ' name2,',
511 ' };',
512 '};'],
513 'Trailing comma in block.'),
514 ('invalid_idl_5.idl',
515 ['//',
516 'namespace test {',
517 ' callback Callback1 = void(;',
518 '};'],
519 'Unexpected ";" after "(".'),
520 ('invalid_idl_6.idl',
521 ['//',
522 'namespace test {',
523 ' callback Callback1 = void(long );',
524 '};'],
525 'Unexpected ")" after symbol long.'),
526 ('invalid_idl_7.idl',
527 ['//',
528 'namespace test {',
529 ' interace Events {',
530 ' static void onFoo1();',
531 ' };',
532 '};'],
533 'Unexpected symbol Events after symbol interace.'),
534 ('invalid_idl_8.idl',
535 ['//',
536 'namespace test {',
537 ' interface NotEvent {',
538 ' static void onFoo1();',
539 ' };',
540 '};'],
541 'Did not process Interface Interface(NotEvent)'),
542 ('invalid_idl_9.idl',
543 ['//',
544 'namespace test {',
545 ' interface {',
546 ' static void function1();',
547 ' };',
548 '};'],
549 'Interface missing name.'),
550 ]
551
552 input_api.files = [MockFile(filename, contents)
553 for (filename, contents, _) in test_data]
554
555 for (filename, _, expected_error) in test_data:
556 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
557 self.assertTrue(expected_error in str(actual_error),
558 "'%s' not found in '%s'" % (expected_error, actual_error))
559
560
[email protected]0bb112362014-07-26 04:38:32561class TryServerMasterTest(unittest.TestCase):
562 def testTryServerMasters(self):
563 bots = {
tandriie5587792016-07-14 00:34:50564 'master.tryserver.chromium.android': [
jbudorick3ae7a772016-05-20 02:36:04565 'android_archive_rel_ng',
566 'android_arm64_dbg_recipe',
567 'android_blink_rel',
568 'android_chromium_variable',
569 'android_chromium_variable_archive',
570 'android_chromium_variable_arm64',
571 'android_chromium_variable_cast_shell',
572 'android_chromium_variable_clang',
573 'android_chromium_variable_gn',
574 'android_chromium_variable_nexus4',
575 'android_clang_dbg_recipe',
576 'android_compile_dbg',
577 'android_compile_mips_dbg',
jbudorick3ae7a772016-05-20 02:36:04578 'android_compile_x64_dbg',
579 'android_compile_x86_dbg',
580 'android_coverage',
581 'android_cronet_tester'
582 'android_swarming_rel',
583 'cast_shell_android',
584 'linux_android_dbg_ng',
585 'linux_android_rel_ng',
586 ],
tandriie5587792016-07-14 00:34:50587 'master.tryserver.chromium.mac': [
[email protected]0bb112362014-07-26 04:38:32588 'ios_dbg_simulator',
589 'ios_rel_device',
590 'ios_rel_device_ninja',
591 'mac_asan',
592 'mac_asan_64',
593 'mac_chromium_compile_dbg',
594 'mac_chromium_compile_rel',
595 'mac_chromium_dbg',
596 'mac_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32597 'mac_nacl_sdk',
598 'mac_nacl_sdk_build',
599 'mac_rel_naclmore',
[email protected]0bb112362014-07-26 04:38:32600 'mac_x64_rel',
601 'mac_xcodebuild',
602 ],
tandriie5587792016-07-14 00:34:50603 'master.tryserver.chromium.linux': [
[email protected]0bb112362014-07-26 04:38:32604 'chromium_presubmit',
605 'linux_arm_cross_compile',
606 'linux_arm_tester',
[email protected]0bb112362014-07-26 04:38:32607 'linux_chromeos_asan',
608 'linux_chromeos_browser_asan',
609 'linux_chromeos_valgrind',
[email protected]0bb112362014-07-26 04:38:32610 'linux_chromium_chromeos_dbg',
611 'linux_chromium_chromeos_rel',
[email protected]0bb112362014-07-26 04:38:32612 'linux_chromium_compile_dbg',
613 'linux_chromium_compile_rel',
614 'linux_chromium_dbg',
615 'linux_chromium_gn_dbg',
616 'linux_chromium_gn_rel',
617 'linux_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32618 'linux_chromium_trusty32_dbg',
619 'linux_chromium_trusty32_rel',
620 'linux_chromium_trusty_dbg',
621 'linux_chromium_trusty_rel',
622 'linux_clang_tsan',
623 'linux_ecs_ozone',
624 'linux_layout',
625 'linux_layout_asan',
626 'linux_layout_rel',
627 'linux_layout_rel_32',
628 'linux_nacl_sdk',
629 'linux_nacl_sdk_bionic',
630 'linux_nacl_sdk_bionic_build',
631 'linux_nacl_sdk_build',
632 'linux_redux',
633 'linux_rel_naclmore',
634 'linux_rel_precise32',
635 'linux_valgrind',
636 'tools_build_presubmit',
637 ],
tandriie5587792016-07-14 00:34:50638 'master.tryserver.chromium.win': [
[email protected]0bb112362014-07-26 04:38:32639 'win8_aura',
640 'win8_chromium_dbg',
641 'win8_chromium_rel',
642 'win_chromium_compile_dbg',
643 'win_chromium_compile_rel',
644 'win_chromium_dbg',
645 'win_chromium_rel',
646 'win_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32647 'win_chromium_x64_dbg',
648 'win_chromium_x64_rel',
[email protected]0bb112362014-07-26 04:38:32649 'win_nacl_sdk',
650 'win_nacl_sdk_build',
651 'win_rel_naclmore',
652 ],
653 }
654 for master, bots in bots.iteritems():
655 for bot in bots:
656 self.assertEqual(master, PRESUBMIT.GetTryServerMasterForBot(bot),
657 'bot=%s: expected %s, computed %s' % (
658 bot, master, PRESUBMIT.GetTryServerMasterForBot(bot)))
659
660
davileene0426252015-03-02 21:10:41661class UserMetricsActionTest(unittest.TestCase):
662 def testUserMetricsActionInActions(self):
663 input_api = MockInputApi()
664 file_with_user_action = 'file_with_user_action.cc'
665 contents_with_user_action = [
666 'base::UserMetricsAction("AboutChrome")'
667 ]
668
669 input_api.files = [MockFile(file_with_user_action,
670 contents_with_user_action)]
671
672 self.assertEqual(
673 [], PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi()))
674
675
676 def testUserMetricsActionNotAddedToActions(self):
677 input_api = MockInputApi()
678 file_with_user_action = 'file_with_user_action.cc'
679 contents_with_user_action = [
680 'base::UserMetricsAction("NotInActionsXml")'
681 ]
682
683 input_api.files = [MockFile(file_with_user_action,
684 contents_with_user_action)]
685
686 output = PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi())
687 self.assertEqual(
688 ('File %s line %d: %s is missing in '
689 'tools/metrics/actions/actions.xml. Please run '
690 'tools/metrics/actions/extract_actions.py to update.'
691 % (file_with_user_action, 1, 'NotInActionsXml')),
692 output[0].message)
693
694
agrievef32bcc72016-04-04 14:57:40695class PydepsNeedsUpdatingTest(unittest.TestCase):
696
697 class MockSubprocess(object):
698 CalledProcessError = subprocess.CalledProcessError
699
700 def setUp(self):
701 mock_all_pydeps = ['A.pydeps', 'B.pydeps']
702 self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES
703 PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps
704 self.mock_input_api = MockInputApi()
705 self.mock_output_api = MockOutputApi()
706 self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess()
707 self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps)
708 self.checker._file_cache = {
709 'A.pydeps': '# Generated by:\n# CMD A\nA.py\nC.py\n',
710 'B.pydeps': '# Generated by:\n# CMD B\nB.py\nC.py\n',
711 }
712
713 def tearDown(self):
714 PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES
715
716 def _RunCheck(self):
717 return PRESUBMIT._CheckPydepsNeedsUpdating(self.mock_input_api,
718 self.mock_output_api,
719 checker_for_tests=self.checker)
720
721 def testAddedPydep(self):
pastarmovj89f7ee12016-09-20 14:58:13722 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
723 if self.mock_input_api.platform != 'linux2':
724 return []
725
agrievef32bcc72016-04-04 14:57:40726 self.mock_input_api.files = [
727 MockAffectedFile('new.pydeps', [], action='A'),
728 ]
729
Zhiling Huang45cabf32018-03-10 00:50:03730 self.mock_input_api.CreateMockFileInPath(
731 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
732 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40733 results = self._RunCheck()
734 self.assertEqual(1, len(results))
735 self.assertTrue('PYDEPS_FILES' in str(results[0]))
736
Zhiling Huang45cabf32018-03-10 00:50:03737 def testPydepNotInSrc(self):
738 self.mock_input_api.files = [
739 MockAffectedFile('new.pydeps', [], action='A'),
740 ]
741 self.mock_input_api.CreateMockFileInPath([])
742 results = self._RunCheck()
743 self.assertEqual(0, len(results))
744
agrievef32bcc72016-04-04 14:57:40745 def testRemovedPydep(self):
pastarmovj89f7ee12016-09-20 14:58:13746 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
747 if self.mock_input_api.platform != 'linux2':
748 return []
749
agrievef32bcc72016-04-04 14:57:40750 self.mock_input_api.files = [
751 MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'),
752 ]
Zhiling Huang45cabf32018-03-10 00:50:03753 self.mock_input_api.CreateMockFileInPath(
754 [x.LocalPath() for x in self.mock_input_api.AffectedFiles(
755 include_deletes=True)])
agrievef32bcc72016-04-04 14:57:40756 results = self._RunCheck()
757 self.assertEqual(1, len(results))
758 self.assertTrue('PYDEPS_FILES' in str(results[0]))
759
760 def testRandomPyIgnored(self):
pastarmovj89f7ee12016-09-20 14:58:13761 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
762 if self.mock_input_api.platform != 'linux2':
763 return []
764
agrievef32bcc72016-04-04 14:57:40765 self.mock_input_api.files = [
766 MockAffectedFile('random.py', []),
767 ]
768
769 results = self._RunCheck()
770 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
771
772 def testRelevantPyNoChange(self):
pastarmovj89f7ee12016-09-20 14:58:13773 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
774 if self.mock_input_api.platform != 'linux2':
775 return []
776
agrievef32bcc72016-04-04 14:57:40777 self.mock_input_api.files = [
778 MockAffectedFile('A.py', []),
779 ]
780
John Budorickab2fa102017-10-06 16:59:49781 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40782 self.assertEqual('CMD A --output ""', cmd)
783 return self.checker._file_cache['A.pydeps']
784
785 self.mock_input_api.subprocess.check_output = mock_check_output
786
787 results = self._RunCheck()
788 self.assertEqual(0, len(results), 'Unexpected results: %r' % results)
789
790 def testRelevantPyOneChange(self):
pastarmovj89f7ee12016-09-20 14:58:13791 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
792 if self.mock_input_api.platform != 'linux2':
793 return []
794
agrievef32bcc72016-04-04 14:57:40795 self.mock_input_api.files = [
796 MockAffectedFile('A.py', []),
797 ]
798
John Budorickab2fa102017-10-06 16:59:49799 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40800 self.assertEqual('CMD A --output ""', cmd)
801 return 'changed data'
802
803 self.mock_input_api.subprocess.check_output = mock_check_output
804
805 results = self._RunCheck()
806 self.assertEqual(1, len(results))
807 self.assertTrue('File is stale' in str(results[0]))
808
809 def testRelevantPyTwoChanges(self):
pastarmovj89f7ee12016-09-20 14:58:13810 # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Android.
811 if self.mock_input_api.platform != 'linux2':
812 return []
813
agrievef32bcc72016-04-04 14:57:40814 self.mock_input_api.files = [
815 MockAffectedFile('C.py', []),
816 ]
817
John Budorickab2fa102017-10-06 16:59:49818 def mock_check_output(cmd, shell=False, env=None):
agrievef32bcc72016-04-04 14:57:40819 return 'changed data'
820
821 self.mock_input_api.subprocess.check_output = mock_check_output
822
823 results = self._RunCheck()
824 self.assertEqual(2, len(results))
825 self.assertTrue('File is stale' in str(results[0]))
826 self.assertTrue('File is stale' in str(results[1]))
827
Daniel Bratell8ba52722018-03-02 16:06:14828class IncludeGuardTest(unittest.TestCase):
829 def testIncludeGuardChecks(self):
830 mock_input_api = MockInputApi()
831 mock_output_api = MockOutputApi()
832 mock_input_api.files = [
833 MockAffectedFile('content/browser/thing/foo.h', [
834 '// Comment',
835 '#ifndef CONTENT_BROWSER_THING_FOO_H_',
836 '#define CONTENT_BROWSER_THING_FOO_H_',
837 'struct McBoatFace;',
838 '#endif // CONTENT_BROWSER_THING_FOO_H_',
839 ]),
840 MockAffectedFile('content/browser/thing/bar.h', [
841 '#ifndef CONTENT_BROWSER_THING_BAR_H_',
842 '#define CONTENT_BROWSER_THING_BAR_H_',
843 'namespace content {',
844 '#endif // CONTENT_BROWSER_THING_BAR_H_',
845 '} // namespace content',
846 ]),
847 MockAffectedFile('content/browser/test1.h', [
848 'namespace content {',
849 '} // namespace content',
850 ]),
851 MockAffectedFile('content\\browser\\win.h', [
852 '#ifndef CONTENT_BROWSER_WIN_H_',
853 '#define CONTENT_BROWSER_WIN_H_',
854 'struct McBoatFace;',
855 '#endif // CONTENT_BROWSER_WIN_H_',
856 ]),
857 MockAffectedFile('content/browser/test2.h', [
858 '// Comment',
859 '#ifndef CONTENT_BROWSER_TEST2_H_',
860 'struct McBoatFace;',
861 '#endif // CONTENT_BROWSER_TEST2_H_',
862 ]),
863 MockAffectedFile('content/browser/internal.h', [
864 '// Comment',
865 '#ifndef CONTENT_BROWSER_INTERNAL_H_',
866 '#define CONTENT_BROWSER_INTERNAL_H_',
867 '// Comment',
868 '#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
869 '#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
870 'namespace internal {',
871 '} // namespace internal',
872 '#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
873 'namespace content {',
874 '} // namespace content',
875 '#endif // CONTENT_BROWSER_THING_BAR_H_',
876 ]),
877 MockAffectedFile('content/browser/thing/foo.cc', [
878 '// This is a non-header.',
879 ]),
880 MockAffectedFile('content/browser/disabled.h', [
881 '// no-include-guard-because-multiply-included',
882 'struct McBoatFace;',
883 ]),
884 # New files don't allow misspelled include guards.
885 MockAffectedFile('content/browser/spleling.h', [
886 '#ifndef CONTENT_BROWSER_SPLLEING_H_',
887 '#define CONTENT_BROWSER_SPLLEING_H_',
888 'struct McBoatFace;',
889 '#endif // CONTENT_BROWSER_SPLLEING_H_',
890 ]),
891 # Old files allow misspelled include guards (for now).
892 MockAffectedFile('chrome/old.h', [
893 '// New contents',
894 '#ifndef CHROME_ODL_H_',
895 '#define CHROME_ODL_H_',
896 '#endif // CHROME_ODL_H_',
897 ], [
898 '// Old contents',
899 '#ifndef CHROME_ODL_H_',
900 '#define CHROME_ODL_H_',
901 '#endif // CHROME_ODL_H_',
902 ]),
903 # Using a Blink style include guard outside Blink is wrong.
904 MockAffectedFile('content/NotInBlink.h', [
905 '#ifndef NotInBlink_h',
906 '#define NotInBlink_h',
907 'struct McBoatFace;',
908 '#endif // NotInBlink_h',
909 ]),
910 # Using a Blink style include guard in Blink is ok for now.
911 MockAffectedFile('third_party/WebKit/InBlink.h', [
912 '#ifndef InBlink_h',
913 '#define InBlink_h',
914 'struct McBoatFace;',
915 '#endif // InBlink_h',
916 ]),
917 # Using a bad include guard in Blink is not ok.
918 MockAffectedFile('third_party/WebKit/AlsoInBlink.h', [
919 '#ifndef WrongInBlink_h',
920 '#define WrongInBlink_h',
921 'struct McBoatFace;',
922 '#endif // WrongInBlink_h',
923 ]),
924 # Using a bad include guard in Blink is accepted if it's an old file.
925 MockAffectedFile('third_party/WebKit/StillInBlink.h', [
926 '// New contents',
927 '#ifndef AcceptedInBlink_h',
928 '#define AcceptedInBlink_h',
929 'struct McBoatFace;',
930 '#endif // AcceptedInBlink_h',
931 ], [
932 '// Old contents',
933 '#ifndef AcceptedInBlink_h',
934 '#define AcceptedInBlink_h',
935 'struct McBoatFace;',
936 '#endif // AcceptedInBlink_h',
937 ]),
938 ]
939 msgs = PRESUBMIT._CheckForIncludeGuards(
940 mock_input_api, mock_output_api)
941 expected_fail_count = 6
942 self.assertEqual(expected_fail_count, len(msgs),
943 'Expected %d items, found %d: %s'
944 % (expected_fail_count, len(msgs), msgs))
945 self.assertEqual(msgs[0].items, [ 'content/browser/thing/bar.h' ])
946 self.assertEqual(msgs[0].message,
947 'Include guard CONTENT_BROWSER_THING_BAR_H_ '
948 'not covering the whole file')
949
950 self.assertEqual(msgs[1].items, [ 'content/browser/test1.h' ])
951 self.assertEqual(msgs[1].message,
952 'Missing include guard CONTENT_BROWSER_TEST1_H_')
953
954 self.assertEqual(msgs[2].items, [ 'content/browser/test2.h:3' ])
955 self.assertEqual(msgs[2].message,
956 'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
957 'include guard')
958
959 self.assertEqual(msgs[3].items, [ 'content/browser/spleling.h:1' ])
960 self.assertEqual(msgs[3].message,
961 'Header using the wrong include guard name '
962 'CONTENT_BROWSER_SPLLEING_H_')
963
964 self.assertEqual(msgs[4].items, [ 'content/NotInBlink.h:1' ])
965 self.assertEqual(msgs[4].message,
966 'Header using the wrong include guard name '
967 'NotInBlink_h')
968
969 self.assertEqual(msgs[5].items, [ 'third_party/WebKit/AlsoInBlink.h:1' ])
970 self.assertEqual(msgs[5].message,
971 'Header using the wrong include guard name '
972 'WrongInBlink_h')
973
yolandyan45001472016-12-21 21:12:42974class AndroidDeprecatedTestAnnotationTest(unittest.TestCase):
975 def testCheckAndroidTestAnnotationUsage(self):
976 mock_input_api = MockInputApi()
977 mock_output_api = MockOutputApi()
978
979 mock_input_api.files = [
980 MockAffectedFile('LalaLand.java', [
981 'random stuff'
982 ]),
983 MockAffectedFile('CorrectUsage.java', [
984 'import android.support.test.filters.LargeTest;',
985 'import android.support.test.filters.MediumTest;',
986 'import android.support.test.filters.SmallTest;',
987 ]),
988 MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java', [
989 'import android.test.suitebuilder.annotation.LargeTest;',
990 ]),
991 MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java', [
992 'import android.test.suitebuilder.annotation.MediumTest;',
993 ]),
994 MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java', [
995 'import android.test.suitebuilder.annotation.SmallTest;',
996 ]),
997 MockAffectedFile('UsedDeprecatedSmokeAnnotation.java', [
998 'import android.test.suitebuilder.annotation.Smoke;',
999 ])
1000 ]
1001 msgs = PRESUBMIT._CheckAndroidTestAnnotationUsage(
1002 mock_input_api, mock_output_api)
1003 self.assertEqual(1, len(msgs),
1004 'Expected %d items, found %d: %s'
1005 % (1, len(msgs), msgs))
1006 self.assertEqual(4, len(msgs[0].items),
1007 'Expected %d items, found %d: %s'
1008 % (4, len(msgs[0].items), msgs[0].items))
1009 self.assertTrue('UsedDeprecatedLargeTestAnnotation.java:1' in msgs[0].items,
1010 'UsedDeprecatedLargeTestAnnotation not found in errors')
1011 self.assertTrue('UsedDeprecatedMediumTestAnnotation.java:1'
1012 in msgs[0].items,
1013 'UsedDeprecatedMediumTestAnnotation not found in errors')
1014 self.assertTrue('UsedDeprecatedSmallTestAnnotation.java:1' in msgs[0].items,
1015 'UsedDeprecatedSmallTestAnnotation not found in errors')
1016 self.assertTrue('UsedDeprecatedSmokeAnnotation.java:1' in msgs[0].items,
1017 'UsedDeprecatedSmokeAnnotation not found in errors')
1018
Yoland Yanb92fa522017-08-28 17:37:061019class AndroidDeprecatedJUnitFrameworkTest(unittest.TestCase):
1020 def testCheckAndroidTestAnnotationUsage(self):
1021 mock_input_api = MockInputApi()
1022 mock_output_api = MockOutputApi()
yolandyan45001472016-12-21 21:12:421023
Yoland Yanb92fa522017-08-28 17:37:061024 mock_input_api.files = [
1025 MockAffectedFile('LalaLand.java', [
1026 'random stuff'
1027 ]),
1028 MockAffectedFile('CorrectUsage.java', [
1029 'import org.junit.ABC',
1030 'import org.junit.XYZ;',
1031 ]),
1032 MockAffectedFile('UsedDeprecatedJUnit.java', [
1033 'import junit.framework.*;',
1034 ]),
1035 MockAffectedFile('UsedDeprecatedJUnitAssert.java', [
1036 'import junit.framework.Assert;',
1037 ]),
1038 ]
1039 msgs = PRESUBMIT._CheckAndroidTestJUnitFrameworkImport(
1040 mock_input_api, mock_output_api)
1041 self.assertEqual(1, len(msgs),
1042 'Expected %d items, found %d: %s'
1043 % (1, len(msgs), msgs))
1044 self.assertEqual(2, len(msgs[0].items),
1045 'Expected %d items, found %d: %s'
1046 % (2, len(msgs[0].items), msgs[0].items))
1047 self.assertTrue('UsedDeprecatedJUnit.java:1' in msgs[0].items,
1048 'UsedDeprecatedJUnit.java not found in errors')
1049 self.assertTrue('UsedDeprecatedJUnitAssert.java:1'
1050 in msgs[0].items,
1051 'UsedDeprecatedJUnitAssert not found in errors')
1052
1053class AndroidJUnitBaseClass(unittest.TestCase):
1054 def testCheckAndroidTestAnnotationUsage(self):
1055 mock_input_api = MockInputApi()
1056 mock_output_api = MockOutputApi()
1057
1058 mock_input_api.files = [
1059 MockAffectedFile('LalaLand.java', [
1060 'random stuff'
1061 ]),
1062 MockAffectedFile('CorrectTest.java', [
1063 '@RunWith(ABC.class);'
1064 'public class CorrectTest {',
1065 '}',
1066 ]),
1067 MockAffectedFile('HistoricallyIncorrectTest.java', [
1068 'public class Test extends BaseCaseA {',
1069 '}',
1070 ], old_contents=[
1071 'public class Test extends BaseCaseB {',
1072 '}',
1073 ]),
1074 MockAffectedFile('CorrectTestWithInterface.java', [
1075 '@RunWith(ABC.class);'
1076 'public class CorrectTest implement Interface {',
1077 '}',
1078 ]),
1079 MockAffectedFile('IncorrectTest.java', [
1080 'public class IncorrectTest extends TestCase {',
1081 '}',
1082 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241083 MockAffectedFile('IncorrectWithInterfaceTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061084 'public class Test implements X extends BaseClass {',
1085 '}',
1086 ]),
Vaclav Brozekf01ed502018-03-16 19:38:241087 MockAffectedFile('IncorrectMultiLineTest.java', [
Yoland Yanb92fa522017-08-28 17:37:061088 'public class Test implements X, Y, Z',
1089 ' extends TestBase {',
1090 '}',
1091 ]),
1092 ]
1093 msgs = PRESUBMIT._CheckAndroidTestJUnitInheritance(
1094 mock_input_api, mock_output_api)
1095 self.assertEqual(1, len(msgs),
1096 'Expected %d items, found %d: %s'
1097 % (1, len(msgs), msgs))
1098 self.assertEqual(3, len(msgs[0].items),
1099 'Expected %d items, found %d: %s'
1100 % (3, len(msgs[0].items), msgs[0].items))
1101 self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
1102 'IncorrectTest not found in errors')
Vaclav Brozekf01ed502018-03-16 19:38:241103 self.assertTrue('IncorrectWithInterfaceTest.java:1'
Yoland Yanb92fa522017-08-28 17:37:061104 in msgs[0].items,
Vaclav Brozekf01ed502018-03-16 19:38:241105 'IncorrectWithInterfaceTest not found in errors')
1106 self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
1107 'IncorrectMultiLineTest not found in errors')
yolandyan45001472016-12-21 21:12:421108
dgn4401aa52015-04-29 16:26:171109class LogUsageTest(unittest.TestCase):
1110
dgnaa68d5e2015-06-10 10:08:221111 def testCheckAndroidCrLogUsage(self):
1112 mock_input_api = MockInputApi()
1113 mock_output_api = MockOutputApi()
1114
1115 mock_input_api.files = [
1116 MockAffectedFile('RandomStuff.java', [
1117 'random stuff'
1118 ]),
dgn87d9fb62015-06-12 09:15:121119 MockAffectedFile('HasAndroidLog.java', [
1120 'import android.util.Log;',
1121 'some random stuff',
1122 'Log.d("TAG", "foo");',
1123 ]),
1124 MockAffectedFile('HasExplicitUtilLog.java', [
1125 'some random stuff',
1126 'android.util.Log.d("TAG", "foo");',
1127 ]),
1128 MockAffectedFile('IsInBasePackage.java', [
1129 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:511130 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121131 'Log.d(TAG, "foo");',
1132 ]),
1133 MockAffectedFile('IsInBasePackageButImportsLog.java', [
1134 'package org.chromium.base;',
1135 'import android.util.Log;',
dgn38736db2015-09-18 19:20:511136 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121137 'Log.d(TAG, "foo");',
1138 ]),
1139 MockAffectedFile('HasBothLog.java', [
1140 'import org.chromium.base.Log;',
1141 'some random stuff',
dgn38736db2015-09-18 19:20:511142 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:121143 'Log.d(TAG, "foo");',
1144 'android.util.Log.d("TAG", "foo");',
1145 ]),
dgnaa68d5e2015-06-10 10:08:221146 MockAffectedFile('HasCorrectTag.java', [
1147 'import org.chromium.base.Log;',
1148 'some random stuff',
dgn38736db2015-09-18 19:20:511149 'private static final String TAG = "cr_Foo";',
1150 'Log.d(TAG, "foo");',
1151 ]),
1152 MockAffectedFile('HasOldTag.java', [
1153 'import org.chromium.base.Log;',
1154 'some random stuff',
dgnaa68d5e2015-06-10 10:08:221155 'private static final String TAG = "cr.Foo";',
1156 'Log.d(TAG, "foo");',
1157 ]),
dgn38736db2015-09-18 19:20:511158 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:221159 'import org.chromium.base.Log;',
1160 'some random stuff',
dgn38736db2015-09-18 19:20:511161 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:221162 'Log.d(TAG, "foo");',
1163 ]),
1164 MockAffectedFile('HasNoTagDecl.java', [
1165 'import org.chromium.base.Log;',
1166 'some random stuff',
1167 'Log.d(TAG, "foo");',
1168 ]),
1169 MockAffectedFile('HasIncorrectTagDecl.java', [
1170 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:511171 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221172 'some random stuff',
1173 'Log.d(TAG, "foo");',
1174 ]),
1175 MockAffectedFile('HasInlineTag.java', [
1176 'import org.chromium.base.Log;',
1177 'some random stuff',
dgn38736db2015-09-18 19:20:511178 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:221179 'Log.d("TAG", "foo");',
1180 ]),
dgn38736db2015-09-18 19:20:511181 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:221182 'import org.chromium.base.Log;',
1183 'some random stuff',
1184 'private static final String TAG = "rubbish";',
1185 'Log.d(TAG, "foo");',
1186 ]),
1187 MockAffectedFile('HasTooLongTag.java', [
1188 'import org.chromium.base.Log;',
1189 'some random stuff',
dgn38736db2015-09-18 19:20:511190 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:221191 'Log.d(TAG, "foo");',
1192 ]),
1193 ]
1194
1195 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
1196 mock_input_api, mock_output_api)
1197
dgn38736db2015-09-18 19:20:511198 self.assertEqual(5, len(msgs),
1199 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:221200
1201 # Declaration format
dgn38736db2015-09-18 19:20:511202 nb = len(msgs[0].items)
1203 self.assertEqual(2, nb,
1204 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:221205 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
1206 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:221207
1208 # Tag length
dgn38736db2015-09-18 19:20:511209 nb = len(msgs[1].items)
1210 self.assertEqual(1, nb,
1211 'Expected %d items, found %d: %s' % (1, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:221212 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
1213
1214 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:511215 nb = len(msgs[2].items)
1216 self.assertEqual(1, nb,
1217 'Expected %d items, found %d: %s' % (1, nb, msgs[2].items))
dgnaa68d5e2015-06-10 10:08:221218 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
1219
dgn87d9fb62015-06-12 09:15:121220 # Util Log usage
dgn38736db2015-09-18 19:20:511221 nb = len(msgs[3].items)
1222 self.assertEqual(2, nb,
1223 'Expected %d items, found %d: %s' % (2, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:121224 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
1225 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:221226
dgn38736db2015-09-18 19:20:511227 # Tag must not contain
1228 nb = len(msgs[4].items)
1229 self.assertEqual(2, nb,
1230 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
1231 self.assertTrue('HasDottedTag.java' in msgs[4].items)
1232 self.assertTrue('HasOldTag.java' in msgs[4].items)
1233
estadee17314a02017-01-12 16:22:161234class GoogleAnswerUrlFormatTest(unittest.TestCase):
1235
1236 def testCatchAnswerUrlId(self):
1237 input_api = MockInputApi()
1238 input_api.files = [
1239 MockFile('somewhere/file.cc',
1240 ['char* host = '
1241 ' "https://support.google.com/chrome/answer/123456";']),
1242 MockFile('somewhere_else/file.cc',
1243 ['char* host = '
1244 ' "https://support.google.com/chrome/a/answer/123456";']),
1245 ]
1246
1247 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1248 input_api, MockOutputApi())
1249 self.assertEqual(1, len(warnings))
1250 self.assertEqual(2, len(warnings[0].items))
1251
1252 def testAllowAnswerUrlParam(self):
1253 input_api = MockInputApi()
1254 input_api.files = [
1255 MockFile('somewhere/file.cc',
1256 ['char* host = '
1257 ' "https://support.google.com/chrome/?p=cpn_crash_reports";']),
1258 ]
1259
1260 warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl(
1261 input_api, MockOutputApi())
1262 self.assertEqual(0, len(warnings))
1263
reillyi38965732015-11-16 18:27:331264class HardcodedGoogleHostsTest(unittest.TestCase):
1265
1266 def testWarnOnAssignedLiterals(self):
1267 input_api = MockInputApi()
1268 input_api.files = [
1269 MockFile('content/file.cc',
1270 ['char* host = "https://www.google.com";']),
1271 MockFile('content/file.cc',
1272 ['char* host = "https://www.googleapis.com";']),
1273 MockFile('content/file.cc',
1274 ['char* host = "https://clients1.google.com";']),
1275 ]
1276
1277 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1278 input_api, MockOutputApi())
1279 self.assertEqual(1, len(warnings))
1280 self.assertEqual(3, len(warnings[0].items))
1281
1282 def testAllowInComment(self):
1283 input_api = MockInputApi()
1284 input_api.files = [
1285 MockFile('content/file.cc',
1286 ['char* host = "https://www.aol.com"; // google.com'])
1287 ]
1288
1289 warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers(
1290 input_api, MockOutputApi())
1291 self.assertEqual(0, len(warnings))
1292
dgn4401aa52015-04-29 16:26:171293
jbriance9e12f162016-11-25 07:57:501294class ForwardDeclarationTest(unittest.TestCase):
jbriance2c51e821a2016-12-12 08:24:311295 def testCheckHeadersOnlyOutsideThirdParty(self):
jbriance9e12f162016-11-25 07:57:501296 mock_input_api = MockInputApi()
1297 mock_input_api.files = [
1298 MockAffectedFile('somewhere/file.cc', [
1299 'class DummyClass;'
jbriance2c51e821a2016-12-12 08:24:311300 ]),
1301 MockAffectedFile('third_party/header.h', [
1302 'class DummyClass;'
jbriance9e12f162016-11-25 07:57:501303 ])
1304 ]
1305 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1306 MockOutputApi())
1307 self.assertEqual(0, len(warnings))
1308
1309 def testNoNestedDeclaration(self):
1310 mock_input_api = MockInputApi()
1311 mock_input_api.files = [
1312 MockAffectedFile('somewhere/header.h', [
jbriance2c51e821a2016-12-12 08:24:311313 'class SomeClass {',
1314 ' protected:',
1315 ' class NotAMatch;',
jbriance9e12f162016-11-25 07:57:501316 '};'
1317 ])
1318 ]
1319 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1320 MockOutputApi())
1321 self.assertEqual(0, len(warnings))
1322
1323 def testSubStrings(self):
1324 mock_input_api = MockInputApi()
1325 mock_input_api.files = [
1326 MockAffectedFile('somewhere/header.h', [
1327 'class NotUsefulClass;',
1328 'struct SomeStruct;',
1329 'UsefulClass *p1;',
1330 'SomeStructPtr *p2;'
1331 ])
1332 ]
1333 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1334 MockOutputApi())
1335 self.assertEqual(2, len(warnings))
1336
1337 def testUselessForwardDeclaration(self):
1338 mock_input_api = MockInputApi()
1339 mock_input_api.files = [
1340 MockAffectedFile('somewhere/header.h', [
1341 'class DummyClass;',
1342 'struct DummyStruct;',
1343 'class UsefulClass;',
1344 'std::unique_ptr<UsefulClass> p;'
jbriance2c51e821a2016-12-12 08:24:311345 ])
jbriance9e12f162016-11-25 07:57:501346 ]
1347 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1348 MockOutputApi())
1349 self.assertEqual(2, len(warnings))
1350
jbriance2c51e821a2016-12-12 08:24:311351 def testBlinkHeaders(self):
1352 mock_input_api = MockInputApi()
1353 mock_input_api.files = [
1354 MockAffectedFile('third_party/WebKit/header.h', [
1355 'class DummyClass;',
1356 'struct DummyStruct;',
1357 ]),
1358 MockAffectedFile('third_party\\WebKit\\header.h', [
1359 'class DummyClass;',
1360 'struct DummyStruct;',
1361 ])
1362 ]
1363 warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api,
1364 MockOutputApi())
1365 self.assertEqual(4, len(warnings))
1366
jbriance9e12f162016-11-25 07:57:501367
dbeam1ec68ac2016-12-15 05:22:241368class RiskyJsTest(unittest.TestCase):
1369 def testArrowWarnInIos9Code(self):
1370 mock_input_api = MockInputApi()
1371 mock_output_api = MockOutputApi()
1372
1373 mock_input_api.files = [
1374 MockAffectedFile('components/blah.js', ["shouldn't use => here"]),
1375 ]
1376 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1377 mock_input_api, mock_output_api)
1378 self.assertEqual(1, len(warnings))
1379
1380 mock_input_api.files = [
1381 MockAffectedFile('ios/blee.js', ['might => break folks']),
1382 ]
1383 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1384 mock_input_api, mock_output_api)
1385 self.assertEqual(1, len(warnings))
1386
1387 mock_input_api.files = [
1388 MockAffectedFile('ui/webui/resources/blarg.js', ['on => iOS9']),
1389 ]
1390 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1391 mock_input_api, mock_output_api)
1392 self.assertEqual(1, len(warnings))
1393
1394 def testArrowsAllowedInChromeCode(self):
1395 mock_input_api = MockInputApi()
1396 mock_input_api.files = [
1397 MockAffectedFile('chrome/browser/resources/blah.js', 'arrow => OK here'),
1398 ]
1399 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1400 mock_input_api, MockOutputApi())
1401 self.assertEqual(0, len(warnings))
1402
dpapadd651231d82017-07-21 02:44:471403 def testConstLetWarningIos9Code(self):
1404 mock_input_api = MockInputApi()
1405 mock_output_api = MockOutputApi()
1406
1407 mock_input_api.files = [
1408 MockAffectedFile('components/blah.js', [" const foo = 'bar';"]),
1409 MockAffectedFile('ui/webui/resources/blah.js', [" let foo = 3;"]),
1410 ]
1411 warnings = PRESUBMIT._CheckForRiskyJsFeatures(
1412 mock_input_api, mock_output_api)
1413 self.assertEqual(2, len(warnings))
1414
rlanday6802cf632017-05-30 17:48:361415class RelativeIncludesTest(unittest.TestCase):
1416 def testThirdPartyNotWebKitIgnored(self):
1417 mock_input_api = MockInputApi()
1418 mock_input_api.files = [
1419 MockAffectedFile('third_party/test.cpp', '#include "../header.h"'),
1420 MockAffectedFile('third_party/test/test.cpp', '#include "../header.h"'),
1421 ]
1422
1423 mock_output_api = MockOutputApi()
1424
1425 errors = PRESUBMIT._CheckForRelativeIncludes(
1426 mock_input_api, mock_output_api)
1427 self.assertEqual(0, len(errors))
1428
1429 def testNonCppFileIgnored(self):
1430 mock_input_api = MockInputApi()
1431 mock_input_api.files = [
1432 MockAffectedFile('test.py', '#include "../header.h"'),
1433 ]
1434
1435 mock_output_api = MockOutputApi()
1436
1437 errors = PRESUBMIT._CheckForRelativeIncludes(
1438 mock_input_api, mock_output_api)
1439 self.assertEqual(0, len(errors))
1440
1441 def testInnocuousChangesAllowed(self):
1442 mock_input_api = MockInputApi()
1443 mock_input_api.files = [
1444 MockAffectedFile('test.cpp', '#include "header.h"'),
1445 MockAffectedFile('test2.cpp', '../'),
1446 ]
1447
1448 mock_output_api = MockOutputApi()
1449
1450 errors = PRESUBMIT._CheckForRelativeIncludes(
1451 mock_input_api, mock_output_api)
1452 self.assertEqual(0, len(errors))
1453
1454 def testRelativeIncludeNonWebKitProducesError(self):
1455 mock_input_api = MockInputApi()
1456 mock_input_api.files = [
1457 MockAffectedFile('test.cpp', ['#include "../header.h"']),
1458 ]
1459
1460 mock_output_api = MockOutputApi()
1461
1462 errors = PRESUBMIT._CheckForRelativeIncludes(
1463 mock_input_api, mock_output_api)
1464 self.assertEqual(1, len(errors))
1465
1466 def testRelativeIncludeWebKitProducesError(self):
1467 mock_input_api = MockInputApi()
1468 mock_input_api.files = [
1469 MockAffectedFile('third_party/WebKit/test.cpp',
1470 ['#include "../header.h']),
1471 ]
1472
1473 mock_output_api = MockOutputApi()
1474
1475 errors = PRESUBMIT._CheckForRelativeIncludes(
1476 mock_input_api, mock_output_api)
1477 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:241478
Daniel Cheng13ca61a882017-08-25 15:11:251479
1480class MojoManifestOwnerTest(unittest.TestCase):
1481 def testMojoManifestChangeNeedsSecurityOwner(self):
1482 mock_input_api = MockInputApi()
1483 mock_input_api.files = [
1484 MockAffectedFile('services/goat/manifest.json',
1485 [
1486 '{',
1487 ' "name": "teleporter",',
1488 ' "display_name": "Goat Teleporter",'
1489 ' "interface_provider_specs": {',
1490 ' }',
1491 '}',
1492 ])
1493 ]
1494 mock_output_api = MockOutputApi()
1495 errors = PRESUBMIT._CheckIpcOwners(
1496 mock_input_api, mock_output_api)
1497 self.assertEqual(1, len(errors))
1498 self.assertEqual(
1499 'Found OWNERS files that need to be updated for IPC security review ' +
1500 'coverage.\nPlease update the OWNERS files below:', errors[0].message)
1501
1502 # No warning if already covered by an OWNERS rule.
1503
1504 def testNonManifestChangesDoNotRequireSecurityOwner(self):
1505 mock_input_api = MockInputApi()
1506 mock_input_api.files = [
1507 MockAffectedFile('services/goat/species.json',
1508 [
1509 '[',
1510 ' "anglo-nubian",',
1511 ' "angora"',
1512 ']',
1513 ])
1514 ]
1515 mock_output_api = MockOutputApi()
1516 errors = PRESUBMIT._CheckIpcOwners(
1517 mock_input_api, mock_output_api)
1518 self.assertEqual([], errors)
1519
1520
Miguel Casas-Sancheze0d46d42017-12-14 15:52:191521class CrbugUrlFormatTest(unittest.TestCase):
1522
1523 def testCheckCrbugLinksHaveHttps(self):
1524 input_api = MockInputApi()
1525 input_api.files = [
1526 MockFile('somewhere/file.cc',
1527 ['// TODO(developer): crbug.com should be linkified',
1528 '// TODO(developer): (crbug.com) should be linkified',
1529 '// TODO(developer): crbug/123 should be well formed',
1530 '// TODO(developer): http://crbug.com it\'s OK',
Miguel Casas68bdb652017-12-19 16:29:091531 '// TODO(developer): https://crbug.com is just great',
1532 '// TODO(crbug.com/123456): this pattern it\'s also OK']),
Miguel Casas-Sancheze0d46d42017-12-14 15:52:191533 ]
1534
1535 warnings = PRESUBMIT._CheckCrbugLinksHaveHttps(input_api, MockOutputApi())
1536 self.assertEqual(1, len(warnings))
Miguel Casas68bdb652017-12-19 16:29:091537 self.assertEqual(3, warnings[0].message.count('\n'));
Miguel Casas-Sancheze0d46d42017-12-14 15:52:191538
1539
Sylvain Defresnea8b73d252018-02-28 15:45:541540class BannedFunctionCheckTest(unittest.TestCase):
1541
1542 def testBannedIosObcjFunctions(self):
1543 input_api = MockInputApi()
1544 input_api.files = [
1545 MockFile('some/ios/file.mm',
1546 ['TEST(SomeClassTest, SomeInteraction) {',
1547 '}']),
1548 MockFile('some/mac/file.mm',
1549 ['TEST(SomeClassTest, SomeInteraction) {',
1550 '}']),
1551 MockFile('another/ios_file.mm',
1552 ['class SomeTest : public testing::Test {};']),
1553 ]
1554
1555 errors = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi())
1556 self.assertEqual(1, len(errors))
1557 self.assertTrue('some/ios/file.mm' in errors[0].message)
1558 self.assertTrue('another/ios_file.mm' in errors[0].message)
1559 self.assertTrue('some/mac/file.mm' not in errors[0].message)
1560
1561
Vaclav Brozekf01ed502018-03-16 19:38:241562class NoProductionCodeUsingTestOnlyFunctions(unittest.TestCase):
1563 def testTruePositives(self):
1564 mock_input_api = MockInputApi()
1565 mock_input_api.files = [
1566 MockFile('some/path/foo.cc', ['foo_for_testing();']),
1567 MockFile('some/path/foo.mm', ['FooForTesting();']),
1568 MockFile('some/path/foo.cxx', ['FooForTests();']),
1569 MockFile('some/path/foo.cpp', ['foo_for_test();']),
1570 ]
1571
1572 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
1573 mock_input_api, MockOutputApi())
1574 self.assertEqual(1, len(results))
1575 self.assertEqual(4, len(results[0].items))
1576 self.assertTrue('foo.cc' in results[0].items[0])
1577 self.assertTrue('foo.mm' in results[0].items[1])
1578 self.assertTrue('foo.cxx' in results[0].items[2])
1579 self.assertTrue('foo.cpp' in results[0].items[3])
1580
1581 def testFalsePositives(self):
1582 mock_input_api = MockInputApi()
1583 mock_input_api.files = [
1584 MockFile('some/path/foo.h', ['foo_for_testing();']),
1585 MockFile('some/path/foo.mm', ['FooForTesting() {']),
1586 MockFile('some/path/foo.cc', ['::FooForTests();']),
1587 MockFile('some/path/foo.cpp', ['// foo_for_test();']),
1588 ]
1589
1590 results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
1591 mock_input_api, MockOutputApi())
1592 self.assertEqual(0, len(results))
1593
1594
[email protected]2299dcf2012-11-15 19:56:241595if __name__ == '__main__':
1596 unittest.main()