Update cpplint.py to #122:

- Don't check quoted filenames with irrelevant tests.
- Make cpplint accept 'for (foo; bar; ) {}'.
- Work with temporary files generated by Emacs flymake-mode.
- Don't warn on "/// Doxygen comments."
- Check the use of DCHECK in the same way we check the use of CHECK.
- Properly handle relative file paths with IncludeWhatYouUse checking.
- Start checking for IncludeWhatYouUse in a limited way in .cc files.
This commit is contained in:
erg@google.com
2009-06-19 20:52:09 +00:00
parent a764d2becf
commit e35f765fa6
2 changed files with 330 additions and 40 deletions
+142 -2
View File
@@ -13,6 +13,9 @@
"""Unit test for cpplint.py."""
# TODO(unknown): Add a good test that tests UpdateIncludeState.
import codecs
import os
import random
import re
@@ -72,6 +75,18 @@ class ErrorCollector:
self._errors = self._errors[0:index] + self._errors[(index + 1):]
break
# This class is a lame mock of codecs. We do not verify filename, mode, or
# encoding, but for the current use case it is not needed.
class MockIo:
def __init__(self, mock_file):
self.mock_file = mock_file
def open(self, unused_filename, unused_mode, unused_encoding, _): # NOLINT
# (lint doesn't like open as a method name)
return self.mock_file
class CpplintTestBase(unittest.TestCase):
"""Provides some useful helper functions for cpplint tests."""
@@ -147,7 +162,7 @@ class CpplintTestBase(unittest.TestCase):
function_state, error_collector)
return error_collector.Results()
def PerformIncludeWhatYouUse(self, code, filename='foo.h'):
def PerformIncludeWhatYouUse(self, code, filename='foo.h', io=codecs):
# First, build up the include state.
error_collector = ErrorCollector(self.assert_)
include_state = cpplint._IncludeState()
@@ -163,7 +178,7 @@ class CpplintTestBase(unittest.TestCase):
# Second, look for missing includes.
cpplint.CheckForIncludeWhatYouUse(filename, lines, include_state,
error_collector)
error_collector, io)
return error_collector.Results()
# Perform lint and compare the error message with "expected_message".
@@ -430,6 +445,15 @@ class CpplintTest(CpplintTestBase):
'Using sizeof(type). Use sizeof(varname) instead if possible'
' [runtime/sizeof] [1]')
# Test false errors that happened with some include file names
def testIncludeFilenameFalseError(self):
self.TestLint(
'#include "foo/long-foo.h"',
'')
self.TestLint(
'#include "foo/sprintf.h"',
'')
# Test typedef cases. There was a bug that cpplint misidentified
# typedef for pointer to function as C-style cast and produced
# false-positive error messages.
@@ -581,6 +605,75 @@ class CpplintTest(CpplintTestBase):
''',
'')
# Test the UpdateIncludeState code path.
mock_header_contents = ['#include "blah/foo.h"', '#include "blah/bar.h"']
message = self.PerformIncludeWhatYouUse(
'#include "blah/a.h"',
filename='blah/a.cc',
io=MockIo(mock_header_contents))
self.assertEquals(message, '')
mock_header_contents = ['#include <set>']
message = self.PerformIncludeWhatYouUse(
'''#include "blah/a.h"
std::set<int> foo;''',
filename='blah/a.cc',
io=MockIo(mock_header_contents))
self.assertEquals(message, '')
# Make sure we can find the correct header file if the cc file seems to be
# a temporary file generated by Emacs's flymake.
mock_header_contents = ['']
message = self.PerformIncludeWhatYouUse(
'''#include "blah/a.h"
std::set<int> foo;''',
filename='blah/a_flymake.cc',
io=MockIo(mock_header_contents))
self.assertEquals(message, 'Add #include <set> for set<> '
'[build/include_what_you_use] [4]')
# If there's just a cc and the header can't be found then it's ok.
message = self.PerformIncludeWhatYouUse(
'''#include "blah/a.h"
std::set<int> foo;''',
filename='blah/a.cc')
self.assertEquals(message, '')
# Make sure we find the headers with relative paths.
mock_header_contents = ['']
message = self.PerformIncludeWhatYouUse(
'''#include "%s/a.h"
std::set<int> foo;''' % os.path.basename(os.getcwd()),
filename='a.cc',
io=MockIo(mock_header_contents))
self.assertEquals(message, 'Add #include <set> for set<> '
'[build/include_what_you_use] [4]')
def testFilesBelongToSameModule(self):
f = cpplint.FilesBelongToSameModule
self.assertEquals((True, ''), f('a.cc', 'a.h'))
self.assertEquals((True, ''), f('base/google.cc', 'base/google.h'))
self.assertEquals((True, ''), f('base/google_test.cc', 'base/google.h'))
self.assertEquals((True, ''),
f('base/google_unittest.cc', 'base/google.h'))
self.assertEquals((True, ''),
f('base/internal/google_unittest.cc',
'base/public/google.h'))
self.assertEquals((True, 'xxx/yyy/'),
f('xxx/yyy/base/internal/google_unittest.cc',
'base/public/google.h'))
self.assertEquals((True, 'xxx/yyy/'),
f('xxx/yyy/base/google_unittest.cc',
'base/public/google.h'))
self.assertEquals((True, ''),
f('base/google_unittest.cc', 'base/google-inl.h'))
self.assertEquals((True, '/home/build/google3/'),
f('/home/build/google3/base/google.cc', 'base/google.h'))
self.assertEquals((False, ''),
f('/home/build/google3/base/google.cc', 'basu/google.h'))
self.assertEquals((False, ''), f('a.cc', 'b.h'))
def testCleanseLine(self):
self.assertEquals('int foo = 0; ',
cpplint.CleanseComments('int foo = 0; // danger!'))
@@ -962,6 +1055,25 @@ class CpplintTest(CpplintTestBase):
'Consider using CHECK_LT instead of CHECK(a < b)'
' [readability/check] [2]')
self.TestLint('DCHECK(x == 42)',
'Consider using DCHECK_EQ instead of DCHECK(a == b)'
' [readability/check] [2]')
self.TestLint('DCHECK(x != 42)',
'Consider using DCHECK_NE instead of DCHECK(a != b)'
' [readability/check] [2]')
self.TestLint('DCHECK(x >= 42)',
'Consider using DCHECK_GE instead of DCHECK(a >= b)'
' [readability/check] [2]')
self.TestLint('DCHECK(x > 42)',
'Consider using DCHECK_GT instead of DCHECK(a > b)'
' [readability/check] [2]')
self.TestLint('DCHECK(x <= 42)',
'Consider using DCHECK_LE instead of DCHECK(a <= b)'
' [readability/check] [2]')
self.TestLint('DCHECK(x < 42)',
'Consider using DCHECK_LT instead of DCHECK(a < b)'
' [readability/check] [2]')
self.TestLint(
'EXPECT_TRUE("42" == x)',
'Consider using EXPECT_EQ instead of EXPECT_TRUE(a == b)'
@@ -1088,9 +1200,12 @@ class CpplintTest(CpplintTestBase):
' [whitespace/parens] [5]')
self.TestLint('switch ( foo) {', 'Mismatching spaces inside () in switch'
' [whitespace/parens] [5]')
self.TestLint('for (foo; ba; bar ) {', 'Mismatching spaces inside () in for'
' [whitespace/parens] [5]')
self.TestLint('for (; foo; bar) {', '')
self.TestLint('for ( ; foo; bar) {', '')
self.TestLint('for ( ; foo; bar ) {', '')
self.TestLint('for (foo; bar; ) {', '')
self.TestLint('while ( foo ) {', 'Should have zero or one spaces inside'
' ( and ) in while [whitespace/parens] [5]')
@@ -1285,6 +1400,13 @@ class CpplintTest(CpplintTestBase):
self.TestLint('//x', 'Should have a space between // and comment'
' [whitespace/comments] [4]')
self.TestLint('// x', '')
self.TestLint('//----', '')
self.TestLint('//====', '')
self.TestLint('//////', '')
self.TestLint('////// x', '')
self.TestLint('/// x', '')
self.TestLint('////x', 'Should have a space between // and comment'
' [whitespace/comments] [4]')
# Test a line preceded by empty or comment lines. There was a bug
# that caused it to print the same warning N times if the erroneous
@@ -1529,6 +1651,24 @@ class CpplintTest(CpplintTestBase):
finally:
cpplint._cpplint_state.filters = old_filters
def testDefaultFilter(self):
default_filters = cpplint._DEFAULT_FILTERS
old_filters = cpplint._cpplint_state.filters
cpplint._DEFAULT_FILTERS = [ '-whitespace' ]
try:
# Reset filters
cpplint._cpplint_state.SetFilters('')
self.TestLint('// Hello there ', '')
cpplint._cpplint_state.SetFilters('+whitespace/end_of_line')
self.TestLint(
'// Hello there ',
'Line ends in whitespace. Consider deleting these extra spaces.'
' [whitespace/end_of_line] [4]')
self.TestLint(' weird opening space', '')
finally:
cpplint._cpplint_state.filters = old_filters
cpplint._DEFAULT_FILTERS = default_filters
def testUnnamedNamespacesInHeaders(self):
self.TestLanguageRulesCheck(
'foo.h', 'namespace {',