| OLD | NEW |
| (Empty) |
| 1 # -*- coding: utf-8; -*- | |
| 2 # | |
| 3 # Copyright (C) 2011 Google Inc. All rights reserved. | |
| 4 # Copyright (C) 2009 Torch Mobile Inc. | |
| 5 # Copyright (C) 2009 Apple Inc. All rights reserved. | |
| 6 # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org) | |
| 7 # | |
| 8 # Redistribution and use in source and binary forms, with or without | |
| 9 # modification, are permitted provided that the following conditions are | |
| 10 # met: | |
| 11 # | |
| 12 # * Redistributions of source code must retain the above copyright | |
| 13 # notice, this list of conditions and the following disclaimer. | |
| 14 # * Redistributions in binary form must reproduce the above | |
| 15 # copyright notice, this list of conditions and the following disclaimer | |
| 16 # in the documentation and/or other materials provided with the | |
| 17 # distribution. | |
| 18 # * Neither the name of Google Inc. nor the names of its | |
| 19 # contributors may be used to endorse or promote products derived from | |
| 20 # this software without specific prior written permission. | |
| 21 # | |
| 22 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 23 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 24 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 25 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 26 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 27 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 28 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 29 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 30 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 31 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 32 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 33 | |
| 34 """Unit test for cpp_style.py.""" | |
| 35 | |
| 36 # FIXME: Add a good test that tests UpdateIncludeState. | |
| 37 | |
| 38 import os | |
| 39 import random | |
| 40 import re | |
| 41 import unittest | |
| 42 | |
| 43 import cpp as cpp_style | |
| 44 from cpp import CppChecker | |
| 45 from ..filter import FilterConfiguration | |
| 46 from webkitpy.common.system.filesystem import FileSystem | |
| 47 | |
| 48 # This class works as an error collector and replaces cpp_style.Error | |
| 49 # function for the unit tests. We also verify each category we see | |
| 50 # is in STYLE_CATEGORIES, to help keep that list up to date. | |
| 51 class ErrorCollector: | |
| 52 _all_style_categories = CppChecker.categories | |
| 53 # This is a list including all categories seen in any unit test. | |
| 54 _seen_style_categories = {} | |
| 55 | |
| 56 def __init__(self, assert_fn, filter=None, lines_to_check=None): | |
| 57 """assert_fn: a function to call when we notice a problem. | |
| 58 filter: filters the errors that we are concerned about.""" | |
| 59 self._assert_fn = assert_fn | |
| 60 self._errors = [] | |
| 61 self._lines_to_check = lines_to_check | |
| 62 if not filter: | |
| 63 filter = FilterConfiguration() | |
| 64 self._filter = filter | |
| 65 | |
| 66 def __call__(self, line_number, category, confidence, message): | |
| 67 self._assert_fn(category in self._all_style_categories, | |
| 68 'Message "%s" has category "%s",' | |
| 69 ' which is not in STYLE_CATEGORIES' % (message, category
)) | |
| 70 | |
| 71 if self._lines_to_check and not line_number in self._lines_to_check: | |
| 72 return False | |
| 73 | |
| 74 if self._filter.should_check(category, ""): | |
| 75 self._seen_style_categories[category] = 1 | |
| 76 self._errors.append('%s [%s] [%d]' % (message, category, confidence
)) | |
| 77 return True | |
| 78 | |
| 79 def results(self): | |
| 80 if len(self._errors) < 2: | |
| 81 return ''.join(self._errors) # Most tests expect to have a string. | |
| 82 else: | |
| 83 return self._errors # Let's give a list if there is more than one. | |
| 84 | |
| 85 def result_list(self): | |
| 86 return self._errors | |
| 87 | |
| 88 def verify_all_categories_are_seen(self): | |
| 89 """Fails if there's a category in _all_style_categories - _seen_style_ca
tegories. | |
| 90 | |
| 91 This should only be called after all tests are run, so | |
| 92 _seen_style_categories has had a chance to fully populate. Since | |
| 93 this isn't called from within the normal unittest framework, we | |
| 94 can't use the normal unittest assert macros. Instead we just exit | |
| 95 when we see an error. Good thing this test is always run last! | |
| 96 """ | |
| 97 for category in self._all_style_categories: | |
| 98 if category not in self._seen_style_categories: | |
| 99 import sys | |
| 100 sys.exit('FATAL ERROR: There are no tests for category "%s"' % c
ategory) | |
| 101 | |
| 102 | |
| 103 class CppFunctionsTest(unittest.TestCase): | |
| 104 | |
| 105 """Supports testing functions that do not need CppStyleTestBase.""" | |
| 106 | |
| 107 def test_convert_to_lower_with_underscores(self): | |
| 108 self.assertEqual(cpp_style._convert_to_lower_with_underscores('ABC'), 'a
bc') | |
| 109 self.assertEqual(cpp_style._convert_to_lower_with_underscores('aB'), 'a_
b') | |
| 110 self.assertEqual(cpp_style._convert_to_lower_with_underscores('isAName')
, 'is_a_name') | |
| 111 self.assertEqual(cpp_style._convert_to_lower_with_underscores('AnotherTe
st'), 'another_test') | |
| 112 self.assertEqual(cpp_style._convert_to_lower_with_underscores('PassRefPt
r<MyClass>'), 'pass_ref_ptr<my_class>') | |
| 113 self.assertEqual(cpp_style._convert_to_lower_with_underscores('_ABC'), '
_abc') | |
| 114 | |
| 115 def test_create_acronym(self): | |
| 116 self.assertEqual(cpp_style._create_acronym('ABC'), 'ABC') | |
| 117 self.assertEqual(cpp_style._create_acronym('IsAName'), 'IAN') | |
| 118 self.assertEqual(cpp_style._create_acronym('PassRefPtr<MyClass>'), 'PRP<
MC>') | |
| 119 | |
| 120 def test_is_c_or_objective_c(self): | |
| 121 clean_lines = cpp_style.CleansedLines(['']) | |
| 122 clean_objc_lines = cpp_style.CleansedLines(['#import "header.h"']) | |
| 123 self.assertTrue(cpp_style._FileState(clean_lines, 'c').is_c_or_objective
_c()) | |
| 124 self.assertTrue(cpp_style._FileState(clean_lines, 'm').is_c_or_objective
_c()) | |
| 125 self.assertFalse(cpp_style._FileState(clean_lines, 'cpp').is_c_or_object
ive_c()) | |
| 126 self.assertFalse(cpp_style._FileState(clean_lines, 'cc').is_c_or_objecti
ve_c()) | |
| 127 self.assertFalse(cpp_style._FileState(clean_lines, 'h').is_c_or_objectiv
e_c()) | |
| 128 self.assertTrue(cpp_style._FileState(clean_objc_lines, 'h').is_c_or_obje
ctive_c()) | |
| 129 | |
| 130 def test_parameter(self): | |
| 131 # Test type. | |
| 132 parameter = cpp_style.Parameter('ExceptionCode', 13, 1) | |
| 133 self.assertEqual(parameter.type, 'ExceptionCode') | |
| 134 self.assertEqual(parameter.name, '') | |
| 135 self.assertEqual(parameter.row, 1) | |
| 136 | |
| 137 # Test type and name. | |
| 138 parameter = cpp_style.Parameter('PassRefPtr<MyClass> parent', 19, 1) | |
| 139 self.assertEqual(parameter.type, 'PassRefPtr<MyClass>') | |
| 140 self.assertEqual(parameter.name, 'parent') | |
| 141 self.assertEqual(parameter.row, 1) | |
| 142 | |
| 143 # Test type, no name, with default value. | |
| 144 parameter = cpp_style.Parameter('MyClass = 0', 7, 0) | |
| 145 self.assertEqual(parameter.type, 'MyClass') | |
| 146 self.assertEqual(parameter.name, '') | |
| 147 self.assertEqual(parameter.row, 0) | |
| 148 | |
| 149 # Test type, name, and default value. | |
| 150 parameter = cpp_style.Parameter('MyClass a = 0', 7, 0) | |
| 151 self.assertEqual(parameter.type, 'MyClass') | |
| 152 self.assertEqual(parameter.name, 'a') | |
| 153 self.assertEqual(parameter.row, 0) | |
| 154 | |
| 155 def test_single_line_view(self): | |
| 156 start_position = cpp_style.Position(row=1, column=1) | |
| 157 end_position = cpp_style.Position(row=3, column=1) | |
| 158 single_line_view = cpp_style.SingleLineView(['0', 'abcde', 'fgh', 'i'],
start_position, end_position) | |
| 159 self.assertEqual(single_line_view.single_line, 'bcde fgh i') | |
| 160 self.assertEqual(single_line_view.convert_column_to_row(0), 1) | |
| 161 self.assertEqual(single_line_view.convert_column_to_row(4), 1) | |
| 162 self.assertEqual(single_line_view.convert_column_to_row(5), 2) | |
| 163 self.assertEqual(single_line_view.convert_column_to_row(8), 2) | |
| 164 self.assertEqual(single_line_view.convert_column_to_row(9), 3) | |
| 165 self.assertEqual(single_line_view.convert_column_to_row(100), 3) | |
| 166 | |
| 167 start_position = cpp_style.Position(row=0, column=3) | |
| 168 end_position = cpp_style.Position(row=0, column=4) | |
| 169 single_line_view = cpp_style.SingleLineView(['abcdef'], start_position,
end_position) | |
| 170 self.assertEqual(single_line_view.single_line, 'd') | |
| 171 | |
| 172 def test_create_skeleton_parameters(self): | |
| 173 self.assertEqual(cpp_style.create_skeleton_parameters(''), '') | |
| 174 self.assertEqual(cpp_style.create_skeleton_parameters(' '), ' ') | |
| 175 self.assertEqual(cpp_style.create_skeleton_parameters('long'), 'long,') | |
| 176 self.assertEqual(cpp_style.create_skeleton_parameters('const unsigned lo
ng int'), ' int,') | |
| 177 self.assertEqual(cpp_style.create_skeleton_parameters('long int*'), '
int ,') | |
| 178 self.assertEqual(cpp_style.create_skeleton_parameters('PassRefPtr<Foo> a
'), 'PassRefPtr a,') | |
| 179 self.assertEqual(cpp_style.create_skeleton_parameters( | |
| 180 'ComplexTemplate<NestedTemplate1<MyClass1, MyClass2>, NestedTemp
late1<MyClass1, MyClass2> > param, int second'), | |
| 181 'ComplexTemplate
param, int second,') | |
| 182 self.assertEqual(cpp_style.create_skeleton_parameters('int = 0, Namespac
e::Type& a'), 'int , Type a,') | |
| 183 # Create skeleton parameters is a bit too aggressive with function varia
bles, but | |
| 184 # it allows for parsing other parameters and declarations like this are
rare. | |
| 185 self.assertEqual(cpp_style.create_skeleton_parameters('void (*fn)(int a,
int b), Namespace::Type& a'), | |
| 186 'void , Type a,') | |
| 187 | |
| 188 # This doesn't look like functions declarations but the simplifications
help to eliminate false positives. | |
| 189 self.assertEqual(cpp_style.create_skeleton_parameters('b{d}'), 'b ,') | |
| 190 | |
| 191 def test_find_parameter_name_index(self): | |
| 192 self.assertEqual(cpp_style.find_parameter_name_index(' int a '), 5) | |
| 193 self.assertEqual(cpp_style.find_parameter_name_index(' PassRefPtr ')
, 16) | |
| 194 self.assertEqual(cpp_style.find_parameter_name_index('double'), 6) | |
| 195 | |
| 196 def test_parameter_list(self): | |
| 197 elided_lines = ['int blah(PassRefPtr<MyClass> paramName,', | |
| 198 'const Other1Class& foo,', | |
| 199 'const ComplexTemplate<Class1, NestedTemplate<P1, P2> >*
const * param = new ComplexTemplate<Class1, NestedTemplate<P1, P2> >(34, 42),', | |
| 200 'int* myCount = 0);'] | |
| 201 start_position = cpp_style.Position(row=0, column=8) | |
| 202 end_position = cpp_style.Position(row=3, column=16) | |
| 203 | |
| 204 expected_parameters = ({'type': 'PassRefPtr<MyClass>', 'name': 'paramNam
e', 'row': 0}, | |
| 205 {'type': 'const Other1Class&', 'name': 'foo', 'ro
w': 1}, | |
| 206 {'type': 'const ComplexTemplate<Class1, NestedTem
plate<P1, P2> >* const *', 'name': 'param', 'row': 2}, | |
| 207 {'type': 'int*', 'name': 'myCount', 'row': 3}) | |
| 208 index = 0 | |
| 209 for parameter in cpp_style.parameter_list(elided_lines, start_position,
end_position): | |
| 210 expected_parameter = expected_parameters[index] | |
| 211 self.assertEqual(parameter.type, expected_parameter['type']) | |
| 212 self.assertEqual(parameter.name, expected_parameter['name']) | |
| 213 self.assertEqual(parameter.row, expected_parameter['row']) | |
| 214 index += 1 | |
| 215 self.assertEqual(index, len(expected_parameters)) | |
| 216 | |
| 217 def test_check_parameter_against_text(self): | |
| 218 error_collector = ErrorCollector(self.assertTrue) | |
| 219 parameter = cpp_style.Parameter('FooF ooF', 4, 1) | |
| 220 self.assertFalse(cpp_style._check_parameter_name_against_text(parameter,
'FooF', error_collector)) | |
| 221 self.assertEqual(error_collector.results(), | |
| 222 'The parameter name "ooF" adds no information, so it s
hould be removed. [readability/parameter_name] [5]') | |
| 223 | |
| 224 class CppStyleTestBase(unittest.TestCase): | |
| 225 """Provides some useful helper functions for cpp_style tests. | |
| 226 | |
| 227 Attributes: | |
| 228 min_confidence: An integer that is the current minimum confidence | |
| 229 level for the tests. | |
| 230 | |
| 231 """ | |
| 232 | |
| 233 # FIXME: Refactor the unit tests so the confidence level is passed | |
| 234 # explicitly, just like it is in the real code. | |
| 235 min_confidence = 1; | |
| 236 | |
| 237 # Helper function to avoid needing to explicitly pass confidence | |
| 238 # in all the unit test calls to cpp_style.process_file_data(). | |
| 239 def process_file_data(self, filename, file_extension, lines, error, fs=None)
: | |
| 240 """Call cpp_style.process_file_data() with the min_confidence.""" | |
| 241 return cpp_style.process_file_data(filename, file_extension, lines, | |
| 242 error, self.min_confidence, fs) | |
| 243 | |
| 244 def perform_lint(self, code, filename, basic_error_rules, fs=None, lines_to_
check=None): | |
| 245 error_collector = ErrorCollector(self.assertTrue, FilterConfiguration(ba
sic_error_rules), lines_to_check) | |
| 246 lines = code.split('\n') | |
| 247 extension = filename.split('.')[1] | |
| 248 self.process_file_data(filename, extension, lines, error_collector, fs) | |
| 249 return error_collector.results() | |
| 250 | |
| 251 # Perform lint on single line of input and return the error message. | |
| 252 def perform_single_line_lint(self, code, filename): | |
| 253 basic_error_rules = ('-build/header_guard', | |
| 254 '-legal/copyright', | |
| 255 '-readability/fn_size', | |
| 256 '-readability/parameter_name', | |
| 257 '-readability/pass_ptr', | |
| 258 '-whitespace/ending_newline') | |
| 259 return self.perform_lint(code, filename, basic_error_rules) | |
| 260 | |
| 261 # Perform lint over multiple lines and return the error message. | |
| 262 def perform_multi_line_lint(self, code, file_extension): | |
| 263 basic_error_rules = ('-build/header_guard', | |
| 264 '-legal/copyright', | |
| 265 '-readability/parameter_name', | |
| 266 '-whitespace/ending_newline') | |
| 267 return self.perform_lint(code, 'test.' + file_extension, basic_error_rul
es) | |
| 268 | |
| 269 # Only keep some errors related to includes, namespaces and rtti. | |
| 270 def perform_language_rules_check(self, filename, code, lines_to_check=None): | |
| 271 basic_error_rules = ('-', | |
| 272 '+build/include', | |
| 273 '+build/include_order', | |
| 274 '+build/namespaces', | |
| 275 '+runtime/rtti') | |
| 276 return self.perform_lint(code, filename, basic_error_rules, lines_to_che
ck=lines_to_check) | |
| 277 | |
| 278 # Only keep function length errors. | |
| 279 def perform_function_lengths_check(self, code): | |
| 280 basic_error_rules = ('-', | |
| 281 '+readability/fn_size') | |
| 282 return self.perform_lint(code, 'test.cpp', basic_error_rules) | |
| 283 | |
| 284 # Only keep pass ptr errors. | |
| 285 def perform_pass_ptr_check(self, code): | |
| 286 basic_error_rules = ('-', | |
| 287 '+readability/pass_ptr') | |
| 288 return self.perform_lint(code, 'test.cpp', basic_error_rules) | |
| 289 | |
| 290 # Only keep leaky pattern errors. | |
| 291 def perform_leaky_pattern_check(self, code): | |
| 292 basic_error_rules = ('-', | |
| 293 '+runtime/leaky_pattern') | |
| 294 return self.perform_lint(code, 'test.cpp', basic_error_rules) | |
| 295 | |
| 296 # Only include what you use errors. | |
| 297 def perform_include_what_you_use(self, code, filename='foo.h', fs=None): | |
| 298 basic_error_rules = ('-', | |
| 299 '+build/include_what_you_use') | |
| 300 return self.perform_lint(code, filename, basic_error_rules, fs) | |
| 301 | |
| 302 def perform_avoid_static_cast_of_objects(self, code, filename='foo.cpp', fs=
None): | |
| 303 basic_error_rules = ('-', | |
| 304 '+runtime/casting') | |
| 305 return self.perform_lint(code, filename, basic_error_rules, fs) | |
| 306 | |
| 307 # Perform lint and compare the error message with "expected_message". | |
| 308 def assert_lint(self, code, expected_message, file_name='foo.cpp'): | |
| 309 self.assertEqual(expected_message, self.perform_single_line_lint(code, f
ile_name)) | |
| 310 | |
| 311 def assert_lint_one_of_many_errors_re(self, code, expected_message_re, file_
name='foo.cpp'): | |
| 312 messages = self.perform_single_line_lint(code, file_name) | |
| 313 for message in messages: | |
| 314 if re.search(expected_message_re, message): | |
| 315 return | |
| 316 | |
| 317 self.assertEqual(expected_message_re, messages) | |
| 318 | |
| 319 def assert_multi_line_lint(self, code, expected_message, file_name='foo.h'): | |
| 320 file_extension = file_name[file_name.rfind('.') + 1:] | |
| 321 self.assertEqual(expected_message, self.perform_multi_line_lint(code, fi
le_extension)) | |
| 322 | |
| 323 def assert_multi_line_lint_re(self, code, expected_message_re, file_name='fo
o.h'): | |
| 324 file_extension = file_name[file_name.rfind('.') + 1:] | |
| 325 message = self.perform_multi_line_lint(code, file_extension) | |
| 326 if not re.search(expected_message_re, message): | |
| 327 self.fail('Message was:\n' + message + 'Expected match to "' + expec
ted_message_re + '"') | |
| 328 | |
| 329 def assert_language_rules_check(self, file_name, code, expected_message, lin
es_to_check=None): | |
| 330 self.assertEqual(expected_message, | |
| 331 self.perform_language_rules_check(file_name, code, lin
es_to_check)) | |
| 332 | |
| 333 def assert_include_what_you_use(self, code, expected_message): | |
| 334 self.assertEqual(expected_message, | |
| 335 self.perform_include_what_you_use(code)) | |
| 336 | |
| 337 def assert_blank_lines_check(self, lines, start_errors, end_errors): | |
| 338 error_collector = ErrorCollector(self.assertTrue) | |
| 339 self.process_file_data('foo.cpp', 'cpp', lines, error_collector) | |
| 340 self.assertEqual( | |
| 341 start_errors, | |
| 342 error_collector.results().count( | |
| 343 'Blank line at the start of a code block. Is this needed?' | |
| 344 ' [whitespace/blank_line] [2]')) | |
| 345 self.assertEqual( | |
| 346 end_errors, | |
| 347 error_collector.results().count( | |
| 348 'Blank line at the end of a code block. Is this needed?' | |
| 349 ' [whitespace/blank_line] [3]')) | |
| 350 | |
| 351 def assert_positions_equal(self, position, tuple_position): | |
| 352 """Checks if the two positions are equal. | |
| 353 | |
| 354 position: a cpp_style.Position object. | |
| 355 tuple_position: a tuple (row, column) to compare against.""" | |
| 356 self.assertEqual(position, cpp_style.Position(tuple_position[0], tuple_p
osition[1]), | |
| 357 'position %s, tuple_position %s' % (position, tuple_po
sition)) | |
| 358 | |
| 359 | |
| 360 class FunctionDetectionTest(CppStyleTestBase): | |
| 361 def perform_function_detection(self, lines, function_information, detection_
line=0): | |
| 362 clean_lines = cpp_style.CleansedLines(lines) | |
| 363 function_state = cpp_style._FunctionState(5) | |
| 364 error_collector = ErrorCollector(self.assertTrue) | |
| 365 cpp_style.detect_functions(clean_lines, detection_line, function_state,
error_collector) | |
| 366 if not function_information: | |
| 367 self.assertEqual(function_state.in_a_function, False) | |
| 368 return | |
| 369 self.assertEqual(function_state.in_a_function, True) | |
| 370 self.assertEqual(function_state.current_function, function_information['
name'] + '()') | |
| 371 self.assertEqual(function_state.modifiers_and_return_type(), function_in
formation['modifiers_and_return_type']) | |
| 372 self.assertEqual(function_state.is_pure, function_information['is_pure']
) | |
| 373 self.assertEqual(function_state.is_declaration, function_information['is
_declaration']) | |
| 374 self.assert_positions_equal(function_state.function_name_start_position,
function_information['function_name_start_position']) | |
| 375 self.assert_positions_equal(function_state.parameter_start_position, fun
ction_information['parameter_start_position']) | |
| 376 self.assert_positions_equal(function_state.parameter_end_position, funct
ion_information['parameter_end_position']) | |
| 377 self.assert_positions_equal(function_state.body_start_position, function
_information['body_start_position']) | |
| 378 self.assert_positions_equal(function_state.end_position, function_inform
ation['end_position']) | |
| 379 expected_parameters = function_information.get('parameter_list') | |
| 380 if expected_parameters: | |
| 381 actual_parameters = function_state.parameter_list() | |
| 382 self.assertEqual(len(actual_parameters), len(expected_parameters)) | |
| 383 for index in range(len(expected_parameters)): | |
| 384 actual_parameter = actual_parameters[index] | |
| 385 expected_parameter = expected_parameters[index] | |
| 386 self.assertEqual(actual_parameter.type, expected_parameter['type
']) | |
| 387 self.assertEqual(actual_parameter.name, expected_parameter['name
']) | |
| 388 self.assertEqual(actual_parameter.row, expected_parameter['row']
) | |
| 389 | |
| 390 def test_basic_function_detection(self): | |
| 391 self.perform_function_detection( | |
| 392 ['void theTestFunctionName(int) {', | |
| 393 '}'], | |
| 394 {'name': 'theTestFunctionName', | |
| 395 'modifiers_and_return_type': 'void', | |
| 396 'function_name_start_position': (0, 5), | |
| 397 'parameter_start_position': (0, 24), | |
| 398 'parameter_end_position': (0, 29), | |
| 399 'body_start_position': (0, 30), | |
| 400 'end_position': (1, 1), | |
| 401 'is_pure': False, | |
| 402 'is_declaration': False}) | |
| 403 | |
| 404 def test_function_declaration_detection(self): | |
| 405 self.perform_function_detection( | |
| 406 ['void aFunctionName(int);'], | |
| 407 {'name': 'aFunctionName', | |
| 408 'modifiers_and_return_type': 'void', | |
| 409 'function_name_start_position': (0, 5), | |
| 410 'parameter_start_position': (0, 18), | |
| 411 'parameter_end_position': (0, 23), | |
| 412 'body_start_position': (0, 23), | |
| 413 'end_position': (0, 24), | |
| 414 'is_pure': False, | |
| 415 'is_declaration': True}) | |
| 416 | |
| 417 self.perform_function_detection( | |
| 418 ['CheckedInt<T> operator /(const CheckedInt<T> &lhs, const CheckedIn
t<T> &rhs);'], | |
| 419 {'name': 'operator /', | |
| 420 'modifiers_and_return_type': 'CheckedInt<T>', | |
| 421 'function_name_start_position': (0, 14), | |
| 422 'parameter_start_position': (0, 24), | |
| 423 'parameter_end_position': (0, 76), | |
| 424 'body_start_position': (0, 76), | |
| 425 'end_position': (0, 77), | |
| 426 'is_pure': False, | |
| 427 'is_declaration': True}) | |
| 428 | |
| 429 self.perform_function_detection( | |
| 430 ['CheckedInt<T> operator -(const CheckedInt<T> &lhs, const CheckedIn
t<T> &rhs);'], | |
| 431 {'name': 'operator -', | |
| 432 'modifiers_and_return_type': 'CheckedInt<T>', | |
| 433 'function_name_start_position': (0, 14), | |
| 434 'parameter_start_position': (0, 24), | |
| 435 'parameter_end_position': (0, 76), | |
| 436 'body_start_position': (0, 76), | |
| 437 'end_position': (0, 77), | |
| 438 'is_pure': False, | |
| 439 'is_declaration': True}) | |
| 440 | |
| 441 self.perform_function_detection( | |
| 442 ['CheckedInt<T> operator !=(const CheckedInt<T> &lhs, const CheckedI
nt<T> &rhs);'], | |
| 443 {'name': 'operator !=', | |
| 444 'modifiers_and_return_type': 'CheckedInt<T>', | |
| 445 'function_name_start_position': (0, 14), | |
| 446 'parameter_start_position': (0, 25), | |
| 447 'parameter_end_position': (0, 77), | |
| 448 'body_start_position': (0, 77), | |
| 449 'end_position': (0, 78), | |
| 450 'is_pure': False, | |
| 451 'is_declaration': True}) | |
| 452 | |
| 453 self.perform_function_detection( | |
| 454 ['CheckedInt<T> operator +(const CheckedInt<T> &lhs, const CheckedIn
t<T> &rhs);'], | |
| 455 {'name': 'operator +', | |
| 456 'modifiers_and_return_type': 'CheckedInt<T>', | |
| 457 'function_name_start_position': (0, 14), | |
| 458 'parameter_start_position': (0, 24), | |
| 459 'parameter_end_position': (0, 76), | |
| 460 'body_start_position': (0, 76), | |
| 461 'end_position': (0, 77), | |
| 462 'is_pure': False, | |
| 463 'is_declaration': True}) | |
| 464 | |
| 465 def test_pure_function_detection(self): | |
| 466 self.perform_function_detection( | |
| 467 ['virtual void theTestFunctionName(int = 0);'], | |
| 468 {'name': 'theTestFunctionName', | |
| 469 'modifiers_and_return_type': 'virtual void', | |
| 470 'function_name_start_position': (0, 13), | |
| 471 'parameter_start_position': (0, 32), | |
| 472 'parameter_end_position': (0, 41), | |
| 473 'body_start_position': (0, 41), | |
| 474 'end_position': (0, 42), | |
| 475 'is_pure': False, | |
| 476 'is_declaration': True}) | |
| 477 | |
| 478 self.perform_function_detection( | |
| 479 ['virtual void theTestFunctionName(int) = 0;'], | |
| 480 {'name': 'theTestFunctionName', | |
| 481 'modifiers_and_return_type': 'virtual void', | |
| 482 'function_name_start_position': (0, 13), | |
| 483 'parameter_start_position': (0, 32), | |
| 484 'parameter_end_position': (0, 37), | |
| 485 'body_start_position': (0, 41), | |
| 486 'end_position': (0, 42), | |
| 487 'is_pure': True, | |
| 488 'is_declaration': True}) | |
| 489 | |
| 490 # Hopefully, no one writes code like this but it is a tricky case. | |
| 491 self.perform_function_detection( | |
| 492 ['virtual void theTestFunctionName(int)', | |
| 493 ' = ', | |
| 494 ' 0 ;'], | |
| 495 {'name': 'theTestFunctionName', | |
| 496 'modifiers_and_return_type': 'virtual void', | |
| 497 'function_name_start_position': (0, 13), | |
| 498 'parameter_start_position': (0, 32), | |
| 499 'parameter_end_position': (0, 37), | |
| 500 'body_start_position': (2, 3), | |
| 501 'end_position': (2, 4), | |
| 502 'is_pure': True, | |
| 503 'is_declaration': True}) | |
| 504 | |
| 505 def test_ignore_macros(self): | |
| 506 self.perform_function_detection(['void aFunctionName(int); \\'], None) | |
| 507 | |
| 508 def test_non_functions(self): | |
| 509 # This case exposed an error because the open brace was in quotes. | |
| 510 self.perform_function_detection( | |
| 511 ['asm(', | |
| 512 ' "stmdb sp!, {r1-r3}" "\n"', | |
| 513 ');'], | |
| 514 # This isn't a function but it looks like one to our simple | |
| 515 # algorithm and that is ok. | |
| 516 {'name': 'asm', | |
| 517 'modifiers_and_return_type': '', | |
| 518 'function_name_start_position': (0, 0), | |
| 519 'parameter_start_position': (0, 3), | |
| 520 'parameter_end_position': (2, 1), | |
| 521 'body_start_position': (2, 1), | |
| 522 'end_position': (2, 2), | |
| 523 'is_pure': False, | |
| 524 'is_declaration': True}) | |
| 525 | |
| 526 # Simple test case with something that is not a function. | |
| 527 self.perform_function_detection(['class Stuff;'], None) | |
| 528 | |
| 529 def test_parameter_list(self): | |
| 530 # A function with no arguments. | |
| 531 function_state = self.perform_function_detection( | |
| 532 ['void functionName();'], | |
| 533 {'name': 'functionName', | |
| 534 'modifiers_and_return_type': 'void', | |
| 535 'function_name_start_position': (0, 5), | |
| 536 'parameter_start_position': (0, 17), | |
| 537 'parameter_end_position': (0, 19), | |
| 538 'body_start_position': (0, 19), | |
| 539 'end_position': (0, 20), | |
| 540 'is_pure': False, | |
| 541 'is_declaration': True, | |
| 542 'parameter_list': ()}) | |
| 543 | |
| 544 # A function with one argument. | |
| 545 function_state = self.perform_function_detection( | |
| 546 ['void functionName(int);'], | |
| 547 {'name': 'functionName', | |
| 548 'modifiers_and_return_type': 'void', | |
| 549 'function_name_start_position': (0, 5), | |
| 550 'parameter_start_position': (0, 17), | |
| 551 'parameter_end_position': (0, 22), | |
| 552 'body_start_position': (0, 22), | |
| 553 'end_position': (0, 23), | |
| 554 'is_pure': False, | |
| 555 'is_declaration': True, | |
| 556 'parameter_list': | |
| 557 ({'type': 'int', 'name': '', 'row': 0},)}) | |
| 558 | |
| 559 # A function with unsigned and short arguments | |
| 560 function_state = self.perform_function_detection( | |
| 561 ['void functionName(unsigned a, short b, long c, long long short uns
igned int);'], | |
| 562 {'name': 'functionName', | |
| 563 'modifiers_and_return_type': 'void', | |
| 564 'function_name_start_position': (0, 5), | |
| 565 'parameter_start_position': (0, 17), | |
| 566 'parameter_end_position': (0, 76), | |
| 567 'body_start_position': (0, 76), | |
| 568 'end_position': (0, 77), | |
| 569 'is_pure': False, | |
| 570 'is_declaration': True, | |
| 571 'parameter_list': | |
| 572 ({'type': 'unsigned', 'name': 'a', 'row': 0}, | |
| 573 {'type': 'short', 'name': 'b', 'row': 0}, | |
| 574 {'type': 'long', 'name': 'c', 'row': 0}, | |
| 575 {'type': 'long long short unsigned int', 'name': '', 'row': 0}
)}) | |
| 576 | |
| 577 # Some parameter type with modifiers and no parameter names. | |
| 578 function_state = self.perform_function_detection( | |
| 579 ['virtual void determineARIADropEffects(Vector<String>*&, const unsi
gned long int*&, const MediaPlayer::Preload, Other<Other2, Other3<P1, P2> >, int
);'], | |
| 580 {'name': 'determineARIADropEffects', | |
| 581 'modifiers_and_return_type': 'virtual void', | |
| 582 'parameter_start_position': (0, 37), | |
| 583 'function_name_start_position': (0, 13), | |
| 584 'parameter_end_position': (0, 147), | |
| 585 'body_start_position': (0, 147), | |
| 586 'end_position': (0, 148), | |
| 587 'is_pure': False, | |
| 588 'is_declaration': True, | |
| 589 'parameter_list': | |
| 590 ({'type': 'Vector<String>*&', 'name': '', 'row': 0}, | |
| 591 {'type': 'const unsigned long int*&', 'name': '', 'row': 0}, | |
| 592 {'type': 'const MediaPlayer::Preload', 'name': '', 'row': 0}, | |
| 593 {'type': 'Other<Other2, Other3<P1, P2> >', 'name': '', 'row':
0}, | |
| 594 {'type': 'int', 'name': '', 'row': 0})}) | |
| 595 | |
| 596 # Try parsing a function with a very complex definition. | |
| 597 function_state = self.perform_function_detection( | |
| 598 ['#define MyMacro(a) a', | |
| 599 'virtual', | |
| 600 'AnotherTemplate<Class1, Class2> aFunctionName(PassRefPtr<MyClass>
paramName,', | |
| 601 'const Other1Class& foo,', | |
| 602 'const ComplexTemplate<Class1, NestedTemplate<P1, P2> >* const * pa
ram = new ComplexTemplate<Class1, NestedTemplate<P1, P2> >(34, 42),', | |
| 603 'int* myCount = 0);'], | |
| 604 {'name': 'aFunctionName', | |
| 605 'modifiers_and_return_type': 'virtual AnotherTemplate<Class1, Class
2>', | |
| 606 'function_name_start_position': (2, 32), | |
| 607 'parameter_start_position': (2, 45), | |
| 608 'parameter_end_position': (5, 17), | |
| 609 'body_start_position': (5, 17), | |
| 610 'end_position': (5, 18), | |
| 611 'is_pure': False, | |
| 612 'is_declaration': True, | |
| 613 'parameter_list': | |
| 614 ({'type': 'PassRefPtr<MyClass>', 'name': 'paramName', 'row': 2}
, | |
| 615 {'type': 'const Other1Class&', 'name': 'foo', 'row': 3}, | |
| 616 {'type': 'const ComplexTemplate<Class1, NestedTemplate<P1, P2>
>* const *', 'name': 'param', 'row': 4}, | |
| 617 {'type': 'int*', 'name': 'myCount', 'row': 5})}, | |
| 618 detection_line=2) | |
| 619 | |
| 620 | |
| 621 class CppStyleTest(CppStyleTestBase): | |
| 622 | |
| 623 def test_asm_lines_ignored(self): | |
| 624 self.assert_lint( | |
| 625 '__asm mov [registration], eax', | |
| 626 '') | |
| 627 | |
| 628 # Test get line width. | |
| 629 def test_get_line_width(self): | |
| 630 self.assertEqual(0, cpp_style.get_line_width('')) | |
| 631 self.assertEqual(10, cpp_style.get_line_width(u'x' * 10)) | |
| 632 self.assertEqual(16, cpp_style.get_line_width(u'都|道|府|県|支庁')) | |
| 633 | |
| 634 def test_find_next_multi_line_comment_start(self): | |
| 635 self.assertEqual(1, cpp_style.find_next_multi_line_comment_start([''], 0
)) | |
| 636 | |
| 637 lines = ['a', 'b', '/* c'] | |
| 638 self.assertEqual(2, cpp_style.find_next_multi_line_comment_start(lines,
0)) | |
| 639 | |
| 640 lines = ['char a[] = "/*";'] # not recognized as comment. | |
| 641 self.assertEqual(1, cpp_style.find_next_multi_line_comment_start(lines,
0)) | |
| 642 | |
| 643 def test_find_next_multi_line_comment_end(self): | |
| 644 self.assertEqual(1, cpp_style.find_next_multi_line_comment_end([''], 0)) | |
| 645 lines = ['a', 'b', ' c */'] | |
| 646 self.assertEqual(2, cpp_style.find_next_multi_line_comment_end(lines, 0)
) | |
| 647 | |
| 648 def test_remove_multi_line_comments_from_range(self): | |
| 649 lines = ['a', ' /* comment ', ' * still comment', ' comment */ ', 'b'
] | |
| 650 cpp_style.remove_multi_line_comments_from_range(lines, 1, 4) | |
| 651 self.assertEqual(['a', '// dummy', '// dummy', '// dummy', 'b'], lines) | |
| 652 | |
| 653 def test_position(self): | |
| 654 position = cpp_style.Position(3, 4) | |
| 655 self.assert_positions_equal(position, (3, 4)) | |
| 656 self.assertEqual(position.row, 3) | |
| 657 self.assertTrue(position > cpp_style.Position(position.row - 1, position
.column + 1)) | |
| 658 self.assertTrue(position > cpp_style.Position(position.row, position.col
umn - 1)) | |
| 659 self.assertTrue(position < cpp_style.Position(position.row, position.col
umn + 1)) | |
| 660 self.assertTrue(position < cpp_style.Position(position.row + 1, position
.column - 1)) | |
| 661 self.assertEqual(position.__str__(), '(3, 4)') | |
| 662 | |
| 663 def test_rfind_in_lines(self): | |
| 664 not_found_position = cpp_style.Position(10, 11) | |
| 665 start_position = cpp_style.Position(2, 2) | |
| 666 lines = ['ab', 'ace', 'test'] | |
| 667 self.assertEqual(not_found_position, cpp_style._rfind_in_lines('st', lin
es, start_position, not_found_position)) | |
| 668 self.assertTrue(cpp_style.Position(1, 1) == cpp_style._rfind_in_lines('a
', lines, start_position, not_found_position)) | |
| 669 self.assertEqual(cpp_style.Position(2, 2), cpp_style._rfind_in_lines('(t
e|a)', lines, start_position, not_found_position)) | |
| 670 | |
| 671 def test_close_expression(self): | |
| 672 self.assertEqual(cpp_style.Position(1, -1), cpp_style.close_expression([
')('], cpp_style.Position(0, 1))) | |
| 673 self.assertEqual(cpp_style.Position(1, -1), cpp_style.close_expression([
') ()'], cpp_style.Position(0, 1))) | |
| 674 self.assertEqual(cpp_style.Position(0, 4), cpp_style.close_expression(['
)[)]'], cpp_style.Position(0, 1))) | |
| 675 self.assertEqual(cpp_style.Position(0, 5), cpp_style.close_expression(['
}{}{}'], cpp_style.Position(0, 3))) | |
| 676 self.assertEqual(cpp_style.Position(1, 1), cpp_style.close_expression(['
}{}{', '}'], cpp_style.Position(0, 3))) | |
| 677 self.assertEqual(cpp_style.Position(2, -1), cpp_style.close_expression([
'][][', ' '], cpp_style.Position(0, 3))) | |
| 678 | |
| 679 def test_spaces_at_end_of_line(self): | |
| 680 self.assert_lint( | |
| 681 '// Hello there ', | |
| 682 'Line ends in whitespace. Consider deleting these extra spaces.' | |
| 683 ' [whitespace/end_of_line] [4]') | |
| 684 | |
| 685 # Test C-style cast cases. | |
| 686 def test_cstyle_cast(self): | |
| 687 self.assert_lint( | |
| 688 'int a = (int)1.0;', | |
| 689 'Using C-style cast. Use static_cast<int>(...) instead' | |
| 690 ' [readability/casting] [4]') | |
| 691 self.assert_lint( | |
| 692 'int *a = (int *)DEFINED_VALUE;', | |
| 693 'Using C-style cast. Use reinterpret_cast<int *>(...) instead' | |
| 694 ' [readability/casting] [4]', 'foo.c') | |
| 695 self.assert_lint( | |
| 696 'uint16 a = (uint16)1.0;', | |
| 697 'Using C-style cast. Use static_cast<uint16>(...) instead' | |
| 698 ' [readability/casting] [4]') | |
| 699 self.assert_lint( | |
| 700 'int32 a = (int32)1.0;', | |
| 701 'Using C-style cast. Use static_cast<int32>(...) instead' | |
| 702 ' [readability/casting] [4]') | |
| 703 self.assert_lint( | |
| 704 'uint64 a = (uint64)1.0;', | |
| 705 'Using C-style cast. Use static_cast<uint64>(...) instead' | |
| 706 ' [readability/casting] [4]') | |
| 707 | |
| 708 # Test taking address of casts (runtime/casting) | |
| 709 def test_runtime_casting(self): | |
| 710 self.assert_lint( | |
| 711 'int* x = &static_cast<int*>(foo);', | |
| 712 'Are you taking an address of a cast? ' | |
| 713 'This is dangerous: could be a temp var. ' | |
| 714 'Take the address before doing the cast, rather than after' | |
| 715 ' [runtime/casting] [4]') | |
| 716 | |
| 717 self.assert_lint( | |
| 718 'int* x = &dynamic_cast<int *>(foo);', | |
| 719 ['Are you taking an address of a cast? ' | |
| 720 'This is dangerous: could be a temp var. ' | |
| 721 'Take the address before doing the cast, rather than after' | |
| 722 ' [runtime/casting] [4]', | |
| 723 'Do not use dynamic_cast<>. If you need to cast within a class ' | |
| 724 'hierarchy, use static_cast<> to upcast. Google doesn\'t support ' | |
| 725 'RTTI. [runtime/rtti] [5]']) | |
| 726 | |
| 727 self.assert_lint( | |
| 728 'int* x = &reinterpret_cast<int *>(foo);', | |
| 729 'Are you taking an address of a cast? ' | |
| 730 'This is dangerous: could be a temp var. ' | |
| 731 'Take the address before doing the cast, rather than after' | |
| 732 ' [runtime/casting] [4]') | |
| 733 | |
| 734 # It's OK to cast an address. | |
| 735 self.assert_lint( | |
| 736 'int* x = reinterpret_cast<int *>(&foo);', | |
| 737 '') | |
| 738 | |
| 739 def test_runtime_selfinit(self): | |
| 740 self.assert_lint( | |
| 741 'Foo::Foo(Bar r, Bel l) : r_(r_), l_(l_) { }', | |
| 742 'You seem to be initializing a member variable with itself.' | |
| 743 ' [runtime/init] [4]') | |
| 744 self.assert_lint( | |
| 745 'Foo::Foo(Bar r, Bel l) : r_(r), l_(l) { }', | |
| 746 '') | |
| 747 self.assert_lint( | |
| 748 'Foo::Foo(Bar r) : r_(r), l_(r_), ll_(l_) { }', | |
| 749 '') | |
| 750 | |
| 751 def test_runtime_rtti(self): | |
| 752 statement = 'int* x = dynamic_cast<int*>(&foo);' | |
| 753 error_message = ( | |
| 754 'Do not use dynamic_cast<>. If you need to cast within a class ' | |
| 755 'hierarchy, use static_cast<> to upcast. Google doesn\'t support ' | |
| 756 'RTTI. [runtime/rtti] [5]') | |
| 757 # dynamic_cast is disallowed in most files. | |
| 758 self.assert_language_rules_check('foo.cpp', statement, error_message) | |
| 759 self.assert_language_rules_check('foo.h', statement, error_message) | |
| 760 | |
| 761 # Tests for static_cast readability. | |
| 762 def test_static_cast_on_objects_with_toFoo(self): | |
| 763 mock_header_contents = ['inline Foo* toFoo(Bar* bar)'] | |
| 764 fs = FileSystem() | |
| 765 orig_read_text_file_fn = fs.read_text_file | |
| 766 | |
| 767 def mock_read_text_file_fn(path): | |
| 768 return mock_header_contents | |
| 769 | |
| 770 try: | |
| 771 fs.read_text_file = mock_read_text_file_fn | |
| 772 message = self.perform_avoid_static_cast_of_objects( | |
| 773 'Foo* x = static_cast<Foo*>(bar);', | |
| 774 filename='casting.cpp', | |
| 775 fs=fs) | |
| 776 self.assertEqual(message, 'static_cast of class objects is not allow
ed. Use toFoo defined in Foo.h.' | |
| 777 ' [runtime/casting] [4]') | |
| 778 finally: | |
| 779 fs.read_text_file = orig_read_text_file_fn | |
| 780 | |
| 781 def test_static_cast_on_objects_without_toFoo(self): | |
| 782 mock_header_contents = ['inline FooBar* toFooBar(Bar* bar)'] | |
| 783 fs = FileSystem() | |
| 784 orig_read_text_file_fn = fs.read_text_file | |
| 785 | |
| 786 def mock_read_text_file_fn(path): | |
| 787 return mock_header_contents | |
| 788 | |
| 789 try: | |
| 790 fs.read_text_file = mock_read_text_file_fn | |
| 791 message = self.perform_avoid_static_cast_of_objects( | |
| 792 'Foo* x = static_cast<Foo*>(bar);', | |
| 793 filename='casting.cpp', | |
| 794 fs=fs) | |
| 795 self.assertEqual(message, 'static_cast of class objects is not allow
ed. Add toFoo in Foo.h and use it instead.' | |
| 796 ' [runtime/casting] [4]') | |
| 797 finally: | |
| 798 fs.read_text_file = orig_read_text_file_fn | |
| 799 | |
| 800 # We cannot test this functionality because of difference of | |
| 801 # function definitions. Anyway, we may never enable this. | |
| 802 # | |
| 803 # # Test for unnamed arguments in a method. | |
| 804 # def test_check_for_unnamed_params(self): | |
| 805 # message = ('All parameters should be named in a function' | |
| 806 # ' [readability/function] [3]') | |
| 807 # self.assert_lint('virtual void A(int*) const;', message) | |
| 808 # self.assert_lint('virtual void B(void (*fn)(int*));', message) | |
| 809 # self.assert_lint('virtual void C(int*);', message) | |
| 810 # self.assert_lint('void *(*f)(void *) = x;', message) | |
| 811 # self.assert_lint('void Method(char*) {', message) | |
| 812 # self.assert_lint('void Method(char*);', message) | |
| 813 # self.assert_lint('void Method(char* /*x*/);', message) | |
| 814 # self.assert_lint('typedef void (*Method)(int32);', message) | |
| 815 # self.assert_lint('static void operator delete[](void*) throw();', messag
e) | |
| 816 # | |
| 817 # self.assert_lint('virtual void D(int* p);', '') | |
| 818 # self.assert_lint('void operator delete(void* x) throw();', '') | |
| 819 # self.assert_lint('void Method(char* x)\n{', '') | |
| 820 # self.assert_lint('void Method(char* /*x*/)\n{', '') | |
| 821 # self.assert_lint('void Method(char* x);', '') | |
| 822 # self.assert_lint('typedef void (*Method)(int32 x);', '') | |
| 823 # self.assert_lint('static void operator delete[](void* x) throw();', '') | |
| 824 # self.assert_lint('static void operator delete[](void* /*x*/) throw();',
'') | |
| 825 # | |
| 826 # # This one should technically warn, but doesn't because the function | |
| 827 # # pointer is confusing. | |
| 828 # self.assert_lint('virtual void E(void (*fn)(int* p));', '') | |
| 829 | |
| 830 # Test deprecated casts such as int(d) | |
| 831 def test_deprecated_cast(self): | |
| 832 self.assert_lint( | |
| 833 'int a = int(2.2);', | |
| 834 'Using deprecated casting style. ' | |
| 835 'Use static_cast<int>(...) instead' | |
| 836 ' [readability/casting] [4]') | |
| 837 # Checks for false positives... | |
| 838 self.assert_lint( | |
| 839 'int a = int(); // Constructor, o.k.', | |
| 840 '') | |
| 841 self.assert_lint( | |
| 842 'X::X() : a(int()) { } // default Constructor, o.k.', | |
| 843 '') | |
| 844 self.assert_lint( | |
| 845 'operator bool(); // Conversion operator, o.k.', | |
| 846 '') | |
| 847 | |
| 848 # The second parameter to a gMock method definition is a function signature | |
| 849 # that often looks like a bad cast but should not picked up by lint. | |
| 850 def test_mock_method(self): | |
| 851 self.assert_lint( | |
| 852 'MOCK_METHOD0(method, int());', | |
| 853 '') | |
| 854 self.assert_lint( | |
| 855 'MOCK_CONST_METHOD1(method, float(string));', | |
| 856 '') | |
| 857 self.assert_lint( | |
| 858 'MOCK_CONST_METHOD2_T(method, double(float, float));', | |
| 859 '') | |
| 860 | |
| 861 # Test sizeof(type) cases. | |
| 862 def test_sizeof_type(self): | |
| 863 self.assert_lint( | |
| 864 'sizeof(int);', | |
| 865 'Using sizeof(type). Use sizeof(varname) instead if possible' | |
| 866 ' [runtime/sizeof] [1]') | |
| 867 self.assert_lint( | |
| 868 'sizeof(int *);', | |
| 869 'Using sizeof(type). Use sizeof(varname) instead if possible' | |
| 870 ' [runtime/sizeof] [1]') | |
| 871 | |
| 872 # Test typedef cases. There was a bug that cpp_style misidentified | |
| 873 # typedef for pointer to function as C-style cast and produced | |
| 874 # false-positive error messages. | |
| 875 def test_typedef_for_pointer_to_function(self): | |
| 876 self.assert_lint( | |
| 877 'typedef void (*Func)(int x);', | |
| 878 '') | |
| 879 self.assert_lint( | |
| 880 'typedef void (*Func)(int *x);', | |
| 881 '') | |
| 882 self.assert_lint( | |
| 883 'typedef void Func(int x);', | |
| 884 '') | |
| 885 self.assert_lint( | |
| 886 'typedef void Func(int *x);', | |
| 887 '') | |
| 888 | |
| 889 def test_include_what_you_use_no_implementation_files(self): | |
| 890 code = 'std::vector<int> foo;' | |
| 891 self.assertEqual('Add #include <vector> for vector<>' | |
| 892 ' [build/include_what_you_use] [4]', | |
| 893 self.perform_include_what_you_use(code, 'foo.h')) | |
| 894 self.assertEqual('', | |
| 895 self.perform_include_what_you_use(code, 'foo.cpp')) | |
| 896 | |
| 897 def test_include_what_you_use(self): | |
| 898 self.assert_include_what_you_use( | |
| 899 '''#include <vector> | |
| 900 std::vector<int> foo; | |
| 901 ''', | |
| 902 '') | |
| 903 self.assert_include_what_you_use( | |
| 904 '''#include <map> | |
| 905 std::pair<int,int> foo; | |
| 906 ''', | |
| 907 '') | |
| 908 self.assert_include_what_you_use( | |
| 909 '''#include <multimap> | |
| 910 std::pair<int,int> foo; | |
| 911 ''', | |
| 912 '') | |
| 913 self.assert_include_what_you_use( | |
| 914 '''#include <hash_map> | |
| 915 std::pair<int,int> foo; | |
| 916 ''', | |
| 917 '') | |
| 918 self.assert_include_what_you_use( | |
| 919 '''#include <utility> | |
| 920 std::pair<int,int> foo; | |
| 921 ''', | |
| 922 '') | |
| 923 self.assert_include_what_you_use( | |
| 924 '''#include <vector> | |
| 925 DECLARE_string(foobar); | |
| 926 ''', | |
| 927 '') | |
| 928 self.assert_include_what_you_use( | |
| 929 '''#include <vector> | |
| 930 DEFINE_string(foobar, "", ""); | |
| 931 ''', | |
| 932 '') | |
| 933 self.assert_include_what_you_use( | |
| 934 '''#include <vector> | |
| 935 std::pair<int,int> foo; | |
| 936 ''', | |
| 937 'Add #include <utility> for pair<>' | |
| 938 ' [build/include_what_you_use] [4]') | |
| 939 self.assert_include_what_you_use( | |
| 940 '''#include "base/foobar.h" | |
| 941 std::vector<int> foo; | |
| 942 ''', | |
| 943 'Add #include <vector> for vector<>' | |
| 944 ' [build/include_what_you_use] [4]') | |
| 945 self.assert_include_what_you_use( | |
| 946 '''#include <vector> | |
| 947 std::set<int> foo; | |
| 948 ''', | |
| 949 'Add #include <set> for set<>' | |
| 950 ' [build/include_what_you_use] [4]') | |
| 951 self.assert_include_what_you_use( | |
| 952 '''#include "base/foobar.h" | |
| 953 hash_map<int, int> foobar; | |
| 954 ''', | |
| 955 'Add #include <hash_map> for hash_map<>' | |
| 956 ' [build/include_what_you_use] [4]') | |
| 957 self.assert_include_what_you_use( | |
| 958 '''#include "base/foobar.h" | |
| 959 bool foobar = std::less<int>(0,1); | |
| 960 ''', | |
| 961 'Add #include <functional> for less<>' | |
| 962 ' [build/include_what_you_use] [4]') | |
| 963 self.assert_include_what_you_use( | |
| 964 '''#include "base/foobar.h" | |
| 965 bool foobar = min<int>(0,1); | |
| 966 ''', | |
| 967 'Add #include <algorithm> for min [build/include_what_you_use] [4]'
) | |
| 968 self.assert_include_what_you_use( | |
| 969 'void a(const string &foobar);', | |
| 970 'Add #include <string> for string [build/include_what_you_use] [4]'
) | |
| 971 self.assert_include_what_you_use( | |
| 972 '''#include "base/foobar.h" | |
| 973 bool foobar = swap(0,1); | |
| 974 ''', | |
| 975 'Add #include <algorithm> for swap [build/include_what_you_use] [4]
') | |
| 976 self.assert_include_what_you_use( | |
| 977 '''#include "base/foobar.h" | |
| 978 bool foobar = transform(a.begin(), a.end(), b.start(), Foo); | |
| 979 ''', | |
| 980 'Add #include <algorithm> for transform ' | |
| 981 '[build/include_what_you_use] [4]') | |
| 982 self.assert_include_what_you_use( | |
| 983 '''#include "base/foobar.h" | |
| 984 bool foobar = min_element(a.begin(), a.end()); | |
| 985 ''', | |
| 986 'Add #include <algorithm> for min_element ' | |
| 987 '[build/include_what_you_use] [4]') | |
| 988 self.assert_include_what_you_use( | |
| 989 '''foo->swap(0,1); | |
| 990 foo.swap(0,1); | |
| 991 ''', | |
| 992 '') | |
| 993 self.assert_include_what_you_use( | |
| 994 '''#include <string> | |
| 995 void a(const std::multimap<int,string> &foobar); | |
| 996 ''', | |
| 997 'Add #include <map> for multimap<>' | |
| 998 ' [build/include_what_you_use] [4]') | |
| 999 self.assert_include_what_you_use( | |
| 1000 '''#include <queue> | |
| 1001 void a(const std::priority_queue<int> &foobar); | |
| 1002 ''', | |
| 1003 '') | |
| 1004 self.assert_include_what_you_use( | |
| 1005 '''#include "base/basictypes.h" | |
| 1006 #include "base/port.h" | |
| 1007 #include <assert.h> | |
| 1008 #include <string> | |
| 1009 #include <vector> | |
| 1010 vector<string> hajoa;''', '') | |
| 1011 self.assert_include_what_you_use( | |
| 1012 '''#include <string> | |
| 1013 int i = numeric_limits<int>::max() | |
| 1014 ''', | |
| 1015 'Add #include <limits> for numeric_limits<>' | |
| 1016 ' [build/include_what_you_use] [4]') | |
| 1017 self.assert_include_what_you_use( | |
| 1018 '''#include <limits> | |
| 1019 int i = numeric_limits<int>::max() | |
| 1020 ''', | |
| 1021 '') | |
| 1022 | |
| 1023 # Test the UpdateIncludeState code path. | |
| 1024 mock_header_contents = ['#include "blah/foo.h"', '#include "blah/bar.h"'
] | |
| 1025 fs = FileSystem() | |
| 1026 orig_read_text_file_fn = fs.read_text_file | |
| 1027 | |
| 1028 def mock_read_text_file_fn(path): | |
| 1029 return mock_header_contents | |
| 1030 | |
| 1031 try: | |
| 1032 fs.read_text_file = mock_read_text_file_fn | |
| 1033 message = self.perform_include_what_you_use( | |
| 1034 '#include "config.h"\n' | |
| 1035 '#include "blah/a.h"\n', | |
| 1036 filename='blah/a.cpp', | |
| 1037 fs=fs) | |
| 1038 self.assertEqual(message, '') | |
| 1039 | |
| 1040 mock_header_contents = ['#include <set>'] | |
| 1041 message = self.perform_include_what_you_use( | |
| 1042 '''#include "config.h" | |
| 1043 #include "blah/a.h" | |
| 1044 | |
| 1045 std::set<int> foo;''', | |
| 1046 filename='blah/a.cpp', | |
| 1047 fs=fs) | |
| 1048 self.assertEqual(message, '') | |
| 1049 | |
| 1050 # If there's just a .cpp and the header can't be found then it's ok. | |
| 1051 message = self.perform_include_what_you_use( | |
| 1052 '''#include "config.h" | |
| 1053 #include "blah/a.h" | |
| 1054 | |
| 1055 std::set<int> foo;''', | |
| 1056 filename='blah/a.cpp') | |
| 1057 self.assertEqual(message, '') | |
| 1058 | |
| 1059 # Make sure we find the headers with relative paths. | |
| 1060 mock_header_contents = [''] | |
| 1061 message = self.perform_include_what_you_use( | |
| 1062 '''#include "config.h" | |
| 1063 #include "%s%sa.h" | |
| 1064 | |
| 1065 std::set<int> foo;''' % (os.path.basename(os.getcwd()), os.pa
th.sep), | |
| 1066 filename='a.cpp', | |
| 1067 fs=fs) | |
| 1068 self.assertEqual(message, 'Add #include <set> for set<> ' | |
| 1069 '[build/include_what_you_use] [4]') | |
| 1070 finally: | |
| 1071 fs.read_text_file = orig_read_text_file_fn | |
| 1072 | |
| 1073 def test_files_belong_to_same_module(self): | |
| 1074 f = cpp_style.files_belong_to_same_module | |
| 1075 self.assertEqual((True, ''), f('a.cpp', 'a.h')) | |
| 1076 self.assertEqual((True, ''), f('base/google.cpp', 'base/google.h')) | |
| 1077 self.assertEqual((True, ''), f('base/google_test.cpp', 'base/google.h')) | |
| 1078 self.assertEqual((True, ''), | |
| 1079 f('base/google_unittest.cpp', 'base/google.h')) | |
| 1080 self.assertEqual((True, ''), | |
| 1081 f('base/internal/google_unittest.cpp', | |
| 1082 'base/public/google.h')) | |
| 1083 self.assertEqual((True, 'xxx/yyy/'), | |
| 1084 f('xxx/yyy/base/internal/google_unittest.cpp', | |
| 1085 'base/public/google.h')) | |
| 1086 self.assertEqual((True, 'xxx/yyy/'), | |
| 1087 f('xxx/yyy/base/google_unittest.cpp', | |
| 1088 'base/public/google.h')) | |
| 1089 self.assertEqual((True, ''), | |
| 1090 f('base/google_unittest.cpp', 'base/google-inl.h')) | |
| 1091 self.assertEqual((True, '/home/build/google3/'), | |
| 1092 f('/home/build/google3/base/google.cpp', 'base/google.
h')) | |
| 1093 | |
| 1094 self.assertEqual((False, ''), | |
| 1095 f('/home/build/google3/base/google.cpp', 'basu/google.
h')) | |
| 1096 self.assertEqual((False, ''), f('a.cpp', 'b.h')) | |
| 1097 | |
| 1098 def test_cleanse_line(self): | |
| 1099 self.assertEqual('int foo = 0; ', | |
| 1100 cpp_style.cleanse_comments('int foo = 0; // danger!')
) | |
| 1101 self.assertEqual('int o = 0;', | |
| 1102 cpp_style.cleanse_comments('int /* foo */ o = 0;')) | |
| 1103 self.assertEqual('foo(int a, int b);', | |
| 1104 cpp_style.cleanse_comments('foo(int a /* abc */, int b
);')) | |
| 1105 self.assertEqual('f(a, b);', | |
| 1106 cpp_style.cleanse_comments('f(a, /* name */ b);')) | |
| 1107 self.assertEqual('f(a, b);', | |
| 1108 cpp_style.cleanse_comments('f(a /* name */, b);')) | |
| 1109 self.assertEqual('f(a, b);', | |
| 1110 cpp_style.cleanse_comments('f(a, /* name */b);')) | |
| 1111 | |
| 1112 def test_multi_line_comments(self): | |
| 1113 # missing explicit is bad | |
| 1114 self.assert_multi_line_lint( | |
| 1115 r'''int a = 0; | |
| 1116 /* multi-liner | |
| 1117 class Foo { | |
| 1118 Foo(int f); // should cause a lint warning in code | |
| 1119 } | |
| 1120 */ ''', | |
| 1121 '') | |
| 1122 self.assert_multi_line_lint( | |
| 1123 '''\ | |
| 1124 /* int a = 0; multi-liner | |
| 1125 static const int b = 0;''', | |
| 1126 ['Could not find end of multi-line comment' | |
| 1127 ' [readability/multiline_comment] [5]', | |
| 1128 'Complex multi-line /*...*/-style comment found. ' | |
| 1129 'Lint may give bogus warnings. Consider replacing these with ' | |
| 1130 '//-style comments, with #if 0...#endif, or with more clearly ' | |
| 1131 'structured multi-line comments. [readability/multiline_comment] [
5]']) | |
| 1132 self.assert_multi_line_lint(r''' /* multi-line comment''', | |
| 1133 ['Could not find end of multi-line comment' | |
| 1134 ' [readability/multiline_comment] [5]', | |
| 1135 'Complex multi-line /*...*/-style comment f
ound. ' | |
| 1136 'Lint may give bogus warnings. Consider re
placing these with ' | |
| 1137 '//-style comments, with #if 0...#endif, or
with more clearly ' | |
| 1138 'structured multi-line comments. [readabil
ity/multiline_comment] [5]']) | |
| 1139 self.assert_multi_line_lint(r''' // /* comment, but not multi-line'''
, '') | |
| 1140 | |
| 1141 def test_multiline_strings(self): | |
| 1142 multiline_string_error_message = ( | |
| 1143 'Multi-line string ("...") found. This lint script doesn\'t ' | |
| 1144 'do well with such strings, and may give bogus warnings. They\'re ' | |
| 1145 'ugly and unnecessary, and you should use concatenation instead".' | |
| 1146 ' [readability/multiline_string] [5]') | |
| 1147 | |
| 1148 file_path = 'mydir/foo.cpp' | |
| 1149 | |
| 1150 error_collector = ErrorCollector(self.assertTrue) | |
| 1151 self.process_file_data(file_path, 'cpp', | |
| 1152 ['const char* str = "This is a\\', | |
| 1153 ' multiline string.";'], | |
| 1154 error_collector) | |
| 1155 self.assertEqual( | |
| 1156 2, # One per line. | |
| 1157 error_collector.result_list().count(multiline_string_error_message)) | |
| 1158 | |
| 1159 # Test non-explicit single-argument constructors | |
| 1160 def test_explicit_single_argument_constructors(self): | |
| 1161 # missing explicit is bad | |
| 1162 self.assert_multi_line_lint( | |
| 1163 '''\ | |
| 1164 class Foo { | |
| 1165 Foo(int f); | |
| 1166 };''', | |
| 1167 'Single-argument constructors should be marked explicit.' | |
| 1168 ' [runtime/explicit] [5]') | |
| 1169 # missing explicit is bad, even with whitespace | |
| 1170 self.assert_multi_line_lint( | |
| 1171 '''\ | |
| 1172 class Foo { | |
| 1173 Foo (int f); | |
| 1174 };''', | |
| 1175 ['Extra space before ( in function call [whitespace/parens] [4]', | |
| 1176 'Single-argument constructors should be marked explicit.' | |
| 1177 ' [runtime/explicit] [5]']) | |
| 1178 # missing explicit, with distracting comment, is still bad | |
| 1179 self.assert_multi_line_lint( | |
| 1180 '''\ | |
| 1181 class Foo { | |
| 1182 Foo(int f); // simpler than Foo(blargh, blarg) | |
| 1183 };''', | |
| 1184 'Single-argument constructors should be marked explicit.' | |
| 1185 ' [runtime/explicit] [5]') | |
| 1186 # missing explicit, with qualified classname | |
| 1187 self.assert_multi_line_lint( | |
| 1188 '''\ | |
| 1189 class Qualifier::AnotherOne::Foo { | |
| 1190 Foo(int f); | |
| 1191 };''', | |
| 1192 'Single-argument constructors should be marked explicit.' | |
| 1193 ' [runtime/explicit] [5]') | |
| 1194 # structs are caught as well. | |
| 1195 self.assert_multi_line_lint( | |
| 1196 '''\ | |
| 1197 struct Foo { | |
| 1198 Foo(int f); | |
| 1199 };''', | |
| 1200 'Single-argument constructors should be marked explicit.' | |
| 1201 ' [runtime/explicit] [5]') | |
| 1202 # Templatized classes are caught as well. | |
| 1203 self.assert_multi_line_lint( | |
| 1204 '''\ | |
| 1205 template<typename T> class Foo { | |
| 1206 Foo(int f); | |
| 1207 };''', | |
| 1208 'Single-argument constructors should be marked explicit.' | |
| 1209 ' [runtime/explicit] [5]') | |
| 1210 # proper style is okay | |
| 1211 self.assert_multi_line_lint( | |
| 1212 '''\ | |
| 1213 class Foo { | |
| 1214 explicit Foo(int f); | |
| 1215 };''', | |
| 1216 '') | |
| 1217 # two argument constructor is okay | |
| 1218 self.assert_multi_line_lint( | |
| 1219 '''\ | |
| 1220 class Foo { | |
| 1221 Foo(int f, int b); | |
| 1222 };''', | |
| 1223 '') | |
| 1224 # two argument constructor, across two lines, is okay | |
| 1225 self.assert_multi_line_lint( | |
| 1226 '''\ | |
| 1227 class Foo { | |
| 1228 Foo(int f, | |
| 1229 int b); | |
| 1230 };''', | |
| 1231 '') | |
| 1232 # non-constructor (but similar name), is okay | |
| 1233 self.assert_multi_line_lint( | |
| 1234 '''\ | |
| 1235 class Foo { | |
| 1236 aFoo(int f); | |
| 1237 };''', | |
| 1238 '') | |
| 1239 # constructor with void argument is okay | |
| 1240 self.assert_multi_line_lint( | |
| 1241 '''\ | |
| 1242 class Foo { | |
| 1243 Foo(void); | |
| 1244 };''', | |
| 1245 '') | |
| 1246 # single argument method is okay | |
| 1247 self.assert_multi_line_lint( | |
| 1248 '''\ | |
| 1249 class Foo { | |
| 1250 Bar(int b); | |
| 1251 };''', | |
| 1252 '') | |
| 1253 # comments should be ignored | |
| 1254 self.assert_multi_line_lint( | |
| 1255 '''\ | |
| 1256 class Foo { | |
| 1257 // Foo(int f); | |
| 1258 };''', | |
| 1259 '') | |
| 1260 # single argument function following class definition is okay | |
| 1261 # (okay, it's not actually valid, but we don't want a false positive) | |
| 1262 self.assert_multi_line_lint( | |
| 1263 '''\ | |
| 1264 class Foo { | |
| 1265 Foo(int f, int b); | |
| 1266 }; | |
| 1267 Foo(int f);''', | |
| 1268 '') | |
| 1269 # single argument function is okay | |
| 1270 self.assert_multi_line_lint( | |
| 1271 '''static Foo(int f);''', | |
| 1272 '') | |
| 1273 # single argument copy constructor is okay. | |
| 1274 self.assert_multi_line_lint( | |
| 1275 '''\ | |
| 1276 class Foo { | |
| 1277 Foo(const Foo&); | |
| 1278 };''', | |
| 1279 '') | |
| 1280 self.assert_multi_line_lint( | |
| 1281 '''\ | |
| 1282 class Foo { | |
| 1283 Foo(Foo&); | |
| 1284 };''', | |
| 1285 '') | |
| 1286 | |
| 1287 def test_slash_star_comment_on_single_line(self): | |
| 1288 self.assert_multi_line_lint( | |
| 1289 '''/* static */ Foo(int f);''', | |
| 1290 '') | |
| 1291 self.assert_multi_line_lint( | |
| 1292 '''/*/ static */ Foo(int f);''', | |
| 1293 '') | |
| 1294 self.assert_multi_line_lint( | |
| 1295 '''/*/ static Foo(int f);''', | |
| 1296 'Could not find end of multi-line comment' | |
| 1297 ' [readability/multiline_comment] [5]') | |
| 1298 self.assert_multi_line_lint( | |
| 1299 ''' /*/ static Foo(int f);''', | |
| 1300 'Could not find end of multi-line comment' | |
| 1301 ' [readability/multiline_comment] [5]') | |
| 1302 | |
| 1303 # Test suspicious usage of "if" like this: | |
| 1304 # if (a == b) { | |
| 1305 # DoSomething(); | |
| 1306 # } if (a == c) { // Should be "else if". | |
| 1307 # DoSomething(); // This gets called twice if a == b && a == c. | |
| 1308 # } | |
| 1309 def test_suspicious_usage_of_if(self): | |
| 1310 self.assert_lint( | |
| 1311 ' if (a == b) {', | |
| 1312 '') | |
| 1313 self.assert_lint( | |
| 1314 ' } if (a == b) {', | |
| 1315 'Did you mean "else if"? If not, start a new line for "if".' | |
| 1316 ' [readability/braces] [4]') | |
| 1317 | |
| 1318 # Test suspicious usage of memset. Specifically, a 0 | |
| 1319 # as the final argument is almost certainly an error. | |
| 1320 def test_suspicious_usage_of_memset(self): | |
| 1321 # Normal use is okay. | |
| 1322 self.assert_lint( | |
| 1323 ' memset(buf, 0, sizeof(buf))', | |
| 1324 '') | |
| 1325 | |
| 1326 # A 0 as the final argument is almost certainly an error. | |
| 1327 self.assert_lint( | |
| 1328 ' memset(buf, sizeof(buf), 0)', | |
| 1329 'Did you mean "memset(buf, 0, sizeof(buf))"?' | |
| 1330 ' [runtime/memset] [4]') | |
| 1331 self.assert_lint( | |
| 1332 ' memset(buf, xsize * ysize, 0)', | |
| 1333 'Did you mean "memset(buf, 0, xsize * ysize)"?' | |
| 1334 ' [runtime/memset] [4]') | |
| 1335 | |
| 1336 # There is legitimate test code that uses this form. | |
| 1337 # This is okay since the second argument is a literal. | |
| 1338 self.assert_lint( | |
| 1339 " memset(buf, 'y', 0)", | |
| 1340 '') | |
| 1341 self.assert_lint( | |
| 1342 ' memset(buf, 4, 0)', | |
| 1343 '') | |
| 1344 self.assert_lint( | |
| 1345 ' memset(buf, -1, 0)', | |
| 1346 '') | |
| 1347 self.assert_lint( | |
| 1348 ' memset(buf, 0xF1, 0)', | |
| 1349 '') | |
| 1350 self.assert_lint( | |
| 1351 ' memset(buf, 0xcd, 0)', | |
| 1352 '') | |
| 1353 | |
| 1354 def test_check_posix_threading(self): | |
| 1355 self.assert_lint('sctime_r()', '') | |
| 1356 self.assert_lint('strtok_r()', '') | |
| 1357 self.assert_lint(' strtok_r(foo, ba, r)', '') | |
| 1358 self.assert_lint('brand()', '') | |
| 1359 self.assert_lint('_rand()', '') | |
| 1360 self.assert_lint('.rand()', '') | |
| 1361 self.assert_lint('>rand()', '') | |
| 1362 self.assert_lint('rand()', | |
| 1363 'Consider using rand_r(...) instead of rand(...)' | |
| 1364 ' for improved thread safety.' | |
| 1365 ' [runtime/threadsafe_fn] [2]') | |
| 1366 self.assert_lint('strtok()', | |
| 1367 'Consider using strtok_r(...) ' | |
| 1368 'instead of strtok(...)' | |
| 1369 ' for improved thread safety.' | |
| 1370 ' [runtime/threadsafe_fn] [2]') | |
| 1371 | |
| 1372 # Test potential format string bugs like printf(foo). | |
| 1373 def test_format_strings(self): | |
| 1374 self.assert_lint('printf("foo")', '') | |
| 1375 self.assert_lint('printf("foo: %s", foo)', '') | |
| 1376 self.assert_lint('DocidForPrintf(docid)', '') # Should not trigger. | |
| 1377 self.assert_lint( | |
| 1378 'printf(foo)', | |
| 1379 'Potential format string bug. Do printf("%s", foo) instead.' | |
| 1380 ' [runtime/printf] [4]') | |
| 1381 self.assert_lint( | |
| 1382 'printf(foo.c_str())', | |
| 1383 'Potential format string bug. ' | |
| 1384 'Do printf("%s", foo.c_str()) instead.' | |
| 1385 ' [runtime/printf] [4]') | |
| 1386 self.assert_lint( | |
| 1387 'printf(foo->c_str())', | |
| 1388 'Potential format string bug. ' | |
| 1389 'Do printf("%s", foo->c_str()) instead.' | |
| 1390 ' [runtime/printf] [4]') | |
| 1391 self.assert_lint( | |
| 1392 'StringPrintf(foo)', | |
| 1393 'Potential format string bug. Do StringPrintf("%s", foo) instead.' | |
| 1394 '' | |
| 1395 ' [runtime/printf] [4]') | |
| 1396 | |
| 1397 # Variable-length arrays are not permitted. | |
| 1398 def test_variable_length_array_detection(self): | |
| 1399 errmsg = ('Do not use variable-length arrays. Use an appropriately name
d ' | |
| 1400 "('k' followed by CamelCase) compile-time constant for the siz
e." | |
| 1401 ' [runtime/arrays] [1]') | |
| 1402 | |
| 1403 self.assert_lint('int a[any_old_variable];', errmsg) | |
| 1404 self.assert_lint('int doublesize[some_var * 2];', errmsg) | |
| 1405 self.assert_lint('int a[afunction()];', errmsg) | |
| 1406 self.assert_lint('int a[function(kMaxFooBars)];', errmsg) | |
| 1407 self.assert_lint('bool aList[items_->size()];', errmsg) | |
| 1408 self.assert_lint('namespace::Type buffer[len+1];', errmsg) | |
| 1409 | |
| 1410 self.assert_lint('int a[64];', '') | |
| 1411 self.assert_lint('int a[0xFF];', '') | |
| 1412 self.assert_lint('int first[256], second[256];', '') | |
| 1413 self.assert_lint('int arrayName[kCompileTimeConstant];', '') | |
| 1414 self.assert_lint('char buf[somenamespace::kBufSize];', '') | |
| 1415 self.assert_lint('int arrayName[ALL_CAPS];', '') | |
| 1416 self.assert_lint('AClass array1[foo::bar::ALL_CAPS];', '') | |
| 1417 self.assert_lint('int a[kMaxStrLen + 1];', '') | |
| 1418 self.assert_lint('int a[sizeof(foo)];', '') | |
| 1419 self.assert_lint('int a[sizeof(*foo)];', '') | |
| 1420 self.assert_lint('int a[sizeof foo];', '') | |
| 1421 self.assert_lint('int a[sizeof(struct Foo)];', '') | |
| 1422 self.assert_lint('int a[128 - sizeof(const bar)];', '') | |
| 1423 self.assert_lint('int a[(sizeof(foo) * 4)];', '') | |
| 1424 self.assert_lint('int a[(arraysize(fixed_size_array)/2) << 1];', 'Missin
g spaces around / [whitespace/operators] [3]') | |
| 1425 self.assert_lint('delete a[some_var];', '') | |
| 1426 self.assert_lint('return a[some_var];', '') | |
| 1427 | |
| 1428 # Brace usage | |
| 1429 def test_braces(self): | |
| 1430 # Braces shouldn't be followed by a ; unless they're defining a struct | |
| 1431 # or initializing an array | |
| 1432 self.assert_lint('int a[3] = { 1, 2, 3 };', '') | |
| 1433 self.assert_lint( | |
| 1434 '''\ | |
| 1435 const int foo[] = | |
| 1436 {1, 2, 3 };''', | |
| 1437 '') | |
| 1438 # For single line, unmatched '}' with a ';' is ignored (not enough conte
xt) | |
| 1439 self.assert_multi_line_lint( | |
| 1440 '''\ | |
| 1441 int a[3] = { 1, | |
| 1442 2, | |
| 1443 3 };''', | |
| 1444 '') | |
| 1445 self.assert_multi_line_lint( | |
| 1446 '''\ | |
| 1447 int a[2][3] = { { 1, 2 }, | |
| 1448 { 3, 4 } };''', | |
| 1449 '') | |
| 1450 self.assert_multi_line_lint( | |
| 1451 '''\ | |
| 1452 int a[2][3] = | |
| 1453 { { 1, 2 }, | |
| 1454 { 3, 4 } };''', | |
| 1455 '') | |
| 1456 | |
| 1457 # CHECK/EXPECT_TRUE/EXPECT_FALSE replacements | |
| 1458 def test_check_check(self): | |
| 1459 self.assert_lint('CHECK(x == 42)', | |
| 1460 'Consider using CHECK_EQ instead of CHECK(a == b)' | |
| 1461 ' [readability/check] [2]') | |
| 1462 self.assert_lint('CHECK(x != 42)', | |
| 1463 'Consider using CHECK_NE instead of CHECK(a != b)' | |
| 1464 ' [readability/check] [2]') | |
| 1465 self.assert_lint('CHECK(x >= 42)', | |
| 1466 'Consider using CHECK_GE instead of CHECK(a >= b)' | |
| 1467 ' [readability/check] [2]') | |
| 1468 self.assert_lint('CHECK(x > 42)', | |
| 1469 'Consider using CHECK_GT instead of CHECK(a > b)' | |
| 1470 ' [readability/check] [2]') | |
| 1471 self.assert_lint('CHECK(x <= 42)', | |
| 1472 'Consider using CHECK_LE instead of CHECK(a <= b)' | |
| 1473 ' [readability/check] [2]') | |
| 1474 self.assert_lint('CHECK(x < 42)', | |
| 1475 'Consider using CHECK_LT instead of CHECK(a < b)' | |
| 1476 ' [readability/check] [2]') | |
| 1477 | |
| 1478 self.assert_lint('DCHECK(x == 42)', | |
| 1479 'Consider using DCHECK_EQ instead of DCHECK(a == b)' | |
| 1480 ' [readability/check] [2]') | |
| 1481 self.assert_lint('DCHECK(x != 42)', | |
| 1482 'Consider using DCHECK_NE instead of DCHECK(a != b)' | |
| 1483 ' [readability/check] [2]') | |
| 1484 self.assert_lint('DCHECK(x >= 42)', | |
| 1485 'Consider using DCHECK_GE instead of DCHECK(a >= b)' | |
| 1486 ' [readability/check] [2]') | |
| 1487 self.assert_lint('DCHECK(x > 42)', | |
| 1488 'Consider using DCHECK_GT instead of DCHECK(a > b)' | |
| 1489 ' [readability/check] [2]') | |
| 1490 self.assert_lint('DCHECK(x <= 42)', | |
| 1491 'Consider using DCHECK_LE instead of DCHECK(a <= b)' | |
| 1492 ' [readability/check] [2]') | |
| 1493 self.assert_lint('DCHECK(x < 42)', | |
| 1494 'Consider using DCHECK_LT instead of DCHECK(a < b)' | |
| 1495 ' [readability/check] [2]') | |
| 1496 | |
| 1497 self.assert_lint( | |
| 1498 'EXPECT_TRUE("42" == x)', | |
| 1499 'Consider using EXPECT_EQ instead of EXPECT_TRUE(a == b)' | |
| 1500 ' [readability/check] [2]') | |
| 1501 self.assert_lint( | |
| 1502 'EXPECT_TRUE("42" != x)', | |
| 1503 'Consider using EXPECT_NE instead of EXPECT_TRUE(a != b)' | |
| 1504 ' [readability/check] [2]') | |
| 1505 self.assert_lint( | |
| 1506 'EXPECT_TRUE(+42 >= x)', | |
| 1507 'Consider using EXPECT_GE instead of EXPECT_TRUE(a >= b)' | |
| 1508 ' [readability/check] [2]') | |
| 1509 self.assert_lint( | |
| 1510 'EXPECT_TRUE_M(-42 > x)', | |
| 1511 'Consider using EXPECT_GT_M instead of EXPECT_TRUE_M(a > b)' | |
| 1512 ' [readability/check] [2]') | |
| 1513 self.assert_lint( | |
| 1514 'EXPECT_TRUE_M(42U <= x)', | |
| 1515 'Consider using EXPECT_LE_M instead of EXPECT_TRUE_M(a <= b)' | |
| 1516 ' [readability/check] [2]') | |
| 1517 self.assert_lint( | |
| 1518 'EXPECT_TRUE_M(42L < x)', | |
| 1519 'Consider using EXPECT_LT_M instead of EXPECT_TRUE_M(a < b)' | |
| 1520 ' [readability/check] [2]') | |
| 1521 | |
| 1522 self.assert_lint( | |
| 1523 'EXPECT_FALSE(x == 42)', | |
| 1524 'Consider using EXPECT_NE instead of EXPECT_FALSE(a == b)' | |
| 1525 ' [readability/check] [2]') | |
| 1526 self.assert_lint( | |
| 1527 'EXPECT_FALSE(x != 42)', | |
| 1528 'Consider using EXPECT_EQ instead of EXPECT_FALSE(a != b)' | |
| 1529 ' [readability/check] [2]') | |
| 1530 self.assert_lint( | |
| 1531 'EXPECT_FALSE(x >= 42)', | |
| 1532 'Consider using EXPECT_LT instead of EXPECT_FALSE(a >= b)' | |
| 1533 ' [readability/check] [2]') | |
| 1534 self.assert_lint( | |
| 1535 'ASSERT_FALSE(x > 42)', | |
| 1536 'Consider using ASSERT_LE instead of ASSERT_FALSE(a > b)' | |
| 1537 ' [readability/check] [2]') | |
| 1538 self.assert_lint( | |
| 1539 'ASSERT_FALSE(x <= 42)', | |
| 1540 'Consider using ASSERT_GT instead of ASSERT_FALSE(a <= b)' | |
| 1541 ' [readability/check] [2]') | |
| 1542 self.assert_lint( | |
| 1543 'ASSERT_FALSE_M(x < 42)', | |
| 1544 'Consider using ASSERT_GE_M instead of ASSERT_FALSE_M(a < b)' | |
| 1545 ' [readability/check] [2]') | |
| 1546 | |
| 1547 self.assert_lint('CHECK(some_iterator == obj.end())', '') | |
| 1548 self.assert_lint('EXPECT_TRUE(some_iterator == obj.end())', '') | |
| 1549 self.assert_lint('EXPECT_FALSE(some_iterator == obj.end())', '') | |
| 1550 | |
| 1551 self.assert_lint('CHECK(CreateTestFile(dir, (1 << 20)));', '') | |
| 1552 self.assert_lint('CHECK(CreateTestFile(dir, (1 >> 20)));', '') | |
| 1553 | |
| 1554 self.assert_lint('CHECK(x<42)', | |
| 1555 ['Missing spaces around <' | |
| 1556 ' [whitespace/operators] [3]', | |
| 1557 'Consider using CHECK_LT instead of CHECK(a < b)' | |
| 1558 ' [readability/check] [2]']) | |
| 1559 self.assert_lint('CHECK(x>42)', | |
| 1560 'Consider using CHECK_GT instead of CHECK(a > b)' | |
| 1561 ' [readability/check] [2]') | |
| 1562 | |
| 1563 self.assert_lint( | |
| 1564 ' EXPECT_TRUE(42 < x) // Random comment.', | |
| 1565 'Consider using EXPECT_LT instead of EXPECT_TRUE(a < b)' | |
| 1566 ' [readability/check] [2]') | |
| 1567 self.assert_lint( | |
| 1568 'EXPECT_TRUE( 42 < x )', | |
| 1569 ['Extra space after ( in function call' | |
| 1570 ' [whitespace/parens] [4]', | |
| 1571 'Consider using EXPECT_LT instead of EXPECT_TRUE(a < b)' | |
| 1572 ' [readability/check] [2]']) | |
| 1573 self.assert_lint( | |
| 1574 'CHECK("foo" == "foo")', | |
| 1575 'Consider using CHECK_EQ instead of CHECK(a == b)' | |
| 1576 ' [readability/check] [2]') | |
| 1577 | |
| 1578 self.assert_lint('CHECK_EQ("foo", "foo")', '') | |
| 1579 | |
| 1580 def test_brace_at_begin_of_line(self): | |
| 1581 self.assert_lint('{', | |
| 1582 'This { should be at the end of the previous line' | |
| 1583 ' [whitespace/braces] [4]') | |
| 1584 self.assert_multi_line_lint( | |
| 1585 '#endif\n' | |
| 1586 '{\n' | |
| 1587 '}\n', | |
| 1588 '') | |
| 1589 self.assert_multi_line_lint( | |
| 1590 'if (condition) {', | |
| 1591 '') | |
| 1592 self.assert_multi_line_lint( | |
| 1593 ' MACRO1(macroArg) {', | |
| 1594 '') | |
| 1595 self.assert_multi_line_lint( | |
| 1596 'ACCESSOR_GETTER(MessageEventPorts) {', | |
| 1597 'Place brace on its own line for function definitions. [whitespace/
braces] [4]') | |
| 1598 self.assert_multi_line_lint( | |
| 1599 'int foo() {', | |
| 1600 'Place brace on its own line for function definitions. [whitespace/
braces] [4]') | |
| 1601 self.assert_multi_line_lint( | |
| 1602 'int foo() const {', | |
| 1603 'Place brace on its own line for function definitions. [whitespace/
braces] [4]') | |
| 1604 self.assert_multi_line_lint( | |
| 1605 'int foo() const OVERRIDE {', | |
| 1606 'Place brace on its own line for function definitions. [whitespace/
braces] [4]') | |
| 1607 self.assert_multi_line_lint( | |
| 1608 'int foo() OVERRIDE {', | |
| 1609 'Place brace on its own line for function definitions. [whitespace/
braces] [4]') | |
| 1610 self.assert_multi_line_lint( | |
| 1611 'int foo() const\n' | |
| 1612 '{\n' | |
| 1613 '}\n', | |
| 1614 '') | |
| 1615 self.assert_multi_line_lint( | |
| 1616 'int foo() OVERRIDE\n' | |
| 1617 '{\n' | |
| 1618 '}\n', | |
| 1619 '') | |
| 1620 self.assert_multi_line_lint( | |
| 1621 'if (condition\n' | |
| 1622 ' && condition2\n' | |
| 1623 ' && condition3) {\n' | |
| 1624 '}\n', | |
| 1625 '') | |
| 1626 | |
| 1627 def test_mismatching_spaces_in_parens(self): | |
| 1628 self.assert_lint('if (foo ) {', 'Extra space before ) in if' | |
| 1629 ' [whitespace/parens] [5]') | |
| 1630 self.assert_lint('switch ( foo) {', 'Extra space after ( in switch' | |
| 1631 ' [whitespace/parens] [5]') | |
| 1632 self.assert_lint('for (foo; ba; bar ) {', 'Extra space before ) in for' | |
| 1633 ' [whitespace/parens] [5]') | |
| 1634 self.assert_lint('for ((foo); (ba); (bar) ) {', 'Extra space before ) in
for' | |
| 1635 ' [whitespace/parens] [5]') | |
| 1636 self.assert_lint('for (; foo; bar) {', '') | |
| 1637 self.assert_lint('for (; (foo); (bar)) {', '') | |
| 1638 self.assert_lint('for ( ; foo; bar) {', '') | |
| 1639 self.assert_lint('for ( ; (foo); (bar)) {', '') | |
| 1640 self.assert_lint('for ( ; foo; bar ) {', 'Extra space before ) in for' | |
| 1641 ' [whitespace/parens] [5]') | |
| 1642 self.assert_lint('for ( ; (foo); (bar) ) {', 'Extra space before ) in fo
r' | |
| 1643 ' [whitespace/parens] [5]') | |
| 1644 self.assert_lint('for (foo; bar; ) {', '') | |
| 1645 self.assert_lint('for ((foo); (bar); ) {', '') | |
| 1646 self.assert_lint('foreach (foo, foos ) {', 'Extra space before ) in fore
ach' | |
| 1647 ' [whitespace/parens] [5]') | |
| 1648 self.assert_lint('foreach ( foo, foos) {', 'Extra space after ( in forea
ch' | |
| 1649 ' [whitespace/parens] [5]') | |
| 1650 self.assert_lint('while ( foo) {', 'Extra space after ( in while' | |
| 1651 ' [whitespace/parens] [5]') | |
| 1652 | |
| 1653 def test_spacing_for_fncall(self): | |
| 1654 self.assert_lint('if (foo) {', '') | |
| 1655 self.assert_lint('for (foo;bar;baz) {', '') | |
| 1656 self.assert_lint('foreach (foo, foos) {', '') | |
| 1657 self.assert_lint('while (foo) {', '') | |
| 1658 self.assert_lint('switch (foo) {', '') | |
| 1659 self.assert_lint('new (RenderArena()) RenderInline(document())', '') | |
| 1660 self.assert_lint('foo( bar)', 'Extra space after ( in function call' | |
| 1661 ' [whitespace/parens] [4]') | |
| 1662 self.assert_lint('foobar( \\', '') | |
| 1663 self.assert_lint('foobar( \\', '') | |
| 1664 self.assert_lint('( a + b)', 'Extra space after (' | |
| 1665 ' [whitespace/parens] [2]') | |
| 1666 self.assert_lint('((a+b))', '') | |
| 1667 self.assert_lint('foo (foo)', 'Extra space before ( in function call' | |
| 1668 ' [whitespace/parens] [4]') | |
| 1669 self.assert_lint('#elif (foo(bar))', '') | |
| 1670 self.assert_lint('#elif (foo(bar) && foo(baz))', '') | |
| 1671 self.assert_lint('typedef foo (*foo)(foo)', '') | |
| 1672 self.assert_lint('typedef foo (*foo12bar_)(foo)', '') | |
| 1673 self.assert_lint('typedef foo (Foo::*bar)(foo)', '') | |
| 1674 self.assert_lint('foo (Foo::*bar)(', | |
| 1675 'Extra space before ( in function call' | |
| 1676 ' [whitespace/parens] [4]') | |
| 1677 self.assert_lint('typedef foo (Foo::*bar)(', '') | |
| 1678 self.assert_lint('(foo)(bar)', '') | |
| 1679 self.assert_lint('Foo (*foo)(bar)', '') | |
| 1680 self.assert_lint('Foo (*foo)(Bar bar,', '') | |
| 1681 self.assert_lint('char (*p)[sizeof(foo)] = &foo', '') | |
| 1682 self.assert_lint('char (&ref)[sizeof(foo)] = &foo', '') | |
| 1683 self.assert_lint('const char32 (*table[])[6];', '') | |
| 1684 | |
| 1685 def test_spacing_before_braces(self): | |
| 1686 self.assert_lint('if (foo){', 'Missing space before {' | |
| 1687 ' [whitespace/braces] [5]') | |
| 1688 self.assert_lint('for{', 'Missing space before {' | |
| 1689 ' [whitespace/braces] [5]') | |
| 1690 self.assert_lint('for {', '') | |
| 1691 self.assert_lint('EXPECT_DEBUG_DEATH({', '') | |
| 1692 | |
| 1693 def test_spacing_between_braces(self): | |
| 1694 self.assert_lint(' { }', '') | |
| 1695 self.assert_lint(' {}', 'Missing space inside { }. [whitespace/brace
s] [5]') | |
| 1696 self.assert_lint(' { }', 'Too many spaces inside { }. [whitespace/
braces] [5]') | |
| 1697 | |
| 1698 def test_spacing_around_else(self): | |
| 1699 self.assert_lint('}else {', 'Missing space before else' | |
| 1700 ' [whitespace/braces] [5]') | |
| 1701 self.assert_lint('} else{', 'Missing space before {' | |
| 1702 ' [whitespace/braces] [5]') | |
| 1703 self.assert_lint('} else {', '') | |
| 1704 self.assert_lint('} else if', '') | |
| 1705 | |
| 1706 def test_spacing_for_binary_ops(self): | |
| 1707 self.assert_lint('if (foo<=bar) {', 'Missing spaces around <=' | |
| 1708 ' [whitespace/operators] [3]') | |
| 1709 self.assert_lint('if (foo<bar) {', 'Missing spaces around <' | |
| 1710 ' [whitespace/operators] [3]') | |
| 1711 self.assert_lint('if (foo<bar->baz) {', 'Missing spaces around <' | |
| 1712 ' [whitespace/operators] [3]') | |
| 1713 self.assert_lint('if (foo<bar->bar) {', 'Missing spaces around <' | |
| 1714 ' [whitespace/operators] [3]') | |
| 1715 self.assert_lint('typedef hash_map<Foo, Bar', 'Missing spaces around <' | |
| 1716 ' [whitespace/operators] [3]') | |
| 1717 self.assert_lint('typedef hash_map<FoooooType, BaaaaarType,', '') | |
| 1718 self.assert_lint('a<Foo> t+=b;', 'Missing spaces around +=' | |
| 1719 ' [whitespace/operators] [3]') | |
| 1720 self.assert_lint('a<Foo> t-=b;', 'Missing spaces around -=' | |
| 1721 ' [whitespace/operators] [3]') | |
| 1722 self.assert_lint('a<Foo*> t*=b;', 'Missing spaces around *=' | |
| 1723 ' [whitespace/operators] [3]') | |
| 1724 self.assert_lint('a<Foo*> t/=b;', 'Missing spaces around /=' | |
| 1725 ' [whitespace/operators] [3]') | |
| 1726 self.assert_lint('a<Foo*> t|=b;', 'Missing spaces around |=' | |
| 1727 ' [whitespace/operators] [3]') | |
| 1728 self.assert_lint('a<Foo*> t&=b;', 'Missing spaces around &=' | |
| 1729 ' [whitespace/operators] [3]') | |
| 1730 self.assert_lint('a<Foo*> t<<=b;', 'Missing spaces around <<=' | |
| 1731 ' [whitespace/operators] [3]') | |
| 1732 self.assert_lint('a<Foo*> t>>=b;', 'Missing spaces around >>=' | |
| 1733 ' [whitespace/operators] [3]') | |
| 1734 self.assert_lint('a<Foo*> t>>=&b|c;', 'Missing spaces around >>=' | |
| 1735 ' [whitespace/operators] [3]') | |
| 1736 self.assert_lint('a<Foo*> t<<=*b/c;', 'Missing spaces around <<=' | |
| 1737 ' [whitespace/operators] [3]') | |
| 1738 self.assert_lint('a<Foo> t -= b;', '') | |
| 1739 self.assert_lint('a<Foo> t += b;', '') | |
| 1740 self.assert_lint('a<Foo*> t *= b;', '') | |
| 1741 self.assert_lint('a<Foo*> t /= b;', '') | |
| 1742 self.assert_lint('a<Foo*> t |= b;', '') | |
| 1743 self.assert_lint('a<Foo*> t &= b;', '') | |
| 1744 self.assert_lint('a<Foo*> t <<= b;', '') | |
| 1745 self.assert_lint('a<Foo*> t >>= b;', '') | |
| 1746 self.assert_lint('a<Foo*> t >>= &b|c;', 'Missing spaces around |' | |
| 1747 ' [whitespace/operators] [3]') | |
| 1748 self.assert_lint('a<Foo*> t <<= *b/c;', 'Missing spaces around /' | |
| 1749 ' [whitespace/operators] [3]') | |
| 1750 self.assert_lint('a<Foo*> t <<= b/c; //Test', [ | |
| 1751 'Should have a space between // and comment ' | |
| 1752 '[whitespace/comments] [4]', 'Missing' | |
| 1753 ' spaces around / [whitespace/operators] [3]']) | |
| 1754 self.assert_lint('a<Foo*> t <<= b||c; //Test', ['One space before end' | |
| 1755 ' of line comments [whitespace/comments] [5]', | |
| 1756 'Should have a space between // and comment ' | |
| 1757 '[whitespace/comments] [4]', | |
| 1758 'Missing spaces around || [whitespace/operators] [3]']
) | |
| 1759 self.assert_lint('a<Foo*> t <<= b&&c; // Test', 'Missing spaces around' | |
| 1760 ' && [whitespace/operators] [3]') | |
| 1761 self.assert_lint('a<Foo*> t <<= b&&&c; // Test', 'Missing spaces around' | |
| 1762 ' && [whitespace/operators] [3]') | |
| 1763 self.assert_lint('a<Foo*> t <<= b&&*c; // Test', 'Missing spaces around' | |
| 1764 ' && [whitespace/operators] [3]') | |
| 1765 self.assert_lint('a<Foo*> t <<= b && *c; // Test', '') | |
| 1766 self.assert_lint('a<Foo*> t <<= b && &c; // Test', '') | |
| 1767 self.assert_lint('a<Foo*> t <<= b || &c; /*Test', 'Complex multi-line ' | |
| 1768 '/*...*/-style comment found. Lint may give bogus ' | |
| 1769 'warnings. Consider replacing these with //-style' | |
| 1770 ' comments, with #if 0...#endif, or with more clearly' | |
| 1771 ' structured multi-line comments. [readability/multili
ne_comment] [5]') | |
| 1772 self.assert_lint('a<Foo&> t <<= &b | &c;', '') | |
| 1773 self.assert_lint('a<Foo*> t <<= &b & &c; // Test', '') | |
| 1774 self.assert_lint('a<Foo*> t <<= *b / &c; // Test', '') | |
| 1775 self.assert_lint('if (a=b == 1)', 'Missing spaces around = [whitespace/
operators] [4]') | |
| 1776 self.assert_lint('a = 1<<20', 'Missing spaces around << [whitespace/ope
rators] [3]') | |
| 1777 self.assert_lint('if (a = b == 1)', '') | |
| 1778 self.assert_lint('a = 1 << 20', '') | |
| 1779 self.assert_multi_line_lint('#include <sys/io.h>\n', '') | |
| 1780 self.assert_multi_line_lint('#import <foo/bar.h>\n', '') | |
| 1781 | |
| 1782 def test_operator_methods(self): | |
| 1783 self.assert_lint('String operator+(const String&, const String&);', '') | |
| 1784 self.assert_lint('String operator/(const String&, const String&);', '') | |
| 1785 self.assert_lint('bool operator==(const String&, const String&);', '') | |
| 1786 self.assert_lint('String& operator-=(const String&, const String&);', ''
) | |
| 1787 self.assert_lint('String& operator+=(const String&, const String&);', ''
) | |
| 1788 self.assert_lint('String& operator*=(const String&, const String&);', ''
) | |
| 1789 self.assert_lint('String& operator%=(const String&, const String&);', ''
) | |
| 1790 self.assert_lint('String& operator&=(const String&, const String&);', ''
) | |
| 1791 self.assert_lint('String& operator<<=(const String&, const String&);', '
') | |
| 1792 self.assert_lint('String& operator>>=(const String&, const String&);', '
') | |
| 1793 self.assert_lint('String& operator|=(const String&, const String&);', ''
) | |
| 1794 self.assert_lint('String& operator^=(const String&, const String&);', ''
) | |
| 1795 | |
| 1796 def test_spacing_before_last_semicolon(self): | |
| 1797 self.assert_lint('call_function() ;', | |
| 1798 'Extra space before last semicolon. If this should be a
n ' | |
| 1799 'empty statement, use { } instead.' | |
| 1800 ' [whitespace/semicolon] [5]') | |
| 1801 self.assert_lint('while (true) ;', | |
| 1802 'Extra space before last semicolon. If this should be a
n ' | |
| 1803 'empty statement, use { } instead.' | |
| 1804 ' [whitespace/semicolon] [5]') | |
| 1805 self.assert_lint('default:;', | |
| 1806 'Semicolon defining empty statement. Use { } instead.' | |
| 1807 ' [whitespace/semicolon] [5]') | |
| 1808 self.assert_lint(' ;', | |
| 1809 'Line contains only semicolon. If this should be an emp
ty ' | |
| 1810 'statement, use { } instead.' | |
| 1811 ' [whitespace/semicolon] [5]') | |
| 1812 self.assert_lint('for (int i = 0; ;', '') | |
| 1813 | |
| 1814 # Static or global STL strings. | |
| 1815 def test_static_or_global_stlstrings(self): | |
| 1816 self.assert_lint('string foo;', | |
| 1817 'For a static/global string constant, use a C style ' | |
| 1818 'string instead: "char foo[]".' | |
| 1819 ' [runtime/string] [4]') | |
| 1820 self.assert_lint('string kFoo = "hello"; // English', | |
| 1821 'For a static/global string constant, use a C style ' | |
| 1822 'string instead: "char kFoo[]".' | |
| 1823 ' [runtime/string] [4]') | |
| 1824 self.assert_lint('static string foo;', | |
| 1825 'For a static/global string constant, use a C style ' | |
| 1826 'string instead: "static char foo[]".' | |
| 1827 ' [runtime/string] [4]') | |
| 1828 self.assert_lint('static const string foo;', | |
| 1829 'For a static/global string constant, use a C style ' | |
| 1830 'string instead: "static const char foo[]".' | |
| 1831 ' [runtime/string] [4]') | |
| 1832 self.assert_lint('string Foo::bar;', | |
| 1833 'For a static/global string constant, use a C style ' | |
| 1834 'string instead: "char Foo::bar[]".' | |
| 1835 ' [runtime/string] [4]') | |
| 1836 # Rare case. | |
| 1837 self.assert_lint('string foo("foobar");', | |
| 1838 'For a static/global string constant, use a C style ' | |
| 1839 'string instead: "char foo[]".' | |
| 1840 ' [runtime/string] [4]') | |
| 1841 # Should not catch local or member variables. | |
| 1842 self.assert_lint(' string foo', '') | |
| 1843 # Should not catch functions. | |
| 1844 self.assert_lint('string EmptyString() { return ""; }', '') | |
| 1845 self.assert_lint('string EmptyString () { return ""; }', '') | |
| 1846 self.assert_lint('string VeryLongNameFunctionSometimesEndsWith(\n' | |
| 1847 ' VeryLongNameType veryLongNameVariable) { }', '') | |
| 1848 self.assert_lint('template<>\n' | |
| 1849 'string FunctionTemplateSpecialization<SomeType>(\n' | |
| 1850 ' int x) { return ""; }', '') | |
| 1851 self.assert_lint('template<>\n' | |
| 1852 'string FunctionTemplateSpecialization<vector<A::B>* >(
\n' | |
| 1853 ' int x) { return ""; }', '') | |
| 1854 | |
| 1855 # should not catch methods of template classes. | |
| 1856 self.assert_lint('string Class<Type>::Method() const\n' | |
| 1857 '{\n' | |
| 1858 ' return "";\n' | |
| 1859 '}\n', '') | |
| 1860 self.assert_lint('string Class<Type>::Method(\n' | |
| 1861 ' int arg) const\n' | |
| 1862 '{\n' | |
| 1863 ' return "";\n' | |
| 1864 '}\n', '') | |
| 1865 | |
| 1866 def test_no_spaces_in_function_calls(self): | |
| 1867 self.assert_lint('TellStory(1, 3);', | |
| 1868 '') | |
| 1869 self.assert_lint('TellStory(1, 3 );', | |
| 1870 'Extra space before )' | |
| 1871 ' [whitespace/parens] [2]') | |
| 1872 self.assert_lint('TellStory(1 /* wolf */, 3 /* pigs */);', | |
| 1873 '') | |
| 1874 self.assert_multi_line_lint('#endif\n );', | |
| 1875 '') | |
| 1876 | |
| 1877 def test_one_spaces_between_code_and_comments(self): | |
| 1878 self.assert_lint('} // namespace foo', | |
| 1879 '') | |
| 1880 self.assert_lint('}// namespace foo', | |
| 1881 'One space before end of line comments' | |
| 1882 ' [whitespace/comments] [5]') | |
| 1883 self.assert_lint('printf("foo"); // Outside quotes.', | |
| 1884 '') | |
| 1885 self.assert_lint('int i = 0; // Having one space is fine.','') | |
| 1886 self.assert_lint('int i = 0; // Having two spaces is bad.', | |
| 1887 'One space before end of line comments' | |
| 1888 ' [whitespace/comments] [5]') | |
| 1889 self.assert_lint('int i = 0; // Having three spaces is bad.', | |
| 1890 'One space before end of line comments' | |
| 1891 ' [whitespace/comments] [5]') | |
| 1892 self.assert_lint('// Top level comment', '') | |
| 1893 self.assert_lint(' // Line starts with four spaces.', '') | |
| 1894 self.assert_lint('foo();\n' | |
| 1895 '{ // A scope is opening.', '') | |
| 1896 self.assert_lint(' foo();\n' | |
| 1897 ' { // An indented scope is opening.', '') | |
| 1898 self.assert_lint('if (foo) { // not a pure scope', | |
| 1899 '') | |
| 1900 self.assert_lint('printf("// In quotes.")', '') | |
| 1901 self.assert_lint('printf("\\"%s // In quotes.")', '') | |
| 1902 self.assert_lint('printf("%s", "// In quotes.")', '') | |
| 1903 | |
| 1904 def test_one_spaces_after_punctuation_in_comments(self): | |
| 1905 self.assert_lint('int a; // This is a sentence.', | |
| 1906 '') | |
| 1907 self.assert_lint('int a; // This is a sentence. ', | |
| 1908 'Line ends in whitespace. Consider deleting these extr
a spaces. [whitespace/end_of_line] [4]') | |
| 1909 self.assert_lint('int a; // This is a sentence. This is a another senten
ce.', | |
| 1910 '') | |
| 1911 self.assert_lint('int a; // This is a sentence. This is a another sente
nce.', | |
| 1912 'Should have only a single space after a punctuation in
a comment. [whitespace/comments] [5]') | |
| 1913 self.assert_lint('int a; // This is a sentence! This is a another sente
nce.', | |
| 1914 'Should have only a single space after a punctuation in
a comment. [whitespace/comments] [5]') | |
| 1915 self.assert_lint('int a; // Why did I write this? This is a another sen
tence.', | |
| 1916 'Should have only a single space after a punctuation in
a comment. [whitespace/comments] [5]') | |
| 1917 self.assert_lint('int a; // Elementary, my dear.', | |
| 1918 'Should have only a single space after a punctuation in
a comment. [whitespace/comments] [5]') | |
| 1919 self.assert_lint('int a; // The following should be clear: Is it?', | |
| 1920 'Should have only a single space after a punctuation in
a comment. [whitespace/comments] [5]') | |
| 1921 self.assert_lint('int a; // Look at the follow semicolon; I hope this g
ives an error.', | |
| 1922 'Should have only a single space after a punctuation in
a comment. [whitespace/comments] [5]') | |
| 1923 | |
| 1924 def test_space_after_comment_marker(self): | |
| 1925 self.assert_lint('//', '') | |
| 1926 self.assert_lint('//x', 'Should have a space between // and comment' | |
| 1927 ' [whitespace/comments] [4]') | |
| 1928 self.assert_lint('// x', '') | |
| 1929 self.assert_lint('//----', '') | |
| 1930 self.assert_lint('//====', '') | |
| 1931 self.assert_lint('//////', '') | |
| 1932 self.assert_lint('////// x', '') | |
| 1933 self.assert_lint('/// x', '') | |
| 1934 self.assert_lint('////x', 'Should have a space between // and comment' | |
| 1935 ' [whitespace/comments] [4]') | |
| 1936 | |
| 1937 def test_newline_at_eof(self): | |
| 1938 def do_test(self, data, is_missing_eof): | |
| 1939 error_collector = ErrorCollector(self.assertTrue) | |
| 1940 self.process_file_data('foo.cpp', 'cpp', data.split('\n'), | |
| 1941 error_collector) | |
| 1942 # The warning appears only once. | |
| 1943 self.assertEqual( | |
| 1944 int(is_missing_eof), | |
| 1945 error_collector.results().count( | |
| 1946 'Could not find a newline character at the end of the file.' | |
| 1947 ' [whitespace/ending_newline] [5]')) | |
| 1948 | |
| 1949 do_test(self, '// Newline\n// at EOF\n', False) | |
| 1950 do_test(self, '// No newline\n// at EOF', True) | |
| 1951 | |
| 1952 def test_invalid_utf8(self): | |
| 1953 def do_test(self, raw_bytes, has_invalid_utf8): | |
| 1954 error_collector = ErrorCollector(self.assertTrue) | |
| 1955 self.process_file_data('foo.cpp', 'cpp', | |
| 1956 unicode(raw_bytes, 'utf8', 'replace').split('
\n'), | |
| 1957 error_collector) | |
| 1958 # The warning appears only once. | |
| 1959 self.assertEqual( | |
| 1960 int(has_invalid_utf8), | |
| 1961 error_collector.results().count( | |
| 1962 'Line contains invalid UTF-8' | |
| 1963 ' (or Unicode replacement character).' | |
| 1964 ' [readability/utf8] [5]')) | |
| 1965 | |
| 1966 do_test(self, 'Hello world\n', False) | |
| 1967 do_test(self, '\xe9\x8e\xbd\n', False) | |
| 1968 do_test(self, '\xe9x\x8e\xbd\n', True) | |
| 1969 # This is the encoding of the replacement character itself (which | |
| 1970 # you can see by evaluating codecs.getencoder('utf8')(u'\ufffd')). | |
| 1971 do_test(self, '\xef\xbf\xbd\n', True) | |
| 1972 | |
| 1973 def test_is_blank_line(self): | |
| 1974 self.assertTrue(cpp_style.is_blank_line('')) | |
| 1975 self.assertTrue(cpp_style.is_blank_line(' ')) | |
| 1976 self.assertTrue(cpp_style.is_blank_line(' \t\r\n')) | |
| 1977 self.assertTrue(not cpp_style.is_blank_line('int a;')) | |
| 1978 self.assertTrue(not cpp_style.is_blank_line('{')) | |
| 1979 | |
| 1980 def test_blank_lines_check(self): | |
| 1981 self.assert_blank_lines_check(['{\n', '\n', '\n', '}\n'], 1, 1) | |
| 1982 self.assert_blank_lines_check([' if (foo) {\n', '\n', ' }\n'], 1, 1) | |
| 1983 self.assert_blank_lines_check( | |
| 1984 ['\n', '// {\n', '\n', '\n', '// Comment\n', '{\n', '}\n'], 0, 0) | |
| 1985 self.assert_blank_lines_check(['\n', 'run("{");\n', '\n'], 0, 0) | |
| 1986 self.assert_blank_lines_check(['\n', ' if (foo) { return 0; }\n', '\n']
, 0, 0) | |
| 1987 | |
| 1988 def test_allow_blank_line_before_closing_namespace(self): | |
| 1989 error_collector = ErrorCollector(self.assertTrue) | |
| 1990 self.process_file_data('foo.cpp', 'cpp', | |
| 1991 ['namespace {', '', '} // namespace'], | |
| 1992 error_collector) | |
| 1993 self.assertEqual(0, error_collector.results().count( | |
| 1994 'Blank line at the end of a code block. Is this needed?' | |
| 1995 ' [whitespace/blank_line] [3]')) | |
| 1996 | |
| 1997 def test_allow_blank_line_before_if_else_chain(self): | |
| 1998 error_collector = ErrorCollector(self.assertTrue) | |
| 1999 self.process_file_data('foo.cpp', 'cpp', | |
| 2000 ['if (hoge) {', | |
| 2001 '', # No warning | |
| 2002 '} else if (piyo) {', | |
| 2003 '', # No warning | |
| 2004 '} else if (piyopiyo) {', | |
| 2005 ' hoge = true;', # No warning | |
| 2006 '} else {', | |
| 2007 '', # Warning on this line | |
| 2008 '}'], | |
| 2009 error_collector) | |
| 2010 self.assertEqual(1, error_collector.results().count( | |
| 2011 'Blank line at the end of a code block. Is this needed?' | |
| 2012 ' [whitespace/blank_line] [3]')) | |
| 2013 | |
| 2014 def test_else_on_same_line_as_closing_braces(self): | |
| 2015 error_collector = ErrorCollector(self.assertTrue) | |
| 2016 self.process_file_data('foo.cpp', 'cpp', | |
| 2017 ['if (hoge) {', | |
| 2018 '', | |
| 2019 '}', | |
| 2020 ' else {' # Warning on this line | |
| 2021 '', | |
| 2022 '}'], | |
| 2023 error_collector) | |
| 2024 self.assertEqual(1, error_collector.results().count( | |
| 2025 'An else should appear on the same line as the preceding }' | |
| 2026 ' [whitespace/newline] [4]')) | |
| 2027 | |
| 2028 def test_else_clause_not_on_same_line_as_else(self): | |
| 2029 self.assert_lint(' else DoSomethingElse();', | |
| 2030 'Else clause should never be on same line as else ' | |
| 2031 '(use 2 lines) [whitespace/newline] [4]') | |
| 2032 self.assert_lint(' else ifDoSomethingElse();', | |
| 2033 'Else clause should never be on same line as else ' | |
| 2034 '(use 2 lines) [whitespace/newline] [4]') | |
| 2035 self.assert_lint(' else if (blah) {', '') | |
| 2036 self.assert_lint(' variable_ends_in_else = true;', '') | |
| 2037 | |
| 2038 def test_comma(self): | |
| 2039 self.assert_lint('a = f(1,2);', | |
| 2040 'Missing space after , [whitespace/comma] [3]') | |
| 2041 self.assert_lint('int tmp=a,a=b,b=tmp;', | |
| 2042 ['Missing spaces around = [whitespace/operators] [4]', | |
| 2043 'Missing space after , [whitespace/comma] [3]']) | |
| 2044 self.assert_lint('f(a, /* name */ b);', '') | |
| 2045 self.assert_lint('f(a, /* name */b);', '') | |
| 2046 | |
| 2047 def test_declaration(self): | |
| 2048 self.assert_lint('int a;', '') | |
| 2049 self.assert_lint('int a;', 'Extra space between int and a [whitespace
/declaration] [3]') | |
| 2050 self.assert_lint('int* a;', 'Extra space between int* and a [whitespac
e/declaration] [3]') | |
| 2051 self.assert_lint('else if { }', '') | |
| 2052 self.assert_lint('else if { }', 'Extra space between else and if [whi
tespace/declaration] [3]') | |
| 2053 | |
| 2054 def test_pointer_reference_marker_location(self): | |
| 2055 self.assert_lint('int* b;', '', 'foo.cpp') | |
| 2056 self.assert_lint('int *b;', | |
| 2057 'Declaration has space between type name and * in int *
b [whitespace/declaration] [3]', | |
| 2058 'foo.cpp') | |
| 2059 self.assert_lint('return *b;', '', 'foo.cpp') | |
| 2060 self.assert_lint('delete *b;', '', 'foo.cpp') | |
| 2061 self.assert_lint('int *b;', '', 'foo.c') | |
| 2062 self.assert_lint('int* b;', | |
| 2063 'Declaration has space between * and variable name in i
nt* b [whitespace/declaration] [3]', | |
| 2064 'foo.c') | |
| 2065 self.assert_lint('int& b;', '', 'foo.cpp') | |
| 2066 self.assert_lint('int &b;', | |
| 2067 'Declaration has space between type name and & in int &
b [whitespace/declaration] [3]', | |
| 2068 'foo.cpp') | |
| 2069 self.assert_lint('return &b;', '', 'foo.cpp') | |
| 2070 | |
| 2071 def test_indent(self): | |
| 2072 self.assert_lint('static int noindent;', '') | |
| 2073 self.assert_lint(' int fourSpaceIndent;', '') | |
| 2074 self.assert_lint(' int oneSpaceIndent;', | |
| 2075 'Weird number of spaces at line-start. ' | |
| 2076 'Are you using a 4-space indent? [whitespace/indent] [
3]') | |
| 2077 self.assert_lint(' int threeSpaceIndent;', | |
| 2078 'Weird number of spaces at line-start. ' | |
| 2079 'Are you using a 4-space indent? [whitespace/indent] [
3]') | |
| 2080 self.assert_lint(' char* oneSpaceIndent = "public:";', | |
| 2081 'Weird number of spaces at line-start. ' | |
| 2082 'Are you using a 4-space indent? [whitespace/indent] [
3]') | |
| 2083 self.assert_lint(' public:', | |
| 2084 'Weird number of spaces at line-start. ' | |
| 2085 'Are you using a 4-space indent? [whitespace/indent] [
3]') | |
| 2086 self.assert_lint(' public:', | |
| 2087 'Weird number of spaces at line-start. ' | |
| 2088 'Are you using a 4-space indent? [whitespace/indent] [
3]') | |
| 2089 self.assert_lint(' public:', | |
| 2090 'Weird number of spaces at line-start. ' | |
| 2091 'Are you using a 4-space indent? [whitespace/indent] [
3]') | |
| 2092 self.assert_multi_line_lint( | |
| 2093 'class Foo {\n' | |
| 2094 'public:\n' | |
| 2095 ' enum Bar {\n' | |
| 2096 ' Alpha,\n' | |
| 2097 ' Beta,\n' | |
| 2098 '#if ENABLED_BETZ\n' | |
| 2099 ' Charlie,\n' | |
| 2100 '#endif\n' | |
| 2101 ' };\n' | |
| 2102 '};', | |
| 2103 '') | |
| 2104 self.assert_multi_line_lint( | |
| 2105 'if (true) {\n' | |
| 2106 ' myFunction(reallyLongParam1, reallyLongParam2,\n' | |
| 2107 ' reallyLongParam3);\n' | |
| 2108 '}\n', | |
| 2109 'Weird number of spaces at line-start. Are you using a 4-space inde
nt? [whitespace/indent] [3]') | |
| 2110 | |
| 2111 self.assert_multi_line_lint( | |
| 2112 'if (true) {\n' | |
| 2113 ' myFunction(reallyLongParam1, reallyLongParam2,\n' | |
| 2114 ' reallyLongParam3);\n' | |
| 2115 '}\n', | |
| 2116 'When wrapping a line, only indent 4 spaces. [whitespace/indent] [3
]') | |
| 2117 | |
| 2118 | |
| 2119 def test_not_alabel(self): | |
| 2120 self.assert_lint('MyVeryLongNamespace::MyVeryLongClassName::', '') | |
| 2121 | |
| 2122 def test_tab(self): | |
| 2123 self.assert_lint('\tint a;', | |
| 2124 'Tab found; better to use spaces [whitespace/tab] [1]'
) | |
| 2125 self.assert_lint('int a = 5;\t// set a to 5', | |
| 2126 'Tab found; better to use spaces [whitespace/tab] [1]'
) | |
| 2127 | |
| 2128 def test_unnamed_namespaces_in_headers(self): | |
| 2129 self.assert_language_rules_check( | |
| 2130 'foo.h', 'namespace {', | |
| 2131 'Do not use unnamed namespaces in header files. See' | |
| 2132 ' http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Nam
espaces' | |
| 2133 ' for more information. [build/namespaces] [4]') | |
| 2134 # namespace registration macros are OK. | |
| 2135 self.assert_language_rules_check('foo.h', 'namespace { \\', '') | |
| 2136 # named namespaces are OK. | |
| 2137 self.assert_language_rules_check('foo.h', 'namespace foo {', '') | |
| 2138 self.assert_language_rules_check('foo.h', 'namespace foonamespace {', ''
) | |
| 2139 self.assert_language_rules_check('foo.cpp', 'namespace {', '') | |
| 2140 self.assert_language_rules_check('foo.cpp', 'namespace foo {', '') | |
| 2141 | |
| 2142 def test_build_class(self): | |
| 2143 # Test that the linter can parse to the end of class definitions, | |
| 2144 # and that it will report when it can't. | |
| 2145 # Use multi-line linter because it performs the ClassState check. | |
| 2146 self.assert_multi_line_lint( | |
| 2147 'class Foo {', | |
| 2148 'Failed to find complete declaration of class Foo' | |
| 2149 ' [build/class] [5]') | |
| 2150 # Don't warn on forward declarations of various types. | |
| 2151 self.assert_multi_line_lint( | |
| 2152 'class Foo;', | |
| 2153 '') | |
| 2154 self.assert_multi_line_lint( | |
| 2155 '''\ | |
| 2156 struct Foo* | |
| 2157 foo = NewFoo();''', | |
| 2158 '') | |
| 2159 # Here is an example where the linter gets confused, even though | |
| 2160 # the code doesn't violate the style guide. | |
| 2161 self.assert_multi_line_lint( | |
| 2162 'class Foo\n' | |
| 2163 '#ifdef DERIVE_FROM_GOO\n' | |
| 2164 ' : public Goo {\n' | |
| 2165 '#else\n' | |
| 2166 ' : public Hoo {\n' | |
| 2167 '#endif\n' | |
| 2168 '};', | |
| 2169 'Failed to find complete declaration of class Foo' | |
| 2170 ' [build/class] [5]') | |
| 2171 | |
| 2172 def test_build_end_comment(self): | |
| 2173 # The crosstool compiler we currently use will fail to compile the | |
| 2174 # code in this test, so we might consider removing the lint check. | |
| 2175 self.assert_lint('#endif Not a comment', | |
| 2176 'Uncommented text after #endif is non-standard.' | |
| 2177 ' Use a comment.' | |
| 2178 ' [build/endif_comment] [5]') | |
| 2179 | |
| 2180 def test_build_forward_decl(self): | |
| 2181 # The crosstool compiler we currently use will fail to compile the | |
| 2182 # code in this test, so we might consider removing the lint check. | |
| 2183 self.assert_lint('class Foo::Goo;', | |
| 2184 'Inner-style forward declarations are invalid.' | |
| 2185 ' Remove this line.' | |
| 2186 ' [build/forward_decl] [5]') | |
| 2187 | |
| 2188 def test_build_header_guard(self): | |
| 2189 file_path = 'mydir/Foo.h' | |
| 2190 | |
| 2191 # We can't rely on our internal stuff to get a sane path on the open sou
rce | |
| 2192 # side of things, so just parse out the suggested header guard. This | |
| 2193 # doesn't allow us to test the suggested header guard, but it does let u
s | |
| 2194 # test all the other header tests. | |
| 2195 error_collector = ErrorCollector(self.assertTrue) | |
| 2196 self.process_file_data(file_path, 'h', [], error_collector) | |
| 2197 expected_guard = '' | |
| 2198 matcher = re.compile( | |
| 2199 'No \#ifndef header guard found\, suggested CPP variable is\: ([A-Za
-z_0-9]+) ') | |
| 2200 for error in error_collector.result_list(): | |
| 2201 matches = matcher.match(error) | |
| 2202 if matches: | |
| 2203 expected_guard = matches.group(1) | |
| 2204 break | |
| 2205 | |
| 2206 # Make sure we extracted something for our header guard. | |
| 2207 self.assertNotEqual(expected_guard, '') | |
| 2208 | |
| 2209 # Wrong guard | |
| 2210 error_collector = ErrorCollector(self.assertTrue) | |
| 2211 self.process_file_data(file_path, 'h', | |
| 2212 ['#ifndef FOO_H', '#define FOO_H'], error_collect
or) | |
| 2213 self.assertEqual( | |
| 2214 1, | |
| 2215 error_collector.result_list().count( | |
| 2216 '#ifndef header guard has wrong style, please use: %s' | |
| 2217 ' [build/header_guard] [5]' % expected_guard), | |
| 2218 error_collector.result_list()) | |
| 2219 | |
| 2220 # No define | |
| 2221 error_collector = ErrorCollector(self.assertTrue) | |
| 2222 self.process_file_data(file_path, 'h', | |
| 2223 ['#ifndef %s' % expected_guard], error_collector) | |
| 2224 self.assertEqual( | |
| 2225 1, | |
| 2226 error_collector.result_list().count( | |
| 2227 'No #ifndef header guard found, suggested CPP variable is: %s' | |
| 2228 ' [build/header_guard] [5]' % expected_guard), | |
| 2229 error_collector.result_list()) | |
| 2230 | |
| 2231 # Mismatched define | |
| 2232 error_collector = ErrorCollector(self.assertTrue) | |
| 2233 self.process_file_data(file_path, 'h', | |
| 2234 ['#ifndef %s' % expected_guard, | |
| 2235 '#define FOO_H'], | |
| 2236 error_collector) | |
| 2237 self.assertEqual( | |
| 2238 1, | |
| 2239 error_collector.result_list().count( | |
| 2240 'No #ifndef header guard found, suggested CPP variable is: %s' | |
| 2241 ' [build/header_guard] [5]' % expected_guard), | |
| 2242 error_collector.result_list()) | |
| 2243 | |
| 2244 # No header guard errors | |
| 2245 error_collector = ErrorCollector(self.assertTrue) | |
| 2246 self.process_file_data(file_path, 'h', | |
| 2247 ['#ifndef %s' % expected_guard, | |
| 2248 '#define %s' % expected_guard, | |
| 2249 '#endif // %s' % expected_guard], | |
| 2250 error_collector) | |
| 2251 for line in error_collector.result_list(): | |
| 2252 if line.find('build/header_guard') != -1: | |
| 2253 self.fail('Unexpected error: %s' % line) | |
| 2254 | |
| 2255 # Completely incorrect header guard | |
| 2256 error_collector = ErrorCollector(self.assertTrue) | |
| 2257 self.process_file_data(file_path, 'h', | |
| 2258 ['#ifndef FOO', | |
| 2259 '#define FOO', | |
| 2260 '#endif // FOO'], | |
| 2261 error_collector) | |
| 2262 self.assertEqual( | |
| 2263 1, | |
| 2264 error_collector.result_list().count( | |
| 2265 '#ifndef header guard has wrong style, please use: %s' | |
| 2266 ' [build/header_guard] [5]' % expected_guard), | |
| 2267 error_collector.result_list()) | |
| 2268 | |
| 2269 # Special case for flymake | |
| 2270 error_collector = ErrorCollector(self.assertTrue) | |
| 2271 self.process_file_data('mydir/Foo_flymake.h', 'h', | |
| 2272 ['#ifndef %s' % expected_guard, | |
| 2273 '#define %s' % expected_guard, | |
| 2274 '#endif // %s' % expected_guard], | |
| 2275 error_collector) | |
| 2276 for line in error_collector.result_list(): | |
| 2277 if line.find('build/header_guard') != -1: | |
| 2278 self.fail('Unexpected error: %s' % line) | |
| 2279 | |
| 2280 error_collector = ErrorCollector(self.assertTrue) | |
| 2281 self.process_file_data('mydir/Foo_flymake.h', 'h', [], error_collector) | |
| 2282 self.assertEqual( | |
| 2283 1, | |
| 2284 error_collector.result_list().count( | |
| 2285 'No #ifndef header guard found, suggested CPP variable is: %s' | |
| 2286 ' [build/header_guard] [5]' % expected_guard), | |
| 2287 error_collector.result_list()) | |
| 2288 | |
| 2289 # Verify that we don't blindly suggest the WTF prefix for all headers. | |
| 2290 self.assertFalse(expected_guard.startswith('WTF_')) | |
| 2291 | |
| 2292 # Allow the WTF_ prefix for files in that directory. | |
| 2293 header_guard_filter = FilterConfiguration(('-', '+build/header_guard')) | |
| 2294 error_collector = ErrorCollector(self.assertTrue, header_guard_filter) | |
| 2295 self.process_file_data('Source/JavaScriptCore/wtf/TestName.h', 'h', | |
| 2296 ['#ifndef WTF_TestName_h', '#define WTF_TestName_
h'], | |
| 2297 error_collector) | |
| 2298 self.assertEqual(0, len(error_collector.result_list()), | |
| 2299 error_collector.result_list()) | |
| 2300 | |
| 2301 # Also allow the non WTF_ prefix for files in that directory. | |
| 2302 error_collector = ErrorCollector(self.assertTrue, header_guard_filter) | |
| 2303 self.process_file_data('Source/JavaScriptCore/wtf/TestName.h', 'h', | |
| 2304 ['#ifndef TestName_h', '#define TestName_h'], | |
| 2305 error_collector) | |
| 2306 self.assertEqual(0, len(error_collector.result_list()), | |
| 2307 error_collector.result_list()) | |
| 2308 | |
| 2309 # Verify that we suggest the WTF prefix version. | |
| 2310 error_collector = ErrorCollector(self.assertTrue, header_guard_filter) | |
| 2311 self.process_file_data('Source/JavaScriptCore/wtf/TestName.h', 'h', | |
| 2312 ['#ifndef BAD_TestName_h', '#define BAD_TestName_
h'], | |
| 2313 error_collector) | |
| 2314 self.assertEqual( | |
| 2315 1, | |
| 2316 error_collector.result_list().count( | |
| 2317 '#ifndef header guard has wrong style, please use: WTF_TestName_
h' | |
| 2318 ' [build/header_guard] [5]'), | |
| 2319 error_collector.result_list()) | |
| 2320 | |
| 2321 # Verify that the Chromium-style header guard is allowed as well. | |
| 2322 error_collector = ErrorCollector(self.assertTrue, header_guard_filter) | |
| 2323 self.process_file_data('Source/foo/testname.h', 'h', | |
| 2324 ['#ifndef BLINK_FOO_TESTNAME_H_', | |
| 2325 '#define BLINK_FOO_TESTNAME_H_'], | |
| 2326 error_collector) | |
| 2327 self.assertEqual(0, len(error_collector.result_list()), | |
| 2328 error_collector.result_list()) | |
| 2329 | |
| 2330 def test_build_printf_format(self): | |
| 2331 self.assert_lint( | |
| 2332 r'printf("\%%d", value);', | |
| 2333 '%, [, (, and { are undefined character escapes. Unescape them.' | |
| 2334 ' [build/printf_format] [3]') | |
| 2335 | |
| 2336 self.assert_lint( | |
| 2337 r'snprintf(buffer, sizeof(buffer), "\[%d", value);', | |
| 2338 '%, [, (, and { are undefined character escapes. Unescape them.' | |
| 2339 ' [build/printf_format] [3]') | |
| 2340 | |
| 2341 self.assert_lint( | |
| 2342 r'fprintf(file, "\(%d", value);', | |
| 2343 '%, [, (, and { are undefined character escapes. Unescape them.' | |
| 2344 ' [build/printf_format] [3]') | |
| 2345 | |
| 2346 self.assert_lint( | |
| 2347 r'vsnprintf(buffer, sizeof(buffer), "\\\{%d", ap);', | |
| 2348 '%, [, (, and { are undefined character escapes. Unescape them.' | |
| 2349 ' [build/printf_format] [3]') | |
| 2350 | |
| 2351 # Don't warn if double-slash precedes the symbol | |
| 2352 self.assert_lint(r'printf("\\%%%d", value);', | |
| 2353 '') | |
| 2354 | |
| 2355 def test_runtime_printf_format(self): | |
| 2356 self.assert_lint( | |
| 2357 r'fprintf(file, "%q", value);', | |
| 2358 '%q in format strings is deprecated. Use %ll instead.' | |
| 2359 ' [runtime/printf_format] [3]') | |
| 2360 | |
| 2361 self.assert_lint( | |
| 2362 r'aprintf(file, "The number is %12q", value);', | |
| 2363 '%q in format strings is deprecated. Use %ll instead.' | |
| 2364 ' [runtime/printf_format] [3]') | |
| 2365 | |
| 2366 self.assert_lint( | |
| 2367 r'printf(file, "The number is" "%-12q", value);', | |
| 2368 '%q in format strings is deprecated. Use %ll instead.' | |
| 2369 ' [runtime/printf_format] [3]') | |
| 2370 | |
| 2371 self.assert_lint( | |
| 2372 r'printf(file, "The number is" "%+12q", value);', | |
| 2373 '%q in format strings is deprecated. Use %ll instead.' | |
| 2374 ' [runtime/printf_format] [3]') | |
| 2375 | |
| 2376 self.assert_lint( | |
| 2377 r'printf(file, "The number is" "% 12q", value);', | |
| 2378 '%q in format strings is deprecated. Use %ll instead.' | |
| 2379 ' [runtime/printf_format] [3]') | |
| 2380 | |
| 2381 self.assert_lint( | |
| 2382 r'snprintf(file, "Never mix %d and %1$d parmaeters!", value);', | |
| 2383 '%N$ formats are unconventional. Try rewriting to avoid them.' | |
| 2384 ' [runtime/printf_format] [2]') | |
| 2385 | |
| 2386 def assert_lintLogCodeOnError(self, code, expected_message): | |
| 2387 # Special assert_lint which logs the input code on error. | |
| 2388 result = self.perform_single_line_lint(code, 'foo.cpp') | |
| 2389 if result != expected_message: | |
| 2390 self.fail('For code: "%s"\nGot: "%s"\nExpected: "%s"' | |
| 2391 % (code, result, expected_message)) | |
| 2392 | |
| 2393 def test_build_storage_class(self): | |
| 2394 qualifiers = [None, 'const', 'volatile'] | |
| 2395 signs = [None, 'signed', 'unsigned'] | |
| 2396 types = ['void', 'char', 'int', 'float', 'double', | |
| 2397 'schar', 'int8', 'uint8', 'int16', 'uint16', | |
| 2398 'int32', 'uint32', 'int64', 'uint64'] | |
| 2399 storage_classes = ['auto', 'extern', 'register', 'static', 'typedef'] | |
| 2400 | |
| 2401 build_storage_class_error_message = ( | |
| 2402 'Storage class (static, extern, typedef, etc) should be first.' | |
| 2403 ' [build/storage_class] [5]') | |
| 2404 | |
| 2405 # Some explicit cases. Legal in C++, deprecated in C99. | |
| 2406 self.assert_lint('const int static foo = 5;', | |
| 2407 build_storage_class_error_message) | |
| 2408 | |
| 2409 self.assert_lint('char static foo;', | |
| 2410 build_storage_class_error_message) | |
| 2411 | |
| 2412 self.assert_lint('double const static foo = 2.0;', | |
| 2413 build_storage_class_error_message) | |
| 2414 | |
| 2415 self.assert_lint('uint64 typedef unsignedLongLong;', | |
| 2416 build_storage_class_error_message) | |
| 2417 | |
| 2418 self.assert_lint('int register foo = 0;', | |
| 2419 build_storage_class_error_message) | |
| 2420 | |
| 2421 # Since there are a very large number of possibilities, randomly | |
| 2422 # construct declarations. | |
| 2423 # Make sure that the declaration is logged if there's an error. | |
| 2424 # Seed generator with an integer for absolute reproducibility. | |
| 2425 random.seed(25) | |
| 2426 for unused_i in range(10): | |
| 2427 # Build up random list of non-storage-class declaration specs. | |
| 2428 other_decl_specs = [random.choice(qualifiers), random.choice(signs), | |
| 2429 random.choice(types)] | |
| 2430 # remove None | |
| 2431 other_decl_specs = filter(lambda x: x is not None, other_decl_specs) | |
| 2432 | |
| 2433 # shuffle | |
| 2434 random.shuffle(other_decl_specs) | |
| 2435 | |
| 2436 # insert storage class after the first | |
| 2437 storage_class = random.choice(storage_classes) | |
| 2438 insertion_point = random.randint(1, len(other_decl_specs)) | |
| 2439 decl_specs = (other_decl_specs[0:insertion_point] | |
| 2440 + [storage_class] | |
| 2441 + other_decl_specs[insertion_point:]) | |
| 2442 | |
| 2443 self.assert_lintLogCodeOnError( | |
| 2444 ' '.join(decl_specs) + ';', | |
| 2445 build_storage_class_error_message) | |
| 2446 | |
| 2447 # but no error if storage class is first | |
| 2448 self.assert_lintLogCodeOnError( | |
| 2449 storage_class + ' ' + ' '.join(other_decl_specs), | |
| 2450 '') | |
| 2451 | |
| 2452 def test_legal_copyright(self): | |
| 2453 legal_copyright_message = ( | |
| 2454 'No copyright message found. ' | |
| 2455 'You should have a line: "Copyright [year] <Copyright Owner>"' | |
| 2456 ' [legal/copyright] [5]') | |
| 2457 | |
| 2458 copyright_line = '// Copyright 2008 Google Inc. All Rights Reserved.' | |
| 2459 | |
| 2460 file_path = 'mydir/googleclient/foo.cpp' | |
| 2461 | |
| 2462 # There should be a copyright message in the first 10 lines | |
| 2463 error_collector = ErrorCollector(self.assertTrue) | |
| 2464 self.process_file_data(file_path, 'cpp', [], error_collector) | |
| 2465 self.assertEqual( | |
| 2466 1, | |
| 2467 error_collector.result_list().count(legal_copyright_message)) | |
| 2468 | |
| 2469 error_collector = ErrorCollector(self.assertTrue) | |
| 2470 self.process_file_data( | |
| 2471 file_path, 'cpp', | |
| 2472 ['' for unused_i in range(10)] + [copyright_line], | |
| 2473 error_collector) | |
| 2474 self.assertEqual( | |
| 2475 1, | |
| 2476 error_collector.result_list().count(legal_copyright_message)) | |
| 2477 | |
| 2478 # Test that warning isn't issued if Copyright line appears early enough. | |
| 2479 error_collector = ErrorCollector(self.assertTrue) | |
| 2480 self.process_file_data(file_path, 'cpp', [copyright_line], error_collect
or) | |
| 2481 for message in error_collector.result_list(): | |
| 2482 if message.find('legal/copyright') != -1: | |
| 2483 self.fail('Unexpected error: %s' % message) | |
| 2484 | |
| 2485 error_collector = ErrorCollector(self.assertTrue) | |
| 2486 self.process_file_data( | |
| 2487 file_path, 'cpp', | |
| 2488 ['' for unused_i in range(9)] + [copyright_line], | |
| 2489 error_collector) | |
| 2490 for message in error_collector.result_list(): | |
| 2491 if message.find('legal/copyright') != -1: | |
| 2492 self.fail('Unexpected error: %s' % message) | |
| 2493 | |
| 2494 def test_invalid_increment(self): | |
| 2495 self.assert_lint('*count++;', | |
| 2496 'Changing pointer instead of value (or unused value of
' | |
| 2497 'operator*). [runtime/invalid_increment] [5]') | |
| 2498 | |
| 2499 # Integral bitfields must be declared with either signed or unsigned keyword
. | |
| 2500 def test_plain_integral_bitfields(self): | |
| 2501 errmsg = ('Please declare integral type bitfields with either signed or
unsigned. [runtime/bitfields] [5]') | |
| 2502 | |
| 2503 self.assert_lint('int a : 30;', errmsg) | |
| 2504 self.assert_lint('mutable short a : 14;', errmsg) | |
| 2505 self.assert_lint('const char a : 6;', errmsg) | |
| 2506 self.assert_lint('long int a : 30;', errmsg) | |
| 2507 self.assert_lint('int a = 1 ? 0 : 30;', '') | |
| 2508 | |
| 2509 # A mixture of unsigned and bool bitfields in a class will generate a warnin
g. | |
| 2510 def test_mixing_unsigned_bool_bitfields(self): | |
| 2511 def errmsg(bool_bitfields, unsigned_bitfields, name): | |
| 2512 bool_list = ', '.join(bool_bitfields) | |
| 2513 unsigned_list = ', '.join(unsigned_bitfields) | |
| 2514 return ('The class %s contains mixed unsigned and bool bitfields, ' | |
| 2515 'which will pack into separate words on the MSVC compiler.\n
' | |
| 2516 'Bool bitfields are [%s].\nUnsigned bitfields are [%s].\n' | |
| 2517 'Consider converting bool bitfields to unsigned. [runtime/b
itfields] [5]' | |
| 2518 % (name, bool_list, unsigned_list)) | |
| 2519 | |
| 2520 def build_test_case(bitfields, name, will_warn, extra_warnings=[]): | |
| 2521 bool_bitfields = [] | |
| 2522 unsigned_bitfields = [] | |
| 2523 test_string = 'class %s {\n' % (name,) | |
| 2524 line = 2 | |
| 2525 for bitfield in bitfields: | |
| 2526 test_string += ' %s %s : %d;\n' % bitfield | |
| 2527 if bitfield[0] == 'bool': | |
| 2528 bool_bitfields.append('%d: %s' % (line, bitfield[1])) | |
| 2529 elif bitfield[0].startswith('unsigned'): | |
| 2530 unsigned_bitfields.append('%d: %s' % (line, bitfield[1])) | |
| 2531 line += 1 | |
| 2532 test_string += '}\n' | |
| 2533 error = '' | |
| 2534 if will_warn: | |
| 2535 error = errmsg(bool_bitfields, unsigned_bitfields, name) | |
| 2536 if extra_warnings and error: | |
| 2537 error = extra_warnings + [error] | |
| 2538 self.assert_multi_line_lint(test_string, error) | |
| 2539 | |
| 2540 build_test_case([('bool', 'm_boolMember', 4), ('unsigned', 'm_unsignedMe
mber', 3)], | |
| 2541 'MyClass', True) | |
| 2542 build_test_case([('bool', 'm_boolMember', 4), ('bool', 'm_anotherBool',
3)], | |
| 2543 'MyClass', False) | |
| 2544 build_test_case([('unsigned', 'm_unsignedMember', 4), ('unsigned', 'm_an
otherUnsigned', 3)], | |
| 2545 'MyClass', False) | |
| 2546 | |
| 2547 build_test_case([('bool', 'm_boolMember', 4), ('bool', 'm_anotherbool',
3), | |
| 2548 ('bool', 'm_moreBool', 1), ('bool', 'm_lastBool', 1), | |
| 2549 ('unsigned int', 'm_tokenUnsigned', 4)], | |
| 2550 'MyClass', True, ['Omit int when using unsigned [runtim
e/unsigned] [1]']) | |
| 2551 | |
| 2552 self.assert_multi_line_lint('class NoProblemsHere {\n' | |
| 2553 ' bool m_boolMember;\n' | |
| 2554 ' unsigned m_unsignedMember;\n' | |
| 2555 ' unsigned m_bitField1 : 1;\n' | |
| 2556 ' unsigned m_bitField4 : 4;\n' | |
| 2557 '}\n', '') | |
| 2558 | |
| 2559 # Bitfields which are not declared unsigned or bool will generate a warning. | |
| 2560 def test_unsigned_bool_bitfields(self): | |
| 2561 def errmsg(member, name, bit_type): | |
| 2562 return ('Member %s of class %s defined as a bitfield of type %s. ' | |
| 2563 'Please declare all bitfields as unsigned. [runtime/bitfiel
ds] [4]' | |
| 2564 % (member, name, bit_type)) | |
| 2565 | |
| 2566 def warning_bitfield_test(member, name, bit_type, bits): | |
| 2567 self.assert_multi_line_lint('class %s {\n%s %s: %d;\n}\n' | |
| 2568 % (name, bit_type, member, bits), | |
| 2569 errmsg(member, name, bit_type)) | |
| 2570 | |
| 2571 def safe_bitfield_test(member, name, bit_type, bits): | |
| 2572 self.assert_multi_line_lint('class %s {\n%s %s: %d;\n}\n' | |
| 2573 % (name, bit_type, member, bits), | |
| 2574 '') | |
| 2575 | |
| 2576 warning_bitfield_test('a', 'A', 'int32_t', 25) | |
| 2577 warning_bitfield_test('m_someField', 'SomeClass', 'signed', 4) | |
| 2578 warning_bitfield_test('m_someField', 'SomeClass', 'SomeEnum', 2) | |
| 2579 | |
| 2580 safe_bitfield_test('a', 'A', 'unsigned', 22) | |
| 2581 safe_bitfield_test('m_someField', 'SomeClass', 'bool', 1) | |
| 2582 safe_bitfield_test('m_someField', 'SomeClass', 'unsigned', 2) | |
| 2583 | |
| 2584 # Declarations in 'Expected' or 'SameSizeAs' classes are OK. | |
| 2585 warning_bitfield_test('m_bitfields', 'SomeClass', 'int32_t', 32) | |
| 2586 safe_bitfield_test('m_bitfields', 'ExpectedSomeClass', 'int32_t', 32) | |
| 2587 safe_bitfield_test('m_bitfields', 'SameSizeAsSomeClass', 'int32_t', 32) | |
| 2588 | |
| 2589 class CleansedLinesTest(unittest.TestCase): | |
| 2590 def test_init(self): | |
| 2591 lines = ['Line 1', | |
| 2592 'Line 2', | |
| 2593 'Line 3 // Comment test', | |
| 2594 'Line 4 "foo"'] | |
| 2595 | |
| 2596 clean_lines = cpp_style.CleansedLines(lines) | |
| 2597 self.assertEqual(lines, clean_lines.raw_lines) | |
| 2598 self.assertEqual(4, clean_lines.num_lines()) | |
| 2599 | |
| 2600 self.assertEqual(['Line 1', | |
| 2601 'Line 2', | |
| 2602 'Line 3 ', | |
| 2603 'Line 4 "foo"'], | |
| 2604 clean_lines.lines) | |
| 2605 | |
| 2606 self.assertEqual(['Line 1', | |
| 2607 'Line 2', | |
| 2608 'Line 3 ', | |
| 2609 'Line 4 ""'], | |
| 2610 clean_lines.elided) | |
| 2611 | |
| 2612 def test_init_empty(self): | |
| 2613 clean_lines = cpp_style.CleansedLines([]) | |
| 2614 self.assertEqual([], clean_lines.raw_lines) | |
| 2615 self.assertEqual(0, clean_lines.num_lines()) | |
| 2616 | |
| 2617 def test_collapse_strings(self): | |
| 2618 collapse = cpp_style.CleansedLines.collapse_strings | |
| 2619 self.assertEqual('""', collapse('""')) # "" (empty) | |
| 2620 self.assertEqual('"""', collapse('"""')) # """ (bad) | |
| 2621 self.assertEqual('""', collapse('"xyz"')) # "xyz" (string) | |
| 2622 self.assertEqual('""', collapse('"\\\""')) # "\"" (string) | |
| 2623 self.assertEqual('""', collapse('"\'"')) # "'" (string) | |
| 2624 self.assertEqual('"\"', collapse('"\"')) # "\" (bad) | |
| 2625 self.assertEqual('""', collapse('"\\\\"')) # "\\" (string) | |
| 2626 self.assertEqual('"', collapse('"\\\\\\"')) # "\\\" (bad) | |
| 2627 self.assertEqual('""', collapse('"\\\\\\\\"')) # "\\\\" (string) | |
| 2628 | |
| 2629 self.assertEqual('\'\'', collapse('\'\'')) # '' (empty) | |
| 2630 self.assertEqual('\'\'', collapse('\'a\'')) # 'a' (char) | |
| 2631 self.assertEqual('\'\'', collapse('\'\\\'\'')) # '\'' (char) | |
| 2632 self.assertEqual('\'', collapse('\'\\\'')) # '\' (bad) | |
| 2633 self.assertEqual('', collapse('\\012')) # '\012' (char) | |
| 2634 self.assertEqual('', collapse('\\xfF0')) # '\xfF0' (char) | |
| 2635 self.assertEqual('', collapse('\\n')) # '\n' (char) | |
| 2636 self.assertEqual('\#', collapse('\\#')) # '\#' (bad) | |
| 2637 | |
| 2638 self.assertEqual('StringReplace(body, "", "");', | |
| 2639 collapse('StringReplace(body, "\\\\", "\\\\\\\\");')) | |
| 2640 self.assertEqual('\'\' ""', | |
| 2641 collapse('\'"\' "foo"')) | |
| 2642 | |
| 2643 | |
| 2644 class OrderOfIncludesTest(CppStyleTestBase): | |
| 2645 def setUp(self): | |
| 2646 self.include_state = cpp_style._IncludeState() | |
| 2647 | |
| 2648 # Cheat os.path.abspath called in FileInfo class. | |
| 2649 self.os_path_abspath_orig = os.path.abspath | |
| 2650 os.path.abspath = lambda value: value | |
| 2651 | |
| 2652 def tearDown(self): | |
| 2653 os.path.abspath = self.os_path_abspath_orig | |
| 2654 | |
| 2655 def test_try_drop_common_suffixes(self): | |
| 2656 self.assertEqual('foo/foo', cpp_style._drop_common_suffixes('foo/foo-inl
.h')) | |
| 2657 self.assertEqual('foo/bar/foo', | |
| 2658 cpp_style._drop_common_suffixes('foo/bar/foo_inl.h')) | |
| 2659 self.assertEqual('foo/foo', cpp_style._drop_common_suffixes('foo/foo.cpp
')) | |
| 2660 self.assertEqual('foo/foo_unusualinternal', | |
| 2661 cpp_style._drop_common_suffixes('foo/foo_unusualinterna
l.h')) | |
| 2662 self.assertEqual('', | |
| 2663 cpp_style._drop_common_suffixes('_test.cpp')) | |
| 2664 self.assertEqual('test', | |
| 2665 cpp_style._drop_common_suffixes('test.cpp')) | |
| 2666 | |
| 2667 | |
| 2668 class OrderOfIncludesTest(CppStyleTestBase): | |
| 2669 def setUp(self): | |
| 2670 self.include_state = cpp_style._IncludeState() | |
| 2671 | |
| 2672 # Cheat os.path.abspath called in FileInfo class. | |
| 2673 self.os_path_abspath_orig = os.path.abspath | |
| 2674 self.os_path_isfile_orig = os.path.isfile | |
| 2675 os.path.abspath = lambda value: value | |
| 2676 | |
| 2677 def tearDown(self): | |
| 2678 os.path.abspath = self.os_path_abspath_orig | |
| 2679 os.path.isfile = self.os_path_isfile_orig | |
| 2680 | |
| 2681 def test_check_next_include_order__no_config(self): | |
| 2682 self.assertEqual('Header file should not contain WebCore config.h.', | |
| 2683 self.include_state.check_next_include_order(cpp_style._
CONFIG_HEADER, True, True)) | |
| 2684 | |
| 2685 def test_check_next_include_order__no_self(self): | |
| 2686 self.assertEqual('Header file should not contain itself.', | |
| 2687 self.include_state.check_next_include_order(cpp_style._
PRIMARY_HEADER, True, True)) | |
| 2688 # Test actual code to make sure that header types are correctly assigned
. | |
| 2689 self.assert_language_rules_check('Foo.h', | |
| 2690 '#include "Foo.h"\n', | |
| 2691 'Header file should not contain itself.
Should be: alphabetically sorted.' | |
| 2692 ' [build/include_order] [4]') | |
| 2693 self.assert_language_rules_check('FooBar.h', | |
| 2694 '#include "Foo.h"\n', | |
| 2695 '') | |
| 2696 | |
| 2697 def test_check_next_include_order__likely_then_config(self): | |
| 2698 self.assertEqual('Found header this file implements before WebCore confi
g.h.', | |
| 2699 self.include_state.check_next_include_order(cpp_style._
PRIMARY_HEADER, False, True)) | |
| 2700 self.assertEqual('Found WebCore config.h after a header this file implem
ents.', | |
| 2701 self.include_state.check_next_include_order(cpp_style._
CONFIG_HEADER, False, True)) | |
| 2702 | |
| 2703 def test_check_next_include_order__other_then_config(self): | |
| 2704 self.assertEqual('Found other header before WebCore config.h.', | |
| 2705 self.include_state.check_next_include_order(cpp_style._
OTHER_HEADER, False, True)) | |
| 2706 self.assertEqual('Found WebCore config.h after other header.', | |
| 2707 self.include_state.check_next_include_order(cpp_style._
CONFIG_HEADER, False, True)) | |
| 2708 | |
| 2709 def test_check_next_include_order__config_then_other_then_likely(self): | |
| 2710 self.assertEqual('', self.include_state.check_next_include_order(cpp_sty
le._CONFIG_HEADER, False, True)) | |
| 2711 self.assertEqual('Found other header before a header this file implement
s.', | |
| 2712 self.include_state.check_next_include_order(cpp_style._
OTHER_HEADER, False, True)) | |
| 2713 self.assertEqual('Found header this file implements after other header.'
, | |
| 2714 self.include_state.check_next_include_order(cpp_style._
PRIMARY_HEADER, False, True)) | |
| 2715 | |
| 2716 def test_check_alphabetical_include_order(self): | |
| 2717 self.assert_language_rules_check('foo.h', | |
| 2718 '#include "a.h"\n' | |
| 2719 '#include "c.h"\n' | |
| 2720 '#include "b.h"\n', | |
| 2721 'Alphabetical sorting problem. [build/
include_order] [4]') | |
| 2722 | |
| 2723 self.assert_language_rules_check('foo.h', | |
| 2724 '#include "a.h"\n' | |
| 2725 '#include "b.h"\n' | |
| 2726 '#include "c.h"\n', | |
| 2727 '') | |
| 2728 | |
| 2729 self.assert_language_rules_check('foo.h', | |
| 2730 '#include <assert.h>\n' | |
| 2731 '#include "bar.h"\n', | |
| 2732 'Alphabetical sorting problem. [build/
include_order] [4]') | |
| 2733 | |
| 2734 self.assert_language_rules_check('foo.h', | |
| 2735 '#include "bar.h"\n' | |
| 2736 '#include <assert.h>\n', | |
| 2737 '') | |
| 2738 | |
| 2739 def test_check_alphabetical_include_order_errors_reported_for_both_lines(sel
f): | |
| 2740 # If one of the two lines of out of order headers are filtered, the erro
r should be | |
| 2741 # reported on the other line. | |
| 2742 self.assert_language_rules_check('foo.h', | |
| 2743 '#include "a.h"\n' | |
| 2744 '#include "c.h"\n' | |
| 2745 '#include "b.h"\n', | |
| 2746 'Alphabetical sorting problem. [build/
include_order] [4]', | |
| 2747 lines_to_check=[2]) | |
| 2748 | |
| 2749 self.assert_language_rules_check('foo.h', | |
| 2750 '#include "a.h"\n' | |
| 2751 '#include "c.h"\n' | |
| 2752 '#include "b.h"\n', | |
| 2753 'Alphabetical sorting problem. [build/
include_order] [4]', | |
| 2754 lines_to_check=[3]) | |
| 2755 | |
| 2756 # If no lines are filtered, the error should be reported only once. | |
| 2757 self.assert_language_rules_check('foo.h', | |
| 2758 '#include "a.h"\n' | |
| 2759 '#include "c.h"\n' | |
| 2760 '#include "b.h"\n', | |
| 2761 'Alphabetical sorting problem. [build/
include_order] [4]') | |
| 2762 | |
| 2763 def test_check_line_break_after_own_header(self): | |
| 2764 self.assert_language_rules_check('foo.cpp', | |
| 2765 '#include "config.h"\n' | |
| 2766 '#include "foo.h"\n' | |
| 2767 '#include "bar.h"\n', | |
| 2768 'You should add a blank line after impl
ementation file\'s own header. [build/include_order] [4]') | |
| 2769 | |
| 2770 self.assert_language_rules_check('foo.cpp', | |
| 2771 '#include "config.h"\n' | |
| 2772 '#include "foo.h"\n' | |
| 2773 '\n' | |
| 2774 '#include "bar.h"\n', | |
| 2775 '') | |
| 2776 | |
| 2777 def test_check_preprocessor_in_include_section(self): | |
| 2778 self.assert_language_rules_check('foo.cpp', | |
| 2779 '#include "config.h"\n' | |
| 2780 '#include "foo.h"\n' | |
| 2781 '\n' | |
| 2782 '#ifdef BAZ\n' | |
| 2783 '#include "baz.h"\n' | |
| 2784 '#else\n' | |
| 2785 '#include "foobar.h"\n' | |
| 2786 '#endif"\n' | |
| 2787 '#include "bar.h"\n', # No flag because
previous is in preprocessor section | |
| 2788 '') | |
| 2789 | |
| 2790 self.assert_language_rules_check('foo.cpp', | |
| 2791 '#include "config.h"\n' | |
| 2792 '#include "foo.h"\n' | |
| 2793 '\n' | |
| 2794 '#ifdef BAZ\n' | |
| 2795 '#include "baz.h"\n' | |
| 2796 '#endif"\n' | |
| 2797 '#include "bar.h"\n' | |
| 2798 '#include "a.h"\n', # Should still flag
this. | |
| 2799 'Alphabetical sorting problem. [build/
include_order] [4]') | |
| 2800 | |
| 2801 self.assert_language_rules_check('foo.cpp', | |
| 2802 '#include "config.h"\n' | |
| 2803 '#include "foo.h"\n' | |
| 2804 '\n' | |
| 2805 '#ifdef BAZ\n' | |
| 2806 '#include "baz.h"\n' | |
| 2807 '#include "bar.h"\n' #Should still flag
this | |
| 2808 '#endif"\n', | |
| 2809 'Alphabetical sorting problem. [build/
include_order] [4]') | |
| 2810 | |
| 2811 self.assert_language_rules_check('foo.cpp', | |
| 2812 '#include "config.h"\n' | |
| 2813 '#include "foo.h"\n' | |
| 2814 '\n' | |
| 2815 '#ifdef BAZ\n' | |
| 2816 '#include "baz.h"\n' | |
| 2817 '#endif"\n' | |
| 2818 '#ifdef FOOBAR\n' | |
| 2819 '#include "foobar.h"\n' | |
| 2820 '#endif"\n' | |
| 2821 '#include "bar.h"\n' | |
| 2822 '#include "a.h"\n', # Should still flag
this. | |
| 2823 'Alphabetical sorting problem. [build/
include_order] [4]') | |
| 2824 | |
| 2825 # Check that after an already included error, the sorting rules still wo
rk. | |
| 2826 self.assert_language_rules_check('foo.cpp', | |
| 2827 '#include "config.h"\n' | |
| 2828 '#include "foo.h"\n' | |
| 2829 '\n' | |
| 2830 '#include "foo.h"\n' | |
| 2831 '#include "g.h"\n', | |
| 2832 '"foo.h" already included at foo.cpp:2
[build/include] [4]') | |
| 2833 | |
| 2834 def test_primary_header(self): | |
| 2835 # File with non-existing primary header should not produce errors. | |
| 2836 self.assert_language_rules_check('foo.cpp', | |
| 2837 '#include "config.h"\n' | |
| 2838 '\n' | |
| 2839 '#include "bar.h"\n', | |
| 2840 '') | |
| 2841 # Pretend that header files exist. | |
| 2842 os.path.isfile = lambda filename: True | |
| 2843 # Missing include for existing primary header -> error. | |
| 2844 self.assert_language_rules_check('foo.cpp', | |
| 2845 '#include "config.h"\n' | |
| 2846 '\n' | |
| 2847 '#include "bar.h"\n', | |
| 2848 'Found other header before a header thi
s file implements. ' | |
| 2849 'Should be: config.h, primary header, b
lank line, and then ' | |
| 2850 'alphabetically sorted. [build/include
_order] [4]') | |
| 2851 # Having include for existing primary header -> no error. | |
| 2852 self.assert_language_rules_check('foo.cpp', | |
| 2853 '#include "config.h"\n' | |
| 2854 '#include "foo.h"\n' | |
| 2855 '\n' | |
| 2856 '#include "bar.h"\n', | |
| 2857 '') | |
| 2858 | |
| 2859 os.path.isfile = self.os_path_isfile_orig | |
| 2860 | |
| 2861 def test_public_primary_header(self): | |
| 2862 # System header is not considered a primary header. | |
| 2863 self.assert_language_rules_check('foo.cpp', | |
| 2864 '#include "config.h"\n' | |
| 2865 '#include <other/foo.h>\n' | |
| 2866 '\n' | |
| 2867 '#include "a.h"\n', | |
| 2868 'Alphabetical sorting problem. [build/
include_order] [4]') | |
| 2869 | |
| 2870 # ...except that it starts with public/. | |
| 2871 self.assert_language_rules_check('foo.cpp', | |
| 2872 '#include "config.h"\n' | |
| 2873 '#include <public/foo.h>\n' | |
| 2874 '\n' | |
| 2875 '#include "a.h"\n', | |
| 2876 '') | |
| 2877 | |
| 2878 # Even if it starts with public/ its base part must match with the sourc
e file name. | |
| 2879 self.assert_language_rules_check('foo.cpp', | |
| 2880 '#include "config.h"\n' | |
| 2881 '#include <public/foop.h>\n' | |
| 2882 '\n' | |
| 2883 '#include "a.h"\n', | |
| 2884 'Alphabetical sorting problem. [build/
include_order] [4]') | |
| 2885 | |
| 2886 def test_check_wtf_includes(self): | |
| 2887 self.assert_language_rules_check('foo.cpp', | |
| 2888 '#include "config.h"\n' | |
| 2889 '#include "foo.h"\n' | |
| 2890 '\n' | |
| 2891 '#include <wtf/Assertions.h>\n', | |
| 2892 'wtf includes should be "wtf/file.h" in
stead of <wtf/file.h>.' | |
| 2893 ' [build/include] [4]') | |
| 2894 self.assert_language_rules_check('foo.cpp', | |
| 2895 '#include "config.h"\n' | |
| 2896 '#include "foo.h"\n' | |
| 2897 '\n' | |
| 2898 '#include "wtf/Assertions.h"\n', | |
| 2899 '') | |
| 2900 | |
| 2901 def test_check_cc_includes(self): | |
| 2902 self.assert_language_rules_check('bar/chromium/foo.cpp', | |
| 2903 '#include "config.h"\n' | |
| 2904 '#include "foo.h"\n' | |
| 2905 '\n' | |
| 2906 '#include "cc/CCProxy.h"\n', | |
| 2907 'cc includes should be "CCFoo.h" instea
d of "cc/CCFoo.h".' | |
| 2908 ' [build/include] [4]') | |
| 2909 | |
| 2910 def test_classify_include(self): | |
| 2911 classify_include = cpp_style._classify_include | |
| 2912 include_state = cpp_style._IncludeState() | |
| 2913 self.assertEqual(cpp_style._CONFIG_HEADER, | |
| 2914 classify_include('foo/foo.cpp', | |
| 2915 'config.h', | |
| 2916 False, include_state)) | |
| 2917 self.assertEqual(cpp_style._PRIMARY_HEADER, | |
| 2918 classify_include('foo/internal/foo.cpp', | |
| 2919 'foo/public/foo.h', | |
| 2920 False, include_state)) | |
| 2921 self.assertEqual(cpp_style._PRIMARY_HEADER, | |
| 2922 classify_include('foo/internal/foo.cpp', | |
| 2923 'foo/other/public/foo.h', | |
| 2924 False, include_state)) | |
| 2925 self.assertEqual(cpp_style._OTHER_HEADER, | |
| 2926 classify_include('foo/internal/foo.cpp', | |
| 2927 'foo/other/public/foop.h', | |
| 2928 False, include_state)) | |
| 2929 self.assertEqual(cpp_style._OTHER_HEADER, | |
| 2930 classify_include('foo/foo.cpp', | |
| 2931 'string', | |
| 2932 True, include_state)) | |
| 2933 self.assertEqual(cpp_style._PRIMARY_HEADER, | |
| 2934 classify_include('fooCustom.cpp', | |
| 2935 'foo.h', | |
| 2936 False, include_state)) | |
| 2937 self.assertEqual(cpp_style._PRIMARY_HEADER, | |
| 2938 classify_include('PrefixFooCustom.cpp', | |
| 2939 'Foo.h', | |
| 2940 False, include_state)) | |
| 2941 self.assertEqual(cpp_style._MOC_HEADER, | |
| 2942 classify_include('foo.cpp', | |
| 2943 'foo.moc', | |
| 2944 False, include_state)) | |
| 2945 self.assertEqual(cpp_style._MOC_HEADER, | |
| 2946 classify_include('foo.cpp', | |
| 2947 'moc_foo.cpp', | |
| 2948 False, include_state)) | |
| 2949 # <public/foo.h> must be considered as primary even if is_system is True
. | |
| 2950 self.assertEqual(cpp_style._PRIMARY_HEADER, | |
| 2951 classify_include('foo/foo.cpp', | |
| 2952 'public/foo.h', | |
| 2953 True, include_state)) | |
| 2954 self.assertEqual(cpp_style._OTHER_HEADER, | |
| 2955 classify_include('foo.cpp', | |
| 2956 'foo.h', | |
| 2957 True, include_state)) | |
| 2958 self.assertEqual(cpp_style._OTHER_HEADER, | |
| 2959 classify_include('foo.cpp', | |
| 2960 'public/foop.h', | |
| 2961 True, include_state)) | |
| 2962 # Qt private APIs use _p.h suffix. | |
| 2963 self.assertEqual(cpp_style._PRIMARY_HEADER, | |
| 2964 classify_include('foo.cpp', | |
| 2965 'foo_p.h', | |
| 2966 False, include_state)) | |
| 2967 # Tricky example where both includes might be classified as primary. | |
| 2968 self.assert_language_rules_check('ScrollbarThemeWince.cpp', | |
| 2969 '#include "config.h"\n' | |
| 2970 '#include "ScrollbarThemeWince.h"\n' | |
| 2971 '\n' | |
| 2972 '#include "Scrollbar.h"\n', | |
| 2973 '') | |
| 2974 self.assert_language_rules_check('ScrollbarThemeWince.cpp', | |
| 2975 '#include "config.h"\n' | |
| 2976 '#include "Scrollbar.h"\n' | |
| 2977 '\n' | |
| 2978 '#include "ScrollbarThemeWince.h"\n', | |
| 2979 'Found header this file implements afte
r a header this file implements.' | |
| 2980 ' Should be: config.h, primary header,
blank line, and then alphabetically sorted.' | |
| 2981 ' [build/include_order] [4]') | |
| 2982 self.assert_language_rules_check('ResourceHandleWin.cpp', | |
| 2983 '#include "config.h"\n' | |
| 2984 '#include "ResourceHandle.h"\n' | |
| 2985 '\n' | |
| 2986 '#include "ResourceHandleWin.h"\n', | |
| 2987 '') | |
| 2988 | |
| 2989 def test_try_drop_common_suffixes(self): | |
| 2990 self.assertEqual('foo/foo', cpp_style._drop_common_suffixes('foo/foo-inl
.h')) | |
| 2991 self.assertEqual('foo/bar/foo', | |
| 2992 cpp_style._drop_common_suffixes('foo/bar/foo_inl.h')) | |
| 2993 self.assertEqual('foo/foo', cpp_style._drop_common_suffixes('foo/foo.cpp
')) | |
| 2994 self.assertEqual('foo/foo_unusualinternal', | |
| 2995 cpp_style._drop_common_suffixes('foo/foo_unusualinterna
l.h')) | |
| 2996 self.assertEqual('', | |
| 2997 cpp_style._drop_common_suffixes('_test.cpp')) | |
| 2998 self.assertEqual('test', | |
| 2999 cpp_style._drop_common_suffixes('test.cpp')) | |
| 3000 self.assertEqual('test', | |
| 3001 cpp_style._drop_common_suffixes('test.cpp')) | |
| 3002 | |
| 3003 class CheckForFunctionLengthsTest(CppStyleTestBase): | |
| 3004 def setUp(self): | |
| 3005 # Reducing these thresholds for the tests speeds up tests significantly. | |
| 3006 self.old_normal_trigger = cpp_style._FunctionState._NORMAL_TRIGGER | |
| 3007 self.old_test_trigger = cpp_style._FunctionState._TEST_TRIGGER | |
| 3008 | |
| 3009 cpp_style._FunctionState._NORMAL_TRIGGER = 10 | |
| 3010 cpp_style._FunctionState._TEST_TRIGGER = 25 | |
| 3011 | |
| 3012 def tearDown(self): | |
| 3013 cpp_style._FunctionState._NORMAL_TRIGGER = self.old_normal_trigger | |
| 3014 cpp_style._FunctionState._TEST_TRIGGER = self.old_test_trigger | |
| 3015 | |
| 3016 # FIXME: Eliminate the need for this function. | |
| 3017 def set_min_confidence(self, min_confidence): | |
| 3018 """Set new test confidence and return old test confidence.""" | |
| 3019 old_min_confidence = self.min_confidence | |
| 3020 self.min_confidence = min_confidence | |
| 3021 return old_min_confidence | |
| 3022 | |
| 3023 def assert_function_lengths_check(self, code, expected_message): | |
| 3024 """Check warnings for long function bodies are as expected. | |
| 3025 | |
| 3026 Args: | |
| 3027 code: C++ source code expected to generate a warning message. | |
| 3028 expected_message: Message expected to be generated by the C++ code. | |
| 3029 """ | |
| 3030 self.assertEqual(expected_message, | |
| 3031 self.perform_function_lengths_check(code)) | |
| 3032 | |
| 3033 def trigger_lines(self, error_level): | |
| 3034 """Return number of lines needed to trigger a function length warning. | |
| 3035 | |
| 3036 Args: | |
| 3037 error_level: --v setting for cpp_style. | |
| 3038 | |
| 3039 Returns: | |
| 3040 Number of lines needed to trigger a function length warning. | |
| 3041 """ | |
| 3042 return cpp_style._FunctionState._NORMAL_TRIGGER * 2 ** error_level | |
| 3043 | |
| 3044 def trigger_test_lines(self, error_level): | |
| 3045 """Return number of lines needed to trigger a test function length warni
ng. | |
| 3046 | |
| 3047 Args: | |
| 3048 error_level: --v setting for cpp_style. | |
| 3049 | |
| 3050 Returns: | |
| 3051 Number of lines needed to trigger a test function length warning. | |
| 3052 """ | |
| 3053 return cpp_style._FunctionState._TEST_TRIGGER * 2 ** error_level | |
| 3054 | |
| 3055 def assert_function_length_check_definition(self, lines, error_level): | |
| 3056 """Generate long function definition and check warnings are as expected. | |
| 3057 | |
| 3058 Args: | |
| 3059 lines: Number of lines to generate. | |
| 3060 error_level: --v setting for cpp_style. | |
| 3061 """ | |
| 3062 trigger_level = self.trigger_lines(self.min_confidence) | |
| 3063 self.assert_function_lengths_check( | |
| 3064 'void test(int x)' + self.function_body(lines), | |
| 3065 ('Small and focused functions are preferred: ' | |
| 3066 'test() has %d non-comment lines ' | |
| 3067 '(error triggered by exceeding %d lines).' | |
| 3068 ' [readability/fn_size] [%d]' | |
| 3069 % (lines, trigger_level, error_level))) | |
| 3070 | |
| 3071 def assert_function_length_check_definition_ok(self, lines): | |
| 3072 """Generate shorter function definition and check no warning is produced
. | |
| 3073 | |
| 3074 Args: | |
| 3075 lines: Number of lines to generate. | |
| 3076 """ | |
| 3077 self.assert_function_lengths_check( | |
| 3078 'void test(int x)' + self.function_body(lines), | |
| 3079 '') | |
| 3080 | |
| 3081 def assert_function_length_check_at_error_level(self, error_level): | |
| 3082 """Generate and check function at the trigger level for --v setting. | |
| 3083 | |
| 3084 Args: | |
| 3085 error_level: --v setting for cpp_style. | |
| 3086 """ | |
| 3087 self.assert_function_length_check_definition(self.trigger_lines(error_le
vel), | |
| 3088 error_level) | |
| 3089 | |
| 3090 def assert_function_length_check_below_error_level(self, error_level): | |
| 3091 """Generate and check function just below the trigger level for --v sett
ing. | |
| 3092 | |
| 3093 Args: | |
| 3094 error_level: --v setting for cpp_style. | |
| 3095 """ | |
| 3096 self.assert_function_length_check_definition(self.trigger_lines(error_le
vel) - 1, | |
| 3097 error_level - 1) | |
| 3098 | |
| 3099 def assert_function_length_check_above_error_level(self, error_level): | |
| 3100 """Generate and check function just above the trigger level for --v sett
ing. | |
| 3101 | |
| 3102 Args: | |
| 3103 error_level: --v setting for cpp_style. | |
| 3104 """ | |
| 3105 self.assert_function_length_check_definition(self.trigger_lines(error_le
vel) + 1, | |
| 3106 error_level) | |
| 3107 | |
| 3108 def function_body(self, number_of_lines): | |
| 3109 return ' {\n' + ' this_is_just_a_test();\n' * number_of_lines + '}' | |
| 3110 | |
| 3111 def function_body_with_blank_lines(self, number_of_lines): | |
| 3112 return ' {\n' + ' this_is_just_a_test();\n\n' * number_of_lines + '}' | |
| 3113 | |
| 3114 def function_body_with_no_lints(self, number_of_lines): | |
| 3115 return ' {\n' + ' this_is_just_a_test(); // NOLINT\n' * number_of_li
nes + '}' | |
| 3116 | |
| 3117 # Test line length checks. | |
| 3118 def test_function_length_check_declaration(self): | |
| 3119 self.assert_function_lengths_check( | |
| 3120 'void test();', # Not a function definition | |
| 3121 '') | |
| 3122 | |
| 3123 def test_function_length_check_declaration_with_block_following(self): | |
| 3124 self.assert_function_lengths_check( | |
| 3125 ('void test();\n' | |
| 3126 + self.function_body(66)), # Not a function definition | |
| 3127 '') | |
| 3128 | |
| 3129 def test_function_length_check_class_definition(self): | |
| 3130 self.assert_function_lengths_check( # Not a function definition | |
| 3131 'class Test' + self.function_body(66) + ';', | |
| 3132 '') | |
| 3133 | |
| 3134 def test_function_length_check_trivial(self): | |
| 3135 self.assert_function_lengths_check( | |
| 3136 'void test() {}', # Not counted | |
| 3137 '') | |
| 3138 | |
| 3139 def test_function_length_check_empty(self): | |
| 3140 self.assert_function_lengths_check( | |
| 3141 'void test() {\n}', | |
| 3142 '') | |
| 3143 | |
| 3144 def test_function_length_check_definition_below_severity0(self): | |
| 3145 old_min_confidence = self.set_min_confidence(0) | |
| 3146 self.assert_function_length_check_definition_ok(self.trigger_lines(0) -
1) | |
| 3147 self.set_min_confidence(old_min_confidence) | |
| 3148 | |
| 3149 def test_function_length_check_definition_at_severity0(self): | |
| 3150 old_min_confidence = self.set_min_confidence(0) | |
| 3151 self.assert_function_length_check_definition_ok(self.trigger_lines(0)) | |
| 3152 self.set_min_confidence(old_min_confidence) | |
| 3153 | |
| 3154 def test_function_length_check_definition_above_severity0(self): | |
| 3155 old_min_confidence = self.set_min_confidence(0) | |
| 3156 self.assert_function_length_check_above_error_level(0) | |
| 3157 self.set_min_confidence(old_min_confidence) | |
| 3158 | |
| 3159 def test_function_length_check_definition_below_severity1v0(self): | |
| 3160 old_min_confidence = self.set_min_confidence(0) | |
| 3161 self.assert_function_length_check_below_error_level(1) | |
| 3162 self.set_min_confidence(old_min_confidence) | |
| 3163 | |
| 3164 def test_function_length_check_definition_at_severity1v0(self): | |
| 3165 old_min_confidence = self.set_min_confidence(0) | |
| 3166 self.assert_function_length_check_at_error_level(1) | |
| 3167 self.set_min_confidence(old_min_confidence) | |
| 3168 | |
| 3169 def test_function_length_check_definition_below_severity1(self): | |
| 3170 self.assert_function_length_check_definition_ok(self.trigger_lines(1) -
1) | |
| 3171 | |
| 3172 def test_function_length_check_definition_at_severity1(self): | |
| 3173 self.assert_function_length_check_definition_ok(self.trigger_lines(1)) | |
| 3174 | |
| 3175 def test_function_length_check_definition_above_severity1(self): | |
| 3176 self.assert_function_length_check_above_error_level(1) | |
| 3177 | |
| 3178 def test_function_length_check_definition_severity1_plus_indented(self): | |
| 3179 error_level = 1 | |
| 3180 error_lines = self.trigger_lines(error_level) + 1 | |
| 3181 trigger_level = self.trigger_lines(self.min_confidence) | |
| 3182 indent_spaces = ' ' | |
| 3183 self.assert_function_lengths_check( | |
| 3184 re.sub(r'(?m)^(.)', indent_spaces + r'\1', | |
| 3185 'void test_indent(int x)\n' + self.function_body(error_lines)
), | |
| 3186 ('Small and focused functions are preferred: ' | |
| 3187 'test_indent() has %d non-comment lines ' | |
| 3188 '(error triggered by exceeding %d lines).' | |
| 3189 ' [readability/fn_size] [%d]') | |
| 3190 % (error_lines, trigger_level, error_level)) | |
| 3191 | |
| 3192 def test_function_length_check_definition_severity1_plus_blanks(self): | |
| 3193 error_level = 1 | |
| 3194 error_lines = self.trigger_lines(error_level) + 1 | |
| 3195 trigger_level = self.trigger_lines(self.min_confidence) | |
| 3196 self.assert_function_lengths_check( | |
| 3197 'void test_blanks(int x)' + self.function_body(error_lines), | |
| 3198 ('Small and focused functions are preferred: ' | |
| 3199 'test_blanks() has %d non-comment lines ' | |
| 3200 '(error triggered by exceeding %d lines).' | |
| 3201 ' [readability/fn_size] [%d]') | |
| 3202 % (error_lines, trigger_level, error_level)) | |
| 3203 | |
| 3204 def test_function_length_check_complex_definition_severity1(self): | |
| 3205 error_level = 1 | |
| 3206 error_lines = self.trigger_lines(error_level) + 1 | |
| 3207 trigger_level = self.trigger_lines(self.min_confidence) | |
| 3208 self.assert_function_lengths_check( | |
| 3209 ('my_namespace::my_other_namespace::MyVeryLongTypeName<Type1, bool f
unc(const Element*)>*\n' | |
| 3210 'my_namespace::my_other_namespace<Type3, Type4>::~MyFunction<Type5<
Type6, Type7> >(int arg1, char* arg2)' | |
| 3211 + self.function_body(error_lines)), | |
| 3212 ('Small and focused functions are preferred: ' | |
| 3213 'my_namespace::my_other_namespace<Type3, Type4>::~MyFunction<Type5<
Type6, Type7> >()' | |
| 3214 ' has %d non-comment lines ' | |
| 3215 '(error triggered by exceeding %d lines).' | |
| 3216 ' [readability/fn_size] [%d]') | |
| 3217 % (error_lines, trigger_level, error_level)) | |
| 3218 | |
| 3219 def test_function_length_check_definition_severity1_for_test(self): | |
| 3220 error_level = 1 | |
| 3221 error_lines = self.trigger_test_lines(error_level) + 1 | |
| 3222 trigger_level = self.trigger_test_lines(self.min_confidence) | |
| 3223 self.assert_function_lengths_check( | |
| 3224 'TEST_F(Test, Mutator)' + self.function_body(error_lines), | |
| 3225 ('Small and focused functions are preferred: ' | |
| 3226 'TEST_F(Test, Mutator) has %d non-comment lines ' | |
| 3227 '(error triggered by exceeding %d lines).' | |
| 3228 ' [readability/fn_size] [%d]') | |
| 3229 % (error_lines, trigger_level, error_level)) | |
| 3230 | |
| 3231 def test_function_length_check_definition_severity1_for_split_line_test(self
): | |
| 3232 error_level = 1 | |
| 3233 error_lines = self.trigger_test_lines(error_level) + 1 | |
| 3234 trigger_level = self.trigger_test_lines(self.min_confidence) | |
| 3235 self.assert_function_lengths_check( | |
| 3236 ('TEST_F(GoogleUpdateRecoveryRegistryProtectedTest,\n' | |
| 3237 ' FixGoogleUpdate_AllValues_MachineApp)' # note: 4 spaces | |
| 3238 + self.function_body(error_lines)), | |
| 3239 ('Small and focused functions are preferred: ' | |
| 3240 'TEST_F(GoogleUpdateRecoveryRegistryProtectedTest, ' # 1 space | |
| 3241 'FixGoogleUpdate_AllValues_MachineApp) has %d non-comment lines ' | |
| 3242 '(error triggered by exceeding %d lines).' | |
| 3243 ' [readability/fn_size] [%d]') | |
| 3244 % (error_lines, trigger_level, error_level)) | |
| 3245 | |
| 3246 def test_function_length_check_definition_severity1_for_bad_test_doesnt_brea
k(self): | |
| 3247 error_level = 1 | |
| 3248 error_lines = self.trigger_test_lines(error_level) + 1 | |
| 3249 trigger_level = self.trigger_test_lines(self.min_confidence) | |
| 3250 # Since the function name isn't valid, the function detection algorithm | |
| 3251 # will skip it, so no error is produced. | |
| 3252 self.assert_function_lengths_check( | |
| 3253 ('TEST_F(' | |
| 3254 + self.function_body(error_lines)), | |
| 3255 '') | |
| 3256 | |
| 3257 def test_function_length_check_definition_severity1_with_embedded_no_lints(s
elf): | |
| 3258 error_level = 1 | |
| 3259 error_lines = self.trigger_lines(error_level) + 1 | |
| 3260 trigger_level = self.trigger_lines(self.min_confidence) | |
| 3261 self.assert_function_lengths_check( | |
| 3262 'void test(int x)' + self.function_body_with_no_lints(error_lines), | |
| 3263 ('Small and focused functions are preferred: ' | |
| 3264 'test() has %d non-comment lines ' | |
| 3265 '(error triggered by exceeding %d lines).' | |
| 3266 ' [readability/fn_size] [%d]') | |
| 3267 % (error_lines, trigger_level, error_level)) | |
| 3268 | |
| 3269 def test_function_length_check_definition_severity1_with_no_lint(self): | |
| 3270 self.assert_function_lengths_check( | |
| 3271 ('void test(int x)' + self.function_body(self.trigger_lines(1)) | |
| 3272 + ' // NOLINT -- long function'), | |
| 3273 '') | |
| 3274 | |
| 3275 def test_function_length_check_definition_below_severity2(self): | |
| 3276 self.assert_function_length_check_below_error_level(2) | |
| 3277 | |
| 3278 def test_function_length_check_definition_severity2(self): | |
| 3279 self.assert_function_length_check_at_error_level(2) | |
| 3280 | |
| 3281 def test_function_length_check_definition_above_severity2(self): | |
| 3282 self.assert_function_length_check_above_error_level(2) | |
| 3283 | |
| 3284 def test_function_length_check_definition_below_severity3(self): | |
| 3285 self.assert_function_length_check_below_error_level(3) | |
| 3286 | |
| 3287 def test_function_length_check_definition_severity3(self): | |
| 3288 self.assert_function_length_check_at_error_level(3) | |
| 3289 | |
| 3290 def test_function_length_check_definition_above_severity3(self): | |
| 3291 self.assert_function_length_check_above_error_level(3) | |
| 3292 | |
| 3293 def test_function_length_check_definition_below_severity4(self): | |
| 3294 self.assert_function_length_check_below_error_level(4) | |
| 3295 | |
| 3296 def test_function_length_check_definition_severity4(self): | |
| 3297 self.assert_function_length_check_at_error_level(4) | |
| 3298 | |
| 3299 def test_function_length_check_definition_above_severity4(self): | |
| 3300 self.assert_function_length_check_above_error_level(4) | |
| 3301 | |
| 3302 def test_function_length_check_definition_below_severity5(self): | |
| 3303 self.assert_function_length_check_below_error_level(5) | |
| 3304 | |
| 3305 def test_function_length_check_definition_at_severity5(self): | |
| 3306 self.assert_function_length_check_at_error_level(5) | |
| 3307 | |
| 3308 def test_function_length_check_definition_above_severity5(self): | |
| 3309 self.assert_function_length_check_above_error_level(5) | |
| 3310 | |
| 3311 def test_function_length_check_definition_huge_lines(self): | |
| 3312 # 5 is the limit | |
| 3313 self.assert_function_length_check_definition(self.trigger_lines(6), 5) | |
| 3314 | |
| 3315 def test_function_length_not_determinable(self): | |
| 3316 # Macro invocation without terminating semicolon. | |
| 3317 self.assert_function_lengths_check( | |
| 3318 'MACRO(arg)', | |
| 3319 '') | |
| 3320 | |
| 3321 # Macro with underscores | |
| 3322 self.assert_function_lengths_check( | |
| 3323 'MACRO_WITH_UNDERSCORES(arg1, arg2, arg3)', | |
| 3324 '') | |
| 3325 | |
| 3326 self.assert_function_lengths_check( | |
| 3327 'NonMacro(arg)', | |
| 3328 'Lint failed to find start of function body.' | |
| 3329 ' [readability/fn_size] [5]') | |
| 3330 | |
| 3331 | |
| 3332 class NoNonVirtualDestructorsTest(CppStyleTestBase): | |
| 3333 | |
| 3334 def test_no_error(self): | |
| 3335 self.assert_multi_line_lint( | |
| 3336 '''\ | |
| 3337 class Foo { | |
| 3338 virtual ~Foo(); | |
| 3339 virtual void foo(); | |
| 3340 };''', | |
| 3341 '') | |
| 3342 | |
| 3343 self.assert_multi_line_lint( | |
| 3344 '''\ | |
| 3345 class Foo { | |
| 3346 virtual inline ~Foo(); | |
| 3347 virtual void foo(); | |
| 3348 };''', | |
| 3349 '') | |
| 3350 | |
| 3351 self.assert_multi_line_lint( | |
| 3352 '''\ | |
| 3353 class Foo { | |
| 3354 inline virtual ~Foo(); | |
| 3355 virtual void foo(); | |
| 3356 };''', | |
| 3357 '') | |
| 3358 | |
| 3359 self.assert_multi_line_lint( | |
| 3360 '''\ | |
| 3361 class Foo::Goo { | |
| 3362 virtual ~Goo(); | |
| 3363 virtual void goo(); | |
| 3364 };''', | |
| 3365 '') | |
| 3366 self.assert_multi_line_lint( | |
| 3367 'class Foo { void foo(); };', | |
| 3368 'More than one command on the same line [whitespace/newline] [4]') | |
| 3369 self.assert_multi_line_lint( | |
| 3370 'class MyClass {\n' | |
| 3371 ' int getIntValue() { ASSERT(m_ptr); return *m_ptr; }\n' | |
| 3372 '};\n', | |
| 3373 '') | |
| 3374 self.assert_multi_line_lint( | |
| 3375 'class MyClass {\n' | |
| 3376 ' int getIntValue()\n' | |
| 3377 ' {\n' | |
| 3378 ' ASSERT(m_ptr); return *m_ptr;\n' | |
| 3379 ' }\n' | |
| 3380 '};\n', | |
| 3381 'More than one command on the same line [whitespace/newline] [4]') | |
| 3382 | |
| 3383 self.assert_multi_line_lint( | |
| 3384 '''\ | |
| 3385 class Qualified::Goo : public Foo { | |
| 3386 virtual void goo(); | |
| 3387 };''', | |
| 3388 '') | |
| 3389 | |
| 3390 def test_no_destructor_when_virtual_needed(self): | |
| 3391 self.assert_multi_line_lint_re( | |
| 3392 '''\ | |
| 3393 class Foo { | |
| 3394 virtual void foo(); | |
| 3395 };''', | |
| 3396 'The class Foo probably needs a virtual destructor') | |
| 3397 | |
| 3398 def test_enum_casing(self): | |
| 3399 self.assert_multi_line_lint( | |
| 3400 '''\ | |
| 3401 enum Foo { | |
| 3402 FOO_ONE = 1, | |
| 3403 FOO_TWO | |
| 3404 }; | |
| 3405 enum { FOO_ONE }; | |
| 3406 enum {FooOne, fooTwo}; | |
| 3407 enum { | |
| 3408 FOO_ONE | |
| 3409 };''', | |
| 3410 ['enum members should use InterCaps with an initial capital letter.
[readability/enum_casing] [4]'] * 5) | |
| 3411 | |
| 3412 self.assert_multi_line_lint( | |
| 3413 '''\ | |
| 3414 enum Foo { | |
| 3415 fooOne = 1, | |
| 3416 FooTwo = 2 | |
| 3417 };''', | |
| 3418 'enum members should use InterCaps with an initial capital letter.
[readability/enum_casing] [4]') | |
| 3419 | |
| 3420 self.assert_multi_line_lint( | |
| 3421 '''\ | |
| 3422 enum Foo { | |
| 3423 FooOne = 1, | |
| 3424 FooTwo | |
| 3425 } fooVar = FooOne; | |
| 3426 enum { FooOne, FooTwo }; | |
| 3427 enum { FooOne, FooTwo } fooVar = FooTwo; | |
| 3428 enum { FooOne= FooTwo } foo; | |
| 3429 enum Enum123 { | |
| 3430 FooOne, | |
| 3431 FooTwo = FooOne, | |
| 3432 };''', | |
| 3433 '') | |
| 3434 | |
| 3435 self.assert_multi_line_lint( | |
| 3436 '''\ | |
| 3437 // WebIDL enum | |
| 3438 enum Foo { | |
| 3439 FOO_ONE = 1, | |
| 3440 FOO_TWO = 2, | |
| 3441 };''', | |
| 3442 '') | |
| 3443 | |
| 3444 self.assert_multi_line_lint( | |
| 3445 '''\ | |
| 3446 // WebKitIDL enum | |
| 3447 enum Foo { FOO_ONE, FOO_TWO };''', | |
| 3448 '') | |
| 3449 | |
| 3450 def test_destructor_non_virtual_when_virtual_needed(self): | |
| 3451 self.assert_multi_line_lint_re( | |
| 3452 '''\ | |
| 3453 class Foo { | |
| 3454 ~Foo(); | |
| 3455 virtual void foo(); | |
| 3456 };''', | |
| 3457 'The class Foo probably needs a virtual destructor') | |
| 3458 | |
| 3459 def test_no_warn_when_derived(self): | |
| 3460 self.assert_multi_line_lint( | |
| 3461 '''\ | |
| 3462 class Foo : public Goo { | |
| 3463 virtual void foo(); | |
| 3464 };''', | |
| 3465 '') | |
| 3466 | |
| 3467 def test_internal_braces(self): | |
| 3468 self.assert_multi_line_lint_re( | |
| 3469 '''\ | |
| 3470 class Foo { | |
| 3471 enum Goo { | |
| 3472 Goo | |
| 3473 }; | |
| 3474 virtual void foo(); | |
| 3475 };''', | |
| 3476 'The class Foo probably needs a virtual destructor') | |
| 3477 | |
| 3478 def test_inner_class_needs_virtual_destructor(self): | |
| 3479 self.assert_multi_line_lint_re( | |
| 3480 '''\ | |
| 3481 class Foo { | |
| 3482 class Goo { | |
| 3483 virtual void goo(); | |
| 3484 }; | |
| 3485 };''', | |
| 3486 'The class Goo probably needs a virtual destructor') | |
| 3487 | |
| 3488 def test_outer_class_needs_virtual_destructor(self): | |
| 3489 self.assert_multi_line_lint_re( | |
| 3490 '''\ | |
| 3491 class Foo { | |
| 3492 class Goo { | |
| 3493 }; | |
| 3494 virtual void foo(); | |
| 3495 };''', | |
| 3496 'The class Foo probably needs a virtual destructor') | |
| 3497 | |
| 3498 def test_qualified_class_needs_virtual_destructor(self): | |
| 3499 self.assert_multi_line_lint_re( | |
| 3500 '''\ | |
| 3501 class Qualified::Foo { | |
| 3502 virtual void foo(); | |
| 3503 };''', | |
| 3504 'The class Qualified::Foo probably needs a virtual destructor') | |
| 3505 | |
| 3506 def test_multi_line_declaration_no_error(self): | |
| 3507 self.assert_multi_line_lint_re( | |
| 3508 '''\ | |
| 3509 class Foo | |
| 3510 : public Goo { | |
| 3511 virtual void foo(); | |
| 3512 };''', | |
| 3513 '') | |
| 3514 | |
| 3515 def test_multi_line_declaration_with_error(self): | |
| 3516 self.assert_multi_line_lint( | |
| 3517 '''\ | |
| 3518 class Foo | |
| 3519 { | |
| 3520 virtual void foo(); | |
| 3521 };''', | |
| 3522 ['This { should be at the end of the previous line ' | |
| 3523 '[whitespace/braces] [4]', | |
| 3524 'The class Foo probably needs a virtual destructor due to having ' | |
| 3525 'virtual method(s), one declared at line 3. [runtime/virtual] [4]'
]) | |
| 3526 | |
| 3527 | |
| 3528 class PassPtrTest(CppStyleTestBase): | |
| 3529 # For http://webkit.org/coding/RefPtr.html | |
| 3530 | |
| 3531 def assert_pass_ptr_check(self, code, expected_message): | |
| 3532 """Check warnings for Pass*Ptr are as expected. | |
| 3533 | |
| 3534 Args: | |
| 3535 code: C++ source code expected to generate a warning message. | |
| 3536 expected_message: Message expected to be generated by the C++ code. | |
| 3537 """ | |
| 3538 self.assertEqual(expected_message, | |
| 3539 self.perform_pass_ptr_check(code)) | |
| 3540 | |
| 3541 def test_pass_ref_ptr_in_function(self): | |
| 3542 self.assert_pass_ptr_check( | |
| 3543 'int myFunction()\n' | |
| 3544 '{\n' | |
| 3545 ' PassRefPtr<Type1> variable = variable2;\n' | |
| 3546 '}', | |
| 3547 'Local variables should never be PassRefPtr (see ' | |
| 3548 'http://webkit.org/coding/RefPtr.html). [readability/pass_ptr] [5]'
) | |
| 3549 | |
| 3550 def test_pass_own_ptr_in_function(self): | |
| 3551 self.assert_pass_ptr_check( | |
| 3552 'int myFunction()\n' | |
| 3553 '{\n' | |
| 3554 ' PassOwnPtr<Type1> variable = variable2;\n' | |
| 3555 '}', | |
| 3556 'Local variables should never be PassOwnPtr (see ' | |
| 3557 'http://webkit.org/coding/RefPtr.html). [readability/pass_ptr] [5]'
) | |
| 3558 | |
| 3559 def test_pass_other_type_ptr_in_function(self): | |
| 3560 self.assert_pass_ptr_check( | |
| 3561 'int myFunction()\n' | |
| 3562 '{\n' | |
| 3563 ' PassOtherTypePtr<Type1> variable;\n' | |
| 3564 '}', | |
| 3565 'Local variables should never be PassOtherTypePtr (see ' | |
| 3566 'http://webkit.org/coding/RefPtr.html). [readability/pass_ptr] [5]'
) | |
| 3567 | |
| 3568 def test_pass_ref_ptr_return_value(self): | |
| 3569 self.assert_pass_ptr_check( | |
| 3570 'PassRefPtr<Type1>\n' | |
| 3571 'myFunction(int)\n' | |
| 3572 '{\n' | |
| 3573 '}', | |
| 3574 '') | |
| 3575 self.assert_pass_ptr_check( | |
| 3576 'PassRefPtr<Type1> myFunction(int)\n' | |
| 3577 '{\n' | |
| 3578 '}', | |
| 3579 '') | |
| 3580 self.assert_pass_ptr_check( | |
| 3581 'PassRefPtr<Type1> myFunction();\n', | |
| 3582 '') | |
| 3583 self.assert_pass_ptr_check( | |
| 3584 'OwnRefPtr<Type1> myFunction();\n', | |
| 3585 '') | |
| 3586 self.assert_pass_ptr_check( | |
| 3587 'RefPtr<Type1> myFunction(int)\n' | |
| 3588 '{\n' | |
| 3589 '}', | |
| 3590 'The return type should use PassRefPtr instead of RefPtr. [readabil
ity/pass_ptr] [5]') | |
| 3591 self.assert_pass_ptr_check( | |
| 3592 'OwnPtr<Type1> myFunction(int)\n' | |
| 3593 '{\n' | |
| 3594 '}', | |
| 3595 'The return type should use PassOwnPtr instead of OwnPtr. [readabil
ity/pass_ptr] [5]') | |
| 3596 | |
| 3597 def test_ref_ptr_parameter_value(self): | |
| 3598 self.assert_pass_ptr_check( | |
| 3599 'int myFunction(PassRefPtr<Type1>)\n' | |
| 3600 '{\n' | |
| 3601 '}', | |
| 3602 '') | |
| 3603 self.assert_pass_ptr_check( | |
| 3604 'int myFunction(RefPtr<Type1>)\n' | |
| 3605 '{\n' | |
| 3606 '}', | |
| 3607 'The parameter type should use PassRefPtr instead of RefPtr. [reada
bility/pass_ptr] [5]') | |
| 3608 self.assert_pass_ptr_check( | |
| 3609 'int myFunction(RefPtr<Type1>&)\n' | |
| 3610 '{\n' | |
| 3611 '}', | |
| 3612 '') | |
| 3613 self.assert_pass_ptr_check( | |
| 3614 'int myFunction(RefPtr<Type1>*)\n' | |
| 3615 '{\n' | |
| 3616 '}', | |
| 3617 '') | |
| 3618 self.assert_pass_ptr_check( | |
| 3619 'int myFunction(RefPtr<Type1>* = 0)\n' | |
| 3620 '{\n' | |
| 3621 '}', | |
| 3622 '') | |
| 3623 self.assert_pass_ptr_check( | |
| 3624 'int myFunction(RefPtr<Type1>* = 0)\n' | |
| 3625 '{\n' | |
| 3626 '}', | |
| 3627 '') | |
| 3628 | |
| 3629 def test_own_ptr_parameter_value(self): | |
| 3630 self.assert_pass_ptr_check( | |
| 3631 'int myFunction(PassOwnPtr<Type1>)\n' | |
| 3632 '{\n' | |
| 3633 '}', | |
| 3634 '') | |
| 3635 self.assert_pass_ptr_check( | |
| 3636 'int myFunction(OwnPtr<Type1>)\n' | |
| 3637 '{\n' | |
| 3638 '}', | |
| 3639 'The parameter type should use PassOwnPtr instead of OwnPtr. [reada
bility/pass_ptr] [5]') | |
| 3640 self.assert_pass_ptr_check( | |
| 3641 'int myFunction(OwnPtr<Type1>& simple)\n' | |
| 3642 '{\n' | |
| 3643 '}', | |
| 3644 '') | |
| 3645 | |
| 3646 def test_ref_ptr_member_variable(self): | |
| 3647 self.assert_pass_ptr_check( | |
| 3648 'class Foo {' | |
| 3649 ' RefPtr<Type1> m_other;\n' | |
| 3650 '};\n', | |
| 3651 '') | |
| 3652 | |
| 3653 | |
| 3654 class LeakyPatternTest(CppStyleTestBase): | |
| 3655 | |
| 3656 def assert_leaky_pattern_check(self, code, expected_message): | |
| 3657 """Check warnings for leaky patterns are as expected. | |
| 3658 | |
| 3659 Args: | |
| 3660 code: C++ source code expected to generate a warning message. | |
| 3661 expected_message: Message expected to be generated by the C++ code. | |
| 3662 """ | |
| 3663 self.assertEqual(expected_message, | |
| 3664 self.perform_leaky_pattern_check(code)) | |
| 3665 | |
| 3666 def test_get_dc(self): | |
| 3667 self.assert_leaky_pattern_check( | |
| 3668 'HDC hdc = GetDC(hwnd);', | |
| 3669 'Use the class HWndDC instead of calling GetDC to avoid potential ' | |
| 3670 'memory leaks. [runtime/leaky_pattern] [5]') | |
| 3671 | |
| 3672 def test_get_dc(self): | |
| 3673 self.assert_leaky_pattern_check( | |
| 3674 'HDC hdc = GetDCEx(hwnd, 0, 0);', | |
| 3675 'Use the class HWndDC instead of calling GetDCEx to avoid potential
' | |
| 3676 'memory leaks. [runtime/leaky_pattern] [5]') | |
| 3677 | |
| 3678 def test_own_get_dc(self): | |
| 3679 self.assert_leaky_pattern_check( | |
| 3680 'HWndDC hdc(hwnd);', | |
| 3681 '') | |
| 3682 | |
| 3683 def test_create_dc(self): | |
| 3684 self.assert_leaky_pattern_check( | |
| 3685 'HDC dc2 = ::CreateDC();', | |
| 3686 'Use adoptPtr and OwnPtr<HDC> when calling CreateDC to avoid potenti
al ' | |
| 3687 'memory leaks. [runtime/leaky_pattern] [5]') | |
| 3688 | |
| 3689 self.assert_leaky_pattern_check( | |
| 3690 'adoptPtr(CreateDC());', | |
| 3691 '') | |
| 3692 | |
| 3693 def test_create_compatible_dc(self): | |
| 3694 self.assert_leaky_pattern_check( | |
| 3695 'HDC dc2 = CreateCompatibleDC(dc);', | |
| 3696 'Use adoptPtr and OwnPtr<HDC> when calling CreateCompatibleDC to avo
id potential ' | |
| 3697 'memory leaks. [runtime/leaky_pattern] [5]') | |
| 3698 self.assert_leaky_pattern_check( | |
| 3699 'adoptPtr(CreateCompatibleDC(dc));', | |
| 3700 '') | |
| 3701 | |
| 3702 | |
| 3703 class WebKitStyleTest(CppStyleTestBase): | |
| 3704 | |
| 3705 # for http://webkit.org/coding/coding-style.html | |
| 3706 def test_indentation(self): | |
| 3707 # 1. Use spaces, not tabs. Tabs should only appear in files that | |
| 3708 # require them for semantic meaning, like Makefiles. | |
| 3709 self.assert_multi_line_lint( | |
| 3710 'class Foo {\n' | |
| 3711 ' int goo;\n' | |
| 3712 '};', | |
| 3713 '') | |
| 3714 self.assert_multi_line_lint( | |
| 3715 'class Foo {\n' | |
| 3716 '\tint goo;\n' | |
| 3717 '};', | |
| 3718 'Tab found; better to use spaces [whitespace/tab] [1]') | |
| 3719 | |
| 3720 # 2. The indent size is 4 spaces. | |
| 3721 self.assert_multi_line_lint( | |
| 3722 'class Foo {\n' | |
| 3723 ' int goo;\n' | |
| 3724 '};', | |
| 3725 '') | |
| 3726 self.assert_multi_line_lint( | |
| 3727 'class Foo {\n' | |
| 3728 ' int goo;\n' | |
| 3729 '};', | |
| 3730 'Weird number of spaces at line-start. Are you using a 4-space inde
nt? [whitespace/indent] [3]') | |
| 3731 | |
| 3732 # 3. In a header, code inside a namespace should not be indented. | |
| 3733 self.assert_multi_line_lint( | |
| 3734 'namespace WebCore {\n\n' | |
| 3735 'class Document {\n' | |
| 3736 ' int myVariable;\n' | |
| 3737 '};\n' | |
| 3738 '}', | |
| 3739 '', | |
| 3740 'foo.h') | |
| 3741 self.assert_multi_line_lint( | |
| 3742 'namespace OuterNamespace {\n' | |
| 3743 ' namespace InnerNamespace {\n' | |
| 3744 ' class Document {\n' | |
| 3745 '};\n' | |
| 3746 '};\n' | |
| 3747 '}', | |
| 3748 'Code inside a namespace should not be indented. [whitespace/indent
] [4]', | |
| 3749 'foo.h') | |
| 3750 self.assert_multi_line_lint( | |
| 3751 'namespace OuterNamespace {\n' | |
| 3752 ' class Document {\n' | |
| 3753 ' namespace InnerNamespace {\n' | |
| 3754 '};\n' | |
| 3755 '};\n' | |
| 3756 '}', | |
| 3757 'Code inside a namespace should not be indented. [whitespace/indent
] [4]', | |
| 3758 'foo.h') | |
| 3759 self.assert_multi_line_lint( | |
| 3760 'namespace WebCore {\n' | |
| 3761 '#if 0\n' | |
| 3762 ' class Document {\n' | |
| 3763 '};\n' | |
| 3764 '#endif\n' | |
| 3765 '}', | |
| 3766 'Code inside a namespace should not be indented. [whitespace/indent
] [4]', | |
| 3767 'foo.h') | |
| 3768 self.assert_multi_line_lint( | |
| 3769 'namespace WebCore {\n' | |
| 3770 'class Document {\n' | |
| 3771 '};\n' | |
| 3772 '}', | |
| 3773 '', | |
| 3774 'foo.h') | |
| 3775 | |
| 3776 # 4. In an implementation file (files with the extension .cpp, .c | |
| 3777 # or .mm), code inside a namespace should not be indented. | |
| 3778 self.assert_multi_line_lint( | |
| 3779 'namespace WebCore {\n\n' | |
| 3780 'Document::Foo()\n' | |
| 3781 ' : foo(bar)\n' | |
| 3782 ' , boo(far)\n' | |
| 3783 '{\n' | |
| 3784 ' stuff();\n' | |
| 3785 '}', | |
| 3786 '', | |
| 3787 'foo.cpp') | |
| 3788 self.assert_multi_line_lint( | |
| 3789 'namespace OuterNamespace {\n' | |
| 3790 'namespace InnerNamespace {\n' | |
| 3791 'Document::Foo() { }\n' | |
| 3792 ' void* p;\n' | |
| 3793 '}\n' | |
| 3794 '}\n', | |
| 3795 'Code inside a namespace should not be indented. [whitespace/indent
] [4]', | |
| 3796 'foo.cpp') | |
| 3797 self.assert_multi_line_lint( | |
| 3798 'namespace OuterNamespace {\n' | |
| 3799 'namespace InnerNamespace {\n' | |
| 3800 'Document::Foo() { }\n' | |
| 3801 '}\n' | |
| 3802 ' void* p;\n' | |
| 3803 '}\n', | |
| 3804 'Code inside a namespace should not be indented. [whitespace/indent
] [4]', | |
| 3805 'foo.cpp') | |
| 3806 self.assert_multi_line_lint( | |
| 3807 'namespace WebCore {\n\n' | |
| 3808 ' const char* foo = "start:;"\n' | |
| 3809 ' "dfsfsfs";\n' | |
| 3810 '}\n', | |
| 3811 'Code inside a namespace should not be indented. [whitespace/indent
] [4]', | |
| 3812 'foo.cpp') | |
| 3813 self.assert_multi_line_lint( | |
| 3814 'namespace WebCore {\n\n' | |
| 3815 'const char* foo(void* a = ";", // ;\n' | |
| 3816 ' void* b);\n' | |
| 3817 ' void* p;\n' | |
| 3818 '}\n', | |
| 3819 'Code inside a namespace should not be indented. [whitespace/indent
] [4]', | |
| 3820 'foo.cpp') | |
| 3821 self.assert_multi_line_lint( | |
| 3822 'namespace WebCore {\n\n' | |
| 3823 'const char* foo[] = {\n' | |
| 3824 ' "void* b);", // ;\n' | |
| 3825 ' "asfdf",\n' | |
| 3826 ' }\n' | |
| 3827 ' void* p;\n' | |
| 3828 '}\n', | |
| 3829 'Code inside a namespace should not be indented. [whitespace/indent
] [4]', | |
| 3830 'foo.cpp') | |
| 3831 self.assert_multi_line_lint( | |
| 3832 'namespace WebCore {\n\n' | |
| 3833 'const char* foo[] = {\n' | |
| 3834 ' "void* b);", // }\n' | |
| 3835 ' "asfdf",\n' | |
| 3836 ' }\n' | |
| 3837 '}\n', | |
| 3838 '', | |
| 3839 'foo.cpp') | |
| 3840 self.assert_multi_line_lint( | |
| 3841 ' namespace WebCore {\n\n' | |
| 3842 ' void Document::Foo()\n' | |
| 3843 ' {\n' | |
| 3844 'start: // infinite loops are fun!\n' | |
| 3845 ' goto start;\n' | |
| 3846 ' }', | |
| 3847 'namespace should never be indented. [whitespace/indent] [4]', | |
| 3848 'foo.cpp') | |
| 3849 self.assert_multi_line_lint( | |
| 3850 'namespace WebCore {\n' | |
| 3851 ' Document::Foo() { }\n' | |
| 3852 '}', | |
| 3853 'Code inside a namespace should not be indented.' | |
| 3854 ' [whitespace/indent] [4]', | |
| 3855 'foo.cpp') | |
| 3856 self.assert_multi_line_lint( | |
| 3857 'namespace WebCore {\n' | |
| 3858 '#define abc(x) x; \\\n' | |
| 3859 ' x\n' | |
| 3860 '}', | |
| 3861 '', | |
| 3862 'foo.cpp') | |
| 3863 self.assert_multi_line_lint( | |
| 3864 'namespace WebCore {\n' | |
| 3865 '#define abc(x) x; \\\n' | |
| 3866 ' x\n' | |
| 3867 ' void* x;' | |
| 3868 '}', | |
| 3869 'Code inside a namespace should not be indented. [whitespace/indent
] [4]', | |
| 3870 'foo.cpp') | |
| 3871 | |
| 3872 # 5. A case label should line up with its switch statement. The | |
| 3873 # case statement is indented. | |
| 3874 self.assert_multi_line_lint( | |
| 3875 ' switch (condition) {\n' | |
| 3876 ' case fooCondition:\n' | |
| 3877 ' case barCondition:\n' | |
| 3878 ' i++;\n' | |
| 3879 ' break;\n' | |
| 3880 ' default:\n' | |
| 3881 ' i--;\n' | |
| 3882 ' }\n', | |
| 3883 '') | |
| 3884 self.assert_multi_line_lint( | |
| 3885 ' switch (condition) {\n' | |
| 3886 ' case fooCondition:\n' | |
| 3887 ' switch (otherCondition) {\n' | |
| 3888 ' default:\n' | |
| 3889 ' return;\n' | |
| 3890 ' }\n' | |
| 3891 ' default:\n' | |
| 3892 ' i--;\n' | |
| 3893 ' }\n', | |
| 3894 '') | |
| 3895 self.assert_multi_line_lint( | |
| 3896 ' switch (condition) {\n' | |
| 3897 ' case fooCondition: break;\n' | |
| 3898 ' default: return;\n' | |
| 3899 ' }\n', | |
| 3900 '') | |
| 3901 self.assert_multi_line_lint( | |
| 3902 ' switch (condition) {\n' | |
| 3903 ' case fooCondition:\n' | |
| 3904 ' case barCondition:\n' | |
| 3905 ' i++;\n' | |
| 3906 ' break;\n' | |
| 3907 ' default:\n' | |
| 3908 ' i--;\n' | |
| 3909 ' }\n', | |
| 3910 'A case label should not be indented, but line up with its switch st
atement.' | |
| 3911 ' [whitespace/indent] [4]') | |
| 3912 self.assert_multi_line_lint( | |
| 3913 ' switch (condition) {\n' | |
| 3914 ' case fooCondition:\n' | |
| 3915 ' break;\n' | |
| 3916 ' default:\n' | |
| 3917 ' i--;\n' | |
| 3918 ' }\n', | |
| 3919 'A case label should not be indented, but line up with its switch st
atement.' | |
| 3920 ' [whitespace/indent] [4]') | |
| 3921 self.assert_multi_line_lint( | |
| 3922 ' switch (condition) {\n' | |
| 3923 ' case fooCondition:\n' | |
| 3924 ' case barCondition:\n' | |
| 3925 ' switch (otherCondition) {\n' | |
| 3926 ' default:\n' | |
| 3927 ' return;\n' | |
| 3928 ' }\n' | |
| 3929 ' default:\n' | |
| 3930 ' i--;\n' | |
| 3931 ' }\n', | |
| 3932 'A case label should not be indented, but line up with its switch st
atement.' | |
| 3933 ' [whitespace/indent] [4]') | |
| 3934 self.assert_multi_line_lint( | |
| 3935 ' switch (condition) {\n' | |
| 3936 ' case fooCondition:\n' | |
| 3937 ' case barCondition:\n' | |
| 3938 ' i++;\n' | |
| 3939 ' break;\n\n' | |
| 3940 ' default:\n' | |
| 3941 ' i--;\n' | |
| 3942 ' }\n', | |
| 3943 'Non-label code inside switch statements should be indented.' | |
| 3944 ' [whitespace/indent] [4]') | |
| 3945 self.assert_multi_line_lint( | |
| 3946 ' switch (condition) {\n' | |
| 3947 ' case fooCondition:\n' | |
| 3948 ' case barCondition:\n' | |
| 3949 ' switch (otherCondition) {\n' | |
| 3950 ' default:\n' | |
| 3951 ' return;\n' | |
| 3952 ' }\n' | |
| 3953 ' default:\n' | |
| 3954 ' i--;\n' | |
| 3955 ' }\n', | |
| 3956 'Non-label code inside switch statements should be indented.' | |
| 3957 ' [whitespace/indent] [4]') | |
| 3958 | |
| 3959 # 6. Boolean expressions at the same nesting level that span | |
| 3960 # multiple lines should have their operators on the left side of | |
| 3961 # the line instead of the right side. | |
| 3962 self.assert_multi_line_lint( | |
| 3963 ' return attr->name() == srcAttr\n' | |
| 3964 ' || attr->name() == lowsrcAttr;\n', | |
| 3965 '') | |
| 3966 self.assert_multi_line_lint( | |
| 3967 ' return attr->name() == srcAttr ||\n' | |
| 3968 ' attr->name() == lowsrcAttr;\n', | |
| 3969 'Boolean expressions that span multiple lines should have their ' | |
| 3970 'operators on the left side of the line instead of the right side.' | |
| 3971 ' [whitespace/operators] [4]') | |
| 3972 | |
| 3973 def test_spacing(self): | |
| 3974 # 1. Do not place spaces around unary operators. | |
| 3975 self.assert_multi_line_lint( | |
| 3976 'i++;', | |
| 3977 '') | |
| 3978 self.assert_multi_line_lint( | |
| 3979 'i ++;', | |
| 3980 'Extra space for operator ++; [whitespace/operators] [4]') | |
| 3981 | |
| 3982 # 2. Do place spaces around binary and ternary operators. | |
| 3983 self.assert_multi_line_lint( | |
| 3984 'y = m * x + b;', | |
| 3985 '') | |
| 3986 self.assert_multi_line_lint( | |
| 3987 'f(a, b);', | |
| 3988 '') | |
| 3989 self.assert_multi_line_lint( | |
| 3990 'c = a | b;', | |
| 3991 '') | |
| 3992 self.assert_multi_line_lint( | |
| 3993 'return condition ? 1 : 0;', | |
| 3994 '') | |
| 3995 self.assert_multi_line_lint( | |
| 3996 'y=m*x+b;', | |
| 3997 'Missing spaces around = [whitespace/operators] [4]') | |
| 3998 self.assert_multi_line_lint( | |
| 3999 'f(a,b);', | |
| 4000 'Missing space after , [whitespace/comma] [3]') | |
| 4001 self.assert_multi_line_lint( | |
| 4002 'c = a|b;', | |
| 4003 'Missing spaces around | [whitespace/operators] [3]') | |
| 4004 # FIXME: We cannot catch this lint error. | |
| 4005 # self.assert_multi_line_lint( | |
| 4006 # 'return condition ? 1:0;', | |
| 4007 # '') | |
| 4008 | |
| 4009 # 3. Place spaces between control statements and their parentheses. | |
| 4010 self.assert_multi_line_lint( | |
| 4011 ' if (condition)\n' | |
| 4012 ' doIt();\n', | |
| 4013 '') | |
| 4014 self.assert_multi_line_lint( | |
| 4015 ' if(condition)\n' | |
| 4016 ' doIt();\n', | |
| 4017 'Missing space before ( in if( [whitespace/parens] [5]') | |
| 4018 | |
| 4019 # 4. Do not place spaces between a function and its parentheses, | |
| 4020 # or between a parenthesis and its content. | |
| 4021 self.assert_multi_line_lint( | |
| 4022 'f(a, b);', | |
| 4023 '') | |
| 4024 self.assert_multi_line_lint( | |
| 4025 'f (a, b);', | |
| 4026 'Extra space before ( in function call [whitespace/parens] [4]') | |
| 4027 self.assert_multi_line_lint( | |
| 4028 'f( a, b );', | |
| 4029 ['Extra space after ( in function call [whitespace/parens] [4]', | |
| 4030 'Extra space before ) [whitespace/parens] [2]']) | |
| 4031 | |
| 4032 def test_line_breaking(self): | |
| 4033 # 1. Each statement should get its own line. | |
| 4034 self.assert_multi_line_lint( | |
| 4035 ' x++;\n' | |
| 4036 ' y++;\n' | |
| 4037 ' if (condition);\n' | |
| 4038 ' doIt();\n', | |
| 4039 '') | |
| 4040 self.assert_multi_line_lint( | |
| 4041 ' if (condition) \\\n' | |
| 4042 ' doIt();\n', | |
| 4043 '') | |
| 4044 self.assert_multi_line_lint( | |
| 4045 ' x++; y++;', | |
| 4046 'More than one command on the same line [whitespace/newline] [4]') | |
| 4047 self.assert_multi_line_lint( | |
| 4048 ' if (condition) doIt();\n', | |
| 4049 'More than one command on the same line in if [whitespace/parens] [
4]') | |
| 4050 # Ensure that having a # in the line doesn't hide the error. | |
| 4051 self.assert_multi_line_lint( | |
| 4052 ' x++; char a[] = "#";', | |
| 4053 'More than one command on the same line [whitespace/newline] [4]') | |
| 4054 # Ignore preprocessor if's. | |
| 4055 self.assert_multi_line_lint( | |
| 4056 '#if (condition) || (condition2)\n', | |
| 4057 '') | |
| 4058 | |
| 4059 # 2. An else statement should go on the same line as a preceding | |
| 4060 # close brace if one is present, else it should line up with the | |
| 4061 # if statement. | |
| 4062 self.assert_multi_line_lint( | |
| 4063 'if (condition) {\n' | |
| 4064 ' doSomething();\n' | |
| 4065 ' doSomethingAgain();\n' | |
| 4066 '} else {\n' | |
| 4067 ' doSomethingElse();\n' | |
| 4068 ' doSomethingElseAgain();\n' | |
| 4069 '}\n', | |
| 4070 '') | |
| 4071 self.assert_multi_line_lint( | |
| 4072 'if (condition)\n' | |
| 4073 ' doSomething();\n' | |
| 4074 'else\n' | |
| 4075 ' doSomethingElse();\n', | |
| 4076 '') | |
| 4077 self.assert_multi_line_lint( | |
| 4078 'if (condition) {\n' | |
| 4079 ' doSomething();\n' | |
| 4080 '} else {\n' | |
| 4081 ' doSomethingElse();\n' | |
| 4082 ' doSomethingElseAgain();\n' | |
| 4083 '}\n', | |
| 4084 '') | |
| 4085 self.assert_multi_line_lint( | |
| 4086 '#define TEST_ASSERT(expression) do { if (!(expression)) { TestsCont
roller::shared().testFailed(__FILE__, __LINE__, #expression); return; } } while
(0)\n', | |
| 4087 '') | |
| 4088 self.assert_multi_line_lint( | |
| 4089 '#define TEST_ASSERT(expression) do { if ( !(expression)) { TestsCon
troller::shared().testFailed(__FILE__, __LINE__, #expression); return; } } while
(0)\n', | |
| 4090 'Extra space after ( in if [whitespace/parens] [5]') | |
| 4091 # FIXME: currently we only check first conditional, so we cannot detect
errors in next ones. | |
| 4092 # self.assert_multi_line_lint( | |
| 4093 # '#define TEST_ASSERT(expression) do { if (!(expression)) { TestsCo
ntroller::shared().testFailed(__FILE__, __LINE__, #expression); return; } } whil
e (0 )\n', | |
| 4094 # 'Mismatching spaces inside () in if [whitespace/parens] [5]') | |
| 4095 self.assert_multi_line_lint( | |
| 4096 'WTF_MAKE_NONCOPYABLE(ClassName); WTF_MAKE_FAST_ALLOCATED;\n', | |
| 4097 '') | |
| 4098 self.assert_multi_line_lint( | |
| 4099 'if (condition) {\n' | |
| 4100 ' doSomething();\n' | |
| 4101 ' doSomethingAgain();\n' | |
| 4102 '}\n' | |
| 4103 'else {\n' | |
| 4104 ' doSomethingElse();\n' | |
| 4105 ' doSomethingElseAgain();\n' | |
| 4106 '}\n', | |
| 4107 'An else should appear on the same line as the preceding } [whitesp
ace/newline] [4]') | |
| 4108 self.assert_multi_line_lint( | |
| 4109 'if (condition) doSomething(); else doSomethingElse();\n', | |
| 4110 ['More than one command on the same line [whitespace/newline] [4]', | |
| 4111 'Else clause should never be on same line as else (use 2 lines) [w
hitespace/newline] [4]', | |
| 4112 'More than one command on the same line in if [whitespace/parens]
[4]']) | |
| 4113 self.assert_multi_line_lint( | |
| 4114 'if (condition) doSomething(); else {\n' | |
| 4115 ' doSomethingElse();\n' | |
| 4116 '}\n', | |
| 4117 ['More than one command on the same line in if [whitespace/parens]
[4]', | |
| 4118 'If one part of an if-else statement uses curly braces, the other p
art must too. [whitespace/braces] [4]']) | |
| 4119 self.assert_multi_line_lint( | |
| 4120 'void func()\n' | |
| 4121 '{\n' | |
| 4122 ' while (condition) { }\n' | |
| 4123 ' return 0;\n' | |
| 4124 '}\n', | |
| 4125 '') | |
| 4126 self.assert_multi_line_lint( | |
| 4127 'void func()\n' | |
| 4128 '{\n' | |
| 4129 ' for (i = 0; i < 42; i++) { foobar(); }\n' | |
| 4130 ' return 0;\n' | |
| 4131 '}\n', | |
| 4132 'More than one command on the same line in for [whitespace/parens]
[4]') | |
| 4133 | |
| 4134 # 3. An else if statement should be written as an if statement | |
| 4135 # when the prior if concludes with a return statement. | |
| 4136 self.assert_multi_line_lint( | |
| 4137 'if (motivated) {\n' | |
| 4138 ' if (liquid)\n' | |
| 4139 ' return money;\n' | |
| 4140 '} else if (tired) {\n' | |
| 4141 ' break;\n' | |
| 4142 '}', | |
| 4143 '') | |
| 4144 self.assert_multi_line_lint( | |
| 4145 'if (condition)\n' | |
| 4146 ' doSomething();\n' | |
| 4147 'else if (otherCondition)\n' | |
| 4148 ' doSomethingElse();\n', | |
| 4149 '') | |
| 4150 self.assert_multi_line_lint( | |
| 4151 'if (condition)\n' | |
| 4152 ' doSomething();\n' | |
| 4153 'else\n' | |
| 4154 ' doSomethingElse();\n', | |
| 4155 '') | |
| 4156 self.assert_multi_line_lint( | |
| 4157 'if (condition)\n' | |
| 4158 ' returnValue = foo;\n' | |
| 4159 'else if (otherCondition)\n' | |
| 4160 ' returnValue = bar;\n', | |
| 4161 '') | |
| 4162 self.assert_multi_line_lint( | |
| 4163 'if (condition)\n' | |
| 4164 ' returnValue = foo;\n' | |
| 4165 'else\n' | |
| 4166 ' returnValue = bar;\n', | |
| 4167 '') | |
| 4168 self.assert_multi_line_lint( | |
| 4169 'if (condition)\n' | |
| 4170 ' doSomething();\n' | |
| 4171 'else if (liquid)\n' | |
| 4172 ' return money;\n' | |
| 4173 'else if (broke)\n' | |
| 4174 ' return favor;\n' | |
| 4175 'else\n' | |
| 4176 ' sleep(28800);\n', | |
| 4177 '') | |
| 4178 self.assert_multi_line_lint( | |
| 4179 'if (liquid) {\n' | |
| 4180 ' prepare();\n' | |
| 4181 ' return money;\n' | |
| 4182 '} else if (greedy) {\n' | |
| 4183 ' keep();\n' | |
| 4184 ' return nothing;\n' | |
| 4185 '}\n', | |
| 4186 'An else if statement should be written as an if statement when the
' | |
| 4187 'prior "if" concludes with a return, break, continue or goto stateme
nt.' | |
| 4188 ' [readability/control_flow] [4]') | |
| 4189 self.assert_multi_line_lint( | |
| 4190 ' if (stupid) {\n' | |
| 4191 'infiniteLoop:\n' | |
| 4192 ' goto infiniteLoop;\n' | |
| 4193 ' } else if (evil)\n' | |
| 4194 ' goto hell;\n', | |
| 4195 ['If one part of an if-else statement uses curly braces, the other p
art must too. [whitespace/braces] [4]', | |
| 4196 'An else if statement should be written as an if statement when the
' | |
| 4197 'prior "if" concludes with a return, break, continue or goto statem
ent.' | |
| 4198 ' [readability/control_flow] [4]']) | |
| 4199 self.assert_multi_line_lint( | |
| 4200 'if (liquid)\n' | |
| 4201 '{\n' | |
| 4202 ' prepare();\n' | |
| 4203 ' return money;\n' | |
| 4204 '}\n' | |
| 4205 'else if (greedy)\n' | |
| 4206 ' keep();\n', | |
| 4207 ['If one part of an if-else statement uses curly braces, the other p
art must too. [whitespace/braces] [4]', | |
| 4208 'This { should be at the end of the previous line [whitespace/brac
es] [4]', | |
| 4209 'An else should appear on the same line as the preceding } [whites
pace/newline] [4]', | |
| 4210 'An else if statement should be written as an if statement when the
' | |
| 4211 'prior "if" concludes with a return, break, continue or goto statem
ent.' | |
| 4212 ' [readability/control_flow] [4]']) | |
| 4213 self.assert_multi_line_lint( | |
| 4214 'if (gone)\n' | |
| 4215 ' return;\n' | |
| 4216 'else if (here)\n' | |
| 4217 ' go();\n', | |
| 4218 'An else if statement should be written as an if statement when the
' | |
| 4219 'prior "if" concludes with a return, break, continue or goto stateme
nt.' | |
| 4220 ' [readability/control_flow] [4]') | |
| 4221 self.assert_multi_line_lint( | |
| 4222 'if (gone)\n' | |
| 4223 ' return;\n' | |
| 4224 'else\n' | |
| 4225 ' go();\n', | |
| 4226 'An else statement can be removed when the prior "if" concludes ' | |
| 4227 'with a return, break, continue or goto statement.' | |
| 4228 ' [readability/control_flow] [4]') | |
| 4229 self.assert_multi_line_lint( | |
| 4230 'if (motivated) {\n' | |
| 4231 ' prepare();\n' | |
| 4232 ' continue;\n' | |
| 4233 '} else {\n' | |
| 4234 ' cleanUp();\n' | |
| 4235 ' break;\n' | |
| 4236 '}\n', | |
| 4237 'An else statement can be removed when the prior "if" concludes ' | |
| 4238 'with a return, break, continue or goto statement.' | |
| 4239 ' [readability/control_flow] [4]') | |
| 4240 self.assert_multi_line_lint( | |
| 4241 'if (tired)\n' | |
| 4242 ' break;\n' | |
| 4243 'else {\n' | |
| 4244 ' prepare();\n' | |
| 4245 ' continue;\n' | |
| 4246 '}\n', | |
| 4247 ['If one part of an if-else statement uses curly braces, the other p
art must too. [whitespace/braces] [4]', | |
| 4248 'An else statement can be removed when the prior "if" concludes ' | |
| 4249 'with a return, break, continue or goto statement.' | |
| 4250 ' [readability/control_flow] [4]']) | |
| 4251 | |
| 4252 def test_braces(self): | |
| 4253 # 1. Function definitions: place each brace on its own line. | |
| 4254 self.assert_multi_line_lint( | |
| 4255 'int main()\n' | |
| 4256 '{\n' | |
| 4257 ' doSomething();\n' | |
| 4258 '}\n', | |
| 4259 '') | |
| 4260 self.assert_multi_line_lint( | |
| 4261 'int main() {\n' | |
| 4262 ' doSomething();\n' | |
| 4263 '}\n', | |
| 4264 'Place brace on its own line for function definitions. [whitespace/
braces] [4]') | |
| 4265 | |
| 4266 # 2. Other braces: place the open brace on the line preceding the | |
| 4267 # code block; place the close brace on its own line. | |
| 4268 self.assert_multi_line_lint( | |
| 4269 'class MyClass {\n' | |
| 4270 ' int foo;\n' | |
| 4271 '};\n', | |
| 4272 '') | |
| 4273 self.assert_multi_line_lint( | |
| 4274 'namespace WebCore {\n' | |
| 4275 'int foo;\n' | |
| 4276 '};\n', | |
| 4277 '') | |
| 4278 self.assert_multi_line_lint( | |
| 4279 'for (int i = 0; i < 10; i++) {\n' | |
| 4280 ' DoSomething();\n' | |
| 4281 '};\n', | |
| 4282 '') | |
| 4283 self.assert_multi_line_lint( | |
| 4284 'class MyClass\n' | |
| 4285 '{\n' | |
| 4286 ' int foo;\n' | |
| 4287 '};\n', | |
| 4288 'This { should be at the end of the previous line [whitespace/brace
s] [4]') | |
| 4289 self.assert_multi_line_lint( | |
| 4290 'if (condition)\n' | |
| 4291 '{\n' | |
| 4292 ' int foo;\n' | |
| 4293 '}\n', | |
| 4294 'This { should be at the end of the previous line [whitespace/brace
s] [4]') | |
| 4295 self.assert_multi_line_lint( | |
| 4296 'for (int i = 0; i < 10; i++)\n' | |
| 4297 '{\n' | |
| 4298 ' int foo;\n' | |
| 4299 '}\n', | |
| 4300 'This { should be at the end of the previous line [whitespace/brace
s] [4]') | |
| 4301 self.assert_multi_line_lint( | |
| 4302 'while (true)\n' | |
| 4303 '{\n' | |
| 4304 ' int foo;\n' | |
| 4305 '}\n', | |
| 4306 'This { should be at the end of the previous line [whitespace/brace
s] [4]') | |
| 4307 self.assert_multi_line_lint( | |
| 4308 'foreach (Foo* foo, foos)\n' | |
| 4309 '{\n' | |
| 4310 ' int bar;\n' | |
| 4311 '}\n', | |
| 4312 'This { should be at the end of the previous line [whitespace/brace
s] [4]') | |
| 4313 self.assert_multi_line_lint( | |
| 4314 'switch (type)\n' | |
| 4315 '{\n' | |
| 4316 'case foo: return;\n' | |
| 4317 '}\n', | |
| 4318 'This { should be at the end of the previous line [whitespace/brace
s] [4]') | |
| 4319 self.assert_multi_line_lint( | |
| 4320 'if (condition)\n' | |
| 4321 '{\n' | |
| 4322 ' int foo;\n' | |
| 4323 '}\n', | |
| 4324 'This { should be at the end of the previous line [whitespace/brace
s] [4]') | |
| 4325 self.assert_multi_line_lint( | |
| 4326 'for (int i = 0; i < 10; i++)\n' | |
| 4327 '{\n' | |
| 4328 ' int foo;\n' | |
| 4329 '}\n', | |
| 4330 'This { should be at the end of the previous line [whitespace/brace
s] [4]') | |
| 4331 self.assert_multi_line_lint( | |
| 4332 'while (true)\n' | |
| 4333 '{\n' | |
| 4334 ' int foo;\n' | |
| 4335 '}\n', | |
| 4336 'This { should be at the end of the previous line [whitespace/brace
s] [4]') | |
| 4337 self.assert_multi_line_lint( | |
| 4338 'switch (type)\n' | |
| 4339 '{\n' | |
| 4340 'case foo: return;\n' | |
| 4341 '}\n', | |
| 4342 'This { should be at the end of the previous line [whitespace/brace
s] [4]') | |
| 4343 self.assert_multi_line_lint( | |
| 4344 'else if (type)\n' | |
| 4345 '{\n' | |
| 4346 'case foo: return;\n' | |
| 4347 '}\n', | |
| 4348 'This { should be at the end of the previous line [whitespace/brace
s] [4]') | |
| 4349 | |
| 4350 # 3. Curly braces are not required for single-line conditionals and | |
| 4351 # loop bodies, but are required for single-statement bodies that | |
| 4352 # span multiple lines. | |
| 4353 | |
| 4354 # | |
| 4355 # Positive tests | |
| 4356 # | |
| 4357 self.assert_multi_line_lint( | |
| 4358 'if (condition1)\n' | |
| 4359 ' statement1();\n' | |
| 4360 'else\n' | |
| 4361 ' statement2();\n', | |
| 4362 '') | |
| 4363 | |
| 4364 self.assert_multi_line_lint( | |
| 4365 'if (condition1)\n' | |
| 4366 ' statement1();\n' | |
| 4367 'else if (condition2)\n' | |
| 4368 ' statement2();\n', | |
| 4369 '') | |
| 4370 | |
| 4371 self.assert_multi_line_lint( | |
| 4372 'if (condition1)\n' | |
| 4373 ' statement1();\n' | |
| 4374 'else if (condition2)\n' | |
| 4375 ' statement2();\n' | |
| 4376 'else\n' | |
| 4377 ' statement3();\n', | |
| 4378 '') | |
| 4379 | |
| 4380 self.assert_multi_line_lint( | |
| 4381 'for (; foo; bar)\n' | |
| 4382 ' int foo;\n', | |
| 4383 '') | |
| 4384 | |
| 4385 self.assert_multi_line_lint( | |
| 4386 'for (; foo; bar) {\n' | |
| 4387 ' int foo;\n' | |
| 4388 '}\n', | |
| 4389 '') | |
| 4390 | |
| 4391 self.assert_multi_line_lint( | |
| 4392 'foreach (foo, foos) {\n' | |
| 4393 ' int bar;\n' | |
| 4394 '}\n', | |
| 4395 '') | |
| 4396 | |
| 4397 self.assert_multi_line_lint( | |
| 4398 'foreach (foo, foos)\n' | |
| 4399 ' int bar;\n', | |
| 4400 '') | |
| 4401 | |
| 4402 self.assert_multi_line_lint( | |
| 4403 'while (true) {\n' | |
| 4404 ' int foo;\n' | |
| 4405 '}\n', | |
| 4406 '') | |
| 4407 | |
| 4408 self.assert_multi_line_lint( | |
| 4409 'while (true)\n' | |
| 4410 ' int foo;\n', | |
| 4411 '') | |
| 4412 | |
| 4413 self.assert_multi_line_lint( | |
| 4414 'if (condition1) {\n' | |
| 4415 ' statement1();\n' | |
| 4416 '} else {\n' | |
| 4417 ' statement2();\n' | |
| 4418 '}\n', | |
| 4419 '') | |
| 4420 | |
| 4421 self.assert_multi_line_lint( | |
| 4422 'if (condition1) {\n' | |
| 4423 ' statement1();\n' | |
| 4424 '} else if (condition2) {\n' | |
| 4425 ' statement2();\n' | |
| 4426 '}\n', | |
| 4427 '') | |
| 4428 | |
| 4429 self.assert_multi_line_lint( | |
| 4430 'if (condition1) {\n' | |
| 4431 ' statement1();\n' | |
| 4432 '} else if (condition2) {\n' | |
| 4433 ' statement2();\n' | |
| 4434 '} else {\n' | |
| 4435 ' statement3();\n' | |
| 4436 '}\n', | |
| 4437 '') | |
| 4438 | |
| 4439 self.assert_multi_line_lint( | |
| 4440 'if (condition1) {\n' | |
| 4441 ' statement1();\n' | |
| 4442 ' statement1_2();\n' | |
| 4443 '} else if (condition2) {\n' | |
| 4444 ' statement2();\n' | |
| 4445 ' statement2_2();\n' | |
| 4446 '}\n', | |
| 4447 '') | |
| 4448 | |
| 4449 self.assert_multi_line_lint( | |
| 4450 'if (condition1) {\n' | |
| 4451 ' statement1();\n' | |
| 4452 ' statement1_2();\n' | |
| 4453 '} else if (condition2) {\n' | |
| 4454 ' statement2();\n' | |
| 4455 ' statement2_2();\n' | |
| 4456 '} else {\n' | |
| 4457 ' statement3();\n' | |
| 4458 ' statement3_2();\n' | |
| 4459 '}\n', | |
| 4460 '') | |
| 4461 | |
| 4462 # | |
| 4463 # Negative tests | |
| 4464 # | |
| 4465 | |
| 4466 self.assert_multi_line_lint( | |
| 4467 'if (condition)\n' | |
| 4468 ' doSomething(\n' | |
| 4469 ' spanningMultipleLines);\n', | |
| 4470 'A conditional or loop body must use braces if the statement is more
than one line long. [whitespace/braces] [4]') | |
| 4471 | |
| 4472 self.assert_multi_line_lint( | |
| 4473 'if (condition)\n' | |
| 4474 ' // Single-line comment\n' | |
| 4475 ' doSomething();\n', | |
| 4476 'A conditional or loop body must use braces if the statement is more
than one line long. [whitespace/braces] [4]') | |
| 4477 | |
| 4478 self.assert_multi_line_lint( | |
| 4479 'if (condition1)\n' | |
| 4480 ' statement1();\n' | |
| 4481 'else if (condition2)\n' | |
| 4482 ' // Single-line comment\n' | |
| 4483 ' statement2();\n', | |
| 4484 'A conditional or loop body must use braces if the statement is more
than one line long. [whitespace/braces] [4]') | |
| 4485 | |
| 4486 self.assert_multi_line_lint( | |
| 4487 'if (condition1)\n' | |
| 4488 ' statement1();\n' | |
| 4489 'else if (condition2)\n' | |
| 4490 ' statement2();\n' | |
| 4491 'else\n' | |
| 4492 ' // Single-line comment\n' | |
| 4493 ' statement3();\n', | |
| 4494 'A conditional or loop body must use braces if the statement is more
than one line long. [whitespace/braces] [4]') | |
| 4495 | |
| 4496 self.assert_multi_line_lint( | |
| 4497 'for (; foo; bar)\n' | |
| 4498 ' // Single-line comment\n' | |
| 4499 ' int foo;\n', | |
| 4500 'A conditional or loop body must use braces if the statement is more
than one line long. [whitespace/braces] [4]') | |
| 4501 | |
| 4502 self.assert_multi_line_lint( | |
| 4503 'foreach (foo, foos)\n' | |
| 4504 ' // Single-line comment\n' | |
| 4505 ' int bar;\n', | |
| 4506 'A conditional or loop body must use braces if the statement is more
than one line long. [whitespace/braces] [4]') | |
| 4507 | |
| 4508 self.assert_multi_line_lint( | |
| 4509 'while (true)\n' | |
| 4510 ' // Single-line comment\n' | |
| 4511 ' int foo;\n' | |
| 4512 '\n', | |
| 4513 'A conditional or loop body must use braces if the statement is more
than one line long. [whitespace/braces] [4]') | |
| 4514 | |
| 4515 # 4. If one part of an if-else statement uses curly braces, the | |
| 4516 # other part must too. | |
| 4517 | |
| 4518 self.assert_multi_line_lint( | |
| 4519 'if (condition1) {\n' | |
| 4520 ' doSomething1();\n' | |
| 4521 ' doSomething1_2();\n' | |
| 4522 '} else if (condition2)\n' | |
| 4523 ' doSomething2();\n' | |
| 4524 'else\n' | |
| 4525 ' doSomething3();\n', | |
| 4526 'If one part of an if-else statement uses curly braces, the other pa
rt must too. [whitespace/braces] [4]') | |
| 4527 | |
| 4528 self.assert_multi_line_lint( | |
| 4529 'if (condition1)\n' | |
| 4530 ' doSomething1();\n' | |
| 4531 'else if (condition2) {\n' | |
| 4532 ' doSomething2();\n' | |
| 4533 ' doSomething2_2();\n' | |
| 4534 '} else\n' | |
| 4535 ' doSomething3();\n', | |
| 4536 'If one part of an if-else statement uses curly braces, the other pa
rt must too. [whitespace/braces] [4]') | |
| 4537 | |
| 4538 self.assert_multi_line_lint( | |
| 4539 'if (condition1) {\n' | |
| 4540 ' doSomething1();\n' | |
| 4541 '} else if (condition2) {\n' | |
| 4542 ' doSomething2();\n' | |
| 4543 ' doSomething2_2();\n' | |
| 4544 '} else\n' | |
| 4545 ' doSomething3();\n', | |
| 4546 'If one part of an if-else statement uses curly braces, the other pa
rt must too. [whitespace/braces] [4]') | |
| 4547 | |
| 4548 self.assert_multi_line_lint( | |
| 4549 'if (condition1)\n' | |
| 4550 ' doSomething1();\n' | |
| 4551 'else if (condition2)\n' | |
| 4552 ' doSomething2();\n' | |
| 4553 'else {\n' | |
| 4554 ' doSomething3();\n' | |
| 4555 ' doSomething3_2();\n' | |
| 4556 '}\n', | |
| 4557 'If one part of an if-else statement uses curly braces, the other pa
rt must too. [whitespace/braces] [4]') | |
| 4558 | |
| 4559 self.assert_multi_line_lint( | |
| 4560 'if (condition1) {\n' | |
| 4561 ' doSomething1();\n' | |
| 4562 ' doSomething1_2();\n' | |
| 4563 '} else if (condition2)\n' | |
| 4564 ' doSomething2();\n' | |
| 4565 'else {\n' | |
| 4566 ' doSomething3();\n' | |
| 4567 ' doSomething3_2();\n' | |
| 4568 '}\n', | |
| 4569 'If one part of an if-else statement uses curly braces, the other pa
rt must too. [whitespace/braces] [4]') | |
| 4570 | |
| 4571 self.assert_multi_line_lint( | |
| 4572 'if (condition1)\n' | |
| 4573 ' doSomething1();\n' | |
| 4574 'else if (condition2) {\n' | |
| 4575 ' doSomething2();\n' | |
| 4576 ' doSomething2_2();\n' | |
| 4577 '} else {\n' | |
| 4578 ' doSomething3();\n' | |
| 4579 ' doSomething3_2();\n' | |
| 4580 '}\n', | |
| 4581 'If one part of an if-else statement uses curly braces, the other pa
rt must too. [whitespace/braces] [4]') | |
| 4582 | |
| 4583 | |
| 4584 # 5. Control clauses without a body should use empty braces. | |
| 4585 self.assert_multi_line_lint( | |
| 4586 'for ( ; current; current = current->next) { }\n', | |
| 4587 '') | |
| 4588 self.assert_multi_line_lint( | |
| 4589 'for ( ; current;\n' | |
| 4590 ' current = current->next) { }\n', | |
| 4591 'Weird number of spaces at line-start. Are you using a 4-space inde
nt? [whitespace/indent] [3]') | |
| 4592 self.assert_multi_line_lint( | |
| 4593 'for ( ; current; current = current->next);\n', | |
| 4594 'Semicolon defining empty statement for this loop. Use { } instead.
[whitespace/semicolon] [5]') | |
| 4595 self.assert_multi_line_lint( | |
| 4596 'while (true);\n', | |
| 4597 'Semicolon defining empty statement for this loop. Use { } instead.
[whitespace/semicolon] [5]') | |
| 4598 self.assert_multi_line_lint( | |
| 4599 '} while (true);\n', | |
| 4600 '') | |
| 4601 | |
| 4602 def test_null_false_zero(self): | |
| 4603 # 1. In C++, the null pointer value should be written as 0. In C, | |
| 4604 # it should be written as NULL. In Objective-C and Objective-C++, | |
| 4605 # follow the guideline for C or C++, respectively, but use nil to | |
| 4606 # represent a null Objective-C object. | |
| 4607 self.assert_lint( | |
| 4608 'functionCall(NULL)', | |
| 4609 'Use 0 instead of NULL.' | |
| 4610 ' [readability/null] [5]', | |
| 4611 'foo.cpp') | |
| 4612 self.assert_lint( | |
| 4613 "// Don't use NULL in comments since it isn't in code.", | |
| 4614 'Use 0 or null instead of NULL (even in *comments*).' | |
| 4615 ' [readability/null] [4]', | |
| 4616 'foo.cpp') | |
| 4617 self.assert_lint( | |
| 4618 '"A string with NULL" // and a comment with NULL is tricky to flag c
orrectly in cpp_style.', | |
| 4619 'Use 0 or null instead of NULL (even in *comments*).' | |
| 4620 ' [readability/null] [4]', | |
| 4621 'foo.cpp') | |
| 4622 self.assert_lint( | |
| 4623 '"A string containing NULL is ok"', | |
| 4624 '', | |
| 4625 'foo.cpp') | |
| 4626 self.assert_lint( | |
| 4627 'if (aboutNULL)', | |
| 4628 '', | |
| 4629 'foo.cpp') | |
| 4630 self.assert_lint( | |
| 4631 'myVariable = NULLify', | |
| 4632 '', | |
| 4633 'foo.cpp') | |
| 4634 # Make sure that the NULL check does not apply to C and Objective-C file
s. | |
| 4635 self.assert_lint( | |
| 4636 'functionCall(NULL)', | |
| 4637 '', | |
| 4638 'foo.c') | |
| 4639 self.assert_lint( | |
| 4640 'functionCall(NULL)', | |
| 4641 '', | |
| 4642 'foo.m') | |
| 4643 | |
| 4644 # Make sure that the NULL check does not apply to g_object_{set,get} and | |
| 4645 # g_str{join,concat} | |
| 4646 self.assert_lint( | |
| 4647 'g_object_get(foo, "prop", &bar, NULL);', | |
| 4648 '') | |
| 4649 self.assert_lint( | |
| 4650 'g_object_set(foo, "prop", bar, NULL);', | |
| 4651 '') | |
| 4652 self.assert_lint( | |
| 4653 'g_build_filename(foo, bar, NULL);', | |
| 4654 '') | |
| 4655 self.assert_lint( | |
| 4656 'gst_bin_add_many(foo, bar, boo, NULL);', | |
| 4657 '') | |
| 4658 self.assert_lint( | |
| 4659 'gst_bin_remove_many(foo, bar, boo, NULL);', | |
| 4660 '') | |
| 4661 self.assert_lint( | |
| 4662 'gst_element_link_many(foo, bar, boo, NULL);', | |
| 4663 '') | |
| 4664 self.assert_lint( | |
| 4665 'gst_element_unlink_many(foo, bar, boo, NULL);', | |
| 4666 '') | |
| 4667 self.assert_lint( | |
| 4668 'gst_structure_get(foo, "value", G_TYPE_INT, &value, NULL);', | |
| 4669 '') | |
| 4670 self.assert_lint( | |
| 4671 'gst_structure_set(foo, "value", G_TYPE_INT, value, NULL);', | |
| 4672 '') | |
| 4673 self.assert_lint( | |
| 4674 'gst_structure_remove_fields(foo, "value", "bar", NULL);', | |
| 4675 '') | |
| 4676 self.assert_lint( | |
| 4677 'gst_structure_new("foo", "value", G_TYPE_INT, value, NULL);', | |
| 4678 '') | |
| 4679 self.assert_lint( | |
| 4680 'gst_structure_id_new(FOO, VALUE, G_TYPE_INT, value, NULL);', | |
| 4681 '') | |
| 4682 self.assert_lint( | |
| 4683 'gst_structure_id_set(FOO, VALUE, G_TYPE_INT, value, NULL);', | |
| 4684 '') | |
| 4685 self.assert_lint( | |
| 4686 'gst_structure_id_get(FOO, VALUE, G_TYPE_INT, &value, NULL);', | |
| 4687 '') | |
| 4688 self.assert_lint( | |
| 4689 'gst_caps_new_simple(mime, "value", G_TYPE_INT, &value, NULL);', | |
| 4690 '') | |
| 4691 self.assert_lint( | |
| 4692 'gst_caps_new_full(structure1, structure2, NULL);', | |
| 4693 '') | |
| 4694 self.assert_lint( | |
| 4695 'gchar* result = g_strconcat("part1", "part2", "part3", NULL);', | |
| 4696 '') | |
| 4697 self.assert_lint( | |
| 4698 'gchar* result = g_strconcat("part1", NULL);', | |
| 4699 '') | |
| 4700 self.assert_lint( | |
| 4701 'gchar* result = g_strjoin(",", "part1", "part2", "part3", NULL);', | |
| 4702 '') | |
| 4703 self.assert_lint( | |
| 4704 'gchar* result = g_strjoin(",", "part1", NULL);', | |
| 4705 '') | |
| 4706 self.assert_lint( | |
| 4707 'gchar* result = gdk_pixbuf_save_to_callback(pixbuf, function, data,
type, error, NULL);', | |
| 4708 '') | |
| 4709 self.assert_lint( | |
| 4710 'gchar* result = gdk_pixbuf_save_to_buffer(pixbuf, function, data, t
ype, error, NULL);', | |
| 4711 '') | |
| 4712 self.assert_lint( | |
| 4713 'gchar* result = gdk_pixbuf_save_to_stream(pixbuf, function, data, t
ype, error, NULL);', | |
| 4714 '') | |
| 4715 self.assert_lint( | |
| 4716 'gtk_widget_style_get(style, "propertyName", &value, "otherName", &o
therValue, NULL);', | |
| 4717 '') | |
| 4718 self.assert_lint( | |
| 4719 'gtk_style_context_get_style(context, "propertyName", &value, "other
Name", &otherValue, NULL);', | |
| 4720 '') | |
| 4721 self.assert_lint( | |
| 4722 'gtk_style_context_get(context, static_cast<GtkStateFlags>(0), "prop
erty", &value, NULL);', | |
| 4723 '') | |
| 4724 self.assert_lint( | |
| 4725 'gtk_widget_style_get_property(style, NULL, NULL);', | |
| 4726 'Use 0 instead of NULL. [readability/null] [5]', | |
| 4727 'foo.cpp') | |
| 4728 self.assert_lint( | |
| 4729 'gtk_widget_style_get_valist(style, NULL, NULL);', | |
| 4730 'Use 0 instead of NULL. [readability/null] [5]', | |
| 4731 'foo.cpp') | |
| 4732 | |
| 4733 # 2. C++ and C bool values should be written as true and | |
| 4734 # false. Objective-C BOOL values should be written as YES and NO. | |
| 4735 # FIXME: Implement this. | |
| 4736 | |
| 4737 # 3. Tests for true/false and null/non-null should be done without | |
| 4738 # equality comparisons. | |
| 4739 self.assert_lint_one_of_many_errors_re( | |
| 4740 'if (string != NULL)', | |
| 4741 r'Tests for true/false and null/non-null should be done without equa
lity comparisons\.') | |
| 4742 self.assert_lint( | |
| 4743 'if (p == nullptr)', | |
| 4744 'Tests for true/false and null/non-null should be done without equal
ity comparisons.' | |
| 4745 ' [readability/comparison_to_boolean] [5]') | |
| 4746 self.assert_lint( | |
| 4747 'if (condition == true)', | |
| 4748 'Tests for true/false and null/non-null should be done without equal
ity comparisons.' | |
| 4749 ' [readability/comparison_to_boolean] [5]') | |
| 4750 self.assert_lint( | |
| 4751 'if (myVariable != /* Why would anyone put a comment here? */ false)
', | |
| 4752 'Tests for true/false and null/non-null should be done without equal
ity comparisons.' | |
| 4753 ' [readability/comparison_to_boolean] [5]') | |
| 4754 | |
| 4755 self.assert_lint_one_of_many_errors_re( | |
| 4756 'if (NULL == thisMayBeNull)', | |
| 4757 r'Tests for true/false and null/non-null should be done without equa
lity comparisons\.') | |
| 4758 self.assert_lint( | |
| 4759 'if (nullptr /* funny place for a comment */ == p)', | |
| 4760 'Tests for true/false and null/non-null should be done without equal
ity comparisons.' | |
| 4761 ' [readability/comparison_to_boolean] [5]') | |
| 4762 self.assert_lint( | |
| 4763 'if (true != anotherCondition)', | |
| 4764 'Tests for true/false and null/non-null should be done without equal
ity comparisons.' | |
| 4765 ' [readability/comparison_to_boolean] [5]') | |
| 4766 self.assert_lint( | |
| 4767 'if (false == myBoolValue)', | |
| 4768 'Tests for true/false and null/non-null should be done without equal
ity comparisons.' | |
| 4769 ' [readability/comparison_to_boolean] [5]') | |
| 4770 | |
| 4771 self.assert_lint( | |
| 4772 'if (fontType == trueType)', | |
| 4773 '') | |
| 4774 self.assert_lint( | |
| 4775 'if (othertrue == fontType)', | |
| 4776 '') | |
| 4777 self.assert_lint( | |
| 4778 'if (LIKELY(foo == 0))', | |
| 4779 '') | |
| 4780 self.assert_lint( | |
| 4781 'if (UNLIKELY(foo == 0))', | |
| 4782 '') | |
| 4783 self.assert_lint( | |
| 4784 'if ((a - b) == 0.5)', | |
| 4785 '') | |
| 4786 self.assert_lint( | |
| 4787 'if (0.5 == (a - b))', | |
| 4788 '') | |
| 4789 self.assert_lint( | |
| 4790 'if (LIKELY(foo == NULL))', | |
| 4791 'Use 0 instead of NULL. [readability/null] [5]') | |
| 4792 self.assert_lint( | |
| 4793 'if (UNLIKELY(foo == NULL))', | |
| 4794 'Use 0 instead of NULL. [readability/null] [5]') | |
| 4795 | |
| 4796 def test_directive_indentation(self): | |
| 4797 self.assert_lint( | |
| 4798 " #if FOO", | |
| 4799 "preprocessor directives (e.g., #ifdef, #define, #import) should nev
er be indented." | |
| 4800 " [whitespace/indent] [4]", | |
| 4801 "foo.cpp") | |
| 4802 | |
| 4803 def test_using_std(self): | |
| 4804 self.assert_lint( | |
| 4805 'using std::min;', | |
| 4806 "Use 'using namespace std;' instead of 'using std::min;'." | |
| 4807 " [build/using_std] [4]", | |
| 4808 'foo.cpp') | |
| 4809 | |
| 4810 def test_using_std_swap_ignored(self): | |
| 4811 self.assert_lint( | |
| 4812 'using std::swap;', | |
| 4813 '', | |
| 4814 'foo.cpp') | |
| 4815 | |
| 4816 def test_max_macro(self): | |
| 4817 self.assert_lint( | |
| 4818 'int i = MAX(0, 1);', | |
| 4819 '', | |
| 4820 'foo.c') | |
| 4821 | |
| 4822 self.assert_lint( | |
| 4823 'int i = MAX(0, 1);', | |
| 4824 'Use std::max() or std::max<type>() instead of the MAX() macro.' | |
| 4825 ' [runtime/max_min_macros] [4]', | |
| 4826 'foo.cpp') | |
| 4827 | |
| 4828 self.assert_lint( | |
| 4829 'inline int foo() { return MAX(0, 1); }', | |
| 4830 'Use std::max() or std::max<type>() instead of the MAX() macro.' | |
| 4831 ' [runtime/max_min_macros] [4]', | |
| 4832 'foo.h') | |
| 4833 | |
| 4834 def test_min_macro(self): | |
| 4835 self.assert_lint( | |
| 4836 'int i = MIN(0, 1);', | |
| 4837 '', | |
| 4838 'foo.c') | |
| 4839 | |
| 4840 self.assert_lint( | |
| 4841 'int i = MIN(0, 1);', | |
| 4842 'Use std::min() or std::min<type>() instead of the MIN() macro.' | |
| 4843 ' [runtime/max_min_macros] [4]', | |
| 4844 'foo.cpp') | |
| 4845 | |
| 4846 self.assert_lint( | |
| 4847 'inline int foo() { return MIN(0, 1); }', | |
| 4848 'Use std::min() or std::min<type>() instead of the MIN() macro.' | |
| 4849 ' [runtime/max_min_macros] [4]', | |
| 4850 'foo.h') | |
| 4851 | |
| 4852 def test_ctype_fucntion(self): | |
| 4853 self.assert_lint( | |
| 4854 'int i = isascii(8);', | |
| 4855 'Use equivelent function in <wtf/ASCIICType.h> instead of the ' | |
| 4856 'isascii() function. [runtime/ctype_function] [4]', | |
| 4857 'foo.cpp') | |
| 4858 | |
| 4859 def test_names(self): | |
| 4860 name_underscore_error_message = " is incorrectly named. Don't use unders
cores in your identifier names. [readability/naming/underscores] [4]" | |
| 4861 name_tooshort_error_message = " is incorrectly named. Don't use the sing
le letter 'l' as an identifier name. [readability/naming] [4]" | |
| 4862 | |
| 4863 # Basic cases from WebKit style guide. | |
| 4864 self.assert_lint('struct Data;', '') | |
| 4865 self.assert_lint('size_t bufferSize;', '') | |
| 4866 self.assert_lint('class HTMLDocument;', '') | |
| 4867 self.assert_lint('String mimeType();', '') | |
| 4868 self.assert_lint('size_t buffer_size;', | |
| 4869 'buffer_size' + name_underscore_error_message) | |
| 4870 self.assert_lint('short m_length;', '') | |
| 4871 self.assert_lint('short _length;', | |
| 4872 '_length' + name_underscore_error_message) | |
| 4873 self.assert_lint('short length_;', | |
| 4874 'length_' + name_underscore_error_message) | |
| 4875 self.assert_lint('unsigned _length;', | |
| 4876 '_length' + name_underscore_error_message) | |
| 4877 self.assert_lint('unsigned long _length;', | |
| 4878 '_length' + name_underscore_error_message) | |
| 4879 self.assert_lint('unsigned long long _length;', | |
| 4880 '_length' + name_underscore_error_message) | |
| 4881 | |
| 4882 # Allow underscores in Objective C files. | |
| 4883 self.assert_lint('unsigned long long _length;', | |
| 4884 '', | |
| 4885 'foo.m') | |
| 4886 self.assert_lint('unsigned long long _length;', | |
| 4887 '', | |
| 4888 'foo.mm') | |
| 4889 self.assert_lint('#import "header_file.h"\n' | |
| 4890 'unsigned long long _length;', | |
| 4891 '', | |
| 4892 'foo.h') | |
| 4893 self.assert_lint('unsigned long long _length;\n' | |
| 4894 '@interface WebFullscreenWindow;', | |
| 4895 '', | |
| 4896 'foo.h') | |
| 4897 self.assert_lint('unsigned long long _length;\n' | |
| 4898 '@implementation WebFullscreenWindow;', | |
| 4899 '', | |
| 4900 'foo.h') | |
| 4901 self.assert_lint('unsigned long long _length;\n' | |
| 4902 '@class WebWindowFadeAnimation;', | |
| 4903 '', | |
| 4904 'foo.h') | |
| 4905 | |
| 4906 # Variable name 'l' is easy to confuse with '1' | |
| 4907 self.assert_lint('int l;', 'l' + name_tooshort_error_message) | |
| 4908 self.assert_lint('size_t l;', 'l' + name_tooshort_error_message) | |
| 4909 self.assert_lint('long long l;', 'l' + name_tooshort_error_message) | |
| 4910 | |
| 4911 # Pointers, references, functions, templates, and adjectives. | |
| 4912 self.assert_lint('char* under_score;', | |
| 4913 'under_score' + name_underscore_error_message) | |
| 4914 self.assert_lint('const int UNDER_SCORE;', | |
| 4915 'UNDER_SCORE' + name_underscore_error_message) | |
| 4916 self.assert_lint('static inline const char const& const under_score;', | |
| 4917 'under_score' + name_underscore_error_message) | |
| 4918 self.assert_lint('WebCore::RenderObject* under_score;', | |
| 4919 'under_score' + name_underscore_error_message) | |
| 4920 self.assert_lint('int func_name();', | |
| 4921 'func_name' + name_underscore_error_message) | |
| 4922 self.assert_lint('RefPtr<RenderObject*> under_score;', | |
| 4923 'under_score' + name_underscore_error_message) | |
| 4924 self.assert_lint('WTF::Vector<WTF::RefPtr<const RenderObject* const> > u
nder_score;', | |
| 4925 'under_score' + name_underscore_error_message) | |
| 4926 self.assert_lint('int under_score[];', | |
| 4927 'under_score' + name_underscore_error_message) | |
| 4928 self.assert_lint('struct dirent* under_score;', | |
| 4929 'under_score' + name_underscore_error_message) | |
| 4930 self.assert_lint('long under_score;', | |
| 4931 'under_score' + name_underscore_error_message) | |
| 4932 self.assert_lint('long long under_score;', | |
| 4933 'under_score' + name_underscore_error_message) | |
| 4934 self.assert_lint('long double under_score;', | |
| 4935 'under_score' + name_underscore_error_message) | |
| 4936 self.assert_lint('long long int under_score;', | |
| 4937 'under_score' + name_underscore_error_message) | |
| 4938 | |
| 4939 # Declarations in control statement. | |
| 4940 self.assert_lint('if (int under_score = 42) {', | |
| 4941 'under_score' + name_underscore_error_message) | |
| 4942 self.assert_lint('else if (int under_score = 42) {', | |
| 4943 'under_score' + name_underscore_error_message) | |
| 4944 self.assert_lint('for (int under_score = 42; cond; i++) {', | |
| 4945 'under_score' + name_underscore_error_message) | |
| 4946 self.assert_lint('while (foo & under_score = bar) {', | |
| 4947 'under_score' + name_underscore_error_message) | |
| 4948 self.assert_lint('for (foo * under_score = p; cond; i++) {', | |
| 4949 'under_score' + name_underscore_error_message) | |
| 4950 self.assert_lint('for (foo * under_score; cond; i++) {', | |
| 4951 'under_score' + name_underscore_error_message) | |
| 4952 self.assert_lint('while (foo & value_in_thirdparty_library) {', '') | |
| 4953 self.assert_lint('while (foo * value_in_thirdparty_library) {', '') | |
| 4954 self.assert_lint('if (mli && S_OK == mli->foo()) {', '') | |
| 4955 | |
| 4956 # More member variables and functions. | |
| 4957 self.assert_lint('int SomeClass::s_validName', '') | |
| 4958 self.assert_lint('int m_under_score;', | |
| 4959 'm_under_score' + name_underscore_error_message) | |
| 4960 self.assert_lint('int SomeClass::s_under_score = 0;', | |
| 4961 'SomeClass::s_under_score' + name_underscore_error_mess
age) | |
| 4962 self.assert_lint('int SomeClass::under_score = 0;', | |
| 4963 'SomeClass::under_score' + name_underscore_error_messag
e) | |
| 4964 | |
| 4965 # Other statements. | |
| 4966 self.assert_lint('return INT_MAX;', '') | |
| 4967 self.assert_lint('return_t under_score;', | |
| 4968 'under_score' + name_underscore_error_message) | |
| 4969 self.assert_lint('goto under_score;', | |
| 4970 'under_score' + name_underscore_error_message) | |
| 4971 self.assert_lint('delete static_cast<Foo*>(p);', '') | |
| 4972 | |
| 4973 # Multiple variables in one line. | |
| 4974 self.assert_lint('void myFunction(int variable1, int another_variable);'
, | |
| 4975 'another_variable' + name_underscore_error_message) | |
| 4976 self.assert_lint('int variable1, another_variable;', | |
| 4977 'another_variable' + name_underscore_error_message) | |
| 4978 self.assert_lint('int first_variable, secondVariable;', | |
| 4979 'first_variable' + name_underscore_error_message) | |
| 4980 self.assert_lint('void my_function(int variable_1, int variable_2);', | |
| 4981 ['my_function' + name_underscore_error_message, | |
| 4982 'variable_1' + name_underscore_error_message, | |
| 4983 'variable_2' + name_underscore_error_message]) | |
| 4984 self.assert_lint('for (int variable_1, variable_2;;) {', | |
| 4985 ['variable_1' + name_underscore_error_message, | |
| 4986 'variable_2' + name_underscore_error_message]) | |
| 4987 | |
| 4988 # There is an exception for op code functions but only in the JavaScript
Core directory. | |
| 4989 self.assert_lint('void this_op_code(int var1, int var2)', '', 'Source/Ja
vaScriptCore/foo.cpp') | |
| 4990 self.assert_lint('void op_code(int var1, int var2)', '', 'Source/JavaScr
iptCore/foo.cpp') | |
| 4991 self.assert_lint('void this_op_code(int var1, int var2)', 'this_op_code'
+ name_underscore_error_message) | |
| 4992 | |
| 4993 # GObject requires certain magical names in class declarations. | |
| 4994 self.assert_lint('void webkit_dom_object_init();', '') | |
| 4995 self.assert_lint('void webkit_dom_object_class_init();', '') | |
| 4996 | |
| 4997 # There is an exception for GTK+ API. | |
| 4998 self.assert_lint('void webkit_web_view_load(int var1, int var2)', '', 'S
ource/Webkit/gtk/webkit/foo.cpp') | |
| 4999 self.assert_lint('void webkit_web_view_load(int var1, int var2)', '', 'S
ource/Webkit2/UIProcess/gtk/foo.cpp') | |
| 5000 | |
| 5001 # Test that this doesn't also apply to files not in a 'gtk' directory. | |
| 5002 self.assert_lint('void webkit_web_view_load(int var1, int var2)', | |
| 5003 'webkit_web_view_load is incorrectly named. Don\'t use underscores i
n your identifier names.' | |
| 5004 ' [readability/naming/underscores] [4]', 'Source/Webkit/webkit/foo.
cpp') | |
| 5005 # Test that this doesn't also apply to names that don't start with 'webk
it_'. | |
| 5006 self.assert_lint_one_of_many_errors_re('void otherkit_web_view_load(int
var1, int var2)', | |
| 5007 'otherkit_web_view_load is incorrectly named. Don\'t use underscores
in your identifier names.' | |
| 5008 ' [readability/naming/underscores] [4]', 'Source/Webkit/webkit/foo.
cpp') | |
| 5009 | |
| 5010 # There is an exception for some unit tests that begin with "tst_". | |
| 5011 self.assert_lint('void tst_QWebFrame::arrayObjectEnumerable(int var1, in
t var2)', '') | |
| 5012 | |
| 5013 # The Qt API uses names that begin with "qt_" or "_q_". | |
| 5014 self.assert_lint('void QTFrame::qt_drt_is_awesome(int var1, int var2)',
'') | |
| 5015 self.assert_lint('void QTFrame::_q_drt_is_awesome(int var1, int var2)',
'') | |
| 5016 self.assert_lint('void qt_drt_is_awesome(int var1, int var2);', '') | |
| 5017 self.assert_lint('void _q_drt_is_awesome(int var1, int var2);', '') | |
| 5018 | |
| 5019 # Cairo forward-declarations should not be a failure. | |
| 5020 self.assert_lint('typedef struct _cairo cairo_t;', '') | |
| 5021 self.assert_lint('typedef struct _cairo_surface cairo_surface_t;', '') | |
| 5022 self.assert_lint('typedef struct _cairo_scaled_font cairo_scaled_font_t;
', '') | |
| 5023 | |
| 5024 # EFL forward-declarations should not be a failure. | |
| 5025 self.assert_lint('typedef struct _Ecore_Evas Ecore_Evas;', '') | |
| 5026 self.assert_lint('typedef struct _Ecore_Pipe Ecore_Pipe;', '') | |
| 5027 self.assert_lint('typedef struct _Eina_Rectangle Eina_Rectangle;', '') | |
| 5028 self.assert_lint('typedef struct _Evas_Object Evas_Object;', '') | |
| 5029 self.assert_lint('typedef struct _Ewk_History_Item Ewk_History_Item;', '
') | |
| 5030 | |
| 5031 # const_iterator is allowed as well. | |
| 5032 self.assert_lint('typedef VectorType::const_iterator const_iterator;', '
') | |
| 5033 | |
| 5034 # vm_throw is allowed as well. | |
| 5035 self.assert_lint('int vm_throw;', '') | |
| 5036 | |
| 5037 # Attributes. | |
| 5038 self.assert_lint('int foo ALLOW_UNUSED;', '') | |
| 5039 self.assert_lint('int foo_error ALLOW_UNUSED;', 'foo_error' + name_under
score_error_message) | |
| 5040 self.assert_lint('ThreadFunctionInvocation* leakedInvocation ALLOW_UNUSE
D = invocation.leakPtr()', '') | |
| 5041 | |
| 5042 # Bitfields. | |
| 5043 self.assert_lint('unsigned _fillRule : 1;', | |
| 5044 '_fillRule' + name_underscore_error_message) | |
| 5045 | |
| 5046 # new operators in initialization. | |
| 5047 self.assert_lint('OwnPtr<uint32_t> variable(new uint32_t);', '') | |
| 5048 self.assert_lint('OwnPtr<uint32_t> variable(new (expr) uint32_t);', '') | |
| 5049 self.assert_lint('OwnPtr<uint32_t> under_score(new uint32_t);', | |
| 5050 'under_score' + name_underscore_error_message) | |
| 5051 | |
| 5052 # Conversion operator declaration. | |
| 5053 self.assert_lint('operator int64_t();', '') | |
| 5054 | |
| 5055 def test_parameter_names(self): | |
| 5056 # Leave meaningless variable names out of function declarations. | |
| 5057 meaningless_variable_name_error_message = 'The parameter name "%s" adds
no information, so it should be removed. [readability/parameter_name] [5]' | |
| 5058 | |
| 5059 parameter_error_rules = ('-', | |
| 5060 '+readability/parameter_name') | |
| 5061 # No variable name, so no error. | |
| 5062 self.assertEqual('', | |
| 5063 self.perform_lint('void func(int);', 'test.cpp', param
eter_error_rules)) | |
| 5064 | |
| 5065 # Verify that copying the name of the set function causes the error (wit
h some odd casing). | |
| 5066 self.assertEqual(meaningless_variable_name_error_message % 'itemCount', | |
| 5067 self.perform_lint('void setItemCount(size_t itemCount)
;', 'test.cpp', parameter_error_rules)) | |
| 5068 self.assertEqual(meaningless_variable_name_error_message % 'abcCount', | |
| 5069 self.perform_lint('void setABCCount(size_t abcCount);'
, 'test.cpp', parameter_error_rules)) | |
| 5070 | |
| 5071 # Verify that copying a type name will trigger the warning (even if the
type is a template parameter). | |
| 5072 self.assertEqual(meaningless_variable_name_error_message % 'context', | |
| 5073 self.perform_lint('void funct(PassRefPtr<ScriptExecuti
onContext> context);', 'test.cpp', parameter_error_rules)) | |
| 5074 | |
| 5075 # Verify that acronyms as variable names trigger the error (for both set
functions and type names). | |
| 5076 self.assertEqual(meaningless_variable_name_error_message % 'ec', | |
| 5077 self.perform_lint('void setExceptionCode(int ec);', 't
est.cpp', parameter_error_rules)) | |
| 5078 self.assertEqual(meaningless_variable_name_error_message % 'ec', | |
| 5079 self.perform_lint('void funct(ExceptionCode ec);', 'te
st.cpp', parameter_error_rules)) | |
| 5080 | |
| 5081 # 'object' alone, appended, or as part of an acronym is meaningless. | |
| 5082 self.assertEqual(meaningless_variable_name_error_message % 'object', | |
| 5083 self.perform_lint('void funct(RenderView object);', 't
est.cpp', parameter_error_rules)) | |
| 5084 self.assertEqual(meaningless_variable_name_error_message % 'viewObject', | |
| 5085 self.perform_lint('void funct(RenderView viewObject);'
, 'test.cpp', parameter_error_rules)) | |
| 5086 self.assertEqual(meaningless_variable_name_error_message % 'rvo', | |
| 5087 self.perform_lint('void funct(RenderView rvo);', 'test
.cpp', parameter_error_rules)) | |
| 5088 | |
| 5089 # Check that r, g, b, and a are allowed. | |
| 5090 self.assertEqual('', | |
| 5091 self.perform_lint('void setRGBAValues(int r, int g, in
t b, int a);', 'test.cpp', parameter_error_rules)) | |
| 5092 | |
| 5093 # Verify that a simple substring match isn't done which would cause fals
e positives. | |
| 5094 self.assertEqual('', | |
| 5095 self.perform_lint('void setNateLateCount(size_t elate)
;', 'test.cpp', parameter_error_rules)) | |
| 5096 self.assertEqual('', | |
| 5097 self.perform_lint('void funct(NateLate elate);', 'test
.cpp', parameter_error_rules)) | |
| 5098 | |
| 5099 # Don't have generate warnings for functions (only declarations). | |
| 5100 self.assertEqual('', | |
| 5101 self.perform_lint('void funct(PassRefPtr<ScriptExecuti
onContext> context)\n' | |
| 5102 '{\n' | |
| 5103 '}\n', 'test.cpp', parameter_error_r
ules)) | |
| 5104 | |
| 5105 def test_comments(self): | |
| 5106 # A comment at the beginning of a line is ok. | |
| 5107 self.assert_lint('// comment', '') | |
| 5108 self.assert_lint(' // comment', '') | |
| 5109 | |
| 5110 self.assert_lint('} // namespace WebCore', | |
| 5111 'One space before end of line comments' | |
| 5112 ' [whitespace/comments] [5]') | |
| 5113 | |
| 5114 def test_webkit_export_check(self): | |
| 5115 webkit_export_error_rules = ('-', | |
| 5116 '+readability/webkit_export') | |
| 5117 self.assertEqual('', | |
| 5118 self.perform_lint('WEBKIT_EXPORT int foo();\n', | |
| 5119 'WebKit/chromium/public/test.h', | |
| 5120 webkit_export_error_rules)) | |
| 5121 self.assertEqual('', | |
| 5122 self.perform_lint('WEBKIT_EXPORT int foo();\n', | |
| 5123 'WebKit/chromium/tests/test.h', | |
| 5124 webkit_export_error_rules)) | |
| 5125 self.assertEqual('WEBKIT_EXPORT should only be used in header files. [r
eadability/webkit_export] [5]', | |
| 5126 self.perform_lint('WEBKIT_EXPORT int foo();\n', | |
| 5127 'WebKit/chromium/public/test.cpp', | |
| 5128 webkit_export_error_rules)) | |
| 5129 self.assertEqual('WEBKIT_EXPORT should only appear in the chromium publi
c (or tests) directory. [readability/webkit_export] [5]', | |
| 5130 self.perform_lint('WEBKIT_EXPORT int foo();\n', | |
| 5131 'WebKit/chromium/src/test.h', | |
| 5132 webkit_export_error_rules)) | |
| 5133 self.assertEqual('WEBKIT_EXPORT should not be used on a function with a
body. [readability/webkit_export] [5]', | |
| 5134 self.perform_lint('WEBKIT_EXPORT int foo() { }\n', | |
| 5135 'WebKit/chromium/public/test.h', | |
| 5136 webkit_export_error_rules)) | |
| 5137 self.assertEqual('WEBKIT_EXPORT should not be used on a function with a
body. [readability/webkit_export] [5]', | |
| 5138 self.perform_lint('WEBKIT_EXPORT inline int foo()\n' | |
| 5139 '{\n' | |
| 5140 '}\n', | |
| 5141 'WebKit/chromium/public/test.h', | |
| 5142 webkit_export_error_rules)) | |
| 5143 self.assertEqual('WEBKIT_EXPORT should not be used with a pure virtual f
unction. [readability/webkit_export] [5]', | |
| 5144 self.perform_lint('{}\n' | |
| 5145 'WEBKIT_EXPORT\n' | |
| 5146 'virtual\n' | |
| 5147 'int\n' | |
| 5148 'foo() = 0;\n', | |
| 5149 'WebKit/chromium/public/test.h', | |
| 5150 webkit_export_error_rules)) | |
| 5151 self.assertEqual('', | |
| 5152 self.perform_lint('{}\n' | |
| 5153 'WEBKIT_EXPORT\n' | |
| 5154 'virtual\n' | |
| 5155 'int\n' | |
| 5156 'foo() = 0;\n', | |
| 5157 'test.h', | |
| 5158 webkit_export_error_rules)) | |
| 5159 | |
| 5160 def test_other(self): | |
| 5161 # FIXME: Implement this. | |
| 5162 pass | |
| 5163 | |
| 5164 | |
| 5165 class CppCheckerTest(unittest.TestCase): | |
| 5166 | |
| 5167 """Tests CppChecker class.""" | |
| 5168 | |
| 5169 def mock_handle_style_error(self): | |
| 5170 pass | |
| 5171 | |
| 5172 def _checker(self): | |
| 5173 return CppChecker("foo", "h", self.mock_handle_style_error, 3) | |
| 5174 | |
| 5175 def test_init(self): | |
| 5176 """Test __init__ constructor.""" | |
| 5177 checker = self._checker() | |
| 5178 self.assertEqual(checker.file_extension, "h") | |
| 5179 self.assertEqual(checker.file_path, "foo") | |
| 5180 self.assertEqual(checker.handle_style_error, self.mock_handle_style_erro
r) | |
| 5181 self.assertEqual(checker.min_confidence, 3) | |
| 5182 | |
| 5183 def test_eq(self): | |
| 5184 """Test __eq__ equality function.""" | |
| 5185 checker1 = self._checker() | |
| 5186 checker2 = self._checker() | |
| 5187 | |
| 5188 # == calls __eq__. | |
| 5189 self.assertTrue(checker1 == checker2) | |
| 5190 | |
| 5191 def mock_handle_style_error2(self): | |
| 5192 pass | |
| 5193 | |
| 5194 # Verify that a difference in any argument cause equality to fail. | |
| 5195 checker = CppChecker("foo", "h", self.mock_handle_style_error, 3) | |
| 5196 self.assertFalse(checker == CppChecker("bar", "h", self.mock_handle_styl
e_error, 3)) | |
| 5197 self.assertFalse(checker == CppChecker("foo", "c", self.mock_handle_styl
e_error, 3)) | |
| 5198 self.assertFalse(checker == CppChecker("foo", "h", mock_handle_style_err
or2, 3)) | |
| 5199 self.assertFalse(checker == CppChecker("foo", "h", self.mock_handle_styl
e_error, 4)) | |
| 5200 | |
| 5201 def test_ne(self): | |
| 5202 """Test __ne__ inequality function.""" | |
| 5203 checker1 = self._checker() | |
| 5204 checker2 = self._checker() | |
| 5205 | |
| 5206 # != calls __ne__. | |
| 5207 # By default, __ne__ always returns true on different objects. | |
| 5208 # Thus, just check the distinguishing case to verify that the | |
| 5209 # code defines __ne__. | |
| 5210 self.assertFalse(checker1 != checker2) | |
| OLD | NEW |