|
1 #!/usr/bin/python |
|
2 # -*- coding: utf-8; -*- |
|
3 # |
|
4 # Copyright (C) 2009 Google Inc. All rights reserved. |
|
5 # Copyright (C) 2009 Torch Mobile Inc. |
|
6 # Copyright (C) 2009 Apple Inc. All rights reserved. |
|
7 # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org) |
|
8 # |
|
9 # Redistribution and use in source and binary forms, with or without |
|
10 # modification, are permitted provided that the following conditions are |
|
11 # met: |
|
12 # |
|
13 # * Redistributions of source code must retain the above copyright |
|
14 # notice, this list of conditions and the following disclaimer. |
|
15 # * Redistributions in binary form must reproduce the above |
|
16 # copyright notice, this list of conditions and the following disclaimer |
|
17 # in the documentation and/or other materials provided with the |
|
18 # distribution. |
|
19 # * Neither the name of Google Inc. nor the names of its |
|
20 # contributors may be used to endorse or promote products derived from |
|
21 # this software without specific prior written permission. |
|
22 # |
|
23 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
24 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
25 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
26 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
27 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
28 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
29 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
30 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
31 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
32 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
33 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
34 |
|
35 """Unit test for cpp_style.py.""" |
|
36 |
|
37 # FIXME: Add a good test that tests UpdateIncludeState. |
|
38 |
|
39 import codecs |
|
40 import os |
|
41 import random |
|
42 import re |
|
43 import unittest |
|
44 import cpp as cpp_style |
|
45 from cpp import CppChecker |
|
46 |
|
47 # This class works as an error collector and replaces cpp_style.Error |
|
48 # function for the unit tests. We also verify each category we see |
|
49 # is in STYLE_CATEGORIES, to help keep that list up to date. |
|
50 class ErrorCollector: |
|
51 _all_style_categories = CppChecker.categories |
|
52 # This is a list including all categories seen in any unit test. |
|
53 _seen_style_categories = {} |
|
54 |
|
55 def __init__(self, assert_fn): |
|
56 """assert_fn: a function to call when we notice a problem.""" |
|
57 self._assert_fn = assert_fn |
|
58 self._errors = [] |
|
59 |
|
60 def __call__(self, unused_linenum, category, confidence, message): |
|
61 self._assert_fn(category in self._all_style_categories, |
|
62 'Message "%s" has category "%s",' |
|
63 ' which is not in STYLE_CATEGORIES' % (message, category)) |
|
64 self._seen_style_categories[category] = 1 |
|
65 self._errors.append('%s [%s] [%d]' % (message, category, confidence)) |
|
66 |
|
67 def results(self): |
|
68 if len(self._errors) < 2: |
|
69 return ''.join(self._errors) # Most tests expect to have a string. |
|
70 else: |
|
71 return self._errors # Let's give a list if there is more than one. |
|
72 |
|
73 def result_list(self): |
|
74 return self._errors |
|
75 |
|
76 def verify_all_categories_are_seen(self): |
|
77 """Fails if there's a category in _all_style_categories - _seen_style_categories. |
|
78 |
|
79 This should only be called after all tests are run, so |
|
80 _seen_style_categories has had a chance to fully populate. Since |
|
81 this isn't called from within the normal unittest framework, we |
|
82 can't use the normal unittest assert macros. Instead we just exit |
|
83 when we see an error. Good thing this test is always run last! |
|
84 """ |
|
85 for category in self._all_style_categories: |
|
86 if category not in self._seen_style_categories: |
|
87 import sys |
|
88 sys.exit('FATAL ERROR: There are no tests for category "%s"' % category) |
|
89 |
|
90 def remove_if_present(self, substr): |
|
91 for (index, error) in enumerate(self._errors): |
|
92 if error.find(substr) != -1: |
|
93 self._errors = self._errors[0:index] + self._errors[(index + 1):] |
|
94 break |
|
95 |
|
96 |
|
97 # This class is a lame mock of codecs. We do not verify filename, mode, or |
|
98 # encoding, but for the current use case it is not needed. |
|
99 class MockIo: |
|
100 def __init__(self, mock_file): |
|
101 self.mock_file = mock_file |
|
102 |
|
103 def open(self, unused_filename, unused_mode, unused_encoding, _): # NOLINT |
|
104 # (lint doesn't like open as a method name) |
|
105 return self.mock_file |
|
106 |
|
107 |
|
108 class CppFunctionsTest(unittest.TestCase): |
|
109 |
|
110 """Supports testing functions that do not need CppStyleTestBase.""" |
|
111 |
|
112 def test_is_c_or_objective_c(self): |
|
113 self.assertTrue(cpp_style.is_c_or_objective_c("c")) |
|
114 self.assertTrue(cpp_style.is_c_or_objective_c("m")) |
|
115 self.assertFalse(cpp_style.is_c_or_objective_c("cpp")) |
|
116 |
|
117 |
|
118 class CppStyleTestBase(unittest.TestCase): |
|
119 """Provides some useful helper functions for cpp_style tests. |
|
120 |
|
121 Attributes: |
|
122 min_confidence: An integer that is the current minimum confidence |
|
123 level for the tests. |
|
124 |
|
125 """ |
|
126 |
|
127 # FIXME: Refactor the unit tests so the confidence level is passed |
|
128 # explicitly, just like it is in the real code. |
|
129 min_confidence = 1; |
|
130 |
|
131 # Helper function to avoid needing to explicitly pass confidence |
|
132 # in all the unit test calls to cpp_style.process_file_data(). |
|
133 def process_file_data(self, filename, file_extension, lines, error): |
|
134 """Call cpp_style.process_file_data() with the min_confidence.""" |
|
135 return cpp_style.process_file_data(filename, file_extension, lines, |
|
136 error, self.min_confidence) |
|
137 |
|
138 # Perform lint on single line of input and return the error message. |
|
139 def perform_single_line_lint(self, code, file_name): |
|
140 error_collector = ErrorCollector(self.assert_) |
|
141 lines = code.split('\n') |
|
142 cpp_style.remove_multi_line_comments(lines, error_collector) |
|
143 clean_lines = cpp_style.CleansedLines(lines) |
|
144 include_state = cpp_style._IncludeState() |
|
145 function_state = cpp_style._FunctionState(self.min_confidence) |
|
146 ext = file_name[file_name.rfind('.') + 1:] |
|
147 class_state = cpp_style._ClassState() |
|
148 file_state = cpp_style._FileState() |
|
149 cpp_style.process_line(file_name, ext, clean_lines, 0, |
|
150 include_state, function_state, |
|
151 class_state, file_state, error_collector) |
|
152 # Single-line lint tests are allowed to fail the 'unlintable function' |
|
153 # check. |
|
154 error_collector.remove_if_present( |
|
155 'Lint failed to find start of function body.') |
|
156 return error_collector.results() |
|
157 |
|
158 # Perform lint over multiple lines and return the error message. |
|
159 def perform_multi_line_lint(self, code, file_extension): |
|
160 error_collector = ErrorCollector(self.assert_) |
|
161 lines = code.split('\n') |
|
162 cpp_style.remove_multi_line_comments(lines, error_collector) |
|
163 lines = cpp_style.CleansedLines(lines) |
|
164 class_state = cpp_style._ClassState() |
|
165 file_state = cpp_style._FileState() |
|
166 for i in xrange(lines.num_lines()): |
|
167 cpp_style.check_style(lines, i, file_extension, file_state, error_collector) |
|
168 cpp_style.check_for_non_standard_constructs(lines, i, class_state, |
|
169 error_collector) |
|
170 class_state.check_finished(error_collector) |
|
171 return error_collector.results() |
|
172 |
|
173 # Similar to perform_multi_line_lint, but calls check_language instead of |
|
174 # check_for_non_standard_constructs |
|
175 def perform_language_rules_check(self, file_name, code): |
|
176 error_collector = ErrorCollector(self.assert_) |
|
177 include_state = cpp_style._IncludeState() |
|
178 lines = code.split('\n') |
|
179 cpp_style.remove_multi_line_comments(lines, error_collector) |
|
180 lines = cpp_style.CleansedLines(lines) |
|
181 ext = file_name[file_name.rfind('.') + 1:] |
|
182 for i in xrange(lines.num_lines()): |
|
183 cpp_style.check_language(file_name, lines, i, ext, include_state, |
|
184 error_collector) |
|
185 return error_collector.results() |
|
186 |
|
187 def perform_function_lengths_check(self, code): |
|
188 """Perform Lint function length check on block of code and return warnings. |
|
189 |
|
190 Builds up an array of lines corresponding to the code and strips comments |
|
191 using cpp_style functions. |
|
192 |
|
193 Establishes an error collector and invokes the function length checking |
|
194 function following cpp_style's pattern. |
|
195 |
|
196 Args: |
|
197 code: C++ source code expected to generate a warning message. |
|
198 |
|
199 Returns: |
|
200 The accumulated errors. |
|
201 """ |
|
202 error_collector = ErrorCollector(self.assert_) |
|
203 function_state = cpp_style._FunctionState(self.min_confidence) |
|
204 lines = code.split('\n') |
|
205 cpp_style.remove_multi_line_comments(lines, error_collector) |
|
206 lines = cpp_style.CleansedLines(lines) |
|
207 for i in xrange(lines.num_lines()): |
|
208 cpp_style.check_for_function_lengths(lines, i, |
|
209 function_state, error_collector) |
|
210 return error_collector.results() |
|
211 |
|
212 def perform_include_what_you_use(self, code, filename='foo.h', io=codecs): |
|
213 # First, build up the include state. |
|
214 error_collector = ErrorCollector(self.assert_) |
|
215 include_state = cpp_style._IncludeState() |
|
216 lines = code.split('\n') |
|
217 cpp_style.remove_multi_line_comments(lines, error_collector) |
|
218 lines = cpp_style.CleansedLines(lines) |
|
219 file_extension = filename[filename.rfind('.') + 1:] |
|
220 for i in xrange(lines.num_lines()): |
|
221 cpp_style.check_language(filename, lines, i, file_extension, include_state, |
|
222 error_collector) |
|
223 # We could clear the error_collector here, but this should |
|
224 # also be fine, since our IncludeWhatYouUse unittests do not |
|
225 # have language problems. |
|
226 |
|
227 # Second, look for missing includes. |
|
228 cpp_style.check_for_include_what_you_use(filename, lines, include_state, |
|
229 error_collector, io) |
|
230 return error_collector.results() |
|
231 |
|
232 # Perform lint and compare the error message with "expected_message". |
|
233 def assert_lint(self, code, expected_message, file_name='foo.cpp'): |
|
234 self.assertEquals(expected_message, self.perform_single_line_lint(code, file_name)) |
|
235 |
|
236 def assert_lint_one_of_many_errors_re(self, code, expected_message_re, file_name='foo.cpp'): |
|
237 messages = self.perform_single_line_lint(code, file_name) |
|
238 for message in messages: |
|
239 if re.search(expected_message_re, message): |
|
240 return |
|
241 |
|
242 self.assertEquals(expected_message_re, messages) |
|
243 |
|
244 def assert_multi_line_lint(self, code, expected_message, file_name='foo.h'): |
|
245 file_extension = file_name[file_name.rfind('.') + 1:] |
|
246 self.assertEquals(expected_message, self.perform_multi_line_lint(code, file_extension)) |
|
247 |
|
248 def assert_multi_line_lint_re(self, code, expected_message_re, file_name='foo.h'): |
|
249 file_extension = file_name[file_name.rfind('.') + 1:] |
|
250 message = self.perform_multi_line_lint(code, file_extension) |
|
251 if not re.search(expected_message_re, message): |
|
252 self.fail('Message was:\n' + message + 'Expected match to "' + expected_message_re + '"') |
|
253 |
|
254 def assert_language_rules_check(self, file_name, code, expected_message): |
|
255 self.assertEquals(expected_message, |
|
256 self.perform_language_rules_check(file_name, code)) |
|
257 |
|
258 def assert_include_what_you_use(self, code, expected_message): |
|
259 self.assertEquals(expected_message, |
|
260 self.perform_include_what_you_use(code)) |
|
261 |
|
262 def assert_blank_lines_check(self, lines, start_errors, end_errors): |
|
263 error_collector = ErrorCollector(self.assert_) |
|
264 self.process_file_data('foo.cpp', 'cpp', lines, error_collector) |
|
265 self.assertEquals( |
|
266 start_errors, |
|
267 error_collector.results().count( |
|
268 'Blank line at the start of a code block. Is this needed?' |
|
269 ' [whitespace/blank_line] [2]')) |
|
270 self.assertEquals( |
|
271 end_errors, |
|
272 error_collector.results().count( |
|
273 'Blank line at the end of a code block. Is this needed?' |
|
274 ' [whitespace/blank_line] [3]')) |
|
275 |
|
276 |
|
277 class CppStyleTest(CppStyleTestBase): |
|
278 |
|
279 # Test get line width. |
|
280 def test_get_line_width(self): |
|
281 self.assertEquals(0, cpp_style.get_line_width('')) |
|
282 self.assertEquals(10, cpp_style.get_line_width(u'x' * 10)) |
|
283 self.assertEquals(16, cpp_style.get_line_width(u'都|道|府|県|支庁')) |
|
284 |
|
285 def test_find_next_multi_line_comment_start(self): |
|
286 self.assertEquals(1, cpp_style.find_next_multi_line_comment_start([''], 0)) |
|
287 |
|
288 lines = ['a', 'b', '/* c'] |
|
289 self.assertEquals(2, cpp_style.find_next_multi_line_comment_start(lines, 0)) |
|
290 |
|
291 lines = ['char a[] = "/*";'] # not recognized as comment. |
|
292 self.assertEquals(1, cpp_style.find_next_multi_line_comment_start(lines, 0)) |
|
293 |
|
294 def test_find_next_multi_line_comment_end(self): |
|
295 self.assertEquals(1, cpp_style.find_next_multi_line_comment_end([''], 0)) |
|
296 lines = ['a', 'b', ' c */'] |
|
297 self.assertEquals(2, cpp_style.find_next_multi_line_comment_end(lines, 0)) |
|
298 |
|
299 def test_remove_multi_line_comments_from_range(self): |
|
300 lines = ['a', ' /* comment ', ' * still comment', ' comment */ ', 'b'] |
|
301 cpp_style.remove_multi_line_comments_from_range(lines, 1, 4) |
|
302 self.assertEquals(['a', '// dummy', '// dummy', '// dummy', 'b'], lines) |
|
303 |
|
304 def test_spaces_at_end_of_line(self): |
|
305 self.assert_lint( |
|
306 '// Hello there ', |
|
307 'Line ends in whitespace. Consider deleting these extra spaces.' |
|
308 ' [whitespace/end_of_line] [4]') |
|
309 |
|
310 # Test C-style cast cases. |
|
311 def test_cstyle_cast(self): |
|
312 self.assert_lint( |
|
313 'int a = (int)1.0;', |
|
314 'Using C-style cast. Use static_cast<int>(...) instead' |
|
315 ' [readability/casting] [4]') |
|
316 self.assert_lint( |
|
317 'int *a = (int *)DEFINED_VALUE;', |
|
318 'Using C-style cast. Use reinterpret_cast<int *>(...) instead' |
|
319 ' [readability/casting] [4]', 'foo.c') |
|
320 self.assert_lint( |
|
321 'uint16 a = (uint16)1.0;', |
|
322 'Using C-style cast. Use static_cast<uint16>(...) instead' |
|
323 ' [readability/casting] [4]') |
|
324 self.assert_lint( |
|
325 'int32 a = (int32)1.0;', |
|
326 'Using C-style cast. Use static_cast<int32>(...) instead' |
|
327 ' [readability/casting] [4]') |
|
328 self.assert_lint( |
|
329 'uint64 a = (uint64)1.0;', |
|
330 'Using C-style cast. Use static_cast<uint64>(...) instead' |
|
331 ' [readability/casting] [4]') |
|
332 |
|
333 # Test taking address of casts (runtime/casting) |
|
334 def test_runtime_casting(self): |
|
335 self.assert_lint( |
|
336 'int* x = &static_cast<int*>(foo);', |
|
337 'Are you taking an address of a cast? ' |
|
338 'This is dangerous: could be a temp var. ' |
|
339 'Take the address before doing the cast, rather than after' |
|
340 ' [runtime/casting] [4]') |
|
341 |
|
342 self.assert_lint( |
|
343 'int* x = &dynamic_cast<int *>(foo);', |
|
344 ['Are you taking an address of a cast? ' |
|
345 'This is dangerous: could be a temp var. ' |
|
346 'Take the address before doing the cast, rather than after' |
|
347 ' [runtime/casting] [4]', |
|
348 'Do not use dynamic_cast<>. If you need to cast within a class ' |
|
349 'hierarchy, use static_cast<> to upcast. Google doesn\'t support ' |
|
350 'RTTI. [runtime/rtti] [5]']) |
|
351 |
|
352 self.assert_lint( |
|
353 'int* x = &reinterpret_cast<int *>(foo);', |
|
354 'Are you taking an address of a cast? ' |
|
355 'This is dangerous: could be a temp var. ' |
|
356 'Take the address before doing the cast, rather than after' |
|
357 ' [runtime/casting] [4]') |
|
358 |
|
359 # It's OK to cast an address. |
|
360 self.assert_lint( |
|
361 'int* x = reinterpret_cast<int *>(&foo);', |
|
362 '') |
|
363 |
|
364 def test_runtime_selfinit(self): |
|
365 self.assert_lint( |
|
366 'Foo::Foo(Bar r, Bel l) : r_(r_), l_(l_) { }', |
|
367 'You seem to be initializing a member variable with itself.' |
|
368 ' [runtime/init] [4]') |
|
369 self.assert_lint( |
|
370 'Foo::Foo(Bar r, Bel l) : r_(r), l_(l) { }', |
|
371 '') |
|
372 self.assert_lint( |
|
373 'Foo::Foo(Bar r) : r_(r), l_(r_), ll_(l_) { }', |
|
374 '') |
|
375 |
|
376 def test_runtime_rtti(self): |
|
377 statement = 'int* x = dynamic_cast<int*>(&foo);' |
|
378 error_message = ( |
|
379 'Do not use dynamic_cast<>. If you need to cast within a class ' |
|
380 'hierarchy, use static_cast<> to upcast. Google doesn\'t support ' |
|
381 'RTTI. [runtime/rtti] [5]') |
|
382 # dynamic_cast is disallowed in most files. |
|
383 self.assert_language_rules_check('foo.cpp', statement, error_message) |
|
384 self.assert_language_rules_check('foo.h', statement, error_message) |
|
385 |
|
386 # We cannot test this functionality because of difference of |
|
387 # function definitions. Anyway, we may never enable this. |
|
388 # |
|
389 # # Test for unnamed arguments in a method. |
|
390 # def test_check_for_unnamed_params(self): |
|
391 # message = ('All parameters should be named in a function' |
|
392 # ' [readability/function] [3]') |
|
393 # self.assert_lint('virtual void A(int*) const;', message) |
|
394 # self.assert_lint('virtual void B(void (*fn)(int*));', message) |
|
395 # self.assert_lint('virtual void C(int*);', message) |
|
396 # self.assert_lint('void *(*f)(void *) = x;', message) |
|
397 # self.assert_lint('void Method(char*) {', message) |
|
398 # self.assert_lint('void Method(char*);', message) |
|
399 # self.assert_lint('void Method(char* /*x*/);', message) |
|
400 # self.assert_lint('typedef void (*Method)(int32);', message) |
|
401 # self.assert_lint('static void operator delete[](void*) throw();', message) |
|
402 # |
|
403 # self.assert_lint('virtual void D(int* p);', '') |
|
404 # self.assert_lint('void operator delete(void* x) throw();', '') |
|
405 # self.assert_lint('void Method(char* x)\n{', '') |
|
406 # self.assert_lint('void Method(char* /*x*/)\n{', '') |
|
407 # self.assert_lint('void Method(char* x);', '') |
|
408 # self.assert_lint('typedef void (*Method)(int32 x);', '') |
|
409 # self.assert_lint('static void operator delete[](void* x) throw();', '') |
|
410 # self.assert_lint('static void operator delete[](void* /*x*/) throw();', '') |
|
411 # |
|
412 # # This one should technically warn, but doesn't because the function |
|
413 # # pointer is confusing. |
|
414 # self.assert_lint('virtual void E(void (*fn)(int* p));', '') |
|
415 |
|
416 # Test deprecated casts such as int(d) |
|
417 def test_deprecated_cast(self): |
|
418 self.assert_lint( |
|
419 'int a = int(2.2);', |
|
420 'Using deprecated casting style. ' |
|
421 'Use static_cast<int>(...) instead' |
|
422 ' [readability/casting] [4]') |
|
423 # Checks for false positives... |
|
424 self.assert_lint( |
|
425 'int a = int(); // Constructor, o.k.', |
|
426 '') |
|
427 self.assert_lint( |
|
428 'X::X() : a(int()) {} // default Constructor, o.k.', |
|
429 '') |
|
430 self.assert_lint( |
|
431 'operator bool(); // Conversion operator, o.k.', |
|
432 '') |
|
433 |
|
434 # The second parameter to a gMock method definition is a function signature |
|
435 # that often looks like a bad cast but should not picked up by lint. |
|
436 def test_mock_method(self): |
|
437 self.assert_lint( |
|
438 'MOCK_METHOD0(method, int());', |
|
439 '') |
|
440 self.assert_lint( |
|
441 'MOCK_CONST_METHOD1(method, float(string));', |
|
442 '') |
|
443 self.assert_lint( |
|
444 'MOCK_CONST_METHOD2_T(method, double(float, float));', |
|
445 '') |
|
446 |
|
447 # Test sizeof(type) cases. |
|
448 def test_sizeof_type(self): |
|
449 self.assert_lint( |
|
450 'sizeof(int);', |
|
451 'Using sizeof(type). Use sizeof(varname) instead if possible' |
|
452 ' [runtime/sizeof] [1]') |
|
453 self.assert_lint( |
|
454 'sizeof(int *);', |
|
455 'Using sizeof(type). Use sizeof(varname) instead if possible' |
|
456 ' [runtime/sizeof] [1]') |
|
457 |
|
458 # Test typedef cases. There was a bug that cpp_style misidentified |
|
459 # typedef for pointer to function as C-style cast and produced |
|
460 # false-positive error messages. |
|
461 def test_typedef_for_pointer_to_function(self): |
|
462 self.assert_lint( |
|
463 'typedef void (*Func)(int x);', |
|
464 '') |
|
465 self.assert_lint( |
|
466 'typedef void (*Func)(int *x);', |
|
467 '') |
|
468 self.assert_lint( |
|
469 'typedef void Func(int x);', |
|
470 '') |
|
471 self.assert_lint( |
|
472 'typedef void Func(int *x);', |
|
473 '') |
|
474 |
|
475 def test_include_what_you_use_no_implementation_files(self): |
|
476 code = 'std::vector<int> foo;' |
|
477 self.assertEquals('Add #include <vector> for vector<>' |
|
478 ' [build/include_what_you_use] [4]', |
|
479 self.perform_include_what_you_use(code, 'foo.h')) |
|
480 self.assertEquals('', |
|
481 self.perform_include_what_you_use(code, 'foo.cpp')) |
|
482 |
|
483 def test_include_what_you_use(self): |
|
484 self.assert_include_what_you_use( |
|
485 '''#include <vector> |
|
486 std::vector<int> foo; |
|
487 ''', |
|
488 '') |
|
489 self.assert_include_what_you_use( |
|
490 '''#include <map> |
|
491 std::pair<int,int> foo; |
|
492 ''', |
|
493 '') |
|
494 self.assert_include_what_you_use( |
|
495 '''#include <multimap> |
|
496 std::pair<int,int> foo; |
|
497 ''', |
|
498 '') |
|
499 self.assert_include_what_you_use( |
|
500 '''#include <hash_map> |
|
501 std::pair<int,int> foo; |
|
502 ''', |
|
503 '') |
|
504 self.assert_include_what_you_use( |
|
505 '''#include <utility> |
|
506 std::pair<int,int> foo; |
|
507 ''', |
|
508 '') |
|
509 self.assert_include_what_you_use( |
|
510 '''#include <vector> |
|
511 DECLARE_string(foobar); |
|
512 ''', |
|
513 '') |
|
514 self.assert_include_what_you_use( |
|
515 '''#include <vector> |
|
516 DEFINE_string(foobar, "", ""); |
|
517 ''', |
|
518 '') |
|
519 self.assert_include_what_you_use( |
|
520 '''#include <vector> |
|
521 std::pair<int,int> foo; |
|
522 ''', |
|
523 'Add #include <utility> for pair<>' |
|
524 ' [build/include_what_you_use] [4]') |
|
525 self.assert_include_what_you_use( |
|
526 '''#include "base/foobar.h" |
|
527 std::vector<int> foo; |
|
528 ''', |
|
529 'Add #include <vector> for vector<>' |
|
530 ' [build/include_what_you_use] [4]') |
|
531 self.assert_include_what_you_use( |
|
532 '''#include <vector> |
|
533 std::set<int> foo; |
|
534 ''', |
|
535 'Add #include <set> for set<>' |
|
536 ' [build/include_what_you_use] [4]') |
|
537 self.assert_include_what_you_use( |
|
538 '''#include "base/foobar.h" |
|
539 hash_map<int, int> foobar; |
|
540 ''', |
|
541 'Add #include <hash_map> for hash_map<>' |
|
542 ' [build/include_what_you_use] [4]') |
|
543 self.assert_include_what_you_use( |
|
544 '''#include "base/foobar.h" |
|
545 bool foobar = std::less<int>(0,1); |
|
546 ''', |
|
547 'Add #include <functional> for less<>' |
|
548 ' [build/include_what_you_use] [4]') |
|
549 self.assert_include_what_you_use( |
|
550 '''#include "base/foobar.h" |
|
551 bool foobar = min<int>(0,1); |
|
552 ''', |
|
553 'Add #include <algorithm> for min [build/include_what_you_use] [4]') |
|
554 self.assert_include_what_you_use( |
|
555 'void a(const string &foobar);', |
|
556 'Add #include <string> for string [build/include_what_you_use] [4]') |
|
557 self.assert_include_what_you_use( |
|
558 '''#include "base/foobar.h" |
|
559 bool foobar = swap(0,1); |
|
560 ''', |
|
561 'Add #include <algorithm> for swap [build/include_what_you_use] [4]') |
|
562 self.assert_include_what_you_use( |
|
563 '''#include "base/foobar.h" |
|
564 bool foobar = transform(a.begin(), a.end(), b.start(), Foo); |
|
565 ''', |
|
566 'Add #include <algorithm> for transform ' |
|
567 '[build/include_what_you_use] [4]') |
|
568 self.assert_include_what_you_use( |
|
569 '''#include "base/foobar.h" |
|
570 bool foobar = min_element(a.begin(), a.end()); |
|
571 ''', |
|
572 'Add #include <algorithm> for min_element ' |
|
573 '[build/include_what_you_use] [4]') |
|
574 self.assert_include_what_you_use( |
|
575 '''foo->swap(0,1); |
|
576 foo.swap(0,1); |
|
577 ''', |
|
578 '') |
|
579 self.assert_include_what_you_use( |
|
580 '''#include <string> |
|
581 void a(const std::multimap<int,string> &foobar); |
|
582 ''', |
|
583 'Add #include <map> for multimap<>' |
|
584 ' [build/include_what_you_use] [4]') |
|
585 self.assert_include_what_you_use( |
|
586 '''#include <queue> |
|
587 void a(const std::priority_queue<int> &foobar); |
|
588 ''', |
|
589 '') |
|
590 self.assert_include_what_you_use( |
|
591 '''#include "base/basictypes.h" |
|
592 #include "base/port.h" |
|
593 #include <assert.h> |
|
594 #include <string> |
|
595 #include <vector> |
|
596 vector<string> hajoa;''', '') |
|
597 self.assert_include_what_you_use( |
|
598 '''#include <string> |
|
599 int i = numeric_limits<int>::max() |
|
600 ''', |
|
601 'Add #include <limits> for numeric_limits<>' |
|
602 ' [build/include_what_you_use] [4]') |
|
603 self.assert_include_what_you_use( |
|
604 '''#include <limits> |
|
605 int i = numeric_limits<int>::max() |
|
606 ''', |
|
607 '') |
|
608 |
|
609 # Test the UpdateIncludeState code path. |
|
610 mock_header_contents = ['#include "blah/foo.h"', '#include "blah/bar.h"'] |
|
611 message = self.perform_include_what_you_use( |
|
612 '#include "config.h"\n' |
|
613 '#include "blah/a.h"\n', |
|
614 filename='blah/a.cpp', |
|
615 io=MockIo(mock_header_contents)) |
|
616 self.assertEquals(message, '') |
|
617 |
|
618 mock_header_contents = ['#include <set>'] |
|
619 message = self.perform_include_what_you_use( |
|
620 '''#include "config.h" |
|
621 #include "blah/a.h" |
|
622 |
|
623 std::set<int> foo;''', |
|
624 filename='blah/a.cpp', |
|
625 io=MockIo(mock_header_contents)) |
|
626 self.assertEquals(message, '') |
|
627 |
|
628 # If there's just a .cpp and the header can't be found then it's ok. |
|
629 message = self.perform_include_what_you_use( |
|
630 '''#include "config.h" |
|
631 #include "blah/a.h" |
|
632 |
|
633 std::set<int> foo;''', |
|
634 filename='blah/a.cpp') |
|
635 self.assertEquals(message, '') |
|
636 |
|
637 # Make sure we find the headers with relative paths. |
|
638 mock_header_contents = [''] |
|
639 message = self.perform_include_what_you_use( |
|
640 '''#include "config.h" |
|
641 #include "%s/a.h" |
|
642 |
|
643 std::set<int> foo;''' % os.path.basename(os.getcwd()), |
|
644 filename='a.cpp', |
|
645 io=MockIo(mock_header_contents)) |
|
646 self.assertEquals(message, 'Add #include <set> for set<> ' |
|
647 '[build/include_what_you_use] [4]') |
|
648 |
|
649 def test_files_belong_to_same_module(self): |
|
650 f = cpp_style.files_belong_to_same_module |
|
651 self.assertEquals((True, ''), f('a.cpp', 'a.h')) |
|
652 self.assertEquals((True, ''), f('base/google.cpp', 'base/google.h')) |
|
653 self.assertEquals((True, ''), f('base/google_test.cpp', 'base/google.h')) |
|
654 self.assertEquals((True, ''), |
|
655 f('base/google_unittest.cpp', 'base/google.h')) |
|
656 self.assertEquals((True, ''), |
|
657 f('base/internal/google_unittest.cpp', |
|
658 'base/public/google.h')) |
|
659 self.assertEquals((True, 'xxx/yyy/'), |
|
660 f('xxx/yyy/base/internal/google_unittest.cpp', |
|
661 'base/public/google.h')) |
|
662 self.assertEquals((True, 'xxx/yyy/'), |
|
663 f('xxx/yyy/base/google_unittest.cpp', |
|
664 'base/public/google.h')) |
|
665 self.assertEquals((True, ''), |
|
666 f('base/google_unittest.cpp', 'base/google-inl.h')) |
|
667 self.assertEquals((True, '/home/build/google3/'), |
|
668 f('/home/build/google3/base/google.cpp', 'base/google.h')) |
|
669 |
|
670 self.assertEquals((False, ''), |
|
671 f('/home/build/google3/base/google.cpp', 'basu/google.h')) |
|
672 self.assertEquals((False, ''), f('a.cpp', 'b.h')) |
|
673 |
|
674 def test_cleanse_line(self): |
|
675 self.assertEquals('int foo = 0; ', |
|
676 cpp_style.cleanse_comments('int foo = 0; // danger!')) |
|
677 self.assertEquals('int o = 0;', |
|
678 cpp_style.cleanse_comments('int /* foo */ o = 0;')) |
|
679 self.assertEquals('foo(int a, int b);', |
|
680 cpp_style.cleanse_comments('foo(int a /* abc */, int b);')) |
|
681 self.assertEqual('f(a, b);', |
|
682 cpp_style.cleanse_comments('f(a, /* name */ b);')) |
|
683 self.assertEqual('f(a, b);', |
|
684 cpp_style.cleanse_comments('f(a /* name */, b);')) |
|
685 self.assertEqual('f(a, b);', |
|
686 cpp_style.cleanse_comments('f(a, /* name */b);')) |
|
687 |
|
688 def test_multi_line_comments(self): |
|
689 # missing explicit is bad |
|
690 self.assert_multi_line_lint( |
|
691 r'''int a = 0; |
|
692 /* multi-liner |
|
693 class Foo { |
|
694 Foo(int f); // should cause a lint warning in code |
|
695 } |
|
696 */ ''', |
|
697 '') |
|
698 self.assert_multi_line_lint( |
|
699 r'''/* int a = 0; multi-liner |
|
700 static const int b = 0;''', |
|
701 'Could not find end of multi-line comment' |
|
702 ' [readability/multiline_comment] [5]') |
|
703 self.assert_multi_line_lint(r''' /* multi-line comment''', |
|
704 'Could not find end of multi-line comment' |
|
705 ' [readability/multiline_comment] [5]') |
|
706 self.assert_multi_line_lint(r''' // /* comment, but not multi-line''', '') |
|
707 |
|
708 def test_multiline_strings(self): |
|
709 multiline_string_error_message = ( |
|
710 'Multi-line string ("...") found. This lint script doesn\'t ' |
|
711 'do well with such strings, and may give bogus warnings. They\'re ' |
|
712 'ugly and unnecessary, and you should use concatenation instead".' |
|
713 ' [readability/multiline_string] [5]') |
|
714 |
|
715 file_path = 'mydir/foo.cpp' |
|
716 |
|
717 error_collector = ErrorCollector(self.assert_) |
|
718 self.process_file_data(file_path, 'cpp', |
|
719 ['const char* str = "This is a\\', |
|
720 ' multiline string.";'], |
|
721 error_collector) |
|
722 self.assertEquals( |
|
723 2, # One per line. |
|
724 error_collector.result_list().count(multiline_string_error_message)) |
|
725 |
|
726 # Test non-explicit single-argument constructors |
|
727 def test_explicit_single_argument_constructors(self): |
|
728 # missing explicit is bad |
|
729 self.assert_multi_line_lint( |
|
730 '''class Foo { |
|
731 Foo(int f); |
|
732 };''', |
|
733 'Single-argument constructors should be marked explicit.' |
|
734 ' [runtime/explicit] [5]') |
|
735 # missing explicit is bad, even with whitespace |
|
736 self.assert_multi_line_lint( |
|
737 '''class Foo { |
|
738 Foo (int f); |
|
739 };''', |
|
740 ['Extra space before ( in function call [whitespace/parens] [4]', |
|
741 'Single-argument constructors should be marked explicit.' |
|
742 ' [runtime/explicit] [5]']) |
|
743 # missing explicit, with distracting comment, is still bad |
|
744 self.assert_multi_line_lint( |
|
745 '''class Foo { |
|
746 Foo(int f); // simpler than Foo(blargh, blarg) |
|
747 };''', |
|
748 'Single-argument constructors should be marked explicit.' |
|
749 ' [runtime/explicit] [5]') |
|
750 # missing explicit, with qualified classname |
|
751 self.assert_multi_line_lint( |
|
752 '''class Qualifier::AnotherOne::Foo { |
|
753 Foo(int f); |
|
754 };''', |
|
755 'Single-argument constructors should be marked explicit.' |
|
756 ' [runtime/explicit] [5]') |
|
757 # structs are caught as well. |
|
758 self.assert_multi_line_lint( |
|
759 '''struct Foo { |
|
760 Foo(int f); |
|
761 };''', |
|
762 'Single-argument constructors should be marked explicit.' |
|
763 ' [runtime/explicit] [5]') |
|
764 # Templatized classes are caught as well. |
|
765 self.assert_multi_line_lint( |
|
766 '''template<typename T> class Foo { |
|
767 Foo(int f); |
|
768 };''', |
|
769 'Single-argument constructors should be marked explicit.' |
|
770 ' [runtime/explicit] [5]') |
|
771 # proper style is okay |
|
772 self.assert_multi_line_lint( |
|
773 '''class Foo { |
|
774 explicit Foo(int f); |
|
775 };''', |
|
776 '') |
|
777 # two argument constructor is okay |
|
778 self.assert_multi_line_lint( |
|
779 '''class Foo { |
|
780 Foo(int f, int b); |
|
781 };''', |
|
782 '') |
|
783 # two argument constructor, across two lines, is okay |
|
784 self.assert_multi_line_lint( |
|
785 '''class Foo { |
|
786 Foo(int f, |
|
787 int b); |
|
788 };''', |
|
789 '') |
|
790 # non-constructor (but similar name), is okay |
|
791 self.assert_multi_line_lint( |
|
792 '''class Foo { |
|
793 aFoo(int f); |
|
794 };''', |
|
795 '') |
|
796 # constructor with void argument is okay |
|
797 self.assert_multi_line_lint( |
|
798 '''class Foo { |
|
799 Foo(void); |
|
800 };''', |
|
801 '') |
|
802 # single argument method is okay |
|
803 self.assert_multi_line_lint( |
|
804 '''class Foo { |
|
805 Bar(int b); |
|
806 };''', |
|
807 '') |
|
808 # comments should be ignored |
|
809 self.assert_multi_line_lint( |
|
810 '''class Foo { |
|
811 // Foo(int f); |
|
812 };''', |
|
813 '') |
|
814 # single argument function following class definition is okay |
|
815 # (okay, it's not actually valid, but we don't want a false positive) |
|
816 self.assert_multi_line_lint( |
|
817 '''class Foo { |
|
818 Foo(int f, int b); |
|
819 }; |
|
820 Foo(int f);''', |
|
821 '') |
|
822 # single argument function is okay |
|
823 self.assert_multi_line_lint( |
|
824 '''static Foo(int f);''', |
|
825 '') |
|
826 # single argument copy constructor is okay. |
|
827 self.assert_multi_line_lint( |
|
828 '''class Foo { |
|
829 Foo(const Foo&); |
|
830 };''', |
|
831 '') |
|
832 self.assert_multi_line_lint( |
|
833 '''class Foo { |
|
834 Foo(Foo&); |
|
835 };''', |
|
836 '') |
|
837 |
|
838 def test_slash_star_comment_on_single_line(self): |
|
839 self.assert_multi_line_lint( |
|
840 '''/* static */ Foo(int f);''', |
|
841 '') |
|
842 self.assert_multi_line_lint( |
|
843 '''/*/ static */ Foo(int f);''', |
|
844 '') |
|
845 self.assert_multi_line_lint( |
|
846 '''/*/ static Foo(int f);''', |
|
847 'Could not find end of multi-line comment' |
|
848 ' [readability/multiline_comment] [5]') |
|
849 self.assert_multi_line_lint( |
|
850 ''' /*/ static Foo(int f);''', |
|
851 'Could not find end of multi-line comment' |
|
852 ' [readability/multiline_comment] [5]') |
|
853 self.assert_multi_line_lint( |
|
854 ''' /**/ static Foo(int f);''', |
|
855 '') |
|
856 |
|
857 # Test suspicious usage of "if" like this: |
|
858 # if (a == b) { |
|
859 # DoSomething(); |
|
860 # } if (a == c) { // Should be "else if". |
|
861 # DoSomething(); // This gets called twice if a == b && a == c. |
|
862 # } |
|
863 def test_suspicious_usage_of_if(self): |
|
864 self.assert_lint( |
|
865 ' if (a == b) {', |
|
866 '') |
|
867 self.assert_lint( |
|
868 ' } if (a == b) {', |
|
869 'Did you mean "else if"? If not, start a new line for "if".' |
|
870 ' [readability/braces] [4]') |
|
871 |
|
872 # Test suspicious usage of memset. Specifically, a 0 |
|
873 # as the final argument is almost certainly an error. |
|
874 def test_suspicious_usage_of_memset(self): |
|
875 # Normal use is okay. |
|
876 self.assert_lint( |
|
877 ' memset(buf, 0, sizeof(buf))', |
|
878 '') |
|
879 |
|
880 # A 0 as the final argument is almost certainly an error. |
|
881 self.assert_lint( |
|
882 ' memset(buf, sizeof(buf), 0)', |
|
883 'Did you mean "memset(buf, 0, sizeof(buf))"?' |
|
884 ' [runtime/memset] [4]') |
|
885 self.assert_lint( |
|
886 ' memset(buf, xsize * ysize, 0)', |
|
887 'Did you mean "memset(buf, 0, xsize * ysize)"?' |
|
888 ' [runtime/memset] [4]') |
|
889 |
|
890 # There is legitimate test code that uses this form. |
|
891 # This is okay since the second argument is a literal. |
|
892 self.assert_lint( |
|
893 " memset(buf, 'y', 0)", |
|
894 '') |
|
895 self.assert_lint( |
|
896 ' memset(buf, 4, 0)', |
|
897 '') |
|
898 self.assert_lint( |
|
899 ' memset(buf, -1, 0)', |
|
900 '') |
|
901 self.assert_lint( |
|
902 ' memset(buf, 0xF1, 0)', |
|
903 '') |
|
904 self.assert_lint( |
|
905 ' memset(buf, 0xcd, 0)', |
|
906 '') |
|
907 |
|
908 def test_check_posix_threading(self): |
|
909 self.assert_lint('sctime_r()', '') |
|
910 self.assert_lint('strtok_r()', '') |
|
911 self.assert_lint(' strtok_r(foo, ba, r)', '') |
|
912 self.assert_lint('brand()', '') |
|
913 self.assert_lint('_rand()', '') |
|
914 self.assert_lint('.rand()', '') |
|
915 self.assert_lint('>rand()', '') |
|
916 self.assert_lint('rand()', |
|
917 'Consider using rand_r(...) instead of rand(...)' |
|
918 ' for improved thread safety.' |
|
919 ' [runtime/threadsafe_fn] [2]') |
|
920 self.assert_lint('strtok()', |
|
921 'Consider using strtok_r(...) ' |
|
922 'instead of strtok(...)' |
|
923 ' for improved thread safety.' |
|
924 ' [runtime/threadsafe_fn] [2]') |
|
925 |
|
926 # Test potential format string bugs like printf(foo). |
|
927 def test_format_strings(self): |
|
928 self.assert_lint('printf("foo")', '') |
|
929 self.assert_lint('printf("foo: %s", foo)', '') |
|
930 self.assert_lint('DocidForPrintf(docid)', '') # Should not trigger. |
|
931 self.assert_lint( |
|
932 'printf(foo)', |
|
933 'Potential format string bug. Do printf("%s", foo) instead.' |
|
934 ' [runtime/printf] [4]') |
|
935 self.assert_lint( |
|
936 'printf(foo.c_str())', |
|
937 'Potential format string bug. ' |
|
938 'Do printf("%s", foo.c_str()) instead.' |
|
939 ' [runtime/printf] [4]') |
|
940 self.assert_lint( |
|
941 'printf(foo->c_str())', |
|
942 'Potential format string bug. ' |
|
943 'Do printf("%s", foo->c_str()) instead.' |
|
944 ' [runtime/printf] [4]') |
|
945 self.assert_lint( |
|
946 'StringPrintf(foo)', |
|
947 'Potential format string bug. Do StringPrintf("%s", foo) instead.' |
|
948 '' |
|
949 ' [runtime/printf] [4]') |
|
950 |
|
951 # Variable-length arrays are not permitted. |
|
952 def test_variable_length_array_detection(self): |
|
953 errmsg = ('Do not use variable-length arrays. Use an appropriately named ' |
|
954 "('k' followed by CamelCase) compile-time constant for the size." |
|
955 ' [runtime/arrays] [1]') |
|
956 |
|
957 self.assert_lint('int a[any_old_variable];', errmsg) |
|
958 self.assert_lint('int doublesize[some_var * 2];', errmsg) |
|
959 self.assert_lint('int a[afunction()];', errmsg) |
|
960 self.assert_lint('int a[function(kMaxFooBars)];', errmsg) |
|
961 self.assert_lint('bool aList[items_->size()];', errmsg) |
|
962 self.assert_lint('namespace::Type buffer[len+1];', errmsg) |
|
963 |
|
964 self.assert_lint('int a[64];', '') |
|
965 self.assert_lint('int a[0xFF];', '') |
|
966 self.assert_lint('int first[256], second[256];', '') |
|
967 self.assert_lint('int arrayName[kCompileTimeConstant];', '') |
|
968 self.assert_lint('char buf[somenamespace::kBufSize];', '') |
|
969 self.assert_lint('int arrayName[ALL_CAPS];', '') |
|
970 self.assert_lint('AClass array1[foo::bar::ALL_CAPS];', '') |
|
971 self.assert_lint('int a[kMaxStrLen + 1];', '') |
|
972 self.assert_lint('int a[sizeof(foo)];', '') |
|
973 self.assert_lint('int a[sizeof(*foo)];', '') |
|
974 self.assert_lint('int a[sizeof foo];', '') |
|
975 self.assert_lint('int a[sizeof(struct Foo)];', '') |
|
976 self.assert_lint('int a[128 - sizeof(const bar)];', '') |
|
977 self.assert_lint('int a[(sizeof(foo) * 4)];', '') |
|
978 self.assert_lint('int a[(arraysize(fixed_size_array)/2) << 1];', 'Missing spaces around / [whitespace/operators] [3]') |
|
979 self.assert_lint('delete a[some_var];', '') |
|
980 self.assert_lint('return a[some_var];', '') |
|
981 |
|
982 # Brace usage |
|
983 def test_braces(self): |
|
984 # Braces shouldn't be followed by a ; unless they're defining a struct |
|
985 # or initializing an array |
|
986 self.assert_lint('int a[3] = { 1, 2, 3 };', '') |
|
987 self.assert_lint( |
|
988 '''const int foo[] = |
|
989 {1, 2, 3 };''', |
|
990 '') |
|
991 # For single line, unmatched '}' with a ';' is ignored (not enough context) |
|
992 self.assert_multi_line_lint( |
|
993 '''int a[3] = { 1, |
|
994 2, |
|
995 3 };''', |
|
996 '') |
|
997 self.assert_multi_line_lint( |
|
998 '''int a[2][3] = { { 1, 2 }, |
|
999 { 3, 4 } };''', |
|
1000 '') |
|
1001 self.assert_multi_line_lint( |
|
1002 '''int a[2][3] = |
|
1003 { { 1, 2 }, |
|
1004 { 3, 4 } };''', |
|
1005 '') |
|
1006 |
|
1007 # CHECK/EXPECT_TRUE/EXPECT_FALSE replacements |
|
1008 def test_check_check(self): |
|
1009 self.assert_lint('CHECK(x == 42)', |
|
1010 'Consider using CHECK_EQ instead of CHECK(a == b)' |
|
1011 ' [readability/check] [2]') |
|
1012 self.assert_lint('CHECK(x != 42)', |
|
1013 'Consider using CHECK_NE instead of CHECK(a != b)' |
|
1014 ' [readability/check] [2]') |
|
1015 self.assert_lint('CHECK(x >= 42)', |
|
1016 'Consider using CHECK_GE instead of CHECK(a >= b)' |
|
1017 ' [readability/check] [2]') |
|
1018 self.assert_lint('CHECK(x > 42)', |
|
1019 'Consider using CHECK_GT instead of CHECK(a > b)' |
|
1020 ' [readability/check] [2]') |
|
1021 self.assert_lint('CHECK(x <= 42)', |
|
1022 'Consider using CHECK_LE instead of CHECK(a <= b)' |
|
1023 ' [readability/check] [2]') |
|
1024 self.assert_lint('CHECK(x < 42)', |
|
1025 'Consider using CHECK_LT instead of CHECK(a < b)' |
|
1026 ' [readability/check] [2]') |
|
1027 |
|
1028 self.assert_lint('DCHECK(x == 42)', |
|
1029 'Consider using DCHECK_EQ instead of DCHECK(a == b)' |
|
1030 ' [readability/check] [2]') |
|
1031 self.assert_lint('DCHECK(x != 42)', |
|
1032 'Consider using DCHECK_NE instead of DCHECK(a != b)' |
|
1033 ' [readability/check] [2]') |
|
1034 self.assert_lint('DCHECK(x >= 42)', |
|
1035 'Consider using DCHECK_GE instead of DCHECK(a >= b)' |
|
1036 ' [readability/check] [2]') |
|
1037 self.assert_lint('DCHECK(x > 42)', |
|
1038 'Consider using DCHECK_GT instead of DCHECK(a > b)' |
|
1039 ' [readability/check] [2]') |
|
1040 self.assert_lint('DCHECK(x <= 42)', |
|
1041 'Consider using DCHECK_LE instead of DCHECK(a <= b)' |
|
1042 ' [readability/check] [2]') |
|
1043 self.assert_lint('DCHECK(x < 42)', |
|
1044 'Consider using DCHECK_LT instead of DCHECK(a < b)' |
|
1045 ' [readability/check] [2]') |
|
1046 |
|
1047 self.assert_lint( |
|
1048 'EXPECT_TRUE("42" == x)', |
|
1049 'Consider using EXPECT_EQ instead of EXPECT_TRUE(a == b)' |
|
1050 ' [readability/check] [2]') |
|
1051 self.assert_lint( |
|
1052 'EXPECT_TRUE("42" != x)', |
|
1053 'Consider using EXPECT_NE instead of EXPECT_TRUE(a != b)' |
|
1054 ' [readability/check] [2]') |
|
1055 self.assert_lint( |
|
1056 'EXPECT_TRUE(+42 >= x)', |
|
1057 'Consider using EXPECT_GE instead of EXPECT_TRUE(a >= b)' |
|
1058 ' [readability/check] [2]') |
|
1059 self.assert_lint( |
|
1060 'EXPECT_TRUE_M(-42 > x)', |
|
1061 'Consider using EXPECT_GT_M instead of EXPECT_TRUE_M(a > b)' |
|
1062 ' [readability/check] [2]') |
|
1063 self.assert_lint( |
|
1064 'EXPECT_TRUE_M(42U <= x)', |
|
1065 'Consider using EXPECT_LE_M instead of EXPECT_TRUE_M(a <= b)' |
|
1066 ' [readability/check] [2]') |
|
1067 self.assert_lint( |
|
1068 'EXPECT_TRUE_M(42L < x)', |
|
1069 'Consider using EXPECT_LT_M instead of EXPECT_TRUE_M(a < b)' |
|
1070 ' [readability/check] [2]') |
|
1071 |
|
1072 self.assert_lint( |
|
1073 'EXPECT_FALSE(x == 42)', |
|
1074 'Consider using EXPECT_NE instead of EXPECT_FALSE(a == b)' |
|
1075 ' [readability/check] [2]') |
|
1076 self.assert_lint( |
|
1077 'EXPECT_FALSE(x != 42)', |
|
1078 'Consider using EXPECT_EQ instead of EXPECT_FALSE(a != b)' |
|
1079 ' [readability/check] [2]') |
|
1080 self.assert_lint( |
|
1081 'EXPECT_FALSE(x >= 42)', |
|
1082 'Consider using EXPECT_LT instead of EXPECT_FALSE(a >= b)' |
|
1083 ' [readability/check] [2]') |
|
1084 self.assert_lint( |
|
1085 'ASSERT_FALSE(x > 42)', |
|
1086 'Consider using ASSERT_LE instead of ASSERT_FALSE(a > b)' |
|
1087 ' [readability/check] [2]') |
|
1088 self.assert_lint( |
|
1089 'ASSERT_FALSE(x <= 42)', |
|
1090 'Consider using ASSERT_GT instead of ASSERT_FALSE(a <= b)' |
|
1091 ' [readability/check] [2]') |
|
1092 self.assert_lint( |
|
1093 'ASSERT_FALSE_M(x < 42)', |
|
1094 'Consider using ASSERT_GE_M instead of ASSERT_FALSE_M(a < b)' |
|
1095 ' [readability/check] [2]') |
|
1096 |
|
1097 self.assert_lint('CHECK(some_iterator == obj.end())', '') |
|
1098 self.assert_lint('EXPECT_TRUE(some_iterator == obj.end())', '') |
|
1099 self.assert_lint('EXPECT_FALSE(some_iterator == obj.end())', '') |
|
1100 |
|
1101 self.assert_lint('CHECK(CreateTestFile(dir, (1 << 20)));', '') |
|
1102 self.assert_lint('CHECK(CreateTestFile(dir, (1 >> 20)));', '') |
|
1103 |
|
1104 self.assert_lint('CHECK(x<42)', |
|
1105 ['Missing spaces around <' |
|
1106 ' [whitespace/operators] [3]', |
|
1107 'Consider using CHECK_LT instead of CHECK(a < b)' |
|
1108 ' [readability/check] [2]']) |
|
1109 self.assert_lint('CHECK(x>42)', |
|
1110 'Consider using CHECK_GT instead of CHECK(a > b)' |
|
1111 ' [readability/check] [2]') |
|
1112 |
|
1113 self.assert_lint( |
|
1114 ' EXPECT_TRUE(42 < x) // Random comment.', |
|
1115 'Consider using EXPECT_LT instead of EXPECT_TRUE(a < b)' |
|
1116 ' [readability/check] [2]') |
|
1117 self.assert_lint( |
|
1118 'EXPECT_TRUE( 42 < x )', |
|
1119 ['Extra space after ( in function call' |
|
1120 ' [whitespace/parens] [4]', |
|
1121 'Consider using EXPECT_LT instead of EXPECT_TRUE(a < b)' |
|
1122 ' [readability/check] [2]']) |
|
1123 self.assert_lint( |
|
1124 'CHECK("foo" == "foo")', |
|
1125 'Consider using CHECK_EQ instead of CHECK(a == b)' |
|
1126 ' [readability/check] [2]') |
|
1127 |
|
1128 self.assert_lint('CHECK_EQ("foo", "foo")', '') |
|
1129 |
|
1130 def test_brace_at_begin_of_line(self): |
|
1131 self.assert_lint('{', |
|
1132 'This { should be at the end of the previous line' |
|
1133 ' [whitespace/braces] [4]') |
|
1134 self.assert_multi_line_lint( |
|
1135 '#endif\n' |
|
1136 '{\n' |
|
1137 '}\n', |
|
1138 '') |
|
1139 self.assert_multi_line_lint( |
|
1140 'if (condition) {', |
|
1141 '') |
|
1142 self.assert_multi_line_lint( |
|
1143 ' MACRO1(macroArg) {', |
|
1144 '') |
|
1145 self.assert_multi_line_lint( |
|
1146 'ACCESSOR_GETTER(MessageEventPorts) {', |
|
1147 'Place brace on its own line for function definitions. [whitespace/braces] [4]') |
|
1148 self.assert_multi_line_lint( |
|
1149 'int foo() {', |
|
1150 'Place brace on its own line for function definitions. [whitespace/braces] [4]') |
|
1151 self.assert_multi_line_lint( |
|
1152 'int foo() const {', |
|
1153 'Place brace on its own line for function definitions. [whitespace/braces] [4]') |
|
1154 self.assert_multi_line_lint( |
|
1155 'int foo() const\n' |
|
1156 '{\n' |
|
1157 '}\n', |
|
1158 '') |
|
1159 self.assert_multi_line_lint( |
|
1160 'if (condition\n' |
|
1161 ' && condition2\n' |
|
1162 ' && condition3) {\n' |
|
1163 '}\n', |
|
1164 '') |
|
1165 |
|
1166 def test_mismatching_spaces_in_parens(self): |
|
1167 self.assert_lint('if (foo ) {', 'Extra space before ) in if' |
|
1168 ' [whitespace/parens] [5]') |
|
1169 self.assert_lint('switch ( foo) {', 'Extra space after ( in switch' |
|
1170 ' [whitespace/parens] [5]') |
|
1171 self.assert_lint('for (foo; ba; bar ) {', 'Extra space before ) in for' |
|
1172 ' [whitespace/parens] [5]') |
|
1173 self.assert_lint('for ((foo); (ba); (bar) ) {', 'Extra space before ) in for' |
|
1174 ' [whitespace/parens] [5]') |
|
1175 self.assert_lint('for (; foo; bar) {', '') |
|
1176 self.assert_lint('for (; (foo); (bar)) {', '') |
|
1177 self.assert_lint('for ( ; foo; bar) {', '') |
|
1178 self.assert_lint('for ( ; (foo); (bar)) {', '') |
|
1179 self.assert_lint('for ( ; foo; bar ) {', 'Extra space before ) in for' |
|
1180 ' [whitespace/parens] [5]') |
|
1181 self.assert_lint('for ( ; (foo); (bar) ) {', 'Extra space before ) in for' |
|
1182 ' [whitespace/parens] [5]') |
|
1183 self.assert_lint('for (foo; bar; ) {', '') |
|
1184 self.assert_lint('for ((foo); (bar); ) {', '') |
|
1185 self.assert_lint('foreach (foo, foos ) {', 'Extra space before ) in foreach' |
|
1186 ' [whitespace/parens] [5]') |
|
1187 self.assert_lint('foreach ( foo, foos) {', 'Extra space after ( in foreach' |
|
1188 ' [whitespace/parens] [5]') |
|
1189 self.assert_lint('while ( foo) {', 'Extra space after ( in while' |
|
1190 ' [whitespace/parens] [5]') |
|
1191 |
|
1192 def test_spacing_for_fncall(self): |
|
1193 self.assert_lint('if (foo) {', '') |
|
1194 self.assert_lint('for (foo;bar;baz) {', '') |
|
1195 self.assert_lint('foreach (foo, foos) {', '') |
|
1196 self.assert_lint('while (foo) {', '') |
|
1197 self.assert_lint('switch (foo) {', '') |
|
1198 self.assert_lint('new (RenderArena()) RenderInline(document())', '') |
|
1199 self.assert_lint('foo( bar)', 'Extra space after ( in function call' |
|
1200 ' [whitespace/parens] [4]') |
|
1201 self.assert_lint('foobar( \\', '') |
|
1202 self.assert_lint('foobar( \\', '') |
|
1203 self.assert_lint('( a + b)', 'Extra space after (' |
|
1204 ' [whitespace/parens] [2]') |
|
1205 self.assert_lint('((a+b))', '') |
|
1206 self.assert_lint('foo (foo)', 'Extra space before ( in function call' |
|
1207 ' [whitespace/parens] [4]') |
|
1208 self.assert_lint('typedef foo (*foo)(foo)', '') |
|
1209 self.assert_lint('typedef foo (*foo12bar_)(foo)', '') |
|
1210 self.assert_lint('typedef foo (Foo::*bar)(foo)', '') |
|
1211 self.assert_lint('foo (Foo::*bar)(', |
|
1212 'Extra space before ( in function call' |
|
1213 ' [whitespace/parens] [4]') |
|
1214 self.assert_lint('typedef foo (Foo::*bar)(', '') |
|
1215 self.assert_lint('(foo)(bar)', '') |
|
1216 self.assert_lint('Foo (*foo)(bar)', '') |
|
1217 self.assert_lint('Foo (*foo)(Bar bar,', '') |
|
1218 self.assert_lint('char (*p)[sizeof(foo)] = &foo', '') |
|
1219 self.assert_lint('char (&ref)[sizeof(foo)] = &foo', '') |
|
1220 self.assert_lint('const char32 (*table[])[6];', '') |
|
1221 |
|
1222 def test_spacing_before_braces(self): |
|
1223 self.assert_lint('if (foo){', 'Missing space before {' |
|
1224 ' [whitespace/braces] [5]') |
|
1225 self.assert_lint('for{', 'Missing space before {' |
|
1226 ' [whitespace/braces] [5]') |
|
1227 self.assert_lint('for {', '') |
|
1228 self.assert_lint('EXPECT_DEBUG_DEATH({', '') |
|
1229 |
|
1230 def test_spacing_around_else(self): |
|
1231 self.assert_lint('}else {', 'Missing space before else' |
|
1232 ' [whitespace/braces] [5]') |
|
1233 self.assert_lint('} else{', 'Missing space before {' |
|
1234 ' [whitespace/braces] [5]') |
|
1235 self.assert_lint('} else {', '') |
|
1236 self.assert_lint('} else if', '') |
|
1237 |
|
1238 def test_spacing_for_binary_ops(self): |
|
1239 self.assert_lint('if (foo<=bar) {', 'Missing spaces around <=' |
|
1240 ' [whitespace/operators] [3]') |
|
1241 self.assert_lint('if (foo<bar) {', 'Missing spaces around <' |
|
1242 ' [whitespace/operators] [3]') |
|
1243 self.assert_lint('if (foo<bar->baz) {', 'Missing spaces around <' |
|
1244 ' [whitespace/operators] [3]') |
|
1245 self.assert_lint('if (foo<bar->bar) {', 'Missing spaces around <' |
|
1246 ' [whitespace/operators] [3]') |
|
1247 self.assert_lint('typedef hash_map<Foo, Bar', 'Missing spaces around <' |
|
1248 ' [whitespace/operators] [3]') |
|
1249 self.assert_lint('typedef hash_map<FoooooType, BaaaaarType,', '') |
|
1250 self.assert_lint('a<Foo> t+=b;', 'Missing spaces around +=' |
|
1251 ' [whitespace/operators] [3]') |
|
1252 self.assert_lint('a<Foo> t-=b;', 'Missing spaces around -=' |
|
1253 ' [whitespace/operators] [3]') |
|
1254 self.assert_lint('a<Foo*> t*=b;', 'Missing spaces around *=' |
|
1255 ' [whitespace/operators] [3]') |
|
1256 self.assert_lint('a<Foo*> t/=b;', 'Missing spaces around /=' |
|
1257 ' [whitespace/operators] [3]') |
|
1258 self.assert_lint('a<Foo*> t|=b;', 'Missing spaces around |=' |
|
1259 ' [whitespace/operators] [3]') |
|
1260 self.assert_lint('a<Foo*> t&=b;', 'Missing spaces around &=' |
|
1261 ' [whitespace/operators] [3]') |
|
1262 self.assert_lint('a<Foo*> t<<=b;', 'Missing spaces around <<=' |
|
1263 ' [whitespace/operators] [3]') |
|
1264 self.assert_lint('a<Foo*> t>>=b;', 'Missing spaces around >>=' |
|
1265 ' [whitespace/operators] [3]') |
|
1266 self.assert_lint('a<Foo*> t>>=&b|c;', 'Missing spaces around >>=' |
|
1267 ' [whitespace/operators] [3]') |
|
1268 self.assert_lint('a<Foo*> t<<=*b/c;', 'Missing spaces around <<=' |
|
1269 ' [whitespace/operators] [3]') |
|
1270 self.assert_lint('a<Foo> t -= b;', '') |
|
1271 self.assert_lint('a<Foo> t += b;', '') |
|
1272 self.assert_lint('a<Foo*> t *= b;', '') |
|
1273 self.assert_lint('a<Foo*> t /= b;', '') |
|
1274 self.assert_lint('a<Foo*> t |= b;', '') |
|
1275 self.assert_lint('a<Foo*> t &= b;', '') |
|
1276 self.assert_lint('a<Foo*> t <<= b;', '') |
|
1277 self.assert_lint('a<Foo*> t >>= b;', '') |
|
1278 self.assert_lint('a<Foo*> t >>= &b|c;', 'Missing spaces around |' |
|
1279 ' [whitespace/operators] [3]') |
|
1280 self.assert_lint('a<Foo*> t <<= *b/c;', 'Missing spaces around /' |
|
1281 ' [whitespace/operators] [3]') |
|
1282 self.assert_lint('a<Foo*> t <<= b/c; //Test', [ |
|
1283 'Should have a space between // and comment ' |
|
1284 '[whitespace/comments] [4]', 'Missing' |
|
1285 ' spaces around / [whitespace/operators] [3]']) |
|
1286 self.assert_lint('a<Foo*> t <<= b||c; //Test', ['One space before end' |
|
1287 ' of line comments [whitespace/comments] [5]', |
|
1288 'Should have a space between // and comment ' |
|
1289 '[whitespace/comments] [4]', |
|
1290 'Missing spaces around || [whitespace/operators] [3]']) |
|
1291 self.assert_lint('a<Foo*> t <<= b&&c; // Test', 'Missing spaces around' |
|
1292 ' && [whitespace/operators] [3]') |
|
1293 self.assert_lint('a<Foo*> t <<= b&&&c; // Test', 'Missing spaces around' |
|
1294 ' && [whitespace/operators] [3]') |
|
1295 self.assert_lint('a<Foo*> t <<= b&&*c; // Test', 'Missing spaces around' |
|
1296 ' && [whitespace/operators] [3]') |
|
1297 self.assert_lint('a<Foo*> t <<= b && *c; // Test', '') |
|
1298 self.assert_lint('a<Foo*> t <<= b && &c; // Test', '') |
|
1299 self.assert_lint('a<Foo*> t <<= b || &c; /*Test', 'Complex multi-line ' |
|
1300 '/*...*/-style comment found. Lint may give bogus ' |
|
1301 'warnings. Consider replacing these with //-style' |
|
1302 ' comments, with #if 0...#endif, or with more clearly' |
|
1303 ' structured multi-line comments. [readability/multiline_comment] [5]') |
|
1304 self.assert_lint('a<Foo&> t <<= &b | &c;', '') |
|
1305 self.assert_lint('a<Foo*> t <<= &b & &c; // Test', '') |
|
1306 self.assert_lint('a<Foo*> t <<= *b / &c; // Test', '') |
|
1307 self.assert_lint('if (a=b == 1)', 'Missing spaces around = [whitespace/operators] [4]') |
|
1308 self.assert_lint('a = 1<<20', 'Missing spaces around << [whitespace/operators] [3]') |
|
1309 self.assert_lint('if (a = b == 1)', '') |
|
1310 self.assert_lint('a = 1 << 20', '') |
|
1311 self.assert_multi_line_lint('#include "config.h"\n#include <sys/io.h>\n', |
|
1312 '') |
|
1313 self.assert_multi_line_lint('#include "config.h"\n#import <foo/bar.h>\n', |
|
1314 '') |
|
1315 |
|
1316 def test_spacing_before_last_semicolon(self): |
|
1317 self.assert_lint('call_function() ;', |
|
1318 'Extra space before last semicolon. If this should be an ' |
|
1319 'empty statement, use { } instead.' |
|
1320 ' [whitespace/semicolon] [5]') |
|
1321 self.assert_lint('while (true) ;', |
|
1322 'Extra space before last semicolon. If this should be an ' |
|
1323 'empty statement, use { } instead.' |
|
1324 ' [whitespace/semicolon] [5]') |
|
1325 self.assert_lint('default:;', |
|
1326 'Semicolon defining empty statement. Use { } instead.' |
|
1327 ' [whitespace/semicolon] [5]') |
|
1328 self.assert_lint(' ;', |
|
1329 'Line contains only semicolon. If this should be an empty ' |
|
1330 'statement, use { } instead.' |
|
1331 ' [whitespace/semicolon] [5]') |
|
1332 self.assert_lint('for (int i = 0; ;', '') |
|
1333 |
|
1334 # Static or global STL strings. |
|
1335 def test_static_or_global_stlstrings(self): |
|
1336 self.assert_lint('string foo;', |
|
1337 'For a static/global string constant, use a C style ' |
|
1338 'string instead: "char foo[]".' |
|
1339 ' [runtime/string] [4]') |
|
1340 self.assert_lint('string kFoo = "hello"; // English', |
|
1341 'For a static/global string constant, use a C style ' |
|
1342 'string instead: "char kFoo[]".' |
|
1343 ' [runtime/string] [4]') |
|
1344 self.assert_lint('static string foo;', |
|
1345 'For a static/global string constant, use a C style ' |
|
1346 'string instead: "static char foo[]".' |
|
1347 ' [runtime/string] [4]') |
|
1348 self.assert_lint('static const string foo;', |
|
1349 'For a static/global string constant, use a C style ' |
|
1350 'string instead: "static const char foo[]".' |
|
1351 ' [runtime/string] [4]') |
|
1352 self.assert_lint('string Foo::bar;', |
|
1353 'For a static/global string constant, use a C style ' |
|
1354 'string instead: "char Foo::bar[]".' |
|
1355 ' [runtime/string] [4]') |
|
1356 # Rare case. |
|
1357 self.assert_lint('string foo("foobar");', |
|
1358 'For a static/global string constant, use a C style ' |
|
1359 'string instead: "char foo[]".' |
|
1360 ' [runtime/string] [4]') |
|
1361 # Should not catch local or member variables. |
|
1362 self.assert_lint(' string foo', '') |
|
1363 # Should not catch functions. |
|
1364 self.assert_lint('string EmptyString() { return ""; }', '') |
|
1365 self.assert_lint('string EmptyString () { return ""; }', '') |
|
1366 self.assert_lint('string VeryLongNameFunctionSometimesEndsWith(\n' |
|
1367 ' VeryLongNameType very_long_name_variable) {}', '') |
|
1368 self.assert_lint('template<>\n' |
|
1369 'string FunctionTemplateSpecialization<SomeType>(\n' |
|
1370 ' int x) { return ""; }', '') |
|
1371 self.assert_lint('template<>\n' |
|
1372 'string FunctionTemplateSpecialization<vector<A::B>* >(\n' |
|
1373 ' int x) { return ""; }', '') |
|
1374 |
|
1375 # should not catch methods of template classes. |
|
1376 self.assert_lint('string Class<Type>::Method() const\n' |
|
1377 '{\n' |
|
1378 ' return "";\n' |
|
1379 '}\n', '') |
|
1380 self.assert_lint('string Class<Type>::Method(\n' |
|
1381 ' int arg) const\n' |
|
1382 '{\n' |
|
1383 ' return "";\n' |
|
1384 '}\n', '') |
|
1385 |
|
1386 def test_no_spaces_in_function_calls(self): |
|
1387 self.assert_lint('TellStory(1, 3);', |
|
1388 '') |
|
1389 self.assert_lint('TellStory(1, 3 );', |
|
1390 'Extra space before )' |
|
1391 ' [whitespace/parens] [2]') |
|
1392 self.assert_lint('TellStory(1 /* wolf */, 3 /* pigs */);', |
|
1393 '') |
|
1394 self.assert_multi_line_lint('#endif\n );', |
|
1395 '') |
|
1396 |
|
1397 def test_two_spaces_between_code_and_comments(self): |
|
1398 self.assert_lint('} // namespace foo', |
|
1399 '') |
|
1400 self.assert_lint('}// namespace foo', |
|
1401 'One space before end of line comments' |
|
1402 ' [whitespace/comments] [5]') |
|
1403 self.assert_lint('printf("foo"); // Outside quotes.', |
|
1404 '') |
|
1405 self.assert_lint('int i = 0; // Having one space is fine.','') |
|
1406 self.assert_lint('int i = 0; // Having two spaces is bad.', |
|
1407 'One space before end of line comments' |
|
1408 ' [whitespace/comments] [5]') |
|
1409 self.assert_lint('int i = 0; // Having three spaces is bad.', |
|
1410 'One space before end of line comments' |
|
1411 ' [whitespace/comments] [5]') |
|
1412 self.assert_lint('// Top level comment', '') |
|
1413 self.assert_lint(' // Line starts with four spaces.', '') |
|
1414 self.assert_lint('foo();\n' |
|
1415 '{ // A scope is opening.', '') |
|
1416 self.assert_lint(' foo();\n' |
|
1417 ' { // An indented scope is opening.', '') |
|
1418 self.assert_lint('if (foo) { // not a pure scope', |
|
1419 '') |
|
1420 self.assert_lint('printf("// In quotes.")', '') |
|
1421 self.assert_lint('printf("\\"%s // In quotes.")', '') |
|
1422 self.assert_lint('printf("%s", "// In quotes.")', '') |
|
1423 |
|
1424 def test_space_after_comment_marker(self): |
|
1425 self.assert_lint('//', '') |
|
1426 self.assert_lint('//x', 'Should have a space between // and comment' |
|
1427 ' [whitespace/comments] [4]') |
|
1428 self.assert_lint('// x', '') |
|
1429 self.assert_lint('//----', '') |
|
1430 self.assert_lint('//====', '') |
|
1431 self.assert_lint('//////', '') |
|
1432 self.assert_lint('////// x', '') |
|
1433 self.assert_lint('/// x', '') |
|
1434 self.assert_lint('////x', 'Should have a space between // and comment' |
|
1435 ' [whitespace/comments] [4]') |
|
1436 |
|
1437 def test_newline_at_eof(self): |
|
1438 def do_test(self, data, is_missing_eof): |
|
1439 error_collector = ErrorCollector(self.assert_) |
|
1440 self.process_file_data('foo.cpp', 'cpp', data.split('\n'), |
|
1441 error_collector) |
|
1442 # The warning appears only once. |
|
1443 self.assertEquals( |
|
1444 int(is_missing_eof), |
|
1445 error_collector.results().count( |
|
1446 'Could not find a newline character at the end of the file.' |
|
1447 ' [whitespace/ending_newline] [5]')) |
|
1448 |
|
1449 do_test(self, '// Newline\n// at EOF\n', False) |
|
1450 do_test(self, '// No newline\n// at EOF', True) |
|
1451 |
|
1452 def test_invalid_utf8(self): |
|
1453 def do_test(self, raw_bytes, has_invalid_utf8): |
|
1454 error_collector = ErrorCollector(self.assert_) |
|
1455 self.process_file_data('foo.cpp', 'cpp', |
|
1456 unicode(raw_bytes, 'utf8', 'replace').split('\n'), |
|
1457 error_collector) |
|
1458 # The warning appears only once. |
|
1459 self.assertEquals( |
|
1460 int(has_invalid_utf8), |
|
1461 error_collector.results().count( |
|
1462 'Line contains invalid UTF-8' |
|
1463 ' (or Unicode replacement character).' |
|
1464 ' [readability/utf8] [5]')) |
|
1465 |
|
1466 do_test(self, 'Hello world\n', False) |
|
1467 do_test(self, '\xe9\x8e\xbd\n', False) |
|
1468 do_test(self, '\xe9x\x8e\xbd\n', True) |
|
1469 # This is the encoding of the replacement character itself (which |
|
1470 # you can see by evaluating codecs.getencoder('utf8')(u'\ufffd')). |
|
1471 do_test(self, '\xef\xbf\xbd\n', True) |
|
1472 |
|
1473 def test_is_blank_line(self): |
|
1474 self.assert_(cpp_style.is_blank_line('')) |
|
1475 self.assert_(cpp_style.is_blank_line(' ')) |
|
1476 self.assert_(cpp_style.is_blank_line(' \t\r\n')) |
|
1477 self.assert_(not cpp_style.is_blank_line('int a;')) |
|
1478 self.assert_(not cpp_style.is_blank_line('{')) |
|
1479 |
|
1480 def test_blank_lines_check(self): |
|
1481 self.assert_blank_lines_check(['{\n', '\n', '\n', '}\n'], 1, 1) |
|
1482 self.assert_blank_lines_check([' if (foo) {\n', '\n', ' }\n'], 1, 1) |
|
1483 self.assert_blank_lines_check( |
|
1484 ['\n', '// {\n', '\n', '\n', '// Comment\n', '{\n', '}\n'], 0, 0) |
|
1485 self.assert_blank_lines_check(['\n', 'run("{");\n', '\n'], 0, 0) |
|
1486 self.assert_blank_lines_check(['\n', ' if (foo) { return 0; }\n', '\n'], 0, 0) |
|
1487 |
|
1488 def test_allow_blank_line_before_closing_namespace(self): |
|
1489 error_collector = ErrorCollector(self.assert_) |
|
1490 self.process_file_data('foo.cpp', 'cpp', |
|
1491 ['namespace {', '', '} // namespace'], |
|
1492 error_collector) |
|
1493 self.assertEquals(0, error_collector.results().count( |
|
1494 'Blank line at the end of a code block. Is this needed?' |
|
1495 ' [whitespace/blank_line] [3]')) |
|
1496 |
|
1497 def test_allow_blank_line_before_if_else_chain(self): |
|
1498 error_collector = ErrorCollector(self.assert_) |
|
1499 self.process_file_data('foo.cpp', 'cpp', |
|
1500 ['if (hoge) {', |
|
1501 '', # No warning |
|
1502 '} else if (piyo) {', |
|
1503 '', # No warning |
|
1504 '} else if (piyopiyo) {', |
|
1505 ' hoge = true;', # No warning |
|
1506 '} else {', |
|
1507 '', # Warning on this line |
|
1508 '}'], |
|
1509 error_collector) |
|
1510 self.assertEquals(1, error_collector.results().count( |
|
1511 'Blank line at the end of a code block. Is this needed?' |
|
1512 ' [whitespace/blank_line] [3]')) |
|
1513 |
|
1514 def test_else_on_same_line_as_closing_braces(self): |
|
1515 error_collector = ErrorCollector(self.assert_) |
|
1516 self.process_file_data('foo.cpp', 'cpp', |
|
1517 ['if (hoge) {', |
|
1518 '', |
|
1519 '}', |
|
1520 ' else {' # Warning on this line |
|
1521 '', |
|
1522 '}'], |
|
1523 error_collector) |
|
1524 self.assertEquals(1, error_collector.results().count( |
|
1525 'An else should appear on the same line as the preceding }' |
|
1526 ' [whitespace/newline] [4]')) |
|
1527 |
|
1528 def test_else_clause_not_on_same_line_as_else(self): |
|
1529 self.assert_lint(' else DoSomethingElse();', |
|
1530 'Else clause should never be on same line as else ' |
|
1531 '(use 2 lines) [whitespace/newline] [4]') |
|
1532 self.assert_lint(' else ifDoSomethingElse();', |
|
1533 'Else clause should never be on same line as else ' |
|
1534 '(use 2 lines) [whitespace/newline] [4]') |
|
1535 self.assert_lint(' else if (blah) {', '') |
|
1536 self.assert_lint(' variable_ends_in_else = true;', '') |
|
1537 |
|
1538 def test_comma(self): |
|
1539 self.assert_lint('a = f(1,2);', |
|
1540 'Missing space after , [whitespace/comma] [3]') |
|
1541 self.assert_lint('int tmp=a,a=b,b=tmp;', |
|
1542 ['Missing spaces around = [whitespace/operators] [4]', |
|
1543 'Missing space after , [whitespace/comma] [3]']) |
|
1544 self.assert_lint('f(a, /* name */ b);', '') |
|
1545 self.assert_lint('f(a, /* name */b);', '') |
|
1546 |
|
1547 def test_declaration(self): |
|
1548 self.assert_lint('int a;', '') |
|
1549 self.assert_lint('int a;', 'Extra space between int and a [whitespace/declaration] [3]') |
|
1550 self.assert_lint('int* a;', 'Extra space between int* and a [whitespace/declaration] [3]') |
|
1551 self.assert_lint('else if { }', '') |
|
1552 self.assert_lint('else if { }', 'Extra space between else and if [whitespace/declaration] [3]') |
|
1553 |
|
1554 def test_pointer_reference_marker_location(self): |
|
1555 self.assert_lint('int* b;', '', 'foo.cpp') |
|
1556 self.assert_lint('int *b;', |
|
1557 'Declaration has space between type name and * in int *b [whitespace/declaration] [3]', |
|
1558 'foo.cpp') |
|
1559 self.assert_lint('return *b;', '', 'foo.cpp') |
|
1560 self.assert_lint('delete *b;', '', 'foo.cpp') |
|
1561 self.assert_lint('int *b;', '', 'foo.c') |
|
1562 self.assert_lint('int* b;', |
|
1563 'Declaration has space between * and variable name in int* b [whitespace/declaration] [3]', |
|
1564 'foo.c') |
|
1565 self.assert_lint('int& b;', '', 'foo.cpp') |
|
1566 self.assert_lint('int &b;', |
|
1567 'Declaration has space between type name and & in int &b [whitespace/declaration] [3]', |
|
1568 'foo.cpp') |
|
1569 self.assert_lint('return &b;', '', 'foo.cpp') |
|
1570 |
|
1571 def test_indent(self): |
|
1572 self.assert_lint('static int noindent;', '') |
|
1573 self.assert_lint(' int fourSpaceIndent;', '') |
|
1574 self.assert_lint(' int oneSpaceIndent;', |
|
1575 'Weird number of spaces at line-start. ' |
|
1576 'Are you using a 4-space indent? [whitespace/indent] [3]') |
|
1577 self.assert_lint(' int threeSpaceIndent;', |
|
1578 'Weird number of spaces at line-start. ' |
|
1579 'Are you using a 4-space indent? [whitespace/indent] [3]') |
|
1580 self.assert_lint(' char* oneSpaceIndent = "public:";', |
|
1581 'Weird number of spaces at line-start. ' |
|
1582 'Are you using a 4-space indent? [whitespace/indent] [3]') |
|
1583 self.assert_lint(' public:', '') |
|
1584 self.assert_lint(' public:', '') |
|
1585 self.assert_lint(' public:', '') |
|
1586 |
|
1587 def test_label(self): |
|
1588 self.assert_lint('public:', |
|
1589 'Labels should always be indented at least one space. ' |
|
1590 'If this is a member-initializer list in a constructor, ' |
|
1591 'the colon should be on the line after the definition ' |
|
1592 'header. [whitespace/labels] [4]') |
|
1593 self.assert_lint(' public:', '') |
|
1594 self.assert_lint(' public:', '') |
|
1595 self.assert_lint(' public:', '') |
|
1596 self.assert_lint(' public:', '') |
|
1597 self.assert_lint(' public:', '') |
|
1598 |
|
1599 def test_not_alabel(self): |
|
1600 self.assert_lint('MyVeryLongNamespace::MyVeryLongClassName::', '') |
|
1601 |
|
1602 def test_tab(self): |
|
1603 self.assert_lint('\tint a;', |
|
1604 'Tab found; better to use spaces [whitespace/tab] [1]') |
|
1605 self.assert_lint('int a = 5;\t// set a to 5', |
|
1606 'Tab found; better to use spaces [whitespace/tab] [1]') |
|
1607 |
|
1608 def test_unnamed_namespaces_in_headers(self): |
|
1609 self.assert_language_rules_check( |
|
1610 'foo.h', 'namespace {', |
|
1611 'Do not use unnamed namespaces in header files. See' |
|
1612 ' http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' |
|
1613 ' for more information. [build/namespaces] [4]') |
|
1614 # namespace registration macros are OK. |
|
1615 self.assert_language_rules_check('foo.h', 'namespace { \\', '') |
|
1616 # named namespaces are OK. |
|
1617 self.assert_language_rules_check('foo.h', 'namespace foo {', '') |
|
1618 self.assert_language_rules_check('foo.h', 'namespace foonamespace {', '') |
|
1619 self.assert_language_rules_check('foo.cpp', 'namespace {', '') |
|
1620 self.assert_language_rules_check('foo.cpp', 'namespace foo {', '') |
|
1621 |
|
1622 def test_build_class(self): |
|
1623 # Test that the linter can parse to the end of class definitions, |
|
1624 # and that it will report when it can't. |
|
1625 # Use multi-line linter because it performs the ClassState check. |
|
1626 self.assert_multi_line_lint( |
|
1627 'class Foo {', |
|
1628 'Failed to find complete declaration of class Foo' |
|
1629 ' [build/class] [5]') |
|
1630 # Don't warn on forward declarations of various types. |
|
1631 self.assert_multi_line_lint( |
|
1632 'class Foo;', |
|
1633 '') |
|
1634 self.assert_multi_line_lint( |
|
1635 '''struct Foo* |
|
1636 foo = NewFoo();''', |
|
1637 '') |
|
1638 # Here is an example where the linter gets confused, even though |
|
1639 # the code doesn't violate the style guide. |
|
1640 self.assert_multi_line_lint( |
|
1641 '''class Foo |
|
1642 #ifdef DERIVE_FROM_GOO |
|
1643 : public Goo { |
|
1644 #else |
|
1645 : public Hoo { |
|
1646 #endif |
|
1647 };''', |
|
1648 'Failed to find complete declaration of class Foo' |
|
1649 ' [build/class] [5]') |
|
1650 |
|
1651 def test_build_end_comment(self): |
|
1652 # The crosstool compiler we currently use will fail to compile the |
|
1653 # code in this test, so we might consider removing the lint check. |
|
1654 self.assert_lint('#endif Not a comment', |
|
1655 'Uncommented text after #endif is non-standard.' |
|
1656 ' Use a comment.' |
|
1657 ' [build/endif_comment] [5]') |
|
1658 |
|
1659 def test_build_forward_decl(self): |
|
1660 # The crosstool compiler we currently use will fail to compile the |
|
1661 # code in this test, so we might consider removing the lint check. |
|
1662 self.assert_lint('class Foo::Goo;', |
|
1663 'Inner-style forward declarations are invalid.' |
|
1664 ' Remove this line.' |
|
1665 ' [build/forward_decl] [5]') |
|
1666 |
|
1667 def test_build_header_guard(self): |
|
1668 file_path = 'mydir/Foo.h' |
|
1669 |
|
1670 # We can't rely on our internal stuff to get a sane path on the open source |
|
1671 # side of things, so just parse out the suggested header guard. This |
|
1672 # doesn't allow us to test the suggested header guard, but it does let us |
|
1673 # test all the other header tests. |
|
1674 error_collector = ErrorCollector(self.assert_) |
|
1675 self.process_file_data(file_path, 'h', [], error_collector) |
|
1676 expected_guard = '' |
|
1677 matcher = re.compile( |
|
1678 'No \#ifndef header guard found\, suggested CPP variable is\: ([A-Za-z_0-9]+) ') |
|
1679 for error in error_collector.result_list(): |
|
1680 matches = matcher.match(error) |
|
1681 if matches: |
|
1682 expected_guard = matches.group(1) |
|
1683 break |
|
1684 |
|
1685 # Make sure we extracted something for our header guard. |
|
1686 self.assertNotEqual(expected_guard, '') |
|
1687 |
|
1688 # Wrong guard |
|
1689 error_collector = ErrorCollector(self.assert_) |
|
1690 self.process_file_data(file_path, 'h', |
|
1691 ['#ifndef FOO_H', '#define FOO_H'], error_collector) |
|
1692 self.assertEquals( |
|
1693 1, |
|
1694 error_collector.result_list().count( |
|
1695 '#ifndef header guard has wrong style, please use: %s' |
|
1696 ' [build/header_guard] [5]' % expected_guard), |
|
1697 error_collector.result_list()) |
|
1698 |
|
1699 # No define |
|
1700 error_collector = ErrorCollector(self.assert_) |
|
1701 self.process_file_data(file_path, 'h', |
|
1702 ['#ifndef %s' % expected_guard], error_collector) |
|
1703 self.assertEquals( |
|
1704 1, |
|
1705 error_collector.result_list().count( |
|
1706 'No #ifndef header guard found, suggested CPP variable is: %s' |
|
1707 ' [build/header_guard] [5]' % expected_guard), |
|
1708 error_collector.result_list()) |
|
1709 |
|
1710 # Mismatched define |
|
1711 error_collector = ErrorCollector(self.assert_) |
|
1712 self.process_file_data(file_path, 'h', |
|
1713 ['#ifndef %s' % expected_guard, |
|
1714 '#define FOO_H'], |
|
1715 error_collector) |
|
1716 self.assertEquals( |
|
1717 1, |
|
1718 error_collector.result_list().count( |
|
1719 'No #ifndef header guard found, suggested CPP variable is: %s' |
|
1720 ' [build/header_guard] [5]' % expected_guard), |
|
1721 error_collector.result_list()) |
|
1722 |
|
1723 # No header guard errors |
|
1724 error_collector = ErrorCollector(self.assert_) |
|
1725 self.process_file_data(file_path, 'h', |
|
1726 ['#ifndef %s' % expected_guard, |
|
1727 '#define %s' % expected_guard, |
|
1728 '#endif // %s' % expected_guard], |
|
1729 error_collector) |
|
1730 for line in error_collector.result_list(): |
|
1731 if line.find('build/header_guard') != -1: |
|
1732 self.fail('Unexpected error: %s' % line) |
|
1733 |
|
1734 # Completely incorrect header guard |
|
1735 error_collector = ErrorCollector(self.assert_) |
|
1736 self.process_file_data(file_path, 'h', |
|
1737 ['#ifndef FOO', |
|
1738 '#define FOO', |
|
1739 '#endif // FOO'], |
|
1740 error_collector) |
|
1741 self.assertEquals( |
|
1742 1, |
|
1743 error_collector.result_list().count( |
|
1744 '#ifndef header guard has wrong style, please use: %s' |
|
1745 ' [build/header_guard] [5]' % expected_guard), |
|
1746 error_collector.result_list()) |
|
1747 |
|
1748 # Special case for flymake |
|
1749 error_collector = ErrorCollector(self.assert_) |
|
1750 self.process_file_data('mydir/Foo_flymake.h', 'h', |
|
1751 ['#ifndef %s' % expected_guard, |
|
1752 '#define %s' % expected_guard, |
|
1753 '#endif // %s' % expected_guard], |
|
1754 error_collector) |
|
1755 for line in error_collector.result_list(): |
|
1756 if line.find('build/header_guard') != -1: |
|
1757 self.fail('Unexpected error: %s' % line) |
|
1758 |
|
1759 error_collector = ErrorCollector(self.assert_) |
|
1760 self.process_file_data('mydir/Foo_flymake.h', 'h', [], error_collector) |
|
1761 self.assertEquals( |
|
1762 1, |
|
1763 error_collector.result_list().count( |
|
1764 'No #ifndef header guard found, suggested CPP variable is: %s' |
|
1765 ' [build/header_guard] [5]' % expected_guard), |
|
1766 error_collector.result_list()) |
|
1767 |
|
1768 def test_build_printf_format(self): |
|
1769 self.assert_lint( |
|
1770 r'printf("\%%d", value);', |
|
1771 '%, [, (, and { are undefined character escapes. Unescape them.' |
|
1772 ' [build/printf_format] [3]') |
|
1773 |
|
1774 self.assert_lint( |
|
1775 r'snprintf(buffer, sizeof(buffer), "\[%d", value);', |
|
1776 '%, [, (, and { are undefined character escapes. Unescape them.' |
|
1777 ' [build/printf_format] [3]') |
|
1778 |
|
1779 self.assert_lint( |
|
1780 r'fprintf(file, "\(%d", value);', |
|
1781 '%, [, (, and { are undefined character escapes. Unescape them.' |
|
1782 ' [build/printf_format] [3]') |
|
1783 |
|
1784 self.assert_lint( |
|
1785 r'vsnprintf(buffer, sizeof(buffer), "\\\{%d", ap);', |
|
1786 '%, [, (, and { are undefined character escapes. Unescape them.' |
|
1787 ' [build/printf_format] [3]') |
|
1788 |
|
1789 # Don't warn if double-slash precedes the symbol |
|
1790 self.assert_lint(r'printf("\\%%%d", value);', |
|
1791 '') |
|
1792 |
|
1793 def test_runtime_printf_format(self): |
|
1794 self.assert_lint( |
|
1795 r'fprintf(file, "%q", value);', |
|
1796 '%q in format strings is deprecated. Use %ll instead.' |
|
1797 ' [runtime/printf_format] [3]') |
|
1798 |
|
1799 self.assert_lint( |
|
1800 r'aprintf(file, "The number is %12q", value);', |
|
1801 '%q in format strings is deprecated. Use %ll instead.' |
|
1802 ' [runtime/printf_format] [3]') |
|
1803 |
|
1804 self.assert_lint( |
|
1805 r'printf(file, "The number is" "%-12q", value);', |
|
1806 '%q in format strings is deprecated. Use %ll instead.' |
|
1807 ' [runtime/printf_format] [3]') |
|
1808 |
|
1809 self.assert_lint( |
|
1810 r'printf(file, "The number is" "%+12q", value);', |
|
1811 '%q in format strings is deprecated. Use %ll instead.' |
|
1812 ' [runtime/printf_format] [3]') |
|
1813 |
|
1814 self.assert_lint( |
|
1815 r'printf(file, "The number is" "% 12q", value);', |
|
1816 '%q in format strings is deprecated. Use %ll instead.' |
|
1817 ' [runtime/printf_format] [3]') |
|
1818 |
|
1819 self.assert_lint( |
|
1820 r'snprintf(file, "Never mix %d and %1$d parmaeters!", value);', |
|
1821 '%N$ formats are unconventional. Try rewriting to avoid them.' |
|
1822 ' [runtime/printf_format] [2]') |
|
1823 |
|
1824 def assert_lintLogCodeOnError(self, code, expected_message): |
|
1825 # Special assert_lint which logs the input code on error. |
|
1826 result = self.perform_single_line_lint(code, 'foo.cpp') |
|
1827 if result != expected_message: |
|
1828 self.fail('For code: "%s"\nGot: "%s"\nExpected: "%s"' |
|
1829 % (code, result, expected_message)) |
|
1830 |
|
1831 def test_build_storage_class(self): |
|
1832 qualifiers = [None, 'const', 'volatile'] |
|
1833 signs = [None, 'signed', 'unsigned'] |
|
1834 types = ['void', 'char', 'int', 'float', 'double', |
|
1835 'schar', 'int8', 'uint8', 'int16', 'uint16', |
|
1836 'int32', 'uint32', 'int64', 'uint64'] |
|
1837 storage_classes = ['auto', 'extern', 'register', 'static', 'typedef'] |
|
1838 |
|
1839 build_storage_class_error_message = ( |
|
1840 'Storage class (static, extern, typedef, etc) should be first.' |
|
1841 ' [build/storage_class] [5]') |
|
1842 |
|
1843 # Some explicit cases. Legal in C++, deprecated in C99. |
|
1844 self.assert_lint('const int static foo = 5;', |
|
1845 build_storage_class_error_message) |
|
1846 |
|
1847 self.assert_lint('char static foo;', |
|
1848 build_storage_class_error_message) |
|
1849 |
|
1850 self.assert_lint('double const static foo = 2.0;', |
|
1851 build_storage_class_error_message) |
|
1852 |
|
1853 self.assert_lint('uint64 typedef unsignedLongLong;', |
|
1854 build_storage_class_error_message) |
|
1855 |
|
1856 self.assert_lint('int register foo = 0;', |
|
1857 build_storage_class_error_message) |
|
1858 |
|
1859 # Since there are a very large number of possibilities, randomly |
|
1860 # construct declarations. |
|
1861 # Make sure that the declaration is logged if there's an error. |
|
1862 # Seed generator with an integer for absolute reproducibility. |
|
1863 random.seed(25) |
|
1864 for unused_i in range(10): |
|
1865 # Build up random list of non-storage-class declaration specs. |
|
1866 other_decl_specs = [random.choice(qualifiers), random.choice(signs), |
|
1867 random.choice(types)] |
|
1868 # remove None |
|
1869 other_decl_specs = filter(lambda x: x is not None, other_decl_specs) |
|
1870 |
|
1871 # shuffle |
|
1872 random.shuffle(other_decl_specs) |
|
1873 |
|
1874 # insert storage class after the first |
|
1875 storage_class = random.choice(storage_classes) |
|
1876 insertion_point = random.randint(1, len(other_decl_specs)) |
|
1877 decl_specs = (other_decl_specs[0:insertion_point] |
|
1878 + [storage_class] |
|
1879 + other_decl_specs[insertion_point:]) |
|
1880 |
|
1881 self.assert_lintLogCodeOnError( |
|
1882 ' '.join(decl_specs) + ';', |
|
1883 build_storage_class_error_message) |
|
1884 |
|
1885 # but no error if storage class is first |
|
1886 self.assert_lintLogCodeOnError( |
|
1887 storage_class + ' ' + ' '.join(other_decl_specs), |
|
1888 '') |
|
1889 |
|
1890 def test_legal_copyright(self): |
|
1891 legal_copyright_message = ( |
|
1892 'No copyright message found. ' |
|
1893 'You should have a line: "Copyright [year] <Copyright Owner>"' |
|
1894 ' [legal/copyright] [5]') |
|
1895 |
|
1896 copyright_line = '// Copyright 2008 Google Inc. All Rights Reserved.' |
|
1897 |
|
1898 file_path = 'mydir/googleclient/foo.cpp' |
|
1899 |
|
1900 # There should be a copyright message in the first 10 lines |
|
1901 error_collector = ErrorCollector(self.assert_) |
|
1902 self.process_file_data(file_path, 'cpp', [], error_collector) |
|
1903 self.assertEquals( |
|
1904 1, |
|
1905 error_collector.result_list().count(legal_copyright_message)) |
|
1906 |
|
1907 error_collector = ErrorCollector(self.assert_) |
|
1908 self.process_file_data( |
|
1909 file_path, 'cpp', |
|
1910 ['' for unused_i in range(10)] + [copyright_line], |
|
1911 error_collector) |
|
1912 self.assertEquals( |
|
1913 1, |
|
1914 error_collector.result_list().count(legal_copyright_message)) |
|
1915 |
|
1916 # Test that warning isn't issued if Copyright line appears early enough. |
|
1917 error_collector = ErrorCollector(self.assert_) |
|
1918 self.process_file_data(file_path, 'cpp', [copyright_line], error_collector) |
|
1919 for message in error_collector.result_list(): |
|
1920 if message.find('legal/copyright') != -1: |
|
1921 self.fail('Unexpected error: %s' % message) |
|
1922 |
|
1923 error_collector = ErrorCollector(self.assert_) |
|
1924 self.process_file_data( |
|
1925 file_path, 'cpp', |
|
1926 ['' for unused_i in range(9)] + [copyright_line], |
|
1927 error_collector) |
|
1928 for message in error_collector.result_list(): |
|
1929 if message.find('legal/copyright') != -1: |
|
1930 self.fail('Unexpected error: %s' % message) |
|
1931 |
|
1932 def test_invalid_increment(self): |
|
1933 self.assert_lint('*count++;', |
|
1934 'Changing pointer instead of value (or unused value of ' |
|
1935 'operator*). [runtime/invalid_increment] [5]') |
|
1936 |
|
1937 |
|
1938 class CleansedLinesTest(unittest.TestCase): |
|
1939 def test_init(self): |
|
1940 lines = ['Line 1', |
|
1941 'Line 2', |
|
1942 'Line 3 // Comment test', |
|
1943 'Line 4 "foo"'] |
|
1944 |
|
1945 clean_lines = cpp_style.CleansedLines(lines) |
|
1946 self.assertEquals(lines, clean_lines.raw_lines) |
|
1947 self.assertEquals(4, clean_lines.num_lines()) |
|
1948 |
|
1949 self.assertEquals(['Line 1', |
|
1950 'Line 2', |
|
1951 'Line 3 ', |
|
1952 'Line 4 "foo"'], |
|
1953 clean_lines.lines) |
|
1954 |
|
1955 self.assertEquals(['Line 1', |
|
1956 'Line 2', |
|
1957 'Line 3 ', |
|
1958 'Line 4 ""'], |
|
1959 clean_lines.elided) |
|
1960 |
|
1961 def test_init_empty(self): |
|
1962 clean_lines = cpp_style.CleansedLines([]) |
|
1963 self.assertEquals([], clean_lines.raw_lines) |
|
1964 self.assertEquals(0, clean_lines.num_lines()) |
|
1965 |
|
1966 def test_collapse_strings(self): |
|
1967 collapse = cpp_style.CleansedLines.collapse_strings |
|
1968 self.assertEquals('""', collapse('""')) # "" (empty) |
|
1969 self.assertEquals('"""', collapse('"""')) # """ (bad) |
|
1970 self.assertEquals('""', collapse('"xyz"')) # "xyz" (string) |
|
1971 self.assertEquals('""', collapse('"\\\""')) # "\"" (string) |
|
1972 self.assertEquals('""', collapse('"\'"')) # "'" (string) |
|
1973 self.assertEquals('"\"', collapse('"\"')) # "\" (bad) |
|
1974 self.assertEquals('""', collapse('"\\\\"')) # "\\" (string) |
|
1975 self.assertEquals('"', collapse('"\\\\\\"')) # "\\\" (bad) |
|
1976 self.assertEquals('""', collapse('"\\\\\\\\"')) # "\\\\" (string) |
|
1977 |
|
1978 self.assertEquals('\'\'', collapse('\'\'')) # '' (empty) |
|
1979 self.assertEquals('\'\'', collapse('\'a\'')) # 'a' (char) |
|
1980 self.assertEquals('\'\'', collapse('\'\\\'\'')) # '\'' (char) |
|
1981 self.assertEquals('\'', collapse('\'\\\'')) # '\' (bad) |
|
1982 self.assertEquals('', collapse('\\012')) # '\012' (char) |
|
1983 self.assertEquals('', collapse('\\xfF0')) # '\xfF0' (char) |
|
1984 self.assertEquals('', collapse('\\n')) # '\n' (char) |
|
1985 self.assertEquals('\#', collapse('\\#')) # '\#' (bad) |
|
1986 |
|
1987 self.assertEquals('StringReplace(body, "", "");', |
|
1988 collapse('StringReplace(body, "\\\\", "\\\\\\\\");')) |
|
1989 self.assertEquals('\'\' ""', |
|
1990 collapse('\'"\' "foo"')) |
|
1991 |
|
1992 |
|
1993 class OrderOfIncludesTest(CppStyleTestBase): |
|
1994 def setUp(self): |
|
1995 self.include_state = cpp_style._IncludeState() |
|
1996 |
|
1997 # Cheat os.path.abspath called in FileInfo class. |
|
1998 self.os_path_abspath_orig = os.path.abspath |
|
1999 os.path.abspath = lambda value: value |
|
2000 |
|
2001 def tearDown(self): |
|
2002 os.path.abspath = self.os_path_abspath_orig |
|
2003 |
|
2004 def test_try_drop_common_suffixes(self): |
|
2005 self.assertEqual('foo/foo', cpp_style._drop_common_suffixes('foo/foo-inl.h')) |
|
2006 self.assertEqual('foo/bar/foo', |
|
2007 cpp_style._drop_common_suffixes('foo/bar/foo_inl.h')) |
|
2008 self.assertEqual('foo/foo', cpp_style._drop_common_suffixes('foo/foo.cpp')) |
|
2009 self.assertEqual('foo/foo_unusualinternal', |
|
2010 cpp_style._drop_common_suffixes('foo/foo_unusualinternal.h')) |
|
2011 self.assertEqual('', |
|
2012 cpp_style._drop_common_suffixes('_test.cpp')) |
|
2013 self.assertEqual('test', |
|
2014 cpp_style._drop_common_suffixes('test.cpp')) |
|
2015 |
|
2016 |
|
2017 class OrderOfIncludesTest(CppStyleTestBase): |
|
2018 def setUp(self): |
|
2019 self.include_state = cpp_style._IncludeState() |
|
2020 |
|
2021 # Cheat os.path.abspath called in FileInfo class. |
|
2022 self.os_path_abspath_orig = os.path.abspath |
|
2023 os.path.abspath = lambda value: value |
|
2024 |
|
2025 def tearDown(self): |
|
2026 os.path.abspath = self.os_path_abspath_orig |
|
2027 |
|
2028 def test_check_next_include_order__no_config(self): |
|
2029 self.assertEqual('Header file should not contain WebCore config.h.', |
|
2030 self.include_state.check_next_include_order(cpp_style._CONFIG_HEADER, True)) |
|
2031 |
|
2032 def test_check_next_include_order__no_self(self): |
|
2033 self.assertEqual('Header file should not contain itself.', |
|
2034 self.include_state.check_next_include_order(cpp_style._PRIMARY_HEADER, True)) |
|
2035 # Test actual code to make sure that header types are correctly assigned. |
|
2036 self.assert_language_rules_check('Foo.h', |
|
2037 '#include "Foo.h"\n', |
|
2038 'Header file should not contain itself. Should be: alphabetically sorted.' |
|
2039 ' [build/include_order] [4]') |
|
2040 self.assert_language_rules_check('FooBar.h', |
|
2041 '#include "Foo.h"\n', |
|
2042 '') |
|
2043 |
|
2044 def test_check_next_include_order__likely_then_config(self): |
|
2045 self.assertEqual('Found header this file implements before WebCore config.h.', |
|
2046 self.include_state.check_next_include_order(cpp_style._PRIMARY_HEADER, False)) |
|
2047 self.assertEqual('Found WebCore config.h after a header this file implements.', |
|
2048 self.include_state.check_next_include_order(cpp_style._CONFIG_HEADER, False)) |
|
2049 |
|
2050 def test_check_next_include_order__other_then_config(self): |
|
2051 self.assertEqual('Found other header before WebCore config.h.', |
|
2052 self.include_state.check_next_include_order(cpp_style._OTHER_HEADER, False)) |
|
2053 self.assertEqual('Found WebCore config.h after other header.', |
|
2054 self.include_state.check_next_include_order(cpp_style._CONFIG_HEADER, False)) |
|
2055 |
|
2056 def test_check_next_include_order__config_then_other_then_likely(self): |
|
2057 self.assertEqual('', self.include_state.check_next_include_order(cpp_style._CONFIG_HEADER, False)) |
|
2058 self.assertEqual('Found other header before a header this file implements.', |
|
2059 self.include_state.check_next_include_order(cpp_style._OTHER_HEADER, False)) |
|
2060 self.assertEqual('Found header this file implements after other header.', |
|
2061 self.include_state.check_next_include_order(cpp_style._PRIMARY_HEADER, False)) |
|
2062 |
|
2063 def test_check_alphabetical_include_order(self): |
|
2064 self.assert_language_rules_check('foo.h', |
|
2065 '#include "a.h"\n' |
|
2066 '#include "c.h"\n' |
|
2067 '#include "b.h"\n', |
|
2068 'Alphabetical sorting problem. [build/include_order] [4]') |
|
2069 |
|
2070 self.assert_language_rules_check('foo.h', |
|
2071 '#include "a.h"\n' |
|
2072 '#include "b.h"\n' |
|
2073 '#include "c.h"\n', |
|
2074 '') |
|
2075 |
|
2076 self.assert_language_rules_check('foo.h', |
|
2077 '#include <assert.h>\n' |
|
2078 '#include "bar.h"\n', |
|
2079 'Alphabetical sorting problem. [build/include_order] [4]') |
|
2080 |
|
2081 self.assert_language_rules_check('foo.h', |
|
2082 '#include "bar.h"\n' |
|
2083 '#include <assert.h>\n', |
|
2084 '') |
|
2085 |
|
2086 def test_check_line_break_after_own_header(self): |
|
2087 self.assert_language_rules_check('foo.cpp', |
|
2088 '#include "config.h"\n' |
|
2089 '#include "foo.h"\n' |
|
2090 '#include "bar.h"\n', |
|
2091 'You should add a blank line after implementation file\'s own header. [build/include_order] [4]') |
|
2092 |
|
2093 self.assert_language_rules_check('foo.cpp', |
|
2094 '#include "config.h"\n' |
|
2095 '#include "foo.h"\n' |
|
2096 '\n' |
|
2097 '#include "bar.h"\n', |
|
2098 '') |
|
2099 |
|
2100 def test_check_preprocessor_in_include_section(self): |
|
2101 self.assert_language_rules_check('foo.cpp', |
|
2102 '#include "config.h"\n' |
|
2103 '#include "foo.h"\n' |
|
2104 '\n' |
|
2105 '#ifdef BAZ\n' |
|
2106 '#include "baz.h"\n' |
|
2107 '#else\n' |
|
2108 '#include "foobar.h"\n' |
|
2109 '#endif"\n' |
|
2110 '#include "bar.h"\n', # No flag because previous is in preprocessor section |
|
2111 '') |
|
2112 |
|
2113 self.assert_language_rules_check('foo.cpp', |
|
2114 '#include "config.h"\n' |
|
2115 '#include "foo.h"\n' |
|
2116 '\n' |
|
2117 '#ifdef BAZ\n' |
|
2118 '#include "baz.h"\n' |
|
2119 '#endif"\n' |
|
2120 '#include "bar.h"\n' |
|
2121 '#include "a.h"\n', # Should still flag this. |
|
2122 'Alphabetical sorting problem. [build/include_order] [4]') |
|
2123 |
|
2124 self.assert_language_rules_check('foo.cpp', |
|
2125 '#include "config.h"\n' |
|
2126 '#include "foo.h"\n' |
|
2127 '\n' |
|
2128 '#ifdef BAZ\n' |
|
2129 '#include "baz.h"\n' |
|
2130 '#include "bar.h"\n' #Should still flag this |
|
2131 '#endif"\n', |
|
2132 'Alphabetical sorting problem. [build/include_order] [4]') |
|
2133 |
|
2134 self.assert_language_rules_check('foo.cpp', |
|
2135 '#include "config.h"\n' |
|
2136 '#include "foo.h"\n' |
|
2137 '\n' |
|
2138 '#ifdef BAZ\n' |
|
2139 '#include "baz.h"\n' |
|
2140 '#endif"\n' |
|
2141 '#ifdef FOOBAR\n' |
|
2142 '#include "foobar.h"\n' |
|
2143 '#endif"\n' |
|
2144 '#include "bar.h"\n' |
|
2145 '#include "a.h"\n', # Should still flag this. |
|
2146 'Alphabetical sorting problem. [build/include_order] [4]') |
|
2147 |
|
2148 # Check that after an already included error, the sorting rules still work. |
|
2149 self.assert_language_rules_check('foo.cpp', |
|
2150 '#include "config.h"\n' |
|
2151 '#include "foo.h"\n' |
|
2152 '\n' |
|
2153 '#include "foo.h"\n' |
|
2154 '#include "g.h"\n', |
|
2155 '"foo.h" already included at foo.cpp:1 [build/include] [4]') |
|
2156 |
|
2157 def test_check_wtf_includes(self): |
|
2158 self.assert_language_rules_check('foo.cpp', |
|
2159 '#include "config.h"\n' |
|
2160 '#include "foo.h"\n' |
|
2161 '\n' |
|
2162 '#include <wtf/Assertions.h>\n', |
|
2163 '') |
|
2164 self.assert_language_rules_check('foo.cpp', |
|
2165 '#include "config.h"\n' |
|
2166 '#include "foo.h"\n' |
|
2167 '\n' |
|
2168 '#include "wtf/Assertions.h"\n', |
|
2169 'wtf includes should be <wtf/file.h> instead of "wtf/file.h".' |
|
2170 ' [build/include] [4]') |
|
2171 |
|
2172 def test_classify_include(self): |
|
2173 classify_include = cpp_style._classify_include |
|
2174 include_state = cpp_style._IncludeState() |
|
2175 self.assertEqual(cpp_style._CONFIG_HEADER, |
|
2176 classify_include('foo/foo.cpp', |
|
2177 'config.h', |
|
2178 False, include_state)) |
|
2179 self.assertEqual(cpp_style._PRIMARY_HEADER, |
|
2180 classify_include('foo/internal/foo.cpp', |
|
2181 'foo/public/foo.h', |
|
2182 False, include_state)) |
|
2183 self.assertEqual(cpp_style._PRIMARY_HEADER, |
|
2184 classify_include('foo/internal/foo.cpp', |
|
2185 'foo/other/public/foo.h', |
|
2186 False, include_state)) |
|
2187 self.assertEqual(cpp_style._OTHER_HEADER, |
|
2188 classify_include('foo/internal/foo.cpp', |
|
2189 'foo/other/public/foop.h', |
|
2190 False, include_state)) |
|
2191 self.assertEqual(cpp_style._OTHER_HEADER, |
|
2192 classify_include('foo/foo.cpp', |
|
2193 'string', |
|
2194 True, include_state)) |
|
2195 self.assertEqual(cpp_style._PRIMARY_HEADER, |
|
2196 classify_include('fooCustom.cpp', |
|
2197 'foo.h', |
|
2198 False, include_state)) |
|
2199 self.assertEqual(cpp_style._PRIMARY_HEADER, |
|
2200 classify_include('PrefixFooCustom.cpp', |
|
2201 'Foo.h', |
|
2202 False, include_state)) |
|
2203 self.assertEqual(cpp_style._MOC_HEADER, |
|
2204 classify_include('foo.cpp', |
|
2205 'foo.moc', |
|
2206 False, include_state)) |
|
2207 self.assertEqual(cpp_style._MOC_HEADER, |
|
2208 classify_include('foo.cpp', |
|
2209 'moc_foo.cpp', |
|
2210 False, include_state)) |
|
2211 # Tricky example where both includes might be classified as primary. |
|
2212 self.assert_language_rules_check('ScrollbarThemeWince.cpp', |
|
2213 '#include "config.h"\n' |
|
2214 '#include "ScrollbarThemeWince.h"\n' |
|
2215 '\n' |
|
2216 '#include "Scrollbar.h"\n', |
|
2217 '') |
|
2218 self.assert_language_rules_check('ScrollbarThemeWince.cpp', |
|
2219 '#include "config.h"\n' |
|
2220 '#include "Scrollbar.h"\n' |
|
2221 '\n' |
|
2222 '#include "ScrollbarThemeWince.h"\n', |
|
2223 'Found header this file implements after a header this file implements.' |
|
2224 ' Should be: config.h, primary header, blank line, and then alphabetically sorted.' |
|
2225 ' [build/include_order] [4]') |
|
2226 self.assert_language_rules_check('ResourceHandleWin.cpp', |
|
2227 '#include "config.h"\n' |
|
2228 '#include "ResourceHandle.h"\n' |
|
2229 '\n' |
|
2230 '#include "ResourceHandleWin.h"\n', |
|
2231 '') |
|
2232 |
|
2233 def test_try_drop_common_suffixes(self): |
|
2234 self.assertEqual('foo/foo', cpp_style._drop_common_suffixes('foo/foo-inl.h')) |
|
2235 self.assertEqual('foo/bar/foo', |
|
2236 cpp_style._drop_common_suffixes('foo/bar/foo_inl.h')) |
|
2237 self.assertEqual('foo/foo', cpp_style._drop_common_suffixes('foo/foo.cpp')) |
|
2238 self.assertEqual('foo/foo_unusualinternal', |
|
2239 cpp_style._drop_common_suffixes('foo/foo_unusualinternal.h')) |
|
2240 self.assertEqual('', |
|
2241 cpp_style._drop_common_suffixes('_test.cpp')) |
|
2242 self.assertEqual('test', |
|
2243 cpp_style._drop_common_suffixes('test.cpp')) |
|
2244 self.assertEqual('test', |
|
2245 cpp_style._drop_common_suffixes('test.cpp')) |
|
2246 |
|
2247 class CheckForFunctionLengthsTest(CppStyleTestBase): |
|
2248 def setUp(self): |
|
2249 # Reducing these thresholds for the tests speeds up tests significantly. |
|
2250 self.old_normal_trigger = cpp_style._FunctionState._NORMAL_TRIGGER |
|
2251 self.old_test_trigger = cpp_style._FunctionState._TEST_TRIGGER |
|
2252 |
|
2253 cpp_style._FunctionState._NORMAL_TRIGGER = 10 |
|
2254 cpp_style._FunctionState._TEST_TRIGGER = 25 |
|
2255 |
|
2256 def tearDown(self): |
|
2257 cpp_style._FunctionState._NORMAL_TRIGGER = self.old_normal_trigger |
|
2258 cpp_style._FunctionState._TEST_TRIGGER = self.old_test_trigger |
|
2259 |
|
2260 # FIXME: Eliminate the need for this function. |
|
2261 def set_min_confidence(self, min_confidence): |
|
2262 """Set new test confidence and return old test confidence.""" |
|
2263 old_min_confidence = self.min_confidence |
|
2264 self.min_confidence = min_confidence |
|
2265 return old_min_confidence |
|
2266 |
|
2267 def assert_function_lengths_check(self, code, expected_message): |
|
2268 """Check warnings for long function bodies are as expected. |
|
2269 |
|
2270 Args: |
|
2271 code: C++ source code expected to generate a warning message. |
|
2272 expected_message: Message expected to be generated by the C++ code. |
|
2273 """ |
|
2274 self.assertEquals(expected_message, |
|
2275 self.perform_function_lengths_check(code)) |
|
2276 |
|
2277 def trigger_lines(self, error_level): |
|
2278 """Return number of lines needed to trigger a function length warning. |
|
2279 |
|
2280 Args: |
|
2281 error_level: --v setting for cpp_style. |
|
2282 |
|
2283 Returns: |
|
2284 Number of lines needed to trigger a function length warning. |
|
2285 """ |
|
2286 return cpp_style._FunctionState._NORMAL_TRIGGER * 2 ** error_level |
|
2287 |
|
2288 def trigger_test_lines(self, error_level): |
|
2289 """Return number of lines needed to trigger a test function length warning. |
|
2290 |
|
2291 Args: |
|
2292 error_level: --v setting for cpp_style. |
|
2293 |
|
2294 Returns: |
|
2295 Number of lines needed to trigger a test function length warning. |
|
2296 """ |
|
2297 return cpp_style._FunctionState._TEST_TRIGGER * 2 ** error_level |
|
2298 |
|
2299 def assert_function_length_check_definition(self, lines, error_level): |
|
2300 """Generate long function definition and check warnings are as expected. |
|
2301 |
|
2302 Args: |
|
2303 lines: Number of lines to generate. |
|
2304 error_level: --v setting for cpp_style. |
|
2305 """ |
|
2306 trigger_level = self.trigger_lines(self.min_confidence) |
|
2307 self.assert_function_lengths_check( |
|
2308 'void test(int x)' + self.function_body(lines), |
|
2309 ('Small and focused functions are preferred: ' |
|
2310 'test() has %d non-comment lines ' |
|
2311 '(error triggered by exceeding %d lines).' |
|
2312 ' [readability/fn_size] [%d]' |
|
2313 % (lines, trigger_level, error_level))) |
|
2314 |
|
2315 def assert_function_length_check_definition_ok(self, lines): |
|
2316 """Generate shorter function definition and check no warning is produced. |
|
2317 |
|
2318 Args: |
|
2319 lines: Number of lines to generate. |
|
2320 """ |
|
2321 self.assert_function_lengths_check( |
|
2322 'void test(int x)' + self.function_body(lines), |
|
2323 '') |
|
2324 |
|
2325 def assert_function_length_check_at_error_level(self, error_level): |
|
2326 """Generate and check function at the trigger level for --v setting. |
|
2327 |
|
2328 Args: |
|
2329 error_level: --v setting for cpp_style. |
|
2330 """ |
|
2331 self.assert_function_length_check_definition(self.trigger_lines(error_level), |
|
2332 error_level) |
|
2333 |
|
2334 def assert_function_length_check_below_error_level(self, error_level): |
|
2335 """Generate and check function just below the trigger level for --v setting. |
|
2336 |
|
2337 Args: |
|
2338 error_level: --v setting for cpp_style. |
|
2339 """ |
|
2340 self.assert_function_length_check_definition(self.trigger_lines(error_level) - 1, |
|
2341 error_level - 1) |
|
2342 |
|
2343 def assert_function_length_check_above_error_level(self, error_level): |
|
2344 """Generate and check function just above the trigger level for --v setting. |
|
2345 |
|
2346 Args: |
|
2347 error_level: --v setting for cpp_style. |
|
2348 """ |
|
2349 self.assert_function_length_check_definition(self.trigger_lines(error_level) + 1, |
|
2350 error_level) |
|
2351 |
|
2352 def function_body(self, number_of_lines): |
|
2353 return ' {\n' + ' this_is_just_a_test();\n' * number_of_lines + '}' |
|
2354 |
|
2355 def function_body_with_blank_lines(self, number_of_lines): |
|
2356 return ' {\n' + ' this_is_just_a_test();\n\n' * number_of_lines + '}' |
|
2357 |
|
2358 def function_body_with_no_lints(self, number_of_lines): |
|
2359 return ' {\n' + ' this_is_just_a_test(); // NOLINT\n' * number_of_lines + '}' |
|
2360 |
|
2361 # Test line length checks. |
|
2362 def test_function_length_check_declaration(self): |
|
2363 self.assert_function_lengths_check( |
|
2364 'void test();', # Not a function definition |
|
2365 '') |
|
2366 |
|
2367 def test_function_length_check_declaration_with_block_following(self): |
|
2368 self.assert_function_lengths_check( |
|
2369 ('void test();\n' |
|
2370 + self.function_body(66)), # Not a function definition |
|
2371 '') |
|
2372 |
|
2373 def test_function_length_check_class_definition(self): |
|
2374 self.assert_function_lengths_check( # Not a function definition |
|
2375 'class Test' + self.function_body(66) + ';', |
|
2376 '') |
|
2377 |
|
2378 def test_function_length_check_trivial(self): |
|
2379 self.assert_function_lengths_check( |
|
2380 'void test() {}', # Not counted |
|
2381 '') |
|
2382 |
|
2383 def test_function_length_check_empty(self): |
|
2384 self.assert_function_lengths_check( |
|
2385 'void test() {\n}', |
|
2386 '') |
|
2387 |
|
2388 def test_function_length_check_definition_below_severity0(self): |
|
2389 old_min_confidence = self.set_min_confidence(0) |
|
2390 self.assert_function_length_check_definition_ok(self.trigger_lines(0) - 1) |
|
2391 self.set_min_confidence(old_min_confidence) |
|
2392 |
|
2393 def test_function_length_check_definition_at_severity0(self): |
|
2394 old_min_confidence = self.set_min_confidence(0) |
|
2395 self.assert_function_length_check_definition_ok(self.trigger_lines(0)) |
|
2396 self.set_min_confidence(old_min_confidence) |
|
2397 |
|
2398 def test_function_length_check_definition_above_severity0(self): |
|
2399 old_min_confidence = self.set_min_confidence(0) |
|
2400 self.assert_function_length_check_above_error_level(0) |
|
2401 self.set_min_confidence(old_min_confidence) |
|
2402 |
|
2403 def test_function_length_check_definition_below_severity1v0(self): |
|
2404 old_min_confidence = self.set_min_confidence(0) |
|
2405 self.assert_function_length_check_below_error_level(1) |
|
2406 self.set_min_confidence(old_min_confidence) |
|
2407 |
|
2408 def test_function_length_check_definition_at_severity1v0(self): |
|
2409 old_min_confidence = self.set_min_confidence(0) |
|
2410 self.assert_function_length_check_at_error_level(1) |
|
2411 self.set_min_confidence(old_min_confidence) |
|
2412 |
|
2413 def test_function_length_check_definition_below_severity1(self): |
|
2414 self.assert_function_length_check_definition_ok(self.trigger_lines(1) - 1) |
|
2415 |
|
2416 def test_function_length_check_definition_at_severity1(self): |
|
2417 self.assert_function_length_check_definition_ok(self.trigger_lines(1)) |
|
2418 |
|
2419 def test_function_length_check_definition_above_severity1(self): |
|
2420 self.assert_function_length_check_above_error_level(1) |
|
2421 |
|
2422 def test_function_length_check_definition_severity1_plus_blanks(self): |
|
2423 error_level = 1 |
|
2424 error_lines = self.trigger_lines(error_level) + 1 |
|
2425 trigger_level = self.trigger_lines(self.min_confidence) |
|
2426 self.assert_function_lengths_check( |
|
2427 'void test_blanks(int x)' + self.function_body(error_lines), |
|
2428 ('Small and focused functions are preferred: ' |
|
2429 'test_blanks() has %d non-comment lines ' |
|
2430 '(error triggered by exceeding %d lines).' |
|
2431 ' [readability/fn_size] [%d]') |
|
2432 % (error_lines, trigger_level, error_level)) |
|
2433 |
|
2434 def test_function_length_check_complex_definition_severity1(self): |
|
2435 error_level = 1 |
|
2436 error_lines = self.trigger_lines(error_level) + 1 |
|
2437 trigger_level = self.trigger_lines(self.min_confidence) |
|
2438 self.assert_function_lengths_check( |
|
2439 ('my_namespace::my_other_namespace::MyVeryLongTypeName*\n' |
|
2440 'my_namespace::my_other_namespace::MyFunction(int arg1, char* arg2)' |
|
2441 + self.function_body(error_lines)), |
|
2442 ('Small and focused functions are preferred: ' |
|
2443 'my_namespace::my_other_namespace::MyFunction()' |
|
2444 ' has %d non-comment lines ' |
|
2445 '(error triggered by exceeding %d lines).' |
|
2446 ' [readability/fn_size] [%d]') |
|
2447 % (error_lines, trigger_level, error_level)) |
|
2448 |
|
2449 def test_function_length_check_definition_severity1_for_test(self): |
|
2450 error_level = 1 |
|
2451 error_lines = self.trigger_test_lines(error_level) + 1 |
|
2452 trigger_level = self.trigger_test_lines(self.min_confidence) |
|
2453 self.assert_function_lengths_check( |
|
2454 'TEST_F(Test, Mutator)' + self.function_body(error_lines), |
|
2455 ('Small and focused functions are preferred: ' |
|
2456 'TEST_F(Test, Mutator) has %d non-comment lines ' |
|
2457 '(error triggered by exceeding %d lines).' |
|
2458 ' [readability/fn_size] [%d]') |
|
2459 % (error_lines, trigger_level, error_level)) |
|
2460 |
|
2461 def test_function_length_check_definition_severity1_for_split_line_test(self): |
|
2462 error_level = 1 |
|
2463 error_lines = self.trigger_test_lines(error_level) + 1 |
|
2464 trigger_level = self.trigger_test_lines(self.min_confidence) |
|
2465 self.assert_function_lengths_check( |
|
2466 ('TEST_F(GoogleUpdateRecoveryRegistryProtectedTest,\n' |
|
2467 ' FixGoogleUpdate_AllValues_MachineApp)' # note: 4 spaces |
|
2468 + self.function_body(error_lines)), |
|
2469 ('Small and focused functions are preferred: ' |
|
2470 'TEST_F(GoogleUpdateRecoveryRegistryProtectedTest, ' # 1 space |
|
2471 'FixGoogleUpdate_AllValues_MachineApp) has %d non-comment lines ' |
|
2472 '(error triggered by exceeding %d lines).' |
|
2473 ' [readability/fn_size] [%d]') |
|
2474 % (error_lines+1, trigger_level, error_level)) |
|
2475 |
|
2476 def test_function_length_check_definition_severity1_for_bad_test_doesnt_break(self): |
|
2477 error_level = 1 |
|
2478 error_lines = self.trigger_test_lines(error_level) + 1 |
|
2479 trigger_level = self.trigger_test_lines(self.min_confidence) |
|
2480 self.assert_function_lengths_check( |
|
2481 ('TEST_F(' |
|
2482 + self.function_body(error_lines)), |
|
2483 ('Small and focused functions are preferred: ' |
|
2484 'TEST_F has %d non-comment lines ' |
|
2485 '(error triggered by exceeding %d lines).' |
|
2486 ' [readability/fn_size] [%d]') |
|
2487 % (error_lines, trigger_level, error_level)) |
|
2488 |
|
2489 def test_function_length_check_definition_severity1_with_embedded_no_lints(self): |
|
2490 error_level = 1 |
|
2491 error_lines = self.trigger_lines(error_level) + 1 |
|
2492 trigger_level = self.trigger_lines(self.min_confidence) |
|
2493 self.assert_function_lengths_check( |
|
2494 'void test(int x)' + self.function_body_with_no_lints(error_lines), |
|
2495 ('Small and focused functions are preferred: ' |
|
2496 'test() has %d non-comment lines ' |
|
2497 '(error triggered by exceeding %d lines).' |
|
2498 ' [readability/fn_size] [%d]') |
|
2499 % (error_lines, trigger_level, error_level)) |
|
2500 |
|
2501 def test_function_length_check_definition_severity1_with_no_lint(self): |
|
2502 self.assert_function_lengths_check( |
|
2503 ('void test(int x)' + self.function_body(self.trigger_lines(1)) |
|
2504 + ' // NOLINT -- long function'), |
|
2505 '') |
|
2506 |
|
2507 def test_function_length_check_definition_below_severity2(self): |
|
2508 self.assert_function_length_check_below_error_level(2) |
|
2509 |
|
2510 def test_function_length_check_definition_severity2(self): |
|
2511 self.assert_function_length_check_at_error_level(2) |
|
2512 |
|
2513 def test_function_length_check_definition_above_severity2(self): |
|
2514 self.assert_function_length_check_above_error_level(2) |
|
2515 |
|
2516 def test_function_length_check_definition_below_severity3(self): |
|
2517 self.assert_function_length_check_below_error_level(3) |
|
2518 |
|
2519 def test_function_length_check_definition_severity3(self): |
|
2520 self.assert_function_length_check_at_error_level(3) |
|
2521 |
|
2522 def test_function_length_check_definition_above_severity3(self): |
|
2523 self.assert_function_length_check_above_error_level(3) |
|
2524 |
|
2525 def test_function_length_check_definition_below_severity4(self): |
|
2526 self.assert_function_length_check_below_error_level(4) |
|
2527 |
|
2528 def test_function_length_check_definition_severity4(self): |
|
2529 self.assert_function_length_check_at_error_level(4) |
|
2530 |
|
2531 def test_function_length_check_definition_above_severity4(self): |
|
2532 self.assert_function_length_check_above_error_level(4) |
|
2533 |
|
2534 def test_function_length_check_definition_below_severity5(self): |
|
2535 self.assert_function_length_check_below_error_level(5) |
|
2536 |
|
2537 def test_function_length_check_definition_at_severity5(self): |
|
2538 self.assert_function_length_check_at_error_level(5) |
|
2539 |
|
2540 def test_function_length_check_definition_above_severity5(self): |
|
2541 self.assert_function_length_check_above_error_level(5) |
|
2542 |
|
2543 def test_function_length_check_definition_huge_lines(self): |
|
2544 # 5 is the limit |
|
2545 self.assert_function_length_check_definition(self.trigger_lines(10), 5) |
|
2546 |
|
2547 def test_function_length_not_determinable(self): |
|
2548 # Macro invocation without terminating semicolon. |
|
2549 self.assert_function_lengths_check( |
|
2550 'MACRO(arg)', |
|
2551 '') |
|
2552 |
|
2553 # Macro with underscores |
|
2554 self.assert_function_lengths_check( |
|
2555 'MACRO_WITH_UNDERSCORES(arg1, arg2, arg3)', |
|
2556 '') |
|
2557 |
|
2558 self.assert_function_lengths_check( |
|
2559 'NonMacro(arg)', |
|
2560 'Lint failed to find start of function body.' |
|
2561 ' [readability/fn_size] [5]') |
|
2562 |
|
2563 |
|
2564 class NoNonVirtualDestructorsTest(CppStyleTestBase): |
|
2565 |
|
2566 def test_no_error(self): |
|
2567 self.assert_multi_line_lint( |
|
2568 '''class Foo { |
|
2569 virtual ~Foo(); |
|
2570 virtual void foo(); |
|
2571 };''', |
|
2572 '') |
|
2573 |
|
2574 self.assert_multi_line_lint( |
|
2575 '''class Foo { |
|
2576 virtual inline ~Foo(); |
|
2577 virtual void foo(); |
|
2578 };''', |
|
2579 '') |
|
2580 |
|
2581 self.assert_multi_line_lint( |
|
2582 '''class Foo { |
|
2583 inline virtual ~Foo(); |
|
2584 virtual void foo(); |
|
2585 };''', |
|
2586 '') |
|
2587 |
|
2588 self.assert_multi_line_lint( |
|
2589 '''class Foo::Goo { |
|
2590 virtual ~Goo(); |
|
2591 virtual void goo(); |
|
2592 };''', |
|
2593 '') |
|
2594 self.assert_multi_line_lint( |
|
2595 'class Foo { void foo(); };', |
|
2596 'More than one command on the same line [whitespace/newline] [4]') |
|
2597 |
|
2598 self.assert_multi_line_lint( |
|
2599 '''class Qualified::Goo : public Foo { |
|
2600 virtual void goo(); |
|
2601 };''', |
|
2602 '') |
|
2603 |
|
2604 self.assert_multi_line_lint( |
|
2605 # Line-ending : |
|
2606 '''class Goo : |
|
2607 public Foo { |
|
2608 virtual void goo(); |
|
2609 };''', |
|
2610 'Labels should always be indented at least one space. If this is a ' |
|
2611 'member-initializer list in a constructor, the colon should be on the ' |
|
2612 'line after the definition header. [whitespace/labels] [4]') |
|
2613 |
|
2614 def test_no_destructor_when_virtual_needed(self): |
|
2615 self.assert_multi_line_lint_re( |
|
2616 '''class Foo { |
|
2617 virtual void foo(); |
|
2618 };''', |
|
2619 'The class Foo probably needs a virtual destructor') |
|
2620 |
|
2621 def test_destructor_non_virtual_when_virtual_needed(self): |
|
2622 self.assert_multi_line_lint_re( |
|
2623 '''class Foo { |
|
2624 ~Foo(); |
|
2625 virtual void foo(); |
|
2626 };''', |
|
2627 'The class Foo probably needs a virtual destructor') |
|
2628 |
|
2629 def test_no_warn_when_derived(self): |
|
2630 self.assert_multi_line_lint( |
|
2631 '''class Foo : public Goo { |
|
2632 virtual void foo(); |
|
2633 };''', |
|
2634 '') |
|
2635 |
|
2636 def test_internal_braces(self): |
|
2637 self.assert_multi_line_lint_re( |
|
2638 '''class Foo { |
|
2639 enum Goo { |
|
2640 GOO |
|
2641 }; |
|
2642 virtual void foo(); |
|
2643 };''', |
|
2644 'The class Foo probably needs a virtual destructor') |
|
2645 |
|
2646 def test_inner_class_needs_virtual_destructor(self): |
|
2647 self.assert_multi_line_lint_re( |
|
2648 '''class Foo { |
|
2649 class Goo { |
|
2650 virtual void goo(); |
|
2651 }; |
|
2652 };''', |
|
2653 'The class Goo probably needs a virtual destructor') |
|
2654 |
|
2655 def test_outer_class_needs_virtual_destructor(self): |
|
2656 self.assert_multi_line_lint_re( |
|
2657 '''class Foo { |
|
2658 class Goo { |
|
2659 }; |
|
2660 virtual void foo(); |
|
2661 };''', |
|
2662 'The class Foo probably needs a virtual destructor') |
|
2663 |
|
2664 def test_qualified_class_needs_virtual_destructor(self): |
|
2665 self.assert_multi_line_lint_re( |
|
2666 '''class Qualified::Foo { |
|
2667 virtual void foo(); |
|
2668 };''', |
|
2669 'The class Qualified::Foo probably needs a virtual destructor') |
|
2670 |
|
2671 def test_multi_line_declaration_no_error(self): |
|
2672 self.assert_multi_line_lint_re( |
|
2673 '''class Foo |
|
2674 : public Goo { |
|
2675 virtual void foo(); |
|
2676 };''', |
|
2677 '') |
|
2678 |
|
2679 def test_multi_line_declaration_with_error(self): |
|
2680 self.assert_multi_line_lint( |
|
2681 '''class Foo |
|
2682 { |
|
2683 virtual void foo(); |
|
2684 };''', |
|
2685 ['This { should be at the end of the previous line ' |
|
2686 '[whitespace/braces] [4]', |
|
2687 'The class Foo probably needs a virtual destructor due to having ' |
|
2688 'virtual method(s), one declared at line 2. [runtime/virtual] [4]']) |
|
2689 |
|
2690 |
|
2691 class WebKitStyleTest(CppStyleTestBase): |
|
2692 |
|
2693 # for http://webkit.org/coding/coding-style.html |
|
2694 def test_indentation(self): |
|
2695 # 1. Use spaces, not tabs. Tabs should only appear in files that |
|
2696 # require them for semantic meaning, like Makefiles. |
|
2697 self.assert_multi_line_lint( |
|
2698 'class Foo {\n' |
|
2699 ' int goo;\n' |
|
2700 '};', |
|
2701 '') |
|
2702 self.assert_multi_line_lint( |
|
2703 'class Foo {\n' |
|
2704 '\tint goo;\n' |
|
2705 '};', |
|
2706 'Tab found; better to use spaces [whitespace/tab] [1]') |
|
2707 |
|
2708 # 2. The indent size is 4 spaces. |
|
2709 self.assert_multi_line_lint( |
|
2710 'class Foo {\n' |
|
2711 ' int goo;\n' |
|
2712 '};', |
|
2713 '') |
|
2714 self.assert_multi_line_lint( |
|
2715 'class Foo {\n' |
|
2716 ' int goo;\n' |
|
2717 '};', |
|
2718 'Weird number of spaces at line-start. Are you using a 4-space indent? [whitespace/indent] [3]') |
|
2719 # FIXME: No tests for 8-spaces. |
|
2720 |
|
2721 # 3. In a header, code inside a namespace should not be indented. |
|
2722 self.assert_multi_line_lint( |
|
2723 'namespace WebCore {\n\n' |
|
2724 'class Document {\n' |
|
2725 ' int myVariable;\n' |
|
2726 '};\n' |
|
2727 '}', |
|
2728 '', |
|
2729 'foo.h') |
|
2730 self.assert_multi_line_lint( |
|
2731 'namespace OuterNamespace {\n' |
|
2732 ' namespace InnerNamespace {\n' |
|
2733 ' class Document {\n' |
|
2734 '};\n' |
|
2735 '};\n' |
|
2736 '}', |
|
2737 'Code inside a namespace should not be indented. [whitespace/indent] [4]', |
|
2738 'foo.h') |
|
2739 self.assert_multi_line_lint( |
|
2740 'namespace OuterNamespace {\n' |
|
2741 ' class Document {\n' |
|
2742 ' namespace InnerNamespace {\n' |
|
2743 '};\n' |
|
2744 '};\n' |
|
2745 '}', |
|
2746 'Code inside a namespace should not be indented. [whitespace/indent] [4]', |
|
2747 'foo.h') |
|
2748 self.assert_multi_line_lint( |
|
2749 'namespace WebCore {\n' |
|
2750 '#if 0\n' |
|
2751 ' class Document {\n' |
|
2752 '};\n' |
|
2753 '#endif\n' |
|
2754 '}', |
|
2755 'Code inside a namespace should not be indented. [whitespace/indent] [4]', |
|
2756 'foo.h') |
|
2757 self.assert_multi_line_lint( |
|
2758 'namespace WebCore {\n' |
|
2759 'class Document {\n' |
|
2760 '};\n' |
|
2761 '}', |
|
2762 '', |
|
2763 'foo.h') |
|
2764 |
|
2765 # 4. In an implementation file (files with the extension .cpp, .c |
|
2766 # or .mm), code inside a namespace should not be indented. |
|
2767 self.assert_multi_line_lint( |
|
2768 'namespace WebCore {\n\n' |
|
2769 'Document::Foo()\n' |
|
2770 ' : foo(bar)\n' |
|
2771 ' , boo(far)\n' |
|
2772 '{\n' |
|
2773 ' stuff();\n' |
|
2774 '}', |
|
2775 '', |
|
2776 'foo.cpp') |
|
2777 self.assert_multi_line_lint( |
|
2778 'namespace OuterNamespace {\n' |
|
2779 'namespace InnerNamespace {\n' |
|
2780 'Document::Foo() { }\n' |
|
2781 ' void* p;\n' |
|
2782 '}\n' |
|
2783 '}\n', |
|
2784 'Code inside a namespace should not be indented. [whitespace/indent] [4]', |
|
2785 'foo.cpp') |
|
2786 self.assert_multi_line_lint( |
|
2787 'namespace OuterNamespace {\n' |
|
2788 'namespace InnerNamespace {\n' |
|
2789 'Document::Foo() { }\n' |
|
2790 '}\n' |
|
2791 ' void* p;\n' |
|
2792 '}\n', |
|
2793 'Code inside a namespace should not be indented. [whitespace/indent] [4]', |
|
2794 'foo.cpp') |
|
2795 self.assert_multi_line_lint( |
|
2796 'namespace WebCore {\n\n' |
|
2797 ' const char* foo = "start:;"\n' |
|
2798 ' "dfsfsfs";\n' |
|
2799 '}\n', |
|
2800 'Code inside a namespace should not be indented. [whitespace/indent] [4]', |
|
2801 'foo.cpp') |
|
2802 self.assert_multi_line_lint( |
|
2803 'namespace WebCore {\n\n' |
|
2804 'const char* foo(void* a = ";", // ;\n' |
|
2805 ' void* b);\n' |
|
2806 ' void* p;\n' |
|
2807 '}\n', |
|
2808 'Code inside a namespace should not be indented. [whitespace/indent] [4]', |
|
2809 'foo.cpp') |
|
2810 self.assert_multi_line_lint( |
|
2811 'namespace WebCore {\n\n' |
|
2812 'const char* foo[] = {\n' |
|
2813 ' "void* b);", // ;\n' |
|
2814 ' "asfdf",\n' |
|
2815 ' }\n' |
|
2816 ' void* p;\n' |
|
2817 '}\n', |
|
2818 'Code inside a namespace should not be indented. [whitespace/indent] [4]', |
|
2819 'foo.cpp') |
|
2820 self.assert_multi_line_lint( |
|
2821 'namespace WebCore {\n\n' |
|
2822 'const char* foo[] = {\n' |
|
2823 ' "void* b);", // }\n' |
|
2824 ' "asfdf",\n' |
|
2825 ' }\n' |
|
2826 '}\n', |
|
2827 '', |
|
2828 'foo.cpp') |
|
2829 self.assert_multi_line_lint( |
|
2830 ' namespace WebCore {\n\n' |
|
2831 ' void Document::Foo()\n' |
|
2832 ' {\n' |
|
2833 'start: // infinite loops are fun!\n' |
|
2834 ' goto start;\n' |
|
2835 ' }', |
|
2836 'namespace should never be indented. [whitespace/indent] [4]', |
|
2837 'foo.cpp') |
|
2838 self.assert_multi_line_lint( |
|
2839 'namespace WebCore {\n' |
|
2840 ' Document::Foo() { }\n' |
|
2841 '}', |
|
2842 'Code inside a namespace should not be indented.' |
|
2843 ' [whitespace/indent] [4]', |
|
2844 'foo.cpp') |
|
2845 self.assert_multi_line_lint( |
|
2846 'namespace WebCore {\n' |
|
2847 '#define abc(x) x; \\\n' |
|
2848 ' x\n' |
|
2849 '}', |
|
2850 '', |
|
2851 'foo.cpp') |
|
2852 self.assert_multi_line_lint( |
|
2853 'namespace WebCore {\n' |
|
2854 '#define abc(x) x; \\\n' |
|
2855 ' x\n' |
|
2856 ' void* x;' |
|
2857 '}', |
|
2858 'Code inside a namespace should not be indented. [whitespace/indent] [4]', |
|
2859 'foo.cpp') |
|
2860 |
|
2861 # 5. A case label should line up with its switch statement. The |
|
2862 # case statement is indented. |
|
2863 self.assert_multi_line_lint( |
|
2864 ' switch (condition) {\n' |
|
2865 ' case fooCondition:\n' |
|
2866 ' case barCondition:\n' |
|
2867 ' i++;\n' |
|
2868 ' break;\n' |
|
2869 ' default:\n' |
|
2870 ' i--;\n' |
|
2871 ' }\n', |
|
2872 '') |
|
2873 self.assert_multi_line_lint( |
|
2874 ' switch (condition) {\n' |
|
2875 ' case fooCondition:\n' |
|
2876 ' switch (otherCondition) {\n' |
|
2877 ' default:\n' |
|
2878 ' return;\n' |
|
2879 ' }\n' |
|
2880 ' default:\n' |
|
2881 ' i--;\n' |
|
2882 ' }\n', |
|
2883 '') |
|
2884 self.assert_multi_line_lint( |
|
2885 ' switch (condition) {\n' |
|
2886 ' case fooCondition: break;\n' |
|
2887 ' default: return;\n' |
|
2888 ' }\n', |
|
2889 '') |
|
2890 self.assert_multi_line_lint( |
|
2891 ' switch (condition) {\n' |
|
2892 ' case fooCondition:\n' |
|
2893 ' case barCondition:\n' |
|
2894 ' i++;\n' |
|
2895 ' break;\n' |
|
2896 ' default:\n' |
|
2897 ' i--;\n' |
|
2898 ' }\n', |
|
2899 'A case label should not be indented, but line up with its switch statement.' |
|
2900 ' [whitespace/indent] [4]') |
|
2901 self.assert_multi_line_lint( |
|
2902 ' switch (condition) {\n' |
|
2903 ' case fooCondition:\n' |
|
2904 ' break;\n' |
|
2905 ' default:\n' |
|
2906 ' i--;\n' |
|
2907 ' }\n', |
|
2908 'A case label should not be indented, but line up with its switch statement.' |
|
2909 ' [whitespace/indent] [4]') |
|
2910 self.assert_multi_line_lint( |
|
2911 ' switch (condition) {\n' |
|
2912 ' case fooCondition:\n' |
|
2913 ' case barCondition:\n' |
|
2914 ' switch (otherCondition) {\n' |
|
2915 ' default:\n' |
|
2916 ' return;\n' |
|
2917 ' }\n' |
|
2918 ' default:\n' |
|
2919 ' i--;\n' |
|
2920 ' }\n', |
|
2921 'A case label should not be indented, but line up with its switch statement.' |
|
2922 ' [whitespace/indent] [4]') |
|
2923 self.assert_multi_line_lint( |
|
2924 ' switch (condition) {\n' |
|
2925 ' case fooCondition:\n' |
|
2926 ' case barCondition:\n' |
|
2927 ' i++;\n' |
|
2928 ' break;\n\n' |
|
2929 ' default:\n' |
|
2930 ' i--;\n' |
|
2931 ' }\n', |
|
2932 'Non-label code inside switch statements should be indented.' |
|
2933 ' [whitespace/indent] [4]') |
|
2934 self.assert_multi_line_lint( |
|
2935 ' switch (condition) {\n' |
|
2936 ' case fooCondition:\n' |
|
2937 ' case barCondition:\n' |
|
2938 ' switch (otherCondition) {\n' |
|
2939 ' default:\n' |
|
2940 ' return;\n' |
|
2941 ' }\n' |
|
2942 ' default:\n' |
|
2943 ' i--;\n' |
|
2944 ' }\n', |
|
2945 'Non-label code inside switch statements should be indented.' |
|
2946 ' [whitespace/indent] [4]') |
|
2947 |
|
2948 # 6. Boolean expressions at the same nesting level that span |
|
2949 # multiple lines should have their operators on the left side of |
|
2950 # the line instead of the right side. |
|
2951 self.assert_multi_line_lint( |
|
2952 ' return attr->name() == srcAttr\n' |
|
2953 ' || attr->name() == lowsrcAttr;\n', |
|
2954 '') |
|
2955 self.assert_multi_line_lint( |
|
2956 ' return attr->name() == srcAttr ||\n' |
|
2957 ' attr->name() == lowsrcAttr;\n', |
|
2958 'Boolean expressions that span multiple lines should have their ' |
|
2959 'operators on the left side of the line instead of the right side.' |
|
2960 ' [whitespace/operators] [4]') |
|
2961 |
|
2962 def test_spacing(self): |
|
2963 # 1. Do not place spaces around unary operators. |
|
2964 self.assert_multi_line_lint( |
|
2965 'i++;', |
|
2966 '') |
|
2967 self.assert_multi_line_lint( |
|
2968 'i ++;', |
|
2969 'Extra space for operator ++; [whitespace/operators] [4]') |
|
2970 |
|
2971 # 2. Do place spaces around binary and ternary operators. |
|
2972 self.assert_multi_line_lint( |
|
2973 'y = m * x + b;', |
|
2974 '') |
|
2975 self.assert_multi_line_lint( |
|
2976 'f(a, b);', |
|
2977 '') |
|
2978 self.assert_multi_line_lint( |
|
2979 'c = a | b;', |
|
2980 '') |
|
2981 self.assert_multi_line_lint( |
|
2982 'return condition ? 1 : 0;', |
|
2983 '') |
|
2984 self.assert_multi_line_lint( |
|
2985 'y=m*x+b;', |
|
2986 'Missing spaces around = [whitespace/operators] [4]') |
|
2987 self.assert_multi_line_lint( |
|
2988 'f(a,b);', |
|
2989 'Missing space after , [whitespace/comma] [3]') |
|
2990 self.assert_multi_line_lint( |
|
2991 'c = a|b;', |
|
2992 'Missing spaces around | [whitespace/operators] [3]') |
|
2993 # FIXME: We cannot catch this lint error. |
|
2994 # self.assert_multi_line_lint( |
|
2995 # 'return condition ? 1:0;', |
|
2996 # '') |
|
2997 |
|
2998 # 3. Place spaces between control statements and their parentheses. |
|
2999 self.assert_multi_line_lint( |
|
3000 ' if (condition)\n' |
|
3001 ' doIt();\n', |
|
3002 '') |
|
3003 self.assert_multi_line_lint( |
|
3004 ' if(condition)\n' |
|
3005 ' doIt();\n', |
|
3006 'Missing space before ( in if( [whitespace/parens] [5]') |
|
3007 |
|
3008 # 4. Do not place spaces between a function and its parentheses, |
|
3009 # or between a parenthesis and its content. |
|
3010 self.assert_multi_line_lint( |
|
3011 'f(a, b);', |
|
3012 '') |
|
3013 self.assert_multi_line_lint( |
|
3014 'f (a, b);', |
|
3015 'Extra space before ( in function call [whitespace/parens] [4]') |
|
3016 self.assert_multi_line_lint( |
|
3017 'f( a, b );', |
|
3018 ['Extra space after ( in function call [whitespace/parens] [4]', |
|
3019 'Extra space before ) [whitespace/parens] [2]']) |
|
3020 |
|
3021 def test_line_breaking(self): |
|
3022 # 1. Each statement should get its own line. |
|
3023 self.assert_multi_line_lint( |
|
3024 ' x++;\n' |
|
3025 ' y++;\n' |
|
3026 ' if (condition);\n' |
|
3027 ' doIt();\n', |
|
3028 '') |
|
3029 self.assert_multi_line_lint( |
|
3030 ' if (condition) \\\n' |
|
3031 ' doIt();\n', |
|
3032 '') |
|
3033 self.assert_multi_line_lint( |
|
3034 ' x++; y++;', |
|
3035 'More than one command on the same line [whitespace/newline] [4]') |
|
3036 self.assert_multi_line_lint( |
|
3037 ' if (condition) doIt();\n', |
|
3038 'More than one command on the same line in if [whitespace/parens] [4]') |
|
3039 |
|
3040 # 2. An else statement should go on the same line as a preceding |
|
3041 # close brace if one is present, else it should line up with the |
|
3042 # if statement. |
|
3043 self.assert_multi_line_lint( |
|
3044 'if (condition) {\n' |
|
3045 ' doSomething();\n' |
|
3046 ' doSomethingAgain();\n' |
|
3047 '} else {\n' |
|
3048 ' doSomethingElse();\n' |
|
3049 ' doSomethingElseAgain();\n' |
|
3050 '}\n', |
|
3051 '') |
|
3052 self.assert_multi_line_lint( |
|
3053 'if (condition)\n' |
|
3054 ' doSomething();\n' |
|
3055 'else\n' |
|
3056 ' doSomethingElse();\n', |
|
3057 '') |
|
3058 self.assert_multi_line_lint( |
|
3059 'if (condition)\n' |
|
3060 ' doSomething();\n' |
|
3061 'else {\n' |
|
3062 ' doSomethingElse();\n' |
|
3063 ' doSomethingElseAgain();\n' |
|
3064 '}\n', |
|
3065 '') |
|
3066 self.assert_multi_line_lint( |
|
3067 '#define TEST_ASSERT(expression) do { if (!(expression)) { TestsController::shared().testFailed(__FILE__, __LINE__, #expression); return; } } while (0)\n', |
|
3068 '') |
|
3069 self.assert_multi_line_lint( |
|
3070 '#define TEST_ASSERT(expression) do { if ( !(expression)) { TestsController::shared().testFailed(__FILE__, __LINE__, #expression); return; } } while (0)\n', |
|
3071 'Extra space after ( in if [whitespace/parens] [5]') |
|
3072 # FIXME: currently we only check first conditional, so we cannot detect errors in next ones. |
|
3073 # self.assert_multi_line_lint( |
|
3074 # '#define TEST_ASSERT(expression) do { if (!(expression)) { TestsController::shared().testFailed(__FILE__, __LINE__, #expression); return; } } while (0 )\n', |
|
3075 # 'Mismatching spaces inside () in if [whitespace/parens] [5]') |
|
3076 self.assert_multi_line_lint( |
|
3077 'if (condition) {\n' |
|
3078 ' doSomething();\n' |
|
3079 ' doSomethingAgain();\n' |
|
3080 '}\n' |
|
3081 'else {\n' |
|
3082 ' doSomethingElse();\n' |
|
3083 ' doSomethingElseAgain();\n' |
|
3084 '}\n', |
|
3085 'An else should appear on the same line as the preceding } [whitespace/newline] [4]') |
|
3086 self.assert_multi_line_lint( |
|
3087 'if (condition) doSomething(); else doSomethingElse();\n', |
|
3088 ['More than one command on the same line [whitespace/newline] [4]', |
|
3089 'Else clause should never be on same line as else (use 2 lines) [whitespace/newline] [4]', |
|
3090 'More than one command on the same line in if [whitespace/parens] [4]']) |
|
3091 self.assert_multi_line_lint( |
|
3092 'if (condition) doSomething(); else {\n' |
|
3093 ' doSomethingElse();\n' |
|
3094 '}\n', |
|
3095 ['More than one command on the same line in if [whitespace/parens] [4]', |
|
3096 'One line control clauses should not use braces. [whitespace/braces] [4]']) |
|
3097 self.assert_multi_line_lint( |
|
3098 'void func()\n' |
|
3099 '{\n' |
|
3100 ' while (condition) { }\n' |
|
3101 ' return 0;\n' |
|
3102 '}\n', |
|
3103 '') |
|
3104 self.assert_multi_line_lint( |
|
3105 'void func()\n' |
|
3106 '{\n' |
|
3107 ' for (i = 0; i < 42; i++) { foobar(); }\n' |
|
3108 ' return 0;\n' |
|
3109 '}\n', |
|
3110 'More than one command on the same line in for [whitespace/parens] [4]') |
|
3111 |
|
3112 # 3. An else if statement should be written as an if statement |
|
3113 # when the prior if concludes with a return statement. |
|
3114 self.assert_multi_line_lint( |
|
3115 'if (motivated) {\n' |
|
3116 ' if (liquid)\n' |
|
3117 ' return money;\n' |
|
3118 '} else if (tired)\n' |
|
3119 ' break;\n', |
|
3120 '') |
|
3121 self.assert_multi_line_lint( |
|
3122 'if (condition)\n' |
|
3123 ' doSomething();\n' |
|
3124 'else if (otherCondition)\n' |
|
3125 ' doSomethingElse();\n', |
|
3126 '') |
|
3127 self.assert_multi_line_lint( |
|
3128 'if (condition)\n' |
|
3129 ' doSomething();\n' |
|
3130 'else\n' |
|
3131 ' doSomethingElse();\n', |
|
3132 '') |
|
3133 self.assert_multi_line_lint( |
|
3134 'if (condition)\n' |
|
3135 ' returnValue = foo;\n' |
|
3136 'else if (otherCondition)\n' |
|
3137 ' returnValue = bar;\n', |
|
3138 '') |
|
3139 self.assert_multi_line_lint( |
|
3140 'if (condition)\n' |
|
3141 ' returnValue = foo;\n' |
|
3142 'else\n' |
|
3143 ' returnValue = bar;\n', |
|
3144 '') |
|
3145 self.assert_multi_line_lint( |
|
3146 'if (condition)\n' |
|
3147 ' doSomething();\n' |
|
3148 'else if (liquid)\n' |
|
3149 ' return money;\n' |
|
3150 'else if (broke)\n' |
|
3151 ' return favor;\n' |
|
3152 'else\n' |
|
3153 ' sleep(28800);\n', |
|
3154 '') |
|
3155 self.assert_multi_line_lint( |
|
3156 'if (liquid) {\n' |
|
3157 ' prepare();\n' |
|
3158 ' return money;\n' |
|
3159 '} else if (greedy) {\n' |
|
3160 ' keep();\n' |
|
3161 ' return nothing;\n' |
|
3162 '}\n', |
|
3163 'An else if statement should be written as an if statement when the ' |
|
3164 'prior "if" concludes with a return, break, continue or goto statement.' |
|
3165 ' [readability/control_flow] [4]') |
|
3166 self.assert_multi_line_lint( |
|
3167 ' if (stupid) {\n' |
|
3168 'infiniteLoop:\n' |
|
3169 ' goto infiniteLoop;\n' |
|
3170 ' } else if (evil)\n' |
|
3171 ' goto hell;\n', |
|
3172 'An else if statement should be written as an if statement when the ' |
|
3173 'prior "if" concludes with a return, break, continue or goto statement.' |
|
3174 ' [readability/control_flow] [4]') |
|
3175 self.assert_multi_line_lint( |
|
3176 'if (liquid)\n' |
|
3177 '{\n' |
|
3178 ' prepare();\n' |
|
3179 ' return money;\n' |
|
3180 '}\n' |
|
3181 'else if (greedy)\n' |
|
3182 ' keep();\n', |
|
3183 ['This { should be at the end of the previous line [whitespace/braces] [4]', |
|
3184 'An else should appear on the same line as the preceding } [whitespace/newline] [4]', |
|
3185 'An else if statement should be written as an if statement when the ' |
|
3186 'prior "if" concludes with a return, break, continue or goto statement.' |
|
3187 ' [readability/control_flow] [4]']) |
|
3188 self.assert_multi_line_lint( |
|
3189 'if (gone)\n' |
|
3190 ' return;\n' |
|
3191 'else if (here)\n' |
|
3192 ' go();\n', |
|
3193 'An else if statement should be written as an if statement when the ' |
|
3194 'prior "if" concludes with a return, break, continue or goto statement.' |
|
3195 ' [readability/control_flow] [4]') |
|
3196 self.assert_multi_line_lint( |
|
3197 'if (gone)\n' |
|
3198 ' return;\n' |
|
3199 'else\n' |
|
3200 ' go();\n', |
|
3201 'An else statement can be removed when the prior "if" concludes ' |
|
3202 'with a return, break, continue or goto statement.' |
|
3203 ' [readability/control_flow] [4]') |
|
3204 self.assert_multi_line_lint( |
|
3205 'if (motivated) {\n' |
|
3206 ' prepare();\n' |
|
3207 ' continue;\n' |
|
3208 '} else {\n' |
|
3209 ' cleanUp();\n' |
|
3210 ' break;\n' |
|
3211 '}\n', |
|
3212 'An else statement can be removed when the prior "if" concludes ' |
|
3213 'with a return, break, continue or goto statement.' |
|
3214 ' [readability/control_flow] [4]') |
|
3215 self.assert_multi_line_lint( |
|
3216 'if (tired)\n' |
|
3217 ' break;\n' |
|
3218 'else {\n' |
|
3219 ' prepare();\n' |
|
3220 ' continue;\n' |
|
3221 '}\n', |
|
3222 'An else statement can be removed when the prior "if" concludes ' |
|
3223 'with a return, break, continue or goto statement.' |
|
3224 ' [readability/control_flow] [4]') |
|
3225 |
|
3226 def test_braces(self): |
|
3227 # 1. Function definitions: place each brace on its own line. |
|
3228 self.assert_multi_line_lint( |
|
3229 'int main()\n' |
|
3230 '{\n' |
|
3231 ' doSomething();\n' |
|
3232 '}\n', |
|
3233 '') |
|
3234 self.assert_multi_line_lint( |
|
3235 'int main() {\n' |
|
3236 ' doSomething();\n' |
|
3237 '}\n', |
|
3238 'Place brace on its own line for function definitions. [whitespace/braces] [4]') |
|
3239 |
|
3240 # 2. Other braces: place the open brace on the line preceding the |
|
3241 # code block; place the close brace on its own line. |
|
3242 self.assert_multi_line_lint( |
|
3243 'class MyClass {\n' |
|
3244 ' int foo;\n' |
|
3245 '};\n', |
|
3246 '') |
|
3247 self.assert_multi_line_lint( |
|
3248 'namespace WebCore {\n' |
|
3249 'int foo;\n' |
|
3250 '};\n', |
|
3251 '') |
|
3252 self.assert_multi_line_lint( |
|
3253 'for (int i = 0; i < 10; i++) {\n' |
|
3254 ' DoSomething();\n' |
|
3255 '};\n', |
|
3256 '') |
|
3257 self.assert_multi_line_lint( |
|
3258 'class MyClass\n' |
|
3259 '{\n' |
|
3260 ' int foo;\n' |
|
3261 '};\n', |
|
3262 'This { should be at the end of the previous line [whitespace/braces] [4]') |
|
3263 self.assert_multi_line_lint( |
|
3264 'if (condition)\n' |
|
3265 '{\n' |
|
3266 ' int foo;\n' |
|
3267 '}\n', |
|
3268 'This { should be at the end of the previous line [whitespace/braces] [4]') |
|
3269 self.assert_multi_line_lint( |
|
3270 'for (int i = 0; i < 10; i++)\n' |
|
3271 '{\n' |
|
3272 ' int foo;\n' |
|
3273 '}\n', |
|
3274 'This { should be at the end of the previous line [whitespace/braces] [4]') |
|
3275 self.assert_multi_line_lint( |
|
3276 'while (true)\n' |
|
3277 '{\n' |
|
3278 ' int foo;\n' |
|
3279 '}\n', |
|
3280 'This { should be at the end of the previous line [whitespace/braces] [4]') |
|
3281 self.assert_multi_line_lint( |
|
3282 'foreach (Foo* foo, foos)\n' |
|
3283 '{\n' |
|
3284 ' int bar;\n' |
|
3285 '}\n', |
|
3286 'This { should be at the end of the previous line [whitespace/braces] [4]') |
|
3287 self.assert_multi_line_lint( |
|
3288 'switch (type)\n' |
|
3289 '{\n' |
|
3290 'case foo: return;\n' |
|
3291 '}\n', |
|
3292 'This { should be at the end of the previous line [whitespace/braces] [4]') |
|
3293 self.assert_multi_line_lint( |
|
3294 'if (condition)\n' |
|
3295 '{\n' |
|
3296 ' int foo;\n' |
|
3297 '}\n', |
|
3298 'This { should be at the end of the previous line [whitespace/braces] [4]') |
|
3299 self.assert_multi_line_lint( |
|
3300 'for (int i = 0; i < 10; i++)\n' |
|
3301 '{\n' |
|
3302 ' int foo;\n' |
|
3303 '}\n', |
|
3304 'This { should be at the end of the previous line [whitespace/braces] [4]') |
|
3305 self.assert_multi_line_lint( |
|
3306 'while (true)\n' |
|
3307 '{\n' |
|
3308 ' int foo;\n' |
|
3309 '}\n', |
|
3310 'This { should be at the end of the previous line [whitespace/braces] [4]') |
|
3311 self.assert_multi_line_lint( |
|
3312 'switch (type)\n' |
|
3313 '{\n' |
|
3314 'case foo: return;\n' |
|
3315 '}\n', |
|
3316 'This { should be at the end of the previous line [whitespace/braces] [4]') |
|
3317 self.assert_multi_line_lint( |
|
3318 'else if (type)\n' |
|
3319 '{\n' |
|
3320 'case foo: return;\n' |
|
3321 '}\n', |
|
3322 'This { should be at the end of the previous line [whitespace/braces] [4]') |
|
3323 |
|
3324 # 3. One-line control clauses should not use braces unless |
|
3325 # comments are included or a single statement spans multiple |
|
3326 # lines. |
|
3327 self.assert_multi_line_lint( |
|
3328 'if (true) {\n' |
|
3329 ' int foo;\n' |
|
3330 '}\n', |
|
3331 'One line control clauses should not use braces. [whitespace/braces] [4]') |
|
3332 |
|
3333 self.assert_multi_line_lint( |
|
3334 'for (; foo; bar) {\n' |
|
3335 ' int foo;\n' |
|
3336 '}\n', |
|
3337 'One line control clauses should not use braces. [whitespace/braces] [4]') |
|
3338 |
|
3339 self.assert_multi_line_lint( |
|
3340 'foreach (foo, foos) {\n' |
|
3341 ' int bar;\n' |
|
3342 '}\n', |
|
3343 'One line control clauses should not use braces. [whitespace/braces] [4]') |
|
3344 |
|
3345 self.assert_multi_line_lint( |
|
3346 'while (true) {\n' |
|
3347 ' int foo;\n' |
|
3348 '}\n', |
|
3349 'One line control clauses should not use braces. [whitespace/braces] [4]') |
|
3350 |
|
3351 self.assert_multi_line_lint( |
|
3352 'if (true)\n' |
|
3353 ' int foo;\n' |
|
3354 'else {\n' |
|
3355 ' int foo;\n' |
|
3356 '}\n', |
|
3357 'One line control clauses should not use braces. [whitespace/braces] [4]') |
|
3358 |
|
3359 self.assert_multi_line_lint( |
|
3360 'if (true) {\n' |
|
3361 ' int foo;\n' |
|
3362 '} else\n' |
|
3363 ' int foo;\n', |
|
3364 'One line control clauses should not use braces. [whitespace/braces] [4]') |
|
3365 |
|
3366 self.assert_multi_line_lint( |
|
3367 'if (true) {\n' |
|
3368 ' // Some comment\n' |
|
3369 ' int foo;\n' |
|
3370 '}\n', |
|
3371 '') |
|
3372 |
|
3373 self.assert_multi_line_lint( |
|
3374 'if (true) {\n' |
|
3375 ' myFunction(reallyLongParam1, reallyLongParam2,\n' |
|
3376 ' reallyLongParam3);\n' |
|
3377 '}\n', |
|
3378 '') |
|
3379 |
|
3380 # 4. Control clauses without a body should use empty braces. |
|
3381 self.assert_multi_line_lint( |
|
3382 'for ( ; current; current = current->next) { }\n', |
|
3383 '') |
|
3384 self.assert_multi_line_lint( |
|
3385 'for ( ; current;\n' |
|
3386 ' current = current->next) {}\n', |
|
3387 '') |
|
3388 self.assert_multi_line_lint( |
|
3389 'for ( ; current; current = current->next);\n', |
|
3390 'Semicolon defining empty statement for this loop. Use { } instead. [whitespace/semicolon] [5]') |
|
3391 self.assert_multi_line_lint( |
|
3392 'while (true);\n', |
|
3393 'Semicolon defining empty statement for this loop. Use { } instead. [whitespace/semicolon] [5]') |
|
3394 self.assert_multi_line_lint( |
|
3395 '} while (true);\n', |
|
3396 '') |
|
3397 |
|
3398 def test_null_false_zero(self): |
|
3399 # 1. In C++, the null pointer value should be written as 0. In C, |
|
3400 # it should be written as NULL. In Objective-C and Objective-C++, |
|
3401 # follow the guideline for C or C++, respectively, but use nil to |
|
3402 # represent a null Objective-C object. |
|
3403 self.assert_lint( |
|
3404 'functionCall(NULL)', |
|
3405 'Use 0 instead of NULL.' |
|
3406 ' [readability/null] [5]', |
|
3407 'foo.cpp') |
|
3408 self.assert_lint( |
|
3409 "// Don't use NULL in comments since it isn't in code.", |
|
3410 'Use 0 instead of NULL.' |
|
3411 ' [readability/null] [4]', |
|
3412 'foo.cpp') |
|
3413 self.assert_lint( |
|
3414 '"A string with NULL" // and a comment with NULL is tricky to flag correctly in cpp_style.', |
|
3415 'Use 0 instead of NULL.' |
|
3416 ' [readability/null] [4]', |
|
3417 'foo.cpp') |
|
3418 self.assert_lint( |
|
3419 '"A string containing NULL is ok"', |
|
3420 '', |
|
3421 'foo.cpp') |
|
3422 self.assert_lint( |
|
3423 'if (aboutNULL)', |
|
3424 '', |
|
3425 'foo.cpp') |
|
3426 self.assert_lint( |
|
3427 'myVariable = NULLify', |
|
3428 '', |
|
3429 'foo.cpp') |
|
3430 # Make sure that the NULL check does not apply to C and Objective-C files. |
|
3431 self.assert_lint( |
|
3432 'functionCall(NULL)', |
|
3433 '', |
|
3434 'foo.c') |
|
3435 self.assert_lint( |
|
3436 'functionCall(NULL)', |
|
3437 '', |
|
3438 'foo.m') |
|
3439 |
|
3440 # Make sure that the NULL check does not apply to g_object_{set,get} and |
|
3441 # g_str{join,concat} |
|
3442 self.assert_lint( |
|
3443 'g_object_get(foo, "prop", &bar, NULL);', |
|
3444 '') |
|
3445 self.assert_lint( |
|
3446 'g_object_set(foo, "prop", bar, NULL);', |
|
3447 '') |
|
3448 self.assert_lint( |
|
3449 'g_build_filename(foo, bar, NULL);', |
|
3450 '') |
|
3451 self.assert_lint( |
|
3452 'gst_bin_add_many(foo, bar, boo, NULL);', |
|
3453 '') |
|
3454 self.assert_lint( |
|
3455 'gst_bin_remove_many(foo, bar, boo, NULL);', |
|
3456 '') |
|
3457 self.assert_lint( |
|
3458 'gst_element_link_many(foo, bar, boo, NULL);', |
|
3459 '') |
|
3460 self.assert_lint( |
|
3461 'gst_element_unlink_many(foo, bar, boo, NULL);', |
|
3462 '') |
|
3463 self.assert_lint( |
|
3464 'gchar* result = g_strconcat("part1", "part2", "part3", NULL);', |
|
3465 '') |
|
3466 self.assert_lint( |
|
3467 'gchar* result = g_strconcat("part1", NULL);', |
|
3468 '') |
|
3469 self.assert_lint( |
|
3470 'gchar* result = g_strjoin(",", "part1", "part2", "part3", NULL);', |
|
3471 '') |
|
3472 self.assert_lint( |
|
3473 'gchar* result = g_strjoin(",", "part1", NULL);', |
|
3474 '') |
|
3475 |
|
3476 # 2. C++ and C bool values should be written as true and |
|
3477 # false. Objective-C BOOL values should be written as YES and NO. |
|
3478 # FIXME: Implement this. |
|
3479 |
|
3480 # 3. Tests for true/false, null/non-null, and zero/non-zero should |
|
3481 # all be done without equality comparisons. |
|
3482 self.assert_lint( |
|
3483 'if (count == 0)', |
|
3484 'Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.' |
|
3485 ' [readability/comparison_to_zero] [5]') |
|
3486 self.assert_lint_one_of_many_errors_re( |
|
3487 'if (string != NULL)', |
|
3488 r'Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons\.') |
|
3489 self.assert_lint( |
|
3490 'if (condition == true)', |
|
3491 'Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.' |
|
3492 ' [readability/comparison_to_zero] [5]') |
|
3493 self.assert_lint( |
|
3494 'if (myVariable != /* Why would anyone put a comment here? */ false)', |
|
3495 'Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.' |
|
3496 ' [readability/comparison_to_zero] [5]') |
|
3497 |
|
3498 self.assert_lint( |
|
3499 'if (0 /* This comment also looks odd to me. */ != aLongerVariableName)', |
|
3500 'Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.' |
|
3501 ' [readability/comparison_to_zero] [5]') |
|
3502 self.assert_lint_one_of_many_errors_re( |
|
3503 'if (NULL == thisMayBeNull)', |
|
3504 r'Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons\.') |
|
3505 self.assert_lint( |
|
3506 'if (true != anotherCondition)', |
|
3507 'Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.' |
|
3508 ' [readability/comparison_to_zero] [5]') |
|
3509 self.assert_lint( |
|
3510 'if (false == myBoolValue)', |
|
3511 'Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.' |
|
3512 ' [readability/comparison_to_zero] [5]') |
|
3513 |
|
3514 self.assert_lint( |
|
3515 'if (fontType == trueType)', |
|
3516 '') |
|
3517 self.assert_lint( |
|
3518 'if (othertrue == fontType)', |
|
3519 '') |
|
3520 |
|
3521 def test_using_std(self): |
|
3522 self.assert_lint( |
|
3523 'using std::min;', |
|
3524 "Use 'using namespace std;' instead of 'using std::min;'." |
|
3525 " [build/using_std] [4]", |
|
3526 'foo.cpp') |
|
3527 |
|
3528 def test_max_macro(self): |
|
3529 self.assert_lint( |
|
3530 'int i = MAX(0, 1);', |
|
3531 '', |
|
3532 'foo.c') |
|
3533 |
|
3534 self.assert_lint( |
|
3535 'int i = MAX(0, 1);', |
|
3536 'Use std::max() or std::max<type>() instead of the MAX() macro.' |
|
3537 ' [runtime/max_min_macros] [4]', |
|
3538 'foo.cpp') |
|
3539 |
|
3540 self.assert_lint( |
|
3541 'inline int foo() { return MAX(0, 1); }', |
|
3542 'Use std::max() or std::max<type>() instead of the MAX() macro.' |
|
3543 ' [runtime/max_min_macros] [4]', |
|
3544 'foo.h') |
|
3545 |
|
3546 def test_min_macro(self): |
|
3547 self.assert_lint( |
|
3548 'int i = MIN(0, 1);', |
|
3549 '', |
|
3550 'foo.c') |
|
3551 |
|
3552 self.assert_lint( |
|
3553 'int i = MIN(0, 1);', |
|
3554 'Use std::min() or std::min<type>() instead of the MIN() macro.' |
|
3555 ' [runtime/max_min_macros] [4]', |
|
3556 'foo.cpp') |
|
3557 |
|
3558 self.assert_lint( |
|
3559 'inline int foo() { return MIN(0, 1); }', |
|
3560 'Use std::min() or std::min<type>() instead of the MIN() macro.' |
|
3561 ' [runtime/max_min_macros] [4]', |
|
3562 'foo.h') |
|
3563 |
|
3564 def test_names(self): |
|
3565 name_underscore_error_message = " is incorrectly named. Don't use underscores in your identifier names. [readability/naming] [4]" |
|
3566 name_tooshort_error_message = " is incorrectly named. Don't use the single letter 'l' as an identifier name. [readability/naming] [4]" |
|
3567 |
|
3568 # Basic cases from WebKit style guide. |
|
3569 self.assert_lint('struct Data;', '') |
|
3570 self.assert_lint('size_t bufferSize;', '') |
|
3571 self.assert_lint('class HTMLDocument;', '') |
|
3572 self.assert_lint('String mimeType();', '') |
|
3573 self.assert_lint('size_t buffer_size;', |
|
3574 'buffer_size' + name_underscore_error_message) |
|
3575 self.assert_lint('short m_length;', '') |
|
3576 self.assert_lint('short _length;', |
|
3577 '_length' + name_underscore_error_message) |
|
3578 self.assert_lint('short length_;', |
|
3579 'length_' + name_underscore_error_message) |
|
3580 self.assert_lint('unsigned _length;', |
|
3581 '_length' + name_underscore_error_message) |
|
3582 self.assert_lint('unsigned int _length;', |
|
3583 '_length' + name_underscore_error_message) |
|
3584 self.assert_lint('unsigned long long _length;', |
|
3585 '_length' + name_underscore_error_message) |
|
3586 |
|
3587 # Variable name 'l' is easy to confuse with '1' |
|
3588 self.assert_lint('int l;', 'l' + name_tooshort_error_message) |
|
3589 self.assert_lint('size_t l;', 'l' + name_tooshort_error_message) |
|
3590 self.assert_lint('long long l;', 'l' + name_tooshort_error_message) |
|
3591 |
|
3592 # Pointers, references, functions, templates, and adjectives. |
|
3593 self.assert_lint('char* under_score;', |
|
3594 'under_score' + name_underscore_error_message) |
|
3595 self.assert_lint('const int UNDER_SCORE;', |
|
3596 'UNDER_SCORE' + name_underscore_error_message) |
|
3597 self.assert_lint('static inline const char const& const under_score;', |
|
3598 'under_score' + name_underscore_error_message) |
|
3599 self.assert_lint('WebCore::RenderObject* under_score;', |
|
3600 'under_score' + name_underscore_error_message) |
|
3601 self.assert_lint('int func_name();', |
|
3602 'func_name' + name_underscore_error_message) |
|
3603 self.assert_lint('RefPtr<RenderObject*> under_score;', |
|
3604 'under_score' + name_underscore_error_message) |
|
3605 self.assert_lint('WTF::Vector<WTF::RefPtr<const RenderObject* const> > under_score;', |
|
3606 'under_score' + name_underscore_error_message) |
|
3607 self.assert_lint('int under_score[];', |
|
3608 'under_score' + name_underscore_error_message) |
|
3609 self.assert_lint('struct dirent* under_score;', |
|
3610 'under_score' + name_underscore_error_message) |
|
3611 self.assert_lint('long under_score;', |
|
3612 'under_score' + name_underscore_error_message) |
|
3613 self.assert_lint('long long under_score;', |
|
3614 'under_score' + name_underscore_error_message) |
|
3615 self.assert_lint('long double under_score;', |
|
3616 'under_score' + name_underscore_error_message) |
|
3617 self.assert_lint('long long int under_score;', |
|
3618 'under_score' + name_underscore_error_message) |
|
3619 |
|
3620 # Declarations in control statement. |
|
3621 self.assert_lint('if (int under_score = 42) {', |
|
3622 'under_score' + name_underscore_error_message) |
|
3623 self.assert_lint('else if (int under_score = 42) {', |
|
3624 'under_score' + name_underscore_error_message) |
|
3625 self.assert_lint('for (int under_score = 42; cond; i++) {', |
|
3626 'under_score' + name_underscore_error_message) |
|
3627 self.assert_lint('while (foo & under_score = bar) {', |
|
3628 'under_score' + name_underscore_error_message) |
|
3629 self.assert_lint('for (foo * under_score = p; cond; i++) {', |
|
3630 'under_score' + name_underscore_error_message) |
|
3631 self.assert_lint('for (foo * under_score; cond; i++) {', |
|
3632 'under_score' + name_underscore_error_message) |
|
3633 self.assert_lint('while (foo & value_in_thirdparty_library) {', '') |
|
3634 self.assert_lint('while (foo * value_in_thirdparty_library) {', '') |
|
3635 self.assert_lint('if (mli && S_OK == mli->foo()) {', '') |
|
3636 |
|
3637 # More member variables and functions. |
|
3638 self.assert_lint('int SomeClass::s_validName', '') |
|
3639 self.assert_lint('int m_under_score;', |
|
3640 'm_under_score' + name_underscore_error_message) |
|
3641 self.assert_lint('int SomeClass::s_under_score = 0;', |
|
3642 'SomeClass::s_under_score' + name_underscore_error_message) |
|
3643 self.assert_lint('int SomeClass::under_score = 0;', |
|
3644 'SomeClass::under_score' + name_underscore_error_message) |
|
3645 |
|
3646 # Other statements. |
|
3647 self.assert_lint('return INT_MAX;', '') |
|
3648 self.assert_lint('return_t under_score;', |
|
3649 'under_score' + name_underscore_error_message) |
|
3650 self.assert_lint('goto under_score;', |
|
3651 'under_score' + name_underscore_error_message) |
|
3652 self.assert_lint('delete static_cast<Foo*>(p);', '') |
|
3653 |
|
3654 # Multiple variables in one line. |
|
3655 self.assert_lint('void myFunction(int variable1, int another_variable);', |
|
3656 'another_variable' + name_underscore_error_message) |
|
3657 self.assert_lint('int variable1, another_variable;', |
|
3658 'another_variable' + name_underscore_error_message) |
|
3659 self.assert_lint('int first_variable, secondVariable;', |
|
3660 'first_variable' + name_underscore_error_message) |
|
3661 self.assert_lint('void my_function(int variable_1, int variable_2);', |
|
3662 ['my_function' + name_underscore_error_message, |
|
3663 'variable_1' + name_underscore_error_message, |
|
3664 'variable_2' + name_underscore_error_message]) |
|
3665 self.assert_lint('for (int variable_1, variable_2;;) {', |
|
3666 ['variable_1' + name_underscore_error_message, |
|
3667 'variable_2' + name_underscore_error_message]) |
|
3668 |
|
3669 # There is an exception for op code functions but only in the JavaScriptCore directory. |
|
3670 self.assert_lint('void this_op_code(int var1, int var2)', '', 'JavaScriptCore/foo.cpp') |
|
3671 self.assert_lint('void this_op_code(int var1, int var2)', 'this_op_code' + name_underscore_error_message) |
|
3672 |
|
3673 # GObject requires certain magical names in class declarations. |
|
3674 self.assert_lint('void webkit_dom_object_init();', '') |
|
3675 self.assert_lint('void webkit_dom_object_class_init();', '') |
|
3676 |
|
3677 # There is an exception for some unit tests that begin with "tst_". |
|
3678 self.assert_lint('void tst_QWebFrame::arrayObjectEnumerable(int var1, int var2)', '') |
|
3679 |
|
3680 # The Qt API uses names that begin with "qt_". |
|
3681 self.assert_lint('void QTFrame::qt_drt_is_awesome(int var1, int var2)', '') |
|
3682 self.assert_lint('void qt_drt_is_awesome(int var1, int var2);', '') |
|
3683 |
|
3684 # const_iterator is allowed as well. |
|
3685 self.assert_lint('typedef VectorType::const_iterator const_iterator;', '') |
|
3686 |
|
3687 # Bitfields. |
|
3688 self.assert_lint('unsigned _fillRule : 1;', |
|
3689 '_fillRule' + name_underscore_error_message) |
|
3690 |
|
3691 |
|
3692 def test_comments(self): |
|
3693 # A comment at the beginning of a line is ok. |
|
3694 self.assert_lint('// comment', '') |
|
3695 self.assert_lint(' // comment', '') |
|
3696 |
|
3697 self.assert_lint('} // namespace WebCore', |
|
3698 'One space before end of line comments' |
|
3699 ' [whitespace/comments] [5]') |
|
3700 |
|
3701 def test_other(self): |
|
3702 # FIXME: Implement this. |
|
3703 pass |
|
3704 |
|
3705 |
|
3706 class CppCheckerTest(unittest.TestCase): |
|
3707 |
|
3708 """Tests CppChecker class.""" |
|
3709 |
|
3710 def mock_handle_style_error(self): |
|
3711 pass |
|
3712 |
|
3713 def _checker(self): |
|
3714 return CppChecker("foo", "h", self.mock_handle_style_error, 3) |
|
3715 |
|
3716 def test_init(self): |
|
3717 """Test __init__ constructor.""" |
|
3718 checker = self._checker() |
|
3719 self.assertEquals(checker.file_extension, "h") |
|
3720 self.assertEquals(checker.file_path, "foo") |
|
3721 self.assertEquals(checker.handle_style_error, self.mock_handle_style_error) |
|
3722 self.assertEquals(checker.min_confidence, 3) |
|
3723 |
|
3724 def test_eq(self): |
|
3725 """Test __eq__ equality function.""" |
|
3726 checker1 = self._checker() |
|
3727 checker2 = self._checker() |
|
3728 |
|
3729 # == calls __eq__. |
|
3730 self.assertTrue(checker1 == checker2) |
|
3731 |
|
3732 def mock_handle_style_error2(self): |
|
3733 pass |
|
3734 |
|
3735 # Verify that a difference in any argument cause equality to fail. |
|
3736 checker = CppChecker("foo", "h", self.mock_handle_style_error, 3) |
|
3737 self.assertFalse(checker == CppChecker("bar", "h", self.mock_handle_style_error, 3)) |
|
3738 self.assertFalse(checker == CppChecker("foo", "c", self.mock_handle_style_error, 3)) |
|
3739 self.assertFalse(checker == CppChecker("foo", "h", mock_handle_style_error2, 3)) |
|
3740 self.assertFalse(checker == CppChecker("foo", "h", self.mock_handle_style_error, 4)) |
|
3741 |
|
3742 def test_ne(self): |
|
3743 """Test __ne__ inequality function.""" |
|
3744 checker1 = self._checker() |
|
3745 checker2 = self._checker() |
|
3746 |
|
3747 # != calls __ne__. |
|
3748 # By default, __ne__ always returns true on different objects. |
|
3749 # Thus, just check the distinguishing case to verify that the |
|
3750 # code defines __ne__. |
|
3751 self.assertFalse(checker1 != checker2) |
|
3752 |
|
3753 |
|
3754 def tearDown(): |
|
3755 """A global check to make sure all error-categories have been tested. |
|
3756 |
|
3757 The main tearDown() routine is the only code we can guarantee will be |
|
3758 run after all other tests have been executed. |
|
3759 """ |
|
3760 try: |
|
3761 if _run_verifyallcategoriesseen: |
|
3762 ErrorCollector(None).verify_all_categories_are_seen() |
|
3763 except NameError: |
|
3764 # If nobody set the global _run_verifyallcategoriesseen, then |
|
3765 # we assume we shouldn't run the test |
|
3766 pass |
|
3767 |
|
3768 if __name__ == '__main__': |
|
3769 import sys |
|
3770 # We don't want to run the verify_all_categories_are_seen() test unless |
|
3771 # we're running the full test suite: if we only run one test, |
|
3772 # obviously we're not going to see all the error categories. So we |
|
3773 # only run verify_all_categories_are_seen() when no commandline flags |
|
3774 # are passed in. |
|
3775 global _run_verifyallcategoriesseen |
|
3776 _run_verifyallcategoriesseen = (len(sys.argv) == 1) |
|
3777 |
|
3778 unittest.main() |