blob: 5aed7eed69dca09badbe94d1d3a217235e08dae1 [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
[email protected]99171a92014-06-03 08:44:476import glob
7import json
[email protected]2299dcf2012-11-15 19:56:248import os
9import re
[email protected]99171a92014-06-03 08:44:4710import subprocess
11import sys
[email protected]2299dcf2012-11-15 19:56:2412import unittest
13
14import PRESUBMIT
glidere61efad2015-02-18 17:39:4315from PRESUBMIT_test_mocks import MockChange, MockFile, MockAffectedFile
gayane3dff8c22014-12-04 17:09:5116from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi
[email protected]2299dcf2012-11-15 19:56:2417
[email protected]99171a92014-06-03 08:44:4718_TEST_DATA_DIR = 'base/test/data/presubmit'
19
[email protected]2299dcf2012-11-15 19:56:2420class IncludeOrderTest(unittest.TestCase):
21 def testSystemHeaderOrder(self):
22 scope = [(1, '#include <csystem.h>'),
23 (2, '#include <cppsystem>'),
24 (3, '#include "acustom.h"')]
25 all_linenums = [linenum for (linenum, _) in scope]
26 mock_input_api = MockInputApi()
27 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
28 '', all_linenums)
29 self.assertEqual(0, len(warnings))
30
31 def testSystemHeaderOrderMismatch1(self):
32 scope = [(10, '#include <cppsystem>'),
33 (20, '#include <csystem.h>'),
34 (30, '#include "acustom.h"')]
35 all_linenums = [linenum for (linenum, _) in scope]
36 mock_input_api = MockInputApi()
37 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
38 '', all_linenums)
39 self.assertEqual(1, len(warnings))
40 self.assertTrue('20' in warnings[0])
41
42 def testSystemHeaderOrderMismatch2(self):
43 scope = [(10, '#include <cppsystem>'),
44 (20, '#include "acustom.h"'),
45 (30, '#include <csystem.h>')]
46 all_linenums = [linenum for (linenum, _) in scope]
47 mock_input_api = MockInputApi()
48 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
49 '', all_linenums)
50 self.assertEqual(1, len(warnings))
51 self.assertTrue('30' in warnings[0])
52
53 def testSystemHeaderOrderMismatch3(self):
54 scope = [(10, '#include "acustom.h"'),
55 (20, '#include <csystem.h>'),
56 (30, '#include <cppsystem>')]
57 all_linenums = [linenum for (linenum, _) in scope]
58 mock_input_api = MockInputApi()
59 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
60 '', all_linenums)
61 self.assertEqual(2, len(warnings))
62 self.assertTrue('20' in warnings[0])
63 self.assertTrue('30' in warnings[1])
64
65 def testAlphabeticalOrderMismatch(self):
66 scope = [(10, '#include <csystem.h>'),
67 (15, '#include <bsystem.h>'),
68 (20, '#include <cppsystem>'),
69 (25, '#include <bppsystem>'),
70 (30, '#include "bcustom.h"'),
71 (35, '#include "acustom.h"')]
72 all_linenums = [linenum for (linenum, _) in scope]
73 mock_input_api = MockInputApi()
74 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
75 '', all_linenums)
76 self.assertEqual(3, len(warnings))
77 self.assertTrue('15' in warnings[0])
78 self.assertTrue('25' in warnings[1])
79 self.assertTrue('35' in warnings[2])
80
81 def testSpecialFirstInclude1(self):
82 mock_input_api = MockInputApi()
83 contents = ['#include "some/path/foo.h"',
84 '#include "a/header.h"']
85 mock_file = MockFile('some/path/foo.cc', contents)
86 warnings = PRESUBMIT._CheckIncludeOrderInFile(
[email protected]ac294a12012-12-06 16:38:4387 mock_input_api, mock_file, range(1, len(contents) + 1))
[email protected]2299dcf2012-11-15 19:56:2488 self.assertEqual(0, len(warnings))
89
90 def testSpecialFirstInclude2(self):
91 mock_input_api = MockInputApi()
92 contents = ['#include "some/other/path/foo.h"',
93 '#include "a/header.h"']
94 mock_file = MockFile('some/path/foo.cc', contents)
95 warnings = PRESUBMIT._CheckIncludeOrderInFile(
[email protected]ac294a12012-12-06 16:38:4396 mock_input_api, mock_file, range(1, len(contents) + 1))
[email protected]2299dcf2012-11-15 19:56:2497 self.assertEqual(0, len(warnings))
98
99 def testSpecialFirstInclude3(self):
100 mock_input_api = MockInputApi()
101 contents = ['#include "some/path/foo.h"',
102 '#include "a/header.h"']
103 mock_file = MockFile('some/path/foo_platform.cc', contents)
104 warnings = PRESUBMIT._CheckIncludeOrderInFile(
[email protected]ac294a12012-12-06 16:38:43105 mock_input_api, mock_file, range(1, len(contents) + 1))
[email protected]2299dcf2012-11-15 19:56:24106 self.assertEqual(0, len(warnings))
107
108 def testSpecialFirstInclude4(self):
109 mock_input_api = MockInputApi()
110 contents = ['#include "some/path/bar.h"',
111 '#include "a/header.h"']
112 mock_file = MockFile('some/path/foo_platform.cc', contents)
113 warnings = PRESUBMIT._CheckIncludeOrderInFile(
[email protected]ac294a12012-12-06 16:38:43114 mock_input_api, mock_file, range(1, len(contents) + 1))
[email protected]2299dcf2012-11-15 19:56:24115 self.assertEqual(1, len(warnings))
116 self.assertTrue('2' in warnings[0])
117
[email protected]ac294a12012-12-06 16:38:43118 def testSpecialFirstInclude5(self):
119 mock_input_api = MockInputApi()
120 contents = ['#include "some/other/path/foo.h"',
121 '#include "a/header.h"']
122 mock_file = MockFile('some/path/foo-suffix.h', contents)
123 warnings = PRESUBMIT._CheckIncludeOrderInFile(
124 mock_input_api, mock_file, range(1, len(contents) + 1))
125 self.assertEqual(0, len(warnings))
126
[email protected]3e83618c2013-10-09 22:32:33127 def testSpecialFirstInclude6(self):
128 mock_input_api = MockInputApi()
129 contents = ['#include "some/other/path/foo_win.h"',
130 '#include <set>',
131 '#include "a/header.h"']
132 mock_file = MockFile('some/path/foo_unittest_win.h', contents)
133 warnings = PRESUBMIT._CheckIncludeOrderInFile(
134 mock_input_api, mock_file, range(1, len(contents) + 1))
135 self.assertEqual(0, len(warnings))
136
[email protected]2299dcf2012-11-15 19:56:24137 def testOrderAlreadyWrong(self):
138 scope = [(1, '#include "b.h"'),
139 (2, '#include "a.h"'),
140 (3, '#include "c.h"')]
141 mock_input_api = MockInputApi()
142 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
143 '', [3])
144 self.assertEqual(0, len(warnings))
145
146 def testConflictAdded1(self):
147 scope = [(1, '#include "a.h"'),
148 (2, '#include "c.h"'),
149 (3, '#include "b.h"')]
150 mock_input_api = MockInputApi()
151 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
152 '', [2])
153 self.assertEqual(1, len(warnings))
154 self.assertTrue('3' in warnings[0])
155
156 def testConflictAdded2(self):
157 scope = [(1, '#include "c.h"'),
158 (2, '#include "b.h"'),
159 (3, '#include "d.h"')]
160 mock_input_api = MockInputApi()
161 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api,
162 '', [2])
163 self.assertEqual(1, len(warnings))
164 self.assertTrue('2' in warnings[0])
165
[email protected]2309b0fa02012-11-16 12:18:27166 def testIfElifElseEndif(self):
167 mock_input_api = MockInputApi()
168 contents = ['#include "e.h"',
[email protected]ac294a12012-12-06 16:38:43169 '#define foo',
170 '#include "f.h"',
171 '#undef foo',
172 '#include "e.h"',
[email protected]2309b0fa02012-11-16 12:18:27173 '#if foo',
174 '#include "d.h"',
175 '#elif bar',
176 '#include "c.h"',
177 '#else',
178 '#include "b.h"',
179 '#endif',
180 '#include "a.h"']
181 mock_file = MockFile('', contents)
182 warnings = PRESUBMIT._CheckIncludeOrderInFile(
[email protected]ac294a12012-12-06 16:38:43183 mock_input_api, mock_file, range(1, len(contents) + 1))
[email protected]2309b0fa02012-11-16 12:18:27184 self.assertEqual(0, len(warnings))
185
[email protected]23093b62013-09-20 12:16:30186 def testExcludedIncludes(self):
[email protected]962f117e2012-11-22 18:11:56187 # #include <sys/...>'s can appear in any order.
188 mock_input_api = MockInputApi()
189 contents = ['#include <sys/b.h>',
190 '#include <sys/a.h>']
191 mock_file = MockFile('', contents)
192 warnings = PRESUBMIT._CheckIncludeOrderInFile(
[email protected]ac294a12012-12-06 16:38:43193 mock_input_api, mock_file, range(1, len(contents) + 1))
[email protected]962f117e2012-11-22 18:11:56194 self.assertEqual(0, len(warnings))
195
[email protected]23093b62013-09-20 12:16:30196 contents = ['#include <atlbase.h>',
197 '#include <aaa.h>']
198 mock_file = MockFile('', contents)
199 warnings = PRESUBMIT._CheckIncludeOrderInFile(
200 mock_input_api, mock_file, range(1, len(contents) + 1))
201 self.assertEqual(0, len(warnings))
202
203 contents = ['#include "build/build_config.h"',
204 '#include "aaa.h"']
205 mock_file = MockFile('', contents)
206 warnings = PRESUBMIT._CheckIncludeOrderInFile(
207 mock_input_api, mock_file, range(1, len(contents) + 1))
208 self.assertEqual(0, len(warnings))
209
[email protected]ac294a12012-12-06 16:38:43210 def testCheckOnlyCFiles(self):
211 mock_input_api = MockInputApi()
212 mock_output_api = MockOutputApi()
213 contents = ['#include <b.h>',
214 '#include <a.h>']
215 mock_file_cc = MockFile('something.cc', contents)
216 mock_file_h = MockFile('something.h', contents)
217 mock_file_other = MockFile('something.py', contents)
218 mock_input_api.files = [mock_file_cc, mock_file_h, mock_file_other]
219 warnings = PRESUBMIT._CheckIncludeOrder(mock_input_api, mock_output_api)
220 self.assertEqual(1, len(warnings))
221 self.assertEqual(2, len(warnings[0].items))
[email protected]f7051d52013-04-02 18:31:42222 self.assertEqual('promptOrNotify', warnings[0].type)
[email protected]ac294a12012-12-06 16:38:43223
[email protected]0e5c1852012-12-18 20:17:11224 def testUncheckableIncludes(self):
225 mock_input_api = MockInputApi()
226 contents = ['#include <windows.h>',
[email protected]4436c9e2014-01-07 23:19:54227 '#include "b.h"',
[email protected]0e5c1852012-12-18 20:17:11228 '#include "a.h"']
229 mock_file = MockFile('', contents)
230 warnings = PRESUBMIT._CheckIncludeOrderInFile(
231 mock_input_api, mock_file, range(1, len(contents) + 1))
[email protected]4436c9e2014-01-07 23:19:54232 self.assertEqual(1, len(warnings))
[email protected]0e5c1852012-12-18 20:17:11233
234 contents = ['#include "gpu/command_buffer/gles_autogen.h"',
[email protected]4436c9e2014-01-07 23:19:54235 '#include "b.h"',
[email protected]0e5c1852012-12-18 20:17:11236 '#include "a.h"']
237 mock_file = MockFile('', contents)
238 warnings = PRESUBMIT._CheckIncludeOrderInFile(
239 mock_input_api, mock_file, range(1, len(contents) + 1))
[email protected]4436c9e2014-01-07 23:19:54240 self.assertEqual(1, len(warnings))
[email protected]0e5c1852012-12-18 20:17:11241
242 contents = ['#include "gl_mock_autogen.h"',
[email protected]4436c9e2014-01-07 23:19:54243 '#include "b.h"',
[email protected]0e5c1852012-12-18 20:17:11244 '#include "a.h"']
245 mock_file = MockFile('', contents)
246 warnings = PRESUBMIT._CheckIncludeOrderInFile(
247 mock_input_api, mock_file, range(1, len(contents) + 1))
[email protected]4436c9e2014-01-07 23:19:54248 self.assertEqual(1, len(warnings))
[email protected]0e5c1852012-12-18 20:17:11249
250 contents = ['#include "ipc/some_macros.h"',
[email protected]4436c9e2014-01-07 23:19:54251 '#include "b.h"',
[email protected]0e5c1852012-12-18 20:17:11252 '#include "a.h"']
253 mock_file = MockFile('', contents)
254 warnings = PRESUBMIT._CheckIncludeOrderInFile(
255 mock_input_api, mock_file, range(1, len(contents) + 1))
[email protected]4436c9e2014-01-07 23:19:54256 self.assertEqual(1, len(warnings))
[email protected]0e5c1852012-12-18 20:17:11257
[email protected]2299dcf2012-11-15 19:56:24258
[email protected]b00342e7f2013-03-26 16:21:54259class VersionControlConflictsTest(unittest.TestCase):
[email protected]70ca77752012-11-20 03:45:03260 def testTypicalConflict(self):
261 lines = ['<<<<<<< HEAD',
262 ' base::ScopedTempDir temp_dir_;',
263 '=======',
264 ' ScopedTempDir temp_dir_;',
265 '>>>>>>> master']
266 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
267 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
268 self.assertEqual(3, len(errors))
269 self.assertTrue('1' in errors[0])
270 self.assertTrue('3' in errors[1])
271 self.assertTrue('5' in errors[2])
272
dbeam95c35a2f2015-06-02 01:40:23273 def testIgnoresReadmes(self):
274 lines = ['A First Level Header',
275 '====================',
276 '',
277 'A Second Level Header',
278 '---------------------']
279 errors = PRESUBMIT._CheckForVersionControlConflictsInFile(
280 MockInputApi(), MockFile('some/polymer/README.md', lines))
281 self.assertEqual(0, len(errors))
282
mcasasb7440c282015-02-04 14:52:19283class UmaHistogramChangeMatchedOrNotTest(unittest.TestCase):
284 def testTypicalCorrectlyMatchedChange(self):
285 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
286 diff_xml = ['<histogram name="Bla.Foo.Dummy"> </histogram>']
287 mock_input_api = MockInputApi()
288 mock_input_api.files = [
289 MockFile('some/path/foo.cc', diff_cc),
290 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
291 ]
292 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
293 MockOutputApi())
294 self.assertEqual(0, len(warnings))
295
296 def testTypicalNotMatchedChange(self):
297 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
298 mock_input_api = MockInputApi()
299 mock_input_api.files = [MockFile('some/path/foo.cc', diff_cc)]
300 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
301 MockOutputApi())
302 self.assertEqual(1, len(warnings))
303 self.assertEqual('warning', warnings[0].type)
304
305 def testTypicalNotMatchedChangeViaSuffixes(self):
306 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
307 diff_xml = ['<histogram_suffixes name="SuperHistogram">',
308 ' <suffix name="Dummy"/>',
309 ' <affected-histogram name="Snafu.Dummy"/>',
310 '</histogram>']
311 mock_input_api = MockInputApi()
312 mock_input_api.files = [
313 MockFile('some/path/foo.cc', diff_cc),
314 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
315 ]
316 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
317 MockOutputApi())
318 self.assertEqual(1, len(warnings))
319 self.assertEqual('warning', warnings[0].type)
320
321 def testTypicalCorrectlyMatchedChangeViaSuffixes(self):
322 diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
323 diff_xml = ['<histogram_suffixes name="SuperHistogram">',
324 ' <suffix name="Dummy"/>',
325 ' <affected-histogram name="Bla.Foo"/>',
326 '</histogram>']
327 mock_input_api = MockInputApi()
328 mock_input_api.files = [
329 MockFile('some/path/foo.cc', diff_cc),
330 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
331 ]
332 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
333 MockOutputApi())
334 self.assertEqual(0, len(warnings))
335
336 def testTypicalCorrectlyMatchedChangeViaSuffixesWithSeparator(self):
337 diff_cc = ['UMA_HISTOGRAM_BOOL("Snafu_Dummy", true)']
338 diff_xml = ['<histogram_suffixes name="SuperHistogram" separator="_">',
339 ' <suffix name="Dummy"/>',
340 ' <affected-histogram name="Snafu"/>',
341 '</histogram>']
342 mock_input_api = MockInputApi()
343 mock_input_api.files = [
344 MockFile('some/path/foo.cc', diff_cc),
345 MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
346 ]
347 warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
348 MockOutputApi())
349 self.assertEqual(0, len(warnings))
[email protected]70ca77752012-11-20 03:45:03350
[email protected]b8079ae4a2012-12-05 19:56:49351class BadExtensionsTest(unittest.TestCase):
352 def testBadRejFile(self):
353 mock_input_api = MockInputApi()
354 mock_input_api.files = [
355 MockFile('some/path/foo.cc', ''),
356 MockFile('some/path/foo.cc.rej', ''),
357 MockFile('some/path2/bar.h.rej', ''),
358 ]
359
360 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
361 self.assertEqual(1, len(results))
362 self.assertEqual(2, len(results[0].items))
363 self.assertTrue('foo.cc.rej' in results[0].items[0])
364 self.assertTrue('bar.h.rej' in results[0].items[1])
365
366 def testBadOrigFile(self):
367 mock_input_api = MockInputApi()
368 mock_input_api.files = [
369 MockFile('other/path/qux.h.orig', ''),
370 MockFile('other/path/qux.h', ''),
371 MockFile('other/path/qux.cc', ''),
372 ]
373
374 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
375 self.assertEqual(1, len(results))
376 self.assertEqual(1, len(results[0].items))
377 self.assertTrue('qux.h.orig' in results[0].items[0])
378
379 def testGoodFiles(self):
380 mock_input_api = MockInputApi()
381 mock_input_api.files = [
382 MockFile('other/path/qux.h', ''),
383 MockFile('other/path/qux.cc', ''),
384 ]
385 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi())
386 self.assertEqual(0, len(results))
387
388
glidere61efad2015-02-18 17:39:43389class CheckSingletonInHeadersTest(unittest.TestCase):
390 def testSingletonInArbitraryHeader(self):
391 diff_singleton_h = ['base::subtle::AtomicWord '
olli.raula36aa8be2015-09-10 11:14:22392 'base::Singleton<Type, Traits, DifferentiatingType>::']
393 diff_foo_h = ['// base::Singleton<Foo> in comment.',
394 'friend class base::Singleton<Foo>']
oysteinec430ad42015-10-22 20:55:24395 diff_foo2_h = [' //Foo* bar = base::Singleton<Foo>::get();']
olli.raula36aa8be2015-09-10 11:14:22396 diff_bad_h = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43397 mock_input_api = MockInputApi()
398 mock_input_api.files = [MockAffectedFile('base/memory/singleton.h',
399 diff_singleton_h),
400 MockAffectedFile('foo.h', diff_foo_h),
oysteinec430ad42015-10-22 20:55:24401 MockAffectedFile('foo2.h', diff_foo2_h),
glidere61efad2015-02-18 17:39:43402 MockAffectedFile('bad.h', diff_bad_h)]
403 warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api,
404 MockOutputApi())
405 self.assertEqual(1, len(warnings))
oysteinec430ad42015-10-22 20:55:24406 self.assertEqual(2, len(warnings[0].items))
glidere61efad2015-02-18 17:39:43407 self.assertEqual('error', warnings[0].type)
olli.raula36aa8be2015-09-10 11:14:22408 self.assertTrue('Found base::Singleton<T>' in warnings[0].message)
glidere61efad2015-02-18 17:39:43409
410 def testSingletonInCC(self):
olli.raula36aa8be2015-09-10 11:14:22411 diff_cc = ['Foo* foo = base::Singleton<Foo>::get();']
glidere61efad2015-02-18 17:39:43412 mock_input_api = MockInputApi()
413 mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)]
414 warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api,
415 MockOutputApi())
416 self.assertEqual(0, len(warnings))
417
418
dbeam3aa38392015-10-16 21:38:03419class CheckBaseMacrosInHeadersTest(unittest.TestCase):
oysteinec430ad42015-10-22 20:55:24420 def _make_h(self, macro, header, line_prefix=''):
dbeam3aa38392015-10-16 21:38:03421 return ("""
422#include "base/%s.h"
423
424class Thing {
425 private:
oysteinec430ad42015-10-22 20:55:24426%sDISALLOW_%s(Thing);
dbeam3aa38392015-10-16 21:38:03427};
oysteinec430ad42015-10-22 20:55:24428""" % (macro, line_prefix, header)).splitlines()
dbeam3aa38392015-10-16 21:38:03429
430 def testBaseMacrosInHeadersBad(self):
431 mock_input_api = MockInputApi()
432 mock_input_api.files = [
433 MockAffectedFile('foo.h', self._make_h('not_macros', 'ASSIGN')),
434 MockAffectedFile('bar.h', self._make_h('not_macros', 'COPY')),
435 MockAffectedFile('baz.h', self._make_h('not_macros', 'COPY_AND_ASSIGN')),
436 MockAffectedFile('qux.h', self._make_h('not_macros', 'EVIL')),
437 ]
438 warnings = PRESUBMIT._CheckBaseMacrosInHeaders(mock_input_api,
439 MockOutputApi())
440 self.assertEqual(1, len(warnings))
441 self.assertEqual(4, len(warnings[0].items))
442
443 def testBaseMacrosInHeadersGood(self):
444 mock_input_api = MockInputApi()
445 mock_input_api.files = [
446 MockAffectedFile('foo.h', self._make_h('macros', 'ASSIGN')),
447 MockAffectedFile('bar.h', self._make_h('macros', 'COPY')),
448 MockAffectedFile('baz.h', self._make_h('macros', 'COPY_AND_ASSIGN')),
449 MockAffectedFile('qux.h', self._make_h('macros', 'EVIL')),
oysteinec430ad42015-10-22 20:55:24450 MockAffectedFile('foz.h', self._make_h('not_macros', 'ASSIGN', '//')),
451 MockAffectedFile('foz.h', self._make_h('not_macros', 'ASSIGN', ' //')),
dbeam3aa38392015-10-16 21:38:03452 ]
453 warnings = PRESUBMIT._CheckBaseMacrosInHeaders(mock_input_api,
454 MockOutputApi())
455 self.assertEqual(0, len(warnings))
456
457
[email protected]b00342e7f2013-03-26 16:21:54458class InvalidOSMacroNamesTest(unittest.TestCase):
459 def testInvalidOSMacroNames(self):
460 lines = ['#if defined(OS_WINDOWS)',
461 ' #elif defined(OS_WINDOW)',
462 ' # if defined(OS_MACOSX) || defined(OS_CHROME)',
463 '# else // defined(OS_MAC)',
464 '#endif // defined(OS_MACOS)']
465 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
466 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
467 self.assertEqual(len(lines), len(errors))
468 self.assertTrue(':1 OS_WINDOWS' in errors[0])
469 self.assertTrue('(did you mean OS_WIN?)' in errors[0])
470
471 def testValidOSMacroNames(self):
472 lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS]
473 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile(
474 MockInputApi(), MockFile('some/path/foo_platform.cc', lines))
475 self.assertEqual(0, len(errors))
476
477
lliabraa35bab3932014-10-01 12:16:44478class InvalidIfDefinedMacroNamesTest(unittest.TestCase):
479 def testInvalidIfDefinedMacroNames(self):
480 lines = ['#if defined(TARGET_IPHONE_SIMULATOR)',
481 '#if !defined(TARGET_IPHONE_SIMULATOR)',
482 '#elif defined(TARGET_IPHONE_SIMULATOR)',
483 '#ifdef TARGET_IPHONE_SIMULATOR',
484 ' # ifdef TARGET_IPHONE_SIMULATOR',
485 '# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
486 '# else // defined(TARGET_IPHONE_SIMULATOR)',
487 '#endif // defined(TARGET_IPHONE_SIMULATOR)',]
488 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
489 MockInputApi(), MockFile('some/path/source.mm', lines))
490 self.assertEqual(len(lines), len(errors))
491
492 def testValidIfDefinedMacroNames(self):
493 lines = ['#if defined(FOO)',
494 '#ifdef BAR',]
495 errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
496 MockInputApi(), MockFile('some/path/source.cc', lines))
497 self.assertEqual(0, len(errors))
498
499
[email protected]f32e2d1e2013-07-26 21:39:08500class CheckAddedDepsHaveTetsApprovalsTest(unittest.TestCase):
[email protected]14a6131c2014-01-08 01:15:41501 def testFilesToCheckForIncomingDeps(self):
[email protected]f32e2d1e2013-07-26 21:39:08502 changed_lines = [
503 '"+breakpad",',
504 '"+chrome/installer",',
505 '"+chrome/plugin/chrome_content_plugin_client.h",',
506 '"+chrome/utility/chrome_content_utility_client.h",',
507 '"+chromeos/chromeos_paths.h",',
dgn38736db2015-09-18 19:20:51508 '"+components/crash/content",',
[email protected]f32e2d1e2013-07-26 21:39:08509 '"+components/nacl/common",',
510 '"+content/public/browser/render_process_host.h",',
[email protected]14a6131c2014-01-08 01:15:41511 '"+jni/fooblat.h",',
[email protected]f32e2d1e2013-07-26 21:39:08512 '"+grit", # For generated headers',
513 '"+grit/generated_resources.h",',
514 '"+grit/",',
515 '"+policy", # For generated headers and source',
516 '"+sandbox",',
517 '"+tools/memory_watcher",',
518 '"+third_party/lss/linux_syscall_support.h",',
519 ]
[email protected]14a6131c2014-01-08 01:15:41520 files_to_check = PRESUBMIT._FilesToCheckForIncomingDeps(re, changed_lines)
[email protected]f32e2d1e2013-07-26 21:39:08521 expected = set([
522 'breakpad/DEPS',
523 'chrome/installer/DEPS',
[email protected]14a6131c2014-01-08 01:15:41524 'chrome/plugin/chrome_content_plugin_client.h',
525 'chrome/utility/chrome_content_utility_client.h',
526 'chromeos/chromeos_paths.h',
sdefresne8ba0b88c2015-09-18 10:33:13527 'components/crash/content/DEPS',
[email protected]f32e2d1e2013-07-26 21:39:08528 'components/nacl/common/DEPS',
[email protected]14a6131c2014-01-08 01:15:41529 'content/public/browser/render_process_host.h',
[email protected]f32e2d1e2013-07-26 21:39:08530 'policy/DEPS',
531 'sandbox/DEPS',
532 'tools/memory_watcher/DEPS',
[email protected]14a6131c2014-01-08 01:15:41533 'third_party/lss/linux_syscall_support.h',
[email protected]f32e2d1e2013-07-26 21:39:08534 ])
535 self.assertEqual(expected, files_to_check);
536
537
[email protected]99171a92014-06-03 08:44:47538class JSONParsingTest(unittest.TestCase):
539 def testSuccess(self):
540 input_api = MockInputApi()
541 filename = 'valid_json.json'
542 contents = ['// This is a comment.',
543 '{',
544 ' "key1": ["value1", "value2"],',
545 ' "key2": 3 // This is an inline comment.',
546 '}'
547 ]
548 input_api.files = [MockFile(filename, contents)]
549 self.assertEqual(None,
550 PRESUBMIT._GetJSONParseError(input_api, filename))
551
552 def testFailure(self):
553 input_api = MockInputApi()
554 test_data = [
555 ('invalid_json_1.json',
556 ['{ x }'],
[email protected]a3343272014-06-17 11:41:53557 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47558 ('invalid_json_2.json',
559 ['// Hello world!',
560 '{ "hello": "world }'],
[email protected]a3343272014-06-17 11:41:53561 'Unterminated string starting at:'),
[email protected]99171a92014-06-03 08:44:47562 ('invalid_json_3.json',
563 ['{ "a": "b", "c": "d", }'],
[email protected]a3343272014-06-17 11:41:53564 'Expecting property name:'),
[email protected]99171a92014-06-03 08:44:47565 ('invalid_json_4.json',
566 ['{ "a": "b" "c": "d" }'],
[email protected]a3343272014-06-17 11:41:53567 'Expecting , delimiter:'),
[email protected]99171a92014-06-03 08:44:47568 ]
569
570 input_api.files = [MockFile(filename, contents)
571 for (filename, contents, _) in test_data]
572
573 for (filename, _, expected_error) in test_data:
574 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename)
[email protected]a3343272014-06-17 11:41:53575 self.assertTrue(expected_error in str(actual_error),
576 "'%s' not found in '%s'" % (expected_error, actual_error))
[email protected]99171a92014-06-03 08:44:47577
578 def testNoEatComments(self):
579 input_api = MockInputApi()
580 file_with_comments = 'file_with_comments.json'
581 contents_with_comments = ['// This is a comment.',
582 '{',
583 ' "key1": ["value1", "value2"],',
584 ' "key2": 3 // This is an inline comment.',
585 '}'
586 ]
587 file_without_comments = 'file_without_comments.json'
588 contents_without_comments = ['{',
589 ' "key1": ["value1", "value2"],',
590 ' "key2": 3',
591 '}'
592 ]
593 input_api.files = [MockFile(file_with_comments, contents_with_comments),
594 MockFile(file_without_comments,
595 contents_without_comments)]
596
597 self.assertEqual('No JSON object could be decoded',
598 str(PRESUBMIT._GetJSONParseError(input_api,
599 file_with_comments,
600 eat_comments=False)))
601 self.assertEqual(None,
602 PRESUBMIT._GetJSONParseError(input_api,
603 file_without_comments,
604 eat_comments=False))
605
606
607class IDLParsingTest(unittest.TestCase):
608 def testSuccess(self):
609 input_api = MockInputApi()
610 filename = 'valid_idl_basics.idl'
611 contents = ['// Tests a valid IDL file.',
612 'namespace idl_basics {',
613 ' enum EnumType {',
614 ' name1,',
615 ' name2',
616 ' };',
617 '',
618 ' dictionary MyType1 {',
619 ' DOMString a;',
620 ' };',
621 '',
622 ' callback Callback1 = void();',
623 ' callback Callback2 = void(long x);',
624 ' callback Callback3 = void(MyType1 arg);',
625 ' callback Callback4 = void(EnumType type);',
626 '',
627 ' interface Functions {',
628 ' static void function1();',
629 ' static void function2(long x);',
630 ' static void function3(MyType1 arg);',
631 ' static void function4(Callback1 cb);',
632 ' static void function5(Callback2 cb);',
633 ' static void function6(Callback3 cb);',
634 ' static void function7(Callback4 cb);',
635 ' };',
636 '',
637 ' interface Events {',
638 ' static void onFoo1();',
639 ' static void onFoo2(long x);',
640 ' static void onFoo2(MyType1 arg);',
641 ' static void onFoo3(EnumType type);',
642 ' };',
643 '};'
644 ]
645 input_api.files = [MockFile(filename, contents)]
646 self.assertEqual(None,
647 PRESUBMIT._GetIDLParseError(input_api, filename))
648
649 def testFailure(self):
650 input_api = MockInputApi()
651 test_data = [
652 ('invalid_idl_1.idl',
653 ['//',
654 'namespace test {',
655 ' dictionary {',
656 ' DOMString s;',
657 ' };',
658 '};'],
659 'Unexpected "{" after keyword "dictionary".\n'),
660 # TODO(yoz): Disabled because it causes the IDL parser to hang.
661 # See crbug.com/363830.
662 # ('invalid_idl_2.idl',
663 # (['namespace test {',
664 # ' dictionary MissingSemicolon {',
665 # ' DOMString a',
666 # ' DOMString b;',
667 # ' };',
668 # '};'],
669 # 'Unexpected symbol DOMString after symbol a.'),
670 ('invalid_idl_3.idl',
671 ['//',
672 'namespace test {',
673 ' enum MissingComma {',
674 ' name1',
675 ' name2',
676 ' };',
677 '};'],
678 'Unexpected symbol name2 after symbol name1.'),
679 ('invalid_idl_4.idl',
680 ['//',
681 'namespace test {',
682 ' enum TrailingComma {',
683 ' name1,',
684 ' name2,',
685 ' };',
686 '};'],
687 'Trailing comma in block.'),
688 ('invalid_idl_5.idl',
689 ['//',
690 'namespace test {',
691 ' callback Callback1 = void(;',
692 '};'],
693 'Unexpected ";" after "(".'),
694 ('invalid_idl_6.idl',
695 ['//',
696 'namespace test {',
697 ' callback Callback1 = void(long );',
698 '};'],
699 'Unexpected ")" after symbol long.'),
700 ('invalid_idl_7.idl',
701 ['//',
702 'namespace test {',
703 ' interace Events {',
704 ' static void onFoo1();',
705 ' };',
706 '};'],
707 'Unexpected symbol Events after symbol interace.'),
708 ('invalid_idl_8.idl',
709 ['//',
710 'namespace test {',
711 ' interface NotEvent {',
712 ' static void onFoo1();',
713 ' };',
714 '};'],
715 'Did not process Interface Interface(NotEvent)'),
716 ('invalid_idl_9.idl',
717 ['//',
718 'namespace test {',
719 ' interface {',
720 ' static void function1();',
721 ' };',
722 '};'],
723 'Interface missing name.'),
724 ]
725
726 input_api.files = [MockFile(filename, contents)
727 for (filename, contents, _) in test_data]
728
729 for (filename, _, expected_error) in test_data:
730 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename)
731 self.assertTrue(expected_error in str(actual_error),
732 "'%s' not found in '%s'" % (expected_error, actual_error))
733
734
[email protected]0bb112362014-07-26 04:38:32735class TryServerMasterTest(unittest.TestCase):
736 def testTryServerMasters(self):
737 bots = {
[email protected]0bb112362014-07-26 04:38:32738 'tryserver.chromium.mac': [
739 'ios_dbg_simulator',
740 'ios_rel_device',
741 'ios_rel_device_ninja',
742 'mac_asan',
743 'mac_asan_64',
744 'mac_chromium_compile_dbg',
745 'mac_chromium_compile_rel',
746 'mac_chromium_dbg',
747 'mac_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32748 'mac_nacl_sdk',
749 'mac_nacl_sdk_build',
750 'mac_rel_naclmore',
751 'mac_valgrind',
752 'mac_x64_rel',
753 'mac_xcodebuild',
754 ],
755 'tryserver.chromium.linux': [
756 'android_aosp',
757 'android_chromium_gn_compile_dbg',
758 'android_chromium_gn_compile_rel',
759 'android_clang_dbg',
760 'android_dbg',
761 'android_dbg_recipe',
762 'android_dbg_triggered_tests',
763 'android_dbg_triggered_tests_recipe',
764 'android_fyi_dbg',
765 'android_fyi_dbg_triggered_tests',
766 'android_rel',
767 'android_rel_triggered_tests',
768 'android_x86_dbg',
769 'blink_android_compile_dbg',
770 'blink_android_compile_rel',
771 'blink_presubmit',
772 'chromium_presubmit',
773 'linux_arm_cross_compile',
774 'linux_arm_tester',
[email protected]0bb112362014-07-26 04:38:32775 'linux_chromeos_asan',
776 'linux_chromeos_browser_asan',
777 'linux_chromeos_valgrind',
[email protected]0bb112362014-07-26 04:38:32778 'linux_chromium_chromeos_dbg',
779 'linux_chromium_chromeos_rel',
[email protected]0bb112362014-07-26 04:38:32780 'linux_chromium_compile_dbg',
781 'linux_chromium_compile_rel',
782 'linux_chromium_dbg',
783 'linux_chromium_gn_dbg',
784 'linux_chromium_gn_rel',
785 'linux_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32786 'linux_chromium_trusty32_dbg',
787 'linux_chromium_trusty32_rel',
788 'linux_chromium_trusty_dbg',
789 'linux_chromium_trusty_rel',
790 'linux_clang_tsan',
791 'linux_ecs_ozone',
792 'linux_layout',
793 'linux_layout_asan',
794 'linux_layout_rel',
795 'linux_layout_rel_32',
796 'linux_nacl_sdk',
797 'linux_nacl_sdk_bionic',
798 'linux_nacl_sdk_bionic_build',
799 'linux_nacl_sdk_build',
800 'linux_redux',
801 'linux_rel_naclmore',
802 'linux_rel_precise32',
803 'linux_valgrind',
804 'tools_build_presubmit',
805 ],
806 'tryserver.chromium.win': [
807 'win8_aura',
808 'win8_chromium_dbg',
809 'win8_chromium_rel',
810 'win_chromium_compile_dbg',
811 'win_chromium_compile_rel',
812 'win_chromium_dbg',
813 'win_chromium_rel',
814 'win_chromium_rel',
[email protected]0bb112362014-07-26 04:38:32815 'win_chromium_x64_dbg',
816 'win_chromium_x64_rel',
817 'win_drmemory',
818 'win_nacl_sdk',
819 'win_nacl_sdk_build',
820 'win_rel_naclmore',
821 ],
822 }
823 for master, bots in bots.iteritems():
824 for bot in bots:
825 self.assertEqual(master, PRESUBMIT.GetTryServerMasterForBot(bot),
826 'bot=%s: expected %s, computed %s' % (
827 bot, master, PRESUBMIT.GetTryServerMasterForBot(bot)))
828
829
davileene0426252015-03-02 21:10:41830class UserMetricsActionTest(unittest.TestCase):
831 def testUserMetricsActionInActions(self):
832 input_api = MockInputApi()
833 file_with_user_action = 'file_with_user_action.cc'
834 contents_with_user_action = [
835 'base::UserMetricsAction("AboutChrome")'
836 ]
837
838 input_api.files = [MockFile(file_with_user_action,
839 contents_with_user_action)]
840
841 self.assertEqual(
842 [], PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi()))
843
844
845 def testUserMetricsActionNotAddedToActions(self):
846 input_api = MockInputApi()
847 file_with_user_action = 'file_with_user_action.cc'
848 contents_with_user_action = [
849 'base::UserMetricsAction("NotInActionsXml")'
850 ]
851
852 input_api.files = [MockFile(file_with_user_action,
853 contents_with_user_action)]
854
855 output = PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi())
856 self.assertEqual(
857 ('File %s line %d: %s is missing in '
858 'tools/metrics/actions/actions.xml. Please run '
859 'tools/metrics/actions/extract_actions.py to update.'
860 % (file_with_user_action, 1, 'NotInActionsXml')),
861 output[0].message)
862
863
dgn4401aa52015-04-29 16:26:17864class LogUsageTest(unittest.TestCase):
865
dgnaa68d5e2015-06-10 10:08:22866 def testCheckAndroidCrLogUsage(self):
867 mock_input_api = MockInputApi()
868 mock_output_api = MockOutputApi()
869
870 mock_input_api.files = [
871 MockAffectedFile('RandomStuff.java', [
872 'random stuff'
873 ]),
dgn87d9fb62015-06-12 09:15:12874 MockAffectedFile('HasAndroidLog.java', [
875 'import android.util.Log;',
876 'some random stuff',
877 'Log.d("TAG", "foo");',
878 ]),
879 MockAffectedFile('HasExplicitUtilLog.java', [
880 'some random stuff',
881 'android.util.Log.d("TAG", "foo");',
882 ]),
883 MockAffectedFile('IsInBasePackage.java', [
884 'package org.chromium.base;',
dgn38736db2015-09-18 19:20:51885 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:12886 'Log.d(TAG, "foo");',
887 ]),
888 MockAffectedFile('IsInBasePackageButImportsLog.java', [
889 'package org.chromium.base;',
890 'import android.util.Log;',
dgn38736db2015-09-18 19:20:51891 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:12892 'Log.d(TAG, "foo");',
893 ]),
894 MockAffectedFile('HasBothLog.java', [
895 'import org.chromium.base.Log;',
896 'some random stuff',
dgn38736db2015-09-18 19:20:51897 'private static final String TAG = "cr_Foo";',
dgn87d9fb62015-06-12 09:15:12898 'Log.d(TAG, "foo");',
899 'android.util.Log.d("TAG", "foo");',
900 ]),
dgnaa68d5e2015-06-10 10:08:22901 MockAffectedFile('HasCorrectTag.java', [
902 'import org.chromium.base.Log;',
903 'some random stuff',
dgn38736db2015-09-18 19:20:51904 'private static final String TAG = "cr_Foo";',
905 'Log.d(TAG, "foo");',
906 ]),
907 MockAffectedFile('HasOldTag.java', [
908 'import org.chromium.base.Log;',
909 'some random stuff',
dgnaa68d5e2015-06-10 10:08:22910 'private static final String TAG = "cr.Foo";',
911 'Log.d(TAG, "foo");',
912 ]),
dgn38736db2015-09-18 19:20:51913 MockAffectedFile('HasDottedTag.java', [
dgnaa68d5e2015-06-10 10:08:22914 'import org.chromium.base.Log;',
915 'some random stuff',
dgn38736db2015-09-18 19:20:51916 'private static final String TAG = "cr_foo.bar";',
dgnaa68d5e2015-06-10 10:08:22917 'Log.d(TAG, "foo");',
918 ]),
919 MockAffectedFile('HasNoTagDecl.java', [
920 'import org.chromium.base.Log;',
921 'some random stuff',
922 'Log.d(TAG, "foo");',
923 ]),
924 MockAffectedFile('HasIncorrectTagDecl.java', [
925 'import org.chromium.base.Log;',
dgn38736db2015-09-18 19:20:51926 'private static final String TAHG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:22927 'some random stuff',
928 'Log.d(TAG, "foo");',
929 ]),
930 MockAffectedFile('HasInlineTag.java', [
931 'import org.chromium.base.Log;',
932 'some random stuff',
dgn38736db2015-09-18 19:20:51933 'private static final String TAG = "cr_Foo";',
dgnaa68d5e2015-06-10 10:08:22934 'Log.d("TAG", "foo");',
935 ]),
dgn38736db2015-09-18 19:20:51936 MockAffectedFile('HasUnprefixedTag.java', [
dgnaa68d5e2015-06-10 10:08:22937 'import org.chromium.base.Log;',
938 'some random stuff',
939 'private static final String TAG = "rubbish";',
940 'Log.d(TAG, "foo");',
941 ]),
942 MockAffectedFile('HasTooLongTag.java', [
943 'import org.chromium.base.Log;',
944 'some random stuff',
dgn38736db2015-09-18 19:20:51945 'private static final String TAG = "21_charachers_long___";',
dgnaa68d5e2015-06-10 10:08:22946 'Log.d(TAG, "foo");',
947 ]),
948 ]
949
950 msgs = PRESUBMIT._CheckAndroidCrLogUsage(
951 mock_input_api, mock_output_api)
952
dgn38736db2015-09-18 19:20:51953 self.assertEqual(5, len(msgs),
954 'Expected %d items, found %d: %s' % (5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:22955
956 # Declaration format
dgn38736db2015-09-18 19:20:51957 nb = len(msgs[0].items)
958 self.assertEqual(2, nb,
959 'Expected %d items, found %d: %s' % (2, nb, msgs[0].items))
dgnaa68d5e2015-06-10 10:08:22960 self.assertTrue('HasNoTagDecl.java' in msgs[0].items)
961 self.assertTrue('HasIncorrectTagDecl.java' in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:22962
963 # Tag length
dgn38736db2015-09-18 19:20:51964 nb = len(msgs[1].items)
965 self.assertEqual(1, nb,
966 'Expected %d items, found %d: %s' % (1, nb, msgs[1].items))
dgnaa68d5e2015-06-10 10:08:22967 self.assertTrue('HasTooLongTag.java' in msgs[1].items)
968
969 # Tag must be a variable named TAG
dgn38736db2015-09-18 19:20:51970 nb = len(msgs[2].items)
971 self.assertEqual(1, nb,
972 'Expected %d items, found %d: %s' % (1, nb, msgs[2].items))
dgnaa68d5e2015-06-10 10:08:22973 self.assertTrue('HasInlineTag.java:4' in msgs[2].items)
974
dgn87d9fb62015-06-12 09:15:12975 # Util Log usage
dgn38736db2015-09-18 19:20:51976 nb = len(msgs[3].items)
977 self.assertEqual(2, nb,
978 'Expected %d items, found %d: %s' % (2, nb, msgs[3].items))
dgn87d9fb62015-06-12 09:15:12979 self.assertTrue('HasAndroidLog.java:3' in msgs[3].items)
980 self.assertTrue('IsInBasePackageButImportsLog.java:4' in msgs[3].items)
dgnaa68d5e2015-06-10 10:08:22981
dgn38736db2015-09-18 19:20:51982 # Tag must not contain
983 nb = len(msgs[4].items)
984 self.assertEqual(2, nb,
985 'Expected %d items, found %d: %s' % (2, nb, msgs[4].items))
986 self.assertTrue('HasDottedTag.java' in msgs[4].items)
987 self.assertTrue('HasOldTag.java' in msgs[4].items)
988
dgn4401aa52015-04-29 16:26:17989
[email protected]2299dcf2012-11-15 19:56:24990if __name__ == '__main__':
991 unittest.main()