How to use lint method in molecule

Best Python code snippet using molecule_python

cpplint_unittest.py

Source:cpplint_unittest.py Github

copy

Full Screen

1#!/usr/bin/python2# -*- coding: utf-8; -*-3#4# Copyright (c) 2009 Google Inc. All rights reserved.5#6# Redistribution and use in source and binary forms, with or without7# modification, are permitted provided that the following conditions are8# met:9#10# * Redistributions of source code must retain the above copyright11# notice, this list of conditions and the following disclaimer.12# * Redistributions in binary form must reproduce the above13# copyright notice, this list of conditions and the following disclaimer14# in the documentation and/or other materials provided with the15# distribution.16# * Neither the name of Google Inc. nor the names of its17# contributors may be used to endorse or promote products derived from18# this software without specific prior written permission.19#20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS21# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT22# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR23# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT24# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,25# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT26# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,27# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY28# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT29# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE30# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.31"""Unit test for cpplint.py."""32# TODO(unknown): Add a good test that tests UpdateIncludeState.33import codecs34import os35import random36import re37import sys38import unittest39import cpplint40# This class works as an error collector and replaces cpplint.Error41# function for the unit tests. We also verify each category we see42# is in cpplint._ERROR_CATEGORIES, to help keep that list up to date.43class ErrorCollector(object):44 # These are a global list, covering all categories seen ever.45 _ERROR_CATEGORIES = cpplint._ERROR_CATEGORIES46 _SEEN_ERROR_CATEGORIES = {}47 def __init__(self, assert_fn):48 """assert_fn: a function to call when we notice a problem."""49 self._assert_fn = assert_fn50 self._errors = []51 cpplint.ResetNolintSuppressions()52 def __call__(self, unused_filename, linenum,53 category, confidence, message):54 self._assert_fn(category in self._ERROR_CATEGORIES,55 'Message "%s" has category "%s",'56 ' which is not in _ERROR_CATEGORIES' % (message, category))57 self._SEEN_ERROR_CATEGORIES[category] = 158 if cpplint._ShouldPrintError(category, confidence, linenum):59 self._errors.append('%s [%s] [%d]' % (message, category, confidence))60 def Results(self):61 if len(self._errors) < 2:62 return ''.join(self._errors) # Most tests expect to have a string.63 else:64 return self._errors # Let's give a list if there is more than one.65 def ResultList(self):66 return self._errors67 def VerifyAllCategoriesAreSeen(self):68 """Fails if there's a category in _ERROR_CATEGORIES~_SEEN_ERROR_CATEGORIES.69 This should only be called after all tests are run, so70 _SEEN_ERROR_CATEGORIES has had a chance to fully populate. Since71 this isn't called from within the normal unittest framework, we72 can't use the normal unittest assert macros. Instead we just exit73 when we see an error. Good thing this test is always run last!74 """75 for category in self._ERROR_CATEGORIES:76 if category not in self._SEEN_ERROR_CATEGORIES:77 sys.exit('FATAL ERROR: There are no tests for category "%s"' % category)78 def RemoveIfPresent(self, substr):79 for (index, error) in enumerate(self._errors):80 if error.find(substr) != -1:81 self._errors = self._errors[0:index] + self._errors[(index + 1):]82 break83# This class is a lame mock of codecs. We do not verify filename, mode, or84# encoding, but for the current use case it is not needed.85class MockIo(object):86 def __init__(self, mock_file):87 self.mock_file = mock_file88 def open(self, # pylint: disable-msg=C640989 unused_filename, unused_mode, unused_encoding, _):90 return self.mock_file91class CpplintTestBase(unittest.TestCase):92 """Provides some useful helper functions for cpplint tests."""93 def setUp(self):94 # Allow subclasses to cheat os.path.abspath called in FileInfo class.95 self.os_path_abspath_orig = os.path.abspath96 def tearDown(self):97 os.path.abspath = self.os_path_abspath_orig98 # Perform lint on single line of input and return the error message.99 def PerformSingleLineLint(self, code):100 error_collector = ErrorCollector(self.assert_)101 lines = code.split('\n')102 cpplint.RemoveMultiLineComments('foo.h', lines, error_collector)103 clean_lines = cpplint.CleansedLines(lines)104 include_state = cpplint._IncludeState()105 function_state = cpplint._FunctionState()106 nesting_state = cpplint.NestingState()107 cpplint.ProcessLine('foo.cc', 'cc', clean_lines, 0,108 include_state, function_state,109 nesting_state, error_collector)110 # Single-line lint tests are allowed to fail the 'unlintable function'111 # check.112 error_collector.RemoveIfPresent(113 'Lint failed to find start of function body.')114 return error_collector.Results()115 # Perform lint over multiple lines and return the error message.116 def PerformMultiLineLint(self, code):117 error_collector = ErrorCollector(self.assert_)118 lines = code.split('\n')119 cpplint.RemoveMultiLineComments('foo.h', lines, error_collector)120 lines = cpplint.CleansedLines(lines)121 nesting_state = cpplint.NestingState()122 for i in xrange(lines.NumLines()):123 nesting_state.Update('foo.h', lines, i, error_collector)124 cpplint.CheckStyle('foo.h', lines, i, 'h', nesting_state,125 error_collector)126 cpplint.CheckForNonStandardConstructs('foo.h', lines, i,127 nesting_state, error_collector)128 nesting_state.CheckCompletedBlocks('foo.h', error_collector)129 return error_collector.Results()130 # Similar to PerformMultiLineLint, but calls CheckLanguage instead of131 # CheckForNonStandardConstructs132 def PerformLanguageRulesCheck(self, file_name, code):133 error_collector = ErrorCollector(self.assert_)134 include_state = cpplint._IncludeState()135 nesting_state = cpplint.NestingState()136 lines = code.split('\n')137 cpplint.RemoveMultiLineComments(file_name, lines, error_collector)138 lines = cpplint.CleansedLines(lines)139 ext = file_name[file_name.rfind('.') + 1:]140 for i in xrange(lines.NumLines()):141 cpplint.CheckLanguage(file_name, lines, i, ext, include_state,142 nesting_state, error_collector)143 return error_collector.Results()144 def PerformFunctionLengthsCheck(self, code):145 """Perform Lint function length check on block of code and return warnings.146 Builds up an array of lines corresponding to the code and strips comments147 using cpplint functions.148 Establishes an error collector and invokes the function length checking149 function following cpplint's pattern.150 Args:151 code: C++ source code expected to generate a warning message.152 Returns:153 The accumulated errors.154 """155 file_name = 'foo.cc'156 error_collector = ErrorCollector(self.assert_)157 function_state = cpplint._FunctionState()158 lines = code.split('\n')159 cpplint.RemoveMultiLineComments(file_name, lines, error_collector)160 lines = cpplint.CleansedLines(lines)161 for i in xrange(lines.NumLines()):162 cpplint.CheckForFunctionLengths(file_name, lines, i,163 function_state, error_collector)164 return error_collector.Results()165 def PerformIncludeWhatYouUse(self, code, filename='foo.h', io=codecs):166 # First, build up the include state.167 error_collector = ErrorCollector(self.assert_)168 include_state = cpplint._IncludeState()169 nesting_state = cpplint.NestingState()170 lines = code.split('\n')171 cpplint.RemoveMultiLineComments(filename, lines, error_collector)172 lines = cpplint.CleansedLines(lines)173 for i in xrange(lines.NumLines()):174 cpplint.CheckLanguage(filename, lines, i, '.h', include_state,175 nesting_state, error_collector)176 # We could clear the error_collector here, but this should177 # also be fine, since our IncludeWhatYouUse unittests do not178 # have language problems.179 # Second, look for missing includes.180 cpplint.CheckForIncludeWhatYouUse(filename, lines, include_state,181 error_collector, io)182 return error_collector.Results()183 # Perform lint and compare the error message with "expected_message".184 def TestLint(self, code, expected_message):185 self.assertEquals(expected_message, self.PerformSingleLineLint(code))186 def TestMultiLineLint(self, code, expected_message):187 self.assertEquals(expected_message, self.PerformMultiLineLint(code))188 def TestMultiLineLintRE(self, code, expected_message_re):189 message = self.PerformMultiLineLint(code)190 if not re.search(expected_message_re, message):191 self.fail('Message was:\n' + message + 'Expected match to "' +192 expected_message_re + '"')193 def TestLanguageRulesCheck(self, file_name, code, expected_message):194 self.assertEquals(expected_message,195 self.PerformLanguageRulesCheck(file_name, code))196 def TestIncludeWhatYouUse(self, code, expected_message):197 self.assertEquals(expected_message,198 self.PerformIncludeWhatYouUse(code))199 def TestBlankLinesCheck(self, lines, start_errors, end_errors):200 error_collector = ErrorCollector(self.assert_)201 cpplint.ProcessFileData('foo.cc', 'cc', lines, error_collector)202 self.assertEquals(203 start_errors,204 error_collector.Results().count(205 'Redundant blank line at the start of a code block '206 'should be deleted. [whitespace/blank_line] [2]'))207 self.assertEquals(208 end_errors,209 error_collector.Results().count(210 'Redundant blank line at the end of a code block '211 'should be deleted. [whitespace/blank_line] [3]'))212class CpplintTest(CpplintTestBase):213 def GetNamespaceResults(self, lines):214 error_collector = ErrorCollector(self.assert_)215 cpplint.RemoveMultiLineComments('foo.h', lines, error_collector)216 lines = cpplint.CleansedLines(lines)217 nesting_state = cpplint.NestingState()218 for i in xrange(lines.NumLines()):219 nesting_state.Update('foo.h', lines, i, error_collector)220 cpplint.CheckForNamespaceIndentation('foo.h', nesting_state,221 lines, i, error_collector)222 return error_collector.Results()223 def testForwardDeclarationNameSpaceIndentation(self):224 lines = ['namespace Test {',225 ' class ForwardDeclaration;',226 '} // namespace Test']227 results = self.GetNamespaceResults(lines)228 self.assertEquals(results, 'Do not indent within a namespace '229 ' [runtime/indentation_namespace] [4]')230 def testNameSpaceIndentationForClass(self):231 lines = ['namespace Test {',232 'void foo() { }',233 ' class Test {',234 ' };',235 '} // namespace Test']236 results = self.GetNamespaceResults(lines)237 self.assertEquals(results, 'Do not indent within a namespace '238 ' [runtime/indentation_namespace] [4]')239 def testNameSpaceIndentationNoError(self):240 lines = ['namespace Test {',241 'void foo() { }',242 '} // namespace Test']243 results = self.GetNamespaceResults(lines)244 self.assertEquals(results, '')245 def testFalsePositivesNoError(self):246 lines = ['namespace Test {',247 'struct OuterClass {',248 ' struct NoFalsePositivesHere;',249 ' struct NoFalsePositivesHere member_variable;',250 '};',251 '} // namespace Test']252 results = self.GetNamespaceResults(lines)253 self.assertEquals(results, '')254 # Test get line width.255 def testGetLineWidth(self):256 self.assertEquals(0, cpplint.GetLineWidth(''))257 self.assertEquals(10, cpplint.GetLineWidth(u'x' * 10))258 self.assertEquals(16, cpplint.GetLineWidth(u'都|道|府|県|支庁'))259 def testGetTextInside(self):260 self.assertEquals('', cpplint._GetTextInside('fun()', r'fun\('))261 self.assertEquals('x, y', cpplint._GetTextInside('f(x, y)', r'f\('))262 self.assertEquals('a(), b(c())', cpplint._GetTextInside(263 'printf(a(), b(c()))', r'printf\('))264 self.assertEquals('x, y{}', cpplint._GetTextInside('f[x, y{}]', r'f\['))265 self.assertEquals(None, cpplint._GetTextInside('f[a, b(}]', r'f\['))266 self.assertEquals(None, cpplint._GetTextInside('f[x, y]', r'f\('))267 self.assertEquals('y, h(z, (a + b))', cpplint._GetTextInside(268 'f(x, g(y, h(z, (a + b))))', r'g\('))269 self.assertEquals('f(f(x))', cpplint._GetTextInside('f(f(f(x)))', r'f\('))270 # Supports multiple lines.271 self.assertEquals('\n return loop(x);\n',272 cpplint._GetTextInside(273 'int loop(int x) {\n return loop(x);\n}\n', r'\{'))274 # '^' matches the beginning of each line.275 self.assertEquals('x, y',276 cpplint._GetTextInside(277 '#include "inl.h" // skip #define\n'278 '#define A2(x, y) a_inl_(x, y, __LINE__)\n'279 '#define A(x) a_inl_(x, "", __LINE__)\n',280 r'^\s*#define\s*\w+\('))281 def testFindNextMultiLineCommentStart(self):282 self.assertEquals(1, cpplint.FindNextMultiLineCommentStart([''], 0))283 lines = ['a', 'b', '/* c']284 self.assertEquals(2, cpplint.FindNextMultiLineCommentStart(lines, 0))285 lines = ['char a[] = "/*";'] # not recognized as comment.286 self.assertEquals(1, cpplint.FindNextMultiLineCommentStart(lines, 0))287 def testFindNextMultiLineCommentEnd(self):288 self.assertEquals(1, cpplint.FindNextMultiLineCommentEnd([''], 0))289 lines = ['a', 'b', ' c */']290 self.assertEquals(2, cpplint.FindNextMultiLineCommentEnd(lines, 0))291 def testRemoveMultiLineCommentsFromRange(self):292 lines = ['a', ' /* comment ', ' * still comment', ' comment */ ', 'b']293 cpplint.RemoveMultiLineCommentsFromRange(lines, 1, 4)294 self.assertEquals(['a', '/**/', '/**/', '/**/', 'b'], lines)295 def testSpacesAtEndOfLine(self):296 self.TestLint(297 '// Hello there ',298 'Line ends in whitespace. Consider deleting these extra spaces.'299 ' [whitespace/end_of_line] [4]')300 # Test line length check.301 def testLineLengthCheck(self):302 self.TestLint(303 '// Hello',304 '')305 self.TestLint(306 '// ' + 'x' * 80,307 'Lines should be <= 80 characters long'308 ' [whitespace/line_length] [2]')309 self.TestLint(310 '// ' + 'x' * 100,311 'Lines should very rarely be longer than 100 characters'312 ' [whitespace/line_length] [4]')313 self.TestLint(314 '// http://g' + ('o' * 100) + 'gle.com/',315 '')316 self.TestLint(317 '// https://g' + ('o' * 100) + 'gle.com/',318 '')319 self.TestLint(320 '// https://g' + ('o' * 60) + 'gle.com/ and some comments',321 'Lines should be <= 80 characters long'322 ' [whitespace/line_length] [2]')323 self.TestLint(324 '// Read https://g' + ('o' * 60) + 'gle.com/',325 '')326 self.TestLint(327 '// $Id: g' + ('o' * 80) + 'gle.cc#1 $',328 '')329 self.TestLint(330 '// $Id: g' + ('o' * 80) + 'gle.cc#1',331 'Lines should be <= 80 characters long'332 ' [whitespace/line_length] [2]')333 self.TestMultiLineLint(334 'static const char kCStr[] = "g' + ('o' * 50) + 'gle";\n',335 'Lines should be <= 80 characters long'336 ' [whitespace/line_length] [2]')337 self.TestMultiLineLint(338 'static const char kRawStr[] = R"(g' + ('o' * 50) + 'gle)";\n',339 '') # no warning because raw string content is elided340 self.TestMultiLineLint(341 'static const char kMultiLineRawStr[] = R"(\n'342 'g' + ('o' * 80) + 'gle\n'343 ')";',344 '')345 self.TestMultiLineLint(346 'static const char kL' + ('o' * 50) + 'ngIdentifier[] = R"()";\n',347 'Lines should be <= 80 characters long'348 ' [whitespace/line_length] [2]')349 # Test error suppression annotations.350 def testErrorSuppression(self):351 # Two errors on same line:352 self.TestLint(353 'long a = (int64) 65;',354 ['Using C-style cast. Use static_cast<int64>(...) instead'355 ' [readability/casting] [4]',356 'Use int16/int64/etc, rather than the C type long'357 ' [runtime/int] [4]',358 ])359 # One category of error suppressed:360 self.TestLint(361 'long a = (int64) 65; // NOLINT(runtime/int)',362 'Using C-style cast. Use static_cast<int64>(...) instead'363 ' [readability/casting] [4]')364 # All categories suppressed: (two aliases)365 self.TestLint('long a = (int64) 65; // NOLINT', '')366 self.TestLint('long a = (int64) 65; // NOLINT(*)', '')367 # Malformed NOLINT directive:368 self.TestLint(369 'long a = 65; // NOLINT(foo)',370 ['Unknown NOLINT error category: foo'371 ' [readability/nolint] [5]',372 'Use int16/int64/etc, rather than the C type long [runtime/int] [4]',373 ])374 # Irrelevant NOLINT directive has no effect:375 self.TestLint(376 'long a = 65; // NOLINT(readability/casting)',377 'Use int16/int64/etc, rather than the C type long'378 ' [runtime/int] [4]')379 # NOLINTNEXTLINE silences warning for the next line instead of current line380 error_collector = ErrorCollector(self.assert_)381 cpplint.ProcessFileData('test.cc', 'cc',382 ['// Copyright 2014 Your Company.',383 '// NOLINTNEXTLINE(whitespace/line_length)',384 '// ./command' + (' -verbose' * 80),385 ''],386 error_collector)387 self.assertEquals('', error_collector.Results())388 # Test Variable Declarations.389 def testVariableDeclarations(self):390 self.TestLint(391 'long a = 65;',392 'Use int16/int64/etc, rather than the C type long'393 ' [runtime/int] [4]')394 self.TestLint(395 'long double b = 65.0;',396 '')397 self.TestLint(398 'long long aa = 6565;',399 'Use int16/int64/etc, rather than the C type long'400 ' [runtime/int] [4]')401 # Test C-style cast cases.402 def testCStyleCast(self):403 self.TestLint(404 'int a = (int)1.0;',405 'Using C-style cast. Use static_cast<int>(...) instead'406 ' [readability/casting] [4]')407 self.TestLint(408 'int a = (int)-1.0;',409 'Using C-style cast. Use static_cast<int>(...) instead'410 ' [readability/casting] [4]')411 self.TestLint(412 'int *a = (int *)NULL;',413 'Using C-style cast. Use reinterpret_cast<int *>(...) instead'414 ' [readability/casting] [4]')415 self.TestLint(416 'uint16 a = (uint16)1.0;',417 'Using C-style cast. Use static_cast<uint16>(...) instead'418 ' [readability/casting] [4]')419 self.TestLint(420 'int32 a = (int32)1.0;',421 'Using C-style cast. Use static_cast<int32>(...) instead'422 ' [readability/casting] [4]')423 self.TestLint(424 'uint64 a = (uint64)1.0;',425 'Using C-style cast. Use static_cast<uint64>(...) instead'426 ' [readability/casting] [4]')427 # These shouldn't be recognized casts.428 self.TestLint('u a = (u)NULL;', '')429 self.TestLint('uint a = (uint)NULL;', '')430 self.TestLint('typedef MockCallback<int(int)> CallbackType;', '')431 self.TestLint('scoped_ptr< MockCallback<int(int)> > callback_value;', '')432 self.TestLint('std::function<int(bool)>', '')433 self.TestLint('x = sizeof(int)', '')434 self.TestLint('x = alignof(int)', '')435 self.TestLint('alignas(int) char x[42]', '')436 self.TestLint('alignas(alignof(x)) char y[42]', '')437 self.TestLint('void F(int (func)(int));', '')438 self.TestLint('void F(int (func)(int*));', '')439 self.TestLint('void F(int (Class::member)(int));', '')440 self.TestLint('void F(int (Class::member)(int*));', '')441 self.TestLint('void F(int (Class::member)(int), int param);', '')442 self.TestLint('void F(int (Class::member)(int*), int param);', '')443 # These should not be recognized (lambda functions without arg names).444 self.TestLint('[](int/*unused*/) -> bool {', '')445 self.TestLint('[](int /*unused*/) -> bool {', '')446 self.TestLint('auto f = [](MyStruct* /*unused*/)->int {', '')447 self.TestLint(448 '[](int) -> bool {',449 'All parameters should be named in a function'450 ' [readability/function] [3]')451 self.TestLint(452 'auto f = [](MyStruct*)->int {',453 'All parameters should be named in a function'454 ' [readability/function] [3]')455 # Test taking address of casts (runtime/casting)456 def testRuntimeCasting(self):457 error_msg = ('Are you taking an address of a cast? '458 'This is dangerous: could be a temp var. '459 'Take the address before doing the cast, rather than after'460 ' [runtime/casting] [4]')461 self.TestLint('int* x = &static_cast<int*>(foo);', error_msg)462 self.TestLint('int* x = &reinterpret_cast<int *>(foo);', error_msg)463 self.TestLint('int* x = &(int*)foo;',464 ['Using C-style cast. Use reinterpret_cast<int*>(...) '465 'instead [readability/casting] [4]',466 error_msg])467 self.TestLint('BudgetBuckets&(BudgetWinHistory::*BucketFn)(void) const;',468 '')469 self.TestLint('&(*func_ptr)(arg)', '')470 self.TestLint('Compute(arg, &(*func_ptr)(i, j));', '')471 # Alternative error message472 alt_error_msg = ('Are you taking an address of something dereferenced '473 'from a cast? Wrapping the dereferenced expression in '474 'parentheses will make the binding more obvious'475 ' [readability/casting] [4]')476 self.TestLint('int* x = &down_cast<Obj*>(obj)->member_;', alt_error_msg)477 self.TestLint('int* x = &down_cast<Obj*>(obj)[index];', alt_error_msg)478 self.TestLint('int* x = &(down_cast<Obj*>(obj)->member_);', '')479 self.TestLint('int* x = &(down_cast<Obj*>(obj)[index]);', '')480 self.TestLint('int* x = &down_cast<Obj*>(obj)\n->member_;', alt_error_msg)481 self.TestLint('int* x = &(down_cast<Obj*>(obj)\n->member_);', '')482 # It's OK to cast an address.483 self.TestLint('int* x = reinterpret_cast<int *>(&foo);', '')484 # Function pointers returning references should not be confused485 # with taking address of old-style casts.486 self.TestLint('auto x = implicit_cast<string &(*)(int)>(&foo);', '')487 def testRuntimeSelfinit(self):488 self.TestLint(489 'Foo::Foo(Bar r, Bel l) : r_(r_), l_(l_) { }',490 'You seem to be initializing a member variable with itself.'491 ' [runtime/init] [4]')492 self.TestLint(493 'Foo::Foo(Bar r, Bel l) : r_(r), l_(l) { }',494 '')495 self.TestLint(496 'Foo::Foo(Bar r) : r_(r), l_(r_), ll_(l_) { }',497 '')498 # Test for unnamed arguments in a method.499 def testCheckForUnnamedParams(self):500 message = ('All parameters should be named in a function'501 ' [readability/function] [3]')502 self.TestLint('virtual void Func(int*) const;', message)503 self.TestLint('virtual void Func(int*);', message)504 self.TestLint('void Method(char*) {', message)505 self.TestLint('void Method(char*);', message)506 self.TestLint('static void operator delete[](void*) throw();', message)507 self.TestLint('int Method(int);', message)508 self.TestLint('virtual void Func(int* p);', '')509 self.TestLint('void operator delete(void* x) throw();', '')510 self.TestLint('void Method(char* x) {', '')511 self.TestLint('void Method(char* /*x*/) {', '')512 self.TestLint('void Method(char* x);', '')513 self.TestLint('typedef void (*Method)(int32 x);', '')514 self.TestLint('static void operator delete[](void* x) throw();', '')515 self.TestLint('static void operator delete[](void* /*x*/) throw();', '')516 self.TestLint('X operator++(int);', '')517 self.TestLint('X operator++(int) {', '')518 self.TestLint('X operator--(int);', '')519 self.TestLint('X operator--(int /*unused*/) {', '')520 self.TestLint('MACRO(int);', '')521 self.TestLint('MACRO(func(int));', '')522 self.TestLint('MACRO(arg, func(int));', '')523 self.TestLint('void (*func)(void*);', '')524 self.TestLint('void Func((*func)(void*)) {}', '')525 self.TestLint('template <void Func(void*)> void func();', '')526 self.TestLint('virtual void f(int /*unused*/) {', '')527 self.TestLint('void f(int /*unused*/) override {', '')528 self.TestLint('void f(int /*unused*/) final {', '')529 # Test deprecated casts such as int(d)530 def testDeprecatedCast(self):531 self.TestLint(532 'int a = int(2.2);',533 'Using deprecated casting style. '534 'Use static_cast<int>(...) instead'535 ' [readability/casting] [4]')536 self.TestLint(537 '(char *) "foo"',538 'Using C-style cast. '539 'Use const_cast<char *>(...) instead'540 ' [readability/casting] [4]')541 self.TestLint(542 '(int*)foo',543 'Using C-style cast. '544 'Use reinterpret_cast<int*>(...) instead'545 ' [readability/casting] [4]')546 # Checks for false positives...547 self.TestLint('int a = int();', '') # constructor548 self.TestLint('X::X() : a(int()) {}', '') # default constructor549 self.TestLint('operator bool();', '') # Conversion operator550 self.TestLint('new int64(123);', '') # "new" operator on basic type551 self.TestLint('new int64(123);', '') # "new" operator on basic type552 self.TestLint('using a = bool(int arg);', '') # C++11 alias-declaration553 self.TestLint('x = bit_cast<double(*)[3]>(y);', '') # array of array554 self.TestLint('void F(const char(&src)[N]);', '') # array of references555 # Placement new556 self.TestLint(557 'new(field_ptr) int(field->default_value_enum()->number());',558 '')559 # C++11 function wrappers560 self.TestLint('std::function<int(bool)>', '')561 self.TestLint('std::function<const int(bool)>', '')562 self.TestLint('std::function< int(bool) >', '')563 self.TestLint('mfunction<int(bool)>', '')564 error_collector = ErrorCollector(self.assert_)565 cpplint.ProcessFileData(566 'test.cc', 'cc',567 ['// Copyright 2014 Your Company. All Rights Reserved.',568 'typedef std::function<',569 ' bool(int)> F;',570 ''],571 error_collector)572 self.assertEquals('', error_collector.Results())573 # Return types for function pointers574 self.TestLint('typedef bool(FunctionPointer)();', '')575 self.TestLint('typedef bool(FunctionPointer)(int param);', '')576 self.TestLint('typedef bool(MyClass::*MemberFunctionPointer)();', '')577 self.TestLint('typedef bool(MyClass::* MemberFunctionPointer)();', '')578 self.TestLint('typedef bool(MyClass::*MemberFunctionPointer)() const;', '')579 self.TestLint('void Function(bool(FunctionPointerArg)());', '')580 self.TestLint('void Function(bool(FunctionPointerArg)()) {}', '')581 self.TestLint('typedef set<int64, bool(*)(int64, int64)> SortedIdSet', '')582 self.TestLint(583 'bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *t)) {}',584 '')585 # The second parameter to a gMock method definition is a function signature586 # that often looks like a bad cast but should not picked up by lint.587 def testMockMethod(self):588 self.TestLint(589 'MOCK_METHOD0(method, int());',590 '')591 self.TestLint(592 'MOCK_CONST_METHOD1(method, float(string));',593 '')594 self.TestLint(595 'MOCK_CONST_METHOD2_T(method, double(float, float));',596 '')597 self.TestLint(598 'MOCK_CONST_METHOD1(method, SomeType(int));',599 '')600 error_collector = ErrorCollector(self.assert_)601 cpplint.ProcessFileData('mock.cc', 'cc',602 ['MOCK_METHOD1(method1,',603 ' bool(int));',604 'MOCK_METHOD1(',605 ' method2,',606 ' bool(int));',607 'MOCK_CONST_METHOD2(',608 ' method3, bool(int,',609 ' int));',610 'MOCK_METHOD1(method4, int(bool));',611 'const int kConstant = int(42);'], # true positive612 error_collector)613 self.assertEquals(614 0,615 error_collector.Results().count(616 ('Using deprecated casting style. '617 'Use static_cast<bool>(...) instead '618 '[readability/casting] [4]')))619 self.assertEquals(620 1,621 error_collector.Results().count(622 ('Using deprecated casting style. '623 'Use static_cast<int>(...) instead '624 '[readability/casting] [4]')))625 # Like gMock method definitions, MockCallback instantiations look very similar626 # to bad casts.627 def testMockCallback(self):628 self.TestLint(629 'MockCallback<bool(int)>',630 '')631 self.TestLint(632 'MockCallback<int(float, char)>',633 '')634 # Test false errors that happened with some include file names635 def testIncludeFilenameFalseError(self):636 self.TestLint(637 '#include "foo/long-foo.h"',638 '')639 self.TestLint(640 '#include "foo/sprintf.h"',641 '')642 # Test typedef cases. There was a bug that cpplint misidentified643 # typedef for pointer to function as C-style cast and produced644 # false-positive error messages.645 def testTypedefForPointerToFunction(self):646 self.TestLint(647 'typedef void (*Func)(int x);',648 '')649 self.TestLint(650 'typedef void (*Func)(int *x);',651 '')652 self.TestLint(653 'typedef void Func(int x);',654 '')655 self.TestLint(656 'typedef void Func(int *x);',657 '')658 def testIncludeWhatYouUseNoImplementationFiles(self):659 code = 'std::vector<int> foo;'660 self.assertEquals('Add #include <vector> for vector<>'661 ' [build/include_what_you_use] [4]',662 self.PerformIncludeWhatYouUse(code, 'foo.h'))663 self.assertEquals('',664 self.PerformIncludeWhatYouUse(code, 'foo.cc'))665 def testIncludeWhatYouUse(self):666 self.TestIncludeWhatYouUse(667 """#include <vector>668 std::vector<int> foo;669 """,670 '')671 self.TestIncludeWhatYouUse(672 """#include <map>673 std::pair<int,int> foo;674 """,675 'Add #include <utility> for pair<>'676 ' [build/include_what_you_use] [4]')677 self.TestIncludeWhatYouUse(678 """#include <multimap>679 std::pair<int,int> foo;680 """,681 'Add #include <utility> for pair<>'682 ' [build/include_what_you_use] [4]')683 self.TestIncludeWhatYouUse(684 """#include <hash_map>685 std::pair<int,int> foo;686 """,687 'Add #include <utility> for pair<>'688 ' [build/include_what_you_use] [4]')689 self.TestIncludeWhatYouUse(690 """#include <utility>691 std::pair<int,int> foo;692 """,693 '')694 self.TestIncludeWhatYouUse(695 """#include <vector>696 DECLARE_string(foobar);697 """,698 '')699 self.TestIncludeWhatYouUse(700 """#include <vector>701 DEFINE_string(foobar, "", "");702 """,703 '')704 self.TestIncludeWhatYouUse(705 """#include <vector>706 std::pair<int,int> foo;707 """,708 'Add #include <utility> for pair<>'709 ' [build/include_what_you_use] [4]')710 self.TestIncludeWhatYouUse(711 """#include "base/foobar.h"712 std::vector<int> foo;713 """,714 'Add #include <vector> for vector<>'715 ' [build/include_what_you_use] [4]')716 self.TestIncludeWhatYouUse(717 """#include <vector>718 std::set<int> foo;719 """,720 'Add #include <set> for set<>'721 ' [build/include_what_you_use] [4]')722 self.TestIncludeWhatYouUse(723 """#include "base/foobar.h"724 hash_map<int, int> foobar;725 """,726 'Add #include <hash_map> for hash_map<>'727 ' [build/include_what_you_use] [4]')728 self.TestIncludeWhatYouUse(729 """#include "base/foobar.h"730 bool foobar = std::less<int>(0,1);731 """,732 'Add #include <functional> for less<>'733 ' [build/include_what_you_use] [4]')734 self.TestIncludeWhatYouUse(735 """#include "base/foobar.h"736 bool foobar = min<int>(0,1);737 """,738 'Add #include <algorithm> for min [build/include_what_you_use] [4]')739 self.TestIncludeWhatYouUse(740 'void a(const string &foobar);',741 'Add #include <string> for string [build/include_what_you_use] [4]')742 self.TestIncludeWhatYouUse(743 'void a(const std::string &foobar);',744 'Add #include <string> for string [build/include_what_you_use] [4]')745 self.TestIncludeWhatYouUse(746 'void a(const my::string &foobar);',747 '') # Avoid false positives on strings in other namespaces.748 self.TestIncludeWhatYouUse(749 """#include "base/foobar.h"750 bool foobar = swap(0,1);751 """,752 'Add #include <algorithm> for swap [build/include_what_you_use] [4]')753 self.TestIncludeWhatYouUse(754 """#include "base/foobar.h"755 bool foobar = transform(a.begin(), a.end(), b.start(), Foo);756 """,757 'Add #include <algorithm> for transform '758 '[build/include_what_you_use] [4]')759 self.TestIncludeWhatYouUse(760 """#include "base/foobar.h"761 bool foobar = min_element(a.begin(), a.end());762 """,763 'Add #include <algorithm> for min_element '764 '[build/include_what_you_use] [4]')765 self.TestIncludeWhatYouUse(766 """foo->swap(0,1);767 foo.swap(0,1);768 """,769 '')770 self.TestIncludeWhatYouUse(771 """#include <string>772 void a(const std::multimap<int,string> &foobar);773 """,774 'Add #include <map> for multimap<>'775 ' [build/include_what_you_use] [4]')776 self.TestIncludeWhatYouUse(777 """#include <queue>778 void a(const std::priority_queue<int> &foobar);779 """,780 '')781 self.TestIncludeWhatYouUse(782 """#include <assert.h>783 #include <string>784 #include <vector>785 #include "base/basictypes.h"786 #include "base/port.h"787 vector<string> hajoa;""", '')788 self.TestIncludeWhatYouUse(789 """#include <string>790 int i = numeric_limits<int>::max()791 """,792 'Add #include <limits> for numeric_limits<>'793 ' [build/include_what_you_use] [4]')794 self.TestIncludeWhatYouUse(795 """#include <limits>796 int i = numeric_limits<int>::max()797 """,798 '')799 # Test the UpdateIncludeState code path.800 mock_header_contents = ['#include "blah/foo.h"', '#include "blah/bar.h"']801 message = self.PerformIncludeWhatYouUse(802 '#include "blah/a.h"',803 filename='blah/a.cc',804 io=MockIo(mock_header_contents))805 self.assertEquals(message, '')806 mock_header_contents = ['#include <set>']807 message = self.PerformIncludeWhatYouUse(808 """#include "blah/a.h"809 std::set<int> foo;""",810 filename='blah/a.cc',811 io=MockIo(mock_header_contents))812 self.assertEquals(message, '')813 # Make sure we can find the correct header file if the cc file seems to be814 # a temporary file generated by Emacs's flymake.815 mock_header_contents = ['']816 message = self.PerformIncludeWhatYouUse(817 """#include "blah/a.h"818 std::set<int> foo;""",819 filename='blah/a_flymake.cc',820 io=MockIo(mock_header_contents))821 self.assertEquals(message, 'Add #include <set> for set<> '822 '[build/include_what_you_use] [4]')823 # If there's just a cc and the header can't be found then it's ok.824 message = self.PerformIncludeWhatYouUse(825 """#include "blah/a.h"826 std::set<int> foo;""",827 filename='blah/a.cc')828 self.assertEquals(message, '')829 # Make sure we find the headers with relative paths.830 mock_header_contents = ['']831 message = self.PerformIncludeWhatYouUse(832 """#include "%s/a.h"833 std::set<int> foo;""" % os.path.basename(os.getcwd()),834 filename='a.cc',835 io=MockIo(mock_header_contents))836 self.assertEquals(message, 'Add #include <set> for set<> '837 '[build/include_what_you_use] [4]')838 def testFilesBelongToSameModule(self):839 f = cpplint.FilesBelongToSameModule840 self.assertEquals((True, ''), f('a.cc', 'a.h'))841 self.assertEquals((True, ''), f('base/google.cc', 'base/google.h'))842 self.assertEquals((True, ''), f('base/google_test.cc', 'base/google.h'))843 self.assertEquals((True, ''),844 f('base/google_unittest.cc', 'base/google.h'))845 self.assertEquals((True, ''),846 f('base/internal/google_unittest.cc',847 'base/public/google.h'))848 self.assertEquals((True, 'xxx/yyy/'),849 f('xxx/yyy/base/internal/google_unittest.cc',850 'base/public/google.h'))851 self.assertEquals((True, 'xxx/yyy/'),852 f('xxx/yyy/base/google_unittest.cc',853 'base/public/google.h'))854 self.assertEquals((True, ''),855 f('base/google_unittest.cc', 'base/google-inl.h'))856 self.assertEquals((True, '/home/build/google3/'),857 f('/home/build/google3/base/google.cc', 'base/google.h'))858 self.assertEquals((False, ''),859 f('/home/build/google3/base/google.cc', 'basu/google.h'))860 self.assertEquals((False, ''), f('a.cc', 'b.h'))861 def testCleanseLine(self):862 self.assertEquals('int foo = 0;',863 cpplint.CleanseComments('int foo = 0; // danger!'))864 self.assertEquals('int o = 0;',865 cpplint.CleanseComments('int /* foo */ o = 0;'))866 self.assertEquals('foo(int a, int b);',867 cpplint.CleanseComments('foo(int a /* abc */, int b);'))868 self.assertEqual('f(a, b);',869 cpplint.CleanseComments('f(a, /* name */ b);'))870 self.assertEqual('f(a, b);',871 cpplint.CleanseComments('f(a /* name */, b);'))872 self.assertEqual('f(a, b);',873 cpplint.CleanseComments('f(a, /* name */b);'))874 self.assertEqual('f(a, b, c);',875 cpplint.CleanseComments('f(a, /**/b, /**/c);'))876 self.assertEqual('f(a, b, c);',877 cpplint.CleanseComments('f(a, /**/b/**/, c);'))878 def testRawStrings(self):879 self.TestMultiLineLint(880 """881 void Func() {882 static const char kString[] = R"(883 #endif <- invalid preprocessor should be ignored884 */ <- invalid comment should be ignored too885 )";886 }""",887 '')888 self.TestMultiLineLint(889 """890 void Func() {891 string s = R"TrueDelimiter(892 )"893 )FalseDelimiter"894 )TrueDelimiter";895 }""",896 '')897 self.TestMultiLineLint(898 """899 void Func() {900 char char kString[] = R"( ";" )";901 }""",902 '')903 self.TestMultiLineLint(904 """905 static const char kRawString[] = R"(906 \tstatic const int kLineWithTab = 1;907 static const int kLineWithTrailingWhiteSpace = 1;\x20908 void WeirdNumberOfSpacesAtLineStart() {909 string x;910 x += StrCat("Use StrAppend instead");911 }912 void BlankLineAtEndOfBlock() {913 // TODO incorrectly formatted914 //Badly formatted comment915 }916 )";""",917 '')918 self.TestMultiLineLint(919 """920 void Func() {921 string s = StrCat(R"TrueDelimiter(922 )"923 )FalseDelimiter"924 )TrueDelimiter", R"TrueDelimiter2(925 )"926 )FalseDelimiter2"927 )TrueDelimiter2");928 }""",929 '')930 self.TestMultiLineLint(931 """932 static SomeStruct kData = {933 {0, R"(line1934 line2935 )"}936 };""",937 '')938 def testMultiLineComments(self):939 # missing explicit is bad940 self.TestMultiLineLint(941 r"""int a = 0;942 /* multi-liner943 class Foo {944 Foo(int f); // should cause a lint warning in code945 }946 */ """,947 '')948 self.TestMultiLineLint(949 r"""/* int a = 0; multi-liner950 static const int b = 0;""",951 'Could not find end of multi-line comment'952 ' [readability/multiline_comment] [5]')953 self.TestMultiLineLint(r""" /* multi-line comment""",954 'Could not find end of multi-line comment'955 ' [readability/multiline_comment] [5]')956 self.TestMultiLineLint(r""" // /* comment, but not multi-line""", '')957 self.TestMultiLineLint(r"""/**********958 */""", '')959 self.TestMultiLineLint(r"""/**960 * Doxygen comment961 */""",962 '')963 self.TestMultiLineLint(r"""/*!964 * Doxygen comment965 */""",966 '')967 def testMultilineStrings(self):968 multiline_string_error_message = (969 'Multi-line string ("...") found. This lint script doesn\'t '970 'do well with such strings, and may give bogus warnings. '971 'Use C++11 raw strings or concatenation instead.'972 ' [readability/multiline_string] [5]')973 file_path = 'mydir/foo.cc'974 error_collector = ErrorCollector(self.assert_)975 cpplint.ProcessFileData(file_path, 'cc',976 ['const char* str = "This is a\\',977 ' multiline string.";'],978 error_collector)979 self.assertEquals(980 2, # One per line.981 error_collector.ResultList().count(multiline_string_error_message))982 # Test non-explicit single-argument constructors983 def testExplicitSingleArgumentConstructors(self):984 old_verbose_level = cpplint._cpplint_state.verbose_level985 cpplint._cpplint_state.verbose_level = 0986 try:987 # missing explicit is bad988 self.TestMultiLineLint(989 """990 class Foo {991 Foo(int f);992 };""",993 'Single-parameter constructors should be marked explicit.'994 ' [runtime/explicit] [5]')995 # missing explicit is bad, even with whitespace996 self.TestMultiLineLint(997 """998 class Foo {999 Foo (int f);1000 };""",1001 ['Extra space before ( in function call [whitespace/parens] [4]',1002 'Single-parameter constructors should be marked explicit.'1003 ' [runtime/explicit] [5]'])1004 # missing explicit, with distracting comment, is still bad1005 self.TestMultiLineLint(1006 """1007 class Foo {1008 Foo(int f); // simpler than Foo(blargh, blarg)1009 };""",1010 'Single-parameter constructors should be marked explicit.'1011 ' [runtime/explicit] [5]')1012 # missing explicit, with qualified classname1013 self.TestMultiLineLint(1014 """1015 class Qualifier::AnotherOne::Foo {1016 Foo(int f);1017 };""",1018 'Single-parameter constructors should be marked explicit.'1019 ' [runtime/explicit] [5]')1020 # missing explicit for inline constructors is bad as well1021 self.TestMultiLineLint(1022 """1023 class Foo {1024 inline Foo(int f);1025 };""",1026 'Single-parameter constructors should be marked explicit.'1027 ' [runtime/explicit] [5]')1028 # structs are caught as well.1029 self.TestMultiLineLint(1030 """1031 struct Foo {1032 Foo(int f);1033 };""",1034 'Single-parameter constructors should be marked explicit.'1035 ' [runtime/explicit] [5]')1036 # Templatized classes are caught as well.1037 self.TestMultiLineLint(1038 """1039 template<typename T> class Foo {1040 Foo(int f);1041 };""",1042 'Single-parameter constructors should be marked explicit.'1043 ' [runtime/explicit] [5]')1044 # inline case for templatized classes.1045 self.TestMultiLineLint(1046 """1047 template<typename T> class Foo {1048 inline Foo(int f);1049 };""",1050 'Single-parameter constructors should be marked explicit.'1051 ' [runtime/explicit] [5]')1052 # constructors with a default argument should still be marked explicit1053 self.TestMultiLineLint(1054 """1055 class Foo {1056 Foo(int f = 0);1057 };""",1058 'Constructors callable with one argument should be marked explicit.'1059 ' [runtime/explicit] [5]')1060 # multi-argument constructors with all but one default argument should be1061 # marked explicit1062 self.TestMultiLineLint(1063 """1064 class Foo {1065 Foo(int f, int g = 0);1066 };""",1067 'Constructors callable with one argument should be marked explicit.'1068 ' [runtime/explicit] [5]')1069 # multi-argument constructors with all default arguments should be marked1070 # explicit1071 self.TestMultiLineLint(1072 """1073 class Foo {1074 Foo(int f = 0, int g = 0);1075 };""",1076 'Constructors callable with one argument should be marked explicit.'1077 ' [runtime/explicit] [5]')1078 # explicit no-argument constructors are bad1079 self.TestMultiLineLint(1080 """1081 class Foo {1082 explicit Foo();1083 };""",1084 'Zero-parameter constructors should not be marked explicit.'1085 ' [runtime/explicit] [5]')1086 # void constructors are considered no-argument1087 self.TestMultiLineLint(1088 """1089 class Foo {1090 explicit Foo(void);1091 };""",1092 'Zero-parameter constructors should not be marked explicit.'1093 ' [runtime/explicit] [5]')1094 # Warn explicit multi-argument constructors at lowest severity1095 self.TestMultiLineLint(1096 """1097 class Foo {1098 explicit Foo(int f, int g);1099 };""",1100 'Constructors that require multiple arguments '1101 'should not be marked explicit. [runtime/explicit] [0]')1102 # but explicit multi-argument constructors with only one non-default1103 # argument are OK1104 self.TestMultiLineLint(1105 """1106 class Foo {1107 explicit Foo(int f, int g = 0);1108 };""",1109 '')1110 # single-argument constructors that take a function that takes multiple1111 # arguments should be explicit1112 self.TestMultiLineLint(1113 """1114 class Foo {1115 Foo(void (*f)(int f, int g));1116 };""",1117 'Single-parameter constructors should be marked explicit.'1118 ' [runtime/explicit] [5]')1119 # single-argument constructors that take a single template argument with1120 # multiple parameters should be explicit1121 self.TestMultiLineLint(1122 """1123 template <typename T, typename S>1124 class Foo {1125 Foo(Bar<T, S> b);1126 };""",1127 'Single-parameter constructors should be marked explicit.'1128 ' [runtime/explicit] [5]')1129 # but copy constructors that take multiple template parameters are OK1130 self.TestMultiLineLint(1131 """1132 template <typename T, S>1133 class Foo {1134 Foo(Foo<T, S>& f);1135 };""",1136 '')1137 # proper style is okay1138 self.TestMultiLineLint(1139 """1140 class Foo {1141 explicit Foo(int f);1142 };""",1143 '')1144 # two argument constructor is okay1145 self.TestMultiLineLint(1146 """1147 class Foo {1148 Foo(int f, int b);1149 };""",1150 '')1151 # two argument constructor, across two lines, is okay1152 self.TestMultiLineLint(1153 """1154 class Foo {1155 Foo(int f,1156 int b);1157 };""",1158 '')1159 # non-constructor (but similar name), is okay1160 self.TestMultiLineLint(1161 """1162 class Foo {1163 aFoo(int f);1164 };""",1165 '')1166 # constructor with void argument is okay1167 self.TestMultiLineLint(1168 """1169 class Foo {1170 Foo(void);1171 };""",1172 '')1173 # single argument method is okay1174 self.TestMultiLineLint(1175 """1176 class Foo {1177 Bar(int b);1178 };""",1179 '')1180 # comments should be ignored1181 self.TestMultiLineLint(1182 """1183 class Foo {1184 // Foo(int f);1185 };""",1186 '')1187 # single argument function following class definition is okay1188 # (okay, it's not actually valid, but we don't want a false positive)1189 self.TestMultiLineLint(1190 """1191 class Foo {1192 Foo(int f, int b);1193 };1194 Foo(int f);""",1195 '')1196 # single argument function is okay1197 self.TestMultiLineLint(1198 """static Foo(int f);""",1199 '')1200 # single argument copy constructor is okay.1201 self.TestMultiLineLint(1202 """1203 class Foo {1204 Foo(const Foo&);1205 };""",1206 '')1207 self.TestMultiLineLint(1208 """1209 class Foo {1210 Foo(Foo const&);1211 };""",1212 '')1213 self.TestMultiLineLint(1214 """1215 class Foo {1216 Foo(Foo&);1217 };""",1218 '')1219 # templatized copy constructor is okay.1220 self.TestMultiLineLint(1221 """1222 template<typename T> class Foo {1223 Foo(const Foo<T>&);1224 };""",1225 '')1226 # Special case for std::initializer_list1227 self.TestMultiLineLint(1228 """1229 class Foo {1230 Foo(std::initializer_list<T> &arg) {}1231 };""",1232 '')1233 # Anything goes inside an assembly block1234 error_collector = ErrorCollector(self.assert_)1235 cpplint.ProcessFileData('foo.cc', 'cc',1236 ['void Func() {',1237 ' __asm__ (',1238 ' "hlt"',1239 ' );',1240 ' asm {',1241 ' movdqa [edx + 32], xmm2',1242 ' }',1243 '}'],1244 error_collector)1245 self.assertEquals(1246 0,1247 error_collector.ResultList().count(1248 'Extra space before ( in function call [whitespace/parens] [4]'))1249 self.assertEquals(1250 0,1251 error_collector.ResultList().count(1252 'Closing ) should be moved to the previous line '1253 '[whitespace/parens] [2]'))1254 self.assertEquals(1255 0,1256 error_collector.ResultList().count(1257 'Extra space before [ [whitespace/braces] [5]'))1258 finally:1259 cpplint._cpplint_state.verbose_level = old_verbose_level1260 def testSlashStarCommentOnSingleLine(self):1261 self.TestMultiLineLint(1262 """/* static */ Foo(int f);""",1263 '')1264 self.TestMultiLineLint(1265 """/*/ static */ Foo(int f);""",1266 '')1267 self.TestMultiLineLint(1268 """/*/ static Foo(int f);""",1269 'Could not find end of multi-line comment'1270 ' [readability/multiline_comment] [5]')1271 self.TestMultiLineLint(1272 """ /*/ static Foo(int f);""",1273 'Could not find end of multi-line comment'1274 ' [readability/multiline_comment] [5]')1275 self.TestMultiLineLint(1276 """ /**/ static Foo(int f);""",1277 '')1278 # Test suspicious usage of "if" like this:1279 # if (a == b) {1280 # DoSomething();1281 # } if (a == c) { // Should be "else if".1282 # DoSomething(); // This gets called twice if a == b && a == c.1283 # }1284 def testSuspiciousUsageOfIf(self):1285 self.TestLint(1286 ' if (a == b) {',1287 '')1288 self.TestLint(1289 ' } if (a == b) {',1290 'Did you mean "else if"? If not, start a new line for "if".'1291 ' [readability/braces] [4]')1292 # Test suspicious usage of memset. Specifically, a 01293 # as the final argument is almost certainly an error.1294 def testSuspiciousUsageOfMemset(self):1295 # Normal use is okay.1296 self.TestLint(1297 ' memset(buf, 0, sizeof(buf))',1298 '')1299 # A 0 as the final argument is almost certainly an error.1300 self.TestLint(1301 ' memset(buf, sizeof(buf), 0)',1302 'Did you mean "memset(buf, 0, sizeof(buf))"?'1303 ' [runtime/memset] [4]')1304 self.TestLint(1305 ' memset(buf, xsize * ysize, 0)',1306 'Did you mean "memset(buf, 0, xsize * ysize)"?'1307 ' [runtime/memset] [4]')1308 # There is legitimate test code that uses this form.1309 # This is okay since the second argument is a literal.1310 self.TestLint(1311 " memset(buf, 'y', 0)",1312 '')1313 self.TestLint(1314 ' memset(buf, 4, 0)',1315 '')1316 self.TestLint(1317 ' memset(buf, -1, 0)',1318 '')1319 self.TestLint(1320 ' memset(buf, 0xF1, 0)',1321 '')1322 self.TestLint(1323 ' memset(buf, 0xcd, 0)',1324 '')1325 def testRedundantVirtual(self):1326 self.TestLint('virtual void F()', '')1327 self.TestLint('virtual void F();', '')1328 self.TestLint('virtual void F() {}', '')1329 message_template = ('"%s" is redundant since function is already '1330 'declared as "%s" [readability/inheritance] [4]')1331 for virt_specifier in ['override', 'final']:1332 error_message = message_template % ('virtual', virt_specifier)1333 self.TestLint('virtual int F() %s' % virt_specifier, error_message)1334 self.TestLint('virtual int F() %s;' % virt_specifier, error_message)1335 self.TestLint('virtual int F() %s {' % virt_specifier, error_message)1336 error_collector = ErrorCollector(self.assert_)1337 cpplint.ProcessFileData(1338 'foo.cc', 'cc',1339 ['// Copyright 2014 Your Company.',1340 'virtual void F(int a,',1341 ' int b) ' + virt_specifier + ';',1342 'virtual void F(int a,',1343 ' int b) LOCKS_EXCLUDED(lock) ' + virt_specifier + ';',1344 'virtual void F(int a,',1345 ' int b)',1346 ' LOCKS_EXCLUDED(lock) ' + virt_specifier + ';',1347 ''],1348 error_collector)1349 self.assertEquals(1350 [error_message, error_message, error_message],1351 error_collector.Results())1352 error_message = message_template % ('override', 'final')1353 self.TestLint('int F() override final', error_message)1354 self.TestLint('int F() override final;', error_message)1355 self.TestLint('int F() override final {}', error_message)1356 self.TestLint('int F() final override', error_message)1357 self.TestLint('int F() final override;', error_message)1358 self.TestLint('int F() final override {}', error_message)1359 error_collector = ErrorCollector(self.assert_)1360 cpplint.ProcessFileData(1361 'foo.cc', 'cc',1362 ['// Copyright 2014 Your Company.',1363 'struct A : virtual B {',1364 ' ~A() override;'1365 '};',1366 'class C',1367 ' : public D,',1368 ' public virtual E {',1369 ' void Func() override;',1370 '}',1371 ''],1372 error_collector)1373 self.assertEquals('', error_collector.Results())1374 self.TestLint('void Finalize(AnnotationProto *final) override;', '')1375 def testCheckDeprecated(self):1376 self.TestLanguageRulesCheck('foo_test.cc', '#include <iostream>', '')1377 self.TestLanguageRulesCheck('foo_unittest.cc', '#include <iostream>', '')1378 def testCheckPosixThreading(self):1379 self.TestLint('var = sctime_r()', '')1380 self.TestLint('var = strtok_r()', '')1381 self.TestLint('var = strtok_r(foo, ba, r)', '')1382 self.TestLint('var = brand()', '')1383 self.TestLint('_rand()', '')1384 self.TestLint('.rand()', '')1385 self.TestLint('->rand()', '')1386 self.TestLint('ACMRandom rand(seed)', '')1387 self.TestLint('ISAACRandom rand()', '')1388 self.TestLint('var = rand()',1389 'Consider using rand_r(...) instead of rand(...)'1390 ' for improved thread safety.'1391 ' [runtime/threadsafe_fn] [2]')1392 self.TestLint('var = strtok(str, delim)',1393 'Consider using strtok_r(...) '1394 'instead of strtok(...)'1395 ' for improved thread safety.'1396 ' [runtime/threadsafe_fn] [2]')1397 def testVlogMisuse(self):1398 self.TestLint('VLOG(1)', '')1399 self.TestLint('VLOG(99)', '')1400 self.TestLint('LOG(ERROR)', '')1401 self.TestLint('LOG(INFO)', '')1402 self.TestLint('LOG(WARNING)', '')1403 self.TestLint('LOG(FATAL)', '')1404 self.TestLint('LOG(DFATAL)', '')1405 self.TestLint('VLOG(SOMETHINGWEIRD)', '')1406 self.TestLint('MYOWNVLOG(ERROR)', '')1407 errmsg = ('VLOG() should be used with numeric verbosity level. '1408 'Use LOG() if you want symbolic severity levels.'1409 ' [runtime/vlog] [5]')1410 self.TestLint('VLOG(ERROR)', errmsg)1411 self.TestLint('VLOG(INFO)', errmsg)1412 self.TestLint('VLOG(WARNING)', errmsg)1413 self.TestLint('VLOG(FATAL)', errmsg)1414 self.TestLint('VLOG(DFATAL)', errmsg)1415 self.TestLint(' VLOG(ERROR)', errmsg)1416 self.TestLint(' VLOG(INFO)', errmsg)1417 self.TestLint(' VLOG(WARNING)', errmsg)1418 self.TestLint(' VLOG(FATAL)', errmsg)1419 self.TestLint(' VLOG(DFATAL)', errmsg)1420 # Test potential format string bugs like printf(foo).1421 def testFormatStrings(self):1422 self.TestLint('printf("foo")', '')1423 self.TestLint('printf("foo: %s", foo)', '')1424 self.TestLint('DocidForPrintf(docid)', '') # Should not trigger.1425 self.TestLint('printf(format, value)', '') # Should not trigger.1426 self.TestLint('printf(__VA_ARGS__)', '') # Should not trigger.1427 self.TestLint('printf(format.c_str(), value)', '') # Should not trigger.1428 self.TestLint('printf(format(index).c_str(), value)', '')1429 self.TestLint(1430 'printf(foo)',1431 'Potential format string bug. Do printf("%s", foo) instead.'1432 ' [runtime/printf] [4]')1433 self.TestLint(1434 'printf(foo.c_str())',1435 'Potential format string bug. '1436 'Do printf("%s", foo.c_str()) instead.'1437 ' [runtime/printf] [4]')1438 self.TestLint(1439 'printf(foo->c_str())',1440 'Potential format string bug. '1441 'Do printf("%s", foo->c_str()) instead.'1442 ' [runtime/printf] [4]')1443 self.TestLint(1444 'StringPrintf(foo)',1445 'Potential format string bug. Do StringPrintf("%s", foo) instead.'1446 ''1447 ' [runtime/printf] [4]')1448 # Test disallowed use of operator& and other operators.1449 def testIllegalOperatorOverloading(self):1450 errmsg = ('Unary operator& is dangerous. Do not use it.'1451 ' [runtime/operator] [4]')1452 self.TestLint('void operator=(const Myclass&)', '')1453 self.TestLint('void operator&(int a, int b)', '') # binary operator& ok1454 self.TestLint('void operator&() { }', errmsg)1455 self.TestLint('void operator & ( ) { }',1456 ['Extra space after ( [whitespace/parens] [2]', errmsg])1457 # const string reference members are dangerous..1458 def testConstStringReferenceMembers(self):1459 errmsg = ('const string& members are dangerous. It is much better to use '1460 'alternatives, such as pointers or simple constants.'1461 ' [runtime/member_string_references] [2]')1462 members_declarations = ['const string& church',1463 'const string &turing',1464 'const string & godel']1465 # TODO(unknown): Enable also these tests if and when we ever1466 # decide to check for arbitrary member references.1467 # "const Turing & a",1468 # "const Church& a",1469 # "const vector<int>& a",1470 # "const Kurt::Godel & godel",1471 # "const Kazimierz::Kuratowski& kk" ]1472 # The Good.1473 self.TestLint('void f(const string&)', '')1474 self.TestLint('const string& f(const string& a, const string& b)', '')1475 self.TestLint('typedef const string& A;', '')1476 for decl in members_declarations:1477 self.TestLint(decl + ' = b;', '')1478 self.TestLint(decl + ' =', '')1479 # The Bad.1480 for decl in members_declarations:1481 self.TestLint(decl + ';', errmsg)1482 # Variable-length arrays are not permitted.1483 def testVariableLengthArrayDetection(self):1484 errmsg = ('Do not use variable-length arrays. Use an appropriately named '1485 "('k' followed by CamelCase) compile-time constant for the size."1486 ' [runtime/arrays] [1]')1487 self.TestLint('int a[any_old_variable];', errmsg)1488 self.TestLint('int doublesize[some_var * 2];', errmsg)1489 self.TestLint('int a[afunction()];', errmsg)1490 self.TestLint('int a[function(kMaxFooBars)];', errmsg)1491 self.TestLint('bool a_list[items_->size()];', errmsg)1492 self.TestLint('namespace::Type buffer[len+1];', errmsg)1493 self.TestLint('int a[64];', '')1494 self.TestLint('int a[0xFF];', '')1495 self.TestLint('int first[256], second[256];', '')1496 self.TestLint('int array_name[kCompileTimeConstant];', '')1497 self.TestLint('char buf[somenamespace::kBufSize];', '')1498 self.TestLint('int array_name[ALL_CAPS];', '')1499 self.TestLint('AClass array1[foo::bar::ALL_CAPS];', '')1500 self.TestLint('int a[kMaxStrLen + 1];', '')1501 self.TestLint('int a[sizeof(foo)];', '')1502 self.TestLint('int a[sizeof(*foo)];', '')1503 self.TestLint('int a[sizeof foo];', '')1504 self.TestLint('int a[sizeof(struct Foo)];', '')1505 self.TestLint('int a[128 - sizeof(const bar)];', '')1506 self.TestLint('int a[(sizeof(foo) * 4)];', '')1507 self.TestLint('int a[(arraysize(fixed_size_array)/2) << 1];', '')1508 self.TestLint('delete a[some_var];', '')1509 self.TestLint('return a[some_var];', '')1510 # DISALLOW_COPY_AND_ASSIGN and DISALLOW_IMPLICIT_CONSTRUCTORS should be at1511 # end of class if present.1512 def testDisallowMacrosAtEnd(self):1513 for macro_name in (1514 'DISALLOW_COPY_AND_ASSIGN',1515 'DISALLOW_IMPLICIT_CONSTRUCTORS'):1516 error_collector = ErrorCollector(self.assert_)1517 cpplint.ProcessFileData(1518 'foo.cc', 'cc',1519 ['// Copyright 2014 Your Company.',1520 'class SomeClass {',1521 ' private:',1522 ' %s(SomeClass);' % macro_name,1523 ' int member_;',1524 '};',1525 ''],1526 error_collector)1527 self.assertEquals(1528 ('%s should be the last thing in the class' % macro_name) +1529 ' [readability/constructors] [3]',1530 error_collector.Results())1531 error_collector = ErrorCollector(self.assert_)1532 cpplint.ProcessFileData(1533 'foo.cc', 'cc',1534 ['// Copyright 2014 Your Company.',1535 'class OuterClass {',1536 ' private:',1537 ' struct InnerClass {',1538 ' private:',1539 ' %s(InnerClass);' % macro_name,1540 ' int member;',1541 ' };',1542 '};',1543 ''],1544 error_collector)1545 self.assertEquals(1546 ('%s should be the last thing in the class' % macro_name) +1547 ' [readability/constructors] [3]',1548 error_collector.Results())1549 error_collector = ErrorCollector(self.assert_)1550 cpplint.ProcessFileData(1551 'foo.cc', 'cc',1552 ['// Copyright 2014 Your Company.',1553 'class OuterClass1 {',1554 ' private:',1555 ' struct InnerClass1 {',1556 ' private:',1557 ' %s(InnerClass1);' % macro_name,1558 ' };',1559 ' %s(OuterClass1);' % macro_name,1560 '};',1561 'struct OuterClass2 {',1562 ' private:',1563 ' class InnerClass2 {',1564 ' private:',1565 ' %s(InnerClass2);' % macro_name,1566 ' // comment',1567 ' };',1568 '',1569 ' %s(OuterClass2);' % macro_name,1570 '',1571 ' // comment',1572 '};',1573 'void Func() {',1574 ' struct LocalClass {',1575 ' private:',1576 ' %s(LocalClass);' % macro_name,1577 ' } variable;',1578 '}',1579 ''],1580 error_collector)1581 self.assertEquals('', error_collector.Results())1582 # DISALLOW* macros should be in the private: section.1583 def testMisplacedDisallowMacros(self):1584 for macro_name in (1585 'DISALLOW_COPY_AND_ASSIGN',1586 'DISALLOW_IMPLICIT_CONSTRUCTORS'):1587 self.TestMultiLineLint(1588 """1589 class A {'1590 public:1591 %s(A);1592 };""" % macro_name,1593 ('%s must be in the private: section' % macro_name) +1594 ' [readability/constructors] [3]')1595 self.TestMultiLineLint(1596 """1597 struct B {'1598 %s(B);1599 };""" % macro_name,1600 ('%s must be in the private: section' % macro_name) +1601 ' [readability/constructors] [3]')1602 self.TestMultiLineLint(1603 """1604 class Outer1 {'1605 private:1606 struct Inner1 {1607 %s(Inner1);1608 };1609 %s(Outer1);1610 };""" % (macro_name, macro_name),1611 ('%s must be in the private: section' % macro_name) +1612 ' [readability/constructors] [3]')1613 self.TestMultiLineLint(1614 """1615 class Outer2 {'1616 private:1617 class Inner2 {1618 %s(Inner2);1619 };1620 %s(Outer2);1621 };""" % (macro_name, macro_name),1622 '')1623 # Extra checks to make sure that nested classes are handled1624 # correctly. Use different macros for inner and outer classes so1625 # that we can tell the error messages apart.1626 self.TestMultiLineLint(1627 """1628 class Outer3 {1629 struct Inner3 {1630 DISALLOW_COPY_AND_ASSIGN(Inner3);1631 };1632 DISALLOW_IMPLICIT_CONSTRUCTORS(Outer3);1633 };""",1634 ('DISALLOW_COPY_AND_ASSIGN must be in the private: section'1635 ' [readability/constructors] [3]'))1636 self.TestMultiLineLint(1637 """1638 struct Outer4 {1639 class Inner4 {1640 DISALLOW_COPY_AND_ASSIGN(Inner4);1641 };1642 DISALLOW_IMPLICIT_CONSTRUCTORS(Outer4);1643 };""",1644 ('DISALLOW_IMPLICIT_CONSTRUCTORS must be in the private: section'1645 ' [readability/constructors] [3]'))1646 # Brace usage1647 def testBraces(self):1648 # Braces shouldn't be followed by a ; unless they're defining a struct1649 # or initializing an array1650 self.TestLint('int a[3] = { 1, 2, 3 };', '')1651 self.TestLint(1652 """const int foo[] =1653 {1, 2, 3 };""",1654 '')1655 # For single line, unmatched '}' with a ';' is ignored (not enough context)1656 self.TestMultiLineLint(1657 """int a[3] = { 1,1658 2,1659 3 };""",1660 '')1661 self.TestMultiLineLint(1662 """int a[2][3] = { { 1, 2 },1663 { 3, 4 } };""",1664 '')1665 self.TestMultiLineLint(1666 """int a[2][3] =1667 { { 1, 2 },1668 { 3, 4 } };""",1669 '')1670 # CHECK/EXPECT_TRUE/EXPECT_FALSE replacements1671 def testCheckCheck(self):1672 self.TestLint('CHECK(x == 42);',1673 'Consider using CHECK_EQ instead of CHECK(a == b)'1674 ' [readability/check] [2]')1675 self.TestLint('CHECK(x != 42);',1676 'Consider using CHECK_NE instead of CHECK(a != b)'1677 ' [readability/check] [2]')1678 self.TestLint('CHECK(x >= 42);',1679 'Consider using CHECK_GE instead of CHECK(a >= b)'1680 ' [readability/check] [2]')1681 self.TestLint('CHECK(x > 42);',1682 'Consider using CHECK_GT instead of CHECK(a > b)'1683 ' [readability/check] [2]')1684 self.TestLint('CHECK(x <= 42);',1685 'Consider using CHECK_LE instead of CHECK(a <= b)'1686 ' [readability/check] [2]')1687 self.TestLint('CHECK(x < 42);',1688 'Consider using CHECK_LT instead of CHECK(a < b)'1689 ' [readability/check] [2]')1690 self.TestLint('DCHECK(x == 42);',1691 'Consider using DCHECK_EQ instead of DCHECK(a == b)'1692 ' [readability/check] [2]')1693 self.TestLint('DCHECK(x != 42);',1694 'Consider using DCHECK_NE instead of DCHECK(a != b)'1695 ' [readability/check] [2]')1696 self.TestLint('DCHECK(x >= 42);',1697 'Consider using DCHECK_GE instead of DCHECK(a >= b)'1698 ' [readability/check] [2]')1699 self.TestLint('DCHECK(x > 42);',1700 'Consider using DCHECK_GT instead of DCHECK(a > b)'1701 ' [readability/check] [2]')1702 self.TestLint('DCHECK(x <= 42);',1703 'Consider using DCHECK_LE instead of DCHECK(a <= b)'1704 ' [readability/check] [2]')1705 self.TestLint('DCHECK(x < 42);',1706 'Consider using DCHECK_LT instead of DCHECK(a < b)'1707 ' [readability/check] [2]')1708 self.TestLint(1709 'EXPECT_TRUE("42" == x);',1710 'Consider using EXPECT_EQ instead of EXPECT_TRUE(a == b)'1711 ' [readability/check] [2]')1712 self.TestLint(1713 'EXPECT_TRUE("42" != x);',1714 'Consider using EXPECT_NE instead of EXPECT_TRUE(a != b)'1715 ' [readability/check] [2]')1716 self.TestLint(1717 'EXPECT_TRUE(+42 >= x);',1718 'Consider using EXPECT_GE instead of EXPECT_TRUE(a >= b)'1719 ' [readability/check] [2]')1720 self.TestLint(1721 'EXPECT_TRUE_M(-42 > x);',1722 'Consider using EXPECT_GT_M instead of EXPECT_TRUE_M(a > b)'1723 ' [readability/check] [2]')1724 self.TestLint(1725 'EXPECT_TRUE_M(42U <= x);',1726 'Consider using EXPECT_LE_M instead of EXPECT_TRUE_M(a <= b)'1727 ' [readability/check] [2]')1728 self.TestLint(1729 'EXPECT_TRUE_M(42L < x);',1730 'Consider using EXPECT_LT_M instead of EXPECT_TRUE_M(a < b)'1731 ' [readability/check] [2]')1732 self.TestLint(1733 'EXPECT_FALSE(x == 42);',1734 'Consider using EXPECT_NE instead of EXPECT_FALSE(a == b)'1735 ' [readability/check] [2]')1736 self.TestLint(1737 'EXPECT_FALSE(x != 42);',1738 'Consider using EXPECT_EQ instead of EXPECT_FALSE(a != b)'1739 ' [readability/check] [2]')1740 self.TestLint(1741 'EXPECT_FALSE(x >= 42);',1742 'Consider using EXPECT_LT instead of EXPECT_FALSE(a >= b)'1743 ' [readability/check] [2]')1744 self.TestLint(1745 'ASSERT_FALSE(x > 42);',1746 'Consider using ASSERT_LE instead of ASSERT_FALSE(a > b)'1747 ' [readability/check] [2]')1748 self.TestLint(1749 'ASSERT_FALSE(x <= 42);',1750 'Consider using ASSERT_GT instead of ASSERT_FALSE(a <= b)'1751 ' [readability/check] [2]')1752 self.TestLint(1753 'ASSERT_FALSE_M(x < 42);',1754 'Consider using ASSERT_GE_M instead of ASSERT_FALSE_M(a < b)'1755 ' [readability/check] [2]')1756 self.TestLint('CHECK(x<42);',1757 ['Missing spaces around <'1758 ' [whitespace/operators] [3]',1759 'Consider using CHECK_LT instead of CHECK(a < b)'1760 ' [readability/check] [2]'])1761 self.TestLint('CHECK(x>42);',1762 ['Missing spaces around >'1763 ' [whitespace/operators] [3]',1764 'Consider using CHECK_GT instead of CHECK(a > b)'1765 ' [readability/check] [2]'])1766 self.TestLint('using some::namespace::operator<<;', '')1767 self.TestLint('using some::namespace::operator>>;', '')1768 self.TestLint('CHECK(x->y == 42);',1769 'Consider using CHECK_EQ instead of CHECK(a == b)'1770 ' [readability/check] [2]')1771 self.TestLint(1772 ' EXPECT_TRUE(42 < x); // Random comment.',1773 'Consider using EXPECT_LT instead of EXPECT_TRUE(a < b)'1774 ' [readability/check] [2]')1775 self.TestLint(1776 'EXPECT_TRUE( 42 < x );',1777 ['Extra space after ( in function call'1778 ' [whitespace/parens] [4]',1779 'Extra space before ) [whitespace/parens] [2]',1780 'Consider using EXPECT_LT instead of EXPECT_TRUE(a < b)'1781 ' [readability/check] [2]'])1782 self.TestLint('CHECK(4\'2 == x);',1783 'Consider using CHECK_EQ instead of CHECK(a == b)'1784 ' [readability/check] [2]')1785 def testCheckCheckFalsePositives(self):1786 self.TestLint('CHECK(some_iterator == obj.end());', '')1787 self.TestLint('EXPECT_TRUE(some_iterator == obj.end());', '')1788 self.TestLint('EXPECT_FALSE(some_iterator == obj.end());', '')1789 self.TestLint('CHECK(some_pointer != NULL);', '')1790 self.TestLint('EXPECT_TRUE(some_pointer != NULL);', '')1791 self.TestLint('EXPECT_FALSE(some_pointer != NULL);', '')1792 self.TestLint('CHECK(CreateTestFile(dir, (1 << 20)));', '')1793 self.TestLint('CHECK(CreateTestFile(dir, (1 >> 20)));', '')1794 self.TestLint('CHECK(x ^ (y < 42));', '')1795 self.TestLint('CHECK((x > 42) ^ (x < 54));', '')1796 self.TestLint('CHECK(a && b < 42);', '')1797 self.TestLint('CHECK(42 < a && a < b);', '')1798 self.TestLint('SOFT_CHECK(x > 42);', '')1799 self.TestMultiLineLint(1800 """_STLP_DEFINE_BINARY_OP_CHECK(==, _OP_EQUAL);1801 _STLP_DEFINE_BINARY_OP_CHECK(!=, _OP_NOT_EQUAL);1802 _STLP_DEFINE_BINARY_OP_CHECK(<, _OP_LESS_THAN);1803 _STLP_DEFINE_BINARY_OP_CHECK(<=, _OP_LESS_EQUAL);1804 _STLP_DEFINE_BINARY_OP_CHECK(>, _OP_GREATER_THAN);1805 _STLP_DEFINE_BINARY_OP_CHECK(>=, _OP_GREATER_EQUAL);1806 _STLP_DEFINE_BINARY_OP_CHECK(+, _OP_PLUS);1807 _STLP_DEFINE_BINARY_OP_CHECK(*, _OP_TIMES);1808 _STLP_DEFINE_BINARY_OP_CHECK(/, _OP_DIVIDE);1809 _STLP_DEFINE_BINARY_OP_CHECK(-, _OP_SUBTRACT);1810 _STLP_DEFINE_BINARY_OP_CHECK(%, _OP_MOD);""",1811 '')1812 self.TestLint('CHECK(x < 42) << "Custom error message";', '')1813 # Alternative token to punctuation operator replacements1814 def testCheckAltTokens(self):1815 self.TestLint('true or true',1816 'Use operator || instead of or'1817 ' [readability/alt_tokens] [2]')1818 self.TestLint('true and true',1819 'Use operator && instead of and'1820 ' [readability/alt_tokens] [2]')1821 self.TestLint('if (not true)',1822 'Use operator ! instead of not'1823 ' [readability/alt_tokens] [2]')1824 self.TestLint('1 bitor 1',1825 'Use operator | instead of bitor'1826 ' [readability/alt_tokens] [2]')1827 self.TestLint('1 xor 1',1828 'Use operator ^ instead of xor'1829 ' [readability/alt_tokens] [2]')1830 self.TestLint('1 bitand 1',1831 'Use operator & instead of bitand'1832 ' [readability/alt_tokens] [2]')1833 self.TestLint('x = compl 1',1834 'Use operator ~ instead of compl'1835 ' [readability/alt_tokens] [2]')1836 self.TestLint('x and_eq y',1837 'Use operator &= instead of and_eq'1838 ' [readability/alt_tokens] [2]')1839 self.TestLint('x or_eq y',1840 'Use operator |= instead of or_eq'1841 ' [readability/alt_tokens] [2]')1842 self.TestLint('x xor_eq y',1843 'Use operator ^= instead of xor_eq'1844 ' [readability/alt_tokens] [2]')1845 self.TestLint('x not_eq y',1846 'Use operator != instead of not_eq'1847 ' [readability/alt_tokens] [2]')1848 self.TestLint('line_continuation or',1849 'Use operator || instead of or'1850 ' [readability/alt_tokens] [2]')1851 self.TestLint('if(true and(parentheses',1852 'Use operator && instead of and'1853 ' [readability/alt_tokens] [2]')1854 self.TestLint('#include "base/false-and-false.h"', '')1855 self.TestLint('#error false or false', '')1856 self.TestLint('false nor false', '')1857 self.TestLint('false nand false', '')1858 # Passing and returning non-const references1859 def testNonConstReference(self):1860 # Passing a non-const reference as function parameter is forbidden.1861 operand_error_message = ('Is this a non-const reference? '1862 'If so, make const or use a pointer: %s'1863 ' [runtime/references] [2]')1864 # Warn of use of a non-const reference in operators and functions1865 self.TestLint('bool operator>(Foo& s, Foo& f);',1866 [operand_error_message % 'Foo& s',1867 operand_error_message % 'Foo& f'])1868 self.TestLint('bool operator+(Foo& s, Foo& f);',1869 [operand_error_message % 'Foo& s',1870 operand_error_message % 'Foo& f'])1871 self.TestLint('int len(Foo& s);', operand_error_message % 'Foo& s')1872 # Allow use of non-const references in a few specific cases1873 self.TestLint('stream& operator>>(stream& s, Foo& f);', '')1874 self.TestLint('stream& operator<<(stream& s, Foo& f);', '')1875 self.TestLint('void swap(Bar& a, Bar& b);', '')1876 # Returning a non-const reference from a function is OK.1877 self.TestLint('int& g();', '')1878 # Passing a const reference to a struct (using the struct keyword) is OK.1879 self.TestLint('void foo(const struct tm& tm);', '')1880 # Passing a const reference to a typename is OK.1881 self.TestLint('void foo(const typename tm& tm);', '')1882 # Const reference to a pointer type is OK.1883 self.TestLint('void foo(const Bar* const& p) {', '')1884 self.TestLint('void foo(Bar const* const& p) {', '')1885 self.TestLint('void foo(Bar* const& p) {', '')1886 # Const reference to a templated type is OK.1887 self.TestLint('void foo(const std::vector<std::string>& v);', '')1888 # Non-const reference to a pointer type is not OK.1889 self.TestLint('void foo(Bar*& p);',1890 operand_error_message % 'Bar*& p')1891 self.TestLint('void foo(const Bar*& p);',1892 operand_error_message % 'const Bar*& p')1893 self.TestLint('void foo(Bar const*& p);',1894 operand_error_message % 'Bar const*& p')1895 self.TestLint('void foo(struct Bar*& p);',1896 operand_error_message % 'struct Bar*& p')1897 self.TestLint('void foo(const struct Bar*& p);',1898 operand_error_message % 'const struct Bar*& p')1899 self.TestLint('void foo(struct Bar const*& p);',1900 operand_error_message % 'struct Bar const*& p')1901 # Non-const reference to a templated type is not OK.1902 self.TestLint('void foo(std::vector<int>& p);',1903 operand_error_message % 'std::vector<int>& p')1904 # Returning an address of something is not prohibited.1905 self.TestLint('return &something;', '')1906 self.TestLint('if (condition) {return &something; }', '')1907 self.TestLint('if (condition) return &something;', '')1908 self.TestLint('if (condition) address = &something;', '')1909 self.TestLint('if (condition) result = lhs&rhs;', '')1910 self.TestLint('if (condition) result = lhs & rhs;', '')1911 self.TestLint('a = (b+c) * sizeof &f;', '')1912 self.TestLint('a = MySize(b) * sizeof &f;', '')1913 # We don't get confused by C++11 range-based for loops.1914 self.TestLint('for (const string& s : c)', '')1915 self.TestLint('for (auto& r : c)', '')1916 self.TestLint('for (typename Type& a : b)', '')1917 # We don't get confused by some other uses of '&'.1918 self.TestLint('T& operator=(const T& t);', '')1919 self.TestLint('int g() { return (a & b); }', '')1920 self.TestLint('T& r = (T&)*(vp());', '')1921 self.TestLint('T& r = v', '')1922 self.TestLint('static_assert((kBits & kMask) == 0, "text");', '')1923 self.TestLint('COMPILE_ASSERT((kBits & kMask) == 0, text);', '')1924 # Spaces before template arguments. This is poor style, but1925 # happens 0.15% of the time.1926 self.TestLint('void Func(const vector <int> &const_x, '1927 'vector <int> &nonconst_x) {',1928 operand_error_message % 'vector<int> &nonconst_x')1929 # Derived member functions are spared from override check1930 self.TestLint('void Func(X& x);', operand_error_message % 'X& x')1931 self.TestLint('void Func(X& x) {}', operand_error_message % 'X& x')1932 self.TestLint('void Func(X& x) override;', '')1933 self.TestLint('void Func(X& x) override {', '')1934 self.TestLint('void Func(X& x) const override;', '')1935 self.TestLint('void Func(X& x) const override {', '')1936 # Don't warn on out-of-line method definitions.1937 self.TestLint('void NS::Func(X& x) {', '')1938 error_collector = ErrorCollector(self.assert_)1939 cpplint.ProcessFileData(1940 'foo.cc', 'cc',1941 ['// Copyright 2014 Your Company. All Rights Reserved.',1942 'void a::b() {}',1943 'void f(int& q) {}',1944 ''],1945 error_collector)1946 self.assertEquals(1947 operand_error_message % 'int& q',1948 error_collector.Results())1949 # Other potential false positives. These need full parser1950 # state to reproduce as opposed to just TestLint.1951 error_collector = ErrorCollector(self.assert_)1952 cpplint.ProcessFileData(1953 'foo.cc', 'cc',1954 ['// Copyright 2014 Your Company. All Rights Reserved.',1955 'void swap(int &x,',1956 ' int &y) {',1957 '}',1958 'void swap(',1959 ' sparsegroup<T, GROUP_SIZE, Alloc> &x,',1960 ' sparsegroup<T, GROUP_SIZE, Alloc> &y) {',1961 '}',1962 'ostream& operator<<(',1963 ' ostream& out',1964 ' const dense_hash_set<Value, Hash, Equals, Alloc>& seq) {',1965 '}',1966 'class A {',1967 ' void Function(',1968 ' string &x) override {',1969 ' }',1970 '};',1971 'void Derived::Function(',1972 ' string &x) {',1973 '}',1974 '#define UNSUPPORTED_MASK(_mask) \\',1975 ' if (flags & _mask) { \\',1976 ' LOG(FATAL) << "Unsupported flag: " << #_mask; \\',1977 ' }',1978 'Constructor::Constructor()',1979 ' : initializer1_(a1 & b1),',1980 ' initializer2_(a2 & b2) {',1981 '}',1982 'Constructor::Constructor()',1983 ' : initializer1_{a3 & b3},',1984 ' initializer2_(a4 & b4) {',1985 '}',1986 'Constructor::Constructor()',1987 ' : initializer1_{a5 & b5},',1988 ' initializer2_(a6 & b6) {}',1989 ''],1990 error_collector)1991 self.assertEquals('', error_collector.Results())1992 # Multi-line references1993 error_collector = ErrorCollector(self.assert_)1994 cpplint.ProcessFileData(1995 'foo.cc', 'cc',1996 ['// Copyright 2014 Your Company. All Rights Reserved.',1997 'void Func(const Outer::',1998 ' Inner& const_x,',1999 ' const Outer',2000 ' ::Inner& const_y,',2001 ' const Outer<',2002 ' int>::Inner& const_z,',2003 ' Outer::',2004 ' Inner& nonconst_x,',2005 ' Outer',2006 ' ::Inner& nonconst_y,',2007 ' Outer<',2008 ' int>::Inner& nonconst_z) {',2009 '}',2010 ''],2011 error_collector)2012 self.assertEquals(2013 [operand_error_message % 'Outer::Inner& nonconst_x',2014 operand_error_message % 'Outer::Inner& nonconst_y',2015 operand_error_message % 'Outer<int>::Inner& nonconst_z'],2016 error_collector.Results())2017 # A peculiar false positive due to bad template argument parsing2018 error_collector = ErrorCollector(self.assert_)2019 cpplint.ProcessFileData(2020 'foo.cc', 'cc',2021 ['// Copyright 2014 Your Company. All Rights Reserved.',2022 'inline RCULocked<X>::ReadPtr::ReadPtr(const RCULocked* rcu) {',2023 ' DCHECK(!(data & kFlagMask)) << "Error";',2024 '}',2025 '',2026 'RCULocked<X>::WritePtr::WritePtr(RCULocked* rcu)',2027 ' : lock_(&rcu_->mutex_) {',2028 '}',2029 ''],2030 error_collector.Results())2031 self.assertEquals('', error_collector.Results())2032 def testBraceAtBeginOfLine(self):2033 self.TestLint('{',2034 '{ should almost always be at the end of the previous line'2035 ' [whitespace/braces] [4]')2036 error_collector = ErrorCollector(self.assert_)2037 cpplint.ProcessFileData('foo.cc', 'cc',2038 ['int function()',2039 '{', # warning here2040 ' MutexLock l(&mu);',2041 '}',2042 'int variable;'2043 '{', # no warning2044 ' MutexLock l(&mu);',2045 '}',2046 'MyType m = {',2047 ' {value1, value2},',2048 ' {', # no warning2049 ' loooong_value1, looooong_value2',2050 ' }',2051 '};',2052 '#if PREPROCESSOR',2053 '{', # no warning2054 ' MutexLock l(&mu);',2055 '}',2056 '#endif'],2057 error_collector)2058 self.assertEquals(1, error_collector.Results().count(2059 '{ should almost always be at the end of the previous line'2060 ' [whitespace/braces] [4]'))2061 self.TestMultiLineLint(2062 """2063 foo(2064 {2065 loooooooooooooooong_value,2066 });""",2067 '')2068 def testMismatchingSpacesInParens(self):2069 self.TestLint('if (foo ) {', 'Mismatching spaces inside () in if'2070 ' [whitespace/parens] [5]')2071 self.TestLint('switch ( foo) {', 'Mismatching spaces inside () in switch'2072 ' [whitespace/parens] [5]')2073 self.TestLint('for (foo; ba; bar ) {', 'Mismatching spaces inside () in for'2074 ' [whitespace/parens] [5]')2075 self.TestLint('for (; foo; bar) {', '')2076 self.TestLint('for ( ; foo; bar) {', '')2077 self.TestLint('for ( ; foo; bar ) {', '')2078 self.TestLint('for (foo; bar; ) {', '')2079 self.TestLint('while ( foo ) {', 'Should have zero or one spaces inside'2080 ' ( and ) in while [whitespace/parens] [5]')2081 def testSpacingForFncall(self):2082 self.TestLint('if (foo) {', '')2083 self.TestLint('for (foo; bar; baz) {', '')2084 self.TestLint('for (;;) {', '')2085 # Space should be allowed in placement new operators.2086 self.TestLint('Something* p = new (place) Something();', '')2087 # Test that there is no warning when increment statement is empty.2088 self.TestLint('for (foo; baz;) {', '')2089 self.TestLint('for (foo;bar;baz) {', 'Missing space after ;'2090 ' [whitespace/semicolon] [3]')2091 # we don't warn about this semicolon, at least for now2092 self.TestLint('if (condition) {return &something; }',2093 '')2094 # seen in some macros2095 self.TestLint('DoSth();\\', '')2096 # Test that there is no warning about semicolon here.2097 self.TestLint('abc;// this is abc',2098 'At least two spaces is best between code'2099 ' and comments [whitespace/comments] [2]')2100 self.TestLint('while (foo) {', '')2101 self.TestLint('switch (foo) {', '')2102 self.TestLint('foo( bar)', 'Extra space after ( in function call'2103 ' [whitespace/parens] [4]')2104 self.TestLint('foo( // comment', '')2105 self.TestLint('foo( // comment',2106 'At least two spaces is best between code'2107 ' and comments [whitespace/comments] [2]')2108 self.TestLint('foobar( \\', '')2109 self.TestLint('foobar( \\', '')2110 self.TestLint('( a + b)', 'Extra space after ('2111 ' [whitespace/parens] [2]')2112 self.TestLint('((a+b))', '')2113 self.TestLint('foo (foo)', 'Extra space before ( in function call'2114 ' [whitespace/parens] [4]')2115 self.TestLint('} catch (const Foo& ex) {', '')2116 self.TestLint('case (42):', '')2117 self.TestLint('typedef foo (*foo)(foo)', '')2118 self.TestLint('typedef foo (*foo12bar_)(foo)', '')2119 self.TestLint('typedef foo (Foo::*bar)(foo)', '')2120 self.TestLint('using foo = type (Foo::*bar)(foo)', '')2121 self.TestLint('using foo = type (Foo::*bar)(', '')2122 self.TestLint('using foo = type (Foo::*)(', '')2123 self.TestLint('foo (Foo::*bar)(', '')2124 self.TestLint('foo (x::y::*z)(', '')2125 self.TestLint('foo (Foo::bar)(',2126 'Extra space before ( in function call'2127 ' [whitespace/parens] [4]')2128 self.TestLint('foo (*bar)(', '')2129 self.TestLint('typedef foo (Foo::*bar)(', '')2130 self.TestLint('(foo)(bar)', '')2131 self.TestLint('Foo (*foo)(bar)', '')2132 self.TestLint('Foo (*foo)(Bar bar,', '')2133 self.TestLint('char (*p)[sizeof(foo)] = &foo', '')2134 self.TestLint('char (&ref)[sizeof(foo)] = &foo', '')2135 self.TestLint('const char32 (*table[])[6];', '')2136 # The sizeof operator is often written as if it were a function call, with2137 # an opening parenthesis directly following the operator name, but it can2138 # also be written like any other operator, with a space following the2139 # operator name, and the argument optionally in parentheses.2140 self.TestLint('sizeof(foo)', '')2141 self.TestLint('sizeof foo', '')2142 self.TestLint('sizeof (foo)', '')2143 def testSpacingBeforeBraces(self):2144 self.TestLint('if (foo){', 'Missing space before {'2145 ' [whitespace/braces] [5]')2146 self.TestLint('for{', 'Missing space before {'2147 ' [whitespace/braces] [5]')2148 self.TestLint('for {', '')2149 self.TestLint('EXPECT_DEBUG_DEATH({', '')2150 self.TestLint('std::is_convertible<A, B>{}', '')2151 def testSemiColonAfterBraces(self):2152 self.TestLint('if (cond) {};',2153 'You don\'t need a ; after a } [readability/braces] [4]')2154 self.TestLint('void Func() {};',2155 'You don\'t need a ; after a } [readability/braces] [4]')2156 self.TestLint('void Func() const {};',2157 'You don\'t need a ; after a } [readability/braces] [4]')2158 self.TestLint('class X {};', '')2159 for keyword in ['struct', 'union']:2160 for align in ['', ' alignas(16)']:2161 for typename in ['', ' X']:2162 for identifier in ['', ' x']:2163 self.TestLint(keyword + align + typename + ' {}' + identifier + ';',2164 '')2165 self.TestLint('class X : public Y {};', '')2166 self.TestLint('class X : public MACRO() {};', '')2167 self.TestLint('DEFINE_FACADE(PCQueue::Watcher, PCQueue) {};', '')2168 self.TestLint('VCLASS(XfaTest, XfaContextTest) {};', '')2169 self.TestLint('TEST(TestCase, TestName) {};',2170 'You don\'t need a ; after a } [readability/braces] [4]')2171 self.TestLint('TEST_F(TestCase, TestName) {};',2172 'You don\'t need a ; after a } [readability/braces] [4]')2173 self.TestLint('file_tocs_[i] = (FileToc) {a, b, c};', '')2174 self.TestMultiLineLint('class X : public Y,\npublic Z {};', '')2175 def testLambda(self):2176 self.TestLint('auto x = []() {};', '')2177 self.TestLint('return []() {};', '')2178 self.TestMultiLineLint('auto x = []() {\n};\n', '')2179 self.TestLint('int operator[](int x) {};',2180 'You don\'t need a ; after a } [readability/braces] [4]')2181 self.TestMultiLineLint('auto x = [&a,\nb]() {};', '')2182 self.TestMultiLineLint('auto x = [&a,\nb]\n() {};', '')2183 self.TestMultiLineLint('auto x = [&a,\n'2184 ' b](\n'2185 ' int a,\n'2186 ' int b) {\n'2187 ' return a +\n'2188 ' b;\n'2189 '};\n',2190 '')2191 for lambda_with_default_capture in ('void f() { [=]{}; }',2192 'void f() { [=](int i) {}; }',2193 'void f() { [=, &x]{}; }',2194 'void f() { [&]{}; }',2195 'void f() { [ & ]{}; }',2196 'void f() { [&, y]{}; }'):2197 self.TestLint(lambda_with_default_capture,2198 'Default lambda captures are an unapproved C++ feature. '2199 '[build/c++11] [4]')2200 # "[&...]" isn't necessarily a default capture, though "[=...]" always is.2201 self.TestLint('void f() { [&variable]{}; }', '')2202 # Avoid false positives with operator[]2203 self.TestLint('table_to_children[&*table].push_back(dependent);', '')2204 def testBraceInitializerList(self):2205 self.TestLint('MyStruct p = {1, 2};', '')2206 self.TestLint('MyStruct p{1, 2};', '')2207 self.TestLint('vector<int> p = {1, 2};', '')2208 self.TestLint('vector<int> p{1, 2};', '')2209 self.TestLint('x = vector<int>{1, 2};', '')2210 self.TestLint('x = (struct in_addr){ 0 };', '')2211 self.TestLint('Func(vector<int>{1, 2})', '')2212 self.TestLint('Func((struct in_addr){ 0 })', '')2213 self.TestLint('Func(vector<int>{1, 2}, 3)', '')2214 self.TestLint('Func((struct in_addr){ 0 }, 3)', '')2215 self.TestLint('LOG(INFO) << char{7};', '')2216 self.TestLint('LOG(INFO) << char{7} << "!";', '')2217 self.TestLint('int p[2] = {1, 2};', '')2218 self.TestLint('return {1, 2};', '')2219 self.TestLint('std::unique_ptr<Foo> foo{new Foo{}};', '')2220 self.TestLint('auto foo = std::unique_ptr<Foo>{new Foo{}};', '')2221 self.TestLint('static_assert(Max7String{}.IsValid(), "");', '')2222 self.TestLint('map_of_pairs[{1, 2}] = 3;', '')2223 self.TestLint('ItemView{has_offer() ? new Offer{offer()} : nullptr', '')2224 self.TestLint('template <class T, EnableIf<::std::is_const<T>{}> = 0>', '')2225 self.TestMultiLineLint('std::unique_ptr<Foo> foo{\n'2226 ' new Foo{}\n'2227 '};\n', '')2228 self.TestMultiLineLint('std::unique_ptr<Foo> foo{\n'2229 ' new Foo{\n'2230 ' new Bar{}\n'2231 ' }\n'2232 '};\n', '')2233 self.TestMultiLineLint('if (true) {\n'2234 ' if (false){}\n'2235 '}\n',2236 'Missing space before { [whitespace/braces] [5]')2237 self.TestMultiLineLint('MyClass::MyClass()\n'2238 ' : initializer_{\n'2239 ' Func()} {\n'2240 '}\n', '')2241 def testSpacingAroundElse(self):2242 self.TestLint('}else {', 'Missing space before else'2243 ' [whitespace/braces] [5]')2244 self.TestLint('} else{', 'Missing space before {'2245 ' [whitespace/braces] [5]')2246 self.TestLint('} else {', '')2247 self.TestLint('} else if (foo) {', '')2248 def testSpacingWithInitializerLists(self):2249 self.TestLint('int v[1][3] = {{1, 2, 3}};', '')2250 self.TestLint('int v[1][1] = {{0}};', '')2251 def testSpacingForBinaryOps(self):2252 self.TestLint('if (foo||bar) {', 'Missing spaces around ||'2253 ' [whitespace/operators] [3]')2254 self.TestLint('if (foo<=bar) {', 'Missing spaces around <='2255 ' [whitespace/operators] [3]')2256 self.TestLint('if (foo<bar) {', 'Missing spaces around <'2257 ' [whitespace/operators] [3]')2258 self.TestLint('if (foo>bar) {', 'Missing spaces around >'2259 ' [whitespace/operators] [3]')2260 self.TestLint('if (foo<bar->baz) {', 'Missing spaces around <'2261 ' [whitespace/operators] [3]')2262 self.TestLint('if (foo<bar->bar) {', 'Missing spaces around <'2263 ' [whitespace/operators] [3]')2264 self.TestLint('template<typename T = double>', '')2265 self.TestLint('std::unique_ptr<No<Spaces>>', '')2266 self.TestLint('typedef hash_map<Foo, Bar>', '')2267 self.TestLint('10<<20', '')2268 self.TestLint('10<<a',2269 'Missing spaces around << [whitespace/operators] [3]')2270 self.TestLint('a<<20',2271 'Missing spaces around << [whitespace/operators] [3]')2272 self.TestLint('a<<b',2273 'Missing spaces around << [whitespace/operators] [3]')2274 self.TestLint('10ULL<<20', '')2275 self.TestLint('a>>b',2276 'Missing spaces around >> [whitespace/operators] [3]')2277 self.TestLint('10>>b',2278 'Missing spaces around >> [whitespace/operators] [3]')2279 self.TestLint('LOG(ERROR)<<*foo',2280 'Missing spaces around << [whitespace/operators] [3]')2281 self.TestLint('LOG(ERROR)<<&foo',2282 'Missing spaces around << [whitespace/operators] [3]')2283 self.TestLint('StringCoder<vector<string>>::ToString()', '')2284 self.TestLint('map<pair<int, int>, map<int, int>>::iterator', '')2285 self.TestLint('func<int, pair<int, pair<int, int>>>()', '')2286 self.TestLint('MACRO1(list<list<int>>)', '')2287 self.TestLint('MACRO2(list<list<int>>, 42)', '')2288 self.TestLint('void DoFoo(const set<vector<string>>& arg1);', '')2289 self.TestLint('void SetFoo(set<vector<string>>* arg1);', '')2290 self.TestLint('foo = new set<vector<string>>;', '')2291 self.TestLint('reinterpret_cast<set<vector<string>>*>(a);', '')2292 self.TestLint('MACRO(<<)', '')2293 self.TestLint('MACRO(<<, arg)', '')2294 self.TestLint('MACRO(<<=)', '')2295 self.TestLint('MACRO(<<=, arg)', '')2296 self.TestLint('using Vector3<T>::operator==;', '')2297 self.TestLint('using Vector3<T>::operator!=;', '')2298 def testRvalueReference(self):2299 space_error = 'Missing spaces around && [whitespace/operators] [3]'2300 rvalue_error = ('RValue references are an unapproved C++ feature.'2301 ' [build/c++11] [3]')2302 # Places where lack of space are allowed2303 self.TestLint('DEFINE_BINARY_OPERATOR(&&)', '')2304 self.TestLint('bool operator&&(A b) {}', '')2305 self.TestLint('bool operator&&(A b) {', '')2306 self.TestLint('bool operator&&(A b);', '')2307 # Assignment expressions2308 self.TestLint('a = b && c;', '')2309 self.TestLint('a = b&& c;', space_error)2310 self.TestLint('a = b &&c;', space_error)2311 self.TestLint('a = (b&& c);', space_error)2312 self.TestLint('a = (b &&c);', space_error)2313 self.TestLint('a&& b = c;', rvalue_error)2314 self.TestLint('a<b>&& c = d;', rvalue_error)2315 self.TestLint('auto&& a = b;', rvalue_error)2316 self.TestLint('const a&& b = c;', rvalue_error)2317 self.TestLint('struct a&& b = c;', rvalue_error)2318 self.TestLint('decltype(a)&& b = c;', rvalue_error)2319 # Cast expressions2320 self.TestLint('a = const_cast<b&&>(c);', rvalue_error)2321 self.TestLint('a = const_cast<const b&&>(c);', rvalue_error)2322 self.TestLint('a = static_cast<b&&>(c);', rvalue_error)2323 self.TestLint('a = static_cast<const b&&>(c);', rvalue_error)2324 self.TestLint('a = dynamic_cast<b&&>(c);', rvalue_error)2325 self.TestLint('a = dynamic_cast<const b&&>(c);', rvalue_error)2326 self.TestLint('a = reinterpret_cast<b&&>(c);', rvalue_error)2327 self.TestLint('a = reinterpret_cast<const b&&>(c);', rvalue_error)2328 self.TestLint('a = cast < b&& c;', space_error)2329 # Function parameters2330 for indent in ['', ' ']:2331 for head in ['void Func', 'vector<int> Func', 'vector<int>\nFunc',2332 'inline void Func',2333 'Constructor', 'Constructor::Constructor',2334 'operator=', 'operator =', 'operator = ']:2335 for body in [' {}', ' {', ';']:2336 self.TestMultiLineLint(indent + head + '(A&& b)' + body, rvalue_error)2337 self.TestMultiLineLint(indent + head + '(A &&b)' + body, rvalue_error)2338 self.TestMultiLineLint(indent + head + '(A&&... b)' + body,2339 rvalue_error)2340 self.TestMultiLineLint(indent + head + '(A<B>&& c)' + body,2341 rvalue_error)2342 self.TestMultiLineLint(indent + head + '(A<B> &&c)' + body,2343 rvalue_error)2344 # Function templates2345 self.TestLint('std::conditional<A, B&, C&&>::type', rvalue_error)2346 self.TestLint('std::conditional<A, B&&, C&>::type', rvalue_error)2347 # Template functions2348 self.TestLint('template <typename T> R&& F()', rvalue_error)2349 self.TestLint('template <typename T> R&& F() {', rvalue_error)2350 self.TestMultiLineLint('template <typename T>\nR&& F()', rvalue_error)2351 self.TestMultiLineLint('template <typename T>\nR&& F() {', rvalue_error)2352 self.TestLint('template <typename T> void F(T a, R&& b)', rvalue_error)2353 self.TestLint('template <typename T> void F(T a, R &&b)', rvalue_error)2354 self.TestLint('template <typename T> void F(T a, R&& b) {', rvalue_error)2355 # For loops2356 self.TestLint('for (a&& b;;)', rvalue_error)2357 self.TestLint('for (a&& b;;) {', rvalue_error)2358 self.TestLint('for (; a&& b;)', space_error)2359 self.TestLint('for (; a&& b;) {', space_error)2360 # Constructors2361 self.TestLint('A(a&& b)', rvalue_error)2362 self.TestLint('explicit A(a&& b)', rvalue_error)2363 self.TestLint('A(a b) : c(d&& e)', space_error)2364 self.TestLint('A(a b) : c(), d(e&& f)', space_error)2365 def testAllowedRvalueReference(self):2366 # Verify that RValue reference warnings for a line range can be silenced2367 error_collector = ErrorCollector(self.assert_)2368 cpplint.ProcessFileData('foo.cc', 'cc',2369 ['// Copyright 2014 Your Company.',2370 'GOOGLE_ALLOW_RVALUE_REFERENCES_PUSH',2371 'void F(A&& b);',2372 'GOOGLE_ALLOW_RVALUE_REFERENCES_POP',2373 ''],2374 error_collector)2375 self.assertEquals(error_collector.Results(), '')2376 # RValue references for constructors and operator=2377 error_collector = ErrorCollector(self.assert_)2378 cpplint.ProcessFileData(2379 'foo.cc', 'cc',2380 ['// Copyright 2014 Your Company.',2381 'class X {',2382 ' X(X&& param) = delete; // NOLINT(runtime/explicit)',2383 ' X(X &&param) = default; // NOLINT(runtime/explicit)',2384 ' inline X(X&& param) = default; // NOLINT(runtime/explicit)',2385 '',2386 ' X& operator=(X&& param) = delete;',2387 ' X& operator=(X&& param) = default;',2388 '};',2389 'A::A(A&&) = default;',2390 'Outer::Inner::Inner(Inner&&) = default;',2391 ''],2392 error_collector)2393 self.assertEquals(error_collector.Results(), '')2394 # Assume templated function parameters are forwarded, and are allowed2395 error_collector = ErrorCollector(self.assert_)2396 cpplint.ProcessFileData(2397 'foo.cc', 'cc',2398 ['// Copyright 2014 Your Company.',2399 'template <typename Allowed1>',2400 'void Function1(Allowed1&& a);',2401 '',2402 'template <typename Allowed2, typename Allowed3>',2403 'void Function2(Allowed2&& a, Allowed3 &&b) {',2404 '}',2405 '',2406 'template <class Allowed4>',2407 'void Function3(Ignored1 *a, Allowed4&& b) {',2408 '}',2409 '',2410 'template <typename... Allowed5>',2411 'void Function4(Allowed5&&... a) {',2412 '}',2413 '',2414 'template <class... Allowed6>',2415 'void Function5(',2416 ' Allowed6 &&...a) {',2417 '}',2418 ''],2419 error_collector)2420 self.assertEquals(error_collector.Results(), '')2421 def testSpacingBeforeLastSemicolon(self):2422 self.TestLint('call_function() ;',2423 'Extra space before last semicolon. If this should be an '2424 'empty statement, use {} instead.'2425 ' [whitespace/semicolon] [5]')2426 self.TestLint('while (true) ;',2427 'Extra space before last semicolon. If this should be an '2428 'empty statement, use {} instead.'2429 ' [whitespace/semicolon] [5]')2430 self.TestLint('default:;',2431 'Semicolon defining empty statement. Use {} instead.'2432 ' [whitespace/semicolon] [5]')2433 self.TestLint(' ;',2434 'Line contains only semicolon. If this should be an empty '2435 'statement, use {} instead.'2436 ' [whitespace/semicolon] [5]')2437 self.TestLint('for (int i = 0; ;', '')2438 def testEmptyBlockBody(self):2439 self.TestLint('while (true);',2440 'Empty loop bodies should use {} or continue'2441 ' [whitespace/empty_loop_body] [5]')2442 self.TestLint('if (true);',2443 'Empty conditional bodies should use {}'2444 ' [whitespace/empty_conditional_body] [5]')2445 self.TestLint('while (true)', '')2446 self.TestLint('while (true) continue;', '')2447 self.TestLint('for (;;);',2448 'Empty loop bodies should use {} or continue'2449 ' [whitespace/empty_loop_body] [5]')2450 self.TestLint('for (;;)', '')2451 self.TestLint('for (;;) continue;', '')2452 self.TestLint('for (;;) func();', '')2453 self.TestMultiLineLint("""while (true &&2454 false);""",2455 'Empty loop bodies should use {} or continue'2456 ' [whitespace/empty_loop_body] [5]')2457 self.TestMultiLineLint("""do {2458 } while (false);""",2459 '')2460 self.TestMultiLineLint("""#define MACRO \\2461 do { \\2462 } while (false);""",2463 '')2464 self.TestMultiLineLint("""do {2465 } while (false); // next line gets a warning2466 while (false);""",2467 'Empty loop bodies should use {} or continue'2468 ' [whitespace/empty_loop_body] [5]')2469 def testSpacingForRangeBasedFor(self):2470 # Basic correctly formatted case:2471 self.TestLint('for (int i : numbers) {', '')2472 # Missing space before colon:2473 self.TestLint('for (int i: numbers) {',2474 'Missing space around colon in range-based for loop'2475 ' [whitespace/forcolon] [2]')2476 # Missing space after colon:2477 self.TestLint('for (int i :numbers) {',2478 'Missing space around colon in range-based for loop'2479 ' [whitespace/forcolon] [2]')2480 # Missing spaces both before and after the colon.2481 self.TestLint('for (int i:numbers) {',2482 'Missing space around colon in range-based for loop'2483 ' [whitespace/forcolon] [2]')2484 # The scope operator '::' shouldn't cause warnings...2485 self.TestLint('for (std::size_t i : sizes) {}', '')2486 # ...but it shouldn't suppress them either.2487 self.TestLint('for (std::size_t i: sizes) {}',2488 'Missing space around colon in range-based for loop'2489 ' [whitespace/forcolon] [2]')2490 # Static or global STL strings.2491 def testStaticOrGlobalSTLStrings(self):2492 error_msg = ('For a static/global string constant, use a C style '2493 'string instead: "%s[]". [runtime/string] [4]')2494 self.TestLint('string foo;',2495 error_msg % 'char foo')2496 self.TestLint('string kFoo = "hello"; // English',2497 error_msg % 'char kFoo')2498 self.TestLint('static string foo;',2499 error_msg % 'static char foo')2500 self.TestLint('static const string foo;',2501 error_msg % 'static const char foo')2502 self.TestLint('string Foo::bar;',2503 error_msg % 'char Foo::bar')2504 self.TestLint('string* pointer', '')2505 self.TestLint('string *pointer', '')2506 self.TestLint('string* pointer = Func();', '')2507 self.TestLint('string *pointer = Func();', '')2508 self.TestLint('const string* pointer', '')2509 self.TestLint('const string *pointer', '')2510 self.TestLint('const string* pointer = Func();', '')2511 self.TestLint('const string *pointer = Func();', '')2512 self.TestLint('string const* pointer', '')2513 self.TestLint('string const *pointer', '')2514 self.TestLint('string const* pointer = Func();', '')2515 self.TestLint('string const *pointer = Func();', '')2516 self.TestLint('string* const pointer', '')2517 self.TestLint('string *const pointer', '')2518 self.TestLint('string* const pointer = Func();', '')2519 self.TestLint('string *const pointer = Func();', '')2520 self.TestLint('string Foo::bar() {}', '')2521 self.TestLint('string Foo::operator*() {}', '')2522 # Rare case.2523 self.TestLint('string foo("foobar");', error_msg % 'char foo')2524 # Should not catch local or member variables.2525 self.TestLint(' string foo', '')2526 # Should not catch functions.2527 self.TestLint('string EmptyString() { return ""; }', '')2528 self.TestLint('string EmptyString () { return ""; }', '')2529 self.TestLint('string VeryLongNameFunctionSometimesEndsWith(\n'2530 ' VeryLongNameType very_long_name_variable) {}', '')2531 self.TestLint('template<>\n'2532 'string FunctionTemplateSpecialization<SomeType>(\n'2533 ' int x) { return ""; }', '')2534 self.TestLint('template<>\n'2535 'string FunctionTemplateSpecialization<vector<A::B>* >(\n'2536 ' int x) { return ""; }', '')2537 # should not catch methods of template classes.2538 self.TestLint('string Class<Type>::Method() const {\n'2539 ' return "";\n'2540 '}\n', '')2541 self.TestLint('string Class<Type>::Method(\n'2542 ' int arg) const {\n'2543 ' return "";\n'2544 '}\n', '')2545 # Check multiline cases.2546 error_collector = ErrorCollector(self.assert_)2547 cpplint.ProcessFileData('foo.cc', 'cc',2548 ['// Copyright 2014 Your Company.',2549 'string Class',2550 '::MemberFunction1();',2551 'string Class::',2552 'MemberFunction2();',2553 'string Class::',2554 'NestedClass::MemberFunction3();',2555 'string TemplateClass<T>::',2556 'NestedClass::MemberFunction4();',2557 'string Class',2558 '::static_member_variable1;',2559 'string Class::',2560 'static_member_variable2;',2561 'string Class',2562 '::static_member_variable3 = "initial value";',2563 'string Class::',2564 'static_member_variable4 = "initial value";',2565 ''],2566 error_collector)2567 self.assertEquals(error_collector.Results(),2568 [error_msg % 'char Class::static_member_variable1',2569 error_msg % 'char Class::static_member_variable2',2570 error_msg % 'char Class::static_member_variable3',2571 error_msg % 'char Class::static_member_variable4'])2572 def testNoSpacesInFunctionCalls(self):2573 self.TestLint('TellStory(1, 3);',2574 '')2575 self.TestLint('TellStory(1, 3 );',2576 'Extra space before )'2577 ' [whitespace/parens] [2]')2578 self.TestLint('TellStory(1 /* wolf */, 3 /* pigs */);',2579 '')2580 self.TestMultiLineLint("""TellStory(1, 32581 );""",2582 'Closing ) should be moved to the previous line'2583 ' [whitespace/parens] [2]')2584 self.TestMultiLineLint("""TellStory(Wolves(1),2585 Pigs(32586 ));""",2587 'Closing ) should be moved to the previous line'2588 ' [whitespace/parens] [2]')2589 self.TestMultiLineLint("""TellStory(1,2590 3 );""",2591 'Extra space before )'2592 ' [whitespace/parens] [2]')2593 def testToDoComments(self):2594 start_space = ('Too many spaces before TODO'2595 ' [whitespace/todo] [2]')2596 missing_username = ('Missing username in TODO; it should look like '2597 '"// TODO(my_username): Stuff."'2598 ' [readability/todo] [2]')2599 end_space = ('TODO(my_username) should be followed by a space'2600 ' [whitespace/todo] [2]')2601 self.TestLint('// TODOfix this',2602 [start_space, missing_username, end_space])2603 self.TestLint('// TODO(ljenkins)fix this',2604 [start_space, end_space])2605 self.TestLint('// TODO fix this',2606 [start_space, missing_username])2607 self.TestLint('// TODO fix this', missing_username)2608 self.TestLint('// TODO: fix this', missing_username)2609 self.TestLint('//TODO(ljenkins): Fix this',2610 'Should have a space between // and comment'2611 ' [whitespace/comments] [4]')2612 self.TestLint('// TODO(ljenkins):Fix this', end_space)2613 self.TestLint('// TODO(ljenkins):', '')2614 self.TestLint('// TODO(ljenkins): fix this', '')2615 self.TestLint('// TODO(ljenkins): Fix this', '')2616 self.TestLint('#if 1 // TEST_URLTODOCID_WHICH_HAS_THAT_WORD_IN_IT_H_', '')2617 self.TestLint('// See also similar TODO above', '')2618 def testTwoSpacesBetweenCodeAndComments(self):2619 self.TestLint('} // namespace foo',2620 'At least two spaces is best between code and comments'2621 ' [whitespace/comments] [2]')2622 self.TestLint('}// namespace foo',2623 'At least two spaces is best between code and comments'2624 ' [whitespace/comments] [2]')2625 self.TestLint('printf("foo"); // Outside quotes.',2626 'At least two spaces is best between code and comments'2627 ' [whitespace/comments] [2]')2628 self.TestLint('int i = 0; // Having two spaces is fine.', '')2629 self.TestLint('int i = 0; // Having three spaces is OK.', '')2630 self.TestLint('// Top level comment', '')2631 self.TestLint(' // Line starts with two spaces.', '')2632 self.TestMultiLineLint('void foo() {\n'2633 ' { // A scope is opening.\n'2634 ' int a;', '')2635 self.TestMultiLineLint('void foo() {\n'2636 ' { // A scope is opening.\n'2637 '#define A a',2638 'At least two spaces is best between code and '2639 'comments [whitespace/comments] [2]')2640 self.TestMultiLineLint(' foo();\n'2641 ' { // An indented scope is opening.\n'2642 ' int a;', '')2643 self.TestMultiLineLint('vector<int> my_elements = {// first\n'2644 ' 1,', '')2645 self.TestMultiLineLint('vector<int> my_elements = {// my_elements is ..\n'2646 ' 1,',2647 'At least two spaces is best between code and '2648 'comments [whitespace/comments] [2]')2649 self.TestLint('if (foo) { // not a pure scope; comment is too close!',2650 'At least two spaces is best between code and comments'2651 ' [whitespace/comments] [2]')2652 self.TestLint('printf("// In quotes.")', '')2653 self.TestLint('printf("\\"%s // In quotes.")', '')2654 self.TestLint('printf("%s", "// In quotes.")', '')2655 def testSpaceAfterCommentMarker(self):2656 self.TestLint('//', '')2657 self.TestLint('//x', 'Should have a space between // and comment'2658 ' [whitespace/comments] [4]')2659 self.TestLint('// x', '')2660 self.TestLint('///', '')2661 self.TestLint('/// x', '')2662 self.TestLint('//!', '')2663 self.TestLint('//----', '')2664 self.TestLint('//====', '')2665 self.TestLint('//////', '')2666 self.TestLint('////// x', '')2667 self.TestLint('///< x', '') # After-member Doxygen comment2668 self.TestLint('//!< x', '') # After-member Doxygen comment2669 self.TestLint('////x', 'Should have a space between // and comment'2670 ' [whitespace/comments] [4]')2671 self.TestLint('//}', '')2672 self.TestLint('//}x', 'Should have a space between // and comment'2673 ' [whitespace/comments] [4]')2674 self.TestLint('//!<x', 'Should have a space between // and comment'2675 ' [whitespace/comments] [4]')2676 self.TestLint('///<x', 'Should have a space between // and comment'2677 ' [whitespace/comments] [4]')2678 # Test a line preceded by empty or comment lines. There was a bug2679 # that caused it to print the same warning N times if the erroneous2680 # line was preceded by N lines of empty or comment lines. To be2681 # precise, the '// marker so line numbers and indices both start at2682 # 1' line was also causing the issue.2683 def testLinePrecededByEmptyOrCommentLines(self):2684 def DoTest(self, lines):2685 error_collector = ErrorCollector(self.assert_)2686 cpplint.ProcessFileData('foo.cc', 'cc', lines, error_collector)2687 # The warning appears only once.2688 self.assertEquals(2689 1,2690 error_collector.Results().count(2691 'Do not use namespace using-directives. '2692 'Use using-declarations instead.'2693 ' [build/namespaces] [5]'))2694 DoTest(self, ['using namespace foo;'])2695 DoTest(self, ['', '', '', 'using namespace foo;'])2696 DoTest(self, ['// hello', 'using namespace foo;'])2697 def testNewlineAtEOF(self):2698 def DoTest(self, data, is_missing_eof):2699 error_collector = ErrorCollector(self.assert_)2700 cpplint.ProcessFileData('foo.cc', 'cc', data.split('\n'),2701 error_collector)2702 # The warning appears only once.2703 self.assertEquals(2704 int(is_missing_eof),2705 error_collector.Results().count(2706 'Could not find a newline character at the end of the file.'2707 ' [whitespace/ending_newline] [5]'))2708 DoTest(self, '// Newline\n// at EOF\n', False)2709 DoTest(self, '// No newline\n// at EOF', True)2710 def testInvalidUtf8(self):2711 def DoTest(self, raw_bytes, has_invalid_utf8):2712 error_collector = ErrorCollector(self.assert_)2713 cpplint.ProcessFileData(2714 'foo.cc', 'cc',2715 unicode(raw_bytes, 'utf8', 'replace').split('\n'),2716 error_collector)2717 # The warning appears only once.2718 self.assertEquals(2719 int(has_invalid_utf8),2720 error_collector.Results().count(2721 'Line contains invalid UTF-8'2722 ' (or Unicode replacement character).'2723 ' [readability/utf8] [5]'))2724 DoTest(self, 'Hello world\n', False)2725 DoTest(self, '\xe9\x8e\xbd\n', False)2726 DoTest(self, '\xe9x\x8e\xbd\n', True)2727 # This is the encoding of the replacement character itself (which2728 # you can see by evaluating codecs.getencoder('utf8')(u'\ufffd')).2729 DoTest(self, '\xef\xbf\xbd\n', True)2730 def testBadCharacters(self):2731 # Test for NUL bytes only2732 error_collector = ErrorCollector(self.assert_)2733 cpplint.ProcessFileData('nul.cc', 'cc',2734 ['// Copyright 2014 Your Company.',2735 '\0', ''], error_collector)2736 self.assertEquals(2737 error_collector.Results(),2738 'Line contains NUL byte. [readability/nul] [5]')2739 # Make sure both NUL bytes and UTF-8 are caught if they appear on2740 # the same line.2741 error_collector = ErrorCollector(self.assert_)2742 cpplint.ProcessFileData(2743 'nul_utf8.cc', 'cc',2744 ['// Copyright 2014 Your Company.',2745 unicode('\xe9x\0', 'utf8', 'replace'), ''],2746 error_collector)2747 self.assertEquals(2748 error_collector.Results(),2749 ['Line contains invalid UTF-8 (or Unicode replacement character).'2750 ' [readability/utf8] [5]',2751 'Line contains NUL byte. [readability/nul] [5]'])2752 def testIsBlankLine(self):2753 self.assert_(cpplint.IsBlankLine(''))2754 self.assert_(cpplint.IsBlankLine(' '))2755 self.assert_(cpplint.IsBlankLine(' \t\r\n'))2756 self.assert_(not cpplint.IsBlankLine('int a;'))2757 self.assert_(not cpplint.IsBlankLine('{'))2758 def testBlankLinesCheck(self):2759 self.TestBlankLinesCheck(['{\n', '\n', '\n', '}\n'], 1, 1)2760 self.TestBlankLinesCheck([' if (foo) {\n', '\n', ' }\n'], 1, 1)2761 self.TestBlankLinesCheck(2762 ['\n', '// {\n', '\n', '\n', '// Comment\n', '{\n', '}\n'], 0, 0)2763 self.TestBlankLinesCheck(['\n', 'run("{");\n', '\n'], 0, 0)2764 self.TestBlankLinesCheck(['\n', ' if (foo) { return 0; }\n', '\n'], 0, 0)2765 self.TestBlankLinesCheck(2766 ['int x(\n', ' int a) {\n', '\n', 'return 0;\n', '}'], 0, 0)2767 self.TestBlankLinesCheck(2768 ['int x(\n', ' int a) const {\n', '\n', 'return 0;\n', '}'], 0, 0)2769 self.TestBlankLinesCheck(2770 ['int x(\n', ' int a) {\n', '\n', 'return 0;\n', '}'], 1, 0)2771 self.TestBlankLinesCheck(2772 ['int x(\n', ' int a) {\n', '\n', 'return 0;\n', '}'], 1, 0)2773 def testAllowBlankLineBeforeClosingNamespace(self):2774 error_collector = ErrorCollector(self.assert_)2775 cpplint.ProcessFileData('foo.cc', 'cc',2776 ['namespace {',2777 '',2778 '} // namespace',2779 'namespace another_namespace {',2780 '',2781 '}',2782 'namespace {',2783 '',2784 'template<class T, ',2785 ' class A = hoge<T>, ',2786 ' class B = piyo<T>, ',2787 ' class C = fuga<T> >',2788 'class D {',2789 ' public:',2790 '};',2791 '', '', '', '',2792 '}'],2793 error_collector)2794 self.assertEquals(0, error_collector.Results().count(2795 'Redundant blank line at the end of a code block should be deleted.'2796 ' [whitespace/blank_line] [3]'))2797 def testAllowBlankLineBeforeIfElseChain(self):2798 error_collector = ErrorCollector(self.assert_)2799 cpplint.ProcessFileData('foo.cc', 'cc',2800 ['if (hoge) {',2801 '', # No warning2802 '} else if (piyo) {',2803 '', # No warning2804 '} else if (piyopiyo) {',2805 ' hoge = true;', # No warning2806 '} else {',2807 '', # Warning on this line2808 '}'],2809 error_collector)2810 self.assertEquals(1, error_collector.Results().count(2811 'Redundant blank line at the end of a code block should be deleted.'2812 ' [whitespace/blank_line] [3]'))2813 def testAllowBlankLineAfterExtern(self):2814 error_collector = ErrorCollector(self.assert_)2815 cpplint.ProcessFileData('foo.cc', 'cc',2816 ['extern "C" {',2817 '',2818 'EXPORTAPI void APICALL Some_function() {}',2819 '',2820 '}'],2821 error_collector)2822 self.assertEquals(0, error_collector.Results().count(2823 'Redundant blank line at the start of a code block should be deleted.'2824 ' [whitespace/blank_line] [2]'))2825 self.assertEquals(0, error_collector.Results().count(2826 'Redundant blank line at the end of a code block should be deleted.'2827 ' [whitespace/blank_line] [3]'))2828 def testBlankLineBeforeSectionKeyword(self):2829 error_collector = ErrorCollector(self.assert_)2830 cpplint.ProcessFileData('foo.cc', 'cc',2831 ['class A {',2832 ' public:',2833 ' protected:', # warning 12834 ' private:', # warning 22835 ' struct B {',2836 ' public:',2837 ' private:'] + # warning 32838 ([''] * 100) + # Make A and B longer than 100 lines2839 [' };',2840 ' struct C {',2841 ' protected:',2842 ' private:', # C is too short for warnings2843 ' };',2844 '};',2845 'class D',2846 ' : public {',2847 ' public:', # no warning2848 '};',2849 'class E {\\',2850 ' public:\\'] +2851 (['\\'] * 100) + # Makes E > 100 lines2852 [' int non_empty_line;\\',2853 ' private:\\', # no warning2854 ' int a;\\',2855 '};'],2856 error_collector)2857 self.assertEquals(2, error_collector.Results().count(2858 '"private:" should be preceded by a blank line'2859 ' [whitespace/blank_line] [3]'))2860 self.assertEquals(1, error_collector.Results().count(2861 '"protected:" should be preceded by a blank line'2862 ' [whitespace/blank_line] [3]'))2863 def testNoBlankLineAfterSectionKeyword(self):2864 error_collector = ErrorCollector(self.assert_)2865 cpplint.ProcessFileData('foo.cc', 'cc',2866 ['class A {',2867 ' public:',2868 '', # warning 12869 ' private:',2870 '', # warning 22871 ' struct B {',2872 ' protected:',2873 '', # warning 32874 ' };',2875 '};'],2876 error_collector)2877 self.assertEquals(1, error_collector.Results().count(2878 'Do not leave a blank line after "public:"'2879 ' [whitespace/blank_line] [3]'))2880 self.assertEquals(1, error_collector.Results().count(2881 'Do not leave a blank line after "protected:"'2882 ' [whitespace/blank_line] [3]'))2883 self.assertEquals(1, error_collector.Results().count(2884 'Do not leave a blank line after "private:"'2885 ' [whitespace/blank_line] [3]'))2886 def testAllowBlankLinesInRawStrings(self):2887 error_collector = ErrorCollector(self.assert_)2888 cpplint.ProcessFileData('foo.cc', 'cc',2889 ['// Copyright 2014 Your Company.',2890 'static const char *kData[] = {R"(',2891 '',2892 ')", R"(',2893 '',2894 ')"};',2895 ''],2896 error_collector)2897 self.assertEquals('', error_collector.Results())2898 def testElseOnSameLineAsClosingBraces(self):2899 error_collector = ErrorCollector(self.assert_)2900 cpplint.ProcessFileData('foo.cc', 'cc',2901 ['if (hoge) {',2902 '}',2903 'else if (piyo) {', # Warning on this line2904 '}',2905 ' else {' # Warning on this line2906 '',2907 '}'],2908 error_collector)2909 self.assertEquals(2, error_collector.Results().count(2910 'An else should appear on the same line as the preceding }'2911 ' [whitespace/newline] [4]'))2912 error_collector = ErrorCollector(self.assert_)2913 cpplint.ProcessFileData('foo.cc', 'cc',2914 ['if (hoge) {',2915 '',2916 '}',2917 'else', # Warning on this line2918 '{',2919 '',2920 '}'],2921 error_collector)2922 self.assertEquals(1, error_collector.Results().count(2923 'An else should appear on the same line as the preceding }'2924 ' [whitespace/newline] [4]'))2925 error_collector = ErrorCollector(self.assert_)2926 cpplint.ProcessFileData('foo.cc', 'cc',2927 ['if (hoge) {',2928 '',2929 '}',2930 'else_function();'],2931 error_collector)2932 self.assertEquals(0, error_collector.Results().count(2933 'An else should appear on the same line as the preceding }'2934 ' [whitespace/newline] [4]'))2935 def testMultipleStatementsOnSameLine(self):2936 error_collector = ErrorCollector(self.assert_)2937 cpplint.ProcessFileData('foo.cc', 'cc',2938 ['for (int i = 0; i < 1; i++) {}',2939 'switch (x) {',2940 ' case 0: func(); break; ',2941 '}',2942 'sum += MathUtil::SafeIntRound(x); x += 0.1;'],2943 error_collector)2944 self.assertEquals(0, error_collector.Results().count(2945 'More than one command on the same line [whitespace/newline] [0]'))2946 old_verbose_level = cpplint._cpplint_state.verbose_level2947 cpplint._cpplint_state.verbose_level = 02948 cpplint.ProcessFileData('foo.cc', 'cc',2949 ['sum += MathUtil::SafeIntRound(x); x += 0.1;'],2950 error_collector)2951 cpplint._cpplint_state.verbose_level = old_verbose_level2952 def testEndOfNamespaceComments(self):2953 error_collector = ErrorCollector(self.assert_)2954 cpplint.ProcessFileData('foo.cc', 'cc',2955 ['namespace {',2956 '',2957 '}', # No warning (too short)2958 'namespace expected {',2959 '} // namespace mismatched', # Warning here2960 'namespace {',2961 '} // namespace mismatched', # Warning here2962 'namespace outer { namespace nested {'] +2963 ([''] * 10) +2964 ['}', # Warning here2965 '}', # Warning here2966 'namespace {'] +2967 ([''] * 10) +2968 ['}', # Warning here2969 'namespace {'] +2970 ([''] * 10) +2971 ['} // namespace some description', # Anon warning2972 'namespace {'] +2973 ([''] * 10) +2974 ['} // namespace anonymous', # Variant warning2975 'namespace {'] +2976 ([''] * 10) +2977 ['} // anonymous namespace (utils)', # Variant2978 'namespace {'] +2979 ([''] * 10) +2980 ['} // anonymous namespace', # No warning2981 'namespace missing_comment {'] +2982 ([''] * 10) +2983 ['}', # Warning here2984 'namespace no_warning {'] +2985 ([''] * 10) +2986 ['} // namespace no_warning',2987 'namespace no_warning {'] +2988 ([''] * 10) +2989 ['}; // end namespace no_warning',2990 '#define MACRO \\',2991 'namespace c_style { \\'] +2992 (['\\'] * 10) +2993 ['} /* namespace c_style. */ \\',2994 ';'],2995 error_collector)2996 self.assertEquals(1, error_collector.Results().count(2997 'Namespace should be terminated with "// namespace expected"'2998 ' [readability/namespace] [5]'))2999 self.assertEquals(1, error_collector.Results().count(3000 'Namespace should be terminated with "// namespace outer"'3001 ' [readability/namespace] [5]'))3002 self.assertEquals(1, error_collector.Results().count(3003 'Namespace should be terminated with "// namespace nested"'3004 ' [readability/namespace] [5]'))3005 self.assertEquals(3, error_collector.Results().count(3006 'Anonymous namespace should be terminated with "// namespace"'3007 ' [readability/namespace] [5]'))3008 self.assertEquals(2, error_collector.Results().count(3009 'Anonymous namespace should be terminated with "// namespace" or'3010 ' "// anonymous namespace"'3011 ' [readability/namespace] [5]'))3012 self.assertEquals(1, error_collector.Results().count(3013 'Namespace should be terminated with "// namespace missing_comment"'3014 ' [readability/namespace] [5]'))3015 self.assertEquals(0, error_collector.Results().count(3016 'Namespace should be terminated with "// namespace no_warning"'3017 ' [readability/namespace] [5]'))3018 def testElseClauseNotOnSameLineAsElse(self):3019 self.TestLint(' else DoSomethingElse();',3020 'Else clause should never be on same line as else '3021 '(use 2 lines) [whitespace/newline] [4]')3022 self.TestLint(' else ifDoSomethingElse();',3023 'Else clause should never be on same line as else '3024 '(use 2 lines) [whitespace/newline] [4]')3025 self.TestLint(' } else if (blah) {', '')3026 self.TestLint(' variable_ends_in_else = true;', '')3027 def testComma(self):3028 self.TestLint('a = f(1,2);',3029 'Missing space after , [whitespace/comma] [3]')3030 self.TestLint('int tmp=a,a=b,b=tmp;',3031 ['Missing spaces around = [whitespace/operators] [4]',3032 'Missing space after , [whitespace/comma] [3]'])3033 self.TestLint('f(a, /* name */ b);', '')3034 self.TestLint('f(a, /* name */b);', '')3035 self.TestLint('f(a, /* name */-1);', '')3036 self.TestLint('f(a, /* name */"1");', '')3037 self.TestLint('f(1, /* empty macro arg */, 2)', '')3038 self.TestLint('f(1,, 2)', '')3039 self.TestLint('operator,()', '')3040 self.TestLint('operator,(a,b)',3041 'Missing space after , [whitespace/comma] [3]')3042 def testEqualsOperatorSpacing(self):3043 self.TestLint('int tmp= a;',3044 'Missing spaces around = [whitespace/operators] [4]')3045 self.TestLint('int tmp =a;',3046 'Missing spaces around = [whitespace/operators] [4]')3047 self.TestLint('int tmp=a;',3048 'Missing spaces around = [whitespace/operators] [4]')3049 self.TestLint('int tmp= 7;',3050 'Missing spaces around = [whitespace/operators] [4]')3051 self.TestLint('int tmp =7;',3052 'Missing spaces around = [whitespace/operators] [4]')3053 self.TestLint('int tmp=7;',3054 'Missing spaces around = [whitespace/operators] [4]')3055 self.TestLint('int* tmp=*p;',3056 'Missing spaces around = [whitespace/operators] [4]')3057 self.TestLint('int* tmp= *p;',3058 'Missing spaces around = [whitespace/operators] [4]')3059 self.TestMultiLineLint(3060 TrimExtraIndent('''3061 lookahead_services_=3062 ::strings::Split(FLAGS_ls, ",", ::strings::SkipEmpty());'''),3063 'Missing spaces around = [whitespace/operators] [4]')3064 self.TestLint('bool result = a>=42;',3065 'Missing spaces around >= [whitespace/operators] [3]')3066 self.TestLint('bool result = a<=42;',3067 'Missing spaces around <= [whitespace/operators] [3]')3068 self.TestLint('bool result = a==42;',3069 'Missing spaces around == [whitespace/operators] [3]')3070 self.TestLint('auto result = a!=42;',3071 'Missing spaces around != [whitespace/operators] [3]')3072 self.TestLint('int a = b!=c;',3073 'Missing spaces around != [whitespace/operators] [3]')3074 self.TestLint('a&=42;', '')3075 self.TestLint('a|=42;', '')3076 self.TestLint('a^=42;', '')3077 self.TestLint('a+=42;', '')3078 self.TestLint('a*=42;', '')3079 self.TestLint('a/=42;', '')3080 self.TestLint('a%=42;', '')3081 self.TestLint('a>>=5;', '')3082 self.TestLint('a<<=5;', '')3083 def testShiftOperatorSpacing(self):3084 self.TestLint('a<<b',3085 'Missing spaces around << [whitespace/operators] [3]')3086 self.TestLint('a>>b',3087 'Missing spaces around >> [whitespace/operators] [3]')3088 self.TestLint('1<<20', '')3089 self.TestLint('1024>>10', '')3090 self.TestLint('Kernel<<<1, 2>>>()', '')3091 def testIndent(self):3092 self.TestLint('static int noindent;', '')3093 self.TestLint(' int two_space_indent;', '')3094 self.TestLint(' int four_space_indent;', '')3095 self.TestLint(' int one_space_indent;',3096 'Weird number of spaces at line-start. '3097 'Are you using a 2-space indent? [whitespace/indent] [3]')3098 self.TestLint(' int three_space_indent;',3099 'Weird number of spaces at line-start. '3100 'Are you using a 2-space indent? [whitespace/indent] [3]')3101 self.TestLint(' char* one_space_indent = "public:";',3102 'Weird number of spaces at line-start. '3103 'Are you using a 2-space indent? [whitespace/indent] [3]')3104 self.TestLint(' public:', '')3105 self.TestLint(' protected:', '')3106 self.TestLint(' private:', '')3107 self.TestLint(' protected: \\', '')3108 self.TestLint(' public: \\', '')3109 self.TestLint(' private: \\', '')3110 self.TestMultiLineLint(3111 TrimExtraIndent("""3112 class foo {3113 public slots:3114 void bar();3115 };"""),3116 'Weird number of spaces at line-start. '3117 'Are you using a 2-space indent? [whitespace/indent] [3]')3118 self.TestMultiLineLint(3119 TrimExtraIndent('''3120 static const char kRawString[] = R"("3121 ")";'''),3122 '')3123 self.TestMultiLineLint(3124 TrimExtraIndent('''3125 static const char kNotRawString[] = "("3126 ")";'''),3127 'Weird number of spaces at line-start. '3128 'Are you using a 2-space indent? [whitespace/indent] [3]')3129 self.TestMultiLineLint(3130 ' static const char kSingleLineRawString[] = R"(...)";',3131 'Weird number of spaces at line-start. '3132 'Are you using a 2-space indent? [whitespace/indent] [3]')3133 def testSectionIndent(self):3134 self.TestMultiLineLint(3135 """3136 class A {3137 public: // no warning3138 private: // warning here3139 };""",3140 'private: should be indented +1 space inside class A'3141 ' [whitespace/indent] [3]')3142 self.TestMultiLineLint(3143 """3144 class B {3145 public: // no warning3146 template<> struct C {3147 public: // warning here3148 protected: // no warning3149 };3150 };""",3151 'public: should be indented +1 space inside struct C'3152 ' [whitespace/indent] [3]')3153 self.TestMultiLineLint(3154 """3155 struct D {3156 };""",3157 'Closing brace should be aligned with beginning of struct D'3158 ' [whitespace/indent] [3]')3159 self.TestMultiLineLint(3160 """3161 template<typename E> class F {3162 };""",3163 'Closing brace should be aligned with beginning of class F'3164 ' [whitespace/indent] [3]')3165 self.TestMultiLineLint(3166 """3167 class G {3168 Q_OBJECT3169 public slots:3170 signals:3171 };""",3172 ['public slots: should be indented +1 space inside class G'3173 ' [whitespace/indent] [3]',3174 'signals: should be indented +1 space inside class G'3175 ' [whitespace/indent] [3]'])3176 self.TestMultiLineLint(3177 """3178 class H {3179 /* comments */ class I {3180 public: // no warning3181 private: // warning here3182 };3183 };""",3184 'private: should be indented +1 space inside class I'3185 ' [whitespace/indent] [3]')3186 self.TestMultiLineLint(3187 """3188 class J3189 : public ::K {3190 public: // no warning3191 protected: // warning here3192 };""",3193 'protected: should be indented +1 space inside class J'3194 ' [whitespace/indent] [3]')3195 self.TestMultiLineLint(3196 """3197 class L3198 : public M,3199 public ::N {3200 };""",3201 '')3202 self.TestMultiLineLint(3203 """3204 template <class O,3205 class P,3206 class Q,3207 typename R>3208 static void Func() {3209 }""",3210 '')3211 def testConditionals(self):3212 self.TestMultiLineLint(3213 """3214 if (foo)3215 goto fail;3216 goto fail;""",3217 'If/else bodies with multiple statements require braces'3218 ' [readability/braces] [4]')3219 self.TestMultiLineLint(3220 """3221 if (foo)3222 goto fail; goto fail;""",3223 'If/else bodies with multiple statements require braces'3224 ' [readability/braces] [4]')3225 self.TestMultiLineLint(3226 """3227 if (foo)3228 foo;3229 else3230 goto fail;3231 goto fail;""",3232 'If/else bodies with multiple statements require braces'3233 ' [readability/braces] [4]')3234 self.TestMultiLineLint(3235 """3236 if (foo) goto fail;3237 goto fail;""",3238 'If/else bodies with multiple statements require braces'3239 ' [readability/braces] [4]')3240 self.TestMultiLineLint(3241 """3242 if (foo)3243 if (bar)3244 baz;3245 else3246 qux;""",3247 'Else clause should be indented at the same level as if. Ambiguous'3248 ' nested if/else chains require braces. [readability/braces] [4]')3249 self.TestMultiLineLint(3250 """3251 if (foo)3252 if (bar)3253 baz;3254 else3255 qux;""",3256 'Else clause should be indented at the same level as if. Ambiguous'3257 ' nested if/else chains require braces. [readability/braces] [4]')3258 self.TestMultiLineLint(3259 """3260 if (foo) {3261 bar;3262 baz;3263 } else3264 qux;""",3265 'If an else has a brace on one side, it should have it on both'3266 ' [readability/braces] [5]')3267 self.TestMultiLineLint(3268 """3269 if (foo)3270 bar;3271 else {3272 baz;3273 }""",3274 'If an else has a brace on one side, it should have it on both'3275 ' [readability/braces] [5]')3276 self.TestMultiLineLint(3277 """3278 if (foo)3279 bar;3280 else if (baz) {3281 qux;3282 }""",3283 'If an else has a brace on one side, it should have it on both'3284 ' [readability/braces] [5]')3285 self.TestMultiLineLint(3286 """3287 if (foo) {3288 bar;3289 } else if (baz)3290 qux;""",3291 'If an else has a brace on one side, it should have it on both'3292 ' [readability/braces] [5]')3293 self.TestMultiLineLint(3294 """3295 if (foo)3296 goto fail;3297 bar;""",3298 '')3299 self.TestMultiLineLint(3300 """3301 if (foo3302 && bar) {3303 baz;3304 qux;3305 }""",3306 '')3307 self.TestMultiLineLint(3308 """3309 if (foo)3310 goto3311 fail;""",3312 '')3313 self.TestMultiLineLint(3314 """3315 if (foo)3316 bar;3317 else3318 baz;3319 qux;""",3320 '')3321 self.TestMultiLineLint(3322 """3323 for (;;) {3324 if (foo)3325 bar;3326 else3327 baz;3328 }""",3329 '')3330 self.TestMultiLineLint(3331 """3332 if (foo)3333 bar;3334 else if (baz)3335 baz;""",3336 '')3337 self.TestMultiLineLint(3338 """3339 if (foo)3340 bar;3341 else3342 baz;""",3343 '')3344 self.TestMultiLineLint(3345 """3346 if (foo) {3347 bar;3348 } else {3349 baz;3350 }""",3351 '')3352 self.TestMultiLineLint(3353 """3354 if (foo) {3355 bar;3356 } else if (baz) {3357 qux;3358 }""",3359 '')3360 # Note: this is an error for a different reason, but should not trigger the3361 # single-line if error.3362 self.TestMultiLineLint(3363 """3364 if (foo)3365 {3366 bar;3367 baz;3368 }""",3369 '{ should almost always be at the end of the previous line'3370 ' [whitespace/braces] [4]')3371 self.TestMultiLineLint(3372 """3373 if (foo) { \\3374 bar; \\3375 baz; \\3376 }""",3377 '')3378 self.TestMultiLineLint(3379 """3380 void foo() { if (bar) baz; }""",3381 '')3382 self.TestMultiLineLint(3383 """3384 #if foo3385 bar;3386 #else3387 baz;3388 qux;3389 #endif""",3390 '')3391 self.TestMultiLineLint(3392 """void F() {3393 variable = [] { if (true); };3394 variable =3395 [] { if (true); };3396 Call(3397 [] { if (true); },3398 [] { if (true); });3399 }""",3400 '')3401 def testTab(self):3402 self.TestLint('\tint a;',3403 'Tab found; better to use spaces [whitespace/tab] [1]')3404 self.TestLint('int a = 5;\t\t// set a to 5',3405 'Tab found; better to use spaces [whitespace/tab] [1]')3406 def testParseArguments(self):3407 old_usage = cpplint._USAGE3408 old_error_categories = cpplint._ERROR_CATEGORIES3409 old_output_format = cpplint._cpplint_state.output_format3410 old_verbose_level = cpplint._cpplint_state.verbose_level3411 old_filters = cpplint._cpplint_state.filters3412 old_line_length = cpplint._line_length3413 old_valid_extensions = cpplint._valid_extensions3414 try:3415 # Don't print usage during the tests, or filter categories3416 cpplint._USAGE = ''3417 cpplint._ERROR_CATEGORIES = ''3418 self.assertRaises(SystemExit, cpplint.ParseArguments, [])3419 self.assertRaises(SystemExit, cpplint.ParseArguments, ['--badopt'])3420 self.assertRaises(SystemExit, cpplint.ParseArguments, ['--help'])3421 self.assertRaises(SystemExit, cpplint.ParseArguments, ['--v=0'])3422 self.assertRaises(SystemExit, cpplint.ParseArguments, ['--filter='])3423 # This is illegal because all filters must start with + or -3424 self.assertRaises(SystemExit, cpplint.ParseArguments, ['--filter=foo'])3425 self.assertRaises(SystemExit, cpplint.ParseArguments,3426 ['--filter=+a,b,-c'])3427 self.assertEquals(['foo.cc'], cpplint.ParseArguments(['foo.cc']))3428 self.assertEquals(old_output_format, cpplint._cpplint_state.output_format)3429 self.assertEquals(old_verbose_level, cpplint._cpplint_state.verbose_level)3430 self.assertEquals(['foo.cc'],3431 cpplint.ParseArguments(['--v=1', 'foo.cc']))3432 self.assertEquals(1, cpplint._cpplint_state.verbose_level)3433 self.assertEquals(['foo.h'],3434 cpplint.ParseArguments(['--v=3', 'foo.h']))3435 self.assertEquals(3, cpplint._cpplint_state.verbose_level)3436 self.assertEquals(['foo.cpp'],3437 cpplint.ParseArguments(['--verbose=5', 'foo.cpp']))3438 self.assertEquals(5, cpplint._cpplint_state.verbose_level)3439 self.assertRaises(ValueError,3440 cpplint.ParseArguments, ['--v=f', 'foo.cc'])3441 self.assertEquals(['foo.cc'],3442 cpplint.ParseArguments(['--output=emacs', 'foo.cc']))3443 self.assertEquals('emacs', cpplint._cpplint_state.output_format)3444 self.assertEquals(['foo.h'],3445 cpplint.ParseArguments(['--output=vs7', 'foo.h']))3446 self.assertEquals('vs7', cpplint._cpplint_state.output_format)3447 self.assertRaises(SystemExit,3448 cpplint.ParseArguments, ['--output=blah', 'foo.cc'])3449 filt = '-,+whitespace,-whitespace/indent'3450 self.assertEquals(['foo.h'],3451 cpplint.ParseArguments(['--filter='+filt, 'foo.h']))3452 self.assertEquals(['-', '+whitespace', '-whitespace/indent'],3453 cpplint._cpplint_state.filters)3454 self.assertEquals(['foo.cc', 'foo.h'],3455 cpplint.ParseArguments(['foo.cc', 'foo.h']))3456 self.assertEqual(['foo.h'],3457 cpplint.ParseArguments(['--linelength=120', 'foo.h']))3458 self.assertEqual(120, cpplint._line_length)3459 self.assertEqual(['foo.h'],3460 cpplint.ParseArguments(['--extensions=hpp,cpp,cpp', 'foo.h']))3461 self.assertEqual(set(['hpp', 'cpp']), cpplint._valid_extensions)3462 finally:3463 cpplint._USAGE = old_usage3464 cpplint._ERROR_CATEGORIES = old_error_categories3465 cpplint._cpplint_state.output_format = old_output_format3466 cpplint._cpplint_state.verbose_level = old_verbose_level3467 cpplint._cpplint_state.filters = old_filters3468 cpplint._line_length = old_line_length3469 cpplint._valid_extensions = old_valid_extensions3470 def testLineLength(self):3471 old_line_length = cpplint._line_length3472 try:3473 cpplint._line_length = 803474 self.TestLint(3475 '// %s' % ('H' * 77),3476 '')3477 self.TestLint(3478 '// %s' % ('H' * 78),3479 'Lines should be <= 80 characters long'3480 ' [whitespace/line_length] [2]')3481 cpplint._line_length = 1203482 self.TestLint(3483 '// %s' % ('H' * 117),3484 '')3485 self.TestLint(3486 '// %s' % ('H' * 118),3487 'Lines should be <= 120 characters long'3488 ' [whitespace/line_length] [2]')3489 finally:3490 cpplint._line_length = old_line_length3491 def testFilter(self):3492 old_filters = cpplint._cpplint_state.filters3493 try:3494 cpplint._cpplint_state.SetFilters('-,+whitespace,-whitespace/indent')3495 self.TestLint(3496 '// Hello there ',3497 'Line ends in whitespace. Consider deleting these extra spaces.'3498 ' [whitespace/end_of_line] [4]')3499 self.TestLint('int a = (int)1.0;', '')3500 self.TestLint(' weird opening space', '')3501 finally:3502 cpplint._cpplint_state.filters = old_filters3503 def testDefaultFilter(self):3504 default_filters = cpplint._DEFAULT_FILTERS3505 old_filters = cpplint._cpplint_state.filters3506 cpplint._DEFAULT_FILTERS = ['-whitespace']3507 try:3508 # Reset filters3509 cpplint._cpplint_state.SetFilters('')3510 self.TestLint('// Hello there ', '')3511 cpplint._cpplint_state.SetFilters('+whitespace/end_of_line')3512 self.TestLint(3513 '// Hello there ',3514 'Line ends in whitespace. Consider deleting these extra spaces.'3515 ' [whitespace/end_of_line] [4]')3516 self.TestLint(' weird opening space', '')3517 finally:3518 cpplint._cpplint_state.filters = old_filters3519 cpplint._DEFAULT_FILTERS = default_filters3520 def testDuplicateHeader(self):3521 error_collector = ErrorCollector(self.assert_)3522 cpplint.ProcessFileData('path/self.cc', 'cc',3523 ['// Copyright 2014 Your Company. All Rights Reserved.',3524 '#include "path/self.h"',3525 '#include "path/duplicate.h"',3526 '#include "path/duplicate.h"',3527 '#ifdef MACRO',3528 '#include "path/unique.h"',3529 '#else',3530 '#include "path/unique.h"',3531 '#endif',3532 ''],3533 error_collector)3534 self.assertEquals(3535 ['"path/duplicate.h" already included at path/self.cc:3 '3536 '[build/include] [4]'],3537 error_collector.ResultList())3538 def testUnnamedNamespacesInHeaders(self):3539 self.TestLanguageRulesCheck(3540 'foo.h', 'namespace {',3541 'Do not use unnamed namespaces in header files. See'3542 ' http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'3543 ' for more information. [build/namespaces] [4]')3544 # namespace registration macros are OK.3545 self.TestLanguageRulesCheck('foo.h', 'namespace { \\', '')3546 # named namespaces are OK.3547 self.TestLanguageRulesCheck('foo.h', 'namespace foo {', '')3548 self.TestLanguageRulesCheck('foo.h', 'namespace foonamespace {', '')3549 self.TestLanguageRulesCheck('foo.cc', 'namespace {', '')3550 self.TestLanguageRulesCheck('foo.cc', 'namespace foo {', '')3551 def testBuildClass(self):3552 # Test that the linter can parse to the end of class definitions,3553 # and that it will report when it can't.3554 # Use multi-line linter because it performs the ClassState check.3555 self.TestMultiLineLint(3556 'class Foo {',3557 'Failed to find complete declaration of class Foo'3558 ' [build/class] [5]')3559 # Do the same for namespaces3560 self.TestMultiLineLint(3561 'namespace Foo {',3562 'Failed to find complete declaration of namespace Foo'3563 ' [build/namespaces] [5]')3564 # Don't warn on forward declarations of various types.3565 self.TestMultiLineLint(3566 'class Foo;',3567 '')3568 self.TestMultiLineLint(3569 """struct Foo*3570 foo = NewFoo();""",3571 '')3572 # Test preprocessor.3573 self.TestMultiLineLint(3574 """#ifdef DERIVE_FROM_GOO3575 struct Foo : public Goo {3576 #else3577 struct Foo : public Hoo {3578 #endif3579 };""",3580 '')3581 self.TestMultiLineLint(3582 """3583 class Foo3584 #ifdef DERIVE_FROM_GOO3585 : public Goo {3586 #else3587 : public Hoo {3588 #endif3589 };""",3590 '')3591 # Test incomplete class3592 self.TestMultiLineLint(3593 'class Foo {',3594 'Failed to find complete declaration of class Foo'3595 ' [build/class] [5]')3596 def testBuildEndComment(self):3597 # The crosstool compiler we currently use will fail to compile the3598 # code in this test, so we might consider removing the lint check.3599 self.TestMultiLineLint(3600 """#if 03601 #endif Not a comment""",3602 'Uncommented text after #endif is non-standard. Use a comment.'3603 ' [build/endif_comment] [5]')3604 def testBuildForwardDecl(self):3605 # The crosstool compiler we currently use will fail to compile the3606 # code in this test, so we might consider removing the lint check.3607 self.TestLint('class Foo::Goo;',3608 'Inner-style forward declarations are invalid.'3609 ' Remove this line.'3610 ' [build/forward_decl] [5]')3611 def GetBuildHeaderGuardPreprocessorSymbol(self, file_path):3612 # Figure out the expected header guard by processing an empty file.3613 error_collector = ErrorCollector(self.assert_)3614 cpplint.ProcessFileData(file_path, 'h', [], error_collector)3615 for error in error_collector.ResultList():3616 matched = re.search(3617 'No #ifndef header guard found, suggested CPP variable is: ([A-Z_]+)',3618 error)3619 if matched is not None:3620 return matched.group(1)3621 def testBuildHeaderGuard(self):3622 file_path = 'mydir/foo.h'3623 expected_guard = self.GetBuildHeaderGuardPreprocessorSymbol(file_path)3624 self.assertTrue(re.search('MYDIR_FOO_H_$', expected_guard))3625 # No guard at all: expect one error.3626 error_collector = ErrorCollector(self.assert_)3627 cpplint.ProcessFileData(file_path, 'h', [], error_collector)3628 self.assertEquals(3629 1,3630 error_collector.ResultList().count(3631 'No #ifndef header guard found, suggested CPP variable is: %s'3632 ' [build/header_guard] [5]' % expected_guard),3633 error_collector.ResultList())3634 # No header guard, but the error is suppressed.3635 error_collector = ErrorCollector(self.assert_)3636 cpplint.ProcessFileData(file_path, 'h',3637 ['// Copyright 2014 Your Company.',3638 '// NOLINT(build/header_guard)', ''],3639 error_collector)3640 self.assertEquals([], error_collector.ResultList())3641 # Wrong guard3642 error_collector = ErrorCollector(self.assert_)3643 cpplint.ProcessFileData(file_path, 'h',3644 ['#ifndef FOO_H', '#define FOO_H'], error_collector)3645 self.assertEquals(3646 1,3647 error_collector.ResultList().count(3648 '#ifndef header guard has wrong style, please use: %s'3649 ' [build/header_guard] [5]' % expected_guard),3650 error_collector.ResultList())3651 # No define3652 error_collector = ErrorCollector(self.assert_)3653 cpplint.ProcessFileData(file_path, 'h',3654 ['#ifndef %s' % expected_guard], error_collector)3655 self.assertEquals(3656 1,3657 error_collector.ResultList().count(3658 'No #ifndef header guard found, suggested CPP variable is: %s'3659 ' [build/header_guard] [5]' % expected_guard),3660 error_collector.ResultList())3661 # Mismatched define3662 error_collector = ErrorCollector(self.assert_)3663 cpplint.ProcessFileData(file_path, 'h',3664 ['#ifndef %s' % expected_guard,3665 '#define FOO_H'],3666 error_collector)3667 self.assertEquals(3668 1,3669 error_collector.ResultList().count(3670 'No #ifndef header guard found, suggested CPP variable is: %s'3671 ' [build/header_guard] [5]' % expected_guard),3672 error_collector.ResultList())3673 # No endif3674 error_collector = ErrorCollector(self.assert_)3675 cpplint.ProcessFileData(file_path, 'h',3676 ['#ifndef %s' % expected_guard,3677 '#define %s' % expected_guard,3678 ''],3679 error_collector)3680 self.assertEquals(3681 1,3682 error_collector.ResultList().count(3683 '#endif line should be "#endif // %s"'3684 ' [build/header_guard] [5]' % expected_guard),3685 error_collector.ResultList())3686 # Commentless endif3687 error_collector = ErrorCollector(self.assert_)3688 cpplint.ProcessFileData(file_path, 'h',3689 ['#ifndef %s' % expected_guard,3690 '#define %s' % expected_guard,3691 '#endif'],3692 error_collector)3693 self.assertEquals(3694 1,3695 error_collector.ResultList().count(3696 '#endif line should be "#endif // %s"'3697 ' [build/header_guard] [5]' % expected_guard),3698 error_collector.ResultList())3699 # Commentless endif for old-style guard3700 error_collector = ErrorCollector(self.assert_)3701 cpplint.ProcessFileData(file_path, 'h',3702 ['#ifndef %s_' % expected_guard,3703 '#define %s_' % expected_guard,3704 '#endif'],3705 error_collector)3706 self.assertEquals(3707 1,3708 error_collector.ResultList().count(3709 '#endif line should be "#endif // %s"'3710 ' [build/header_guard] [5]' % expected_guard),3711 error_collector.ResultList())3712 # No header guard errors3713 error_collector = ErrorCollector(self.assert_)3714 cpplint.ProcessFileData(file_path, 'h',3715 ['#ifndef %s' % expected_guard,3716 '#define %s' % expected_guard,3717 '#endif // %s' % expected_guard],3718 error_collector)3719 for line in error_collector.ResultList():3720 if line.find('build/header_guard') != -1:3721 self.fail('Unexpected error: %s' % line)3722 # No header guard errors for old-style guard3723 error_collector = ErrorCollector(self.assert_)3724 cpplint.ProcessFileData(file_path, 'h',3725 ['#ifndef %s_' % expected_guard,3726 '#define %s_' % expected_guard,3727 '#endif // %s_' % expected_guard],3728 error_collector)3729 for line in error_collector.ResultList():3730 if line.find('build/header_guard') != -1:3731 self.fail('Unexpected error: %s' % line)3732 old_verbose_level = cpplint._cpplint_state.verbose_level3733 try:3734 cpplint._cpplint_state.verbose_level = 03735 # Warn on old-style guard if verbosity is 0.3736 error_collector = ErrorCollector(self.assert_)3737 cpplint.ProcessFileData(file_path, 'h',3738 ['#ifndef %s_' % expected_guard,3739 '#define %s_' % expected_guard,3740 '#endif // %s_' % expected_guard],3741 error_collector)3742 self.assertEquals(3743 1,3744 error_collector.ResultList().count(3745 '#ifndef header guard has wrong style, please use: %s'3746 ' [build/header_guard] [0]' % expected_guard),3747 error_collector.ResultList())3748 finally:3749 cpplint._cpplint_state.verbose_level = old_verbose_level3750 # Completely incorrect header guard3751 error_collector = ErrorCollector(self.assert_)3752 cpplint.ProcessFileData(file_path, 'h',3753 ['#ifndef FOO',3754 '#define FOO',3755 '#endif // FOO'],3756 error_collector)3757 self.assertEquals(3758 1,3759 error_collector.ResultList().count(3760 '#ifndef header guard has wrong style, please use: %s'3761 ' [build/header_guard] [5]' % expected_guard),3762 error_collector.ResultList())3763 self.assertEquals(3764 1,3765 error_collector.ResultList().count(3766 '#endif line should be "#endif // %s"'3767 ' [build/header_guard] [5]' % expected_guard),3768 error_collector.ResultList())3769 # incorrect header guard with nolint3770 error_collector = ErrorCollector(self.assert_)3771 cpplint.ProcessFileData(file_path, 'h',3772 ['#ifndef FOO // NOLINT',3773 '#define FOO',3774 '#endif // FOO NOLINT'],3775 error_collector)3776 self.assertEquals(3777 0,3778 error_collector.ResultList().count(3779 '#ifndef header guard has wrong style, please use: %s'3780 ' [build/header_guard] [5]' % expected_guard),3781 error_collector.ResultList())3782 self.assertEquals(3783 0,3784 error_collector.ResultList().count(3785 '#endif line should be "#endif // %s"'3786 ' [build/header_guard] [5]' % expected_guard),3787 error_collector.ResultList())3788 # Special case for flymake3789 for test_file in ['mydir/foo_flymake.h', 'mydir/.flymake/foo.h']:3790 error_collector = ErrorCollector(self.assert_)3791 cpplint.ProcessFileData(test_file, 'h',3792 ['// Copyright 2014 Your Company.', ''],3793 error_collector)3794 self.assertEquals(3795 1,3796 error_collector.ResultList().count(3797 'No #ifndef header guard found, suggested CPP variable is: %s'3798 ' [build/header_guard] [5]' % expected_guard),3799 error_collector.ResultList())3800 def testBuildHeaderGuardWithRoot(self):3801 file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),3802 'cpplint_test_header.h')3803 file_info = cpplint.FileInfo(file_path)3804 if file_info.FullName() == file_info.RepositoryName():3805 # When FileInfo cannot deduce the root directory of the repository,3806 # FileInfo.RepositoryName returns the same value as FileInfo.FullName.3807 # This can happen when this source file was obtained without .svn or3808 # .git directory. (e.g. using 'svn export' or 'git archive').3809 # Skip this test in such a case because --root flag makes sense only3810 # when the root directory of the repository is properly deduced.3811 return3812 self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',3813 cpplint.GetHeaderGuardCPPVariable(file_path))3814 cpplint._root = 'cpplint'3815 self.assertEquals('CPPLINT_TEST_HEADER_H_',3816 cpplint.GetHeaderGuardCPPVariable(file_path))3817 # --root flag is ignored if an non-existent directory is specified.3818 cpplint._root = 'NON_EXISTENT_DIR'3819 self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',3820 cpplint.GetHeaderGuardCPPVariable(file_path))3821 def testBuildInclude(self):3822 # Test that include statements have slashes in them.3823 self.TestLint('#include "foo.h"',3824 'Include the directory when naming .h files'3825 ' [build/include] [4]')3826 self.TestLint('#include "Python.h"', '')3827 self.TestLint('#include "lua.h"', '')3828 def testBuildPrintfFormat(self):3829 error_collector = ErrorCollector(self.assert_)3830 cpplint.ProcessFileData(3831 'foo.cc', 'cc',3832 [r'printf("\%%d", value);',3833 r'snprintf(buffer, sizeof(buffer), "\[%d", value);',3834 r'fprintf(file, "\(%d", value);',3835 r'vsnprintf(buffer, sizeof(buffer), "\\\{%d", ap);'],3836 error_collector)3837 self.assertEquals(3838 4,3839 error_collector.Results().count(3840 '%, [, (, and { are undefined character escapes. Unescape them.'3841 ' [build/printf_format] [3]'))3842 error_collector = ErrorCollector(self.assert_)3843 cpplint.ProcessFileData(3844 'foo.cc', 'cc',3845 ['// Copyright 2014 Your Company.',3846 r'printf("\\%%%d", value);',3847 r'printf(R"(\[)");',3848 r'printf(R"(\[%s)", R"(\])");',3849 ''],3850 error_collector)3851 self.assertEquals('', error_collector.Results())3852 def testRuntimePrintfFormat(self):3853 self.TestLint(3854 r'fprintf(file, "%q", value);',3855 '%q in format strings is deprecated. Use %ll instead.'3856 ' [runtime/printf_format] [3]')3857 self.TestLint(3858 r'aprintf(file, "The number is %12q", value);',3859 '%q in format strings is deprecated. Use %ll instead.'3860 ' [runtime/printf_format] [3]')3861 self.TestLint(3862 r'printf(file, "The number is" "%-12q", value);',3863 '%q in format strings is deprecated. Use %ll instead.'3864 ' [runtime/printf_format] [3]')3865 self.TestLint(3866 r'printf(file, "The number is" "%+12q", value);',3867 '%q in format strings is deprecated. Use %ll instead.'3868 ' [runtime/printf_format] [3]')3869 self.TestLint(3870 r'printf(file, "The number is" "% 12q", value);',3871 '%q in format strings is deprecated. Use %ll instead.'3872 ' [runtime/printf_format] [3]')3873 self.TestLint(3874 r'snprintf(file, "Never mix %d and %1$d parameters!", value);',3875 '%N$ formats are unconventional. Try rewriting to avoid them.'3876 ' [runtime/printf_format] [2]')3877 def TestLintLogCodeOnError(self, code, expected_message):3878 # Special TestLint which logs the input code on error.3879 result = self.PerformSingleLineLint(code)3880 if result != expected_message:3881 self.fail('For code: "%s"\nGot: "%s"\nExpected: "%s"'3882 % (code, result, expected_message))3883 def testBuildStorageClass(self):3884 qualifiers = [None, 'const', 'volatile']3885 signs = [None, 'signed', 'unsigned']3886 types = ['void', 'char', 'int', 'float', 'double',3887 'schar', 'int8', 'uint8', 'int16', 'uint16',3888 'int32', 'uint32', 'int64', 'uint64']3889 storage_classes = ['extern', 'register', 'static', 'typedef']3890 build_storage_class_error_message = (3891 'Storage class (static, extern, typedef, etc) should be first.'3892 ' [build/storage_class] [5]')3893 # Some explicit cases. Legal in C++, deprecated in C99.3894 self.TestLint('const int static foo = 5;',3895 build_storage_class_error_message)3896 self.TestLint('char static foo;',3897 build_storage_class_error_message)3898 self.TestLint('double const static foo = 2.0;',3899 build_storage_class_error_message)3900 self.TestLint('uint64 typedef unsigned_long_long;',3901 build_storage_class_error_message)3902 self.TestLint('int register foo = 0;',3903 build_storage_class_error_message)3904 # Since there are a very large number of possibilities, randomly3905 # construct declarations.3906 # Make sure that the declaration is logged if there's an error.3907 # Seed generator with an integer for absolute reproducibility.3908 random.seed(25)3909 for unused_i in range(10):3910 # Build up random list of non-storage-class declaration specs.3911 other_decl_specs = [random.choice(qualifiers), random.choice(signs),3912 random.choice(types)]3913 # remove None3914 other_decl_specs = [x for x in other_decl_specs if x is not None]3915 # shuffle3916 random.shuffle(other_decl_specs)3917 # insert storage class after the first3918 storage_class = random.choice(storage_classes)3919 insertion_point = random.randint(1, len(other_decl_specs))3920 decl_specs = (other_decl_specs[0:insertion_point]3921 + [storage_class]3922 + other_decl_specs[insertion_point:])3923 self.TestLintLogCodeOnError(3924 ' '.join(decl_specs) + ';',3925 build_storage_class_error_message)3926 # but no error if storage class is first3927 self.TestLintLogCodeOnError(3928 storage_class + ' ' + ' '.join(other_decl_specs),3929 '')3930 def testLegalCopyright(self):3931 legal_copyright_message = (3932 'No copyright message found. '3933 'You should have a line: "Copyright [year] <Copyright Owner>"'3934 ' [legal/copyright] [5]')3935 copyright_line = '// Copyright 2014 Google Inc. All Rights Reserved.'3936 file_path = 'mydir/googleclient/foo.cc'3937 # There should be a copyright message in the first 10 lines3938 error_collector = ErrorCollector(self.assert_)3939 cpplint.ProcessFileData(file_path, 'cc', [], error_collector)3940 self.assertEquals(3941 1,3942 error_collector.ResultList().count(legal_copyright_message))3943 error_collector = ErrorCollector(self.assert_)3944 cpplint.ProcessFileData(3945 file_path, 'cc',3946 ['' for unused_i in range(10)] + [copyright_line],3947 error_collector)3948 self.assertEquals(3949 1,3950 error_collector.ResultList().count(legal_copyright_message))3951 # Test that warning isn't issued if Copyright line appears early enough.3952 error_collector = ErrorCollector(self.assert_)3953 cpplint.ProcessFileData(file_path, 'cc', [copyright_line], error_collector)3954 for message in error_collector.ResultList():3955 if message.find('legal/copyright') != -1:3956 self.fail('Unexpected error: %s' % message)3957 error_collector = ErrorCollector(self.assert_)3958 cpplint.ProcessFileData(3959 file_path, 'cc',3960 ['' for unused_i in range(9)] + [copyright_line],3961 error_collector)3962 for message in error_collector.ResultList():3963 if message.find('legal/copyright') != -1:3964 self.fail('Unexpected error: %s' % message)3965 def testInvalidIncrement(self):3966 self.TestLint('*count++;',3967 'Changing pointer instead of value (or unused value of '3968 'operator*). [runtime/invalid_increment] [5]')3969 def testSnprintfSize(self):3970 self.TestLint('vsnprintf(NULL, 0, format)', '')3971 self.TestLint('snprintf(fisk, 1, format)',3972 'If you can, use sizeof(fisk) instead of 1 as the 2nd arg '3973 'to snprintf. [runtime/printf] [3]')3974class Cxx11Test(CpplintTestBase):3975 def Helper(self, package, extension, lines, count):3976 filename = package + '/foo.' + extension3977 lines = lines[:]3978 # Header files need to have an ifdef guard wrapped around their code.3979 if extension == 'h':3980 guard = filename.upper().replace('/', '_').replace('.', '_') + '_'3981 lines.insert(0, '#ifndef ' + guard)3982 lines.insert(1, '#define ' + guard)3983 lines.append('#endif // ' + guard)3984 # All files need a final blank line.3985 lines.append('')3986 # Process the file and check resulting error count.3987 collector = ErrorCollector(self.assert_)3988 cpplint.ProcessFileData(filename, extension, lines, collector)3989 error_list = collector.ResultList()3990 self.assertEquals(count, len(error_list), error_list)3991 def TestCxx11Feature(self, code, expected_error):3992 lines = code.split('\n')3993 collector = ErrorCollector(self.assert_)3994 cpplint.RemoveMultiLineComments('foo.h', lines, collector)3995 clean_lines = cpplint.CleansedLines(lines)3996 cpplint.FlagCxx11Features('foo.cc', clean_lines, 0, collector)3997 self.assertEquals(expected_error, collector.Results())3998 def testBlockedHeaders(self):3999 self.TestCxx11Feature('#include <mutex>',4000 '<mutex> is an unapproved C++11 header.'4001 ' [build/c++11] [5]')4002 def testBlockedClasses(self):4003 self.TestCxx11Feature('std::alignment_of<T>',4004 'std::alignment_of is an unapproved '4005 'C++11 class or function. Send c-style an example '4006 'of where it would make your code more readable, '4007 'and they may let you use it.'4008 ' [build/c++11] [5]')4009 self.TestCxx11Feature('std::alignment_offer', '')4010 self.TestCxx11Feature('mystd::alignment_of', '')4011 self.TestCxx11Feature('std::binomial_distribution', '')4012 def testBlockedFunctions(self):4013 self.TestCxx11Feature('std::alignment_of<int>',4014 'std::alignment_of is an unapproved '4015 'C++11 class or function. Send c-style an example '4016 'of where it would make your code more readable, '4017 'and they may let you use it.'4018 ' [build/c++11] [5]')4019 # Missed because of the lack of "std::". Compiles because ADL4020 # looks in the namespace of my_shared_ptr, which (presumably) is4021 # std::. But there will be a lint error somewhere in this file4022 # since my_shared_ptr had to be defined.4023 self.TestCxx11Feature('static_pointer_cast<Base>(my_shared_ptr)', '')4024 self.TestCxx11Feature('std::declval<T>()', '')4025 def testExplicitMakePair(self):4026 self.TestLint('make_pair', '')4027 self.TestLint('make_pair(42, 42)', '')4028 self.TestLint('make_pair<',4029 'For C++11-compatibility, omit template arguments from'4030 ' make_pair OR use pair directly OR if appropriate,'4031 ' construct a pair directly'4032 ' [build/explicit_make_pair] [4]')4033 self.TestLint('make_pair <',4034 'For C++11-compatibility, omit template arguments from'4035 ' make_pair OR use pair directly OR if appropriate,'4036 ' construct a pair directly'4037 ' [build/explicit_make_pair] [4]')4038 self.TestLint('my_make_pair<int, int>', '')4039class CleansedLinesTest(unittest.TestCase):4040 def testInit(self):4041 lines = ['Line 1',4042 'Line 2',4043 'Line 3 // Comment test',4044 'Line 4 /* Comment test */',4045 'Line 5 "foo"']4046 clean_lines = cpplint.CleansedLines(lines)4047 self.assertEquals(lines, clean_lines.raw_lines)4048 self.assertEquals(5, clean_lines.NumLines())4049 self.assertEquals(['Line 1',4050 'Line 2',4051 'Line 3',4052 'Line 4',4053 'Line 5 "foo"'],4054 clean_lines.lines)4055 self.assertEquals(['Line 1',4056 'Line 2',4057 'Line 3',4058 'Line 4',4059 'Line 5 ""'],4060 clean_lines.elided)4061 def testInitEmpty(self):4062 clean_lines = cpplint.CleansedLines([])4063 self.assertEquals([], clean_lines.raw_lines)4064 self.assertEquals(0, clean_lines.NumLines())4065 def testCollapseStrings(self):4066 collapse = cpplint.CleansedLines._CollapseStrings4067 self.assertEquals('""', collapse('""')) # "" (empty)4068 self.assertEquals('"""', collapse('"""')) # """ (bad)4069 self.assertEquals('""', collapse('"xyz"')) # "xyz" (string)4070 self.assertEquals('""', collapse('"\\\""')) # "\"" (string)4071 self.assertEquals('""', collapse('"\'"')) # "'" (string)4072 self.assertEquals('"\"', collapse('"\"')) # "\" (bad)4073 self.assertEquals('""', collapse('"\\\\"')) # "\\" (string)4074 self.assertEquals('"', collapse('"\\\\\\"')) # "\\\" (bad)4075 self.assertEquals('""', collapse('"\\\\\\\\"')) # "\\\\" (string)4076 self.assertEquals('\'\'', collapse('\'\'')) # '' (empty)4077 self.assertEquals('\'\'', collapse('\'a\'')) # 'a' (char)4078 self.assertEquals('\'\'', collapse('\'\\\'\'')) # '\'' (char)4079 self.assertEquals('\'', collapse('\'\\\'')) # '\' (bad)4080 self.assertEquals('', collapse('\\012')) # '\012' (char)4081 self.assertEquals('', collapse('\\xfF0')) # '\xfF0' (char)4082 self.assertEquals('', collapse('\\n')) # '\n' (char)4083 self.assertEquals(r'\#', collapse('\\#')) # '\#' (bad)4084 self.assertEquals('"" + ""', collapse('"\'" + "\'"'))4085 self.assertEquals("'', ''", collapse("'\"', '\"'"))4086 self.assertEquals('""[0b10]', collapse('"a\'b"[0b1\'0]'))4087 self.assertEquals('42', collapse("4'2"))4088 self.assertEquals('0b0101', collapse("0b0'1'0'1"))4089 self.assertEquals('1048576', collapse("1'048'576"))4090 self.assertEquals('0X100000', collapse("0X10'0000"))4091 self.assertEquals('0004000000', collapse("0'004'000'000"))4092 self.assertEquals('1.602176565e-19', collapse("1.602'176'565e-19"))4093 self.assertEquals('\'\' + 0xffff', collapse("'i' + 0xf'f'f'f"))4094 self.assertEquals('sizeof\'\' == 1', collapse("sizeof'x' == 1"))4095 self.assertEquals('0x.03p100', collapse('0x.0\'3p1\'0\'0'))4096 self.assertEquals('123.45', collapse('1\'23.4\'5'))4097 self.assertEquals('StringReplace(body, "", "");',4098 collapse('StringReplace(body, "\\\\", "\\\\\\\\");'))4099 self.assertEquals('\'\' ""',4100 collapse('\'"\' "foo"'))4101class OrderOfIncludesTest(CpplintTestBase):4102 def setUp(self):4103 CpplintTestBase.setUp(self)4104 self.include_state = cpplint._IncludeState()4105 os.path.abspath = lambda value: value4106 def testCheckNextIncludeOrder_OtherThenCpp(self):4107 self.assertEqual('', self.include_state.CheckNextIncludeOrder(4108 cpplint._OTHER_HEADER))4109 self.assertEqual('Found C++ system header after other header',4110 self.include_state.CheckNextIncludeOrder(4111 cpplint._CPP_SYS_HEADER))4112 def testCheckNextIncludeOrder_CppThenC(self):4113 self.assertEqual('', self.include_state.CheckNextIncludeOrder(4114 cpplint._CPP_SYS_HEADER))4115 self.assertEqual('Found C system header after C++ system header',4116 self.include_state.CheckNextIncludeOrder(4117 cpplint._C_SYS_HEADER))4118 def testCheckNextIncludeOrder_LikelyThenCpp(self):4119 self.assertEqual('', self.include_state.CheckNextIncludeOrder(4120 cpplint._LIKELY_MY_HEADER))4121 self.assertEqual('', self.include_state.CheckNextIncludeOrder(4122 cpplint._CPP_SYS_HEADER))4123 def testCheckNextIncludeOrder_PossibleThenCpp(self):4124 self.assertEqual('', self.include_state.CheckNextIncludeOrder(4125 cpplint._POSSIBLE_MY_HEADER))4126 self.assertEqual('', self.include_state.CheckNextIncludeOrder(4127 cpplint._CPP_SYS_HEADER))4128 def testCheckNextIncludeOrder_CppThenLikely(self):4129 self.assertEqual('', self.include_state.CheckNextIncludeOrder(4130 cpplint._CPP_SYS_HEADER))4131 # This will eventually fail.4132 self.assertEqual('', self.include_state.CheckNextIncludeOrder(4133 cpplint._LIKELY_MY_HEADER))4134 def testCheckNextIncludeOrder_CppThenPossible(self):4135 self.assertEqual('', self.include_state.CheckNextIncludeOrder(4136 cpplint._CPP_SYS_HEADER))4137 self.assertEqual('', self.include_state.CheckNextIncludeOrder(4138 cpplint._POSSIBLE_MY_HEADER))4139 def testClassifyInclude(self):4140 file_info = cpplint.FileInfo4141 classify_include = cpplint._ClassifyInclude4142 self.assertEqual(cpplint._C_SYS_HEADER,4143 classify_include(file_info('foo/foo.cc'),4144 'stdio.h',4145 True))4146 self.assertEqual(cpplint._CPP_SYS_HEADER,4147 classify_include(file_info('foo/foo.cc'),4148 'string',4149 True))4150 self.assertEqual(cpplint._CPP_SYS_HEADER,4151 classify_include(file_info('foo/foo.cc'),4152 'typeinfo',4153 True))4154 self.assertEqual(cpplint._OTHER_HEADER,4155 classify_include(file_info('foo/foo.cc'),4156 'string',4157 False))4158 self.assertEqual(cpplint._LIKELY_MY_HEADER,4159 classify_include(file_info('foo/foo.cc'),4160 'foo/foo-inl.h',4161 False))4162 self.assertEqual(cpplint._LIKELY_MY_HEADER,4163 classify_include(file_info('foo/internal/foo.cc'),4164 'foo/public/foo.h',4165 False))4166 self.assertEqual(cpplint._POSSIBLE_MY_HEADER,4167 classify_include(file_info('foo/internal/foo.cc'),4168 'foo/other/public/foo.h',4169 False))4170 self.assertEqual(cpplint._OTHER_HEADER,4171 classify_include(file_info('foo/internal/foo.cc'),4172 'foo/other/public/foop.h',4173 False))4174 def testTryDropCommonSuffixes(self):4175 self.assertEqual('foo/foo', cpplint._DropCommonSuffixes('foo/foo-inl.h'))4176 self.assertEqual('foo/bar/foo',4177 cpplint._DropCommonSuffixes('foo/bar/foo_inl.h'))4178 self.assertEqual('foo/foo', cpplint._DropCommonSuffixes('foo/foo.cc'))4179 self.assertEqual('foo/foo_unusualinternal',4180 cpplint._DropCommonSuffixes('foo/foo_unusualinternal.h'))4181 self.assertEqual('',4182 cpplint._DropCommonSuffixes('_test.cc'))4183 self.assertEqual('test',4184 cpplint._DropCommonSuffixes('test.cc'))4185 def testRegression(self):4186 def Format(includes):4187 include_list = []4188 for item in includes:4189 if item.startswith('"') or item.startswith('<'):4190 include_list.append('#include %s\n' % item)4191 else:4192 include_list.append(item + '\n')4193 return ''.join(include_list)4194 # Test singleton cases first.4195 self.TestLanguageRulesCheck('foo/foo.cc', Format(['"foo/foo.h"']), '')4196 self.TestLanguageRulesCheck('foo/foo.cc', Format(['<stdio.h>']), '')4197 self.TestLanguageRulesCheck('foo/foo.cc', Format(['<string>']), '')4198 self.TestLanguageRulesCheck('foo/foo.cc', Format(['"foo/foo-inl.h"']), '')4199 self.TestLanguageRulesCheck('foo/foo.cc', Format(['"bar/bar-inl.h"']), '')4200 self.TestLanguageRulesCheck('foo/foo.cc', Format(['"bar/bar.h"']), '')4201 # Test everything in a good and new order.4202 self.TestLanguageRulesCheck('foo/foo.cc',4203 Format(['"foo/foo.h"',4204 '"foo/foo-inl.h"',4205 '<stdio.h>',4206 '<string>',4207 '<unordered_map>',4208 '"bar/bar-inl.h"',4209 '"bar/bar.h"']),4210 '')4211 # Test bad orders.4212 self.TestLanguageRulesCheck(4213 'foo/foo.cc',4214 Format(['<string>', '<stdio.h>']),4215 'Found C system header after C++ system header.'4216 ' Should be: foo.h, c system, c++ system, other.'4217 ' [build/include_order] [4]')4218 self.TestLanguageRulesCheck(4219 'foo/foo.cc',4220 Format(['"foo/bar-inl.h"',4221 '"foo/foo-inl.h"']),4222 '')4223 self.TestLanguageRulesCheck(4224 'foo/foo.cc',4225 Format(['"foo/e.h"',4226 '"foo/b.h"', # warning here (e>b)4227 '"foo/c.h"',4228 '"foo/d.h"',4229 '"foo/a.h"']), # warning here (d>a)4230 ['Include "foo/b.h" not in alphabetical order'4231 ' [build/include_alpha] [4]',4232 'Include "foo/a.h" not in alphabetical order'4233 ' [build/include_alpha] [4]'])4234 # -inl.h headers are no longer special.4235 self.TestLanguageRulesCheck('foo/foo.cc',4236 Format(['"foo/foo-inl.h"', '<string>']),4237 '')4238 self.TestLanguageRulesCheck('foo/foo.cc',4239 Format(['"foo/bar.h"', '"foo/bar-inl.h"']),4240 '')4241 # Test componentized header. OK to have my header in ../public dir.4242 self.TestLanguageRulesCheck('foo/internal/foo.cc',4243 Format(['"foo/public/foo.h"', '<string>']),4244 '')4245 # OK to have my header in other dir (not stylistically, but4246 # cpplint isn't as good as a human).4247 self.TestLanguageRulesCheck('foo/internal/foo.cc',4248 Format(['"foo/other/public/foo.h"',4249 '<string>']),4250 '')4251 self.TestLanguageRulesCheck('foo/foo.cc',4252 Format(['"foo/foo.h"',4253 '<string>',4254 '"base/google.h"',4255 '"base/flags.h"']),4256 'Include "base/flags.h" not in alphabetical '4257 'order [build/include_alpha] [4]')4258 # According to the style, -inl.h should come before .h, but we don't4259 # complain about that.4260 self.TestLanguageRulesCheck('foo/foo.cc',4261 Format(['"foo/foo-inl.h"',4262 '"foo/foo.h"',4263 '"base/google.h"',4264 '"base/google-inl.h"']),4265 '')4266 # Allow project includes to be separated by blank lines4267 self.TestLanguageRulesCheck('a/a.cc',4268 Format(['"a/a.h"',4269 '<string>',4270 '"base/google.h"',4271 '',4272 '"b/c.h"',4273 '',4274 'MACRO',4275 '"a/b.h"']),4276 '')4277 self.TestLanguageRulesCheck('a/a.cc',4278 Format(['"a/a.h"',4279 '<string>',4280 '"base/google.h"',4281 '"a/b.h"']),4282 'Include "a/b.h" not in alphabetical '4283 'order [build/include_alpha] [4]')4284 # Test conditional includes4285 self.TestLanguageRulesCheck(4286 'a/a.cc',4287 ''.join(['#include <string.h>\n',4288 '#include "base/port.h"\n',4289 '#include <initializer_list>\n']),4290 ('Found C++ system header after other header. '4291 'Should be: a.h, c system, c++ system, other. '4292 '[build/include_order] [4]'))4293 self.TestLanguageRulesCheck(4294 'a/a.cc',4295 ''.join(['#include <string.h>\n',4296 '#include "base/port.h"\n',4297 '#ifdef LANG_CXX11\n',4298 '#include <initializer_list>\n',4299 '#endif // LANG_CXX11\n']),4300 '')4301 self.TestLanguageRulesCheck(4302 'a/a.cc',4303 ''.join(['#include <string.h>\n',4304 '#ifdef LANG_CXX11\n',4305 '#include "base/port.h"\n',4306 '#include <initializer_list>\n',4307 '#endif // LANG_CXX11\n']),4308 ('Found C++ system header after other header. '4309 'Should be: a.h, c system, c++ system, other. '4310 '[build/include_order] [4]'))4311 # Third party headers are exempt from order checks4312 self.TestLanguageRulesCheck('foo/foo.cc',4313 Format(['<string>', '"Python.h"', '<vector>']),4314 '')4315class CheckForFunctionLengthsTest(CpplintTestBase):4316 def setUp(self):4317 # Reducing these thresholds for the tests speeds up tests significantly.4318 self.old_normal_trigger = cpplint._FunctionState._NORMAL_TRIGGER4319 self.old_test_trigger = cpplint._FunctionState._TEST_TRIGGER4320 cpplint._FunctionState._NORMAL_TRIGGER = 104321 cpplint._FunctionState._TEST_TRIGGER = 254322 def tearDown(self):4323 cpplint._FunctionState._NORMAL_TRIGGER = self.old_normal_trigger4324 cpplint._FunctionState._TEST_TRIGGER = self.old_test_trigger4325 def TestFunctionLengthsCheck(self, code, expected_message):4326 """Check warnings for long function bodies are as expected.4327 Args:4328 code: C++ source code expected to generate a warning message.4329 expected_message: Message expected to be generated by the C++ code.4330 """4331 self.assertEquals(expected_message,4332 self.PerformFunctionLengthsCheck(code))4333 def TriggerLines(self, error_level):4334 """Return number of lines needed to trigger a function length warning.4335 Args:4336 error_level: --v setting for cpplint.4337 Returns:4338 Number of lines needed to trigger a function length warning.4339 """4340 return cpplint._FunctionState._NORMAL_TRIGGER * 2**error_level4341 def TestLines(self, error_level):4342 """Return number of lines needed to trigger a test function length warning.4343 Args:4344 error_level: --v setting for cpplint.4345 Returns:4346 Number of lines needed to trigger a test function length warning.4347 """4348 return cpplint._FunctionState._TEST_TRIGGER * 2**error_level4349 def TestFunctionLengthCheckDefinition(self, lines, error_level):4350 """Generate long function definition and check warnings are as expected.4351 Args:4352 lines: Number of lines to generate.4353 error_level: --v setting for cpplint.4354 """4355 trigger_level = self.TriggerLines(cpplint._VerboseLevel())4356 self.TestFunctionLengthsCheck(4357 'void test(int x)' + self.FunctionBody(lines),4358 ('Small and focused functions are preferred: '4359 'test() has %d non-comment lines '4360 '(error triggered by exceeding %d lines).'4361 ' [readability/fn_size] [%d]'4362 % (lines, trigger_level, error_level)))4363 def TestFunctionLengthCheckDefinitionOK(self, lines):4364 """Generate shorter function definition and check no warning is produced.4365 Args:4366 lines: Number of lines to generate.4367 """4368 self.TestFunctionLengthsCheck(4369 'void test(int x)' + self.FunctionBody(lines),4370 '')4371 def TestFunctionLengthCheckAtErrorLevel(self, error_level):4372 """Generate and check function at the trigger level for --v setting.4373 Args:4374 error_level: --v setting for cpplint.4375 """4376 self.TestFunctionLengthCheckDefinition(self.TriggerLines(error_level),4377 error_level)4378 def TestFunctionLengthCheckBelowErrorLevel(self, error_level):4379 """Generate and check function just below the trigger level for --v setting.4380 Args:4381 error_level: --v setting for cpplint.4382 """4383 self.TestFunctionLengthCheckDefinition(self.TriggerLines(error_level)-1,4384 error_level-1)4385 def TestFunctionLengthCheckAboveErrorLevel(self, error_level):4386 """Generate and check function just above the trigger level for --v setting.4387 Args:4388 error_level: --v setting for cpplint.4389 """4390 self.TestFunctionLengthCheckDefinition(self.TriggerLines(error_level)+1,4391 error_level)4392 def FunctionBody(self, number_of_lines):4393 return ' {\n' + ' this_is_just_a_test();\n'*number_of_lines + '}'4394 def FunctionBodyWithBlankLines(self, number_of_lines):4395 return ' {\n' + ' this_is_just_a_test();\n\n'*number_of_lines + '}'4396 def FunctionBodyWithNoLints(self, number_of_lines):4397 return (' {\n' +4398 ' this_is_just_a_test(); // NOLINT\n'*number_of_lines + '}')4399 # Test line length checks.4400 def testFunctionLengthCheckDeclaration(self):4401 self.TestFunctionLengthsCheck(4402 'void test();', # Not a function definition4403 '')4404 def testFunctionLengthCheckDeclarationWithBlockFollowing(self):4405 self.TestFunctionLengthsCheck(4406 ('void test();\n'4407 + self.FunctionBody(66)), # Not a function definition4408 '')4409 def testFunctionLengthCheckClassDefinition(self):4410 self.TestFunctionLengthsCheck( # Not a function definition4411 'class Test' + self.FunctionBody(66) + ';',4412 '')4413 def testFunctionLengthCheckTrivial(self):4414 self.TestFunctionLengthsCheck(4415 'void test() {}', # Not counted4416 '')4417 def testFunctionLengthCheckEmpty(self):4418 self.TestFunctionLengthsCheck(4419 'void test() {\n}',4420 '')4421 def testFunctionLengthCheckDefinitionBelowSeverity0(self):4422 old_verbosity = cpplint._SetVerboseLevel(0)4423 self.TestFunctionLengthCheckDefinitionOK(self.TriggerLines(0)-1)4424 cpplint._SetVerboseLevel(old_verbosity)4425 def testFunctionLengthCheckDefinitionAtSeverity0(self):4426 old_verbosity = cpplint._SetVerboseLevel(0)4427 self.TestFunctionLengthCheckDefinitionOK(self.TriggerLines(0))4428 cpplint._SetVerboseLevel(old_verbosity)4429 def testFunctionLengthCheckDefinitionAboveSeverity0(self):4430 old_verbosity = cpplint._SetVerboseLevel(0)4431 self.TestFunctionLengthCheckAboveErrorLevel(0)4432 cpplint._SetVerboseLevel(old_verbosity)4433 def testFunctionLengthCheckDefinitionBelowSeverity1v0(self):4434 old_verbosity = cpplint._SetVerboseLevel(0)4435 self.TestFunctionLengthCheckBelowErrorLevel(1)4436 cpplint._SetVerboseLevel(old_verbosity)4437 def testFunctionLengthCheckDefinitionAtSeverity1v0(self):4438 old_verbosity = cpplint._SetVerboseLevel(0)4439 self.TestFunctionLengthCheckAtErrorLevel(1)4440 cpplint._SetVerboseLevel(old_verbosity)4441 def testFunctionLengthCheckDefinitionBelowSeverity1(self):4442 self.TestFunctionLengthCheckDefinitionOK(self.TriggerLines(1)-1)4443 def testFunctionLengthCheckDefinitionAtSeverity1(self):4444 self.TestFunctionLengthCheckDefinitionOK(self.TriggerLines(1))4445 def testFunctionLengthCheckDefinitionAboveSeverity1(self):4446 self.TestFunctionLengthCheckAboveErrorLevel(1)4447 def testFunctionLengthCheckDefinitionSeverity1PlusBlanks(self):4448 error_level = 14449 error_lines = self.TriggerLines(error_level) + 14450 trigger_level = self.TriggerLines(cpplint._VerboseLevel())4451 self.TestFunctionLengthsCheck(4452 'void test_blanks(int x)' + self.FunctionBody(error_lines),4453 ('Small and focused functions are preferred: '4454 'test_blanks() has %d non-comment lines '4455 '(error triggered by exceeding %d lines).'4456 ' [readability/fn_size] [%d]')4457 % (error_lines, trigger_level, error_level))4458 def testFunctionLengthCheckComplexDefinitionSeverity1(self):4459 error_level = 14460 error_lines = self.TriggerLines(error_level) + 14461 trigger_level = self.TriggerLines(cpplint._VerboseLevel())4462 self.TestFunctionLengthsCheck(4463 ('my_namespace::my_other_namespace::MyVeryLongTypeName*\n'4464 'my_namespace::my_other_namespace::MyFunction(int arg1, char* arg2)'4465 + self.FunctionBody(error_lines)),4466 ('Small and focused functions are preferred: '4467 'my_namespace::my_other_namespace::MyFunction()'4468 ' has %d non-comment lines '4469 '(error triggered by exceeding %d lines).'4470 ' [readability/fn_size] [%d]')4471 % (error_lines, trigger_level, error_level))4472 def testFunctionLengthCheckDefinitionSeverity1ForTest(self):4473 error_level = 14474 error_lines = self.TestLines(error_level) + 14475 trigger_level = self.TestLines(cpplint._VerboseLevel())4476 self.TestFunctionLengthsCheck(4477 'TEST_F(Test, Mutator)' + self.FunctionBody(error_lines),4478 ('Small and focused functions are preferred: '4479 'TEST_F(Test, Mutator) has %d non-comment lines '4480 '(error triggered by exceeding %d lines).'4481 ' [readability/fn_size] [%d]')4482 % (error_lines, trigger_level, error_level))4483 def testFunctionLengthCheckDefinitionSeverity1ForSplitLineTest(self):4484 error_level = 14485 error_lines = self.TestLines(error_level) + 14486 trigger_level = self.TestLines(cpplint._VerboseLevel())4487 self.TestFunctionLengthsCheck(4488 ('TEST_F(GoogleUpdateRecoveryRegistryProtectedTest,\n'4489 ' FixGoogleUpdate_AllValues_MachineApp)' # note: 4 spaces4490 + self.FunctionBody(error_lines)),4491 ('Small and focused functions are preferred: '4492 'TEST_F(GoogleUpdateRecoveryRegistryProtectedTest, ' # 1 space4493 'FixGoogleUpdate_AllValues_MachineApp) has %d non-comment lines '4494 '(error triggered by exceeding %d lines).'4495 ' [readability/fn_size] [%d]')4496 % (error_lines+1, trigger_level, error_level))4497 def testFunctionLengthCheckDefinitionSeverity1ForBadTestDoesntBreak(self):4498 error_level = 14499 error_lines = self.TestLines(error_level) + 14500 trigger_level = self.TestLines(cpplint._VerboseLevel())4501 self.TestFunctionLengthsCheck(4502 ('TEST_F('4503 + self.FunctionBody(error_lines)),4504 ('Small and focused functions are preferred: '4505 'TEST_F has %d non-comment lines '4506 '(error triggered by exceeding %d lines).'4507 ' [readability/fn_size] [%d]')4508 % (error_lines, trigger_level, error_level))4509 def testFunctionLengthCheckDefinitionSeverity1WithEmbeddedNoLints(self):4510 error_level = 14511 error_lines = self.TriggerLines(error_level)+14512 trigger_level = self.TriggerLines(cpplint._VerboseLevel())4513 self.TestFunctionLengthsCheck(4514 'void test(int x)' + self.FunctionBodyWithNoLints(error_lines),4515 ('Small and focused functions are preferred: '4516 'test() has %d non-comment lines '4517 '(error triggered by exceeding %d lines).'4518 ' [readability/fn_size] [%d]')4519 % (error_lines, trigger_level, error_level))4520 def testFunctionLengthCheckDefinitionSeverity1WithNoLint(self):4521 self.TestFunctionLengthsCheck(4522 ('void test(int x)' + self.FunctionBody(self.TriggerLines(1))4523 + ' // NOLINT -- long function'),4524 '')4525 def testFunctionLengthCheckDefinitionBelowSeverity2(self):4526 self.TestFunctionLengthCheckBelowErrorLevel(2)4527 def testFunctionLengthCheckDefinitionSeverity2(self):4528 self.TestFunctionLengthCheckAtErrorLevel(2)4529 def testFunctionLengthCheckDefinitionAboveSeverity2(self):4530 self.TestFunctionLengthCheckAboveErrorLevel(2)4531 def testFunctionLengthCheckDefinitionBelowSeverity3(self):4532 self.TestFunctionLengthCheckBelowErrorLevel(3)4533 def testFunctionLengthCheckDefinitionSeverity3(self):4534 self.TestFunctionLengthCheckAtErrorLevel(3)4535 def testFunctionLengthCheckDefinitionAboveSeverity3(self):4536 self.TestFunctionLengthCheckAboveErrorLevel(3)4537 def testFunctionLengthCheckDefinitionBelowSeverity4(self):4538 self.TestFunctionLengthCheckBelowErrorLevel(4)4539 def testFunctionLengthCheckDefinitionSeverity4(self):4540 self.TestFunctionLengthCheckAtErrorLevel(4)4541 def testFunctionLengthCheckDefinitionAboveSeverity4(self):4542 self.TestFunctionLengthCheckAboveErrorLevel(4)4543 def testFunctionLengthCheckDefinitionBelowSeverity5(self):4544 self.TestFunctionLengthCheckBelowErrorLevel(5)4545 def testFunctionLengthCheckDefinitionAtSeverity5(self):4546 self.TestFunctionLengthCheckAtErrorLevel(5)4547 def testFunctionLengthCheckDefinitionAboveSeverity5(self):4548 self.TestFunctionLengthCheckAboveErrorLevel(5)4549 def testFunctionLengthCheckDefinitionHugeLines(self):4550 # 5 is the limit4551 self.TestFunctionLengthCheckDefinition(self.TriggerLines(10), 5)4552 def testFunctionLengthNotDeterminable(self):4553 # Macro invocation without terminating semicolon.4554 self.TestFunctionLengthsCheck(4555 'MACRO(arg)',4556 '')4557 # Macro with underscores4558 self.TestFunctionLengthsCheck(4559 'MACRO_WITH_UNDERSCORES(arg1, arg2, arg3)',4560 '')4561 self.TestFunctionLengthsCheck(4562 'NonMacro(arg)',4563 'Lint failed to find start of function body.'4564 ' [readability/fn_size] [5]')4565def TrimExtraIndent(text_block):4566 """Trim a uniform amount of whitespace off of each line in a string.4567 Compute the minimum indent on all non blank lines and trim that from each, so4568 that the block of text has no extra indentation.4569 Args:4570 text_block: a multiline string4571 Returns:4572 text_block with the common whitespace indent of each line removed.4573 """4574 def CountLeadingWhitespace(s):4575 count = 04576 for c in s:4577 if not c.isspace():4578 break4579 count += 14580 return count4581 # find the minimum indent (except for blank lines)4582 min_indent = min([CountLeadingWhitespace(line)4583 for line in text_block.split('\n') if line])4584 return '\n'.join([line[min_indent:] for line in text_block.split('\n')])4585class CloseExpressionTest(unittest.TestCase):4586 def setUp(self):4587 self.lines = cpplint.CleansedLines(4588 # 1 2 3 4 54589 # 01234567890123456789012345678901234567890123456789012345678904590 ['// Line 0',4591 'inline RCULocked<X>::ReadPtr::ReadPtr(const RCULocked* rcu) {',4592 ' DCHECK(!(data & kFlagMask)) << "Error";',4593 '}',4594 '// Line 4',4595 'RCULocked<X>::WritePtr::WritePtr(RCULocked* rcu)',4596 ' : lock_(&rcu_->mutex_) {',4597 '}',4598 '// Line 8',4599 'template <typename T, typename... A>',4600 'typename std::enable_if<',4601 ' std::is_array<T>::value && (std::extent<T>::value > 0)>::type',4602 'MakeUnique(A&&... a) = delete;',4603 '// Line 13',4604 'auto x = []() {};',4605 '// Line 15',4606 'template <typename U>',4607 'friend bool operator==(const reffed_ptr& a,',4608 ' const reffed_ptr<U>& b) {',4609 ' return a.get() == b.get();',4610 '}',4611 '// Line 21'])4612 def testCloseExpression(self):4613 # List of positions to test:4614 # (start line, start position, end line, end position + 1)4615 positions = [(1, 16, 1, 19),4616 (1, 37, 1, 59),4617 (1, 60, 3, 1),4618 (2, 8, 2, 29),4619 (2, 30, 22, -1), # Left shift operator4620 (9, 9, 9, 36),4621 (10, 23, 11, 59),4622 (11, 54, 22, -1), # Greater than operator4623 (14, 9, 14, 11),4624 (14, 11, 14, 13),4625 (14, 14, 14, 16),4626 (17, 22, 18, 46),4627 (18, 47, 20, 1)]4628 for p in positions:4629 (_, line, column) = cpplint.CloseExpression(self.lines, p[0], p[1])4630 self.assertEquals((p[2], p[3]), (line, column))4631 def testReverseCloseExpression(self):4632 # List of positions to test:4633 # (end line, end position, start line, start position)4634 positions = [(1, 18, 1, 16),4635 (1, 58, 1, 37),4636 (2, 27, 2, 10),4637 (2, 28, 2, 8),4638 (6, 18, 0, -1), # -> operator4639 (9, 35, 9, 9),4640 (11, 54, 0, -1), # Greater than operator4641 (11, 57, 11, 31),4642 (14, 10, 14, 9),4643 (14, 12, 14, 11),4644 (14, 15, 14, 14),4645 (18, 45, 17, 22),4646 (20, 0, 18, 47)]4647 for p in positions:4648 (_, line, column) = cpplint.ReverseCloseExpression(self.lines, p[0], p[1])4649 self.assertEquals((p[2], p[3]), (line, column))4650class NestingStateTest(unittest.TestCase):4651 def setUp(self):4652 self.nesting_state = cpplint.NestingState()4653 self.error_collector = ErrorCollector(self.assert_)4654 def UpdateWithLines(self, lines):4655 clean_lines = cpplint.CleansedLines(lines)4656 for line in xrange(clean_lines.NumLines()):4657 self.nesting_state.Update('test.cc',4658 clean_lines, line, self.error_collector)4659 def testEmpty(self):4660 self.UpdateWithLines([])4661 self.assertEquals(self.nesting_state.stack, [])4662 def testNamespace(self):4663 self.UpdateWithLines(['namespace {'])4664 self.assertEquals(len(self.nesting_state.stack), 1)4665 self.assertTrue(isinstance(self.nesting_state.stack[0],4666 cpplint._NamespaceInfo))4667 self.assertTrue(self.nesting_state.stack[0].seen_open_brace)4668 self.assertEquals(self.nesting_state.stack[0].name, '')4669 self.UpdateWithLines(['namespace outer { namespace inner'])4670 self.assertEquals(len(self.nesting_state.stack), 3)4671 self.assertTrue(self.nesting_state.stack[0].seen_open_brace)4672 self.assertTrue(self.nesting_state.stack[1].seen_open_brace)4673 self.assertFalse(self.nesting_state.stack[2].seen_open_brace)4674 self.assertEquals(self.nesting_state.stack[0].name, '')4675 self.assertEquals(self.nesting_state.stack[1].name, 'outer')4676 self.assertEquals(self.nesting_state.stack[2].name, 'inner')4677 self.UpdateWithLines(['{'])4678 self.assertTrue(self.nesting_state.stack[2].seen_open_brace)4679 self.UpdateWithLines(['}', '}}'])4680 self.assertEquals(len(self.nesting_state.stack), 0)4681 def testClass(self):4682 self.UpdateWithLines(['class A {'])4683 self.assertEquals(len(self.nesting_state.stack), 1)4684 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4685 self.assertEquals(self.nesting_state.stack[0].name, 'A')4686 self.assertFalse(self.nesting_state.stack[0].is_derived)4687 self.assertEquals(self.nesting_state.stack[0].class_indent, 0)4688 self.UpdateWithLines(['};',4689 'struct B : public A {'])4690 self.assertEquals(len(self.nesting_state.stack), 1)4691 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4692 self.assertEquals(self.nesting_state.stack[0].name, 'B')4693 self.assertTrue(self.nesting_state.stack[0].is_derived)4694 self.UpdateWithLines(['};',4695 'class C',4696 ': public A {'])4697 self.assertEquals(len(self.nesting_state.stack), 1)4698 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4699 self.assertEquals(self.nesting_state.stack[0].name, 'C')4700 self.assertTrue(self.nesting_state.stack[0].is_derived)4701 self.UpdateWithLines(['};',4702 'template<T>'])4703 self.assertEquals(len(self.nesting_state.stack), 0)4704 self.UpdateWithLines(['class D {', ' class E {'])4705 self.assertEquals(len(self.nesting_state.stack), 2)4706 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4707 self.assertEquals(self.nesting_state.stack[0].name, 'D')4708 self.assertFalse(self.nesting_state.stack[0].is_derived)4709 self.assertTrue(isinstance(self.nesting_state.stack[1], cpplint._ClassInfo))4710 self.assertEquals(self.nesting_state.stack[1].name, 'E')4711 self.assertFalse(self.nesting_state.stack[1].is_derived)4712 self.assertEquals(self.nesting_state.stack[1].class_indent, 2)4713 self.assertEquals(self.nesting_state.InnermostClass().name, 'E')4714 self.UpdateWithLines(['}', '}'])4715 self.assertEquals(len(self.nesting_state.stack), 0)4716 def testClassAccess(self):4717 self.UpdateWithLines(['class A {'])4718 self.assertEquals(len(self.nesting_state.stack), 1)4719 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4720 self.assertEquals(self.nesting_state.stack[0].access, 'private')4721 self.UpdateWithLines([' public:'])4722 self.assertEquals(self.nesting_state.stack[0].access, 'public')4723 self.UpdateWithLines([' protracted:'])4724 self.assertEquals(self.nesting_state.stack[0].access, 'public')4725 self.UpdateWithLines([' protected:'])4726 self.assertEquals(self.nesting_state.stack[0].access, 'protected')4727 self.UpdateWithLines([' private:'])4728 self.assertEquals(self.nesting_state.stack[0].access, 'private')4729 self.UpdateWithLines([' struct B {'])4730 self.assertEquals(len(self.nesting_state.stack), 2)4731 self.assertTrue(isinstance(self.nesting_state.stack[1], cpplint._ClassInfo))4732 self.assertEquals(self.nesting_state.stack[1].access, 'public')4733 self.assertEquals(self.nesting_state.stack[0].access, 'private')4734 self.UpdateWithLines([' protected :'])4735 self.assertEquals(self.nesting_state.stack[1].access, 'protected')4736 self.assertEquals(self.nesting_state.stack[0].access, 'private')4737 self.UpdateWithLines([' }', '}'])4738 self.assertEquals(len(self.nesting_state.stack), 0)4739 def testStruct(self):4740 self.UpdateWithLines(['struct A {'])4741 self.assertEquals(len(self.nesting_state.stack), 1)4742 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4743 self.assertEquals(self.nesting_state.stack[0].name, 'A')4744 self.assertFalse(self.nesting_state.stack[0].is_derived)4745 self.UpdateWithLines(['}',4746 'void Func(struct B arg) {'])4747 self.assertEquals(len(self.nesting_state.stack), 1)4748 self.assertFalse(isinstance(self.nesting_state.stack[0],4749 cpplint._ClassInfo))4750 self.UpdateWithLines(['}'])4751 self.assertEquals(len(self.nesting_state.stack), 0)4752 def testPreprocessor(self):4753 self.assertEquals(len(self.nesting_state.pp_stack), 0)4754 self.UpdateWithLines(['#if MACRO1'])4755 self.assertEquals(len(self.nesting_state.pp_stack), 1)4756 self.UpdateWithLines(['#endif'])4757 self.assertEquals(len(self.nesting_state.pp_stack), 0)4758 self.UpdateWithLines(['#ifdef MACRO2'])4759 self.assertEquals(len(self.nesting_state.pp_stack), 1)4760 self.UpdateWithLines(['#else'])4761 self.assertEquals(len(self.nesting_state.pp_stack), 1)4762 self.UpdateWithLines(['#ifdef MACRO3'])4763 self.assertEquals(len(self.nesting_state.pp_stack), 2)4764 self.UpdateWithLines(['#elif MACRO4'])4765 self.assertEquals(len(self.nesting_state.pp_stack), 2)4766 self.UpdateWithLines(['#endif'])4767 self.assertEquals(len(self.nesting_state.pp_stack), 1)4768 self.UpdateWithLines(['#endif'])4769 self.assertEquals(len(self.nesting_state.pp_stack), 0)4770 self.UpdateWithLines(['#ifdef MACRO5',4771 'class A {',4772 '#elif MACRO6',4773 'class B {',4774 '#else',4775 'class C {',4776 '#endif'])4777 self.assertEquals(len(self.nesting_state.pp_stack), 0)4778 self.assertEquals(len(self.nesting_state.stack), 1)4779 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4780 self.assertEquals(self.nesting_state.stack[0].name, 'A')4781 self.UpdateWithLines(['};'])4782 self.assertEquals(len(self.nesting_state.stack), 0)4783 self.UpdateWithLines(['class D',4784 '#ifdef MACRO7'])4785 self.assertEquals(len(self.nesting_state.pp_stack), 1)4786 self.assertEquals(len(self.nesting_state.stack), 1)4787 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4788 self.assertEquals(self.nesting_state.stack[0].name, 'D')4789 self.assertFalse(self.nesting_state.stack[0].is_derived)4790 self.UpdateWithLines(['#elif MACRO8',4791 ': public E'])4792 self.assertEquals(len(self.nesting_state.stack), 1)4793 self.assertEquals(self.nesting_state.stack[0].name, 'D')4794 self.assertTrue(self.nesting_state.stack[0].is_derived)4795 self.assertFalse(self.nesting_state.stack[0].seen_open_brace)4796 self.UpdateWithLines(['#else',4797 '{'])4798 self.assertEquals(len(self.nesting_state.stack), 1)4799 self.assertEquals(self.nesting_state.stack[0].name, 'D')4800 self.assertFalse(self.nesting_state.stack[0].is_derived)4801 self.assertTrue(self.nesting_state.stack[0].seen_open_brace)4802 self.UpdateWithLines(['#endif'])4803 self.assertEquals(len(self.nesting_state.pp_stack), 0)4804 self.assertEquals(len(self.nesting_state.stack), 1)4805 self.assertEquals(self.nesting_state.stack[0].name, 'D')4806 self.assertFalse(self.nesting_state.stack[0].is_derived)4807 self.assertFalse(self.nesting_state.stack[0].seen_open_brace)4808 self.UpdateWithLines([';'])4809 self.assertEquals(len(self.nesting_state.stack), 0)4810 def testTemplate(self):4811 self.UpdateWithLines(['template <T,',4812 ' class Arg1 = tmpl<T> >'])4813 self.assertEquals(len(self.nesting_state.stack), 0)4814 self.UpdateWithLines(['class A {'])4815 self.assertEquals(len(self.nesting_state.stack), 1)4816 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4817 self.assertEquals(self.nesting_state.stack[0].name, 'A')4818 self.UpdateWithLines(['};',4819 'template <T,',4820 ' template <typename, typename> class B>',4821 'class C'])4822 self.assertEquals(len(self.nesting_state.stack), 1)4823 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4824 self.assertEquals(self.nesting_state.stack[0].name, 'C')4825 self.UpdateWithLines([';'])4826 self.assertEquals(len(self.nesting_state.stack), 0)4827 self.UpdateWithLines(['class D : public Tmpl<E>'])4828 self.assertEquals(len(self.nesting_state.stack), 1)4829 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4830 self.assertEquals(self.nesting_state.stack[0].name, 'D')4831 self.UpdateWithLines(['{', '};'])4832 self.assertEquals(len(self.nesting_state.stack), 0)4833 self.UpdateWithLines(['template <class F,',4834 ' class G,',4835 ' class H,',4836 ' typename I>',4837 'static void Func() {'])4838 self.assertEquals(len(self.nesting_state.stack), 1)4839 self.assertFalse(isinstance(self.nesting_state.stack[0],4840 cpplint._ClassInfo))4841 self.UpdateWithLines(['}',4842 'template <class J> class K {'])4843 self.assertEquals(len(self.nesting_state.stack), 1)4844 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4845 self.assertEquals(self.nesting_state.stack[0].name, 'K')4846 def testTemplateInnerClass(self):4847 self.UpdateWithLines(['class A {',4848 ' public:'])4849 self.assertEquals(len(self.nesting_state.stack), 1)4850 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4851 self.UpdateWithLines([' template <class B>',4852 ' class C<alloc<B> >',4853 ' : public A {'])4854 self.assertEquals(len(self.nesting_state.stack), 2)4855 self.assertTrue(isinstance(self.nesting_state.stack[1], cpplint._ClassInfo))4856 def testArguments(self):4857 self.UpdateWithLines(['class A {'])4858 self.assertEquals(len(self.nesting_state.stack), 1)4859 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4860 self.assertEquals(self.nesting_state.stack[0].name, 'A')4861 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)4862 self.UpdateWithLines([' void Func(',4863 ' struct X arg1,'])4864 self.assertEquals(len(self.nesting_state.stack), 1)4865 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)4866 self.UpdateWithLines([' struct X *arg2);'])4867 self.assertEquals(len(self.nesting_state.stack), 1)4868 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)4869 self.UpdateWithLines(['};'])4870 self.assertEquals(len(self.nesting_state.stack), 0)4871 self.UpdateWithLines(['struct B {'])4872 self.assertEquals(len(self.nesting_state.stack), 1)4873 self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))4874 self.assertEquals(self.nesting_state.stack[0].name, 'B')4875 self.UpdateWithLines(['#ifdef MACRO',4876 ' void Func(',4877 ' struct X arg1'])4878 self.assertEquals(len(self.nesting_state.stack), 1)4879 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)4880 self.UpdateWithLines(['#else'])4881 self.assertEquals(len(self.nesting_state.stack), 1)4882 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)4883 self.UpdateWithLines([' void Func(',4884 ' struct X arg1'])4885 self.assertEquals(len(self.nesting_state.stack), 1)4886 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)4887 self.UpdateWithLines(['#endif'])4888 self.assertEquals(len(self.nesting_state.stack), 1)4889 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)4890 self.UpdateWithLines([' struct X *arg2);'])4891 self.assertEquals(len(self.nesting_state.stack), 1)4892 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)4893 self.UpdateWithLines(['};'])4894 self.assertEquals(len(self.nesting_state.stack), 0)4895 def testInlineAssembly(self):4896 self.UpdateWithLines(['void CopyRow_SSE2(const uint8* src, uint8* dst,',4897 ' int count) {'])4898 self.assertEquals(len(self.nesting_state.stack), 1)4899 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)4900 self.assertEquals(self.nesting_state.stack[-1].inline_asm, cpplint._NO_ASM)4901 self.UpdateWithLines([' asm volatile ('])4902 self.assertEquals(len(self.nesting_state.stack), 1)4903 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)4904 self.assertEquals(self.nesting_state.stack[-1].inline_asm,4905 cpplint._INSIDE_ASM)4906 self.UpdateWithLines([' "sub %0,%1 \\n"',4907 ' "1: \\n"',4908 ' "movdqa (%0),%%xmm0 \\n"',4909 ' "movdqa 0x10(%0),%%xmm1 \\n"',4910 ' "movdqa %%xmm0,(%0,%1) \\n"',4911 ' "movdqa %%xmm1,0x10(%0,%1) \\n"',4912 ' "lea 0x20(%0),%0 \\n"',4913 ' "sub $0x20,%2 \\n"',4914 ' "jg 1b \\n"',4915 ' : "+r"(src), // %0',4916 ' "+r"(dst), // %1',4917 ' "+r"(count) // %2',4918 ' :',4919 ' : "memory", "cc"'])4920 self.assertEquals(len(self.nesting_state.stack), 1)4921 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)4922 self.assertEquals(self.nesting_state.stack[-1].inline_asm,4923 cpplint._INSIDE_ASM)4924 self.UpdateWithLines(['#if defined(__SSE2__)',4925 ' , "xmm0", "xmm1"'])4926 self.assertEquals(len(self.nesting_state.stack), 1)4927 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)4928 self.assertEquals(self.nesting_state.stack[-1].inline_asm,4929 cpplint._INSIDE_ASM)4930 self.UpdateWithLines(['#endif'])4931 self.assertEquals(len(self.nesting_state.stack), 1)4932 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)4933 self.assertEquals(self.nesting_state.stack[-1].inline_asm,4934 cpplint._INSIDE_ASM)4935 self.UpdateWithLines([' );'])4936 self.assertEquals(len(self.nesting_state.stack), 1)4937 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)4938 self.assertEquals(self.nesting_state.stack[-1].inline_asm, cpplint._END_ASM)4939 self.UpdateWithLines(['__asm {'])4940 self.assertEquals(len(self.nesting_state.stack), 2)4941 self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)4942 self.assertEquals(self.nesting_state.stack[-1].inline_asm,4943 cpplint._BLOCK_ASM)4944 self.UpdateWithLines(['}'])4945 self.assertEquals(len(self.nesting_state.stack), 1)4946 self.UpdateWithLines(['}'])4947 self.assertEquals(len(self.nesting_state.stack), 0)4948# pylint: disable-msg=C64094949def setUp():4950 """Runs before all tests are executed.4951 """4952 # Enable all filters, so we don't miss anything that is off by default.4953 cpplint._DEFAULT_FILTERS = []4954 cpplint._cpplint_state.SetFilters('')4955# pylint: disable-msg=C64094956def tearDown():4957 """A global check to make sure all error-categories have been tested.4958 The main tearDown() routine is the only code we can guarantee will be4959 run after all other tests have been executed.4960 """4961 try:4962 if _run_verifyallcategoriesseen:4963 ErrorCollector(None).VerifyAllCategoriesAreSeen()4964 except NameError:4965 # If nobody set the global _run_verifyallcategoriesseen, then4966 # we assume we should silently not run the test4967 pass4968if __name__ == '__main__':4969 # We don't want to run the VerifyAllCategoriesAreSeen() test unless4970 # we're running the full test suite: if we only run one test,4971 # obviously we're not going to see all the error categories. So we4972 # only run VerifyAllCategoriesAreSeen() when no commandline flags4973 # are passed in.4974 global _run_verifyallcategoriesseen4975 _run_verifyallcategoriesseen = (len(sys.argv) == 1)4976 setUp()4977 unittest.main()...

Full Screen

Full Screen

test_lint.py

Source:test_lint.py Github

copy

Full Screen

...7from ...localpaths import repo_root8from .. import lint as lint_mod9from ..lint import filter_whitelist_errors, parse_whitelist, lint, create_parser10_dummy_repo = os.path.join(os.path.dirname(__file__), "dummy")11def _mock_lint(name, **kwargs):12 wrapped = getattr(lint_mod, name)13 return mock.patch(lint_mod.__name__ + "." + name, wraps=wrapped, **kwargs)14def test_filter_whitelist_errors():15 whitelist = {16 'CONSOLE': {17 'svg/*': {12}18 },19 'INDENT TABS': {20 'svg/*': {None}21 }22 }23 # parse_whitelist normalises the case/path of the match string so need to do the same24 whitelist = {e: {os.path.normcase(k): v for k, v in p.items()}25 for e, p in whitelist.items()}26 # paths passed into filter_whitelist_errors are always Unix style27 filteredfile = 'svg/test.html'28 unfilteredfile = 'html/test.html'29 # Tests for passing no errors30 filtered = filter_whitelist_errors(whitelist, [])31 assert filtered == []32 filtered = filter_whitelist_errors(whitelist, [])33 assert filtered == []34 # Tests for filtering on file and line number35 filtered = filter_whitelist_errors(whitelist, [['CONSOLE', '', filteredfile, 12]])36 assert filtered == []37 filtered = filter_whitelist_errors(whitelist, [['CONSOLE', '', unfilteredfile, 12]])38 assert filtered == [['CONSOLE', '', unfilteredfile, 12]]39 filtered = filter_whitelist_errors(whitelist, [['CONSOLE', '', filteredfile, 11]])40 assert filtered == [['CONSOLE', '', filteredfile, 11]]41 # Tests for filtering on just file42 filtered = filter_whitelist_errors(whitelist, [['INDENT TABS', '', filteredfile, 12]])43 assert filtered == []44 filtered = filter_whitelist_errors(whitelist, [['INDENT TABS', '', filteredfile, 11]])45 assert filtered == []46 filtered = filter_whitelist_errors(whitelist, [['INDENT TABS', '', unfilteredfile, 11]])47 assert filtered == [['INDENT TABS', '', unfilteredfile, 11]]48def test_parse_whitelist():49 input_buffer = six.StringIO("""50# Comment51CR AT EOL: svg/import/*52CR AT EOL: streams/resources/test-utils.js53INDENT TABS: .gitmodules54INDENT TABS: app-uri/*55INDENT TABS: svg/*56TRAILING WHITESPACE: app-uri/*57CONSOLE:streams/resources/test-utils.js: 1258CR AT EOL, INDENT TABS: html/test.js59CR AT EOL, INDENT TABS: html/test2.js: 4260*:*.pdf61*:resources/*62*, CR AT EOL: *.png63""")64 expected_data = {65 'INDENT TABS': {66 '.gitmodules': {None},67 'app-uri/*': {None},68 'svg/*': {None},69 'html/test.js': {None},70 'html/test2.js': {42},71 },72 'TRAILING WHITESPACE': {73 'app-uri/*': {None},74 },75 'CONSOLE': {76 'streams/resources/test-utils.js': {12},77 },78 'CR AT EOL': {79 'streams/resources/test-utils.js': {None},80 'svg/import/*': {None},81 'html/test.js': {None},82 'html/test2.js': {42},83 }84 }85 expected_data = {e: {os.path.normcase(k): v for k, v in p.items()}86 for e, p in expected_data.items()}87 expected_ignored = {os.path.normcase(x) for x in {"*.pdf", "resources/*", "*.png"}}88 data, ignored = parse_whitelist(input_buffer)89 assert data == expected_data90 assert ignored == expected_ignored91def test_lint_no_files(caplog):92 rv = lint(_dummy_repo, [], "normal", False)93 assert rv == 094 assert caplog.text == ""95def test_lint_ignored_file(caplog):96 with _mock_lint("check_path") as mocked_check_path:97 with _mock_lint("check_file_contents") as mocked_check_file_contents:98 rv = lint(_dummy_repo, ["broken_ignored.html"], "normal", False)99 assert rv == 0100 assert not mocked_check_path.called101 assert not mocked_check_file_contents.called102 assert caplog.text == ""103def test_lint_not_existing_file(caplog):104 with _mock_lint("check_path") as mocked_check_path:105 with _mock_lint("check_file_contents") as mocked_check_file_contents:106 # really long path-linted filename107 name = "a" * 256 + ".html"108 rv = lint(_dummy_repo, [name], "normal", False)109 assert rv == 0110 assert not mocked_check_path.called111 assert not mocked_check_file_contents.called112 assert caplog.text == ""113def test_lint_passing(caplog):114 with _mock_lint("check_path") as mocked_check_path:115 with _mock_lint("check_file_contents") as mocked_check_file_contents:116 rv = lint(_dummy_repo, ["okay.html"], "normal", False)117 assert rv == 0118 assert mocked_check_path.call_count == 1119 assert mocked_check_file_contents.call_count == 1120 assert caplog.text == ""121def test_lint_failing(caplog):122 with _mock_lint("check_path") as mocked_check_path:123 with _mock_lint("check_file_contents") as mocked_check_file_contents:124 rv = lint(_dummy_repo, ["broken.html"], "normal", False)125 assert rv == 1126 assert mocked_check_path.call_count == 1127 assert mocked_check_file_contents.call_count == 1128 assert "TRAILING WHITESPACE" in caplog.text129 assert "broken.html:1" in caplog.text130def test_ref_existent_relative(caplog):131 with _mock_lint("check_path") as mocked_check_path:132 with _mock_lint("check_file_contents") as mocked_check_file_contents:133 rv = lint(_dummy_repo, ["ref/existent_relative.html"], "normal", False)134 assert rv == 0135 assert mocked_check_path.call_count == 1136 assert mocked_check_file_contents.call_count == 1137 assert caplog.text == ""138def test_ref_existent_root_relative(caplog):139 with _mock_lint("check_path") as mocked_check_path:140 with _mock_lint("check_file_contents") as mocked_check_file_contents:141 rv = lint(_dummy_repo, ["ref/existent_root_relative.html"], "normal", False)142 assert rv == 0143 assert mocked_check_path.call_count == 1144 assert mocked_check_file_contents.call_count == 1145 assert caplog.text == ""146def test_ref_non_existent_relative(caplog):147 with _mock_lint("check_path") as mocked_check_path:148 with _mock_lint("check_file_contents") as mocked_check_file_contents:149 rv = lint(_dummy_repo, ["ref/non_existent_relative.html"], "normal", False)150 assert rv == 1151 assert mocked_check_path.call_count == 1152 assert mocked_check_file_contents.call_count == 1153 assert "NON-EXISTENT-REF" in caplog.text154 assert "ref/non_existent_relative.html" in caplog.text155 assert "non_existent_file.html" in caplog.text156def test_ref_non_existent_root_relative(caplog):157 with _mock_lint("check_path") as mocked_check_path:158 with _mock_lint("check_file_contents") as mocked_check_file_contents:159 rv = lint(_dummy_repo, ["ref/non_existent_root_relative.html"], "normal", False)160 assert rv == 1161 assert mocked_check_path.call_count == 1162 assert mocked_check_file_contents.call_count == 1163 assert "NON-EXISTENT-REF" in caplog.text164 assert "ref/non_existent_root_relative.html" in caplog.text165 assert "/non_existent_file.html" in caplog.text166def test_ref_absolute_url(caplog):167 with _mock_lint("check_path") as mocked_check_path:168 with _mock_lint("check_file_contents") as mocked_check_file_contents:169 rv = lint(_dummy_repo, ["ref/absolute.html"], "normal", False)170 assert rv == 1171 assert mocked_check_path.call_count == 1172 assert mocked_check_file_contents.call_count == 1173 assert "ABSOLUTE-URL-REF" in caplog.text174 assert "http://example.com/reference.html" in caplog.text175 assert "ref/absolute.html" in caplog.text176def test_ref_same_file_empty(caplog):177 with _mock_lint("check_path") as mocked_check_path:178 with _mock_lint("check_file_contents") as mocked_check_file_contents:179 rv = lint(_dummy_repo, ["ref/same_file_empty.html"], "normal", False)180 assert rv == 1181 assert mocked_check_path.call_count == 1182 assert mocked_check_file_contents.call_count == 1183 assert "SAME-FILE-REF" in caplog.text184 assert "same_file_empty.html" in caplog.text185def test_ref_same_file_path(caplog):186 with _mock_lint("check_path") as mocked_check_path:187 with _mock_lint("check_file_contents") as mocked_check_file_contents:188 rv = lint(_dummy_repo, ["ref/same_file_path.html"], "normal", False)189 assert rv == 1190 assert mocked_check_path.call_count == 1191 assert mocked_check_file_contents.call_count == 1192 assert "SAME-FILE-REF" in caplog.text193 assert "same_file_path.html" in caplog.text194def test_lint_passing_and_failing(caplog):195 with _mock_lint("check_path") as mocked_check_path:196 with _mock_lint("check_file_contents") as mocked_check_file_contents:197 rv = lint(_dummy_repo, ["broken.html", "okay.html"], "normal", False)198 assert rv == 1199 assert mocked_check_path.call_count == 2200 assert mocked_check_file_contents.call_count == 2201 assert "TRAILING WHITESPACE" in caplog.text202 assert "broken.html:1" in caplog.text203 assert "okay.html" not in caplog.text204def test_check_css_globally_unique_identical_test(caplog):205 with _mock_lint("check_path") as mocked_check_path:206 with _mock_lint("check_file_contents") as mocked_check_file_contents:207 rv = lint(_dummy_repo, ["css-unique/match/a.html", "css-unique/a.html"], "normal", True)208 assert rv == 0209 assert mocked_check_path.call_count == 2210 assert mocked_check_file_contents.call_count == 2211 assert caplog.text == ""212def test_check_css_globally_unique_different_test(caplog):213 with _mock_lint("check_path") as mocked_check_path:214 with _mock_lint("check_file_contents") as mocked_check_file_contents:215 rv = lint(_dummy_repo, ["css-unique/not-match/a.html", "css-unique/a.html"], "normal", True)216 assert rv == 2217 assert mocked_check_path.call_count == 2218 assert mocked_check_file_contents.call_count == 2219 assert "CSS-COLLIDING-TEST-NAME" in caplog.text220def test_check_css_globally_unique_different_spec_test(caplog):221 with _mock_lint("check_path") as mocked_check_path:222 with _mock_lint("check_file_contents") as mocked_check_file_contents:223 rv = lint(_dummy_repo, ["css-unique/selectors/a.html", "css-unique/a.html"], "normal", True)224 assert rv == 0225 assert mocked_check_path.call_count == 2226 assert mocked_check_file_contents.call_count == 2227 assert caplog.text == ""228def test_check_css_globally_unique_support_ignored(caplog):229 with _mock_lint("check_path") as mocked_check_path:230 with _mock_lint("check_file_contents") as mocked_check_file_contents:231 rv = lint(_dummy_repo, ["css-unique/support/a.html", "css-unique/support/tools/a.html"], "normal", True)232 assert rv == 0233 assert mocked_check_path.call_count == 2234 assert mocked_check_file_contents.call_count == 2235 assert caplog.text == ""236def test_check_css_globally_unique_support_identical(caplog):237 with _mock_lint("check_path") as mocked_check_path:238 with _mock_lint("check_file_contents") as mocked_check_file_contents:239 rv = lint(_dummy_repo, ["css-unique/support/a.html", "css-unique/match/support/a.html"], "normal", True)240 assert rv == 0241 assert mocked_check_path.call_count == 2242 assert mocked_check_file_contents.call_count == 2243 assert caplog.text == ""244def test_check_css_globally_unique_support_different(caplog):245 with _mock_lint("check_path") as mocked_check_path:246 with _mock_lint("check_file_contents") as mocked_check_file_contents:247 rv = lint(_dummy_repo, ["css-unique/not-match/support/a.html", "css-unique/support/a.html"], "normal", True)248 assert rv == 2249 assert mocked_check_path.call_count == 2250 assert mocked_check_file_contents.call_count == 2251 assert "CSS-COLLIDING-SUPPORT-NAME" in caplog.text252def test_check_css_globally_unique_test_support(caplog):253 with _mock_lint("check_path") as mocked_check_path:254 with _mock_lint("check_file_contents") as mocked_check_file_contents:255 rv = lint(_dummy_repo, ["css-unique/support/a.html", "css-unique/a.html"], "normal", True)256 assert rv == 0257 assert mocked_check_path.call_count == 2258 assert mocked_check_file_contents.call_count == 2259 assert caplog.text == ""260def test_check_css_globally_unique_ref_identical(caplog):261 with _mock_lint("check_path") as mocked_check_path:262 with _mock_lint("check_file_contents") as mocked_check_file_contents:263 rv = lint(_dummy_repo, ["css-unique/a-ref.html", "css-unique/match/a-ref.html"], "normal", True)264 assert rv == 0265 assert mocked_check_path.call_count == 2266 assert mocked_check_file_contents.call_count == 2267 assert caplog.text == ""268def test_check_css_globally_unique_ref_different(caplog):269 with _mock_lint("check_path") as mocked_check_path:270 with _mock_lint("check_file_contents") as mocked_check_file_contents:271 rv = lint(_dummy_repo, ["css-unique/not-match/a-ref.html", "css-unique/a-ref.html"], "normal", True)272 assert rv == 2273 assert mocked_check_path.call_count == 2274 assert mocked_check_file_contents.call_count == 2275 assert "CSS-COLLIDING-REF-NAME" in caplog.text276def test_check_css_globally_unique_test_ref(caplog):277 with _mock_lint("check_path") as mocked_check_path:278 with _mock_lint("check_file_contents") as mocked_check_file_contents:279 rv = lint(_dummy_repo, ["css-unique/a-ref.html", "css-unique/a.html"], "normal", True)280 assert rv == 0281 assert mocked_check_path.call_count == 2282 assert mocked_check_file_contents.call_count == 2283 assert caplog.text == ""284def test_check_css_globally_unique_ignored(caplog):285 with _mock_lint("check_path") as mocked_check_path:286 with _mock_lint("check_file_contents") as mocked_check_file_contents:287 rv = lint(_dummy_repo, ["css-unique/tools/a.html", "css-unique/not-match/tools/a.html"], "normal", True)288 assert rv == 0289 assert mocked_check_path.call_count == 2290 assert mocked_check_file_contents.call_count == 2291 assert caplog.text == ""292def test_check_css_globally_unique_ignored_dir(caplog):293 with _mock_lint("check_path") as mocked_check_path:294 with _mock_lint("check_file_contents") as mocked_check_file_contents:295 rv = lint(_dummy_repo, ["css-unique/support/a.html", "css/work-in-progress/foo/support/a.html"], "normal", True)296 assert rv == 0297 assert mocked_check_path.call_count == 2298 assert mocked_check_file_contents.call_count == 2299 assert caplog.text == ""300def test_all_filesystem_paths():301 with mock.patch(302 'os.walk',303 return_value=[('.',304 ['dir_a', 'dir_b'],305 ['file_a', 'file_b']),306 (os.path.join('.', 'dir_a'),307 [],308 ['file_c', 'file_d'])]309 ) as m:310 got = list(lint_mod.all_filesystem_paths('.'))311 assert got == ['file_a',312 'file_b',313 os.path.join('dir_a', 'file_c'),314 os.path.join('dir_a', 'file_d')]315def test_main_with_args():316 orig_argv = sys.argv317 try:318 sys.argv = ['./lint', 'a', 'b', 'c']319 with _mock_lint('lint', return_value=True) as m:320 lint_mod.main(**vars(create_parser().parse_args()))321 m.assert_called_once_with(repo_root, ['a', 'b', 'c'], "normal", False)322 finally:323 sys.argv = orig_argv324def test_main_no_args():325 orig_argv = sys.argv326 try:327 sys.argv = ['./lint']328 with _mock_lint('lint', return_value=True) as m:329 with _mock_lint('changed_files', return_value=['foo', 'bar']) as m2:330 lint_mod.main(**vars(create_parser().parse_args()))331 m.assert_called_once_with(repo_root, ['foo', 'bar'], "normal", False)332 finally:333 sys.argv = orig_argv334def test_main_all():335 orig_argv = sys.argv336 try:337 sys.argv = ['./lint', '--all']338 with _mock_lint('lint', return_value=True) as m:339 with _mock_lint('all_filesystem_paths', return_value=['foo', 'bar']) as m2:340 lint_mod.main(**vars(create_parser().parse_args()))341 m.assert_called_once_with(repo_root, ['foo', 'bar'], "normal", False)342 finally:...

Full Screen

Full Screen

linter.py

Source:linter.py Github

copy

Full Screen

...64 """),65 file=sys.stderr)66 data = None67 return data, source68 def _run_lint(self, lint, lint_args, status):69 """Run lint and capture any stderr output for the status display.70 Args:71 lint: `decorator.Lint` containg the assertion, scope, and condition.72 lint_args: Nested dictionary of args to pass the lint callback function.73 status: The `LinterStatus` to add individual entries for group members.74 Returns:75 Boolean: True if lint passes for all/any cells, otherwise False.76 String: Optional message for a conditional failure.77 """78 cond_fail_msg = None79 try:80 is_success = lint.run(lint_args)81 except decorator.LintFailError as err:82 is_success = False83 if err.always_show:84 # Grab stack trace and carry on.85 f = io.StringIO()86 traceback.print_exc(file=f)87 trace = f.getvalue()88 # Add any non-conditional failure messages to queue. Will de-dup.89 status.log_lint_message(err.message, lint, verbose_msg=trace)90 else:91 # Defer logging a conditional message until the group status is known.92 cond_fail_msg = err.message93 return is_success, cond_fail_msg94 def _run_lint_group(self, lint, lint_args, data, status):95 """Run lint over all cells with scope and return cumulative pass/fail.96 Args:97 lint: `decorator.Lint` containg the assertion, scope, and condition.98 lint_args: Nested dictionary of args to pass the lint callback function.99 data: `dict` containing data of entire parse notebook.100 status: The `LinterStatus` to add individual entries for group members.101 Returns:102 Boolean: True if lint passes for all/any cells, otherwise False.103 Raises:104 Exception: Unsupported lint condition in `decorator.Options.Cond`.105 """106 scope: decorator.Options.Scope = lint.scope107 # Return value of each (scoped) cell in notebook.108 is_success_list: List[bool] = []109 # All conditional failure messages from lint function (deduplicated).110 cond_fail_message_list: Set[str] = set()111 for cell_idx, cell in enumerate(data.get("cells")):112 # Evict notebook cells outside of scope.113 cell_type = cell.get("cell_type")114 if scope is decorator.Options.Scope.TEXT and cell_type != "markdown":115 continue116 elif scope is decorator.Options.Scope.CODE and cell_type != "code":117 continue118 # Add cell-specific data to args passed to lint callback.119 lint_args["cell_data"] = cell120 lint_args["cell_source"] = "".join(cell["source"])121 # Execute lint on cell and collect result.122 is_success, cond_fail_msg = self._run_lint(lint, lint_args, status)123 is_success_list.append(is_success)124 if cond_fail_msg:125 cond_fail_message_list.add(cond_fail_msg)126 # All lint runs get a status entry. Group success is a separate entry.127 name = f"{lint.name}__cell_{cell_idx}"128 status.add_entry(129 lint, is_success, name=name, group=lint.name, is_group_entry=True)130 # Return True/False success for entire cell group.131 if lint.cond is decorator.Options.Cond.ANY:132 return any(is_success_list), cond_fail_message_list133 elif lint.cond is decorator.Options.Cond.ALL:134 return all(is_success_list), cond_fail_message_list135 else:136 raise Exception("Unsupported lint condition.")137 def run(self, path, lint_dict, user_args_dict):138 """Multiple hooks provided to run tests at specific points.139 Args:140 path: `pathlib.Path` of notebook to run lints against.141 lint_dict: A dictionary containing the lint styles.142 user_args_dict: Dictionary of user-defined args passed to lint callback.143 Returns:144 LinterStatus: Provides status and reporting of lint tests for a notebook.145 """146 data, source = self._load_notebook(path)147 if not data:148 return False149 # Args passed to lint callback function.150 lint_args = {151 "cell_data": None, # Added per-cell in _run_lint_group.152 "cell_source": None, # Added per-cell in _run_lint_group.153 "file_data": data,154 "file_source": source,155 "path": path,156 "user": user_args_dict157 }158 status = LinterStatus(path, verbose=self.verbose)159 # File-level scope.160 # Lint run once for the file.161 for lint in lint_dict[decorator.Options.Scope.FILE][162 decorator.Options.Cond.ANY]:163 is_success, _ = self._run_lint(lint, lint_args, status)164 status.add_entry(lint, is_success)165 # Cell-level scope.166 # These lints run on each cell, then return a cumulative result.167 for scope in [168 decorator.Options.Scope.CELLS, decorator.Options.Scope.CODE,169 decorator.Options.Scope.TEXT170 ]:171 for cond in decorator.Options.Cond:172 lints = lint_dict[scope][cond]173 for lint in lints:174 is_success, cond_fail_msgs = self._run_lint_group(175 lint, lint_args, data, status)176 status.add_entry(lint, is_success, group=lint.name)177 if not is_success:...

Full Screen

Full Screen

lint_test_expectations_unittest.py

Source:lint_test_expectations_unittest.py Github

copy

Full Screen

...72 logging_stream = StringIO.StringIO()73 options = optparse.Values({'platform': None})74 logger, handler = lint_test_expectations.set_up_logging(logging_stream)75 try:76 res = lint_test_expectations.lint(host, options)77 finally:78 lint_test_expectations.tear_down_logging(logger, handler)79 self.assertEqual(res, 0)80 self.assertEqual(host.ports_parsed, ['a', 'b', 'b-win'])81 def test_lint_test_files(self):82 logging_stream = StringIO.StringIO()83 options = optparse.Values({'platform': 'test-mac-leopard'})84 host = MockHost()85 # pylint appears to complain incorrectly about the method overrides pylint: disable=E0202,C032286 # FIXME: incorrect complaints about spacing pylint: disable=C032287 host.port_factory.all_port_names = lambda platform=None: [platform]88 logger, handler = lint_test_expectations.set_up_logging(logging_stream)89 try:90 res = lint_test_expectations.lint(host, options)91 self.assertEqual(res, 0)92 finally:93 lint_test_expectations.tear_down_logging(logger, handler)94 def test_lint_test_files__errors(self):95 options = optparse.Values({'platform': 'test', 'debug_rwt_logging': False})96 host = MockHost()97 # FIXME: incorrect complaints about spacing pylint: disable=C032298 port = host.port_factory.get(options.platform, options=options)99 port.expectations_dict = lambda: {'foo': '-- syntax error1', 'bar': '-- syntax error2'}100 host.port_factory.get = lambda platform, options=None: port101 host.port_factory.all_port_names = lambda platform=None: [port.name()]102 logging_stream = StringIO.StringIO()103 logger, handler = lint_test_expectations.set_up_logging(logging_stream)104 try:105 res = lint_test_expectations.lint(host, options)106 finally:107 lint_test_expectations.tear_down_logging(logger, handler)108 self.assertTrue(res)109 self.assertIn('foo:1', logging_stream.getvalue())110 self.assertIn('bar:1', logging_stream.getvalue())111class CheckVirtualSuiteTest(unittest.TestCase):112 def test_check_virtual_test_suites(self):113 host = MockHost()114 options = optparse.Values({'platform': 'test', 'debug_rwt_logging': False})115 orig_get = host.port_factory.get116 host.port_factory.get = lambda options: orig_get('test', options=options)117 logging_stream = StringIO.StringIO()118 logger, handler = lint_test_expectations.set_up_logging(logging_stream)119 try:120 res = lint_test_expectations.check_virtual_test_suites(host, options)121 self.assertTrue(res)122 host.filesystem.exists = lambda path: True123 res = lint_test_expectations.check_virtual_test_suites(host, options)124 self.assertFalse(res)125 finally:126 lint_test_expectations.tear_down_logging(logger, handler)127class MainTest(unittest.TestCase):128 # unused args pylint: disable=W0613129 def setUp(self):130 self.orig_lint_fn = lint_test_expectations.lint131 self.orig_check_fn = lint_test_expectations.check_virtual_test_suites132 lint_test_expectations.check_virtual_test_suites = lambda host, options: False133 self.stdout = StringIO.StringIO()134 self.stderr = StringIO.StringIO()135 def tearDown(self):136 lint_test_expectations.lint = self.orig_lint_fn137 lint_test_expectations.check_virtual_test_suites = self.orig_check_fn138 def test_success(self):139 lint_test_expectations.lint = lambda host, options: False140 res = lint_test_expectations.main(['--platform', 'test'], self.stdout, self.stderr)141 self.assertTrue('Lint succeeded' in self.stderr.getvalue())142 self.assertEqual(res, 0)143 def test_failure(self):144 lint_test_expectations.lint = lambda host, options: True145 res = lint_test_expectations.main(['--platform', 'test'], self.stdout, self.stderr)146 self.assertTrue('Lint failed' in self.stderr.getvalue())147 self.assertEqual(res, 1)148 def test_interrupt(self):149 def interrupting_lint(host, options):150 raise KeyboardInterrupt151 lint_test_expectations.lint = interrupting_lint152 res = lint_test_expectations.main([], self.stdout, self.stderr)153 self.assertEqual(res, lint_test_expectations.INTERRUPTED_EXIT_STATUS)154 def test_exception(self):155 def exception_raising_lint(host, options):156 assert False157 lint_test_expectations.lint = exception_raising_lint158 res = lint_test_expectations.main([], self.stdout, self.stderr)...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run molecule automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful