xref: /aosp_15_r20/external/google-styleguide/cpplint/cpplint_unittest.py (revision 8c35d5ee8e2913d4bd6623e2b93232b1da0ab719)
1*8c35d5eeSXin Li#!/usr/bin/python
2*8c35d5eeSXin Li# -*- coding: utf-8; -*-
3*8c35d5eeSXin Li#
4*8c35d5eeSXin Li# Copyright (c) 2009 Google Inc. All rights reserved.
5*8c35d5eeSXin Li#
6*8c35d5eeSXin Li# Redistribution and use in source and binary forms, with or without
7*8c35d5eeSXin Li# modification, are permitted provided that the following conditions are
8*8c35d5eeSXin Li# met:
9*8c35d5eeSXin Li#
10*8c35d5eeSXin Li#    * Redistributions of source code must retain the above copyright
11*8c35d5eeSXin Li# notice, this list of conditions and the following disclaimer.
12*8c35d5eeSXin Li#    * Redistributions in binary form must reproduce the above
13*8c35d5eeSXin Li# copyright notice, this list of conditions and the following disclaimer
14*8c35d5eeSXin Li# in the documentation and/or other materials provided with the
15*8c35d5eeSXin Li# distribution.
16*8c35d5eeSXin Li#    * Neither the name of Google Inc. nor the names of its
17*8c35d5eeSXin Li# contributors may be used to endorse or promote products derived from
18*8c35d5eeSXin Li# this software without specific prior written permission.
19*8c35d5eeSXin Li#
20*8c35d5eeSXin Li# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*8c35d5eeSXin Li# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*8c35d5eeSXin Li# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23*8c35d5eeSXin Li# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24*8c35d5eeSXin Li# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25*8c35d5eeSXin Li# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26*8c35d5eeSXin Li# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*8c35d5eeSXin Li# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*8c35d5eeSXin Li# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*8c35d5eeSXin Li# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30*8c35d5eeSXin Li# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*8c35d5eeSXin Li
32*8c35d5eeSXin Li"""Unit test for cpplint.py."""
33*8c35d5eeSXin Li
34*8c35d5eeSXin Li# TODO(unknown): Add a good test that tests UpdateIncludeState.
35*8c35d5eeSXin Li
36*8c35d5eeSXin Liimport codecs
37*8c35d5eeSXin Liimport os
38*8c35d5eeSXin Liimport random
39*8c35d5eeSXin Liimport re
40*8c35d5eeSXin Liimport subprocess
41*8c35d5eeSXin Liimport sys
42*8c35d5eeSXin Liimport unittest
43*8c35d5eeSXin Li
44*8c35d5eeSXin Liimport cpplint
45*8c35d5eeSXin Li
46*8c35d5eeSXin Litry:
47*8c35d5eeSXin Li  xrange          # Python 2
48*8c35d5eeSXin Liexcept NameError:
49*8c35d5eeSXin Li  xrange = range  # Python 3
50*8c35d5eeSXin Li
51*8c35d5eeSXin Li
52*8c35d5eeSXin Li# This class works as an error collector and replaces cpplint.Error
53*8c35d5eeSXin Li# function for the unit tests.  We also verify each category we see
54*8c35d5eeSXin Li# is in cpplint._ERROR_CATEGORIES, to help keep that list up to date.
55*8c35d5eeSXin Liclass ErrorCollector(object):
56*8c35d5eeSXin Li  # These are a global list, covering all categories seen ever.
57*8c35d5eeSXin Li  _ERROR_CATEGORIES = cpplint._ERROR_CATEGORIES
58*8c35d5eeSXin Li  _SEEN_ERROR_CATEGORIES = {}
59*8c35d5eeSXin Li
60*8c35d5eeSXin Li  def __init__(self, assert_fn):
61*8c35d5eeSXin Li    """assert_fn: a function to call when we notice a problem."""
62*8c35d5eeSXin Li    self._assert_fn = assert_fn
63*8c35d5eeSXin Li    self._errors = []
64*8c35d5eeSXin Li    cpplint.ResetNolintSuppressions()
65*8c35d5eeSXin Li
66*8c35d5eeSXin Li  def __call__(self, unused_filename, linenum,
67*8c35d5eeSXin Li               category, confidence, message):
68*8c35d5eeSXin Li    self._assert_fn(category in self._ERROR_CATEGORIES,
69*8c35d5eeSXin Li                    'Message "%s" has category "%s",'
70*8c35d5eeSXin Li                    ' which is not in _ERROR_CATEGORIES' % (message, category))
71*8c35d5eeSXin Li    self._SEEN_ERROR_CATEGORIES[category] = 1
72*8c35d5eeSXin Li    if cpplint._ShouldPrintError(category, confidence, linenum):
73*8c35d5eeSXin Li      self._errors.append('%s  [%s] [%d]' % (message, category, confidence))
74*8c35d5eeSXin Li
75*8c35d5eeSXin Li  def Results(self):
76*8c35d5eeSXin Li    if len(self._errors) < 2:
77*8c35d5eeSXin Li      return ''.join(self._errors)  # Most tests expect to have a string.
78*8c35d5eeSXin Li    else:
79*8c35d5eeSXin Li      return self._errors  # Let's give a list if there is more than one.
80*8c35d5eeSXin Li
81*8c35d5eeSXin Li  def ResultList(self):
82*8c35d5eeSXin Li    return self._errors
83*8c35d5eeSXin Li
84*8c35d5eeSXin Li  def VerifyAllCategoriesAreSeen(self):
85*8c35d5eeSXin Li    """Fails if there's a category in _ERROR_CATEGORIES~_SEEN_ERROR_CATEGORIES.
86*8c35d5eeSXin Li
87*8c35d5eeSXin Li    This should only be called after all tests are run, so
88*8c35d5eeSXin Li    _SEEN_ERROR_CATEGORIES has had a chance to fully populate.  Since
89*8c35d5eeSXin Li    this isn't called from within the normal unittest framework, we
90*8c35d5eeSXin Li    can't use the normal unittest assert macros.  Instead we just exit
91*8c35d5eeSXin Li    when we see an error.  Good thing this test is always run last!
92*8c35d5eeSXin Li    """
93*8c35d5eeSXin Li    for category in self._ERROR_CATEGORIES:
94*8c35d5eeSXin Li      if category not in self._SEEN_ERROR_CATEGORIES:
95*8c35d5eeSXin Li        sys.exit('FATAL ERROR: There are no tests for category "%s"' % category)
96*8c35d5eeSXin Li
97*8c35d5eeSXin Li  def RemoveIfPresent(self, substr):
98*8c35d5eeSXin Li    for (index, error) in enumerate(self._errors):
99*8c35d5eeSXin Li      if error.find(substr) != -1:
100*8c35d5eeSXin Li        self._errors = self._errors[0:index] + self._errors[(index + 1):]
101*8c35d5eeSXin Li        break
102*8c35d5eeSXin Li
103*8c35d5eeSXin Li
104*8c35d5eeSXin Li# This class is a lame mock of codecs. We do not verify filename, mode, or
105*8c35d5eeSXin Li# encoding, but for the current use case it is not needed.
106*8c35d5eeSXin Liclass MockIo(object):
107*8c35d5eeSXin Li
108*8c35d5eeSXin Li  def __init__(self, mock_file):
109*8c35d5eeSXin Li    self.mock_file = mock_file
110*8c35d5eeSXin Li
111*8c35d5eeSXin Li  def open(self,  # pylint: disable-msg=C6409
112*8c35d5eeSXin Li           unused_filename, unused_mode, unused_encoding, _):
113*8c35d5eeSXin Li    return self.mock_file
114*8c35d5eeSXin Li
115*8c35d5eeSXin Li
116*8c35d5eeSXin Liclass CpplintTestBase(unittest.TestCase):
117*8c35d5eeSXin Li  """Provides some useful helper functions for cpplint tests."""
118*8c35d5eeSXin Li
119*8c35d5eeSXin Li  def setUp(self):
120*8c35d5eeSXin Li    # Allow subclasses to cheat os.path.abspath called in FileInfo class.
121*8c35d5eeSXin Li    self.os_path_abspath_orig = os.path.abspath
122*8c35d5eeSXin Li
123*8c35d5eeSXin Li  def tearDown(self):
124*8c35d5eeSXin Li    os.path.abspath = self.os_path_abspath_orig
125*8c35d5eeSXin Li
126*8c35d5eeSXin Li  # Perform lint on single line of input and return the error message.
127*8c35d5eeSXin Li  def PerformSingleLineLint(self, code):
128*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
129*8c35d5eeSXin Li    lines = code.split('\n')
130*8c35d5eeSXin Li    cpplint.RemoveMultiLineComments('foo.h', lines, error_collector)
131*8c35d5eeSXin Li    clean_lines = cpplint.CleansedLines(lines)
132*8c35d5eeSXin Li    include_state = cpplint._IncludeState()
133*8c35d5eeSXin Li    function_state = cpplint._FunctionState()
134*8c35d5eeSXin Li    nesting_state = cpplint.NestingState()
135*8c35d5eeSXin Li    cpplint.ProcessLine('foo.cc', 'cc', clean_lines, 0,
136*8c35d5eeSXin Li                        include_state, function_state,
137*8c35d5eeSXin Li                        nesting_state, error_collector)
138*8c35d5eeSXin Li    # Single-line lint tests are allowed to fail the 'unlintable function'
139*8c35d5eeSXin Li    # check.
140*8c35d5eeSXin Li    error_collector.RemoveIfPresent(
141*8c35d5eeSXin Li        'Lint failed to find start of function body.')
142*8c35d5eeSXin Li    return error_collector.Results()
143*8c35d5eeSXin Li
144*8c35d5eeSXin Li  # Perform lint over multiple lines and return the error message.
145*8c35d5eeSXin Li  def PerformMultiLineLint(self, code):
146*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
147*8c35d5eeSXin Li    lines = code.split('\n')
148*8c35d5eeSXin Li    cpplint.RemoveMultiLineComments('foo.h', lines, error_collector)
149*8c35d5eeSXin Li    lines = cpplint.CleansedLines(lines)
150*8c35d5eeSXin Li    nesting_state = cpplint.NestingState()
151*8c35d5eeSXin Li    for i in xrange(lines.NumLines()):
152*8c35d5eeSXin Li      nesting_state.Update('foo.h', lines, i, error_collector)
153*8c35d5eeSXin Li      cpplint.CheckStyle('foo.h', lines, i, 'h', nesting_state,
154*8c35d5eeSXin Li                         error_collector)
155*8c35d5eeSXin Li      cpplint.CheckForNonStandardConstructs('foo.h', lines, i,
156*8c35d5eeSXin Li                                            nesting_state, error_collector)
157*8c35d5eeSXin Li    nesting_state.CheckCompletedBlocks('foo.h', error_collector)
158*8c35d5eeSXin Li    return error_collector.Results()
159*8c35d5eeSXin Li
160*8c35d5eeSXin Li  # Similar to PerformMultiLineLint, but calls CheckLanguage instead of
161*8c35d5eeSXin Li  # CheckForNonStandardConstructs
162*8c35d5eeSXin Li  def PerformLanguageRulesCheck(self, file_name, code):
163*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
164*8c35d5eeSXin Li    include_state = cpplint._IncludeState()
165*8c35d5eeSXin Li    nesting_state = cpplint.NestingState()
166*8c35d5eeSXin Li    lines = code.split('\n')
167*8c35d5eeSXin Li    cpplint.RemoveMultiLineComments(file_name, lines, error_collector)
168*8c35d5eeSXin Li    lines = cpplint.CleansedLines(lines)
169*8c35d5eeSXin Li    ext = file_name[file_name.rfind('.') + 1:]
170*8c35d5eeSXin Li    for i in xrange(lines.NumLines()):
171*8c35d5eeSXin Li      cpplint.CheckLanguage(file_name, lines, i, ext, include_state,
172*8c35d5eeSXin Li                            nesting_state, error_collector)
173*8c35d5eeSXin Li    return error_collector.Results()
174*8c35d5eeSXin Li
175*8c35d5eeSXin Li  def PerformFunctionLengthsCheck(self, code):
176*8c35d5eeSXin Li    """Perform Lint function length check on block of code and return warnings.
177*8c35d5eeSXin Li
178*8c35d5eeSXin Li    Builds up an array of lines corresponding to the code and strips comments
179*8c35d5eeSXin Li    using cpplint functions.
180*8c35d5eeSXin Li
181*8c35d5eeSXin Li    Establishes an error collector and invokes the function length checking
182*8c35d5eeSXin Li    function following cpplint's pattern.
183*8c35d5eeSXin Li
184*8c35d5eeSXin Li    Args:
185*8c35d5eeSXin Li      code: C++ source code expected to generate a warning message.
186*8c35d5eeSXin Li
187*8c35d5eeSXin Li    Returns:
188*8c35d5eeSXin Li      The accumulated errors.
189*8c35d5eeSXin Li    """
190*8c35d5eeSXin Li    file_name = 'foo.cc'
191*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
192*8c35d5eeSXin Li    function_state = cpplint._FunctionState()
193*8c35d5eeSXin Li    lines = code.split('\n')
194*8c35d5eeSXin Li    cpplint.RemoveMultiLineComments(file_name, lines, error_collector)
195*8c35d5eeSXin Li    lines = cpplint.CleansedLines(lines)
196*8c35d5eeSXin Li    for i in xrange(lines.NumLines()):
197*8c35d5eeSXin Li      cpplint.CheckForFunctionLengths(file_name, lines, i,
198*8c35d5eeSXin Li                                      function_state, error_collector)
199*8c35d5eeSXin Li    return error_collector.Results()
200*8c35d5eeSXin Li
201*8c35d5eeSXin Li  def PerformIncludeWhatYouUse(self, code, filename='foo.h', io=codecs):
202*8c35d5eeSXin Li    # First, build up the include state.
203*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
204*8c35d5eeSXin Li    include_state = cpplint._IncludeState()
205*8c35d5eeSXin Li    nesting_state = cpplint.NestingState()
206*8c35d5eeSXin Li    lines = code.split('\n')
207*8c35d5eeSXin Li    cpplint.RemoveMultiLineComments(filename, lines, error_collector)
208*8c35d5eeSXin Li    lines = cpplint.CleansedLines(lines)
209*8c35d5eeSXin Li    for i in xrange(lines.NumLines()):
210*8c35d5eeSXin Li      cpplint.CheckLanguage(filename, lines, i, '.h', include_state,
211*8c35d5eeSXin Li                            nesting_state, error_collector)
212*8c35d5eeSXin Li    # We could clear the error_collector here, but this should
213*8c35d5eeSXin Li    # also be fine, since our IncludeWhatYouUse unittests do not
214*8c35d5eeSXin Li    # have language problems.
215*8c35d5eeSXin Li
216*8c35d5eeSXin Li    # Second, look for missing includes.
217*8c35d5eeSXin Li    cpplint.CheckForIncludeWhatYouUse(filename, lines, include_state,
218*8c35d5eeSXin Li                                      error_collector, io)
219*8c35d5eeSXin Li    return error_collector.Results()
220*8c35d5eeSXin Li
221*8c35d5eeSXin Li  # Perform lint and compare the error message with "expected_message".
222*8c35d5eeSXin Li  def TestLint(self, code, expected_message):
223*8c35d5eeSXin Li    self.assertEquals(expected_message, self.PerformSingleLineLint(code))
224*8c35d5eeSXin Li
225*8c35d5eeSXin Li  def TestMultiLineLint(self, code, expected_message):
226*8c35d5eeSXin Li    self.assertEquals(expected_message, self.PerformMultiLineLint(code))
227*8c35d5eeSXin Li
228*8c35d5eeSXin Li  def TestMultiLineLintRE(self, code, expected_message_re):
229*8c35d5eeSXin Li    message = self.PerformMultiLineLint(code)
230*8c35d5eeSXin Li    if not re.search(expected_message_re, message):
231*8c35d5eeSXin Li      self.fail('Message was:\n' + message + 'Expected match to "' +
232*8c35d5eeSXin Li                expected_message_re + '"')
233*8c35d5eeSXin Li
234*8c35d5eeSXin Li  def TestLanguageRulesCheck(self, file_name, code, expected_message):
235*8c35d5eeSXin Li    self.assertEquals(expected_message,
236*8c35d5eeSXin Li                      self.PerformLanguageRulesCheck(file_name, code))
237*8c35d5eeSXin Li
238*8c35d5eeSXin Li  def TestIncludeWhatYouUse(self, code, expected_message):
239*8c35d5eeSXin Li    self.assertEquals(expected_message,
240*8c35d5eeSXin Li                      self.PerformIncludeWhatYouUse(code))
241*8c35d5eeSXin Li
242*8c35d5eeSXin Li  def TestBlankLinesCheck(self, lines, start_errors, end_errors):
243*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
244*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc', lines, error_collector)
245*8c35d5eeSXin Li    self.assertEquals(
246*8c35d5eeSXin Li        start_errors,
247*8c35d5eeSXin Li        error_collector.Results().count(
248*8c35d5eeSXin Li            'Redundant blank line at the start of a code block '
249*8c35d5eeSXin Li            'should be deleted.  [whitespace/blank_line] [2]'))
250*8c35d5eeSXin Li    self.assertEquals(
251*8c35d5eeSXin Li        end_errors,
252*8c35d5eeSXin Li        error_collector.Results().count(
253*8c35d5eeSXin Li            'Redundant blank line at the end of a code block '
254*8c35d5eeSXin Li            'should be deleted.  [whitespace/blank_line] [3]'))
255*8c35d5eeSXin Li
256*8c35d5eeSXin Li
257*8c35d5eeSXin Liclass CpplintTest(CpplintTestBase):
258*8c35d5eeSXin Li
259*8c35d5eeSXin Li  def GetNamespaceResults(self, lines):
260*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
261*8c35d5eeSXin Li    cpplint.RemoveMultiLineComments('foo.h', lines, error_collector)
262*8c35d5eeSXin Li    lines = cpplint.CleansedLines(lines)
263*8c35d5eeSXin Li    nesting_state = cpplint.NestingState()
264*8c35d5eeSXin Li    for i in xrange(lines.NumLines()):
265*8c35d5eeSXin Li      nesting_state.Update('foo.h', lines, i, error_collector)
266*8c35d5eeSXin Li      cpplint.CheckForNamespaceIndentation('foo.h', nesting_state,
267*8c35d5eeSXin Li                                           lines, i, error_collector)
268*8c35d5eeSXin Li
269*8c35d5eeSXin Li    return error_collector.Results()
270*8c35d5eeSXin Li
271*8c35d5eeSXin Li  def testForwardDeclarationNameSpaceIndentation(self):
272*8c35d5eeSXin Li    lines = ['namespace Test {',
273*8c35d5eeSXin Li             '  class ForwardDeclaration;',
274*8c35d5eeSXin Li             '}  // namespace Test']
275*8c35d5eeSXin Li
276*8c35d5eeSXin Li    results = self.GetNamespaceResults(lines)
277*8c35d5eeSXin Li    self.assertEquals(results, 'Do not indent within a namespace '
278*8c35d5eeSXin Li                      ' [runtime/indentation_namespace] [4]')
279*8c35d5eeSXin Li
280*8c35d5eeSXin Li  def testNameSpaceIndentationForClass(self):
281*8c35d5eeSXin Li    lines = ['namespace Test {',
282*8c35d5eeSXin Li             'void foo() { }',
283*8c35d5eeSXin Li             '  class Test {',
284*8c35d5eeSXin Li             '  };',
285*8c35d5eeSXin Li             '}  // namespace Test']
286*8c35d5eeSXin Li
287*8c35d5eeSXin Li    results = self.GetNamespaceResults(lines)
288*8c35d5eeSXin Li    self.assertEquals(results, 'Do not indent within a namespace '
289*8c35d5eeSXin Li                      ' [runtime/indentation_namespace] [4]')
290*8c35d5eeSXin Li
291*8c35d5eeSXin Li  def testNameSpaceIndentationNoError(self):
292*8c35d5eeSXin Li    lines = ['namespace Test {',
293*8c35d5eeSXin Li             'void foo() { }',
294*8c35d5eeSXin Li             '}  // namespace Test']
295*8c35d5eeSXin Li
296*8c35d5eeSXin Li    results = self.GetNamespaceResults(lines)
297*8c35d5eeSXin Li    self.assertEquals(results, '')
298*8c35d5eeSXin Li
299*8c35d5eeSXin Li  def testWhitespaceBeforeNamespace(self):
300*8c35d5eeSXin Li    lines = ['  namespace Test {',
301*8c35d5eeSXin Li             '  void foo() { }',
302*8c35d5eeSXin Li             '  }  // namespace Test']
303*8c35d5eeSXin Li
304*8c35d5eeSXin Li    results = self.GetNamespaceResults(lines)
305*8c35d5eeSXin Li    self.assertEquals(results, '')
306*8c35d5eeSXin Li
307*8c35d5eeSXin Li  def testFalsePositivesNoError(self):
308*8c35d5eeSXin Li    lines = ['namespace Test {',
309*8c35d5eeSXin Li             'struct OuterClass {',
310*8c35d5eeSXin Li             '  struct NoFalsePositivesHere;',
311*8c35d5eeSXin Li             '  struct NoFalsePositivesHere member_variable;',
312*8c35d5eeSXin Li             '};',
313*8c35d5eeSXin Li             '}  // namespace Test']
314*8c35d5eeSXin Li
315*8c35d5eeSXin Li    results = self.GetNamespaceResults(lines)
316*8c35d5eeSXin Li    self.assertEquals(results, '')
317*8c35d5eeSXin Li
318*8c35d5eeSXin Li
319*8c35d5eeSXin Li  # Test get line width.
320*8c35d5eeSXin Li  def testGetLineWidth(self):
321*8c35d5eeSXin Li    self.assertEquals(0, cpplint.GetLineWidth(''))
322*8c35d5eeSXin Li    self.assertEquals(10, cpplint.GetLineWidth(u'x' * 10))
323*8c35d5eeSXin Li    self.assertEquals(16, cpplint.GetLineWidth(u'都|道|府|県|支庁'))
324*8c35d5eeSXin Li    self.assertEquals(5 + 13 + 9, cpplint.GetLineWidth(
325*8c35d5eeSXin Li        u'd��/dt' + u'f : t ⨯ �� → ℝ' + u't ⨯ �� → ℝ'))
326*8c35d5eeSXin Li
327*8c35d5eeSXin Li  def testGetTextInside(self):
328*8c35d5eeSXin Li    self.assertEquals('', cpplint._GetTextInside('fun()', r'fun\('))
329*8c35d5eeSXin Li    self.assertEquals('x, y', cpplint._GetTextInside('f(x, y)', r'f\('))
330*8c35d5eeSXin Li    self.assertEquals('a(), b(c())', cpplint._GetTextInside(
331*8c35d5eeSXin Li        'printf(a(), b(c()))', r'printf\('))
332*8c35d5eeSXin Li    self.assertEquals('x, y{}', cpplint._GetTextInside('f[x, y{}]', r'f\['))
333*8c35d5eeSXin Li    self.assertEquals(None, cpplint._GetTextInside('f[a, b(}]', r'f\['))
334*8c35d5eeSXin Li    self.assertEquals(None, cpplint._GetTextInside('f[x, y]', r'f\('))
335*8c35d5eeSXin Li    self.assertEquals('y, h(z, (a + b))', cpplint._GetTextInside(
336*8c35d5eeSXin Li        'f(x, g(y, h(z, (a + b))))', r'g\('))
337*8c35d5eeSXin Li    self.assertEquals('f(f(x))', cpplint._GetTextInside('f(f(f(x)))', r'f\('))
338*8c35d5eeSXin Li    # Supports multiple lines.
339*8c35d5eeSXin Li    self.assertEquals('\n  return loop(x);\n',
340*8c35d5eeSXin Li                      cpplint._GetTextInside(
341*8c35d5eeSXin Li                          'int loop(int x) {\n  return loop(x);\n}\n', r'\{'))
342*8c35d5eeSXin Li    # '^' matches the beginning of each line.
343*8c35d5eeSXin Li    self.assertEquals('x, y',
344*8c35d5eeSXin Li                      cpplint._GetTextInside(
345*8c35d5eeSXin Li                          '#include "inl.h"  // skip #define\n'
346*8c35d5eeSXin Li                          '#define A2(x, y) a_inl_(x, y, __LINE__)\n'
347*8c35d5eeSXin Li                          '#define A(x) a_inl_(x, "", __LINE__)\n',
348*8c35d5eeSXin Li                          r'^\s*#define\s*\w+\('))
349*8c35d5eeSXin Li
350*8c35d5eeSXin Li  def testFindNextMultiLineCommentStart(self):
351*8c35d5eeSXin Li    self.assertEquals(1, cpplint.FindNextMultiLineCommentStart([''], 0))
352*8c35d5eeSXin Li
353*8c35d5eeSXin Li    lines = ['a', 'b', '/* c']
354*8c35d5eeSXin Li    self.assertEquals(2, cpplint.FindNextMultiLineCommentStart(lines, 0))
355*8c35d5eeSXin Li
356*8c35d5eeSXin Li    lines = ['char a[] = "/*";']  # not recognized as comment.
357*8c35d5eeSXin Li    self.assertEquals(1, cpplint.FindNextMultiLineCommentStart(lines, 0))
358*8c35d5eeSXin Li
359*8c35d5eeSXin Li  def testFindNextMultiLineCommentEnd(self):
360*8c35d5eeSXin Li    self.assertEquals(1, cpplint.FindNextMultiLineCommentEnd([''], 0))
361*8c35d5eeSXin Li    lines = ['a', 'b', ' c */']
362*8c35d5eeSXin Li    self.assertEquals(2, cpplint.FindNextMultiLineCommentEnd(lines, 0))
363*8c35d5eeSXin Li
364*8c35d5eeSXin Li  def testRemoveMultiLineCommentsFromRange(self):
365*8c35d5eeSXin Li    lines = ['a', '  /* comment ', ' * still comment', ' comment */   ', 'b']
366*8c35d5eeSXin Li    cpplint.RemoveMultiLineCommentsFromRange(lines, 1, 4)
367*8c35d5eeSXin Li    self.assertEquals(['a', '/**/', '/**/', '/**/', 'b'], lines)
368*8c35d5eeSXin Li
369*8c35d5eeSXin Li  def testSpacesAtEndOfLine(self):
370*8c35d5eeSXin Li    self.TestLint(
371*8c35d5eeSXin Li        '// Hello there ',
372*8c35d5eeSXin Li        'Line ends in whitespace.  Consider deleting these extra spaces.'
373*8c35d5eeSXin Li        '  [whitespace/end_of_line] [4]')
374*8c35d5eeSXin Li
375*8c35d5eeSXin Li  # Test line length check.
376*8c35d5eeSXin Li  def testLineLengthCheck(self):
377*8c35d5eeSXin Li    self.TestLint(
378*8c35d5eeSXin Li        '// Hello',
379*8c35d5eeSXin Li        '')
380*8c35d5eeSXin Li    self.TestLint(
381*8c35d5eeSXin Li        '// x' + ' x' * 40,
382*8c35d5eeSXin Li        'Lines should be <= 80 characters long'
383*8c35d5eeSXin Li        '  [whitespace/line_length] [2]')
384*8c35d5eeSXin Li    self.TestLint(
385*8c35d5eeSXin Li        '// x' + ' x' * 50,
386*8c35d5eeSXin Li        'Lines should be <= 80 characters long'
387*8c35d5eeSXin Li        '  [whitespace/line_length] [2]')
388*8c35d5eeSXin Li    self.TestLint(
389*8c35d5eeSXin Li        '// //some/path/to/f' + ('i' * 100) + 'le',
390*8c35d5eeSXin Li        '')
391*8c35d5eeSXin Li    self.TestLint(
392*8c35d5eeSXin Li        '//   //some/path/to/f' + ('i' * 100) + 'le',
393*8c35d5eeSXin Li        '')
394*8c35d5eeSXin Li    self.TestLint(
395*8c35d5eeSXin Li        '//   //some/path/to/f' + ('i' * 50) + 'le and some comments',
396*8c35d5eeSXin Li        'Lines should be <= 80 characters long'
397*8c35d5eeSXin Li        '  [whitespace/line_length] [2]')
398*8c35d5eeSXin Li    self.TestLint(
399*8c35d5eeSXin Li        '// http://g' + ('o' * 100) + 'gle.com/',
400*8c35d5eeSXin Li        '')
401*8c35d5eeSXin Li    self.TestLint(
402*8c35d5eeSXin Li        '//   https://g' + ('o' * 100) + 'gle.com/',
403*8c35d5eeSXin Li        '')
404*8c35d5eeSXin Li    self.TestLint(
405*8c35d5eeSXin Li        '//   https://g' + ('o' * 60) + 'gle.com/ and some comments',
406*8c35d5eeSXin Li        'Lines should be <= 80 characters long'
407*8c35d5eeSXin Li        '  [whitespace/line_length] [2]')
408*8c35d5eeSXin Li    self.TestLint(
409*8c35d5eeSXin Li        '// Read https://g' + ('o' * 60) + 'gle.com/',
410*8c35d5eeSXin Li        '')
411*8c35d5eeSXin Li    self.TestLint(
412*8c35d5eeSXin Li        '// $Id: g' + ('o' * 80) + 'gle.cc#1 $',
413*8c35d5eeSXin Li        '')
414*8c35d5eeSXin Li    self.TestLint(
415*8c35d5eeSXin Li        '// $Id: g' + ('o' * 80) + 'gle.cc#1',
416*8c35d5eeSXin Li        'Lines should be <= 80 characters long'
417*8c35d5eeSXin Li        '  [whitespace/line_length] [2]')
418*8c35d5eeSXin Li    self.TestMultiLineLint(
419*8c35d5eeSXin Li        'static const char kCStr[] = "g' + ('o' * 50) + 'gle";\n',
420*8c35d5eeSXin Li        'Lines should be <= 80 characters long'
421*8c35d5eeSXin Li        '  [whitespace/line_length] [2]')
422*8c35d5eeSXin Li    self.TestMultiLineLint(
423*8c35d5eeSXin Li        'static const char kRawStr[] = R"(g' + ('o' * 50) + 'gle)";\n',
424*8c35d5eeSXin Li        '')  # no warning because raw string content is elided
425*8c35d5eeSXin Li    self.TestMultiLineLint(
426*8c35d5eeSXin Li        'static const char kMultiLineRawStr[] = R"(\n'
427*8c35d5eeSXin Li        'g' + ('o' * 80) + 'gle\n'
428*8c35d5eeSXin Li        ')";',
429*8c35d5eeSXin Li        '')
430*8c35d5eeSXin Li    self.TestMultiLineLint(
431*8c35d5eeSXin Li        'static const char kL' + ('o' * 50) + 'ngIdentifier[] = R"()";\n',
432*8c35d5eeSXin Li        'Lines should be <= 80 characters long'
433*8c35d5eeSXin Li        '  [whitespace/line_length] [2]')
434*8c35d5eeSXin Li
435*8c35d5eeSXin Li  # Test error suppression annotations.
436*8c35d5eeSXin Li  def testErrorSuppression(self):
437*8c35d5eeSXin Li    # Two errors on same line:
438*8c35d5eeSXin Li    self.TestLint(
439*8c35d5eeSXin Li        'long a = (int64) 65;',
440*8c35d5eeSXin Li        ['Using C-style cast.  Use static_cast<int64>(...) instead'
441*8c35d5eeSXin Li         '  [readability/casting] [4]',
442*8c35d5eeSXin Li         'Use int16/int64/etc, rather than the C type long'
443*8c35d5eeSXin Li         '  [runtime/int] [4]',
444*8c35d5eeSXin Li        ])
445*8c35d5eeSXin Li    # One category of error suppressed:
446*8c35d5eeSXin Li    self.TestLint(
447*8c35d5eeSXin Li        'long a = (int64) 65;  // NOLINT(runtime/int)',
448*8c35d5eeSXin Li        'Using C-style cast.  Use static_cast<int64>(...) instead'
449*8c35d5eeSXin Li        '  [readability/casting] [4]')
450*8c35d5eeSXin Li    # All categories suppressed: (two aliases)
451*8c35d5eeSXin Li    self.TestLint('long a = (int64) 65;  // NOLINT', '')
452*8c35d5eeSXin Li    self.TestLint('long a = (int64) 65;  // NOLINT(*)', '')
453*8c35d5eeSXin Li    # Malformed NOLINT directive:
454*8c35d5eeSXin Li    self.TestLint(
455*8c35d5eeSXin Li        'long a = 65;  // NOLINT(foo)',
456*8c35d5eeSXin Li        ['Unknown NOLINT error category: foo'
457*8c35d5eeSXin Li         '  [readability/nolint] [5]',
458*8c35d5eeSXin Li         'Use int16/int64/etc, rather than the C type long  [runtime/int] [4]',
459*8c35d5eeSXin Li        ])
460*8c35d5eeSXin Li    # Irrelevant NOLINT directive has no effect:
461*8c35d5eeSXin Li    self.TestLint(
462*8c35d5eeSXin Li        'long a = 65;  // NOLINT(readability/casting)',
463*8c35d5eeSXin Li        'Use int16/int64/etc, rather than the C type long'
464*8c35d5eeSXin Li        '  [runtime/int] [4]')
465*8c35d5eeSXin Li    # NOLINTNEXTLINE silences warning for the next line instead of current line
466*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
467*8c35d5eeSXin Li    cpplint.ProcessFileData('test.cc', 'cc',
468*8c35d5eeSXin Li                            ['// Copyright 2014 Your Company.',
469*8c35d5eeSXin Li                             '// NOLINTNEXTLINE(whitespace/line_length)',
470*8c35d5eeSXin Li                             '//  ./command' + (' -verbose' * 80),
471*8c35d5eeSXin Li                             ''],
472*8c35d5eeSXin Li                            error_collector)
473*8c35d5eeSXin Li    self.assertEquals('', error_collector.Results())
474*8c35d5eeSXin Li    # LINT_C_FILE silences cast warnings for entire file.
475*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
476*8c35d5eeSXin Li    cpplint.ProcessFileData('test.h', 'h',
477*8c35d5eeSXin Li                            ['// Copyright 2014 Your Company.',
478*8c35d5eeSXin Li                             '// NOLINT(build/header_guard)',
479*8c35d5eeSXin Li                             'int64 a = (uint64) 65;',
480*8c35d5eeSXin Li                             '//  LINT_C_FILE',
481*8c35d5eeSXin Li                             ''],
482*8c35d5eeSXin Li                            error_collector)
483*8c35d5eeSXin Li    self.assertEquals('', error_collector.Results())
484*8c35d5eeSXin Li    # Vim modes silence cast warnings for entire file.
485*8c35d5eeSXin Li    for modeline in ['vi:filetype=c',
486*8c35d5eeSXin Li                     'vi:sw=8 filetype=c',
487*8c35d5eeSXin Li                     'vi:sw=8 filetype=c ts=8',
488*8c35d5eeSXin Li                     'vi: filetype=c',
489*8c35d5eeSXin Li                     'vi: sw=8 filetype=c',
490*8c35d5eeSXin Li                     'vi: sw=8 filetype=c ts=8',
491*8c35d5eeSXin Li                     'vim:filetype=c',
492*8c35d5eeSXin Li                     'vim:sw=8 filetype=c',
493*8c35d5eeSXin Li                     'vim:sw=8 filetype=c ts=8',
494*8c35d5eeSXin Li                     'vim: filetype=c',
495*8c35d5eeSXin Li                     'vim: sw=8 filetype=c',
496*8c35d5eeSXin Li                     'vim: sw=8 filetype=c ts=8',
497*8c35d5eeSXin Li                     'vim: set filetype=c:',
498*8c35d5eeSXin Li                     'vim: set sw=8 filetype=c:',
499*8c35d5eeSXin Li                     'vim: set sw=8 filetype=c ts=8:',
500*8c35d5eeSXin Li                     'vim: set filetype=c :',
501*8c35d5eeSXin Li                     'vim: set sw=8 filetype=c :',
502*8c35d5eeSXin Li                     'vim: set sw=8 filetype=c ts=8 :',
503*8c35d5eeSXin Li                     'vim: se filetype=c:',
504*8c35d5eeSXin Li                     'vim: se sw=8 filetype=c:',
505*8c35d5eeSXin Li                     'vim: se sw=8 filetype=c ts=8:',
506*8c35d5eeSXin Li                     'vim: se filetype=c :',
507*8c35d5eeSXin Li                     'vim: se sw=8 filetype=c :',
508*8c35d5eeSXin Li                     'vim: se sw=8 filetype=c ts=8 :']:
509*8c35d5eeSXin Li      error_collector = ErrorCollector(self.assert_)
510*8c35d5eeSXin Li      cpplint.ProcessFileData('test.h', 'h',
511*8c35d5eeSXin Li                              ['// Copyright 2014 Your Company.',
512*8c35d5eeSXin Li                               '// NOLINT(build/header_guard)',
513*8c35d5eeSXin Li                               'int64 a = (uint64) 65;',
514*8c35d5eeSXin Li                               '/* Prevent warnings about the modeline',
515*8c35d5eeSXin Li                               modeline,
516*8c35d5eeSXin Li                               '*/',
517*8c35d5eeSXin Li                               ''],
518*8c35d5eeSXin Li                              error_collector)
519*8c35d5eeSXin Li      self.assertEquals('', error_collector.Results())
520*8c35d5eeSXin Li    # LINT_KERNEL_FILE silences whitespace/tab warnings for entire file.
521*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
522*8c35d5eeSXin Li    cpplint.ProcessFileData('test.h', 'h',
523*8c35d5eeSXin Li                            ['// Copyright 2014 Your Company.',
524*8c35d5eeSXin Li                             '// NOLINT(build/header_guard)',
525*8c35d5eeSXin Li                             'struct test {',
526*8c35d5eeSXin Li                             '\tint member;',
527*8c35d5eeSXin Li                             '};',
528*8c35d5eeSXin Li                             '//  LINT_KERNEL_FILE',
529*8c35d5eeSXin Li                             ''],
530*8c35d5eeSXin Li                            error_collector)
531*8c35d5eeSXin Li    self.assertEquals('', error_collector.Results())
532*8c35d5eeSXin Li    # NOLINT, NOLINTNEXTLINE silences the readability/braces warning for "};".
533*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
534*8c35d5eeSXin Li    cpplint.ProcessFileData('test.cc', 'cc',
535*8c35d5eeSXin Li                            ['// Copyright 2014 Your Company.',
536*8c35d5eeSXin Li                             'for (int i = 0; i != 100; ++i) {',
537*8c35d5eeSXin Li                             '\tstd::cout << i << std::endl;',
538*8c35d5eeSXin Li                             '};  // NOLINT',
539*8c35d5eeSXin Li                             'for (int i = 0; i != 100; ++i) {',
540*8c35d5eeSXin Li                             '\tstd::cout << i << std::endl;',
541*8c35d5eeSXin Li                             '// NOLINTNEXTLINE',
542*8c35d5eeSXin Li                             '};',
543*8c35d5eeSXin Li                             '//  LINT_KERNEL_FILE',
544*8c35d5eeSXin Li                             ''],
545*8c35d5eeSXin Li                            error_collector)
546*8c35d5eeSXin Li    self.assertEquals('', error_collector.Results())
547*8c35d5eeSXin Li
548*8c35d5eeSXin Li  # Test Variable Declarations.
549*8c35d5eeSXin Li  def testVariableDeclarations(self):
550*8c35d5eeSXin Li    self.TestLint(
551*8c35d5eeSXin Li        'long a = 65;',
552*8c35d5eeSXin Li        'Use int16/int64/etc, rather than the C type long'
553*8c35d5eeSXin Li        '  [runtime/int] [4]')
554*8c35d5eeSXin Li    self.TestLint(
555*8c35d5eeSXin Li        'long double b = 65.0;',
556*8c35d5eeSXin Li        '')
557*8c35d5eeSXin Li    self.TestLint(
558*8c35d5eeSXin Li        'long long aa = 6565;',
559*8c35d5eeSXin Li        'Use int16/int64/etc, rather than the C type long'
560*8c35d5eeSXin Li        '  [runtime/int] [4]')
561*8c35d5eeSXin Li
562*8c35d5eeSXin Li  # Test C-style cast cases.
563*8c35d5eeSXin Li  def testCStyleCast(self):
564*8c35d5eeSXin Li    self.TestLint(
565*8c35d5eeSXin Li        'int a = (int)1.0;',
566*8c35d5eeSXin Li        'Using C-style cast.  Use static_cast<int>(...) instead'
567*8c35d5eeSXin Li        '  [readability/casting] [4]')
568*8c35d5eeSXin Li    self.TestLint(
569*8c35d5eeSXin Li        'int a = (int)-1.0;',
570*8c35d5eeSXin Li        'Using C-style cast.  Use static_cast<int>(...) instead'
571*8c35d5eeSXin Li        '  [readability/casting] [4]')
572*8c35d5eeSXin Li    self.TestLint(
573*8c35d5eeSXin Li        'int *a = (int *)NULL;',
574*8c35d5eeSXin Li        'Using C-style cast.  Use reinterpret_cast<int *>(...) instead'
575*8c35d5eeSXin Li        '  [readability/casting] [4]')
576*8c35d5eeSXin Li
577*8c35d5eeSXin Li    self.TestLint(
578*8c35d5eeSXin Li        'uint16 a = (uint16)1.0;',
579*8c35d5eeSXin Li        'Using C-style cast.  Use static_cast<uint16>(...) instead'
580*8c35d5eeSXin Li        '  [readability/casting] [4]')
581*8c35d5eeSXin Li    self.TestLint(
582*8c35d5eeSXin Li        'int32 a = (int32)1.0;',
583*8c35d5eeSXin Li        'Using C-style cast.  Use static_cast<int32>(...) instead'
584*8c35d5eeSXin Li        '  [readability/casting] [4]')
585*8c35d5eeSXin Li    self.TestLint(
586*8c35d5eeSXin Li        'uint64 a = (uint64)1.0;',
587*8c35d5eeSXin Li        'Using C-style cast.  Use static_cast<uint64>(...) instead'
588*8c35d5eeSXin Li        '  [readability/casting] [4]')
589*8c35d5eeSXin Li
590*8c35d5eeSXin Li    # These shouldn't be recognized casts.
591*8c35d5eeSXin Li    self.TestLint('u a = (u)NULL;', '')
592*8c35d5eeSXin Li    self.TestLint('uint a = (uint)NULL;', '')
593*8c35d5eeSXin Li    self.TestLint('typedef MockCallback<int(int)> CallbackType;', '')
594*8c35d5eeSXin Li    self.TestLint('scoped_ptr< MockCallback<int(int)> > callback_value;', '')
595*8c35d5eeSXin Li    self.TestLint('std::function<int(bool)>', '')
596*8c35d5eeSXin Li    self.TestLint('x = sizeof(int)', '')
597*8c35d5eeSXin Li    self.TestLint('x = alignof(int)', '')
598*8c35d5eeSXin Li    self.TestLint('alignas(int) char x[42]', '')
599*8c35d5eeSXin Li    self.TestLint('alignas(alignof(x)) char y[42]', '')
600*8c35d5eeSXin Li    self.TestLint('void F(int (func)(int));', '')
601*8c35d5eeSXin Li    self.TestLint('void F(int (func)(int*));', '')
602*8c35d5eeSXin Li    self.TestLint('void F(int (Class::member)(int));', '')
603*8c35d5eeSXin Li    self.TestLint('void F(int (Class::member)(int*));', '')
604*8c35d5eeSXin Li    self.TestLint('void F(int (Class::member)(int), int param);', '')
605*8c35d5eeSXin Li    self.TestLint('void F(int (Class::member)(int*), int param);', '')
606*8c35d5eeSXin Li
607*8c35d5eeSXin Li    # These should not be recognized (lambda functions without arg names).
608*8c35d5eeSXin Li    self.TestLint('[](int/*unused*/) -> bool {', '')
609*8c35d5eeSXin Li    self.TestLint('[](int /*unused*/) -> bool {', '')
610*8c35d5eeSXin Li    self.TestLint('auto f = [](MyStruct* /*unused*/)->int {', '')
611*8c35d5eeSXin Li    self.TestLint('[](int) -> bool {', '')
612*8c35d5eeSXin Li    self.TestLint('auto f = [](MyStruct*)->int {', '')
613*8c35d5eeSXin Li
614*8c35d5eeSXin Li    # Cast with brace initializers
615*8c35d5eeSXin Li    self.TestLint('int64_t{4096} * 1000 * 1000', '')
616*8c35d5eeSXin Li    self.TestLint('size_t{4096} * 1000 * 1000', '')
617*8c35d5eeSXin Li    self.TestLint('uint_fast16_t{4096} * 1000 * 1000', '')
618*8c35d5eeSXin Li
619*8c35d5eeSXin Li    # Brace initializer with templated type
620*8c35d5eeSXin Li    self.TestMultiLineLint(
621*8c35d5eeSXin Li        """
622*8c35d5eeSXin Li        template <typename Type1,
623*8c35d5eeSXin Li                  typename Type2>
624*8c35d5eeSXin Li        void Function(int arg1,
625*8c35d5eeSXin Li                      int arg2) {
626*8c35d5eeSXin Li          variable &= ~Type1{0} - 1;
627*8c35d5eeSXin Li        }""",
628*8c35d5eeSXin Li        '')
629*8c35d5eeSXin Li    self.TestMultiLineLint(
630*8c35d5eeSXin Li        """
631*8c35d5eeSXin Li        template <typename Type>
632*8c35d5eeSXin Li        class Class {
633*8c35d5eeSXin Li          void Function() {
634*8c35d5eeSXin Li            variable &= ~Type{0} - 1;
635*8c35d5eeSXin Li          }
636*8c35d5eeSXin Li        };""",
637*8c35d5eeSXin Li        '')
638*8c35d5eeSXin Li    self.TestMultiLineLint(
639*8c35d5eeSXin Li        """
640*8c35d5eeSXin Li        template <typename Type>
641*8c35d5eeSXin Li        class Class {
642*8c35d5eeSXin Li          void Function() {
643*8c35d5eeSXin Li            variable &= ~Type{0} - 1;
644*8c35d5eeSXin Li          }
645*8c35d5eeSXin Li        };""",
646*8c35d5eeSXin Li        '')
647*8c35d5eeSXin Li    self.TestMultiLineLint(
648*8c35d5eeSXin Li        """
649*8c35d5eeSXin Li        namespace {
650*8c35d5eeSXin Li        template <typename Type>
651*8c35d5eeSXin Li        class Class {
652*8c35d5eeSXin Li          void Function() {
653*8c35d5eeSXin Li            if (block) {
654*8c35d5eeSXin Li              variable &= ~Type{0} - 1;
655*8c35d5eeSXin Li            }
656*8c35d5eeSXin Li          }
657*8c35d5eeSXin Li        };
658*8c35d5eeSXin Li        }""",
659*8c35d5eeSXin Li        '')
660*8c35d5eeSXin Li
661*8c35d5eeSXin Li  # Test taking address of casts (runtime/casting)
662*8c35d5eeSXin Li  def testRuntimeCasting(self):
663*8c35d5eeSXin Li    error_msg = ('Are you taking an address of a cast?  '
664*8c35d5eeSXin Li                 'This is dangerous: could be a temp var.  '
665*8c35d5eeSXin Li                 'Take the address before doing the cast, rather than after'
666*8c35d5eeSXin Li                 '  [runtime/casting] [4]')
667*8c35d5eeSXin Li    self.TestLint('int* x = &static_cast<int*>(foo);', error_msg)
668*8c35d5eeSXin Li    self.TestLint('int* x = &reinterpret_cast<int *>(foo);', error_msg)
669*8c35d5eeSXin Li    self.TestLint('int* x = &(int*)foo;',
670*8c35d5eeSXin Li                  ['Using C-style cast.  Use reinterpret_cast<int*>(...) '
671*8c35d5eeSXin Li                   'instead  [readability/casting] [4]',
672*8c35d5eeSXin Li                   error_msg])
673*8c35d5eeSXin Li    self.TestLint('BudgetBuckets&(BudgetWinHistory::*BucketFn)(void) const;',
674*8c35d5eeSXin Li                  '')
675*8c35d5eeSXin Li    self.TestLint('&(*func_ptr)(arg)', '')
676*8c35d5eeSXin Li    self.TestLint('Compute(arg, &(*func_ptr)(i, j));', '')
677*8c35d5eeSXin Li
678*8c35d5eeSXin Li    # Alternative error message
679*8c35d5eeSXin Li    alt_error_msg = ('Are you taking an address of something dereferenced '
680*8c35d5eeSXin Li                     'from a cast?  Wrapping the dereferenced expression in '
681*8c35d5eeSXin Li                     'parentheses will make the binding more obvious'
682*8c35d5eeSXin Li                     '  [readability/casting] [4]')
683*8c35d5eeSXin Li    self.TestLint('int* x = &down_cast<Obj*>(obj)->member_;', alt_error_msg)
684*8c35d5eeSXin Li    self.TestLint('int* x = &down_cast<Obj*>(obj)[index];', alt_error_msg)
685*8c35d5eeSXin Li    self.TestLint('int* x = &(down_cast<Obj*>(obj)->member_);', '')
686*8c35d5eeSXin Li    self.TestLint('int* x = &(down_cast<Obj*>(obj)[index]);', '')
687*8c35d5eeSXin Li    self.TestLint('int* x = &down_cast<Obj*>(obj)\n->member_;', alt_error_msg)
688*8c35d5eeSXin Li    self.TestLint('int* x = &(down_cast<Obj*>(obj)\n->member_);', '')
689*8c35d5eeSXin Li
690*8c35d5eeSXin Li    # It's OK to cast an address.
691*8c35d5eeSXin Li    self.TestLint('int* x = reinterpret_cast<int *>(&foo);', '')
692*8c35d5eeSXin Li
693*8c35d5eeSXin Li    # Function pointers returning references should not be confused
694*8c35d5eeSXin Li    # with taking address of old-style casts.
695*8c35d5eeSXin Li    self.TestLint('auto x = implicit_cast<string &(*)(int)>(&foo);', '')
696*8c35d5eeSXin Li
697*8c35d5eeSXin Li  def testRuntimeSelfinit(self):
698*8c35d5eeSXin Li    self.TestLint(
699*8c35d5eeSXin Li        'Foo::Foo(Bar r, Bel l) : r_(r_), l_(l_) { }',
700*8c35d5eeSXin Li        'You seem to be initializing a member variable with itself.'
701*8c35d5eeSXin Li        '  [runtime/init] [4]')
702*8c35d5eeSXin Li    self.TestLint(
703*8c35d5eeSXin Li        'Foo::Foo(Bar r, Bel l) : r_(CHECK_NOTNULL(r_)) { }',
704*8c35d5eeSXin Li        'You seem to be initializing a member variable with itself.'
705*8c35d5eeSXin Li        '  [runtime/init] [4]')
706*8c35d5eeSXin Li    self.TestLint(
707*8c35d5eeSXin Li        'Foo::Foo(Bar r, Bel l) : r_(r), l_(l) { }',
708*8c35d5eeSXin Li        '')
709*8c35d5eeSXin Li    self.TestLint(
710*8c35d5eeSXin Li        'Foo::Foo(Bar r) : r_(r), l_(r_), ll_(l_) { }',
711*8c35d5eeSXin Li        '')
712*8c35d5eeSXin Li
713*8c35d5eeSXin Li  # Test for unnamed arguments in a method.
714*8c35d5eeSXin Li  def testCheckForUnnamedParams(self):
715*8c35d5eeSXin Li    self.TestLint('virtual void Func(int*) const;', '')
716*8c35d5eeSXin Li    self.TestLint('virtual void Func(int*);', '')
717*8c35d5eeSXin Li    self.TestLint('void Method(char*) {', '')
718*8c35d5eeSXin Li    self.TestLint('void Method(char*);', '')
719*8c35d5eeSXin Li    self.TestLint('static void operator delete[](void*) throw();', '')
720*8c35d5eeSXin Li    self.TestLint('int Method(int);', '')
721*8c35d5eeSXin Li
722*8c35d5eeSXin Li    self.TestLint('virtual void Func(int* p);', '')
723*8c35d5eeSXin Li    self.TestLint('void operator delete(void* x) throw();', '')
724*8c35d5eeSXin Li    self.TestLint('void Method(char* x) {', '')
725*8c35d5eeSXin Li    self.TestLint('void Method(char* /*x*/) {', '')
726*8c35d5eeSXin Li    self.TestLint('void Method(char* x);', '')
727*8c35d5eeSXin Li    self.TestLint('typedef void (*Method)(int32 x);', '')
728*8c35d5eeSXin Li    self.TestLint('static void operator delete[](void* x) throw();', '')
729*8c35d5eeSXin Li    self.TestLint('static void operator delete[](void* /*x*/) throw();', '')
730*8c35d5eeSXin Li
731*8c35d5eeSXin Li    self.TestLint('X operator++(int);', '')
732*8c35d5eeSXin Li    self.TestLint('X operator++(int) {', '')
733*8c35d5eeSXin Li    self.TestLint('X operator--(int);', '')
734*8c35d5eeSXin Li    self.TestLint('X operator--(int /*unused*/) {', '')
735*8c35d5eeSXin Li    self.TestLint('MACRO(int);', '')
736*8c35d5eeSXin Li    self.TestLint('MACRO(func(int));', '')
737*8c35d5eeSXin Li    self.TestLint('MACRO(arg, func(int));', '')
738*8c35d5eeSXin Li
739*8c35d5eeSXin Li    self.TestLint('void (*func)(void*);', '')
740*8c35d5eeSXin Li    self.TestLint('void Func((*func)(void*)) {}', '')
741*8c35d5eeSXin Li    self.TestLint('template <void Func(void*)> void func();', '')
742*8c35d5eeSXin Li    self.TestLint('virtual void f(int /*unused*/) {', '')
743*8c35d5eeSXin Li    self.TestLint('void f(int /*unused*/) override {', '')
744*8c35d5eeSXin Li    self.TestLint('void f(int /*unused*/) final {', '')
745*8c35d5eeSXin Li
746*8c35d5eeSXin Li  # Test deprecated casts such as int(d)
747*8c35d5eeSXin Li  def testDeprecatedCast(self):
748*8c35d5eeSXin Li    self.TestLint(
749*8c35d5eeSXin Li        'int a = int(2.2);',
750*8c35d5eeSXin Li        'Using deprecated casting style.  '
751*8c35d5eeSXin Li        'Use static_cast<int>(...) instead'
752*8c35d5eeSXin Li        '  [readability/casting] [4]')
753*8c35d5eeSXin Li
754*8c35d5eeSXin Li    self.TestLint(
755*8c35d5eeSXin Li        '(char *) "foo"',
756*8c35d5eeSXin Li        'Using C-style cast.  '
757*8c35d5eeSXin Li        'Use const_cast<char *>(...) instead'
758*8c35d5eeSXin Li        '  [readability/casting] [4]')
759*8c35d5eeSXin Li
760*8c35d5eeSXin Li    self.TestLint(
761*8c35d5eeSXin Li        '(int*)foo',
762*8c35d5eeSXin Li        'Using C-style cast.  '
763*8c35d5eeSXin Li        'Use reinterpret_cast<int*>(...) instead'
764*8c35d5eeSXin Li        '  [readability/casting] [4]')
765*8c35d5eeSXin Li
766*8c35d5eeSXin Li    # Checks for false positives...
767*8c35d5eeSXin Li    self.TestLint('int a = int();', '')  # constructor
768*8c35d5eeSXin Li    self.TestLint('X::X() : a(int()) {}', '')  # default constructor
769*8c35d5eeSXin Li    self.TestLint('operator bool();', '')  # Conversion operator
770*8c35d5eeSXin Li    self.TestLint('new int64(123);', '')  # "new" operator on basic type
771*8c35d5eeSXin Li    self.TestLint('new   int64(123);', '')  # "new" operator on basic type
772*8c35d5eeSXin Li    self.TestLint('new const int(42);', '')  # "new" on const-qualified type
773*8c35d5eeSXin Li    self.TestLint('using a = bool(int arg);', '')  # C++11 alias-declaration
774*8c35d5eeSXin Li    self.TestLint('x = bit_cast<double(*)[3]>(y);', '')  # array of array
775*8c35d5eeSXin Li    self.TestLint('void F(const char(&src)[N]);', '')  # array of references
776*8c35d5eeSXin Li
777*8c35d5eeSXin Li    # Placement new
778*8c35d5eeSXin Li    self.TestLint(
779*8c35d5eeSXin Li        'new(field_ptr) int(field->default_value_enum()->number());',
780*8c35d5eeSXin Li        '')
781*8c35d5eeSXin Li
782*8c35d5eeSXin Li    # C++11 function wrappers
783*8c35d5eeSXin Li    self.TestLint('std::function<int(bool)>', '')
784*8c35d5eeSXin Li    self.TestLint('std::function<const int(bool)>', '')
785*8c35d5eeSXin Li    self.TestLint('std::function< int(bool) >', '')
786*8c35d5eeSXin Li    self.TestLint('mfunction<int(bool)>', '')
787*8c35d5eeSXin Li
788*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
789*8c35d5eeSXin Li    cpplint.ProcessFileData(
790*8c35d5eeSXin Li        'test.cc', 'cc',
791*8c35d5eeSXin Li        ['// Copyright 2014 Your Company. All Rights Reserved.',
792*8c35d5eeSXin Li         'typedef std::function<',
793*8c35d5eeSXin Li         '    bool(int)> F;',
794*8c35d5eeSXin Li         ''],
795*8c35d5eeSXin Li        error_collector)
796*8c35d5eeSXin Li    self.assertEquals('', error_collector.Results())
797*8c35d5eeSXin Li
798*8c35d5eeSXin Li    # Return types for function pointers
799*8c35d5eeSXin Li    self.TestLint('typedef bool(FunctionPointer)();', '')
800*8c35d5eeSXin Li    self.TestLint('typedef bool(FunctionPointer)(int param);', '')
801*8c35d5eeSXin Li    self.TestLint('typedef bool(MyClass::*MemberFunctionPointer)();', '')
802*8c35d5eeSXin Li    self.TestLint('typedef bool(MyClass::* MemberFunctionPointer)();', '')
803*8c35d5eeSXin Li    self.TestLint('typedef bool(MyClass::*MemberFunctionPointer)() const;', '')
804*8c35d5eeSXin Li    self.TestLint('void Function(bool(FunctionPointerArg)());', '')
805*8c35d5eeSXin Li    self.TestLint('void Function(bool(FunctionPointerArg)()) {}', '')
806*8c35d5eeSXin Li    self.TestLint('typedef set<int64, bool(*)(int64, int64)> SortedIdSet', '')
807*8c35d5eeSXin Li    self.TestLint(
808*8c35d5eeSXin Li        'bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *t)) {}',
809*8c35d5eeSXin Li        '')
810*8c35d5eeSXin Li
811*8c35d5eeSXin Li  # The second parameter to a gMock method definition is a function signature
812*8c35d5eeSXin Li  # that often looks like a bad cast but should not picked up by lint.
813*8c35d5eeSXin Li  def testMockMethod(self):
814*8c35d5eeSXin Li    self.TestLint(
815*8c35d5eeSXin Li        'MOCK_METHOD0(method, int());',
816*8c35d5eeSXin Li        '')
817*8c35d5eeSXin Li    self.TestLint(
818*8c35d5eeSXin Li        'MOCK_CONST_METHOD1(method, float(string));',
819*8c35d5eeSXin Li        '')
820*8c35d5eeSXin Li    self.TestLint(
821*8c35d5eeSXin Li        'MOCK_CONST_METHOD2_T(method, double(float, float));',
822*8c35d5eeSXin Li        '')
823*8c35d5eeSXin Li    self.TestLint(
824*8c35d5eeSXin Li        'MOCK_CONST_METHOD1(method, SomeType(int));',
825*8c35d5eeSXin Li        '')
826*8c35d5eeSXin Li
827*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
828*8c35d5eeSXin Li    cpplint.ProcessFileData('mock.cc', 'cc',
829*8c35d5eeSXin Li                            ['MOCK_METHOD1(method1,',
830*8c35d5eeSXin Li                             '             bool(int));',
831*8c35d5eeSXin Li                             'MOCK_METHOD1(',
832*8c35d5eeSXin Li                             '    method2,',
833*8c35d5eeSXin Li                             '    bool(int));',
834*8c35d5eeSXin Li                             'MOCK_CONST_METHOD2(',
835*8c35d5eeSXin Li                             '    method3, bool(int,',
836*8c35d5eeSXin Li                             '                  int));',
837*8c35d5eeSXin Li                             'MOCK_METHOD1(method4, int(bool));',
838*8c35d5eeSXin Li                             'const int kConstant = int(42);'],  # true positive
839*8c35d5eeSXin Li                            error_collector)
840*8c35d5eeSXin Li    self.assertEquals(
841*8c35d5eeSXin Li        0,
842*8c35d5eeSXin Li        error_collector.Results().count(
843*8c35d5eeSXin Li            ('Using deprecated casting style.  '
844*8c35d5eeSXin Li             'Use static_cast<bool>(...) instead  '
845*8c35d5eeSXin Li             '[readability/casting] [4]')))
846*8c35d5eeSXin Li    self.assertEquals(
847*8c35d5eeSXin Li        1,
848*8c35d5eeSXin Li        error_collector.Results().count(
849*8c35d5eeSXin Li            ('Using deprecated casting style.  '
850*8c35d5eeSXin Li             'Use static_cast<int>(...) instead  '
851*8c35d5eeSXin Li             '[readability/casting] [4]')))
852*8c35d5eeSXin Li
853*8c35d5eeSXin Li  # Like gMock method definitions, MockCallback instantiations look very similar
854*8c35d5eeSXin Li  # to bad casts.
855*8c35d5eeSXin Li  def testMockCallback(self):
856*8c35d5eeSXin Li    self.TestLint(
857*8c35d5eeSXin Li        'MockCallback<bool(int)>',
858*8c35d5eeSXin Li        '')
859*8c35d5eeSXin Li    self.TestLint(
860*8c35d5eeSXin Li        'MockCallback<int(float, char)>',
861*8c35d5eeSXin Li        '')
862*8c35d5eeSXin Li
863*8c35d5eeSXin Li  # Test false errors that happened with some include file names
864*8c35d5eeSXin Li  def testIncludeFilenameFalseError(self):
865*8c35d5eeSXin Li    self.TestLint(
866*8c35d5eeSXin Li        '#include "foo/long-foo.h"',
867*8c35d5eeSXin Li        '')
868*8c35d5eeSXin Li    self.TestLint(
869*8c35d5eeSXin Li        '#include "foo/sprintf.h"',
870*8c35d5eeSXin Li        '')
871*8c35d5eeSXin Li
872*8c35d5eeSXin Li  # Test typedef cases.  There was a bug that cpplint misidentified
873*8c35d5eeSXin Li  # typedef for pointer to function as C-style cast and produced
874*8c35d5eeSXin Li  # false-positive error messages.
875*8c35d5eeSXin Li  def testTypedefForPointerToFunction(self):
876*8c35d5eeSXin Li    self.TestLint(
877*8c35d5eeSXin Li        'typedef void (*Func)(int x);',
878*8c35d5eeSXin Li        '')
879*8c35d5eeSXin Li    self.TestLint(
880*8c35d5eeSXin Li        'typedef void (*Func)(int *x);',
881*8c35d5eeSXin Li        '')
882*8c35d5eeSXin Li    self.TestLint(
883*8c35d5eeSXin Li        'typedef void Func(int x);',
884*8c35d5eeSXin Li        '')
885*8c35d5eeSXin Li    self.TestLint(
886*8c35d5eeSXin Li        'typedef void Func(int *x);',
887*8c35d5eeSXin Li        '')
888*8c35d5eeSXin Li
889*8c35d5eeSXin Li  def testIncludeWhatYouUseNoImplementationFiles(self):
890*8c35d5eeSXin Li    code = 'std::vector<int> foo;'
891*8c35d5eeSXin Li    self.assertEquals('Add #include <vector> for vector<>'
892*8c35d5eeSXin Li                      '  [build/include_what_you_use] [4]',
893*8c35d5eeSXin Li                      self.PerformIncludeWhatYouUse(code, 'foo.h'))
894*8c35d5eeSXin Li    self.assertEquals('',
895*8c35d5eeSXin Li                      self.PerformIncludeWhatYouUse(code, 'foo.cc'))
896*8c35d5eeSXin Li
897*8c35d5eeSXin Li  def testIncludeWhatYouUse(self):
898*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
899*8c35d5eeSXin Li        """#include <vector>
900*8c35d5eeSXin Li           std::vector<int> foo;
901*8c35d5eeSXin Li        """,
902*8c35d5eeSXin Li        '')
903*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
904*8c35d5eeSXin Li        """#include <map>
905*8c35d5eeSXin Li           std::pair<int,int> foo;
906*8c35d5eeSXin Li        """,
907*8c35d5eeSXin Li        'Add #include <utility> for pair<>'
908*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
909*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
910*8c35d5eeSXin Li        """#include <multimap>
911*8c35d5eeSXin Li           std::pair<int,int> foo;
912*8c35d5eeSXin Li        """,
913*8c35d5eeSXin Li        'Add #include <utility> for pair<>'
914*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
915*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
916*8c35d5eeSXin Li        """#include <hash_map>
917*8c35d5eeSXin Li           std::pair<int,int> foo;
918*8c35d5eeSXin Li        """,
919*8c35d5eeSXin Li        'Add #include <utility> for pair<>'
920*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
921*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
922*8c35d5eeSXin Li        """#include <hash_map>
923*8c35d5eeSXin Li           auto foo = std::make_pair(1, 2);
924*8c35d5eeSXin Li        """,
925*8c35d5eeSXin Li        'Add #include <utility> for make_pair'
926*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
927*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
928*8c35d5eeSXin Li        """#include <utility>
929*8c35d5eeSXin Li           std::pair<int,int> foo;
930*8c35d5eeSXin Li        """,
931*8c35d5eeSXin Li        '')
932*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
933*8c35d5eeSXin Li        """#include <vector>
934*8c35d5eeSXin Li           DECLARE_string(foobar);
935*8c35d5eeSXin Li        """,
936*8c35d5eeSXin Li        '')
937*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
938*8c35d5eeSXin Li        """#include <vector>
939*8c35d5eeSXin Li           DEFINE_string(foobar, "", "");
940*8c35d5eeSXin Li        """,
941*8c35d5eeSXin Li        '')
942*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
943*8c35d5eeSXin Li        """#include <vector>
944*8c35d5eeSXin Li           std::pair<int,int> foo;
945*8c35d5eeSXin Li        """,
946*8c35d5eeSXin Li        'Add #include <utility> for pair<>'
947*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
948*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
949*8c35d5eeSXin Li        """#include "base/foobar.h"
950*8c35d5eeSXin Li           std::vector<int> foo;
951*8c35d5eeSXin Li        """,
952*8c35d5eeSXin Li        'Add #include <vector> for vector<>'
953*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
954*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
955*8c35d5eeSXin Li        """#include <vector>
956*8c35d5eeSXin Li           std::set<int> foo;
957*8c35d5eeSXin Li        """,
958*8c35d5eeSXin Li        'Add #include <set> for set<>'
959*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
960*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
961*8c35d5eeSXin Li        """#include "base/foobar.h"
962*8c35d5eeSXin Li          hash_map<int, int> foobar;
963*8c35d5eeSXin Li        """,
964*8c35d5eeSXin Li        'Add #include <hash_map> for hash_map<>'
965*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
966*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
967*8c35d5eeSXin Li        """#include "base/containers/hash_tables.h"
968*8c35d5eeSXin Li          base::hash_map<int, int> foobar;
969*8c35d5eeSXin Li        """,
970*8c35d5eeSXin Li        '')
971*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
972*8c35d5eeSXin Li        """#include "base/foobar.h"
973*8c35d5eeSXin Li           bool foobar = std::less<int>(0,1);
974*8c35d5eeSXin Li        """,
975*8c35d5eeSXin Li        'Add #include <functional> for less<>'
976*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
977*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
978*8c35d5eeSXin Li        """#include "base/foobar.h"
979*8c35d5eeSXin Li           bool foobar = min<int>(0,1);
980*8c35d5eeSXin Li        """,
981*8c35d5eeSXin Li        'Add #include <algorithm> for min  [build/include_what_you_use] [4]')
982*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
983*8c35d5eeSXin Li        'void a(const string &foobar);',
984*8c35d5eeSXin Li        'Add #include <string> for string  [build/include_what_you_use] [4]')
985*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
986*8c35d5eeSXin Li        'void a(const std::string &foobar);',
987*8c35d5eeSXin Li        'Add #include <string> for string  [build/include_what_you_use] [4]')
988*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
989*8c35d5eeSXin Li        'void a(const my::string &foobar);',
990*8c35d5eeSXin Li        '')  # Avoid false positives on strings in other namespaces.
991*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
992*8c35d5eeSXin Li        """#include "base/foobar.h"
993*8c35d5eeSXin Li           bool foobar = swap(0,1);
994*8c35d5eeSXin Li        """,
995*8c35d5eeSXin Li        'Add #include <utility> for swap  [build/include_what_you_use] [4]')
996*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
997*8c35d5eeSXin Li        """#include "base/foobar.h"
998*8c35d5eeSXin Li           bool foobar = transform(a.begin(), a.end(), b.start(), Foo);
999*8c35d5eeSXin Li        """,
1000*8c35d5eeSXin Li        'Add #include <algorithm> for transform  '
1001*8c35d5eeSXin Li        '[build/include_what_you_use] [4]')
1002*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1003*8c35d5eeSXin Li        """#include "base/foobar.h"
1004*8c35d5eeSXin Li           bool foobar = min_element(a.begin(), a.end());
1005*8c35d5eeSXin Li        """,
1006*8c35d5eeSXin Li        'Add #include <algorithm> for min_element  '
1007*8c35d5eeSXin Li        '[build/include_what_you_use] [4]')
1008*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1009*8c35d5eeSXin Li        """foo->swap(0,1);
1010*8c35d5eeSXin Li           foo.swap(0,1);
1011*8c35d5eeSXin Li        """,
1012*8c35d5eeSXin Li        '')
1013*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1014*8c35d5eeSXin Li        """#include <string>
1015*8c35d5eeSXin Li           void a(const std::multimap<int,string> &foobar);
1016*8c35d5eeSXin Li        """,
1017*8c35d5eeSXin Li        'Add #include <map> for multimap<>'
1018*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
1019*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1020*8c35d5eeSXin Li        """#include <string>
1021*8c35d5eeSXin Li           void a(const std::unordered_map<int,string> &foobar);
1022*8c35d5eeSXin Li        """,
1023*8c35d5eeSXin Li        'Add #include <unordered_map> for unordered_map<>'
1024*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
1025*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1026*8c35d5eeSXin Li        """#include <string>
1027*8c35d5eeSXin Li           void a(const std::unordered_set<int> &foobar);
1028*8c35d5eeSXin Li        """,
1029*8c35d5eeSXin Li        'Add #include <unordered_set> for unordered_set<>'
1030*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
1031*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1032*8c35d5eeSXin Li        """#include <queue>
1033*8c35d5eeSXin Li           void a(const std::priority_queue<int> &foobar);
1034*8c35d5eeSXin Li        """,
1035*8c35d5eeSXin Li        '')
1036*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1037*8c35d5eeSXin Li        """#include <assert.h>
1038*8c35d5eeSXin Li           #include <string>
1039*8c35d5eeSXin Li           #include <vector>
1040*8c35d5eeSXin Li           #include "base/basictypes.h"
1041*8c35d5eeSXin Li           #include "base/port.h"
1042*8c35d5eeSXin Li           vector<string> hajoa;""", '')
1043*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1044*8c35d5eeSXin Li        """#include <string>
1045*8c35d5eeSXin Li           int i = numeric_limits<int>::max()
1046*8c35d5eeSXin Li        """,
1047*8c35d5eeSXin Li        'Add #include <limits> for numeric_limits<>'
1048*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
1049*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1050*8c35d5eeSXin Li        """#include <limits>
1051*8c35d5eeSXin Li           int i = numeric_limits<int>::max()
1052*8c35d5eeSXin Li        """,
1053*8c35d5eeSXin Li        '')
1054*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1055*8c35d5eeSXin Li        """#include <string>
1056*8c35d5eeSXin Li           std::unique_ptr<int> x;
1057*8c35d5eeSXin Li        """,
1058*8c35d5eeSXin Li        'Add #include <memory> for unique_ptr<>'
1059*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
1060*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1061*8c35d5eeSXin Li        """#include <string>
1062*8c35d5eeSXin Li           auto x = std::make_unique<int>(0);
1063*8c35d5eeSXin Li        """,
1064*8c35d5eeSXin Li        'Add #include <memory> for make_unique<>'
1065*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
1066*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1067*8c35d5eeSXin Li        """#include <vector>
1068*8c35d5eeSXin Li           vector<int> foo(vector<int> x) { return std::move(x); }
1069*8c35d5eeSXin Li        """,
1070*8c35d5eeSXin Li        'Add #include <utility> for move'
1071*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
1072*8c35d5eeSXin Li    self.TestIncludeWhatYouUse(
1073*8c35d5eeSXin Li        """#include <string>
1074*8c35d5eeSXin Li           int a, b;
1075*8c35d5eeSXin Li           std::swap(a, b);
1076*8c35d5eeSXin Li        """,
1077*8c35d5eeSXin Li        'Add #include <utility> for swap'
1078*8c35d5eeSXin Li        '  [build/include_what_you_use] [4]')
1079*8c35d5eeSXin Li
1080*8c35d5eeSXin Li    # Test the UpdateIncludeState code path.
1081*8c35d5eeSXin Li    mock_header_contents = ['#include "blah/foo.h"', '#include "blah/bar.h"']
1082*8c35d5eeSXin Li    message = self.PerformIncludeWhatYouUse(
1083*8c35d5eeSXin Li        '#include "blah/a.h"',
1084*8c35d5eeSXin Li        filename='blah/a.cc',
1085*8c35d5eeSXin Li        io=MockIo(mock_header_contents))
1086*8c35d5eeSXin Li    self.assertEquals(message, '')
1087*8c35d5eeSXin Li
1088*8c35d5eeSXin Li    mock_header_contents = ['#include <set>']
1089*8c35d5eeSXin Li    message = self.PerformIncludeWhatYouUse(
1090*8c35d5eeSXin Li        """#include "blah/a.h"
1091*8c35d5eeSXin Li           std::set<int> foo;""",
1092*8c35d5eeSXin Li        filename='blah/a.cc',
1093*8c35d5eeSXin Li        io=MockIo(mock_header_contents))
1094*8c35d5eeSXin Li    self.assertEquals(message, '')
1095*8c35d5eeSXin Li
1096*8c35d5eeSXin Li    # Make sure we can find the correct header file if the cc file seems to be
1097*8c35d5eeSXin Li    # a temporary file generated by Emacs's flymake.
1098*8c35d5eeSXin Li    mock_header_contents = ['']
1099*8c35d5eeSXin Li    message = self.PerformIncludeWhatYouUse(
1100*8c35d5eeSXin Li        """#include "blah/a.h"
1101*8c35d5eeSXin Li           std::set<int> foo;""",
1102*8c35d5eeSXin Li        filename='blah/a_flymake.cc',
1103*8c35d5eeSXin Li        io=MockIo(mock_header_contents))
1104*8c35d5eeSXin Li    self.assertEquals(message, 'Add #include <set> for set<>  '
1105*8c35d5eeSXin Li                      '[build/include_what_you_use] [4]')
1106*8c35d5eeSXin Li
1107*8c35d5eeSXin Li    # If there's just a cc and the header can't be found then it's ok.
1108*8c35d5eeSXin Li    message = self.PerformIncludeWhatYouUse(
1109*8c35d5eeSXin Li        """#include "blah/a.h"
1110*8c35d5eeSXin Li           std::set<int> foo;""",
1111*8c35d5eeSXin Li        filename='blah/a.cc')
1112*8c35d5eeSXin Li    self.assertEquals(message, '')
1113*8c35d5eeSXin Li
1114*8c35d5eeSXin Li    # Make sure we find the headers with relative paths.
1115*8c35d5eeSXin Li    mock_header_contents = ['']
1116*8c35d5eeSXin Li    message = self.PerformIncludeWhatYouUse(
1117*8c35d5eeSXin Li        """#include "%s/a.h"
1118*8c35d5eeSXin Li           std::set<int> foo;""" % os.path.basename(os.getcwd()),
1119*8c35d5eeSXin Li        filename='a.cc',
1120*8c35d5eeSXin Li        io=MockIo(mock_header_contents))
1121*8c35d5eeSXin Li    self.assertEquals(message, 'Add #include <set> for set<>  '
1122*8c35d5eeSXin Li                      '[build/include_what_you_use] [4]')
1123*8c35d5eeSXin Li
1124*8c35d5eeSXin Li  def testFilesBelongToSameModule(self):
1125*8c35d5eeSXin Li    f = cpplint.FilesBelongToSameModule
1126*8c35d5eeSXin Li    self.assertEquals((True, ''), f('a.cc', 'a.h'))
1127*8c35d5eeSXin Li    self.assertEquals((True, ''), f('base/google.cc', 'base/google.h'))
1128*8c35d5eeSXin Li    self.assertEquals((True, ''), f('base/google_test.cc', 'base/google.h'))
1129*8c35d5eeSXin Li    self.assertEquals((True, ''),
1130*8c35d5eeSXin Li                      f('base/google_unittest.cc', 'base/google.h'))
1131*8c35d5eeSXin Li    self.assertEquals((True, ''),
1132*8c35d5eeSXin Li                      f('base/internal/google_unittest.cc',
1133*8c35d5eeSXin Li                        'base/public/google.h'))
1134*8c35d5eeSXin Li    self.assertEquals((True, 'xxx/yyy/'),
1135*8c35d5eeSXin Li                      f('xxx/yyy/base/internal/google_unittest.cc',
1136*8c35d5eeSXin Li                        'base/public/google.h'))
1137*8c35d5eeSXin Li    self.assertEquals((True, 'xxx/yyy/'),
1138*8c35d5eeSXin Li                      f('xxx/yyy/base/google_unittest.cc',
1139*8c35d5eeSXin Li                        'base/public/google.h'))
1140*8c35d5eeSXin Li    self.assertEquals((True, ''),
1141*8c35d5eeSXin Li                      f('base/google_unittest.cc', 'base/google-inl.h'))
1142*8c35d5eeSXin Li    self.assertEquals((True, '/home/build/google3/'),
1143*8c35d5eeSXin Li                      f('/home/build/google3/base/google.cc', 'base/google.h'))
1144*8c35d5eeSXin Li
1145*8c35d5eeSXin Li    self.assertEquals((False, ''),
1146*8c35d5eeSXin Li                      f('/home/build/google3/base/google.cc', 'basu/google.h'))
1147*8c35d5eeSXin Li    self.assertEquals((False, ''), f('a.cc', 'b.h'))
1148*8c35d5eeSXin Li
1149*8c35d5eeSXin Li  def testCleanseLine(self):
1150*8c35d5eeSXin Li    self.assertEquals('int foo = 0;',
1151*8c35d5eeSXin Li                      cpplint.CleanseComments('int foo = 0;  // danger!'))
1152*8c35d5eeSXin Li    self.assertEquals('int o = 0;',
1153*8c35d5eeSXin Li                      cpplint.CleanseComments('int /* foo */ o = 0;'))
1154*8c35d5eeSXin Li    self.assertEquals('foo(int a, int b);',
1155*8c35d5eeSXin Li                      cpplint.CleanseComments('foo(int a /* abc */, int b);'))
1156*8c35d5eeSXin Li    self.assertEqual('f(a, b);',
1157*8c35d5eeSXin Li                     cpplint.CleanseComments('f(a, /* name */ b);'))
1158*8c35d5eeSXin Li    self.assertEqual('f(a, b);',
1159*8c35d5eeSXin Li                     cpplint.CleanseComments('f(a /* name */, b);'))
1160*8c35d5eeSXin Li    self.assertEqual('f(a, b);',
1161*8c35d5eeSXin Li                     cpplint.CleanseComments('f(a, /* name */b);'))
1162*8c35d5eeSXin Li    self.assertEqual('f(a, b, c);',
1163*8c35d5eeSXin Li                     cpplint.CleanseComments('f(a, /**/b, /**/c);'))
1164*8c35d5eeSXin Li    self.assertEqual('f(a, b, c);',
1165*8c35d5eeSXin Li                     cpplint.CleanseComments('f(a, /**/b/**/, c);'))
1166*8c35d5eeSXin Li
1167*8c35d5eeSXin Li  def testRawStrings(self):
1168*8c35d5eeSXin Li    self.TestMultiLineLint(
1169*8c35d5eeSXin Li        """
1170*8c35d5eeSXin Li        void Func() {
1171*8c35d5eeSXin Li          static const char kString[] = R"(
1172*8c35d5eeSXin Li            #endif  <- invalid preprocessor should be ignored
1173*8c35d5eeSXin Li            */      <- invalid comment should be ignored too
1174*8c35d5eeSXin Li          )";
1175*8c35d5eeSXin Li        }""",
1176*8c35d5eeSXin Li        '')
1177*8c35d5eeSXin Li    self.TestMultiLineLint(
1178*8c35d5eeSXin Li        """
1179*8c35d5eeSXin Li        void Func() {
1180*8c35d5eeSXin Li          string s = R"TrueDelimiter(
1181*8c35d5eeSXin Li              )"
1182*8c35d5eeSXin Li              )FalseDelimiter"
1183*8c35d5eeSXin Li              )TrueDelimiter";
1184*8c35d5eeSXin Li        }""",
1185*8c35d5eeSXin Li        '')
1186*8c35d5eeSXin Li    self.TestMultiLineLint(
1187*8c35d5eeSXin Li        """
1188*8c35d5eeSXin Li        void Func() {
1189*8c35d5eeSXin Li          char char kString[] = R"(  ";" )";
1190*8c35d5eeSXin Li        }""",
1191*8c35d5eeSXin Li        '')
1192*8c35d5eeSXin Li    self.TestMultiLineLint(
1193*8c35d5eeSXin Li        """
1194*8c35d5eeSXin Li        static const char kRawString[] = R"(
1195*8c35d5eeSXin Li          \tstatic const int kLineWithTab = 1;
1196*8c35d5eeSXin Li          static const int kLineWithTrailingWhiteSpace = 1;\x20
1197*8c35d5eeSXin Li
1198*8c35d5eeSXin Li           void WeirdNumberOfSpacesAtLineStart() {
1199*8c35d5eeSXin Li            string x;
1200*8c35d5eeSXin Li            x += StrCat("Use StrAppend instead");
1201*8c35d5eeSXin Li          }
1202*8c35d5eeSXin Li
1203*8c35d5eeSXin Li          void BlankLineAtEndOfBlock() {
1204*8c35d5eeSXin Li            // TODO incorrectly formatted
1205*8c35d5eeSXin Li            //Badly formatted comment
1206*8c35d5eeSXin Li
1207*8c35d5eeSXin Li          }
1208*8c35d5eeSXin Li
1209*8c35d5eeSXin Li        )";""",
1210*8c35d5eeSXin Li        '')
1211*8c35d5eeSXin Li    self.TestMultiLineLint(
1212*8c35d5eeSXin Li        """
1213*8c35d5eeSXin Li        void Func() {
1214*8c35d5eeSXin Li          string s = StrCat(R"TrueDelimiter(
1215*8c35d5eeSXin Li              )"
1216*8c35d5eeSXin Li              )FalseDelimiter"
1217*8c35d5eeSXin Li              )TrueDelimiter", R"TrueDelimiter2(
1218*8c35d5eeSXin Li              )"
1219*8c35d5eeSXin Li              )FalseDelimiter2"
1220*8c35d5eeSXin Li              )TrueDelimiter2");
1221*8c35d5eeSXin Li        }""",
1222*8c35d5eeSXin Li        '')
1223*8c35d5eeSXin Li    self.TestMultiLineLint(
1224*8c35d5eeSXin Li        """
1225*8c35d5eeSXin Li        static SomeStruct kData = {
1226*8c35d5eeSXin Li            {0, R"(line1
1227*8c35d5eeSXin Li                   line2
1228*8c35d5eeSXin Li                   )"}
1229*8c35d5eeSXin Li            };""",
1230*8c35d5eeSXin Li        '')
1231*8c35d5eeSXin Li
1232*8c35d5eeSXin Li  def testMultiLineComments(self):
1233*8c35d5eeSXin Li    # missing explicit is bad
1234*8c35d5eeSXin Li    self.TestMultiLineLint(
1235*8c35d5eeSXin Li        r"""int a = 0;
1236*8c35d5eeSXin Li            /* multi-liner
1237*8c35d5eeSXin Li            class Foo {
1238*8c35d5eeSXin Li            Foo(int f);  // should cause a lint warning in code
1239*8c35d5eeSXin Li            }
1240*8c35d5eeSXin Li            */ """,
1241*8c35d5eeSXin Li        '')
1242*8c35d5eeSXin Li    self.TestMultiLineLint(
1243*8c35d5eeSXin Li        r"""/* int a = 0; multi-liner
1244*8c35d5eeSXin Li              static const int b = 0;""",
1245*8c35d5eeSXin Li        'Could not find end of multi-line comment'
1246*8c35d5eeSXin Li        '  [readability/multiline_comment] [5]')
1247*8c35d5eeSXin Li    self.TestMultiLineLint(r"""  /* multi-line comment""",
1248*8c35d5eeSXin Li                           'Could not find end of multi-line comment'
1249*8c35d5eeSXin Li                           '  [readability/multiline_comment] [5]')
1250*8c35d5eeSXin Li    self.TestMultiLineLint(r"""  // /* comment, but not multi-line""", '')
1251*8c35d5eeSXin Li    self.TestMultiLineLint(r"""/**********
1252*8c35d5eeSXin Li                                 */""", '')
1253*8c35d5eeSXin Li    self.TestMultiLineLint(r"""/**
1254*8c35d5eeSXin Li                                 * Doxygen comment
1255*8c35d5eeSXin Li                                 */""",
1256*8c35d5eeSXin Li                           '')
1257*8c35d5eeSXin Li    self.TestMultiLineLint(r"""/*!
1258*8c35d5eeSXin Li                                 * Doxygen comment
1259*8c35d5eeSXin Li                                 */""",
1260*8c35d5eeSXin Li                           '')
1261*8c35d5eeSXin Li
1262*8c35d5eeSXin Li  def testMultilineStrings(self):
1263*8c35d5eeSXin Li    multiline_string_error_message = (
1264*8c35d5eeSXin Li        'Multi-line string ("...") found.  This lint script doesn\'t '
1265*8c35d5eeSXin Li        'do well with such strings, and may give bogus warnings.  '
1266*8c35d5eeSXin Li        'Use C++11 raw strings or concatenation instead.'
1267*8c35d5eeSXin Li        '  [readability/multiline_string] [5]')
1268*8c35d5eeSXin Li
1269*8c35d5eeSXin Li    file_path = 'mydir/foo.cc'
1270*8c35d5eeSXin Li
1271*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
1272*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'cc',
1273*8c35d5eeSXin Li                            ['const char* str = "This is a\\',
1274*8c35d5eeSXin Li                             ' multiline string.";'],
1275*8c35d5eeSXin Li                            error_collector)
1276*8c35d5eeSXin Li    self.assertEquals(
1277*8c35d5eeSXin Li        2,  # One per line.
1278*8c35d5eeSXin Li        error_collector.ResultList().count(multiline_string_error_message))
1279*8c35d5eeSXin Li
1280*8c35d5eeSXin Li  # Test non-explicit single-argument constructors
1281*8c35d5eeSXin Li  def testExplicitSingleArgumentConstructors(self):
1282*8c35d5eeSXin Li    old_verbose_level = cpplint._cpplint_state.verbose_level
1283*8c35d5eeSXin Li    cpplint._cpplint_state.verbose_level = 0
1284*8c35d5eeSXin Li
1285*8c35d5eeSXin Li    try:
1286*8c35d5eeSXin Li      # missing explicit is bad
1287*8c35d5eeSXin Li      self.TestMultiLineLint(
1288*8c35d5eeSXin Li          """
1289*8c35d5eeSXin Li          class Foo {
1290*8c35d5eeSXin Li            Foo(int f);
1291*8c35d5eeSXin Li          };""",
1292*8c35d5eeSXin Li          'Single-parameter constructors should be marked explicit.'
1293*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1294*8c35d5eeSXin Li      # missing explicit is bad, even with whitespace
1295*8c35d5eeSXin Li      self.TestMultiLineLint(
1296*8c35d5eeSXin Li          """
1297*8c35d5eeSXin Li          class Foo {
1298*8c35d5eeSXin Li            Foo (int f);
1299*8c35d5eeSXin Li          };""",
1300*8c35d5eeSXin Li          ['Extra space before ( in function call  [whitespace/parens] [4]',
1301*8c35d5eeSXin Li           'Single-parameter constructors should be marked explicit.'
1302*8c35d5eeSXin Li           '  [runtime/explicit] [5]'])
1303*8c35d5eeSXin Li      # missing explicit, with distracting comment, is still bad
1304*8c35d5eeSXin Li      self.TestMultiLineLint(
1305*8c35d5eeSXin Li          """
1306*8c35d5eeSXin Li          class Foo {
1307*8c35d5eeSXin Li            Foo(int f);  // simpler than Foo(blargh, blarg)
1308*8c35d5eeSXin Li          };""",
1309*8c35d5eeSXin Li          'Single-parameter constructors should be marked explicit.'
1310*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1311*8c35d5eeSXin Li      # missing explicit, with qualified classname
1312*8c35d5eeSXin Li      self.TestMultiLineLint(
1313*8c35d5eeSXin Li          """
1314*8c35d5eeSXin Li          class Qualifier::AnotherOne::Foo {
1315*8c35d5eeSXin Li            Foo(int f);
1316*8c35d5eeSXin Li          };""",
1317*8c35d5eeSXin Li          'Single-parameter constructors should be marked explicit.'
1318*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1319*8c35d5eeSXin Li      # missing explicit for inline constructors is bad as well
1320*8c35d5eeSXin Li      self.TestMultiLineLint(
1321*8c35d5eeSXin Li          """
1322*8c35d5eeSXin Li          class Foo {
1323*8c35d5eeSXin Li            inline Foo(int f);
1324*8c35d5eeSXin Li          };""",
1325*8c35d5eeSXin Li          'Single-parameter constructors should be marked explicit.'
1326*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1327*8c35d5eeSXin Li      # missing explicit for constexpr constructors is bad as well
1328*8c35d5eeSXin Li      self.TestMultiLineLint(
1329*8c35d5eeSXin Li          """
1330*8c35d5eeSXin Li          class Foo {
1331*8c35d5eeSXin Li            constexpr Foo(int f);
1332*8c35d5eeSXin Li          };""",
1333*8c35d5eeSXin Li          'Single-parameter constructors should be marked explicit.'
1334*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1335*8c35d5eeSXin Li      # missing explicit for constexpr+inline constructors is bad as well
1336*8c35d5eeSXin Li      self.TestMultiLineLint(
1337*8c35d5eeSXin Li          """
1338*8c35d5eeSXin Li          class Foo {
1339*8c35d5eeSXin Li            constexpr inline Foo(int f);
1340*8c35d5eeSXin Li          };""",
1341*8c35d5eeSXin Li          'Single-parameter constructors should be marked explicit.'
1342*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1343*8c35d5eeSXin Li      self.TestMultiLineLint(
1344*8c35d5eeSXin Li          """
1345*8c35d5eeSXin Li          class Foo {
1346*8c35d5eeSXin Li            inline constexpr Foo(int f);
1347*8c35d5eeSXin Li          };""",
1348*8c35d5eeSXin Li          'Single-parameter constructors should be marked explicit.'
1349*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1350*8c35d5eeSXin Li      # explicit with inline is accepted
1351*8c35d5eeSXin Li      self.TestMultiLineLint(
1352*8c35d5eeSXin Li          """
1353*8c35d5eeSXin Li          class Foo {
1354*8c35d5eeSXin Li            inline explicit Foo(int f);
1355*8c35d5eeSXin Li          };""",
1356*8c35d5eeSXin Li          '')
1357*8c35d5eeSXin Li      self.TestMultiLineLint(
1358*8c35d5eeSXin Li          """
1359*8c35d5eeSXin Li          class Foo {
1360*8c35d5eeSXin Li            explicit inline Foo(int f);
1361*8c35d5eeSXin Li          };""",
1362*8c35d5eeSXin Li          '')
1363*8c35d5eeSXin Li      # explicit with constexpr is accepted
1364*8c35d5eeSXin Li      self.TestMultiLineLint(
1365*8c35d5eeSXin Li          """
1366*8c35d5eeSXin Li          class Foo {
1367*8c35d5eeSXin Li            constexpr explicit Foo(int f);
1368*8c35d5eeSXin Li          };""",
1369*8c35d5eeSXin Li          '')
1370*8c35d5eeSXin Li      self.TestMultiLineLint(
1371*8c35d5eeSXin Li          """
1372*8c35d5eeSXin Li          class Foo {
1373*8c35d5eeSXin Li            explicit constexpr Foo(int f);
1374*8c35d5eeSXin Li          };""",
1375*8c35d5eeSXin Li          '')
1376*8c35d5eeSXin Li      # explicit with constexpr+inline is accepted
1377*8c35d5eeSXin Li      self.TestMultiLineLint(
1378*8c35d5eeSXin Li          """
1379*8c35d5eeSXin Li          class Foo {
1380*8c35d5eeSXin Li            inline constexpr explicit Foo(int f);
1381*8c35d5eeSXin Li          };""",
1382*8c35d5eeSXin Li          '')
1383*8c35d5eeSXin Li      self.TestMultiLineLint(
1384*8c35d5eeSXin Li          """
1385*8c35d5eeSXin Li          class Foo {
1386*8c35d5eeSXin Li            explicit inline constexpr Foo(int f);
1387*8c35d5eeSXin Li          };""",
1388*8c35d5eeSXin Li          '')
1389*8c35d5eeSXin Li      self.TestMultiLineLint(
1390*8c35d5eeSXin Li          """
1391*8c35d5eeSXin Li          class Foo {
1392*8c35d5eeSXin Li            constexpr inline explicit Foo(int f);
1393*8c35d5eeSXin Li          };""",
1394*8c35d5eeSXin Li          '')
1395*8c35d5eeSXin Li      self.TestMultiLineLint(
1396*8c35d5eeSXin Li          """
1397*8c35d5eeSXin Li          class Foo {
1398*8c35d5eeSXin Li            explicit constexpr inline Foo(int f);
1399*8c35d5eeSXin Li          };""",
1400*8c35d5eeSXin Li          '')
1401*8c35d5eeSXin Li      # structs are caught as well.
1402*8c35d5eeSXin Li      self.TestMultiLineLint(
1403*8c35d5eeSXin Li          """
1404*8c35d5eeSXin Li          struct Foo {
1405*8c35d5eeSXin Li            Foo(int f);
1406*8c35d5eeSXin Li          };""",
1407*8c35d5eeSXin Li          'Single-parameter constructors should be marked explicit.'
1408*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1409*8c35d5eeSXin Li      # Templatized classes are caught as well.
1410*8c35d5eeSXin Li      self.TestMultiLineLint(
1411*8c35d5eeSXin Li          """
1412*8c35d5eeSXin Li          template<typename T> class Foo {
1413*8c35d5eeSXin Li            Foo(int f);
1414*8c35d5eeSXin Li          };""",
1415*8c35d5eeSXin Li          'Single-parameter constructors should be marked explicit.'
1416*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1417*8c35d5eeSXin Li      # inline case for templatized classes.
1418*8c35d5eeSXin Li      self.TestMultiLineLint(
1419*8c35d5eeSXin Li          """
1420*8c35d5eeSXin Li          template<typename T> class Foo {
1421*8c35d5eeSXin Li            inline Foo(int f);
1422*8c35d5eeSXin Li          };""",
1423*8c35d5eeSXin Li          'Single-parameter constructors should be marked explicit.'
1424*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1425*8c35d5eeSXin Li      # constructors with a default argument should still be marked explicit
1426*8c35d5eeSXin Li      self.TestMultiLineLint(
1427*8c35d5eeSXin Li          """
1428*8c35d5eeSXin Li          class Foo {
1429*8c35d5eeSXin Li            Foo(int f = 0);
1430*8c35d5eeSXin Li          };""",
1431*8c35d5eeSXin Li          'Constructors callable with one argument should be marked explicit.'
1432*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1433*8c35d5eeSXin Li      # multi-argument constructors with all but one default argument should be
1434*8c35d5eeSXin Li      # marked explicit
1435*8c35d5eeSXin Li      self.TestMultiLineLint(
1436*8c35d5eeSXin Li          """
1437*8c35d5eeSXin Li          class Foo {
1438*8c35d5eeSXin Li            Foo(int f, int g = 0);
1439*8c35d5eeSXin Li          };""",
1440*8c35d5eeSXin Li          'Constructors callable with one argument should be marked explicit.'
1441*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1442*8c35d5eeSXin Li      # multi-argument constructors with all default arguments should be marked
1443*8c35d5eeSXin Li      # explicit
1444*8c35d5eeSXin Li      self.TestMultiLineLint(
1445*8c35d5eeSXin Li          """
1446*8c35d5eeSXin Li          class Foo {
1447*8c35d5eeSXin Li            Foo(int f = 0, int g = 0);
1448*8c35d5eeSXin Li          };""",
1449*8c35d5eeSXin Li          'Constructors callable with one argument should be marked explicit.'
1450*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1451*8c35d5eeSXin Li      # explicit no-argument constructors are bad
1452*8c35d5eeSXin Li      self.TestMultiLineLint(
1453*8c35d5eeSXin Li          """
1454*8c35d5eeSXin Li          class Foo {
1455*8c35d5eeSXin Li            explicit Foo();
1456*8c35d5eeSXin Li          };""",
1457*8c35d5eeSXin Li          'Zero-parameter constructors should not be marked explicit.'
1458*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1459*8c35d5eeSXin Li      # void constructors are considered no-argument
1460*8c35d5eeSXin Li      self.TestMultiLineLint(
1461*8c35d5eeSXin Li          """
1462*8c35d5eeSXin Li          class Foo {
1463*8c35d5eeSXin Li            explicit Foo(void);
1464*8c35d5eeSXin Li          };""",
1465*8c35d5eeSXin Li          'Zero-parameter constructors should not be marked explicit.'
1466*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1467*8c35d5eeSXin Li      # No warning for multi-parameter constructors
1468*8c35d5eeSXin Li      self.TestMultiLineLint(
1469*8c35d5eeSXin Li          """
1470*8c35d5eeSXin Li          class Foo {
1471*8c35d5eeSXin Li            explicit Foo(int f, int g);
1472*8c35d5eeSXin Li          };""",
1473*8c35d5eeSXin Li          '')
1474*8c35d5eeSXin Li      self.TestMultiLineLint(
1475*8c35d5eeSXin Li          """
1476*8c35d5eeSXin Li          class Foo {
1477*8c35d5eeSXin Li            explicit Foo(int f, int g = 0);
1478*8c35d5eeSXin Li          };""",
1479*8c35d5eeSXin Li          '')
1480*8c35d5eeSXin Li      # single-argument constructors that take a function that takes multiple
1481*8c35d5eeSXin Li      # arguments should be explicit
1482*8c35d5eeSXin Li      self.TestMultiLineLint(
1483*8c35d5eeSXin Li          """
1484*8c35d5eeSXin Li          class Foo {
1485*8c35d5eeSXin Li            Foo(void (*f)(int f, int g));
1486*8c35d5eeSXin Li          };""",
1487*8c35d5eeSXin Li          'Single-parameter constructors should be marked explicit.'
1488*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1489*8c35d5eeSXin Li      # single-argument constructors that take a single template argument with
1490*8c35d5eeSXin Li      # multiple parameters should be explicit
1491*8c35d5eeSXin Li      self.TestMultiLineLint(
1492*8c35d5eeSXin Li          """
1493*8c35d5eeSXin Li          template <typename T, typename S>
1494*8c35d5eeSXin Li          class Foo {
1495*8c35d5eeSXin Li            Foo(Bar<T, S> b);
1496*8c35d5eeSXin Li          };""",
1497*8c35d5eeSXin Li          'Single-parameter constructors should be marked explicit.'
1498*8c35d5eeSXin Li          '  [runtime/explicit] [5]')
1499*8c35d5eeSXin Li      # but copy constructors that take multiple template parameters are OK
1500*8c35d5eeSXin Li      self.TestMultiLineLint(
1501*8c35d5eeSXin Li          """
1502*8c35d5eeSXin Li          template <typename T, S>
1503*8c35d5eeSXin Li          class Foo {
1504*8c35d5eeSXin Li            Foo(Foo<T, S>& f);
1505*8c35d5eeSXin Li          };""",
1506*8c35d5eeSXin Li          '')
1507*8c35d5eeSXin Li      # proper style is okay
1508*8c35d5eeSXin Li      self.TestMultiLineLint(
1509*8c35d5eeSXin Li          """
1510*8c35d5eeSXin Li          class Foo {
1511*8c35d5eeSXin Li            explicit Foo(int f);
1512*8c35d5eeSXin Li          };""",
1513*8c35d5eeSXin Li          '')
1514*8c35d5eeSXin Li      # two argument constructor is okay
1515*8c35d5eeSXin Li      self.TestMultiLineLint(
1516*8c35d5eeSXin Li          """
1517*8c35d5eeSXin Li          class Foo {
1518*8c35d5eeSXin Li            Foo(int f, int b);
1519*8c35d5eeSXin Li          };""",
1520*8c35d5eeSXin Li          '')
1521*8c35d5eeSXin Li      # two argument constructor, across two lines, is okay
1522*8c35d5eeSXin Li      self.TestMultiLineLint(
1523*8c35d5eeSXin Li          """
1524*8c35d5eeSXin Li          class Foo {
1525*8c35d5eeSXin Li            Foo(int f,
1526*8c35d5eeSXin Li                int b);
1527*8c35d5eeSXin Li          };""",
1528*8c35d5eeSXin Li          '')
1529*8c35d5eeSXin Li      # non-constructor (but similar name), is okay
1530*8c35d5eeSXin Li      self.TestMultiLineLint(
1531*8c35d5eeSXin Li          """
1532*8c35d5eeSXin Li          class Foo {
1533*8c35d5eeSXin Li            aFoo(int f);
1534*8c35d5eeSXin Li          };""",
1535*8c35d5eeSXin Li          '')
1536*8c35d5eeSXin Li      # constructor with void argument is okay
1537*8c35d5eeSXin Li      self.TestMultiLineLint(
1538*8c35d5eeSXin Li          """
1539*8c35d5eeSXin Li          class Foo {
1540*8c35d5eeSXin Li            Foo(void);
1541*8c35d5eeSXin Li          };""",
1542*8c35d5eeSXin Li          '')
1543*8c35d5eeSXin Li      # single argument method is okay
1544*8c35d5eeSXin Li      self.TestMultiLineLint(
1545*8c35d5eeSXin Li          """
1546*8c35d5eeSXin Li          class Foo {
1547*8c35d5eeSXin Li            Bar(int b);
1548*8c35d5eeSXin Li          };""",
1549*8c35d5eeSXin Li          '')
1550*8c35d5eeSXin Li      # comments should be ignored
1551*8c35d5eeSXin Li      self.TestMultiLineLint(
1552*8c35d5eeSXin Li          """
1553*8c35d5eeSXin Li          class Foo {
1554*8c35d5eeSXin Li          // Foo(int f);
1555*8c35d5eeSXin Li          };""",
1556*8c35d5eeSXin Li          '')
1557*8c35d5eeSXin Li      # single argument function following class definition is okay
1558*8c35d5eeSXin Li      # (okay, it's not actually valid, but we don't want a false positive)
1559*8c35d5eeSXin Li      self.TestMultiLineLint(
1560*8c35d5eeSXin Li          """
1561*8c35d5eeSXin Li          class Foo {
1562*8c35d5eeSXin Li            Foo(int f, int b);
1563*8c35d5eeSXin Li          };
1564*8c35d5eeSXin Li          Foo(int f);""",
1565*8c35d5eeSXin Li          '')
1566*8c35d5eeSXin Li      # single argument function is okay
1567*8c35d5eeSXin Li      self.TestMultiLineLint(
1568*8c35d5eeSXin Li          """static Foo(int f);""",
1569*8c35d5eeSXin Li          '')
1570*8c35d5eeSXin Li      # single argument copy constructor is okay.
1571*8c35d5eeSXin Li      self.TestMultiLineLint(
1572*8c35d5eeSXin Li          """
1573*8c35d5eeSXin Li          class Foo {
1574*8c35d5eeSXin Li            Foo(const Foo&);
1575*8c35d5eeSXin Li          };""",
1576*8c35d5eeSXin Li          '')
1577*8c35d5eeSXin Li      self.TestMultiLineLint(
1578*8c35d5eeSXin Li          """
1579*8c35d5eeSXin Li          class Foo {
1580*8c35d5eeSXin Li            Foo(Foo const&);
1581*8c35d5eeSXin Li          };""",
1582*8c35d5eeSXin Li          '')
1583*8c35d5eeSXin Li      self.TestMultiLineLint(
1584*8c35d5eeSXin Li          """
1585*8c35d5eeSXin Li          class Foo {
1586*8c35d5eeSXin Li            Foo(Foo&);
1587*8c35d5eeSXin Li          };""",
1588*8c35d5eeSXin Li          '')
1589*8c35d5eeSXin Li      # templatized copy constructor is okay.
1590*8c35d5eeSXin Li      self.TestMultiLineLint(
1591*8c35d5eeSXin Li          """
1592*8c35d5eeSXin Li          template<typename T> class Foo {
1593*8c35d5eeSXin Li            Foo(const Foo<T>&);
1594*8c35d5eeSXin Li          };""",
1595*8c35d5eeSXin Li          '')
1596*8c35d5eeSXin Li      # Special case for std::initializer_list
1597*8c35d5eeSXin Li      self.TestMultiLineLint(
1598*8c35d5eeSXin Li          """
1599*8c35d5eeSXin Li          class Foo {
1600*8c35d5eeSXin Li            Foo(std::initializer_list<T> &arg) {}
1601*8c35d5eeSXin Li          };""",
1602*8c35d5eeSXin Li          '')
1603*8c35d5eeSXin Li      # Anything goes inside an assembly block
1604*8c35d5eeSXin Li      error_collector = ErrorCollector(self.assert_)
1605*8c35d5eeSXin Li      cpplint.ProcessFileData('foo.cc', 'cc',
1606*8c35d5eeSXin Li                              ['void Func() {',
1607*8c35d5eeSXin Li                               '  __asm__ (',
1608*8c35d5eeSXin Li                               '    "hlt"',
1609*8c35d5eeSXin Li                               '  );',
1610*8c35d5eeSXin Li                               '  asm {',
1611*8c35d5eeSXin Li                               '    movdqa [edx + 32], xmm2',
1612*8c35d5eeSXin Li                               '  }',
1613*8c35d5eeSXin Li                               '}'],
1614*8c35d5eeSXin Li                              error_collector)
1615*8c35d5eeSXin Li      self.assertEquals(
1616*8c35d5eeSXin Li          0,
1617*8c35d5eeSXin Li          error_collector.ResultList().count(
1618*8c35d5eeSXin Li              'Extra space before ( in function call  [whitespace/parens] [4]'))
1619*8c35d5eeSXin Li      self.assertEquals(
1620*8c35d5eeSXin Li          0,
1621*8c35d5eeSXin Li          error_collector.ResultList().count(
1622*8c35d5eeSXin Li              'Closing ) should be moved to the previous line  '
1623*8c35d5eeSXin Li              '[whitespace/parens] [2]'))
1624*8c35d5eeSXin Li      self.assertEquals(
1625*8c35d5eeSXin Li          0,
1626*8c35d5eeSXin Li          error_collector.ResultList().count(
1627*8c35d5eeSXin Li              'Extra space before [  [whitespace/braces] [5]'))
1628*8c35d5eeSXin Li    finally:
1629*8c35d5eeSXin Li      cpplint._cpplint_state.verbose_level = old_verbose_level
1630*8c35d5eeSXin Li
1631*8c35d5eeSXin Li  def testSlashStarCommentOnSingleLine(self):
1632*8c35d5eeSXin Li    self.TestMultiLineLint(
1633*8c35d5eeSXin Li        """/* static */ Foo(int f);""",
1634*8c35d5eeSXin Li        '')
1635*8c35d5eeSXin Li    self.TestMultiLineLint(
1636*8c35d5eeSXin Li        """/*/ static */  Foo(int f);""",
1637*8c35d5eeSXin Li        '')
1638*8c35d5eeSXin Li    self.TestMultiLineLint(
1639*8c35d5eeSXin Li        """/*/ static Foo(int f);""",
1640*8c35d5eeSXin Li        'Could not find end of multi-line comment'
1641*8c35d5eeSXin Li        '  [readability/multiline_comment] [5]')
1642*8c35d5eeSXin Li    self.TestMultiLineLint(
1643*8c35d5eeSXin Li        """  /*/ static Foo(int f);""",
1644*8c35d5eeSXin Li        'Could not find end of multi-line comment'
1645*8c35d5eeSXin Li        '  [readability/multiline_comment] [5]')
1646*8c35d5eeSXin Li    self.TestMultiLineLint(
1647*8c35d5eeSXin Li        """  /**/ static Foo(int f);""",
1648*8c35d5eeSXin Li        '')
1649*8c35d5eeSXin Li
1650*8c35d5eeSXin Li  # Test suspicious usage of "if" like this:
1651*8c35d5eeSXin Li  # if (a == b) {
1652*8c35d5eeSXin Li  #   DoSomething();
1653*8c35d5eeSXin Li  # } if (a == c) {   // Should be "else if".
1654*8c35d5eeSXin Li  #   DoSomething();  // This gets called twice if a == b && a == c.
1655*8c35d5eeSXin Li  # }
1656*8c35d5eeSXin Li  def testSuspiciousUsageOfIf(self):
1657*8c35d5eeSXin Li    self.TestLint(
1658*8c35d5eeSXin Li        '  if (a == b) {',
1659*8c35d5eeSXin Li        '')
1660*8c35d5eeSXin Li    self.TestLint(
1661*8c35d5eeSXin Li        '  } if (a == b) {',
1662*8c35d5eeSXin Li        'Did you mean "else if"? If not, start a new line for "if".'
1663*8c35d5eeSXin Li        '  [readability/braces] [4]')
1664*8c35d5eeSXin Li
1665*8c35d5eeSXin Li  # Test suspicious usage of memset. Specifically, a 0
1666*8c35d5eeSXin Li  # as the final argument is almost certainly an error.
1667*8c35d5eeSXin Li  def testSuspiciousUsageOfMemset(self):
1668*8c35d5eeSXin Li    # Normal use is okay.
1669*8c35d5eeSXin Li    self.TestLint(
1670*8c35d5eeSXin Li        '  memset(buf, 0, sizeof(buf))',
1671*8c35d5eeSXin Li        '')
1672*8c35d5eeSXin Li
1673*8c35d5eeSXin Li    # A 0 as the final argument is almost certainly an error.
1674*8c35d5eeSXin Li    self.TestLint(
1675*8c35d5eeSXin Li        '  memset(buf, sizeof(buf), 0)',
1676*8c35d5eeSXin Li        'Did you mean "memset(buf, 0, sizeof(buf))"?'
1677*8c35d5eeSXin Li        '  [runtime/memset] [4]')
1678*8c35d5eeSXin Li    self.TestLint(
1679*8c35d5eeSXin Li        '  memset(buf, xsize * ysize, 0)',
1680*8c35d5eeSXin Li        'Did you mean "memset(buf, 0, xsize * ysize)"?'
1681*8c35d5eeSXin Li        '  [runtime/memset] [4]')
1682*8c35d5eeSXin Li
1683*8c35d5eeSXin Li    # There is legitimate test code that uses this form.
1684*8c35d5eeSXin Li    # This is okay since the second argument is a literal.
1685*8c35d5eeSXin Li    self.TestLint(
1686*8c35d5eeSXin Li        "  memset(buf, 'y', 0)",
1687*8c35d5eeSXin Li        '')
1688*8c35d5eeSXin Li    self.TestLint(
1689*8c35d5eeSXin Li        '  memset(buf, 4, 0)',
1690*8c35d5eeSXin Li        '')
1691*8c35d5eeSXin Li    self.TestLint(
1692*8c35d5eeSXin Li        '  memset(buf, -1, 0)',
1693*8c35d5eeSXin Li        '')
1694*8c35d5eeSXin Li    self.TestLint(
1695*8c35d5eeSXin Li        '  memset(buf, 0xF1, 0)',
1696*8c35d5eeSXin Li        '')
1697*8c35d5eeSXin Li    self.TestLint(
1698*8c35d5eeSXin Li        '  memset(buf, 0xcd, 0)',
1699*8c35d5eeSXin Li        '')
1700*8c35d5eeSXin Li
1701*8c35d5eeSXin Li  def testRedundantVirtual(self):
1702*8c35d5eeSXin Li    self.TestLint('virtual void F()', '')
1703*8c35d5eeSXin Li    self.TestLint('virtual void F();', '')
1704*8c35d5eeSXin Li    self.TestLint('virtual void F() {}', '')
1705*8c35d5eeSXin Li
1706*8c35d5eeSXin Li    message_template = ('"%s" is redundant since function is already '
1707*8c35d5eeSXin Li                        'declared as "%s"  [readability/inheritance] [4]')
1708*8c35d5eeSXin Li    for virt_specifier in ['override', 'final']:
1709*8c35d5eeSXin Li      error_message = message_template % ('virtual', virt_specifier)
1710*8c35d5eeSXin Li      self.TestLint('virtual int F() %s' % virt_specifier, error_message)
1711*8c35d5eeSXin Li      self.TestLint('virtual int F() %s;' % virt_specifier, error_message)
1712*8c35d5eeSXin Li      self.TestLint('virtual int F() %s {' % virt_specifier, error_message)
1713*8c35d5eeSXin Li
1714*8c35d5eeSXin Li      error_collector = ErrorCollector(self.assert_)
1715*8c35d5eeSXin Li      cpplint.ProcessFileData(
1716*8c35d5eeSXin Li          'foo.cc', 'cc',
1717*8c35d5eeSXin Li          ['// Copyright 2014 Your Company.',
1718*8c35d5eeSXin Li           'virtual void F(int a,',
1719*8c35d5eeSXin Li           '               int b) ' + virt_specifier + ';',
1720*8c35d5eeSXin Li           'virtual void F(int a,',
1721*8c35d5eeSXin Li           '               int b) LOCKS_EXCLUDED(lock) ' + virt_specifier + ';',
1722*8c35d5eeSXin Li           'virtual void F(int a,',
1723*8c35d5eeSXin Li           '               int b)',
1724*8c35d5eeSXin Li           '    LOCKS_EXCLUDED(lock) ' + virt_specifier + ';',
1725*8c35d5eeSXin Li           ''],
1726*8c35d5eeSXin Li          error_collector)
1727*8c35d5eeSXin Li      self.assertEquals(
1728*8c35d5eeSXin Li          [error_message, error_message, error_message],
1729*8c35d5eeSXin Li          error_collector.Results())
1730*8c35d5eeSXin Li
1731*8c35d5eeSXin Li    error_message = message_template % ('override', 'final')
1732*8c35d5eeSXin Li    self.TestLint('int F() override final', error_message)
1733*8c35d5eeSXin Li    self.TestLint('int F() override final;', error_message)
1734*8c35d5eeSXin Li    self.TestLint('int F() override final {}', error_message)
1735*8c35d5eeSXin Li    self.TestLint('int F() final override', error_message)
1736*8c35d5eeSXin Li    self.TestLint('int F() final override;', error_message)
1737*8c35d5eeSXin Li    self.TestLint('int F() final override {}', error_message)
1738*8c35d5eeSXin Li
1739*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
1740*8c35d5eeSXin Li    cpplint.ProcessFileData(
1741*8c35d5eeSXin Li        'foo.cc', 'cc',
1742*8c35d5eeSXin Li        ['// Copyright 2014 Your Company.',
1743*8c35d5eeSXin Li         'struct A : virtual B {',
1744*8c35d5eeSXin Li         '  ~A() override;'
1745*8c35d5eeSXin Li         '};',
1746*8c35d5eeSXin Li         'class C',
1747*8c35d5eeSXin Li         '    : public D,',
1748*8c35d5eeSXin Li         '      public virtual E {',
1749*8c35d5eeSXin Li         '  void Func() override;',
1750*8c35d5eeSXin Li         '}',
1751*8c35d5eeSXin Li         ''],
1752*8c35d5eeSXin Li        error_collector)
1753*8c35d5eeSXin Li    self.assertEquals('', error_collector.Results())
1754*8c35d5eeSXin Li
1755*8c35d5eeSXin Li    self.TestLint('void Finalize(AnnotationProto *final) override;', '')
1756*8c35d5eeSXin Li
1757*8c35d5eeSXin Li  def testCheckDeprecated(self):
1758*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo_test.cc', '#include <iostream>', '')
1759*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo_unittest.cc', '#include <iostream>', '')
1760*8c35d5eeSXin Li
1761*8c35d5eeSXin Li  def testCheckPosixThreading(self):
1762*8c35d5eeSXin Li    self.TestLint('var = sctime_r()', '')
1763*8c35d5eeSXin Li    self.TestLint('var = strtok_r()', '')
1764*8c35d5eeSXin Li    self.TestLint('var = strtok_r(foo, ba, r)', '')
1765*8c35d5eeSXin Li    self.TestLint('var = brand()', '')
1766*8c35d5eeSXin Li    self.TestLint('_rand()', '')
1767*8c35d5eeSXin Li    self.TestLint('.rand()', '')
1768*8c35d5eeSXin Li    self.TestLint('->rand()', '')
1769*8c35d5eeSXin Li    self.TestLint('ACMRandom rand(seed)', '')
1770*8c35d5eeSXin Li    self.TestLint('ISAACRandom rand()', '')
1771*8c35d5eeSXin Li    self.TestLint('var = rand()',
1772*8c35d5eeSXin Li                  'Consider using rand_r(...) instead of rand(...)'
1773*8c35d5eeSXin Li                  ' for improved thread safety.'
1774*8c35d5eeSXin Li                  '  [runtime/threadsafe_fn] [2]')
1775*8c35d5eeSXin Li    self.TestLint('var = strtok(str, delim)',
1776*8c35d5eeSXin Li                  'Consider using strtok_r(...) '
1777*8c35d5eeSXin Li                  'instead of strtok(...)'
1778*8c35d5eeSXin Li                  ' for improved thread safety.'
1779*8c35d5eeSXin Li                  '  [runtime/threadsafe_fn] [2]')
1780*8c35d5eeSXin Li
1781*8c35d5eeSXin Li  def testVlogMisuse(self):
1782*8c35d5eeSXin Li    self.TestLint('VLOG(1)', '')
1783*8c35d5eeSXin Li    self.TestLint('VLOG(99)', '')
1784*8c35d5eeSXin Li    self.TestLint('LOG(ERROR)', '')
1785*8c35d5eeSXin Li    self.TestLint('LOG(INFO)', '')
1786*8c35d5eeSXin Li    self.TestLint('LOG(WARNING)', '')
1787*8c35d5eeSXin Li    self.TestLint('LOG(FATAL)', '')
1788*8c35d5eeSXin Li    self.TestLint('LOG(DFATAL)', '')
1789*8c35d5eeSXin Li    self.TestLint('VLOG(SOMETHINGWEIRD)', '')
1790*8c35d5eeSXin Li    self.TestLint('MYOWNVLOG(ERROR)', '')
1791*8c35d5eeSXin Li    errmsg = ('VLOG() should be used with numeric verbosity level.  '
1792*8c35d5eeSXin Li              'Use LOG() if you want symbolic severity levels.'
1793*8c35d5eeSXin Li              '  [runtime/vlog] [5]')
1794*8c35d5eeSXin Li    self.TestLint('VLOG(ERROR)', errmsg)
1795*8c35d5eeSXin Li    self.TestLint('VLOG(INFO)', errmsg)
1796*8c35d5eeSXin Li    self.TestLint('VLOG(WARNING)', errmsg)
1797*8c35d5eeSXin Li    self.TestLint('VLOG(FATAL)', errmsg)
1798*8c35d5eeSXin Li    self.TestLint('VLOG(DFATAL)', errmsg)
1799*8c35d5eeSXin Li    self.TestLint('  VLOG(ERROR)', errmsg)
1800*8c35d5eeSXin Li    self.TestLint('  VLOG(INFO)', errmsg)
1801*8c35d5eeSXin Li    self.TestLint('  VLOG(WARNING)', errmsg)
1802*8c35d5eeSXin Li    self.TestLint('  VLOG(FATAL)', errmsg)
1803*8c35d5eeSXin Li    self.TestLint('  VLOG(DFATAL)', errmsg)
1804*8c35d5eeSXin Li
1805*8c35d5eeSXin Li
1806*8c35d5eeSXin Li  # Test potential format string bugs like printf(foo).
1807*8c35d5eeSXin Li  def testFormatStrings(self):
1808*8c35d5eeSXin Li    self.TestLint('printf("foo")', '')
1809*8c35d5eeSXin Li    self.TestLint('printf("foo: %s", foo)', '')
1810*8c35d5eeSXin Li    self.TestLint('DocidForPrintf(docid)', '')  # Should not trigger.
1811*8c35d5eeSXin Li    self.TestLint('printf(format, value)', '')  # Should not trigger.
1812*8c35d5eeSXin Li    self.TestLint('printf(__VA_ARGS__)', '')  # Should not trigger.
1813*8c35d5eeSXin Li    self.TestLint('printf(format.c_str(), value)', '')  # Should not trigger.
1814*8c35d5eeSXin Li    self.TestLint('printf(format(index).c_str(), value)', '')
1815*8c35d5eeSXin Li    self.TestLint(
1816*8c35d5eeSXin Li        'printf(foo)',
1817*8c35d5eeSXin Li        'Potential format string bug. Do printf("%s", foo) instead.'
1818*8c35d5eeSXin Li        '  [runtime/printf] [4]')
1819*8c35d5eeSXin Li    self.TestLint(
1820*8c35d5eeSXin Li        'printf(foo.c_str())',
1821*8c35d5eeSXin Li        'Potential format string bug. '
1822*8c35d5eeSXin Li        'Do printf("%s", foo.c_str()) instead.'
1823*8c35d5eeSXin Li        '  [runtime/printf] [4]')
1824*8c35d5eeSXin Li    self.TestLint(
1825*8c35d5eeSXin Li        'printf(foo->c_str())',
1826*8c35d5eeSXin Li        'Potential format string bug. '
1827*8c35d5eeSXin Li        'Do printf("%s", foo->c_str()) instead.'
1828*8c35d5eeSXin Li        '  [runtime/printf] [4]')
1829*8c35d5eeSXin Li    self.TestLint(
1830*8c35d5eeSXin Li        'StringPrintf(foo)',
1831*8c35d5eeSXin Li        'Potential format string bug. Do StringPrintf("%s", foo) instead.'
1832*8c35d5eeSXin Li        ''
1833*8c35d5eeSXin Li        '  [runtime/printf] [4]')
1834*8c35d5eeSXin Li
1835*8c35d5eeSXin Li  # Test disallowed use of operator& and other operators.
1836*8c35d5eeSXin Li  def testIllegalOperatorOverloading(self):
1837*8c35d5eeSXin Li    errmsg = ('Unary operator& is dangerous.  Do not use it.'
1838*8c35d5eeSXin Li              '  [runtime/operator] [4]')
1839*8c35d5eeSXin Li    self.TestLint('void operator=(const Myclass&)', '')
1840*8c35d5eeSXin Li    self.TestLint('void operator&(int a, int b)', '')   # binary operator& ok
1841*8c35d5eeSXin Li    self.TestLint('void operator&() { }', errmsg)
1842*8c35d5eeSXin Li    self.TestLint('void operator & (  ) { }',
1843*8c35d5eeSXin Li                  ['Extra space after (  [whitespace/parens] [2]', errmsg])
1844*8c35d5eeSXin Li
1845*8c35d5eeSXin Li  # const string reference members are dangerous..
1846*8c35d5eeSXin Li  def testConstStringReferenceMembers(self):
1847*8c35d5eeSXin Li    errmsg = ('const string& members are dangerous. It is much better to use '
1848*8c35d5eeSXin Li              'alternatives, such as pointers or simple constants.'
1849*8c35d5eeSXin Li              '  [runtime/member_string_references] [2]')
1850*8c35d5eeSXin Li
1851*8c35d5eeSXin Li    members_declarations = ['const string& church',
1852*8c35d5eeSXin Li                            'const string &turing',
1853*8c35d5eeSXin Li                            'const string & godel']
1854*8c35d5eeSXin Li    # TODO(unknown): Enable also these tests if and when we ever
1855*8c35d5eeSXin Li    # decide to check for arbitrary member references.
1856*8c35d5eeSXin Li    #                         "const Turing & a",
1857*8c35d5eeSXin Li    #                         "const Church& a",
1858*8c35d5eeSXin Li    #                         "const vector<int>& a",
1859*8c35d5eeSXin Li    #                         "const     Kurt::Godel    &    godel",
1860*8c35d5eeSXin Li    #                         "const Kazimierz::Kuratowski& kk" ]
1861*8c35d5eeSXin Li
1862*8c35d5eeSXin Li    # The Good.
1863*8c35d5eeSXin Li
1864*8c35d5eeSXin Li    self.TestLint('void f(const string&)', '')
1865*8c35d5eeSXin Li    self.TestLint('const string& f(const string& a, const string& b)', '')
1866*8c35d5eeSXin Li    self.TestLint('typedef const string& A;', '')
1867*8c35d5eeSXin Li
1868*8c35d5eeSXin Li    for decl in members_declarations:
1869*8c35d5eeSXin Li      self.TestLint(decl + ' = b;', '')
1870*8c35d5eeSXin Li      self.TestLint(decl + '      =', '')
1871*8c35d5eeSXin Li
1872*8c35d5eeSXin Li    # The Bad.
1873*8c35d5eeSXin Li
1874*8c35d5eeSXin Li    for decl in members_declarations:
1875*8c35d5eeSXin Li      self.TestLint(decl + ';', errmsg)
1876*8c35d5eeSXin Li
1877*8c35d5eeSXin Li  # Variable-length arrays are not permitted.
1878*8c35d5eeSXin Li  def testVariableLengthArrayDetection(self):
1879*8c35d5eeSXin Li    errmsg = ('Do not use variable-length arrays.  Use an appropriately named '
1880*8c35d5eeSXin Li              "('k' followed by CamelCase) compile-time constant for the size."
1881*8c35d5eeSXin Li              '  [runtime/arrays] [1]')
1882*8c35d5eeSXin Li
1883*8c35d5eeSXin Li    self.TestLint('int a[any_old_variable];', errmsg)
1884*8c35d5eeSXin Li    self.TestLint('int doublesize[some_var * 2];', errmsg)
1885*8c35d5eeSXin Li    self.TestLint('int a[afunction()];', errmsg)
1886*8c35d5eeSXin Li    self.TestLint('int a[function(kMaxFooBars)];', errmsg)
1887*8c35d5eeSXin Li    self.TestLint('bool a_list[items_->size()];', errmsg)
1888*8c35d5eeSXin Li    self.TestLint('namespace::Type buffer[len+1];', errmsg)
1889*8c35d5eeSXin Li
1890*8c35d5eeSXin Li    self.TestLint('int a[64];', '')
1891*8c35d5eeSXin Li    self.TestLint('int a[0xFF];', '')
1892*8c35d5eeSXin Li    self.TestLint('int first[256], second[256];', '')
1893*8c35d5eeSXin Li    self.TestLint('int array_name[kCompileTimeConstant];', '')
1894*8c35d5eeSXin Li    self.TestLint('char buf[somenamespace::kBufSize];', '')
1895*8c35d5eeSXin Li    self.TestLint('int array_name[ALL_CAPS];', '')
1896*8c35d5eeSXin Li    self.TestLint('AClass array1[foo::bar::ALL_CAPS];', '')
1897*8c35d5eeSXin Li    self.TestLint('int a[kMaxStrLen + 1];', '')
1898*8c35d5eeSXin Li    self.TestLint('int a[sizeof(foo)];', '')
1899*8c35d5eeSXin Li    self.TestLint('int a[sizeof(*foo)];', '')
1900*8c35d5eeSXin Li    self.TestLint('int a[sizeof foo];', '')
1901*8c35d5eeSXin Li    self.TestLint('int a[sizeof(struct Foo)];', '')
1902*8c35d5eeSXin Li    self.TestLint('int a[128 - sizeof(const bar)];', '')
1903*8c35d5eeSXin Li    self.TestLint('int a[(sizeof(foo) * 4)];', '')
1904*8c35d5eeSXin Li    self.TestLint('int a[(arraysize(fixed_size_array)/2) << 1];', '')
1905*8c35d5eeSXin Li    self.TestLint('delete a[some_var];', '')
1906*8c35d5eeSXin Li    self.TestLint('return a[some_var];', '')
1907*8c35d5eeSXin Li
1908*8c35d5eeSXin Li  # DISALLOW_COPY_AND_ASSIGN and DISALLOW_IMPLICIT_CONSTRUCTORS should be at
1909*8c35d5eeSXin Li  # end of class if present.
1910*8c35d5eeSXin Li  def testDisallowMacrosAtEnd(self):
1911*8c35d5eeSXin Li    for macro_name in (
1912*8c35d5eeSXin Li        'DISALLOW_COPY_AND_ASSIGN',
1913*8c35d5eeSXin Li        'DISALLOW_IMPLICIT_CONSTRUCTORS'):
1914*8c35d5eeSXin Li      error_collector = ErrorCollector(self.assert_)
1915*8c35d5eeSXin Li      cpplint.ProcessFileData(
1916*8c35d5eeSXin Li          'foo.cc', 'cc',
1917*8c35d5eeSXin Li          ['// Copyright 2014 Your Company.',
1918*8c35d5eeSXin Li           'class SomeClass {',
1919*8c35d5eeSXin Li           ' private:',
1920*8c35d5eeSXin Li           '  %s(SomeClass);' % macro_name,
1921*8c35d5eeSXin Li           '  int member_;',
1922*8c35d5eeSXin Li           '};',
1923*8c35d5eeSXin Li           ''],
1924*8c35d5eeSXin Li          error_collector)
1925*8c35d5eeSXin Li      self.assertEquals(
1926*8c35d5eeSXin Li          ('%s should be the last thing in the class' % macro_name) +
1927*8c35d5eeSXin Li          '  [readability/constructors] [3]',
1928*8c35d5eeSXin Li          error_collector.Results())
1929*8c35d5eeSXin Li
1930*8c35d5eeSXin Li      error_collector = ErrorCollector(self.assert_)
1931*8c35d5eeSXin Li      cpplint.ProcessFileData(
1932*8c35d5eeSXin Li          'foo.cc', 'cc',
1933*8c35d5eeSXin Li          ['// Copyright 2014 Your Company.',
1934*8c35d5eeSXin Li           'class OuterClass {',
1935*8c35d5eeSXin Li           ' private:',
1936*8c35d5eeSXin Li           '  struct InnerClass {',
1937*8c35d5eeSXin Li           '   private:',
1938*8c35d5eeSXin Li           '    %s(InnerClass);' % macro_name,
1939*8c35d5eeSXin Li           '    int member;',
1940*8c35d5eeSXin Li           '  };',
1941*8c35d5eeSXin Li           '};',
1942*8c35d5eeSXin Li           ''],
1943*8c35d5eeSXin Li          error_collector)
1944*8c35d5eeSXin Li      self.assertEquals(
1945*8c35d5eeSXin Li          ('%s should be the last thing in the class' % macro_name) +
1946*8c35d5eeSXin Li          '  [readability/constructors] [3]',
1947*8c35d5eeSXin Li          error_collector.Results())
1948*8c35d5eeSXin Li
1949*8c35d5eeSXin Li      error_collector = ErrorCollector(self.assert_)
1950*8c35d5eeSXin Li      cpplint.ProcessFileData(
1951*8c35d5eeSXin Li          'foo.cc', 'cc',
1952*8c35d5eeSXin Li          ['// Copyright 2014 Your Company.',
1953*8c35d5eeSXin Li           'class OuterClass1 {',
1954*8c35d5eeSXin Li           ' private:',
1955*8c35d5eeSXin Li           '  struct InnerClass1 {',
1956*8c35d5eeSXin Li           '   private:',
1957*8c35d5eeSXin Li           '    %s(InnerClass1);' % macro_name,
1958*8c35d5eeSXin Li           '  };',
1959*8c35d5eeSXin Li           '  %s(OuterClass1);' % macro_name,
1960*8c35d5eeSXin Li           '};',
1961*8c35d5eeSXin Li           'struct OuterClass2 {',
1962*8c35d5eeSXin Li           ' private:',
1963*8c35d5eeSXin Li           '  class InnerClass2 {',
1964*8c35d5eeSXin Li           '   private:',
1965*8c35d5eeSXin Li           '    %s(InnerClass2);' % macro_name,
1966*8c35d5eeSXin Li           '    // comment',
1967*8c35d5eeSXin Li           '  };',
1968*8c35d5eeSXin Li           '',
1969*8c35d5eeSXin Li           '  %s(OuterClass2);' % macro_name,
1970*8c35d5eeSXin Li           '',
1971*8c35d5eeSXin Li           '  // comment',
1972*8c35d5eeSXin Li           '};',
1973*8c35d5eeSXin Li           'void Func() {',
1974*8c35d5eeSXin Li           '  struct LocalClass {',
1975*8c35d5eeSXin Li           '   private:',
1976*8c35d5eeSXin Li           '    %s(LocalClass);' % macro_name,
1977*8c35d5eeSXin Li           '  } variable;',
1978*8c35d5eeSXin Li           '}',
1979*8c35d5eeSXin Li           ''],
1980*8c35d5eeSXin Li          error_collector)
1981*8c35d5eeSXin Li      self.assertEquals('', error_collector.Results())
1982*8c35d5eeSXin Li
1983*8c35d5eeSXin Li  # Brace usage
1984*8c35d5eeSXin Li  def testBraces(self):
1985*8c35d5eeSXin Li    # Braces shouldn't be followed by a ; unless they're defining a struct
1986*8c35d5eeSXin Li    # or initializing an array
1987*8c35d5eeSXin Li    self.TestLint('int a[3] = { 1, 2, 3 };', '')
1988*8c35d5eeSXin Li    self.TestLint(
1989*8c35d5eeSXin Li        """const int foo[] =
1990*8c35d5eeSXin Li               {1, 2, 3 };""",
1991*8c35d5eeSXin Li        '')
1992*8c35d5eeSXin Li    # For single line, unmatched '}' with a ';' is ignored (not enough context)
1993*8c35d5eeSXin Li    self.TestMultiLineLint(
1994*8c35d5eeSXin Li        """int a[3] = { 1,
1995*8c35d5eeSXin Li                        2,
1996*8c35d5eeSXin Li                        3 };""",
1997*8c35d5eeSXin Li        '')
1998*8c35d5eeSXin Li    self.TestMultiLineLint(
1999*8c35d5eeSXin Li        """int a[2][3] = { { 1, 2 },
2000*8c35d5eeSXin Li                         { 3, 4 } };""",
2001*8c35d5eeSXin Li        '')
2002*8c35d5eeSXin Li    self.TestMultiLineLint(
2003*8c35d5eeSXin Li        """int a[2][3] =
2004*8c35d5eeSXin Li               { { 1, 2 },
2005*8c35d5eeSXin Li                 { 3, 4 } };""",
2006*8c35d5eeSXin Li        '')
2007*8c35d5eeSXin Li
2008*8c35d5eeSXin Li  # CHECK/EXPECT_TRUE/EXPECT_FALSE replacements
2009*8c35d5eeSXin Li  def testCheckCheck(self):
2010*8c35d5eeSXin Li    self.TestLint('CHECK(x == 42);',
2011*8c35d5eeSXin Li                  'Consider using CHECK_EQ instead of CHECK(a == b)'
2012*8c35d5eeSXin Li                  '  [readability/check] [2]')
2013*8c35d5eeSXin Li    self.TestLint('CHECK(x != 42);',
2014*8c35d5eeSXin Li                  'Consider using CHECK_NE instead of CHECK(a != b)'
2015*8c35d5eeSXin Li                  '  [readability/check] [2]')
2016*8c35d5eeSXin Li    self.TestLint('CHECK(x >= 42);',
2017*8c35d5eeSXin Li                  'Consider using CHECK_GE instead of CHECK(a >= b)'
2018*8c35d5eeSXin Li                  '  [readability/check] [2]')
2019*8c35d5eeSXin Li    self.TestLint('CHECK(x > 42);',
2020*8c35d5eeSXin Li                  'Consider using CHECK_GT instead of CHECK(a > b)'
2021*8c35d5eeSXin Li                  '  [readability/check] [2]')
2022*8c35d5eeSXin Li    self.TestLint('CHECK(x <= 42);',
2023*8c35d5eeSXin Li                  'Consider using CHECK_LE instead of CHECK(a <= b)'
2024*8c35d5eeSXin Li                  '  [readability/check] [2]')
2025*8c35d5eeSXin Li    self.TestLint('CHECK(x < 42);',
2026*8c35d5eeSXin Li                  'Consider using CHECK_LT instead of CHECK(a < b)'
2027*8c35d5eeSXin Li                  '  [readability/check] [2]')
2028*8c35d5eeSXin Li
2029*8c35d5eeSXin Li    self.TestLint('DCHECK(x == 42);',
2030*8c35d5eeSXin Li                  'Consider using DCHECK_EQ instead of DCHECK(a == b)'
2031*8c35d5eeSXin Li                  '  [readability/check] [2]')
2032*8c35d5eeSXin Li    self.TestLint('DCHECK(x != 42);',
2033*8c35d5eeSXin Li                  'Consider using DCHECK_NE instead of DCHECK(a != b)'
2034*8c35d5eeSXin Li                  '  [readability/check] [2]')
2035*8c35d5eeSXin Li    self.TestLint('DCHECK(x >= 42);',
2036*8c35d5eeSXin Li                  'Consider using DCHECK_GE instead of DCHECK(a >= b)'
2037*8c35d5eeSXin Li                  '  [readability/check] [2]')
2038*8c35d5eeSXin Li    self.TestLint('DCHECK(x > 42);',
2039*8c35d5eeSXin Li                  'Consider using DCHECK_GT instead of DCHECK(a > b)'
2040*8c35d5eeSXin Li                  '  [readability/check] [2]')
2041*8c35d5eeSXin Li    self.TestLint('DCHECK(x <= 42);',
2042*8c35d5eeSXin Li                  'Consider using DCHECK_LE instead of DCHECK(a <= b)'
2043*8c35d5eeSXin Li                  '  [readability/check] [2]')
2044*8c35d5eeSXin Li    self.TestLint('DCHECK(x < 42);',
2045*8c35d5eeSXin Li                  'Consider using DCHECK_LT instead of DCHECK(a < b)'
2046*8c35d5eeSXin Li                  '  [readability/check] [2]')
2047*8c35d5eeSXin Li
2048*8c35d5eeSXin Li    self.TestLint(
2049*8c35d5eeSXin Li        'EXPECT_TRUE("42" == x);',
2050*8c35d5eeSXin Li        'Consider using EXPECT_EQ instead of EXPECT_TRUE(a == b)'
2051*8c35d5eeSXin Li        '  [readability/check] [2]')
2052*8c35d5eeSXin Li    self.TestLint(
2053*8c35d5eeSXin Li        'EXPECT_TRUE("42" != x);',
2054*8c35d5eeSXin Li        'Consider using EXPECT_NE instead of EXPECT_TRUE(a != b)'
2055*8c35d5eeSXin Li        '  [readability/check] [2]')
2056*8c35d5eeSXin Li    self.TestLint(
2057*8c35d5eeSXin Li        'EXPECT_TRUE(+42 >= x);',
2058*8c35d5eeSXin Li        'Consider using EXPECT_GE instead of EXPECT_TRUE(a >= b)'
2059*8c35d5eeSXin Li        '  [readability/check] [2]')
2060*8c35d5eeSXin Li
2061*8c35d5eeSXin Li    self.TestLint(
2062*8c35d5eeSXin Li        'EXPECT_FALSE(x == 42);',
2063*8c35d5eeSXin Li        'Consider using EXPECT_NE instead of EXPECT_FALSE(a == b)'
2064*8c35d5eeSXin Li        '  [readability/check] [2]')
2065*8c35d5eeSXin Li    self.TestLint(
2066*8c35d5eeSXin Li        'EXPECT_FALSE(x != 42);',
2067*8c35d5eeSXin Li        'Consider using EXPECT_EQ instead of EXPECT_FALSE(a != b)'
2068*8c35d5eeSXin Li        '  [readability/check] [2]')
2069*8c35d5eeSXin Li    self.TestLint(
2070*8c35d5eeSXin Li        'EXPECT_FALSE(x >= 42);',
2071*8c35d5eeSXin Li        'Consider using EXPECT_LT instead of EXPECT_FALSE(a >= b)'
2072*8c35d5eeSXin Li        '  [readability/check] [2]')
2073*8c35d5eeSXin Li    self.TestLint(
2074*8c35d5eeSXin Li        'ASSERT_FALSE(x > 42);',
2075*8c35d5eeSXin Li        'Consider using ASSERT_LE instead of ASSERT_FALSE(a > b)'
2076*8c35d5eeSXin Li        '  [readability/check] [2]')
2077*8c35d5eeSXin Li    self.TestLint(
2078*8c35d5eeSXin Li        'ASSERT_FALSE(x <= 42);',
2079*8c35d5eeSXin Li        'Consider using ASSERT_GT instead of ASSERT_FALSE(a <= b)'
2080*8c35d5eeSXin Li        '  [readability/check] [2]')
2081*8c35d5eeSXin Li
2082*8c35d5eeSXin Li    self.TestLint('CHECK(x<42);',
2083*8c35d5eeSXin Li                  ['Missing spaces around <'
2084*8c35d5eeSXin Li                   '  [whitespace/operators] [3]',
2085*8c35d5eeSXin Li                   'Consider using CHECK_LT instead of CHECK(a < b)'
2086*8c35d5eeSXin Li                   '  [readability/check] [2]'])
2087*8c35d5eeSXin Li    self.TestLint('CHECK(x>42);',
2088*8c35d5eeSXin Li                  ['Missing spaces around >'
2089*8c35d5eeSXin Li                   '  [whitespace/operators] [3]',
2090*8c35d5eeSXin Li                   'Consider using CHECK_GT instead of CHECK(a > b)'
2091*8c35d5eeSXin Li                   '  [readability/check] [2]'])
2092*8c35d5eeSXin Li
2093*8c35d5eeSXin Li    self.TestLint('using some::namespace::operator<<;', '')
2094*8c35d5eeSXin Li    self.TestLint('using some::namespace::operator>>;', '')
2095*8c35d5eeSXin Li
2096*8c35d5eeSXin Li    self.TestLint('CHECK(x->y == 42);',
2097*8c35d5eeSXin Li                  'Consider using CHECK_EQ instead of CHECK(a == b)'
2098*8c35d5eeSXin Li                  '  [readability/check] [2]')
2099*8c35d5eeSXin Li
2100*8c35d5eeSXin Li    self.TestLint(
2101*8c35d5eeSXin Li        '  EXPECT_TRUE(42 < x);  // Random comment.',
2102*8c35d5eeSXin Li        'Consider using EXPECT_LT instead of EXPECT_TRUE(a < b)'
2103*8c35d5eeSXin Li        '  [readability/check] [2]')
2104*8c35d5eeSXin Li    self.TestLint(
2105*8c35d5eeSXin Li        'EXPECT_TRUE( 42 < x );',
2106*8c35d5eeSXin Li        ['Extra space after ( in function call'
2107*8c35d5eeSXin Li         '  [whitespace/parens] [4]',
2108*8c35d5eeSXin Li         'Extra space before )  [whitespace/parens] [2]',
2109*8c35d5eeSXin Li         'Consider using EXPECT_LT instead of EXPECT_TRUE(a < b)'
2110*8c35d5eeSXin Li         '  [readability/check] [2]'])
2111*8c35d5eeSXin Li
2112*8c35d5eeSXin Li    self.TestLint('CHECK(4\'2 == x);',
2113*8c35d5eeSXin Li                  'Consider using CHECK_EQ instead of CHECK(a == b)'
2114*8c35d5eeSXin Li                  '  [readability/check] [2]')
2115*8c35d5eeSXin Li
2116*8c35d5eeSXin Li  def testCheckCheckFalsePositives(self):
2117*8c35d5eeSXin Li    self.TestLint('CHECK(some_iterator == obj.end());', '')
2118*8c35d5eeSXin Li    self.TestLint('EXPECT_TRUE(some_iterator == obj.end());', '')
2119*8c35d5eeSXin Li    self.TestLint('EXPECT_FALSE(some_iterator == obj.end());', '')
2120*8c35d5eeSXin Li    self.TestLint('CHECK(some_pointer != NULL);', '')
2121*8c35d5eeSXin Li    self.TestLint('EXPECT_TRUE(some_pointer != NULL);', '')
2122*8c35d5eeSXin Li    self.TestLint('EXPECT_FALSE(some_pointer != NULL);', '')
2123*8c35d5eeSXin Li
2124*8c35d5eeSXin Li    self.TestLint('CHECK(CreateTestFile(dir, (1 << 20)));', '')
2125*8c35d5eeSXin Li    self.TestLint('CHECK(CreateTestFile(dir, (1 >> 20)));', '')
2126*8c35d5eeSXin Li
2127*8c35d5eeSXin Li    self.TestLint('CHECK(x ^ (y < 42));', '')
2128*8c35d5eeSXin Li    self.TestLint('CHECK((x > 42) ^ (x < 54));', '')
2129*8c35d5eeSXin Li    self.TestLint('CHECK(a && b < 42);', '')
2130*8c35d5eeSXin Li    self.TestLint('CHECK(42 < a && a < b);', '')
2131*8c35d5eeSXin Li    self.TestLint('SOFT_CHECK(x > 42);', '')
2132*8c35d5eeSXin Li
2133*8c35d5eeSXin Li    self.TestMultiLineLint(
2134*8c35d5eeSXin Li        """_STLP_DEFINE_BINARY_OP_CHECK(==, _OP_EQUAL);
2135*8c35d5eeSXin Li        _STLP_DEFINE_BINARY_OP_CHECK(!=, _OP_NOT_EQUAL);
2136*8c35d5eeSXin Li        _STLP_DEFINE_BINARY_OP_CHECK(<, _OP_LESS_THAN);
2137*8c35d5eeSXin Li        _STLP_DEFINE_BINARY_OP_CHECK(<=, _OP_LESS_EQUAL);
2138*8c35d5eeSXin Li        _STLP_DEFINE_BINARY_OP_CHECK(>, _OP_GREATER_THAN);
2139*8c35d5eeSXin Li        _STLP_DEFINE_BINARY_OP_CHECK(>=, _OP_GREATER_EQUAL);
2140*8c35d5eeSXin Li        _STLP_DEFINE_BINARY_OP_CHECK(+, _OP_PLUS);
2141*8c35d5eeSXin Li        _STLP_DEFINE_BINARY_OP_CHECK(*, _OP_TIMES);
2142*8c35d5eeSXin Li        _STLP_DEFINE_BINARY_OP_CHECK(/, _OP_DIVIDE);
2143*8c35d5eeSXin Li        _STLP_DEFINE_BINARY_OP_CHECK(-, _OP_SUBTRACT);
2144*8c35d5eeSXin Li        _STLP_DEFINE_BINARY_OP_CHECK(%, _OP_MOD);""",
2145*8c35d5eeSXin Li        '')
2146*8c35d5eeSXin Li
2147*8c35d5eeSXin Li    self.TestLint('CHECK(x < 42) << "Custom error message";', '')
2148*8c35d5eeSXin Li
2149*8c35d5eeSXin Li  # Alternative token to punctuation operator replacements
2150*8c35d5eeSXin Li  def testCheckAltTokens(self):
2151*8c35d5eeSXin Li    self.TestLint('true or true',
2152*8c35d5eeSXin Li                  'Use operator || instead of or'
2153*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2154*8c35d5eeSXin Li    self.TestLint('true and true',
2155*8c35d5eeSXin Li                  'Use operator && instead of and'
2156*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2157*8c35d5eeSXin Li    self.TestLint('if (not true)',
2158*8c35d5eeSXin Li                  'Use operator ! instead of not'
2159*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2160*8c35d5eeSXin Li    self.TestLint('1 bitor 1',
2161*8c35d5eeSXin Li                  'Use operator | instead of bitor'
2162*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2163*8c35d5eeSXin Li    self.TestLint('1 xor 1',
2164*8c35d5eeSXin Li                  'Use operator ^ instead of xor'
2165*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2166*8c35d5eeSXin Li    self.TestLint('1 bitand 1',
2167*8c35d5eeSXin Li                  'Use operator & instead of bitand'
2168*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2169*8c35d5eeSXin Li    self.TestLint('x = compl 1',
2170*8c35d5eeSXin Li                  'Use operator ~ instead of compl'
2171*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2172*8c35d5eeSXin Li    self.TestLint('x and_eq y',
2173*8c35d5eeSXin Li                  'Use operator &= instead of and_eq'
2174*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2175*8c35d5eeSXin Li    self.TestLint('x or_eq y',
2176*8c35d5eeSXin Li                  'Use operator |= instead of or_eq'
2177*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2178*8c35d5eeSXin Li    self.TestLint('x xor_eq y',
2179*8c35d5eeSXin Li                  'Use operator ^= instead of xor_eq'
2180*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2181*8c35d5eeSXin Li    self.TestLint('x not_eq y',
2182*8c35d5eeSXin Li                  'Use operator != instead of not_eq'
2183*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2184*8c35d5eeSXin Li    self.TestLint('line_continuation or',
2185*8c35d5eeSXin Li                  'Use operator || instead of or'
2186*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2187*8c35d5eeSXin Li    self.TestLint('if(true and(parentheses',
2188*8c35d5eeSXin Li                  'Use operator && instead of and'
2189*8c35d5eeSXin Li                  '  [readability/alt_tokens] [2]')
2190*8c35d5eeSXin Li
2191*8c35d5eeSXin Li    self.TestLint('#include "base/false-and-false.h"', '')
2192*8c35d5eeSXin Li    self.TestLint('#error false or false', '')
2193*8c35d5eeSXin Li    self.TestLint('false nor false', '')
2194*8c35d5eeSXin Li    self.TestLint('false nand false', '')
2195*8c35d5eeSXin Li
2196*8c35d5eeSXin Li  # Passing and returning non-const references
2197*8c35d5eeSXin Li  def testNonConstReference(self):
2198*8c35d5eeSXin Li    # Passing a non-const reference as function parameter is forbidden.
2199*8c35d5eeSXin Li    operand_error_message = ('Is this a non-const reference? '
2200*8c35d5eeSXin Li                             'If so, make const or use a pointer: %s'
2201*8c35d5eeSXin Li                             '  [runtime/references] [2]')
2202*8c35d5eeSXin Li    # Warn of use of a non-const reference in operators and functions
2203*8c35d5eeSXin Li    self.TestLint('bool operator>(Foo& s, Foo& f);',
2204*8c35d5eeSXin Li                  [operand_error_message % 'Foo& s',
2205*8c35d5eeSXin Li                   operand_error_message % 'Foo& f'])
2206*8c35d5eeSXin Li    self.TestLint('bool operator+(Foo& s, Foo& f);',
2207*8c35d5eeSXin Li                  [operand_error_message % 'Foo& s',
2208*8c35d5eeSXin Li                   operand_error_message % 'Foo& f'])
2209*8c35d5eeSXin Li    self.TestLint('int len(Foo& s);', operand_error_message % 'Foo& s')
2210*8c35d5eeSXin Li    # Allow use of non-const references in a few specific cases
2211*8c35d5eeSXin Li    self.TestLint('stream& operator>>(stream& s, Foo& f);', '')
2212*8c35d5eeSXin Li    self.TestLint('stream& operator<<(stream& s, Foo& f);', '')
2213*8c35d5eeSXin Li    self.TestLint('void swap(Bar& a, Bar& b);', '')
2214*8c35d5eeSXin Li    self.TestLint('ostream& LogFunc(ostream& s);', '')
2215*8c35d5eeSXin Li    self.TestLint('ostringstream& LogFunc(ostringstream& s);', '')
2216*8c35d5eeSXin Li    self.TestLint('istream& LogFunc(istream& s);', '')
2217*8c35d5eeSXin Li    self.TestLint('istringstream& LogFunc(istringstream& s);', '')
2218*8c35d5eeSXin Li    # Returning a non-const reference from a function is OK.
2219*8c35d5eeSXin Li    self.TestLint('int& g();', '')
2220*8c35d5eeSXin Li    # Passing a const reference to a struct (using the struct keyword) is OK.
2221*8c35d5eeSXin Li    self.TestLint('void foo(const struct tm& tm);', '')
2222*8c35d5eeSXin Li    # Passing a const reference to a typename is OK.
2223*8c35d5eeSXin Li    self.TestLint('void foo(const typename tm& tm);', '')
2224*8c35d5eeSXin Li    # Const reference to a pointer type is OK.
2225*8c35d5eeSXin Li    self.TestLint('void foo(const Bar* const& p) {', '')
2226*8c35d5eeSXin Li    self.TestLint('void foo(Bar const* const& p) {', '')
2227*8c35d5eeSXin Li    self.TestLint('void foo(Bar* const& p) {', '')
2228*8c35d5eeSXin Li    # Const reference to a templated type is OK.
2229*8c35d5eeSXin Li    self.TestLint('void foo(const std::vector<std::string>& v);', '')
2230*8c35d5eeSXin Li    # Non-const reference to a pointer type is not OK.
2231*8c35d5eeSXin Li    self.TestLint('void foo(Bar*& p);',
2232*8c35d5eeSXin Li                  operand_error_message % 'Bar*& p')
2233*8c35d5eeSXin Li    self.TestLint('void foo(const Bar*& p);',
2234*8c35d5eeSXin Li                  operand_error_message % 'const Bar*& p')
2235*8c35d5eeSXin Li    self.TestLint('void foo(Bar const*& p);',
2236*8c35d5eeSXin Li                  operand_error_message % 'Bar const*& p')
2237*8c35d5eeSXin Li    self.TestLint('void foo(struct Bar*& p);',
2238*8c35d5eeSXin Li                  operand_error_message % 'struct Bar*& p')
2239*8c35d5eeSXin Li    self.TestLint('void foo(const struct Bar*& p);',
2240*8c35d5eeSXin Li                  operand_error_message % 'const struct Bar*& p')
2241*8c35d5eeSXin Li    self.TestLint('void foo(struct Bar const*& p);',
2242*8c35d5eeSXin Li                  operand_error_message % 'struct Bar const*& p')
2243*8c35d5eeSXin Li    # Non-const reference to a templated type is not OK.
2244*8c35d5eeSXin Li    self.TestLint('void foo(std::vector<int>& p);',
2245*8c35d5eeSXin Li                  operand_error_message % 'std::vector<int>& p')
2246*8c35d5eeSXin Li    # Returning an address of something is not prohibited.
2247*8c35d5eeSXin Li    self.TestLint('return &something;', '')
2248*8c35d5eeSXin Li    self.TestLint('if (condition) {return &something; }', '')
2249*8c35d5eeSXin Li    self.TestLint('if (condition) return &something;', '')
2250*8c35d5eeSXin Li    self.TestLint('if (condition) address = &something;', '')
2251*8c35d5eeSXin Li    self.TestLint('if (condition) result = lhs&rhs;', '')
2252*8c35d5eeSXin Li    self.TestLint('if (condition) result = lhs & rhs;', '')
2253*8c35d5eeSXin Li    self.TestLint('a = (b+c) * sizeof &f;', '')
2254*8c35d5eeSXin Li    self.TestLint('a = MySize(b) * sizeof &f;', '')
2255*8c35d5eeSXin Li    # We don't get confused by C++11 range-based for loops.
2256*8c35d5eeSXin Li    self.TestLint('for (const string& s : c)', '')
2257*8c35d5eeSXin Li    self.TestLint('for (auto& r : c)', '')
2258*8c35d5eeSXin Li    self.TestLint('for (typename Type& a : b)', '')
2259*8c35d5eeSXin Li    # We don't get confused by some other uses of '&'.
2260*8c35d5eeSXin Li    self.TestLint('T& operator=(const T& t);', '')
2261*8c35d5eeSXin Li    self.TestLint('int g() { return (a & b); }', '')
2262*8c35d5eeSXin Li    self.TestLint('T& r = (T&)*(vp());', '')
2263*8c35d5eeSXin Li    self.TestLint('T& r = v', '')
2264*8c35d5eeSXin Li    self.TestLint('static_assert((kBits & kMask) == 0, "text");', '')
2265*8c35d5eeSXin Li    self.TestLint('COMPILE_ASSERT((kBits & kMask) == 0, text);', '')
2266*8c35d5eeSXin Li    # Spaces before template arguments.  This is poor style, but
2267*8c35d5eeSXin Li    # happens 0.15% of the time.
2268*8c35d5eeSXin Li    self.TestLint('void Func(const vector <int> &const_x, '
2269*8c35d5eeSXin Li                  'vector <int> &nonconst_x) {',
2270*8c35d5eeSXin Li                  operand_error_message % 'vector<int> &nonconst_x')
2271*8c35d5eeSXin Li
2272*8c35d5eeSXin Li    # Derived member functions are spared from override check
2273*8c35d5eeSXin Li    self.TestLint('void Func(X& x);', operand_error_message % 'X& x')
2274*8c35d5eeSXin Li    self.TestLint('void Func(X& x) {}', operand_error_message % 'X& x')
2275*8c35d5eeSXin Li    self.TestLint('void Func(X& x) override;', '')
2276*8c35d5eeSXin Li    self.TestLint('void Func(X& x) override {', '')
2277*8c35d5eeSXin Li    self.TestLint('void Func(X& x) const override;', '')
2278*8c35d5eeSXin Li    self.TestLint('void Func(X& x) const override {', '')
2279*8c35d5eeSXin Li
2280*8c35d5eeSXin Li    # Don't warn on out-of-line method definitions.
2281*8c35d5eeSXin Li    self.TestLint('void NS::Func(X& x) {', '')
2282*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
2283*8c35d5eeSXin Li    cpplint.ProcessFileData(
2284*8c35d5eeSXin Li        'foo.cc', 'cc',
2285*8c35d5eeSXin Li        ['// Copyright 2014 Your Company. All Rights Reserved.',
2286*8c35d5eeSXin Li         'void a::b() {}',
2287*8c35d5eeSXin Li         'void f(int& q) {}',
2288*8c35d5eeSXin Li         ''],
2289*8c35d5eeSXin Li        error_collector)
2290*8c35d5eeSXin Li    self.assertEquals(
2291*8c35d5eeSXin Li        operand_error_message % 'int& q',
2292*8c35d5eeSXin Li        error_collector.Results())
2293*8c35d5eeSXin Li
2294*8c35d5eeSXin Li    # Other potential false positives.  These need full parser
2295*8c35d5eeSXin Li    # state to reproduce as opposed to just TestLint.
2296*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
2297*8c35d5eeSXin Li    cpplint.ProcessFileData(
2298*8c35d5eeSXin Li        'foo.cc', 'cc',
2299*8c35d5eeSXin Li        ['// Copyright 2014 Your Company. All Rights Reserved.',
2300*8c35d5eeSXin Li         'void swap(int &x,',
2301*8c35d5eeSXin Li         '          int &y) {',
2302*8c35d5eeSXin Li         '}',
2303*8c35d5eeSXin Li         'void swap(',
2304*8c35d5eeSXin Li         '    sparsegroup<T, GROUP_SIZE, Alloc> &x,',
2305*8c35d5eeSXin Li         '    sparsegroup<T, GROUP_SIZE, Alloc> &y) {',
2306*8c35d5eeSXin Li         '}',
2307*8c35d5eeSXin Li         'ostream& operator<<(',
2308*8c35d5eeSXin Li         '    ostream& out',
2309*8c35d5eeSXin Li         '    const dense_hash_set<Value, Hash, Equals, Alloc>& seq) {',
2310*8c35d5eeSXin Li         '}',
2311*8c35d5eeSXin Li         'class A {',
2312*8c35d5eeSXin Li         '  void Function(',
2313*8c35d5eeSXin Li         '      string &x) override {',
2314*8c35d5eeSXin Li         '  }',
2315*8c35d5eeSXin Li         '};',
2316*8c35d5eeSXin Li         'void Derived::Function(',
2317*8c35d5eeSXin Li         '    string &x) {',
2318*8c35d5eeSXin Li         '}',
2319*8c35d5eeSXin Li         '#define UNSUPPORTED_MASK(_mask) \\',
2320*8c35d5eeSXin Li         '  if (flags & _mask) { \\',
2321*8c35d5eeSXin Li         '    LOG(FATAL) << "Unsupported flag: " << #_mask; \\',
2322*8c35d5eeSXin Li         '  }',
2323*8c35d5eeSXin Li         'Constructor::Constructor()',
2324*8c35d5eeSXin Li         '    : initializer1_(a1 & b1),',
2325*8c35d5eeSXin Li         '      initializer2_(a2 & b2) {',
2326*8c35d5eeSXin Li         '}',
2327*8c35d5eeSXin Li         'Constructor::Constructor()',
2328*8c35d5eeSXin Li         '    : initializer1_{a3 & b3},',
2329*8c35d5eeSXin Li         '      initializer2_(a4 & b4) {',
2330*8c35d5eeSXin Li         '}',
2331*8c35d5eeSXin Li         'Constructor::Constructor()',
2332*8c35d5eeSXin Li         '    : initializer1_{a5 & b5},',
2333*8c35d5eeSXin Li         '      initializer2_(a6 & b6) {}',
2334*8c35d5eeSXin Li         ''],
2335*8c35d5eeSXin Li        error_collector)
2336*8c35d5eeSXin Li    self.assertEquals('', error_collector.Results())
2337*8c35d5eeSXin Li
2338*8c35d5eeSXin Li    # Multi-line references
2339*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
2340*8c35d5eeSXin Li    cpplint.ProcessFileData(
2341*8c35d5eeSXin Li        'foo.cc', 'cc',
2342*8c35d5eeSXin Li        ['// Copyright 2014 Your Company. All Rights Reserved.',
2343*8c35d5eeSXin Li         'void Func(const Outer::',
2344*8c35d5eeSXin Li         '              Inner& const_x,',
2345*8c35d5eeSXin Li         '          const Outer',
2346*8c35d5eeSXin Li         '              ::Inner& const_y,',
2347*8c35d5eeSXin Li         '          const Outer<',
2348*8c35d5eeSXin Li         '              int>::Inner& const_z,',
2349*8c35d5eeSXin Li         '          Outer::',
2350*8c35d5eeSXin Li         '              Inner& nonconst_x,',
2351*8c35d5eeSXin Li         '          Outer',
2352*8c35d5eeSXin Li         '              ::Inner& nonconst_y,',
2353*8c35d5eeSXin Li         '          Outer<',
2354*8c35d5eeSXin Li         '              int>::Inner& nonconst_z) {',
2355*8c35d5eeSXin Li         '}',
2356*8c35d5eeSXin Li         ''],
2357*8c35d5eeSXin Li        error_collector)
2358*8c35d5eeSXin Li    self.assertEquals(
2359*8c35d5eeSXin Li        [operand_error_message % 'Outer::Inner& nonconst_x',
2360*8c35d5eeSXin Li         operand_error_message % 'Outer::Inner& nonconst_y',
2361*8c35d5eeSXin Li         operand_error_message % 'Outer<int>::Inner& nonconst_z'],
2362*8c35d5eeSXin Li        error_collector.Results())
2363*8c35d5eeSXin Li
2364*8c35d5eeSXin Li    # A peculiar false positive due to bad template argument parsing
2365*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
2366*8c35d5eeSXin Li    cpplint.ProcessFileData(
2367*8c35d5eeSXin Li        'foo.cc', 'cc',
2368*8c35d5eeSXin Li        ['// Copyright 2014 Your Company. All Rights Reserved.',
2369*8c35d5eeSXin Li         'inline RCULocked<X>::ReadPtr::ReadPtr(const RCULocked* rcu) {',
2370*8c35d5eeSXin Li         '  DCHECK(!(data & kFlagMask)) << "Error";',
2371*8c35d5eeSXin Li         '}',
2372*8c35d5eeSXin Li         '',
2373*8c35d5eeSXin Li         'RCULocked<X>::WritePtr::WritePtr(RCULocked* rcu)',
2374*8c35d5eeSXin Li         '    : lock_(&rcu_->mutex_) {',
2375*8c35d5eeSXin Li         '}',
2376*8c35d5eeSXin Li         ''],
2377*8c35d5eeSXin Li        error_collector.Results())
2378*8c35d5eeSXin Li    self.assertEquals('', error_collector.Results())
2379*8c35d5eeSXin Li
2380*8c35d5eeSXin Li  def testBraceAtBeginOfLine(self):
2381*8c35d5eeSXin Li    self.TestLint('{',
2382*8c35d5eeSXin Li                  '{ should almost always be at the end of the previous line'
2383*8c35d5eeSXin Li                  '  [whitespace/braces] [4]')
2384*8c35d5eeSXin Li
2385*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
2386*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
2387*8c35d5eeSXin Li                            ['int function()',
2388*8c35d5eeSXin Li                             '{',  # warning here
2389*8c35d5eeSXin Li                             '  MutexLock l(&mu);',
2390*8c35d5eeSXin Li                             '}',
2391*8c35d5eeSXin Li                             'int variable;'
2392*8c35d5eeSXin Li                             '{',  # no warning
2393*8c35d5eeSXin Li                             '  MutexLock l(&mu);',
2394*8c35d5eeSXin Li                             '}',
2395*8c35d5eeSXin Li                             'MyType m = {',
2396*8c35d5eeSXin Li                             '  {value1, value2},',
2397*8c35d5eeSXin Li                             '  {',  # no warning
2398*8c35d5eeSXin Li                             '    loooong_value1, looooong_value2',
2399*8c35d5eeSXin Li                             '  }',
2400*8c35d5eeSXin Li                             '};',
2401*8c35d5eeSXin Li                             '#if PREPROCESSOR',
2402*8c35d5eeSXin Li                             '{',  # no warning
2403*8c35d5eeSXin Li                             '  MutexLock l(&mu);',
2404*8c35d5eeSXin Li                             '}',
2405*8c35d5eeSXin Li                             '#endif'],
2406*8c35d5eeSXin Li                            error_collector)
2407*8c35d5eeSXin Li    self.assertEquals(1, error_collector.Results().count(
2408*8c35d5eeSXin Li        '{ should almost always be at the end of the previous line'
2409*8c35d5eeSXin Li        '  [whitespace/braces] [4]'))
2410*8c35d5eeSXin Li
2411*8c35d5eeSXin Li    self.TestMultiLineLint(
2412*8c35d5eeSXin Li        """
2413*8c35d5eeSXin Li        foo(
2414*8c35d5eeSXin Li          {
2415*8c35d5eeSXin Li            loooooooooooooooong_value,
2416*8c35d5eeSXin Li          });""",
2417*8c35d5eeSXin Li        '')
2418*8c35d5eeSXin Li
2419*8c35d5eeSXin Li  def testMismatchingSpacesInParens(self):
2420*8c35d5eeSXin Li    self.TestLint('if (foo ) {', 'Mismatching spaces inside () in if'
2421*8c35d5eeSXin Li                  '  [whitespace/parens] [5]')
2422*8c35d5eeSXin Li    self.TestLint('switch ( foo) {', 'Mismatching spaces inside () in switch'
2423*8c35d5eeSXin Li                  '  [whitespace/parens] [5]')
2424*8c35d5eeSXin Li    self.TestLint('for (foo; ba; bar ) {', 'Mismatching spaces inside () in for'
2425*8c35d5eeSXin Li                  '  [whitespace/parens] [5]')
2426*8c35d5eeSXin Li    self.TestLint('for (; foo; bar) {', '')
2427*8c35d5eeSXin Li    self.TestLint('for ( ; foo; bar) {', '')
2428*8c35d5eeSXin Li    self.TestLint('for ( ; foo; bar ) {', '')
2429*8c35d5eeSXin Li    self.TestLint('for (foo; bar; ) {', '')
2430*8c35d5eeSXin Li    self.TestLint('while (  foo  ) {', 'Should have zero or one spaces inside'
2431*8c35d5eeSXin Li                  ' ( and ) in while  [whitespace/parens] [5]')
2432*8c35d5eeSXin Li
2433*8c35d5eeSXin Li  def testSpacingForFncall(self):
2434*8c35d5eeSXin Li    self.TestLint('if (foo) {', '')
2435*8c35d5eeSXin Li    self.TestLint('for (foo; bar; baz) {', '')
2436*8c35d5eeSXin Li    self.TestLint('for (;;) {', '')
2437*8c35d5eeSXin Li    # Space should be allowed in placement new operators.
2438*8c35d5eeSXin Li    self.TestLint('Something* p = new (place) Something();', '')
2439*8c35d5eeSXin Li    # Test that there is no warning when increment statement is empty.
2440*8c35d5eeSXin Li    self.TestLint('for (foo; baz;) {', '')
2441*8c35d5eeSXin Li    self.TestLint('for (foo;bar;baz) {', 'Missing space after ;'
2442*8c35d5eeSXin Li                  '  [whitespace/semicolon] [3]')
2443*8c35d5eeSXin Li    # we don't warn about this semicolon, at least for now
2444*8c35d5eeSXin Li    self.TestLint('if (condition) {return &something; }',
2445*8c35d5eeSXin Li                  '')
2446*8c35d5eeSXin Li    # seen in some macros
2447*8c35d5eeSXin Li    self.TestLint('DoSth();\\', '')
2448*8c35d5eeSXin Li    # Test that there is no warning about semicolon here.
2449*8c35d5eeSXin Li    self.TestLint('abc;// this is abc',
2450*8c35d5eeSXin Li                  'At least two spaces is best between code'
2451*8c35d5eeSXin Li                  ' and comments  [whitespace/comments] [2]')
2452*8c35d5eeSXin Li    self.TestLint('while (foo) {', '')
2453*8c35d5eeSXin Li    self.TestLint('switch (foo) {', '')
2454*8c35d5eeSXin Li    self.TestLint('foo( bar)', 'Extra space after ( in function call'
2455*8c35d5eeSXin Li                  '  [whitespace/parens] [4]')
2456*8c35d5eeSXin Li    self.TestLint('foo(  // comment', '')
2457*8c35d5eeSXin Li    self.TestLint('foo( // comment',
2458*8c35d5eeSXin Li                  'At least two spaces is best between code'
2459*8c35d5eeSXin Li                  ' and comments  [whitespace/comments] [2]')
2460*8c35d5eeSXin Li    self.TestLint('foobar( \\', '')
2461*8c35d5eeSXin Li    self.TestLint('foobar(     \\', '')
2462*8c35d5eeSXin Li    self.TestLint('( a + b)', 'Extra space after ('
2463*8c35d5eeSXin Li                  '  [whitespace/parens] [2]')
2464*8c35d5eeSXin Li    self.TestLint('((a+b))', '')
2465*8c35d5eeSXin Li    self.TestLint('foo (foo)', 'Extra space before ( in function call'
2466*8c35d5eeSXin Li                  '  [whitespace/parens] [4]')
2467*8c35d5eeSXin Li    # asm volatile () may have a space, as it isn't a function call.
2468*8c35d5eeSXin Li    self.TestLint('asm volatile ("")', '')
2469*8c35d5eeSXin Li    self.TestLint('__asm__ __volatile__ ("")', '')
2470*8c35d5eeSXin Li    self.TestLint('} catch (const Foo& ex) {', '')
2471*8c35d5eeSXin Li    self.TestLint('case (42):', '')
2472*8c35d5eeSXin Li    self.TestLint('typedef foo (*foo)(foo)', '')
2473*8c35d5eeSXin Li    self.TestLint('typedef foo (*foo12bar_)(foo)', '')
2474*8c35d5eeSXin Li    self.TestLint('typedef foo (Foo::*bar)(foo)', '')
2475*8c35d5eeSXin Li    self.TestLint('using foo = type (Foo::*bar)(foo)', '')
2476*8c35d5eeSXin Li    self.TestLint('using foo = type (Foo::*bar)(', '')
2477*8c35d5eeSXin Li    self.TestLint('using foo = type (Foo::*)(', '')
2478*8c35d5eeSXin Li    self.TestLint('foo (Foo::*bar)(', '')
2479*8c35d5eeSXin Li    self.TestLint('foo (x::y::*z)(', '')
2480*8c35d5eeSXin Li    self.TestLint('foo (Foo::bar)(',
2481*8c35d5eeSXin Li                  'Extra space before ( in function call'
2482*8c35d5eeSXin Li                  '  [whitespace/parens] [4]')
2483*8c35d5eeSXin Li    self.TestLint('foo (*bar)(', '')
2484*8c35d5eeSXin Li    self.TestLint('typedef foo (Foo::*bar)(', '')
2485*8c35d5eeSXin Li    self.TestLint('(foo)(bar)', '')
2486*8c35d5eeSXin Li    self.TestLint('Foo (*foo)(bar)', '')
2487*8c35d5eeSXin Li    self.TestLint('Foo (*foo)(Bar bar,', '')
2488*8c35d5eeSXin Li    self.TestLint('char (*p)[sizeof(foo)] = &foo', '')
2489*8c35d5eeSXin Li    self.TestLint('char (&ref)[sizeof(foo)] = &foo', '')
2490*8c35d5eeSXin Li    self.TestLint('const char32 (*table[])[6];', '')
2491*8c35d5eeSXin Li    # The sizeof operator is often written as if it were a function call, with
2492*8c35d5eeSXin Li    # an opening parenthesis directly following the operator name, but it can
2493*8c35d5eeSXin Li    # also be written like any other operator, with a space following the
2494*8c35d5eeSXin Li    # operator name, and the argument optionally in parentheses.
2495*8c35d5eeSXin Li    self.TestLint('sizeof(foo)', '')
2496*8c35d5eeSXin Li    self.TestLint('sizeof foo', '')
2497*8c35d5eeSXin Li    self.TestLint('sizeof (foo)', '')
2498*8c35d5eeSXin Li
2499*8c35d5eeSXin Li  def testSpacingBeforeBraces(self):
2500*8c35d5eeSXin Li    self.TestLint('if (foo){', 'Missing space before {'
2501*8c35d5eeSXin Li                  '  [whitespace/braces] [5]')
2502*8c35d5eeSXin Li    self.TestLint('for{', 'Missing space before {'
2503*8c35d5eeSXin Li                  '  [whitespace/braces] [5]')
2504*8c35d5eeSXin Li    self.TestLint('for {', '')
2505*8c35d5eeSXin Li    self.TestLint('EXPECT_DEBUG_DEATH({', '')
2506*8c35d5eeSXin Li    self.TestLint('std::is_convertible<A, B>{}', '')
2507*8c35d5eeSXin Li    self.TestLint('blah{32}', 'Missing space before {'
2508*8c35d5eeSXin Li                  '  [whitespace/braces] [5]')
2509*8c35d5eeSXin Li    self.TestLint('int8_t{3}', '')
2510*8c35d5eeSXin Li    self.TestLint('int16_t{3}', '')
2511*8c35d5eeSXin Li    self.TestLint('int32_t{3}', '')
2512*8c35d5eeSXin Li    self.TestLint('uint64_t{12345}', '')
2513*8c35d5eeSXin Li    self.TestLint('constexpr int64_t kBatchGapMicros ='
2514*8c35d5eeSXin Li                  ' int64_t{7} * 24 * 3600 * 1000000;  // 1 wk.', '')
2515*8c35d5eeSXin Li    self.TestLint('MoveOnly(int i1, int i2) : ip1{new int{i1}}, '
2516*8c35d5eeSXin Li                  'ip2{new int{i2}} {}',
2517*8c35d5eeSXin Li                  '')
2518*8c35d5eeSXin Li
2519*8c35d5eeSXin Li  def testSemiColonAfterBraces(self):
2520*8c35d5eeSXin Li    self.TestLint('if (cond) { func(); };',
2521*8c35d5eeSXin Li                  'You don\'t need a ; after a }  [readability/braces] [4]')
2522*8c35d5eeSXin Li    self.TestLint('void Func() {};',
2523*8c35d5eeSXin Li                  'You don\'t need a ; after a }  [readability/braces] [4]')
2524*8c35d5eeSXin Li    self.TestLint('void Func() const {};',
2525*8c35d5eeSXin Li                  'You don\'t need a ; after a }  [readability/braces] [4]')
2526*8c35d5eeSXin Li    self.TestLint('class X {};', '')
2527*8c35d5eeSXin Li    for keyword in ['struct', 'union']:
2528*8c35d5eeSXin Li      for align in ['', ' alignas(16)']:
2529*8c35d5eeSXin Li        for typename in ['', ' X']:
2530*8c35d5eeSXin Li          for identifier in ['', ' x']:
2531*8c35d5eeSXin Li            self.TestLint(keyword + align + typename + ' {}' + identifier + ';',
2532*8c35d5eeSXin Li                          '')
2533*8c35d5eeSXin Li
2534*8c35d5eeSXin Li    self.TestLint('class X : public Y {};', '')
2535*8c35d5eeSXin Li    self.TestLint('class X : public MACRO() {};', '')
2536*8c35d5eeSXin Li    self.TestLint('class X : public decltype(expr) {};', '')
2537*8c35d5eeSXin Li    self.TestLint('DEFINE_FACADE(PCQueue::Watcher, PCQueue) {};', '')
2538*8c35d5eeSXin Li    self.TestLint('VCLASS(XfaTest, XfaContextTest) {};', '')
2539*8c35d5eeSXin Li    self.TestLint('class STUBBY_CLASS(H, E) {};', '')
2540*8c35d5eeSXin Li    self.TestLint('class STUBBY2_CLASS(H, E) {};', '')
2541*8c35d5eeSXin Li    self.TestLint('TEST(TestCase, TestName) {};',
2542*8c35d5eeSXin Li                  'You don\'t need a ; after a }  [readability/braces] [4]')
2543*8c35d5eeSXin Li    self.TestLint('TEST_F(TestCase, TestName) {};',
2544*8c35d5eeSXin Li                  'You don\'t need a ; after a }  [readability/braces] [4]')
2545*8c35d5eeSXin Li
2546*8c35d5eeSXin Li    self.TestLint('file_tocs_[i] = (FileToc) {a, b, c};', '')
2547*8c35d5eeSXin Li    self.TestMultiLineLint('class X : public Y,\npublic Z {};', '')
2548*8c35d5eeSXin Li
2549*8c35d5eeSXin Li  def testLambda(self):
2550*8c35d5eeSXin Li    self.TestLint('auto x = []() {};', '')
2551*8c35d5eeSXin Li    self.TestLint('return []() {};', '')
2552*8c35d5eeSXin Li    self.TestMultiLineLint('auto x = []() {\n};\n', '')
2553*8c35d5eeSXin Li    self.TestLint('int operator[](int x) {};',
2554*8c35d5eeSXin Li                  'You don\'t need a ; after a }  [readability/braces] [4]')
2555*8c35d5eeSXin Li
2556*8c35d5eeSXin Li    self.TestMultiLineLint('auto x = [&a,\nb]() {};', '')
2557*8c35d5eeSXin Li    self.TestMultiLineLint('auto x = [&a,\nb]\n() {};', '')
2558*8c35d5eeSXin Li    self.TestMultiLineLint('auto x = [&a,\n'
2559*8c35d5eeSXin Li                           '          b](\n'
2560*8c35d5eeSXin Li                           '    int a,\n'
2561*8c35d5eeSXin Li                           '    int b) {\n'
2562*8c35d5eeSXin Li                           '  return a +\n'
2563*8c35d5eeSXin Li                           '         b;\n'
2564*8c35d5eeSXin Li                           '};\n',
2565*8c35d5eeSXin Li                           '')
2566*8c35d5eeSXin Li
2567*8c35d5eeSXin Li    # Avoid false positives with operator[]
2568*8c35d5eeSXin Li    self.TestLint('table_to_children[&*table].push_back(dependent);', '')
2569*8c35d5eeSXin Li
2570*8c35d5eeSXin Li  def testBraceInitializerList(self):
2571*8c35d5eeSXin Li    self.TestLint('MyStruct p = {1, 2};', '')
2572*8c35d5eeSXin Li    self.TestLint('MyStruct p{1, 2};', '')
2573*8c35d5eeSXin Li    self.TestLint('vector<int> p = {1, 2};', '')
2574*8c35d5eeSXin Li    self.TestLint('vector<int> p{1, 2};', '')
2575*8c35d5eeSXin Li    self.TestLint('x = vector<int>{1, 2};', '')
2576*8c35d5eeSXin Li    self.TestLint('x = (struct in_addr){ 0 };', '')
2577*8c35d5eeSXin Li    self.TestLint('Func(vector<int>{1, 2})', '')
2578*8c35d5eeSXin Li    self.TestLint('Func((struct in_addr){ 0 })', '')
2579*8c35d5eeSXin Li    self.TestLint('Func(vector<int>{1, 2}, 3)', '')
2580*8c35d5eeSXin Li    self.TestLint('Func((struct in_addr){ 0 }, 3)', '')
2581*8c35d5eeSXin Li    self.TestLint('LOG(INFO) << char{7};', '')
2582*8c35d5eeSXin Li    self.TestLint('LOG(INFO) << char{7} << "!";', '')
2583*8c35d5eeSXin Li    self.TestLint('int p[2] = {1, 2};', '')
2584*8c35d5eeSXin Li    self.TestLint('return {1, 2};', '')
2585*8c35d5eeSXin Li    self.TestLint('std::unique_ptr<Foo> foo{new Foo{}};', '')
2586*8c35d5eeSXin Li    self.TestLint('auto foo = std::unique_ptr<Foo>{new Foo{}};', '')
2587*8c35d5eeSXin Li    self.TestLint('static_assert(Max7String{}.IsValid(), "");', '')
2588*8c35d5eeSXin Li    self.TestLint('map_of_pairs[{1, 2}] = 3;', '')
2589*8c35d5eeSXin Li    self.TestLint('ItemView{has_offer() ? new Offer{offer()} : nullptr', '')
2590*8c35d5eeSXin Li    self.TestLint('template <class T, EnableIf<::std::is_const<T>{}> = 0>', '')
2591*8c35d5eeSXin Li
2592*8c35d5eeSXin Li    self.TestMultiLineLint('std::unique_ptr<Foo> foo{\n'
2593*8c35d5eeSXin Li                           '  new Foo{}\n'
2594*8c35d5eeSXin Li                           '};\n', '')
2595*8c35d5eeSXin Li    self.TestMultiLineLint('std::unique_ptr<Foo> foo{\n'
2596*8c35d5eeSXin Li                           '  new Foo{\n'
2597*8c35d5eeSXin Li                           '    new Bar{}\n'
2598*8c35d5eeSXin Li                           '  }\n'
2599*8c35d5eeSXin Li                           '};\n', '')
2600*8c35d5eeSXin Li    self.TestMultiLineLint('if (true) {\n'
2601*8c35d5eeSXin Li                           '  if (false){ func(); }\n'
2602*8c35d5eeSXin Li                           '}\n',
2603*8c35d5eeSXin Li                           'Missing space before {  [whitespace/braces] [5]')
2604*8c35d5eeSXin Li    self.TestMultiLineLint('MyClass::MyClass()\n'
2605*8c35d5eeSXin Li                           '    : initializer_{\n'
2606*8c35d5eeSXin Li                           '          Func()} {\n'
2607*8c35d5eeSXin Li                           '}\n', '')
2608*8c35d5eeSXin Li    self.TestLint('const pair<string, string> kCL' +
2609*8c35d5eeSXin Li                  ('o' * 41) + 'gStr[] = {\n',
2610*8c35d5eeSXin Li                  'Lines should be <= 80 characters long'
2611*8c35d5eeSXin Li                  '  [whitespace/line_length] [2]')
2612*8c35d5eeSXin Li    self.TestMultiLineLint('const pair<string, string> kCL' +
2613*8c35d5eeSXin Li                           ('o' * 40) + 'ngStr[] =\n'
2614*8c35d5eeSXin Li                           '    {\n'
2615*8c35d5eeSXin Li                           '        {"gooooo", "oooogle"},\n'
2616*8c35d5eeSXin Li                           '};\n', '')
2617*8c35d5eeSXin Li    self.TestMultiLineLint('const pair<string, string> kCL' +
2618*8c35d5eeSXin Li                           ('o' * 39) + 'ngStr[] =\n'
2619*8c35d5eeSXin Li                           '    {\n'
2620*8c35d5eeSXin Li                           '        {"gooooo", "oooogle"},\n'
2621*8c35d5eeSXin Li                           '};\n', '{ should almost always be at the end of '
2622*8c35d5eeSXin Li                           'the previous line  [whitespace/braces] [4]')
2623*8c35d5eeSXin Li
2624*8c35d5eeSXin Li  def testSpacingAroundElse(self):
2625*8c35d5eeSXin Li    self.TestLint('}else {', 'Missing space before else'
2626*8c35d5eeSXin Li                  '  [whitespace/braces] [5]')
2627*8c35d5eeSXin Li    self.TestLint('} else{', 'Missing space before {'
2628*8c35d5eeSXin Li                  '  [whitespace/braces] [5]')
2629*8c35d5eeSXin Li    self.TestLint('} else {', '')
2630*8c35d5eeSXin Li    self.TestLint('} else if (foo) {', '')
2631*8c35d5eeSXin Li
2632*8c35d5eeSXin Li  def testSpacingWithInitializerLists(self):
2633*8c35d5eeSXin Li    self.TestLint('int v[1][3] = {{1, 2, 3}};', '')
2634*8c35d5eeSXin Li    self.TestLint('int v[1][1] = {{0}};', '')
2635*8c35d5eeSXin Li
2636*8c35d5eeSXin Li  def testSpacingForBinaryOps(self):
2637*8c35d5eeSXin Li    self.TestLint('if (foo||bar) {', 'Missing spaces around ||'
2638*8c35d5eeSXin Li                  '  [whitespace/operators] [3]')
2639*8c35d5eeSXin Li    self.TestLint('if (foo<=bar) {', 'Missing spaces around <='
2640*8c35d5eeSXin Li                  '  [whitespace/operators] [3]')
2641*8c35d5eeSXin Li    self.TestLint('if (foo<bar) {', 'Missing spaces around <'
2642*8c35d5eeSXin Li                  '  [whitespace/operators] [3]')
2643*8c35d5eeSXin Li    self.TestLint('if (foo>bar) {', 'Missing spaces around >'
2644*8c35d5eeSXin Li                  '  [whitespace/operators] [3]')
2645*8c35d5eeSXin Li    self.TestLint('if (foo<bar->baz) {', 'Missing spaces around <'
2646*8c35d5eeSXin Li                  '  [whitespace/operators] [3]')
2647*8c35d5eeSXin Li    self.TestLint('if (foo<bar->bar) {', 'Missing spaces around <'
2648*8c35d5eeSXin Li                  '  [whitespace/operators] [3]')
2649*8c35d5eeSXin Li    self.TestLint('template<typename T = double>', '')
2650*8c35d5eeSXin Li    self.TestLint('std::unique_ptr<No<Spaces>>', '')
2651*8c35d5eeSXin Li    self.TestLint('typedef hash_map<Foo, Bar>', '')
2652*8c35d5eeSXin Li    self.TestLint('10<<20', '')
2653*8c35d5eeSXin Li    self.TestLint('10<<a',
2654*8c35d5eeSXin Li                  'Missing spaces around <<  [whitespace/operators] [3]')
2655*8c35d5eeSXin Li    self.TestLint('a<<20',
2656*8c35d5eeSXin Li                  'Missing spaces around <<  [whitespace/operators] [3]')
2657*8c35d5eeSXin Li    self.TestLint('a<<b',
2658*8c35d5eeSXin Li                  'Missing spaces around <<  [whitespace/operators] [3]')
2659*8c35d5eeSXin Li    self.TestLint('10LL<<20', '')
2660*8c35d5eeSXin Li    self.TestLint('10ULL<<20', '')
2661*8c35d5eeSXin Li    self.TestLint('a>>b',
2662*8c35d5eeSXin Li                  'Missing spaces around >>  [whitespace/operators] [3]')
2663*8c35d5eeSXin Li    self.TestLint('10>>b',
2664*8c35d5eeSXin Li                  'Missing spaces around >>  [whitespace/operators] [3]')
2665*8c35d5eeSXin Li    self.TestLint('LOG(ERROR)<<*foo',
2666*8c35d5eeSXin Li                  'Missing spaces around <<  [whitespace/operators] [3]')
2667*8c35d5eeSXin Li    self.TestLint('LOG(ERROR)<<&foo',
2668*8c35d5eeSXin Li                  'Missing spaces around <<  [whitespace/operators] [3]')
2669*8c35d5eeSXin Li    self.TestLint('StringCoder<vector<string>>::ToString()', '')
2670*8c35d5eeSXin Li    self.TestLint('map<pair<int, int>, map<int, int>>::iterator', '')
2671*8c35d5eeSXin Li    self.TestLint('func<int, pair<int, pair<int, int>>>()', '')
2672*8c35d5eeSXin Li    self.TestLint('MACRO1(list<list<int>>)', '')
2673*8c35d5eeSXin Li    self.TestLint('MACRO2(list<list<int>>, 42)', '')
2674*8c35d5eeSXin Li    self.TestLint('void DoFoo(const set<vector<string>>& arg1);', '')
2675*8c35d5eeSXin Li    self.TestLint('void SetFoo(set<vector<string>>* arg1);', '')
2676*8c35d5eeSXin Li    self.TestLint('foo = new set<vector<string>>;', '')
2677*8c35d5eeSXin Li    self.TestLint('reinterpret_cast<set<vector<string>>*>(a);', '')
2678*8c35d5eeSXin Li    self.TestLint('MACRO(<<)', '')
2679*8c35d5eeSXin Li    self.TestLint('MACRO(<<, arg)', '')
2680*8c35d5eeSXin Li    self.TestLint('MACRO(<<=)', '')
2681*8c35d5eeSXin Li    self.TestLint('MACRO(<<=, arg)', '')
2682*8c35d5eeSXin Li
2683*8c35d5eeSXin Li    self.TestLint('using Vector3<T>::operator==;', '')
2684*8c35d5eeSXin Li    self.TestLint('using Vector3<T>::operator!=;', '')
2685*8c35d5eeSXin Li
2686*8c35d5eeSXin Li  def testSpacingBeforeLastSemicolon(self):
2687*8c35d5eeSXin Li    self.TestLint('call_function() ;',
2688*8c35d5eeSXin Li                  'Extra space before last semicolon. If this should be an '
2689*8c35d5eeSXin Li                  'empty statement, use {} instead.'
2690*8c35d5eeSXin Li                  '  [whitespace/semicolon] [5]')
2691*8c35d5eeSXin Li    self.TestLint('while (true) ;',
2692*8c35d5eeSXin Li                  'Extra space before last semicolon. If this should be an '
2693*8c35d5eeSXin Li                  'empty statement, use {} instead.'
2694*8c35d5eeSXin Li                  '  [whitespace/semicolon] [5]')
2695*8c35d5eeSXin Li    self.TestLint('default:;',
2696*8c35d5eeSXin Li                  'Semicolon defining empty statement. Use {} instead.'
2697*8c35d5eeSXin Li                  '  [whitespace/semicolon] [5]')
2698*8c35d5eeSXin Li    self.TestLint('      ;',
2699*8c35d5eeSXin Li                  'Line contains only semicolon. If this should be an empty '
2700*8c35d5eeSXin Li                  'statement, use {} instead.'
2701*8c35d5eeSXin Li                  '  [whitespace/semicolon] [5]')
2702*8c35d5eeSXin Li    self.TestLint('for (int i = 0; ;', '')
2703*8c35d5eeSXin Li
2704*8c35d5eeSXin Li  def testEmptyBlockBody(self):
2705*8c35d5eeSXin Li    self.TestLint('while (true);',
2706*8c35d5eeSXin Li                  'Empty loop bodies should use {} or continue'
2707*8c35d5eeSXin Li                  '  [whitespace/empty_loop_body] [5]')
2708*8c35d5eeSXin Li    self.TestLint('if (true);',
2709*8c35d5eeSXin Li                  'Empty conditional bodies should use {}'
2710*8c35d5eeSXin Li                  '  [whitespace/empty_conditional_body] [5]')
2711*8c35d5eeSXin Li    self.TestLint('while (true)', '')
2712*8c35d5eeSXin Li    self.TestLint('while (true) continue;', '')
2713*8c35d5eeSXin Li    self.TestLint('for (;;);',
2714*8c35d5eeSXin Li                  'Empty loop bodies should use {} or continue'
2715*8c35d5eeSXin Li                  '  [whitespace/empty_loop_body] [5]')
2716*8c35d5eeSXin Li    self.TestLint('for (;;)', '')
2717*8c35d5eeSXin Li    self.TestLint('for (;;) continue;', '')
2718*8c35d5eeSXin Li    self.TestLint('for (;;) func();', '')
2719*8c35d5eeSXin Li    self.TestLint('if (test) {}',
2720*8c35d5eeSXin Li                  'If statement had no body and no else clause'
2721*8c35d5eeSXin Li                  '  [whitespace/empty_if_body] [4]')
2722*8c35d5eeSXin Li    self.TestLint('if (test) func();', '')
2723*8c35d5eeSXin Li    self.TestLint('if (test) {} else {}', '')
2724*8c35d5eeSXin Li    self.TestMultiLineLint("""while (true &&
2725*8c35d5eeSXin Li                                     false);""",
2726*8c35d5eeSXin Li                           'Empty loop bodies should use {} or continue'
2727*8c35d5eeSXin Li                           '  [whitespace/empty_loop_body] [5]')
2728*8c35d5eeSXin Li    self.TestMultiLineLint("""do {
2729*8c35d5eeSXin Li                           } while (false);""",
2730*8c35d5eeSXin Li                           '')
2731*8c35d5eeSXin Li    self.TestMultiLineLint("""#define MACRO \\
2732*8c35d5eeSXin Li                           do { \\
2733*8c35d5eeSXin Li                           } while (false);""",
2734*8c35d5eeSXin Li                           '')
2735*8c35d5eeSXin Li    self.TestMultiLineLint("""do {
2736*8c35d5eeSXin Li                           } while (false);  // next line gets a warning
2737*8c35d5eeSXin Li                           while (false);""",
2738*8c35d5eeSXin Li                           'Empty loop bodies should use {} or continue'
2739*8c35d5eeSXin Li                           '  [whitespace/empty_loop_body] [5]')
2740*8c35d5eeSXin Li    self.TestMultiLineLint("""if (test) {
2741*8c35d5eeSXin Li                           }""",
2742*8c35d5eeSXin Li                           'If statement had no body and no else clause'
2743*8c35d5eeSXin Li                           '  [whitespace/empty_if_body] [4]')
2744*8c35d5eeSXin Li    self.TestMultiLineLint("""if (test,
2745*8c35d5eeSXin Li                               func({})) {
2746*8c35d5eeSXin Li                           }""",
2747*8c35d5eeSXin Li                           'If statement had no body and no else clause'
2748*8c35d5eeSXin Li                           '  [whitespace/empty_if_body] [4]')
2749*8c35d5eeSXin Li    self.TestMultiLineLint("""if (test)
2750*8c35d5eeSXin Li                             func();""", '')
2751*8c35d5eeSXin Li    self.TestLint('if (test) { hello; }', '')
2752*8c35d5eeSXin Li    self.TestLint('if (test({})) { hello; }', '')
2753*8c35d5eeSXin Li    self.TestMultiLineLint("""if (test) {
2754*8c35d5eeSXin Li                             func();
2755*8c35d5eeSXin Li                           }""", '')
2756*8c35d5eeSXin Li    self.TestMultiLineLint("""if (test) {
2757*8c35d5eeSXin Li                             // multiline
2758*8c35d5eeSXin Li                             // comment
2759*8c35d5eeSXin Li                           }""", '')
2760*8c35d5eeSXin Li    self.TestMultiLineLint("""if (test) {  // comment
2761*8c35d5eeSXin Li                           }""", '')
2762*8c35d5eeSXin Li    self.TestMultiLineLint("""if (test) {
2763*8c35d5eeSXin Li                           } else {
2764*8c35d5eeSXin Li                           }""", '')
2765*8c35d5eeSXin Li    self.TestMultiLineLint("""if (func(p1,
2766*8c35d5eeSXin Li                               p2,
2767*8c35d5eeSXin Li                               p3)) {
2768*8c35d5eeSXin Li                             func();
2769*8c35d5eeSXin Li                           }""", '')
2770*8c35d5eeSXin Li    self.TestMultiLineLint("""if (func({}, p1)) {
2771*8c35d5eeSXin Li                             func();
2772*8c35d5eeSXin Li                           }""", '')
2773*8c35d5eeSXin Li
2774*8c35d5eeSXin Li  def testSpacingForRangeBasedFor(self):
2775*8c35d5eeSXin Li    # Basic correctly formatted case:
2776*8c35d5eeSXin Li    self.TestLint('for (int i : numbers) {', '')
2777*8c35d5eeSXin Li
2778*8c35d5eeSXin Li    # Missing space before colon:
2779*8c35d5eeSXin Li    self.TestLint('for (int i: numbers) {',
2780*8c35d5eeSXin Li                  'Missing space around colon in range-based for loop'
2781*8c35d5eeSXin Li                  '  [whitespace/forcolon] [2]')
2782*8c35d5eeSXin Li    # Missing space after colon:
2783*8c35d5eeSXin Li    self.TestLint('for (int i :numbers) {',
2784*8c35d5eeSXin Li                  'Missing space around colon in range-based for loop'
2785*8c35d5eeSXin Li                  '  [whitespace/forcolon] [2]')
2786*8c35d5eeSXin Li    # Missing spaces both before and after the colon.
2787*8c35d5eeSXin Li    self.TestLint('for (int i:numbers) {',
2788*8c35d5eeSXin Li                  'Missing space around colon in range-based for loop'
2789*8c35d5eeSXin Li                  '  [whitespace/forcolon] [2]')
2790*8c35d5eeSXin Li
2791*8c35d5eeSXin Li    # The scope operator '::' shouldn't cause warnings...
2792*8c35d5eeSXin Li    self.TestLint('for (std::size_t i : sizes) {}', '')
2793*8c35d5eeSXin Li    # ...but it shouldn't suppress them either.
2794*8c35d5eeSXin Li    self.TestLint('for (std::size_t i: sizes) {}',
2795*8c35d5eeSXin Li                  'Missing space around colon in range-based for loop'
2796*8c35d5eeSXin Li                  '  [whitespace/forcolon] [2]')
2797*8c35d5eeSXin Li
2798*8c35d5eeSXin Li
2799*8c35d5eeSXin Li  # Static or global STL strings.
2800*8c35d5eeSXin Li  def testStaticOrGlobalSTLStrings(self):
2801*8c35d5eeSXin Li    # A template for the error message for a const global/static string.
2802*8c35d5eeSXin Li    error_msg = ('For a static/global string constant, use a C style '
2803*8c35d5eeSXin Li                 'string instead: "%s[]".  [runtime/string] [4]')
2804*8c35d5eeSXin Li
2805*8c35d5eeSXin Li    # The error message for a non-const global/static string variable.
2806*8c35d5eeSXin Li    nonconst_error_msg = ('Static/global string variables are not permitted.'
2807*8c35d5eeSXin Li                          '  [runtime/string] [4]')
2808*8c35d5eeSXin Li
2809*8c35d5eeSXin Li    self.TestLint('string foo;',
2810*8c35d5eeSXin Li                  nonconst_error_msg)
2811*8c35d5eeSXin Li    self.TestLint('string kFoo = "hello";  // English',
2812*8c35d5eeSXin Li                  nonconst_error_msg)
2813*8c35d5eeSXin Li    self.TestLint('static string foo;',
2814*8c35d5eeSXin Li                  nonconst_error_msg)
2815*8c35d5eeSXin Li    self.TestLint('static const string foo;',
2816*8c35d5eeSXin Li                  error_msg % 'static const char foo')
2817*8c35d5eeSXin Li    self.TestLint('static const std::string foo;',
2818*8c35d5eeSXin Li                  error_msg % 'static const char foo')
2819*8c35d5eeSXin Li    self.TestLint('string Foo::bar;',
2820*8c35d5eeSXin Li                  nonconst_error_msg)
2821*8c35d5eeSXin Li
2822*8c35d5eeSXin Li    self.TestLint('std::string foo;',
2823*8c35d5eeSXin Li                  nonconst_error_msg)
2824*8c35d5eeSXin Li    self.TestLint('std::string kFoo = "hello";  // English',
2825*8c35d5eeSXin Li                  nonconst_error_msg)
2826*8c35d5eeSXin Li    self.TestLint('static std::string foo;',
2827*8c35d5eeSXin Li                  nonconst_error_msg)
2828*8c35d5eeSXin Li    self.TestLint('static const std::string foo;',
2829*8c35d5eeSXin Li                  error_msg % 'static const char foo')
2830*8c35d5eeSXin Li    self.TestLint('std::string Foo::bar;',
2831*8c35d5eeSXin Li                  nonconst_error_msg)
2832*8c35d5eeSXin Li
2833*8c35d5eeSXin Li    self.TestLint('::std::string foo;',
2834*8c35d5eeSXin Li                  nonconst_error_msg)
2835*8c35d5eeSXin Li    self.TestLint('::std::string kFoo = "hello";  // English',
2836*8c35d5eeSXin Li                  nonconst_error_msg)
2837*8c35d5eeSXin Li    self.TestLint('static ::std::string foo;',
2838*8c35d5eeSXin Li                  nonconst_error_msg)
2839*8c35d5eeSXin Li    self.TestLint('static const ::std::string foo;',
2840*8c35d5eeSXin Li                  error_msg % 'static const char foo')
2841*8c35d5eeSXin Li    self.TestLint('::std::string Foo::bar;',
2842*8c35d5eeSXin Li                  nonconst_error_msg)
2843*8c35d5eeSXin Li
2844*8c35d5eeSXin Li    self.TestLint('string* pointer', '')
2845*8c35d5eeSXin Li    self.TestLint('string *pointer', '')
2846*8c35d5eeSXin Li    self.TestLint('string* pointer = Func();', '')
2847*8c35d5eeSXin Li    self.TestLint('string *pointer = Func();', '')
2848*8c35d5eeSXin Li    self.TestLint('const string* pointer', '')
2849*8c35d5eeSXin Li    self.TestLint('const string *pointer', '')
2850*8c35d5eeSXin Li    self.TestLint('const string* pointer = Func();', '')
2851*8c35d5eeSXin Li    self.TestLint('const string *pointer = Func();', '')
2852*8c35d5eeSXin Li    self.TestLint('string const* pointer', '')
2853*8c35d5eeSXin Li    self.TestLint('string const *pointer', '')
2854*8c35d5eeSXin Li    self.TestLint('string const* pointer = Func();', '')
2855*8c35d5eeSXin Li    self.TestLint('string const *pointer = Func();', '')
2856*8c35d5eeSXin Li    self.TestLint('string* const pointer', '')
2857*8c35d5eeSXin Li    self.TestLint('string *const pointer', '')
2858*8c35d5eeSXin Li    self.TestLint('string* const pointer = Func();', '')
2859*8c35d5eeSXin Li    self.TestLint('string *const pointer = Func();', '')
2860*8c35d5eeSXin Li    self.TestLint('string Foo::bar() {}', '')
2861*8c35d5eeSXin Li    self.TestLint('string Foo::operator*() {}', '')
2862*8c35d5eeSXin Li    # Rare case.
2863*8c35d5eeSXin Li    self.TestLint('string foo("foobar");', nonconst_error_msg)
2864*8c35d5eeSXin Li    # Should not catch local or member variables.
2865*8c35d5eeSXin Li    self.TestLint('  string foo', '')
2866*8c35d5eeSXin Li    # Should not catch functions.
2867*8c35d5eeSXin Li    self.TestLint('string EmptyString() { return ""; }', '')
2868*8c35d5eeSXin Li    self.TestLint('string EmptyString () { return ""; }', '')
2869*8c35d5eeSXin Li    self.TestLint('string const& FileInfo::Pathname() const;', '')
2870*8c35d5eeSXin Li    self.TestLint('string const &FileInfo::Pathname() const;', '')
2871*8c35d5eeSXin Li    self.TestLint('string VeryLongNameFunctionSometimesEndsWith(\n'
2872*8c35d5eeSXin Li                  '    VeryLongNameType very_long_name_variable) {}', '')
2873*8c35d5eeSXin Li    self.TestLint('template<>\n'
2874*8c35d5eeSXin Li                  'string FunctionTemplateSpecialization<SomeType>(\n'
2875*8c35d5eeSXin Li                  '      int x) { return ""; }', '')
2876*8c35d5eeSXin Li    self.TestLint('template<>\n'
2877*8c35d5eeSXin Li                  'string FunctionTemplateSpecialization<vector<A::B>* >(\n'
2878*8c35d5eeSXin Li                  '      int x) { return ""; }', '')
2879*8c35d5eeSXin Li
2880*8c35d5eeSXin Li    # should not catch methods of template classes.
2881*8c35d5eeSXin Li    self.TestLint('string Class<Type>::Method() const {\n'
2882*8c35d5eeSXin Li                  '  return "";\n'
2883*8c35d5eeSXin Li                  '}\n', '')
2884*8c35d5eeSXin Li    self.TestLint('string Class<Type>::Method(\n'
2885*8c35d5eeSXin Li                  '   int arg) const {\n'
2886*8c35d5eeSXin Li                  '  return "";\n'
2887*8c35d5eeSXin Li                  '}\n', '')
2888*8c35d5eeSXin Li
2889*8c35d5eeSXin Li    # Check multiline cases.
2890*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
2891*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
2892*8c35d5eeSXin Li                            ['// Copyright 2014 Your Company.',
2893*8c35d5eeSXin Li                             'string Class',
2894*8c35d5eeSXin Li                             '::MemberFunction1();',
2895*8c35d5eeSXin Li                             'string Class::',
2896*8c35d5eeSXin Li                             'MemberFunction2();',
2897*8c35d5eeSXin Li                             'string Class::',
2898*8c35d5eeSXin Li                             'NestedClass::MemberFunction3();',
2899*8c35d5eeSXin Li                             'string TemplateClass<T>::',
2900*8c35d5eeSXin Li                             'NestedClass::MemberFunction4();',
2901*8c35d5eeSXin Li                             'const string Class',
2902*8c35d5eeSXin Li                             '::static_member_variable1;',
2903*8c35d5eeSXin Li                             'const string Class::',
2904*8c35d5eeSXin Li                             'static_member_variable2;',
2905*8c35d5eeSXin Li                             'const string Class',
2906*8c35d5eeSXin Li                             '::static_member_variable3 = "initial value";',
2907*8c35d5eeSXin Li                             'const string Class::',
2908*8c35d5eeSXin Li                             'static_member_variable4 = "initial value";',
2909*8c35d5eeSXin Li                             'string Class::',
2910*8c35d5eeSXin Li                             'static_member_variable5;',
2911*8c35d5eeSXin Li                             ''],
2912*8c35d5eeSXin Li                            error_collector)
2913*8c35d5eeSXin Li    self.assertEquals(error_collector.Results(),
2914*8c35d5eeSXin Li                      [error_msg % 'const char Class::static_member_variable1',
2915*8c35d5eeSXin Li                       error_msg % 'const char Class::static_member_variable2',
2916*8c35d5eeSXin Li                       error_msg % 'const char Class::static_member_variable3',
2917*8c35d5eeSXin Li                       error_msg % 'const char Class::static_member_variable4',
2918*8c35d5eeSXin Li                       nonconst_error_msg])
2919*8c35d5eeSXin Li
2920*8c35d5eeSXin Li  def testNoSpacesInFunctionCalls(self):
2921*8c35d5eeSXin Li    self.TestLint('TellStory(1, 3);',
2922*8c35d5eeSXin Li                  '')
2923*8c35d5eeSXin Li    self.TestLint('TellStory(1, 3 );',
2924*8c35d5eeSXin Li                  'Extra space before )'
2925*8c35d5eeSXin Li                  '  [whitespace/parens] [2]')
2926*8c35d5eeSXin Li    self.TestLint('TellStory(1 /* wolf */, 3 /* pigs */);',
2927*8c35d5eeSXin Li                  '')
2928*8c35d5eeSXin Li    self.TestMultiLineLint("""TellStory(1, 3
2929*8c35d5eeSXin Li                                        );""",
2930*8c35d5eeSXin Li                           'Closing ) should be moved to the previous line'
2931*8c35d5eeSXin Li                           '  [whitespace/parens] [2]')
2932*8c35d5eeSXin Li    self.TestMultiLineLint("""TellStory(Wolves(1),
2933*8c35d5eeSXin Li                                        Pigs(3
2934*8c35d5eeSXin Li                                        ));""",
2935*8c35d5eeSXin Li                           'Closing ) should be moved to the previous line'
2936*8c35d5eeSXin Li                           '  [whitespace/parens] [2]')
2937*8c35d5eeSXin Li    self.TestMultiLineLint("""TellStory(1,
2938*8c35d5eeSXin Li                                        3 );""",
2939*8c35d5eeSXin Li                           'Extra space before )'
2940*8c35d5eeSXin Li                           '  [whitespace/parens] [2]')
2941*8c35d5eeSXin Li
2942*8c35d5eeSXin Li  def testToDoComments(self):
2943*8c35d5eeSXin Li    start_space = ('Too many spaces before TODO'
2944*8c35d5eeSXin Li                   '  [whitespace/todo] [2]')
2945*8c35d5eeSXin Li    missing_username = ('Missing username in TODO; it should look like '
2946*8c35d5eeSXin Li                        '"// TODO(my_username): Stuff."'
2947*8c35d5eeSXin Li                        '  [readability/todo] [2]')
2948*8c35d5eeSXin Li    end_space = ('TODO(my_username) should be followed by a space'
2949*8c35d5eeSXin Li                 '  [whitespace/todo] [2]')
2950*8c35d5eeSXin Li
2951*8c35d5eeSXin Li    self.TestLint('//   TODOfix this',
2952*8c35d5eeSXin Li                  [start_space, missing_username, end_space])
2953*8c35d5eeSXin Li    self.TestLint('//   TODO(ljenkins)fix this',
2954*8c35d5eeSXin Li                  [start_space, end_space])
2955*8c35d5eeSXin Li    self.TestLint('//   TODO fix this',
2956*8c35d5eeSXin Li                  [start_space, missing_username])
2957*8c35d5eeSXin Li    self.TestLint('// TODO fix this', missing_username)
2958*8c35d5eeSXin Li    self.TestLint('// TODO: fix this', missing_username)
2959*8c35d5eeSXin Li    self.TestLint('//TODO(ljenkins): Fix this',
2960*8c35d5eeSXin Li                  'Should have a space between // and comment'
2961*8c35d5eeSXin Li                  '  [whitespace/comments] [4]')
2962*8c35d5eeSXin Li    self.TestLint('// TODO(ljenkins):Fix this', end_space)
2963*8c35d5eeSXin Li    self.TestLint('// TODO(ljenkins):', '')
2964*8c35d5eeSXin Li    self.TestLint('// TODO(ljenkins): fix this', '')
2965*8c35d5eeSXin Li    self.TestLint('// TODO(ljenkins): Fix this', '')
2966*8c35d5eeSXin Li    self.TestLint('#if 1  // TEST_URLTODOCID_WHICH_HAS_THAT_WORD_IN_IT_H_', '')
2967*8c35d5eeSXin Li    self.TestLint('// See also similar TODO above', '')
2968*8c35d5eeSXin Li    self.TestLint(r'EXPECT_EQ("\\", '
2969*8c35d5eeSXin Li                  r'NormalizePath("/./../foo///bar/..//x/../..", ""));',
2970*8c35d5eeSXin Li                  '')
2971*8c35d5eeSXin Li
2972*8c35d5eeSXin Li  def testTwoSpacesBetweenCodeAndComments(self):
2973*8c35d5eeSXin Li    self.TestLint('} // namespace foo',
2974*8c35d5eeSXin Li                  'At least two spaces is best between code and comments'
2975*8c35d5eeSXin Li                  '  [whitespace/comments] [2]')
2976*8c35d5eeSXin Li    self.TestLint('}// namespace foo',
2977*8c35d5eeSXin Li                  'At least two spaces is best between code and comments'
2978*8c35d5eeSXin Li                  '  [whitespace/comments] [2]')
2979*8c35d5eeSXin Li    self.TestLint('printf("foo"); // Outside quotes.',
2980*8c35d5eeSXin Li                  'At least two spaces is best between code and comments'
2981*8c35d5eeSXin Li                  '  [whitespace/comments] [2]')
2982*8c35d5eeSXin Li    self.TestLint('int i = 0;  // Having two spaces is fine.', '')
2983*8c35d5eeSXin Li    self.TestLint('int i = 0;   // Having three spaces is OK.', '')
2984*8c35d5eeSXin Li    self.TestLint('// Top level comment', '')
2985*8c35d5eeSXin Li    self.TestLint('  // Line starts with two spaces.', '')
2986*8c35d5eeSXin Li    self.TestMultiLineLint('void foo() {\n'
2987*8c35d5eeSXin Li                           '  { // A scope is opening.\n'
2988*8c35d5eeSXin Li                           '    int a;', '')
2989*8c35d5eeSXin Li    self.TestMultiLineLint('void foo() {\n'
2990*8c35d5eeSXin Li                           '  { // A scope is opening.\n'
2991*8c35d5eeSXin Li                           '#define A a',
2992*8c35d5eeSXin Li                           'At least two spaces is best between code and '
2993*8c35d5eeSXin Li                           'comments  [whitespace/comments] [2]')
2994*8c35d5eeSXin Li    self.TestMultiLineLint('  foo();\n'
2995*8c35d5eeSXin Li                           '  { // An indented scope is opening.\n'
2996*8c35d5eeSXin Li                           '    int a;', '')
2997*8c35d5eeSXin Li    self.TestMultiLineLint('vector<int> my_elements = {// first\n'
2998*8c35d5eeSXin Li                           '                           1,', '')
2999*8c35d5eeSXin Li    self.TestMultiLineLint('vector<int> my_elements = {// my_elements is ..\n'
3000*8c35d5eeSXin Li                           '    1,',
3001*8c35d5eeSXin Li                           'At least two spaces is best between code and '
3002*8c35d5eeSXin Li                           'comments  [whitespace/comments] [2]')
3003*8c35d5eeSXin Li    self.TestLint('if (foo) { // not a pure scope; comment is too close!',
3004*8c35d5eeSXin Li                  'At least two spaces is best between code and comments'
3005*8c35d5eeSXin Li                  '  [whitespace/comments] [2]')
3006*8c35d5eeSXin Li    self.TestLint('printf("// In quotes.")', '')
3007*8c35d5eeSXin Li    self.TestLint('printf("\\"%s // In quotes.")', '')
3008*8c35d5eeSXin Li    self.TestLint('printf("%s", "// In quotes.")', '')
3009*8c35d5eeSXin Li
3010*8c35d5eeSXin Li  def testSpaceAfterCommentMarker(self):
3011*8c35d5eeSXin Li    self.TestLint('//', '')
3012*8c35d5eeSXin Li    self.TestLint('//x', 'Should have a space between // and comment'
3013*8c35d5eeSXin Li                  '  [whitespace/comments] [4]')
3014*8c35d5eeSXin Li    self.TestLint('// x', '')
3015*8c35d5eeSXin Li    self.TestLint('///', '')
3016*8c35d5eeSXin Li    self.TestLint('/// x', '')
3017*8c35d5eeSXin Li    self.TestLint('//!', '')
3018*8c35d5eeSXin Li    self.TestLint('//----', '')
3019*8c35d5eeSXin Li    self.TestLint('//====', '')
3020*8c35d5eeSXin Li    self.TestLint('//////', '')
3021*8c35d5eeSXin Li    self.TestLint('////// x', '')
3022*8c35d5eeSXin Li    self.TestLint('///< x', '') # After-member Doxygen comment
3023*8c35d5eeSXin Li    self.TestLint('//!< x', '') # After-member Doxygen comment
3024*8c35d5eeSXin Li    self.TestLint('////x', 'Should have a space between // and comment'
3025*8c35d5eeSXin Li                  '  [whitespace/comments] [4]')
3026*8c35d5eeSXin Li    self.TestLint('//}', '')
3027*8c35d5eeSXin Li    self.TestLint('//}x', 'Should have a space between // and comment'
3028*8c35d5eeSXin Li                  '  [whitespace/comments] [4]')
3029*8c35d5eeSXin Li    self.TestLint('//!<x', 'Should have a space between // and comment'
3030*8c35d5eeSXin Li                  '  [whitespace/comments] [4]')
3031*8c35d5eeSXin Li    self.TestLint('///<x', 'Should have a space between // and comment'
3032*8c35d5eeSXin Li                  '  [whitespace/comments] [4]')
3033*8c35d5eeSXin Li
3034*8c35d5eeSXin Li  # Test a line preceded by empty or comment lines.  There was a bug
3035*8c35d5eeSXin Li  # that caused it to print the same warning N times if the erroneous
3036*8c35d5eeSXin Li  # line was preceded by N lines of empty or comment lines.  To be
3037*8c35d5eeSXin Li  # precise, the '// marker so line numbers and indices both start at
3038*8c35d5eeSXin Li  # 1' line was also causing the issue.
3039*8c35d5eeSXin Li  def testLinePrecededByEmptyOrCommentLines(self):
3040*8c35d5eeSXin Li    def DoTest(self, lines):
3041*8c35d5eeSXin Li      error_collector = ErrorCollector(self.assert_)
3042*8c35d5eeSXin Li      cpplint.ProcessFileData('foo.cc', 'cc', lines, error_collector)
3043*8c35d5eeSXin Li      # The warning appears only once.
3044*8c35d5eeSXin Li      self.assertEquals(
3045*8c35d5eeSXin Li          1,
3046*8c35d5eeSXin Li          error_collector.Results().count(
3047*8c35d5eeSXin Li              'Do not use namespace using-directives.  '
3048*8c35d5eeSXin Li              'Use using-declarations instead.'
3049*8c35d5eeSXin Li              '  [build/namespaces] [5]'))
3050*8c35d5eeSXin Li    DoTest(self, ['using namespace foo;'])
3051*8c35d5eeSXin Li    DoTest(self, ['', '', '', 'using namespace foo;'])
3052*8c35d5eeSXin Li    DoTest(self, ['// hello', 'using namespace foo;'])
3053*8c35d5eeSXin Li
3054*8c35d5eeSXin Li  def testNewlineAtEOF(self):
3055*8c35d5eeSXin Li    def DoTest(self, data, is_missing_eof):
3056*8c35d5eeSXin Li      error_collector = ErrorCollector(self.assert_)
3057*8c35d5eeSXin Li      cpplint.ProcessFileData('foo.cc', 'cc', data.split('\n'),
3058*8c35d5eeSXin Li                              error_collector)
3059*8c35d5eeSXin Li      # The warning appears only once.
3060*8c35d5eeSXin Li      self.assertEquals(
3061*8c35d5eeSXin Li          int(is_missing_eof),
3062*8c35d5eeSXin Li          error_collector.Results().count(
3063*8c35d5eeSXin Li              'Could not find a newline character at the end of the file.'
3064*8c35d5eeSXin Li              '  [whitespace/ending_newline] [5]'))
3065*8c35d5eeSXin Li
3066*8c35d5eeSXin Li    DoTest(self, '// Newline\n// at EOF\n', False)
3067*8c35d5eeSXin Li    DoTest(self, '// No newline\n// at EOF', True)
3068*8c35d5eeSXin Li
3069*8c35d5eeSXin Li  def testInvalidUtf8(self):
3070*8c35d5eeSXin Li    def DoTest(self, raw_bytes, has_invalid_utf8):
3071*8c35d5eeSXin Li      error_collector = ErrorCollector(self.assert_)
3072*8c35d5eeSXin Li      cpplint.ProcessFileData(
3073*8c35d5eeSXin Li          'foo.cc', 'cc',
3074*8c35d5eeSXin Li          unicode(raw_bytes, 'utf8', 'replace').split('\n'),
3075*8c35d5eeSXin Li          error_collector)
3076*8c35d5eeSXin Li      # The warning appears only once.
3077*8c35d5eeSXin Li      self.assertEquals(
3078*8c35d5eeSXin Li          int(has_invalid_utf8),
3079*8c35d5eeSXin Li          error_collector.Results().count(
3080*8c35d5eeSXin Li              'Line contains invalid UTF-8'
3081*8c35d5eeSXin Li              ' (or Unicode replacement character).'
3082*8c35d5eeSXin Li              '  [readability/utf8] [5]'))
3083*8c35d5eeSXin Li
3084*8c35d5eeSXin Li    DoTest(self, 'Hello world\n', False)
3085*8c35d5eeSXin Li    DoTest(self, '\xe9\x8e\xbd\n', False)
3086*8c35d5eeSXin Li    DoTest(self, '\xe9x\x8e\xbd\n', True)
3087*8c35d5eeSXin Li    # This is the encoding of the replacement character itself (which
3088*8c35d5eeSXin Li    # you can see by evaluating codecs.getencoder('utf8')(u'\ufffd')).
3089*8c35d5eeSXin Li    DoTest(self, '\xef\xbf\xbd\n', True)
3090*8c35d5eeSXin Li
3091*8c35d5eeSXin Li  def testBadCharacters(self):
3092*8c35d5eeSXin Li    # Test for NUL bytes only
3093*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3094*8c35d5eeSXin Li    cpplint.ProcessFileData('nul.cc', 'cc',
3095*8c35d5eeSXin Li                            ['// Copyright 2014 Your Company.',
3096*8c35d5eeSXin Li                             '\0', ''], error_collector)
3097*8c35d5eeSXin Li    self.assertEquals(
3098*8c35d5eeSXin Li        error_collector.Results(),
3099*8c35d5eeSXin Li        'Line contains NUL byte.  [readability/nul] [5]')
3100*8c35d5eeSXin Li
3101*8c35d5eeSXin Li    # Make sure both NUL bytes and UTF-8 are caught if they appear on
3102*8c35d5eeSXin Li    # the same line.
3103*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3104*8c35d5eeSXin Li    cpplint.ProcessFileData(
3105*8c35d5eeSXin Li        'nul_utf8.cc', 'cc',
3106*8c35d5eeSXin Li        ['// Copyright 2014 Your Company.',
3107*8c35d5eeSXin Li         unicode('\xe9x\0', 'utf8', 'replace'), ''],
3108*8c35d5eeSXin Li        error_collector)
3109*8c35d5eeSXin Li    self.assertEquals(
3110*8c35d5eeSXin Li        error_collector.Results(),
3111*8c35d5eeSXin Li        ['Line contains invalid UTF-8 (or Unicode replacement character).'
3112*8c35d5eeSXin Li         '  [readability/utf8] [5]',
3113*8c35d5eeSXin Li         'Line contains NUL byte.  [readability/nul] [5]'])
3114*8c35d5eeSXin Li
3115*8c35d5eeSXin Li  def testIsBlankLine(self):
3116*8c35d5eeSXin Li    self.assert_(cpplint.IsBlankLine(''))
3117*8c35d5eeSXin Li    self.assert_(cpplint.IsBlankLine(' '))
3118*8c35d5eeSXin Li    self.assert_(cpplint.IsBlankLine(' \t\r\n'))
3119*8c35d5eeSXin Li    self.assert_(not cpplint.IsBlankLine('int a;'))
3120*8c35d5eeSXin Li    self.assert_(not cpplint.IsBlankLine('{'))
3121*8c35d5eeSXin Li
3122*8c35d5eeSXin Li  def testBlankLinesCheck(self):
3123*8c35d5eeSXin Li    self.TestBlankLinesCheck(['{\n', '\n', '\n', '}\n'], 1, 1)
3124*8c35d5eeSXin Li    self.TestBlankLinesCheck(['  if (foo) {\n', '\n', '  }\n'], 1, 1)
3125*8c35d5eeSXin Li    self.TestBlankLinesCheck(
3126*8c35d5eeSXin Li        ['\n', '// {\n', '\n', '\n', '// Comment\n', '{\n', '}\n'], 0, 0)
3127*8c35d5eeSXin Li    self.TestBlankLinesCheck(['\n', 'run("{");\n', '\n'], 0, 0)
3128*8c35d5eeSXin Li    self.TestBlankLinesCheck(['\n', '  if (foo) { return 0; }\n', '\n'], 0, 0)
3129*8c35d5eeSXin Li    self.TestBlankLinesCheck(
3130*8c35d5eeSXin Li        ['int x(\n', '    int a) {\n', '\n', 'return 0;\n', '}'], 0, 0)
3131*8c35d5eeSXin Li    self.TestBlankLinesCheck(
3132*8c35d5eeSXin Li        ['int x(\n', '    int a) const {\n', '\n', 'return 0;\n', '}'], 0, 0)
3133*8c35d5eeSXin Li    self.TestBlankLinesCheck(
3134*8c35d5eeSXin Li        ['int x(\n', '     int a) {\n', '\n', 'return 0;\n', '}'], 1, 0)
3135*8c35d5eeSXin Li    self.TestBlankLinesCheck(
3136*8c35d5eeSXin Li        ['int x(\n', '   int a) {\n', '\n', 'return 0;\n', '}'], 1, 0)
3137*8c35d5eeSXin Li
3138*8c35d5eeSXin Li  def testAllowBlankLineBeforeClosingNamespace(self):
3139*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3140*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
3141*8c35d5eeSXin Li                            ['namespace {',
3142*8c35d5eeSXin Li                             '',
3143*8c35d5eeSXin Li                             '}  // namespace',
3144*8c35d5eeSXin Li                             'namespace another_namespace {',
3145*8c35d5eeSXin Li                             '',
3146*8c35d5eeSXin Li                             '}',
3147*8c35d5eeSXin Li                             'namespace {',
3148*8c35d5eeSXin Li                             '',
3149*8c35d5eeSXin Li                             'template<class T, ',
3150*8c35d5eeSXin Li                             '         class A = hoge<T>, ',
3151*8c35d5eeSXin Li                             '         class B = piyo<T>, ',
3152*8c35d5eeSXin Li                             '         class C = fuga<T> >',
3153*8c35d5eeSXin Li                             'class D {',
3154*8c35d5eeSXin Li                             ' public:',
3155*8c35d5eeSXin Li                             '};',
3156*8c35d5eeSXin Li                             '', '', '', '',
3157*8c35d5eeSXin Li                             '}'],
3158*8c35d5eeSXin Li                            error_collector)
3159*8c35d5eeSXin Li    self.assertEquals(0, error_collector.Results().count(
3160*8c35d5eeSXin Li        'Redundant blank line at the end of a code block should be deleted.'
3161*8c35d5eeSXin Li        '  [whitespace/blank_line] [3]'))
3162*8c35d5eeSXin Li
3163*8c35d5eeSXin Li  def testAllowBlankLineBeforeIfElseChain(self):
3164*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3165*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
3166*8c35d5eeSXin Li                            ['if (hoge) {',
3167*8c35d5eeSXin Li                             '',  # No warning
3168*8c35d5eeSXin Li                             '} else if (piyo) {',
3169*8c35d5eeSXin Li                             '',  # No warning
3170*8c35d5eeSXin Li                             '} else if (piyopiyo) {',
3171*8c35d5eeSXin Li                             '  hoge = true;',  # No warning
3172*8c35d5eeSXin Li                             '} else {',
3173*8c35d5eeSXin Li                             '',  # Warning on this line
3174*8c35d5eeSXin Li                             '}'],
3175*8c35d5eeSXin Li                            error_collector)
3176*8c35d5eeSXin Li    self.assertEquals(1, error_collector.Results().count(
3177*8c35d5eeSXin Li        'Redundant blank line at the end of a code block should be deleted.'
3178*8c35d5eeSXin Li        '  [whitespace/blank_line] [3]'))
3179*8c35d5eeSXin Li
3180*8c35d5eeSXin Li  def testAllowBlankLineAfterExtern(self):
3181*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3182*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
3183*8c35d5eeSXin Li                            ['extern "C" {',
3184*8c35d5eeSXin Li                             '',
3185*8c35d5eeSXin Li                             'EXPORTAPI void APICALL Some_function() {}',
3186*8c35d5eeSXin Li                             '',
3187*8c35d5eeSXin Li                             '}'],
3188*8c35d5eeSXin Li                            error_collector)
3189*8c35d5eeSXin Li    self.assertEquals(0, error_collector.Results().count(
3190*8c35d5eeSXin Li        'Redundant blank line at the start of a code block should be deleted.'
3191*8c35d5eeSXin Li        '  [whitespace/blank_line] [2]'))
3192*8c35d5eeSXin Li    self.assertEquals(0, error_collector.Results().count(
3193*8c35d5eeSXin Li        'Redundant blank line at the end of a code block should be deleted.'
3194*8c35d5eeSXin Li        '  [whitespace/blank_line] [3]'))
3195*8c35d5eeSXin Li
3196*8c35d5eeSXin Li  def testBlankLineBeforeSectionKeyword(self):
3197*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3198*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
3199*8c35d5eeSXin Li                            ['class A {',
3200*8c35d5eeSXin Li                             ' public:',
3201*8c35d5eeSXin Li                             ' protected:',   # warning 1
3202*8c35d5eeSXin Li                             ' private:',     # warning 2
3203*8c35d5eeSXin Li                             '  struct B {',
3204*8c35d5eeSXin Li                             '   public:',
3205*8c35d5eeSXin Li                             '   private:'] +  # warning 3
3206*8c35d5eeSXin Li                            ([''] * 100) +  # Make A and B longer than 100 lines
3207*8c35d5eeSXin Li                            ['  };',
3208*8c35d5eeSXin Li                             '  struct C {',
3209*8c35d5eeSXin Li                             '   protected:',
3210*8c35d5eeSXin Li                             '   private:',  # C is too short for warnings
3211*8c35d5eeSXin Li                             '  };',
3212*8c35d5eeSXin Li                             '};',
3213*8c35d5eeSXin Li                             'class D',
3214*8c35d5eeSXin Li                             '    : public {',
3215*8c35d5eeSXin Li                             ' public:',  # no warning
3216*8c35d5eeSXin Li                             '};',
3217*8c35d5eeSXin Li                             'class E {\\',
3218*8c35d5eeSXin Li                             ' public:\\'] +
3219*8c35d5eeSXin Li                            (['\\'] * 100) +  # Makes E > 100 lines
3220*8c35d5eeSXin Li                            ['  int non_empty_line;\\',
3221*8c35d5eeSXin Li                             ' private:\\',   # no warning
3222*8c35d5eeSXin Li                             '  int a;\\',
3223*8c35d5eeSXin Li                             '};'],
3224*8c35d5eeSXin Li                            error_collector)
3225*8c35d5eeSXin Li    self.assertEquals(2, error_collector.Results().count(
3226*8c35d5eeSXin Li        '"private:" should be preceded by a blank line'
3227*8c35d5eeSXin Li        '  [whitespace/blank_line] [3]'))
3228*8c35d5eeSXin Li    self.assertEquals(1, error_collector.Results().count(
3229*8c35d5eeSXin Li        '"protected:" should be preceded by a blank line'
3230*8c35d5eeSXin Li        '  [whitespace/blank_line] [3]'))
3231*8c35d5eeSXin Li
3232*8c35d5eeSXin Li  def testNoBlankLineAfterSectionKeyword(self):
3233*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3234*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
3235*8c35d5eeSXin Li                            ['class A {',
3236*8c35d5eeSXin Li                             ' public:',
3237*8c35d5eeSXin Li                             '',  # warning 1
3238*8c35d5eeSXin Li                             ' private:',
3239*8c35d5eeSXin Li                             '',  # warning 2
3240*8c35d5eeSXin Li                             '  struct B {',
3241*8c35d5eeSXin Li                             '   protected:',
3242*8c35d5eeSXin Li                             '',  # warning 3
3243*8c35d5eeSXin Li                             '  };',
3244*8c35d5eeSXin Li                             '};'],
3245*8c35d5eeSXin Li                            error_collector)
3246*8c35d5eeSXin Li    self.assertEquals(1, error_collector.Results().count(
3247*8c35d5eeSXin Li        'Do not leave a blank line after "public:"'
3248*8c35d5eeSXin Li        '  [whitespace/blank_line] [3]'))
3249*8c35d5eeSXin Li    self.assertEquals(1, error_collector.Results().count(
3250*8c35d5eeSXin Li        'Do not leave a blank line after "protected:"'
3251*8c35d5eeSXin Li        '  [whitespace/blank_line] [3]'))
3252*8c35d5eeSXin Li    self.assertEquals(1, error_collector.Results().count(
3253*8c35d5eeSXin Li        'Do not leave a blank line after "private:"'
3254*8c35d5eeSXin Li        '  [whitespace/blank_line] [3]'))
3255*8c35d5eeSXin Li
3256*8c35d5eeSXin Li  def testAllowBlankLinesInRawStrings(self):
3257*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3258*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
3259*8c35d5eeSXin Li                            ['// Copyright 2014 Your Company.',
3260*8c35d5eeSXin Li                             'static const char *kData[] = {R"(',
3261*8c35d5eeSXin Li                             '',
3262*8c35d5eeSXin Li                             ')", R"(',
3263*8c35d5eeSXin Li                             '',
3264*8c35d5eeSXin Li                             ')"};',
3265*8c35d5eeSXin Li                             ''],
3266*8c35d5eeSXin Li                            error_collector)
3267*8c35d5eeSXin Li    self.assertEquals('', error_collector.Results())
3268*8c35d5eeSXin Li
3269*8c35d5eeSXin Li  def testElseOnSameLineAsClosingBraces(self):
3270*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3271*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
3272*8c35d5eeSXin Li                            ['if (hoge) {',
3273*8c35d5eeSXin Li                             '}',
3274*8c35d5eeSXin Li                             'else if (piyo) {',  # Warning on this line
3275*8c35d5eeSXin Li                             '}',
3276*8c35d5eeSXin Li                             ' else {'  # Warning on this line
3277*8c35d5eeSXin Li                             '',
3278*8c35d5eeSXin Li                             '}'],
3279*8c35d5eeSXin Li                            error_collector)
3280*8c35d5eeSXin Li    self.assertEquals(2, error_collector.Results().count(
3281*8c35d5eeSXin Li        'An else should appear on the same line as the preceding }'
3282*8c35d5eeSXin Li        '  [whitespace/newline] [4]'))
3283*8c35d5eeSXin Li
3284*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3285*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
3286*8c35d5eeSXin Li                            ['if (hoge) {',
3287*8c35d5eeSXin Li                             '',
3288*8c35d5eeSXin Li                             '}',
3289*8c35d5eeSXin Li                             'else',  # Warning on this line
3290*8c35d5eeSXin Li                             '{',
3291*8c35d5eeSXin Li                             '',
3292*8c35d5eeSXin Li                             '}'],
3293*8c35d5eeSXin Li                            error_collector)
3294*8c35d5eeSXin Li    self.assertEquals(1, error_collector.Results().count(
3295*8c35d5eeSXin Li        'An else should appear on the same line as the preceding }'
3296*8c35d5eeSXin Li        '  [whitespace/newline] [4]'))
3297*8c35d5eeSXin Li
3298*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3299*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
3300*8c35d5eeSXin Li                            ['if (hoge) {',
3301*8c35d5eeSXin Li                             '',
3302*8c35d5eeSXin Li                             '}',
3303*8c35d5eeSXin Li                             'else_function();'],
3304*8c35d5eeSXin Li                            error_collector)
3305*8c35d5eeSXin Li    self.assertEquals(0, error_collector.Results().count(
3306*8c35d5eeSXin Li        'An else should appear on the same line as the preceding }'
3307*8c35d5eeSXin Li        '  [whitespace/newline] [4]'))
3308*8c35d5eeSXin Li
3309*8c35d5eeSXin Li  def testMultipleStatementsOnSameLine(self):
3310*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3311*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
3312*8c35d5eeSXin Li                            ['for (int i = 0; i < 1; i++) {}',
3313*8c35d5eeSXin Li                             'switch (x) {',
3314*8c35d5eeSXin Li                             '  case 0: func(); break; ',
3315*8c35d5eeSXin Li                             '}',
3316*8c35d5eeSXin Li                             'sum += MathUtil::SafeIntRound(x); x += 0.1;'],
3317*8c35d5eeSXin Li                            error_collector)
3318*8c35d5eeSXin Li    self.assertEquals(0, error_collector.Results().count(
3319*8c35d5eeSXin Li        'More than one command on the same line  [whitespace/newline] [0]'))
3320*8c35d5eeSXin Li
3321*8c35d5eeSXin Li    old_verbose_level = cpplint._cpplint_state.verbose_level
3322*8c35d5eeSXin Li    cpplint._cpplint_state.verbose_level = 0
3323*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
3324*8c35d5eeSXin Li                            ['sum += MathUtil::SafeIntRound(x); x += 0.1;'],
3325*8c35d5eeSXin Li                            error_collector)
3326*8c35d5eeSXin Li    cpplint._cpplint_state.verbose_level = old_verbose_level
3327*8c35d5eeSXin Li
3328*8c35d5eeSXin Li  def testEndOfNamespaceComments(self):
3329*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3330*8c35d5eeSXin Li    cpplint.ProcessFileData('foo.cc', 'cc',
3331*8c35d5eeSXin Li                            ['namespace {',
3332*8c35d5eeSXin Li                             '',
3333*8c35d5eeSXin Li                             '}',  # No warning (too short)
3334*8c35d5eeSXin Li                             'namespace expected {',
3335*8c35d5eeSXin Li                             '}  // namespace mismatched',  # Warning here
3336*8c35d5eeSXin Li                             'namespace {',
3337*8c35d5eeSXin Li                             '}  // namespace mismatched',  # Warning here
3338*8c35d5eeSXin Li                             'namespace outer { namespace nested {'] +
3339*8c35d5eeSXin Li                            ([''] * 10) +
3340*8c35d5eeSXin Li                            ['}',  # Warning here
3341*8c35d5eeSXin Li                             '}',  # Warning here
3342*8c35d5eeSXin Li                             'namespace {'] +
3343*8c35d5eeSXin Li                            ([''] * 10) +
3344*8c35d5eeSXin Li                            ['}',  # Warning here
3345*8c35d5eeSXin Li                             'namespace {'] +
3346*8c35d5eeSXin Li                            ([''] * 10) +
3347*8c35d5eeSXin Li                            ['}  // namespace some description',  # Anon warning
3348*8c35d5eeSXin Li                             'namespace {'] +
3349*8c35d5eeSXin Li                            ([''] * 10) +
3350*8c35d5eeSXin Li                            ['}  // namespace anonymous',  # Variant warning
3351*8c35d5eeSXin Li                             'namespace {'] +
3352*8c35d5eeSXin Li                            ([''] * 10) +
3353*8c35d5eeSXin Li                            ['}  // anonymous namespace (utils)',  # Variant
3354*8c35d5eeSXin Li                             'namespace {'] +
3355*8c35d5eeSXin Li                            ([''] * 10) +
3356*8c35d5eeSXin Li                            ['}  // anonymous namespace',  # No warning
3357*8c35d5eeSXin Li                             'namespace missing_comment {'] +
3358*8c35d5eeSXin Li                            ([''] * 10) +
3359*8c35d5eeSXin Li                            ['}',  # Warning here
3360*8c35d5eeSXin Li                             'namespace no_warning {'] +
3361*8c35d5eeSXin Li                            ([''] * 10) +
3362*8c35d5eeSXin Li                            ['}  // namespace no_warning',
3363*8c35d5eeSXin Li                             'namespace no_warning {'] +
3364*8c35d5eeSXin Li                            ([''] * 10) +
3365*8c35d5eeSXin Li                            ['};  // end namespace no_warning',
3366*8c35d5eeSXin Li                             '#define MACRO \\',
3367*8c35d5eeSXin Li                             'namespace c_style { \\'] +
3368*8c35d5eeSXin Li                            (['\\'] * 10) +
3369*8c35d5eeSXin Li                            ['}  /* namespace c_style. */ \\',
3370*8c35d5eeSXin Li                             ';'],
3371*8c35d5eeSXin Li                            error_collector)
3372*8c35d5eeSXin Li    self.assertEquals(1, error_collector.Results().count(
3373*8c35d5eeSXin Li        'Namespace should be terminated with "// namespace expected"'
3374*8c35d5eeSXin Li        '  [readability/namespace] [5]'))
3375*8c35d5eeSXin Li    self.assertEquals(1, error_collector.Results().count(
3376*8c35d5eeSXin Li        'Namespace should be terminated with "// namespace outer"'
3377*8c35d5eeSXin Li        '  [readability/namespace] [5]'))
3378*8c35d5eeSXin Li    self.assertEquals(1, error_collector.Results().count(
3379*8c35d5eeSXin Li        'Namespace should be terminated with "// namespace nested"'
3380*8c35d5eeSXin Li        '  [readability/namespace] [5]'))
3381*8c35d5eeSXin Li    self.assertEquals(3, error_collector.Results().count(
3382*8c35d5eeSXin Li        'Anonymous namespace should be terminated with "// namespace"'
3383*8c35d5eeSXin Li        '  [readability/namespace] [5]'))
3384*8c35d5eeSXin Li    self.assertEquals(2, error_collector.Results().count(
3385*8c35d5eeSXin Li        'Anonymous namespace should be terminated with "// namespace" or'
3386*8c35d5eeSXin Li        ' "// anonymous namespace"'
3387*8c35d5eeSXin Li        '  [readability/namespace] [5]'))
3388*8c35d5eeSXin Li    self.assertEquals(1, error_collector.Results().count(
3389*8c35d5eeSXin Li        'Namespace should be terminated with "// namespace missing_comment"'
3390*8c35d5eeSXin Li        '  [readability/namespace] [5]'))
3391*8c35d5eeSXin Li    self.assertEquals(0, error_collector.Results().count(
3392*8c35d5eeSXin Li        'Namespace should be terminated with "// namespace no_warning"'
3393*8c35d5eeSXin Li        '  [readability/namespace] [5]'))
3394*8c35d5eeSXin Li
3395*8c35d5eeSXin Li  def testElseClauseNotOnSameLineAsElse(self):
3396*8c35d5eeSXin Li    self.TestLint('  else DoSomethingElse();',
3397*8c35d5eeSXin Li                  'Else clause should never be on same line as else '
3398*8c35d5eeSXin Li                  '(use 2 lines)  [whitespace/newline] [4]')
3399*8c35d5eeSXin Li    self.TestLint('  else ifDoSomethingElse();',
3400*8c35d5eeSXin Li                  'Else clause should never be on same line as else '
3401*8c35d5eeSXin Li                  '(use 2 lines)  [whitespace/newline] [4]')
3402*8c35d5eeSXin Li    self.TestLint('  } else if (blah) {', '')
3403*8c35d5eeSXin Li    self.TestLint('  variable_ends_in_else = true;', '')
3404*8c35d5eeSXin Li
3405*8c35d5eeSXin Li  def testComma(self):
3406*8c35d5eeSXin Li    self.TestLint('a = f(1,2);',
3407*8c35d5eeSXin Li                  'Missing space after ,  [whitespace/comma] [3]')
3408*8c35d5eeSXin Li    self.TestLint('int tmp=a,a=b,b=tmp;',
3409*8c35d5eeSXin Li                  ['Missing spaces around =  [whitespace/operators] [4]',
3410*8c35d5eeSXin Li                   'Missing space after ,  [whitespace/comma] [3]'])
3411*8c35d5eeSXin Li    self.TestLint('f(a, /* name */ b);', '')
3412*8c35d5eeSXin Li    self.TestLint('f(a, /* name */b);', '')
3413*8c35d5eeSXin Li    self.TestLint('f(a, /* name */-1);', '')
3414*8c35d5eeSXin Li    self.TestLint('f(a, /* name */"1");', '')
3415*8c35d5eeSXin Li    self.TestLint('f(1, /* empty macro arg */, 2)', '')
3416*8c35d5eeSXin Li    self.TestLint('f(1,, 2)', '')
3417*8c35d5eeSXin Li    self.TestLint('operator,()', '')
3418*8c35d5eeSXin Li    self.TestLint('operator,(a,b)',
3419*8c35d5eeSXin Li                  'Missing space after ,  [whitespace/comma] [3]')
3420*8c35d5eeSXin Li
3421*8c35d5eeSXin Li  def testEqualsOperatorSpacing(self):
3422*8c35d5eeSXin Li    self.TestLint('int tmp= a;',
3423*8c35d5eeSXin Li                  'Missing spaces around =  [whitespace/operators] [4]')
3424*8c35d5eeSXin Li    self.TestLint('int tmp =a;',
3425*8c35d5eeSXin Li                  'Missing spaces around =  [whitespace/operators] [4]')
3426*8c35d5eeSXin Li    self.TestLint('int tmp=a;',
3427*8c35d5eeSXin Li                  'Missing spaces around =  [whitespace/operators] [4]')
3428*8c35d5eeSXin Li    self.TestLint('int tmp= 7;',
3429*8c35d5eeSXin Li                  'Missing spaces around =  [whitespace/operators] [4]')
3430*8c35d5eeSXin Li    self.TestLint('int tmp =7;',
3431*8c35d5eeSXin Li                  'Missing spaces around =  [whitespace/operators] [4]')
3432*8c35d5eeSXin Li    self.TestLint('int tmp=7;',
3433*8c35d5eeSXin Li                  'Missing spaces around =  [whitespace/operators] [4]')
3434*8c35d5eeSXin Li    self.TestLint('int* tmp=*p;',
3435*8c35d5eeSXin Li                  'Missing spaces around =  [whitespace/operators] [4]')
3436*8c35d5eeSXin Li    self.TestLint('int* tmp= *p;',
3437*8c35d5eeSXin Li                  'Missing spaces around =  [whitespace/operators] [4]')
3438*8c35d5eeSXin Li    self.TestMultiLineLint(
3439*8c35d5eeSXin Li        TrimExtraIndent('''
3440*8c35d5eeSXin Li            lookahead_services_=
3441*8c35d5eeSXin Li              ::strings::Split(FLAGS_ls, ",", ::strings::SkipEmpty());'''),
3442*8c35d5eeSXin Li        'Missing spaces around =  [whitespace/operators] [4]')
3443*8c35d5eeSXin Li    self.TestLint('bool result = a>=42;',
3444*8c35d5eeSXin Li                  'Missing spaces around >=  [whitespace/operators] [3]')
3445*8c35d5eeSXin Li    self.TestLint('bool result = a<=42;',
3446*8c35d5eeSXin Li                  'Missing spaces around <=  [whitespace/operators] [3]')
3447*8c35d5eeSXin Li    self.TestLint('bool result = a==42;',
3448*8c35d5eeSXin Li                  'Missing spaces around ==  [whitespace/operators] [3]')
3449*8c35d5eeSXin Li    self.TestLint('auto result = a!=42;',
3450*8c35d5eeSXin Li                  'Missing spaces around !=  [whitespace/operators] [3]')
3451*8c35d5eeSXin Li    self.TestLint('int a = b!=c;',
3452*8c35d5eeSXin Li                  'Missing spaces around !=  [whitespace/operators] [3]')
3453*8c35d5eeSXin Li    self.TestLint('a&=42;', '')
3454*8c35d5eeSXin Li    self.TestLint('a|=42;', '')
3455*8c35d5eeSXin Li    self.TestLint('a^=42;', '')
3456*8c35d5eeSXin Li    self.TestLint('a+=42;', '')
3457*8c35d5eeSXin Li    self.TestLint('a*=42;', '')
3458*8c35d5eeSXin Li    self.TestLint('a/=42;', '')
3459*8c35d5eeSXin Li    self.TestLint('a%=42;', '')
3460*8c35d5eeSXin Li    self.TestLint('a>>=5;', '')
3461*8c35d5eeSXin Li    self.TestLint('a<<=5;', '')
3462*8c35d5eeSXin Li
3463*8c35d5eeSXin Li  def testShiftOperatorSpacing(self):
3464*8c35d5eeSXin Li    self.TestLint('a<<b',
3465*8c35d5eeSXin Li                  'Missing spaces around <<  [whitespace/operators] [3]')
3466*8c35d5eeSXin Li    self.TestLint('a>>b',
3467*8c35d5eeSXin Li                  'Missing spaces around >>  [whitespace/operators] [3]')
3468*8c35d5eeSXin Li    self.TestLint('1<<20', '')
3469*8c35d5eeSXin Li    self.TestLint('1024>>10', '')
3470*8c35d5eeSXin Li    self.TestLint('Kernel<<<1, 2>>>()', '')
3471*8c35d5eeSXin Li
3472*8c35d5eeSXin Li  def testIndent(self):
3473*8c35d5eeSXin Li    self.TestLint('static int noindent;', '')
3474*8c35d5eeSXin Li    self.TestLint('  int two_space_indent;', '')
3475*8c35d5eeSXin Li    self.TestLint('    int four_space_indent;', '')
3476*8c35d5eeSXin Li    self.TestLint(' int one_space_indent;',
3477*8c35d5eeSXin Li                  'Weird number of spaces at line-start.  '
3478*8c35d5eeSXin Li                  'Are you using a 2-space indent?  [whitespace/indent] [3]')
3479*8c35d5eeSXin Li    self.TestLint('   int three_space_indent;',
3480*8c35d5eeSXin Li                  'Weird number of spaces at line-start.  '
3481*8c35d5eeSXin Li                  'Are you using a 2-space indent?  [whitespace/indent] [3]')
3482*8c35d5eeSXin Li    self.TestLint(' char* one_space_indent = "public:";',
3483*8c35d5eeSXin Li                  'Weird number of spaces at line-start.  '
3484*8c35d5eeSXin Li                  'Are you using a 2-space indent?  [whitespace/indent] [3]')
3485*8c35d5eeSXin Li    self.TestLint(' public:', '')
3486*8c35d5eeSXin Li    self.TestLint('  protected:', '')
3487*8c35d5eeSXin Li    self.TestLint('   private:', '')
3488*8c35d5eeSXin Li    self.TestLint(' protected: \\', '')
3489*8c35d5eeSXin Li    self.TestLint('  public:      \\', '')
3490*8c35d5eeSXin Li    self.TestLint('   private:   \\', '')
3491*8c35d5eeSXin Li    self.TestMultiLineLint(
3492*8c35d5eeSXin Li        TrimExtraIndent("""
3493*8c35d5eeSXin Li            class foo {
3494*8c35d5eeSXin Li             public slots:
3495*8c35d5eeSXin Li              void bar();
3496*8c35d5eeSXin Li            };"""),
3497*8c35d5eeSXin Li        'Weird number of spaces at line-start.  '
3498*8c35d5eeSXin Li        'Are you using a 2-space indent?  [whitespace/indent] [3]')
3499*8c35d5eeSXin Li    self.TestMultiLineLint(
3500*8c35d5eeSXin Li        TrimExtraIndent('''
3501*8c35d5eeSXin Li            static const char kRawString[] = R"("
3502*8c35d5eeSXin Li             ")";'''),
3503*8c35d5eeSXin Li        '')
3504*8c35d5eeSXin Li    self.TestMultiLineLint(
3505*8c35d5eeSXin Li        TrimExtraIndent('''
3506*8c35d5eeSXin Li            KV<Query,
3507*8c35d5eeSXin Li               Tuple<TaxonomyId, PetacatCategoryId, double>>'''),
3508*8c35d5eeSXin Li        '')
3509*8c35d5eeSXin Li    self.TestMultiLineLint(
3510*8c35d5eeSXin Li        ' static const char kSingleLineRawString[] = R"(...)";',
3511*8c35d5eeSXin Li        'Weird number of spaces at line-start.  '
3512*8c35d5eeSXin Li        'Are you using a 2-space indent?  [whitespace/indent] [3]')
3513*8c35d5eeSXin Li
3514*8c35d5eeSXin Li  def testSectionIndent(self):
3515*8c35d5eeSXin Li    self.TestMultiLineLint(
3516*8c35d5eeSXin Li        """
3517*8c35d5eeSXin Li        class A {
3518*8c35d5eeSXin Li         public:  // no warning
3519*8c35d5eeSXin Li          private:  // warning here
3520*8c35d5eeSXin Li        };""",
3521*8c35d5eeSXin Li        'private: should be indented +1 space inside class A'
3522*8c35d5eeSXin Li        '  [whitespace/indent] [3]')
3523*8c35d5eeSXin Li    self.TestMultiLineLint(
3524*8c35d5eeSXin Li        """
3525*8c35d5eeSXin Li        class B {
3526*8c35d5eeSXin Li         public:  // no warning
3527*8c35d5eeSXin Li          template<> struct C {
3528*8c35d5eeSXin Li            public:    // warning here
3529*8c35d5eeSXin Li           protected:  // no warning
3530*8c35d5eeSXin Li          };
3531*8c35d5eeSXin Li        };""",
3532*8c35d5eeSXin Li        'public: should be indented +1 space inside struct C'
3533*8c35d5eeSXin Li        '  [whitespace/indent] [3]')
3534*8c35d5eeSXin Li    self.TestMultiLineLint(
3535*8c35d5eeSXin Li        """
3536*8c35d5eeSXin Li        struct D {
3537*8c35d5eeSXin Li         };""",
3538*8c35d5eeSXin Li        'Closing brace should be aligned with beginning of struct D'
3539*8c35d5eeSXin Li        '  [whitespace/indent] [3]')
3540*8c35d5eeSXin Li    self.TestMultiLineLint(
3541*8c35d5eeSXin Li        """
3542*8c35d5eeSXin Li         template<typename E> class F {
3543*8c35d5eeSXin Li        };""",
3544*8c35d5eeSXin Li        'Closing brace should be aligned with beginning of class F'
3545*8c35d5eeSXin Li        '  [whitespace/indent] [3]')
3546*8c35d5eeSXin Li    self.TestMultiLineLint(
3547*8c35d5eeSXin Li        """
3548*8c35d5eeSXin Li        class G {
3549*8c35d5eeSXin Li          Q_OBJECT
3550*8c35d5eeSXin Li        public slots:
3551*8c35d5eeSXin Li        signals:
3552*8c35d5eeSXin Li        };""",
3553*8c35d5eeSXin Li        ['public slots: should be indented +1 space inside class G'
3554*8c35d5eeSXin Li         '  [whitespace/indent] [3]',
3555*8c35d5eeSXin Li         'signals: should be indented +1 space inside class G'
3556*8c35d5eeSXin Li         '  [whitespace/indent] [3]'])
3557*8c35d5eeSXin Li    self.TestMultiLineLint(
3558*8c35d5eeSXin Li        """
3559*8c35d5eeSXin Li        class H {
3560*8c35d5eeSXin Li          /* comments */ class I {
3561*8c35d5eeSXin Li           public:  // no warning
3562*8c35d5eeSXin Li            private:  // warning here
3563*8c35d5eeSXin Li          };
3564*8c35d5eeSXin Li        };""",
3565*8c35d5eeSXin Li        'private: should be indented +1 space inside class I'
3566*8c35d5eeSXin Li        '  [whitespace/indent] [3]')
3567*8c35d5eeSXin Li    self.TestMultiLineLint(
3568*8c35d5eeSXin Li        """
3569*8c35d5eeSXin Li        class J
3570*8c35d5eeSXin Li            : public ::K {
3571*8c35d5eeSXin Li         public:  // no warning
3572*8c35d5eeSXin Li          protected:  // warning here
3573*8c35d5eeSXin Li        };""",
3574*8c35d5eeSXin Li        'protected: should be indented +1 space inside class J'
3575*8c35d5eeSXin Li        '  [whitespace/indent] [3]')
3576*8c35d5eeSXin Li    self.TestMultiLineLint(
3577*8c35d5eeSXin Li        """
3578*8c35d5eeSXin Li        class L
3579*8c35d5eeSXin Li            : public M,
3580*8c35d5eeSXin Li              public ::N {
3581*8c35d5eeSXin Li        };""",
3582*8c35d5eeSXin Li        '')
3583*8c35d5eeSXin Li    self.TestMultiLineLint(
3584*8c35d5eeSXin Li        """
3585*8c35d5eeSXin Li        template <class O,
3586*8c35d5eeSXin Li                  class P,
3587*8c35d5eeSXin Li                  class Q,
3588*8c35d5eeSXin Li                  typename R>
3589*8c35d5eeSXin Li        static void Func() {
3590*8c35d5eeSXin Li        }""",
3591*8c35d5eeSXin Li        '')
3592*8c35d5eeSXin Li
3593*8c35d5eeSXin Li  def testConditionals(self):
3594*8c35d5eeSXin Li    self.TestMultiLineLint(
3595*8c35d5eeSXin Li        """
3596*8c35d5eeSXin Li        if (foo)
3597*8c35d5eeSXin Li          goto fail;
3598*8c35d5eeSXin Li          goto fail;""",
3599*8c35d5eeSXin Li        'If/else bodies with multiple statements require braces'
3600*8c35d5eeSXin Li        '  [readability/braces] [4]')
3601*8c35d5eeSXin Li    self.TestMultiLineLint(
3602*8c35d5eeSXin Li        """
3603*8c35d5eeSXin Li        if (foo)
3604*8c35d5eeSXin Li          goto fail; goto fail;""",
3605*8c35d5eeSXin Li        'If/else bodies with multiple statements require braces'
3606*8c35d5eeSXin Li        '  [readability/braces] [4]')
3607*8c35d5eeSXin Li    self.TestMultiLineLint(
3608*8c35d5eeSXin Li        """
3609*8c35d5eeSXin Li        if (foo)
3610*8c35d5eeSXin Li          foo;
3611*8c35d5eeSXin Li        else
3612*8c35d5eeSXin Li          goto fail;
3613*8c35d5eeSXin Li          goto fail;""",
3614*8c35d5eeSXin Li        'If/else bodies with multiple statements require braces'
3615*8c35d5eeSXin Li        '  [readability/braces] [4]')
3616*8c35d5eeSXin Li    self.TestMultiLineLint(
3617*8c35d5eeSXin Li        """
3618*8c35d5eeSXin Li        if (foo) goto fail;
3619*8c35d5eeSXin Li          goto fail;""",
3620*8c35d5eeSXin Li        'If/else bodies with multiple statements require braces'
3621*8c35d5eeSXin Li        '  [readability/braces] [4]')
3622*8c35d5eeSXin Li    self.TestMultiLineLint(
3623*8c35d5eeSXin Li        """
3624*8c35d5eeSXin Li        if (foo)
3625*8c35d5eeSXin Li          if (bar)
3626*8c35d5eeSXin Li            baz;
3627*8c35d5eeSXin Li          else
3628*8c35d5eeSXin Li            qux;""",
3629*8c35d5eeSXin Li        'Else clause should be indented at the same level as if. Ambiguous'
3630*8c35d5eeSXin Li        ' nested if/else chains require braces.  [readability/braces] [4]')
3631*8c35d5eeSXin Li    self.TestMultiLineLint(
3632*8c35d5eeSXin Li        """
3633*8c35d5eeSXin Li        if (foo)
3634*8c35d5eeSXin Li          if (bar)
3635*8c35d5eeSXin Li            baz;
3636*8c35d5eeSXin Li        else
3637*8c35d5eeSXin Li          qux;""",
3638*8c35d5eeSXin Li        'Else clause should be indented at the same level as if. Ambiguous'
3639*8c35d5eeSXin Li        ' nested if/else chains require braces.  [readability/braces] [4]')
3640*8c35d5eeSXin Li    self.TestMultiLineLint(
3641*8c35d5eeSXin Li        """
3642*8c35d5eeSXin Li        if (foo) {
3643*8c35d5eeSXin Li          bar;
3644*8c35d5eeSXin Li          baz;
3645*8c35d5eeSXin Li        } else
3646*8c35d5eeSXin Li          qux;""",
3647*8c35d5eeSXin Li        'If an else has a brace on one side, it should have it on both'
3648*8c35d5eeSXin Li        '  [readability/braces] [5]')
3649*8c35d5eeSXin Li    self.TestMultiLineLint(
3650*8c35d5eeSXin Li        """
3651*8c35d5eeSXin Li        if (foo)
3652*8c35d5eeSXin Li          bar;
3653*8c35d5eeSXin Li        else {
3654*8c35d5eeSXin Li          baz;
3655*8c35d5eeSXin Li        }""",
3656*8c35d5eeSXin Li        'If an else has a brace on one side, it should have it on both'
3657*8c35d5eeSXin Li        '  [readability/braces] [5]')
3658*8c35d5eeSXin Li    self.TestMultiLineLint(
3659*8c35d5eeSXin Li        """
3660*8c35d5eeSXin Li        if (foo)
3661*8c35d5eeSXin Li          bar;
3662*8c35d5eeSXin Li        else if (baz) {
3663*8c35d5eeSXin Li          qux;
3664*8c35d5eeSXin Li        }""",
3665*8c35d5eeSXin Li        'If an else has a brace on one side, it should have it on both'
3666*8c35d5eeSXin Li        '  [readability/braces] [5]')
3667*8c35d5eeSXin Li    self.TestMultiLineLint(
3668*8c35d5eeSXin Li        """
3669*8c35d5eeSXin Li        if (foo) {
3670*8c35d5eeSXin Li          bar;
3671*8c35d5eeSXin Li        } else if (baz)
3672*8c35d5eeSXin Li          qux;""",
3673*8c35d5eeSXin Li        'If an else has a brace on one side, it should have it on both'
3674*8c35d5eeSXin Li        '  [readability/braces] [5]')
3675*8c35d5eeSXin Li    self.TestMultiLineLint(
3676*8c35d5eeSXin Li        """
3677*8c35d5eeSXin Li        if (foo)
3678*8c35d5eeSXin Li          goto fail;
3679*8c35d5eeSXin Li        bar;""",
3680*8c35d5eeSXin Li        '')
3681*8c35d5eeSXin Li    self.TestMultiLineLint(
3682*8c35d5eeSXin Li        """
3683*8c35d5eeSXin Li        if (foo
3684*8c35d5eeSXin Li            && bar) {
3685*8c35d5eeSXin Li          baz;
3686*8c35d5eeSXin Li          qux;
3687*8c35d5eeSXin Li        }""",
3688*8c35d5eeSXin Li        '')
3689*8c35d5eeSXin Li    self.TestMultiLineLint(
3690*8c35d5eeSXin Li        """
3691*8c35d5eeSXin Li        if (foo)
3692*8c35d5eeSXin Li          goto
3693*8c35d5eeSXin Li            fail;""",
3694*8c35d5eeSXin Li        '')
3695*8c35d5eeSXin Li    self.TestMultiLineLint(
3696*8c35d5eeSXin Li        """
3697*8c35d5eeSXin Li        if (foo)
3698*8c35d5eeSXin Li          bar;
3699*8c35d5eeSXin Li        else
3700*8c35d5eeSXin Li          baz;
3701*8c35d5eeSXin Li        qux;""",
3702*8c35d5eeSXin Li        '')
3703*8c35d5eeSXin Li    self.TestMultiLineLint(
3704*8c35d5eeSXin Li        """
3705*8c35d5eeSXin Li        for (;;) {
3706*8c35d5eeSXin Li          if (foo)
3707*8c35d5eeSXin Li            bar;
3708*8c35d5eeSXin Li          else
3709*8c35d5eeSXin Li            baz;
3710*8c35d5eeSXin Li        }""",
3711*8c35d5eeSXin Li        '')
3712*8c35d5eeSXin Li    self.TestMultiLineLint(
3713*8c35d5eeSXin Li        """
3714*8c35d5eeSXin Li        if (foo)
3715*8c35d5eeSXin Li          bar;
3716*8c35d5eeSXin Li        else if (baz)
3717*8c35d5eeSXin Li          baz;""",
3718*8c35d5eeSXin Li        '')
3719*8c35d5eeSXin Li    self.TestMultiLineLint(
3720*8c35d5eeSXin Li        """
3721*8c35d5eeSXin Li        if (foo)
3722*8c35d5eeSXin Li          bar;
3723*8c35d5eeSXin Li        else
3724*8c35d5eeSXin Li          baz;""",
3725*8c35d5eeSXin Li        '')
3726*8c35d5eeSXin Li    self.TestMultiLineLint(
3727*8c35d5eeSXin Li        """
3728*8c35d5eeSXin Li        if (foo) {
3729*8c35d5eeSXin Li          bar;
3730*8c35d5eeSXin Li        } else {
3731*8c35d5eeSXin Li          baz;
3732*8c35d5eeSXin Li        }""",
3733*8c35d5eeSXin Li        '')
3734*8c35d5eeSXin Li    self.TestMultiLineLint(
3735*8c35d5eeSXin Li        """
3736*8c35d5eeSXin Li        if (foo) {
3737*8c35d5eeSXin Li          bar;
3738*8c35d5eeSXin Li        } else if (baz) {
3739*8c35d5eeSXin Li          qux;
3740*8c35d5eeSXin Li        }""",
3741*8c35d5eeSXin Li        '')
3742*8c35d5eeSXin Li    # Note: this is an error for a different reason, but should not trigger the
3743*8c35d5eeSXin Li    # single-line if error.
3744*8c35d5eeSXin Li    self.TestMultiLineLint(
3745*8c35d5eeSXin Li        """
3746*8c35d5eeSXin Li        if (foo)
3747*8c35d5eeSXin Li        {
3748*8c35d5eeSXin Li          bar;
3749*8c35d5eeSXin Li          baz;
3750*8c35d5eeSXin Li        }""",
3751*8c35d5eeSXin Li        '{ should almost always be at the end of the previous line'
3752*8c35d5eeSXin Li        '  [whitespace/braces] [4]')
3753*8c35d5eeSXin Li    self.TestMultiLineLint(
3754*8c35d5eeSXin Li        """
3755*8c35d5eeSXin Li        if (foo) { \\
3756*8c35d5eeSXin Li          bar; \\
3757*8c35d5eeSXin Li          baz; \\
3758*8c35d5eeSXin Li        }""",
3759*8c35d5eeSXin Li        '')
3760*8c35d5eeSXin Li    self.TestMultiLineLint(
3761*8c35d5eeSXin Li        """
3762*8c35d5eeSXin Li        void foo() { if (bar) baz; }""",
3763*8c35d5eeSXin Li        '')
3764*8c35d5eeSXin Li    self.TestMultiLineLint(
3765*8c35d5eeSXin Li        """
3766*8c35d5eeSXin Li        #if foo
3767*8c35d5eeSXin Li          bar;
3768*8c35d5eeSXin Li        #else
3769*8c35d5eeSXin Li          baz;
3770*8c35d5eeSXin Li          qux;
3771*8c35d5eeSXin Li        #endif""",
3772*8c35d5eeSXin Li        '')
3773*8c35d5eeSXin Li    self.TestMultiLineLint(
3774*8c35d5eeSXin Li        """void F() {
3775*8c35d5eeSXin Li          variable = [] { if (true); };
3776*8c35d5eeSXin Li          variable =
3777*8c35d5eeSXin Li              [] { if (true); };
3778*8c35d5eeSXin Li          Call(
3779*8c35d5eeSXin Li              [] { if (true); },
3780*8c35d5eeSXin Li              [] { if (true); });
3781*8c35d5eeSXin Li        }""",
3782*8c35d5eeSXin Li        '')
3783*8c35d5eeSXin Li
3784*8c35d5eeSXin Li  def testTab(self):
3785*8c35d5eeSXin Li    self.TestLint('\tint a;',
3786*8c35d5eeSXin Li                  'Tab found; better to use spaces  [whitespace/tab] [1]')
3787*8c35d5eeSXin Li    self.TestLint('int a = 5;\t\t// set a to 5',
3788*8c35d5eeSXin Li                  'Tab found; better to use spaces  [whitespace/tab] [1]')
3789*8c35d5eeSXin Li
3790*8c35d5eeSXin Li  def testParseArguments(self):
3791*8c35d5eeSXin Li    old_usage = cpplint._USAGE
3792*8c35d5eeSXin Li    old_error_categories = cpplint._ERROR_CATEGORIES
3793*8c35d5eeSXin Li    old_output_format = cpplint._cpplint_state.output_format
3794*8c35d5eeSXin Li    old_verbose_level = cpplint._cpplint_state.verbose_level
3795*8c35d5eeSXin Li    old_headers = cpplint._hpp_headers
3796*8c35d5eeSXin Li    old_filters = cpplint._cpplint_state.filters
3797*8c35d5eeSXin Li    old_line_length = cpplint._line_length
3798*8c35d5eeSXin Li    old_valid_extensions = cpplint._valid_extensions
3799*8c35d5eeSXin Li    try:
3800*8c35d5eeSXin Li      # Don't print usage during the tests, or filter categories
3801*8c35d5eeSXin Li      cpplint._USAGE = ''
3802*8c35d5eeSXin Li      cpplint._ERROR_CATEGORIES = ''
3803*8c35d5eeSXin Li
3804*8c35d5eeSXin Li      self.assertRaises(SystemExit, cpplint.ParseArguments, [])
3805*8c35d5eeSXin Li      self.assertRaises(SystemExit, cpplint.ParseArguments, ['--badopt'])
3806*8c35d5eeSXin Li      self.assertRaises(SystemExit, cpplint.ParseArguments, ['--help'])
3807*8c35d5eeSXin Li      self.assertRaises(SystemExit, cpplint.ParseArguments, ['--v=0'])
3808*8c35d5eeSXin Li      self.assertRaises(SystemExit, cpplint.ParseArguments, ['--filter='])
3809*8c35d5eeSXin Li      # This is illegal because all filters must start with + or -
3810*8c35d5eeSXin Li      self.assertRaises(SystemExit, cpplint.ParseArguments, ['--filter=foo'])
3811*8c35d5eeSXin Li      self.assertRaises(SystemExit, cpplint.ParseArguments,
3812*8c35d5eeSXin Li                        ['--filter=+a,b,-c'])
3813*8c35d5eeSXin Li      self.assertRaises(SystemExit, cpplint.ParseArguments, ['--headers'])
3814*8c35d5eeSXin Li
3815*8c35d5eeSXin Li      self.assertEquals(['foo.cc'], cpplint.ParseArguments(['foo.cc']))
3816*8c35d5eeSXin Li      self.assertEquals(old_output_format, cpplint._cpplint_state.output_format)
3817*8c35d5eeSXin Li      self.assertEquals(old_verbose_level, cpplint._cpplint_state.verbose_level)
3818*8c35d5eeSXin Li
3819*8c35d5eeSXin Li      self.assertEquals(['foo.cc'],
3820*8c35d5eeSXin Li                        cpplint.ParseArguments(['--v=1', 'foo.cc']))
3821*8c35d5eeSXin Li      self.assertEquals(1, cpplint._cpplint_state.verbose_level)
3822*8c35d5eeSXin Li      self.assertEquals(['foo.h'],
3823*8c35d5eeSXin Li                        cpplint.ParseArguments(['--v=3', 'foo.h']))
3824*8c35d5eeSXin Li      self.assertEquals(3, cpplint._cpplint_state.verbose_level)
3825*8c35d5eeSXin Li      self.assertEquals(['foo.cpp'],
3826*8c35d5eeSXin Li                        cpplint.ParseArguments(['--verbose=5', 'foo.cpp']))
3827*8c35d5eeSXin Li      self.assertEquals(5, cpplint._cpplint_state.verbose_level)
3828*8c35d5eeSXin Li      self.assertRaises(ValueError,
3829*8c35d5eeSXin Li                        cpplint.ParseArguments, ['--v=f', 'foo.cc'])
3830*8c35d5eeSXin Li
3831*8c35d5eeSXin Li      self.assertEquals(['foo.cc'],
3832*8c35d5eeSXin Li                        cpplint.ParseArguments(['--output=emacs', 'foo.cc']))
3833*8c35d5eeSXin Li      self.assertEquals('emacs', cpplint._cpplint_state.output_format)
3834*8c35d5eeSXin Li      self.assertEquals(['foo.h'],
3835*8c35d5eeSXin Li                        cpplint.ParseArguments(['--output=vs7', 'foo.h']))
3836*8c35d5eeSXin Li      self.assertEquals('vs7', cpplint._cpplint_state.output_format)
3837*8c35d5eeSXin Li      self.assertRaises(SystemExit,
3838*8c35d5eeSXin Li                        cpplint.ParseArguments, ['--output=blah', 'foo.cc'])
3839*8c35d5eeSXin Li
3840*8c35d5eeSXin Li      filt = '-,+whitespace,-whitespace/indent'
3841*8c35d5eeSXin Li      self.assertEquals(['foo.h'],
3842*8c35d5eeSXin Li                        cpplint.ParseArguments(['--filter='+filt, 'foo.h']))
3843*8c35d5eeSXin Li      self.assertEquals(['-', '+whitespace', '-whitespace/indent'],
3844*8c35d5eeSXin Li                        cpplint._cpplint_state.filters)
3845*8c35d5eeSXin Li
3846*8c35d5eeSXin Li      self.assertEquals(['foo.cc', 'foo.h'],
3847*8c35d5eeSXin Li                        cpplint.ParseArguments(['foo.cc', 'foo.h']))
3848*8c35d5eeSXin Li
3849*8c35d5eeSXin Li      self.assertEqual(['foo.h'],
3850*8c35d5eeSXin Li                       cpplint.ParseArguments(['--linelength=120', 'foo.h']))
3851*8c35d5eeSXin Li      self.assertEqual(120, cpplint._line_length)
3852*8c35d5eeSXin Li
3853*8c35d5eeSXin Li      self.assertEqual(['foo.h'],
3854*8c35d5eeSXin Li                       cpplint.ParseArguments(['--extensions=hpp,cpp,cpp', 'foo.h']))
3855*8c35d5eeSXin Li      self.assertEqual(set(['hpp', 'cpp']), cpplint._valid_extensions)
3856*8c35d5eeSXin Li
3857*8c35d5eeSXin Li      self.assertEqual(set(['h']), cpplint._hpp_headers)  # Default value
3858*8c35d5eeSXin Li      self.assertEqual(['foo.h'],
3859*8c35d5eeSXin Li                       cpplint.ParseArguments(['--extensions=cpp,cpp', '--headers=hpp,h', 'foo.h']))
3860*8c35d5eeSXin Li      self.assertEqual(set(['hpp', 'h']), cpplint._hpp_headers)
3861*8c35d5eeSXin Li      self.assertEqual(set(['hpp', 'h', 'cpp']), cpplint._valid_extensions)
3862*8c35d5eeSXin Li
3863*8c35d5eeSXin Li    finally:
3864*8c35d5eeSXin Li      cpplint._USAGE = old_usage
3865*8c35d5eeSXin Li      cpplint._ERROR_CATEGORIES = old_error_categories
3866*8c35d5eeSXin Li      cpplint._cpplint_state.output_format = old_output_format
3867*8c35d5eeSXin Li      cpplint._cpplint_state.verbose_level = old_verbose_level
3868*8c35d5eeSXin Li      cpplint._cpplint_state.filters = old_filters
3869*8c35d5eeSXin Li      cpplint._line_length = old_line_length
3870*8c35d5eeSXin Li      cpplint._valid_extensions = old_valid_extensions
3871*8c35d5eeSXin Li      cpplint._hpp_headers = old_headers
3872*8c35d5eeSXin Li
3873*8c35d5eeSXin Li  def testLineLength(self):
3874*8c35d5eeSXin Li    old_line_length = cpplint._line_length
3875*8c35d5eeSXin Li    try:
3876*8c35d5eeSXin Li      cpplint._line_length = 80
3877*8c35d5eeSXin Li      self.TestLint(
3878*8c35d5eeSXin Li          '// H %s' % ('H' * 75),
3879*8c35d5eeSXin Li          '')
3880*8c35d5eeSXin Li      self.TestLint(
3881*8c35d5eeSXin Li          '// H %s' % ('H' * 76),
3882*8c35d5eeSXin Li          'Lines should be <= 80 characters long'
3883*8c35d5eeSXin Li          '  [whitespace/line_length] [2]')
3884*8c35d5eeSXin Li      cpplint._line_length = 120
3885*8c35d5eeSXin Li      self.TestLint(
3886*8c35d5eeSXin Li          '// H %s' % ('H' * 115),
3887*8c35d5eeSXin Li          '')
3888*8c35d5eeSXin Li      self.TestLint(
3889*8c35d5eeSXin Li          '// H %s' % ('H' * 116),
3890*8c35d5eeSXin Li          'Lines should be <= 120 characters long'
3891*8c35d5eeSXin Li          '  [whitespace/line_length] [2]')
3892*8c35d5eeSXin Li    finally:
3893*8c35d5eeSXin Li      cpplint._line_length = old_line_length
3894*8c35d5eeSXin Li
3895*8c35d5eeSXin Li  def testFilter(self):
3896*8c35d5eeSXin Li    old_filters = cpplint._cpplint_state.filters
3897*8c35d5eeSXin Li    try:
3898*8c35d5eeSXin Li      cpplint._cpplint_state.SetFilters('-,+whitespace,-whitespace/indent')
3899*8c35d5eeSXin Li      self.TestLint(
3900*8c35d5eeSXin Li          '// Hello there ',
3901*8c35d5eeSXin Li          'Line ends in whitespace.  Consider deleting these extra spaces.'
3902*8c35d5eeSXin Li          '  [whitespace/end_of_line] [4]')
3903*8c35d5eeSXin Li      self.TestLint('int a = (int)1.0;', '')
3904*8c35d5eeSXin Li      self.TestLint(' weird opening space', '')
3905*8c35d5eeSXin Li    finally:
3906*8c35d5eeSXin Li      cpplint._cpplint_state.filters = old_filters
3907*8c35d5eeSXin Li
3908*8c35d5eeSXin Li  def testDefaultFilter(self):
3909*8c35d5eeSXin Li    default_filters = cpplint._DEFAULT_FILTERS
3910*8c35d5eeSXin Li    old_filters = cpplint._cpplint_state.filters
3911*8c35d5eeSXin Li    cpplint._DEFAULT_FILTERS = ['-whitespace']
3912*8c35d5eeSXin Li    try:
3913*8c35d5eeSXin Li      # Reset filters
3914*8c35d5eeSXin Li      cpplint._cpplint_state.SetFilters('')
3915*8c35d5eeSXin Li      self.TestLint('// Hello there ', '')
3916*8c35d5eeSXin Li      cpplint._cpplint_state.SetFilters('+whitespace/end_of_line')
3917*8c35d5eeSXin Li      self.TestLint(
3918*8c35d5eeSXin Li          '// Hello there ',
3919*8c35d5eeSXin Li          'Line ends in whitespace.  Consider deleting these extra spaces.'
3920*8c35d5eeSXin Li          '  [whitespace/end_of_line] [4]')
3921*8c35d5eeSXin Li      self.TestLint(' weird opening space', '')
3922*8c35d5eeSXin Li    finally:
3923*8c35d5eeSXin Li      cpplint._cpplint_state.filters = old_filters
3924*8c35d5eeSXin Li      cpplint._DEFAULT_FILTERS = default_filters
3925*8c35d5eeSXin Li
3926*8c35d5eeSXin Li  def testDuplicateHeader(self):
3927*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
3928*8c35d5eeSXin Li    cpplint.ProcessFileData('path/self.cc', 'cc',
3929*8c35d5eeSXin Li                            ['// Copyright 2014 Your Company. All Rights Reserved.',
3930*8c35d5eeSXin Li                             '#include "path/self.h"',
3931*8c35d5eeSXin Li                             '#include "path/duplicate.h"',
3932*8c35d5eeSXin Li                             '#include "path/duplicate.h"',
3933*8c35d5eeSXin Li                             '#ifdef MACRO',
3934*8c35d5eeSXin Li                             '#include "path/unique.h"',
3935*8c35d5eeSXin Li                             '#else',
3936*8c35d5eeSXin Li                             '#include "path/unique.h"',
3937*8c35d5eeSXin Li                             '#endif',
3938*8c35d5eeSXin Li                             ''],
3939*8c35d5eeSXin Li                            error_collector)
3940*8c35d5eeSXin Li    self.assertEquals(
3941*8c35d5eeSXin Li        ['"path/duplicate.h" already included at path/self.cc:3  '
3942*8c35d5eeSXin Li         '[build/include] [4]'],
3943*8c35d5eeSXin Li        error_collector.ResultList())
3944*8c35d5eeSXin Li
3945*8c35d5eeSXin Li  def testUnnamedNamespacesInHeaders(self):
3946*8c35d5eeSXin Li    self.TestLanguageRulesCheck(
3947*8c35d5eeSXin Li        'foo.h', 'namespace {',
3948*8c35d5eeSXin Li        'Do not use unnamed namespaces in header files.  See'
3949*8c35d5eeSXin Li        ' https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
3950*8c35d5eeSXin Li        ' for more information.  [build/namespaces] [4]')
3951*8c35d5eeSXin Li    # namespace registration macros are OK.
3952*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo.h', 'namespace {  \\', '')
3953*8c35d5eeSXin Li    # named namespaces are OK.
3954*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo.h', 'namespace foo {', '')
3955*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo.h', 'namespace foonamespace {', '')
3956*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo.cc', 'namespace {', '')
3957*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo.cc', 'namespace foo {', '')
3958*8c35d5eeSXin Li
3959*8c35d5eeSXin Li  def testBuildClass(self):
3960*8c35d5eeSXin Li    # Test that the linter can parse to the end of class definitions,
3961*8c35d5eeSXin Li    # and that it will report when it can't.
3962*8c35d5eeSXin Li    # Use multi-line linter because it performs the ClassState check.
3963*8c35d5eeSXin Li    self.TestMultiLineLint(
3964*8c35d5eeSXin Li        'class Foo {',
3965*8c35d5eeSXin Li        'Failed to find complete declaration of class Foo'
3966*8c35d5eeSXin Li        '  [build/class] [5]')
3967*8c35d5eeSXin Li    # Do the same for namespaces
3968*8c35d5eeSXin Li    self.TestMultiLineLint(
3969*8c35d5eeSXin Li        'namespace Foo {',
3970*8c35d5eeSXin Li        'Failed to find complete declaration of namespace Foo'
3971*8c35d5eeSXin Li        '  [build/namespaces] [5]')
3972*8c35d5eeSXin Li    # Don't warn on forward declarations of various types.
3973*8c35d5eeSXin Li    self.TestMultiLineLint(
3974*8c35d5eeSXin Li        'class Foo;',
3975*8c35d5eeSXin Li        '')
3976*8c35d5eeSXin Li    self.TestMultiLineLint(
3977*8c35d5eeSXin Li        """struct Foo*
3978*8c35d5eeSXin Li             foo = NewFoo();""",
3979*8c35d5eeSXin Li        '')
3980*8c35d5eeSXin Li    # Test preprocessor.
3981*8c35d5eeSXin Li    self.TestMultiLineLint(
3982*8c35d5eeSXin Li        """#ifdef DERIVE_FROM_GOO
3983*8c35d5eeSXin Li          struct Foo : public Goo {
3984*8c35d5eeSXin Li        #else
3985*8c35d5eeSXin Li          struct Foo : public Hoo {
3986*8c35d5eeSXin Li        #endif
3987*8c35d5eeSXin Li          };""",
3988*8c35d5eeSXin Li        '')
3989*8c35d5eeSXin Li    self.TestMultiLineLint(
3990*8c35d5eeSXin Li        """
3991*8c35d5eeSXin Li        class Foo
3992*8c35d5eeSXin Li        #ifdef DERIVE_FROM_GOO
3993*8c35d5eeSXin Li          : public Goo {
3994*8c35d5eeSXin Li        #else
3995*8c35d5eeSXin Li          : public Hoo {
3996*8c35d5eeSXin Li        #endif
3997*8c35d5eeSXin Li        };""",
3998*8c35d5eeSXin Li        '')
3999*8c35d5eeSXin Li    # Test incomplete class
4000*8c35d5eeSXin Li    self.TestMultiLineLint(
4001*8c35d5eeSXin Li        'class Foo {',
4002*8c35d5eeSXin Li        'Failed to find complete declaration of class Foo'
4003*8c35d5eeSXin Li        '  [build/class] [5]')
4004*8c35d5eeSXin Li
4005*8c35d5eeSXin Li  def testBuildEndComment(self):
4006*8c35d5eeSXin Li    # The crosstool compiler we currently use will fail to compile the
4007*8c35d5eeSXin Li    # code in this test, so we might consider removing the lint check.
4008*8c35d5eeSXin Li    self.TestMultiLineLint(
4009*8c35d5eeSXin Li        """#if 0
4010*8c35d5eeSXin Li        #endif Not a comment""",
4011*8c35d5eeSXin Li        'Uncommented text after #endif is non-standard.  Use a comment.'
4012*8c35d5eeSXin Li        '  [build/endif_comment] [5]')
4013*8c35d5eeSXin Li
4014*8c35d5eeSXin Li  def testBuildForwardDecl(self):
4015*8c35d5eeSXin Li    # The crosstool compiler we currently use will fail to compile the
4016*8c35d5eeSXin Li    # code in this test, so we might consider removing the lint check.
4017*8c35d5eeSXin Li    self.TestLint('class Foo::Goo;',
4018*8c35d5eeSXin Li                  'Inner-style forward declarations are invalid.'
4019*8c35d5eeSXin Li                  '  Remove this line.'
4020*8c35d5eeSXin Li                  '  [build/forward_decl] [5]')
4021*8c35d5eeSXin Li
4022*8c35d5eeSXin Li  def GetBuildHeaderGuardPreprocessorSymbol(self, file_path):
4023*8c35d5eeSXin Li    # Figure out the expected header guard by processing an empty file.
4024*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4025*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h', [], error_collector)
4026*8c35d5eeSXin Li    for error in error_collector.ResultList():
4027*8c35d5eeSXin Li      matched = re.search(
4028*8c35d5eeSXin Li          'No #ifndef header guard found, suggested CPP variable is: '
4029*8c35d5eeSXin Li          '([A-Z0-9_]+)',
4030*8c35d5eeSXin Li          error)
4031*8c35d5eeSXin Li      if matched is not None:
4032*8c35d5eeSXin Li        return matched.group(1)
4033*8c35d5eeSXin Li
4034*8c35d5eeSXin Li  def testBuildHeaderGuard(self):
4035*8c35d5eeSXin Li    file_path = 'mydir/foo.h'
4036*8c35d5eeSXin Li    expected_guard = self.GetBuildHeaderGuardPreprocessorSymbol(file_path)
4037*8c35d5eeSXin Li    self.assertTrue(re.search('MYDIR_FOO_H_$', expected_guard))
4038*8c35d5eeSXin Li
4039*8c35d5eeSXin Li    # No guard at all: expect one error.
4040*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4041*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h', [], error_collector)
4042*8c35d5eeSXin Li    self.assertEquals(
4043*8c35d5eeSXin Li        1,
4044*8c35d5eeSXin Li        error_collector.ResultList().count(
4045*8c35d5eeSXin Li            'No #ifndef header guard found, suggested CPP variable is: %s'
4046*8c35d5eeSXin Li            '  [build/header_guard] [5]' % expected_guard),
4047*8c35d5eeSXin Li        error_collector.ResultList())
4048*8c35d5eeSXin Li
4049*8c35d5eeSXin Li    # No header guard, but the error is suppressed.
4050*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4051*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h',
4052*8c35d5eeSXin Li                            ['// Copyright 2014 Your Company.',
4053*8c35d5eeSXin Li                             '// NOLINT(build/header_guard)', ''],
4054*8c35d5eeSXin Li                            error_collector)
4055*8c35d5eeSXin Li    self.assertEquals([], error_collector.ResultList())
4056*8c35d5eeSXin Li
4057*8c35d5eeSXin Li    # Wrong guard
4058*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4059*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h',
4060*8c35d5eeSXin Li                            ['#ifndef FOO_H', '#define FOO_H'], error_collector)
4061*8c35d5eeSXin Li    self.assertEquals(
4062*8c35d5eeSXin Li        1,
4063*8c35d5eeSXin Li        error_collector.ResultList().count(
4064*8c35d5eeSXin Li            '#ifndef header guard has wrong style, please use: %s'
4065*8c35d5eeSXin Li            '  [build/header_guard] [5]' % expected_guard),
4066*8c35d5eeSXin Li        error_collector.ResultList())
4067*8c35d5eeSXin Li
4068*8c35d5eeSXin Li    # No define
4069*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4070*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h',
4071*8c35d5eeSXin Li                            ['#ifndef %s' % expected_guard], error_collector)
4072*8c35d5eeSXin Li    self.assertEquals(
4073*8c35d5eeSXin Li        1,
4074*8c35d5eeSXin Li        error_collector.ResultList().count(
4075*8c35d5eeSXin Li            'No #ifndef header guard found, suggested CPP variable is: %s'
4076*8c35d5eeSXin Li            '  [build/header_guard] [5]' % expected_guard),
4077*8c35d5eeSXin Li        error_collector.ResultList())
4078*8c35d5eeSXin Li
4079*8c35d5eeSXin Li    # Mismatched define
4080*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4081*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h',
4082*8c35d5eeSXin Li                            ['#ifndef %s' % expected_guard,
4083*8c35d5eeSXin Li                             '#define FOO_H'],
4084*8c35d5eeSXin Li                            error_collector)
4085*8c35d5eeSXin Li    self.assertEquals(
4086*8c35d5eeSXin Li        1,
4087*8c35d5eeSXin Li        error_collector.ResultList().count(
4088*8c35d5eeSXin Li            'No #ifndef header guard found, suggested CPP variable is: %s'
4089*8c35d5eeSXin Li            '  [build/header_guard] [5]' % expected_guard),
4090*8c35d5eeSXin Li        error_collector.ResultList())
4091*8c35d5eeSXin Li
4092*8c35d5eeSXin Li    # No endif
4093*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4094*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h',
4095*8c35d5eeSXin Li                            ['#ifndef %s' % expected_guard,
4096*8c35d5eeSXin Li                             '#define %s' % expected_guard,
4097*8c35d5eeSXin Li                             ''],
4098*8c35d5eeSXin Li                            error_collector)
4099*8c35d5eeSXin Li    self.assertEquals(
4100*8c35d5eeSXin Li        1,
4101*8c35d5eeSXin Li        error_collector.ResultList().count(
4102*8c35d5eeSXin Li            '#endif line should be "#endif  // %s"'
4103*8c35d5eeSXin Li            '  [build/header_guard] [5]' % expected_guard),
4104*8c35d5eeSXin Li        error_collector.ResultList())
4105*8c35d5eeSXin Li
4106*8c35d5eeSXin Li    # Commentless endif
4107*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4108*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h',
4109*8c35d5eeSXin Li                            ['#ifndef %s' % expected_guard,
4110*8c35d5eeSXin Li                             '#define %s' % expected_guard,
4111*8c35d5eeSXin Li                             '#endif'],
4112*8c35d5eeSXin Li                            error_collector)
4113*8c35d5eeSXin Li    self.assertEquals(
4114*8c35d5eeSXin Li        1,
4115*8c35d5eeSXin Li        error_collector.ResultList().count(
4116*8c35d5eeSXin Li            '#endif line should be "#endif  // %s"'
4117*8c35d5eeSXin Li            '  [build/header_guard] [5]' % expected_guard),
4118*8c35d5eeSXin Li        error_collector.ResultList())
4119*8c35d5eeSXin Li
4120*8c35d5eeSXin Li    # Commentless endif for old-style guard
4121*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4122*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h',
4123*8c35d5eeSXin Li                            ['#ifndef %s_' % expected_guard,
4124*8c35d5eeSXin Li                             '#define %s_' % expected_guard,
4125*8c35d5eeSXin Li                             '#endif'],
4126*8c35d5eeSXin Li                            error_collector)
4127*8c35d5eeSXin Li    self.assertEquals(
4128*8c35d5eeSXin Li        1,
4129*8c35d5eeSXin Li        error_collector.ResultList().count(
4130*8c35d5eeSXin Li            '#endif line should be "#endif  // %s"'
4131*8c35d5eeSXin Li            '  [build/header_guard] [5]' % expected_guard),
4132*8c35d5eeSXin Li        error_collector.ResultList())
4133*8c35d5eeSXin Li
4134*8c35d5eeSXin Li    # No header guard errors
4135*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4136*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h',
4137*8c35d5eeSXin Li                            ['#ifndef %s' % expected_guard,
4138*8c35d5eeSXin Li                             '#define %s' % expected_guard,
4139*8c35d5eeSXin Li                             '#endif  // %s' % expected_guard],
4140*8c35d5eeSXin Li                            error_collector)
4141*8c35d5eeSXin Li    for line in error_collector.ResultList():
4142*8c35d5eeSXin Li      if line.find('build/header_guard') != -1:
4143*8c35d5eeSXin Li        self.fail('Unexpected error: %s' % line)
4144*8c35d5eeSXin Li
4145*8c35d5eeSXin Li    # No header guard errors for old-style guard
4146*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4147*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h',
4148*8c35d5eeSXin Li                            ['#ifndef %s_' % expected_guard,
4149*8c35d5eeSXin Li                             '#define %s_' % expected_guard,
4150*8c35d5eeSXin Li                             '#endif  // %s_' % expected_guard],
4151*8c35d5eeSXin Li                            error_collector)
4152*8c35d5eeSXin Li    for line in error_collector.ResultList():
4153*8c35d5eeSXin Li      if line.find('build/header_guard') != -1:
4154*8c35d5eeSXin Li        self.fail('Unexpected error: %s' % line)
4155*8c35d5eeSXin Li
4156*8c35d5eeSXin Li    old_verbose_level = cpplint._cpplint_state.verbose_level
4157*8c35d5eeSXin Li    try:
4158*8c35d5eeSXin Li      cpplint._cpplint_state.verbose_level = 0
4159*8c35d5eeSXin Li      # Warn on old-style guard if verbosity is 0.
4160*8c35d5eeSXin Li      error_collector = ErrorCollector(self.assert_)
4161*8c35d5eeSXin Li      cpplint.ProcessFileData(file_path, 'h',
4162*8c35d5eeSXin Li                              ['#ifndef %s_' % expected_guard,
4163*8c35d5eeSXin Li                               '#define %s_' % expected_guard,
4164*8c35d5eeSXin Li                               '#endif  // %s_' % expected_guard],
4165*8c35d5eeSXin Li                              error_collector)
4166*8c35d5eeSXin Li      self.assertEquals(
4167*8c35d5eeSXin Li          1,
4168*8c35d5eeSXin Li          error_collector.ResultList().count(
4169*8c35d5eeSXin Li              '#ifndef header guard has wrong style, please use: %s'
4170*8c35d5eeSXin Li              '  [build/header_guard] [0]' % expected_guard),
4171*8c35d5eeSXin Li          error_collector.ResultList())
4172*8c35d5eeSXin Li    finally:
4173*8c35d5eeSXin Li      cpplint._cpplint_state.verbose_level = old_verbose_level
4174*8c35d5eeSXin Li
4175*8c35d5eeSXin Li    # Completely incorrect header guard
4176*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4177*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h',
4178*8c35d5eeSXin Li                            ['#ifndef FOO',
4179*8c35d5eeSXin Li                             '#define FOO',
4180*8c35d5eeSXin Li                             '#endif  // FOO'],
4181*8c35d5eeSXin Li                            error_collector)
4182*8c35d5eeSXin Li    self.assertEquals(
4183*8c35d5eeSXin Li        1,
4184*8c35d5eeSXin Li        error_collector.ResultList().count(
4185*8c35d5eeSXin Li            '#ifndef header guard has wrong style, please use: %s'
4186*8c35d5eeSXin Li            '  [build/header_guard] [5]' % expected_guard),
4187*8c35d5eeSXin Li        error_collector.ResultList())
4188*8c35d5eeSXin Li    self.assertEquals(
4189*8c35d5eeSXin Li        1,
4190*8c35d5eeSXin Li        error_collector.ResultList().count(
4191*8c35d5eeSXin Li            '#endif line should be "#endif  // %s"'
4192*8c35d5eeSXin Li            '  [build/header_guard] [5]' % expected_guard),
4193*8c35d5eeSXin Li        error_collector.ResultList())
4194*8c35d5eeSXin Li
4195*8c35d5eeSXin Li    # incorrect header guard with nolint
4196*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4197*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'h',
4198*8c35d5eeSXin Li                            ['#ifndef FOO  // NOLINT',
4199*8c35d5eeSXin Li                             '#define FOO',
4200*8c35d5eeSXin Li                             '#endif  // FOO NOLINT'],
4201*8c35d5eeSXin Li                            error_collector)
4202*8c35d5eeSXin Li    self.assertEquals(
4203*8c35d5eeSXin Li        0,
4204*8c35d5eeSXin Li        error_collector.ResultList().count(
4205*8c35d5eeSXin Li            '#ifndef header guard has wrong style, please use: %s'
4206*8c35d5eeSXin Li            '  [build/header_guard] [5]' % expected_guard),
4207*8c35d5eeSXin Li        error_collector.ResultList())
4208*8c35d5eeSXin Li    self.assertEquals(
4209*8c35d5eeSXin Li        0,
4210*8c35d5eeSXin Li        error_collector.ResultList().count(
4211*8c35d5eeSXin Li            '#endif line should be "#endif  // %s"'
4212*8c35d5eeSXin Li            '  [build/header_guard] [5]' % expected_guard),
4213*8c35d5eeSXin Li        error_collector.ResultList())
4214*8c35d5eeSXin Li
4215*8c35d5eeSXin Li    # Special case for flymake
4216*8c35d5eeSXin Li    for test_file in ['mydir/foo_flymake.h', 'mydir/.flymake/foo.h']:
4217*8c35d5eeSXin Li      error_collector = ErrorCollector(self.assert_)
4218*8c35d5eeSXin Li      cpplint.ProcessFileData(test_file, 'h',
4219*8c35d5eeSXin Li                              ['// Copyright 2014 Your Company.', ''],
4220*8c35d5eeSXin Li                              error_collector)
4221*8c35d5eeSXin Li      self.assertEquals(
4222*8c35d5eeSXin Li          1,
4223*8c35d5eeSXin Li          error_collector.ResultList().count(
4224*8c35d5eeSXin Li              'No #ifndef header guard found, suggested CPP variable is: %s'
4225*8c35d5eeSXin Li              '  [build/header_guard] [5]' % expected_guard),
4226*8c35d5eeSXin Li          error_collector.ResultList())
4227*8c35d5eeSXin Li
4228*8c35d5eeSXin Li  def testBuildHeaderGuardWithRoot(self):
4229*8c35d5eeSXin Li    # note: Tested file paths must be real, otherwise
4230*8c35d5eeSXin Li    # the repository name lookup will fail.
4231*8c35d5eeSXin Li    file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
4232*8c35d5eeSXin Li                             'cpplint_test_header.h')
4233*8c35d5eeSXin Li    file_info = cpplint.FileInfo(file_path)
4234*8c35d5eeSXin Li    if file_info.FullName() == file_info.RepositoryName():
4235*8c35d5eeSXin Li      # When FileInfo cannot deduce the root directory of the repository,
4236*8c35d5eeSXin Li      # FileInfo.RepositoryName returns the same value as FileInfo.FullName.
4237*8c35d5eeSXin Li      # This can happen when this source file was obtained without .svn or
4238*8c35d5eeSXin Li      # .git directory. (e.g. using 'svn export' or 'git archive').
4239*8c35d5eeSXin Li      # Skip this test in such a case because --root flag makes sense only
4240*8c35d5eeSXin Li      # when the root directory of the repository is properly deduced.
4241*8c35d5eeSXin Li      return
4242*8c35d5eeSXin Li
4243*8c35d5eeSXin Li    self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',
4244*8c35d5eeSXin Li                      cpplint.GetHeaderGuardCPPVariable(file_path))
4245*8c35d5eeSXin Li    #
4246*8c35d5eeSXin Li    # test --root flags:
4247*8c35d5eeSXin Li    #   this changes the cpp header guard prefix
4248*8c35d5eeSXin Li    #
4249*8c35d5eeSXin Li
4250*8c35d5eeSXin Li    # left-strip the header guard by using a root dir inside of the repo dir.
4251*8c35d5eeSXin Li    # relative directory
4252*8c35d5eeSXin Li    cpplint._root = 'cpplint'
4253*8c35d5eeSXin Li    self.assertEquals('CPPLINT_TEST_HEADER_H_',
4254*8c35d5eeSXin Li                      cpplint.GetHeaderGuardCPPVariable(file_path))
4255*8c35d5eeSXin Li
4256*8c35d5eeSXin Li    nested_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
4257*8c35d5eeSXin Li                                    os.path.join('nested',
4258*8c35d5eeSXin Li                                                 'cpplint_test_header.h'))
4259*8c35d5eeSXin Li    cpplint._root = os.path.join('cpplint', 'nested')
4260*8c35d5eeSXin Li    actual = cpplint.GetHeaderGuardCPPVariable(nested_file_path)
4261*8c35d5eeSXin Li    self.assertEquals('CPPLINT_TEST_HEADER_H_',
4262*8c35d5eeSXin Li                      actual)
4263*8c35d5eeSXin Li
4264*8c35d5eeSXin Li    # absolute directory
4265*8c35d5eeSXin Li    # (note that CPPLINT.cfg root=setting is always made absolute)
4266*8c35d5eeSXin Li    cpplint._root = os.path.join(os.path.dirname(os.path.abspath(__file__)))
4267*8c35d5eeSXin Li    self.assertEquals('CPPLINT_TEST_HEADER_H_',
4268*8c35d5eeSXin Li                      cpplint.GetHeaderGuardCPPVariable(file_path))
4269*8c35d5eeSXin Li
4270*8c35d5eeSXin Li    nested_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
4271*8c35d5eeSXin Li                                    os.path.join('nested',
4272*8c35d5eeSXin Li                                                 'cpplint_test_header.h'))
4273*8c35d5eeSXin Li    cpplint._root = os.path.join(os.path.dirname(os.path.abspath(__file__)),
4274*8c35d5eeSXin Li                                 'nested')
4275*8c35d5eeSXin Li    self.assertEquals('CPPLINT_TEST_HEADER_H_',
4276*8c35d5eeSXin Li                      cpplint.GetHeaderGuardCPPVariable(nested_file_path))
4277*8c35d5eeSXin Li
4278*8c35d5eeSXin Li    # --root flag is ignored if an non-existent directory is specified.
4279*8c35d5eeSXin Li    cpplint._root = 'NON_EXISTENT_DIR'
4280*8c35d5eeSXin Li    self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',
4281*8c35d5eeSXin Li                      cpplint.GetHeaderGuardCPPVariable(file_path))
4282*8c35d5eeSXin Li
4283*8c35d5eeSXin Li    # prepend to the header guard by using a root dir that is more outer
4284*8c35d5eeSXin Li    # than the repo dir
4285*8c35d5eeSXin Li
4286*8c35d5eeSXin Li    # (using absolute paths)
4287*8c35d5eeSXin Li    # (note that CPPLINT.cfg root=setting is always made absolute)
4288*8c35d5eeSXin Li    this_files_path = os.path.dirname(os.path.abspath(__file__))
4289*8c35d5eeSXin Li    (styleguide_path, this_files_dir) = os.path.split(this_files_path)
4290*8c35d5eeSXin Li    (styleguide_parent_path, styleguide_dir_name) = os.path.split(styleguide_path)
4291*8c35d5eeSXin Li    # parent dir of styleguide
4292*8c35d5eeSXin Li    cpplint._root = styleguide_parent_path
4293*8c35d5eeSXin Li    self.assertIsNotNone(styleguide_parent_path)
4294*8c35d5eeSXin Li    # do not hardcode the 'styleguide' repository name, it could be anything.
4295*8c35d5eeSXin Li    expected_prefix = re.sub(r'[^a-zA-Z0-9]', '_', styleguide_dir_name).upper() + '_'
4296*8c35d5eeSXin Li    # do not have 'styleguide' repo in '/'
4297*8c35d5eeSXin Li    self.assertEquals('%sCPPLINT_CPPLINT_TEST_HEADER_H_' %(expected_prefix),
4298*8c35d5eeSXin Li                      cpplint.GetHeaderGuardCPPVariable(file_path))
4299*8c35d5eeSXin Li
4300*8c35d5eeSXin Li    # To run the 'relative path' tests, we must be in the directory of this test file.
4301*8c35d5eeSXin Li    cur_dir = os.getcwd()
4302*8c35d5eeSXin Li    os.chdir(this_files_path)
4303*8c35d5eeSXin Li
4304*8c35d5eeSXin Li    # (using relative paths)
4305*8c35d5eeSXin Li    styleguide_rel_path = os.path.relpath(styleguide_path, this_files_path)
4306*8c35d5eeSXin Li    # '..'
4307*8c35d5eeSXin Li    cpplint._root = styleguide_rel_path
4308*8c35d5eeSXin Li    self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',
4309*8c35d5eeSXin Li                      cpplint.GetHeaderGuardCPPVariable(file_path))
4310*8c35d5eeSXin Li
4311*8c35d5eeSXin Li    styleguide_rel_path = os.path.relpath(styleguide_parent_path,
4312*8c35d5eeSXin Li                                          this_files_path) # '../..'
4313*8c35d5eeSXin Li    cpplint._root = styleguide_rel_path
4314*8c35d5eeSXin Li    self.assertEquals('%sCPPLINT_CPPLINT_TEST_HEADER_H_' %(expected_prefix),
4315*8c35d5eeSXin Li                      cpplint.GetHeaderGuardCPPVariable(file_path))
4316*8c35d5eeSXin Li
4317*8c35d5eeSXin Li    cpplint._root = None
4318*8c35d5eeSXin Li
4319*8c35d5eeSXin Li    # Restore previous CWD.
4320*8c35d5eeSXin Li    os.chdir(cur_dir)
4321*8c35d5eeSXin Li
4322*8c35d5eeSXin Li  def testPathSplitToList(self):
4323*8c35d5eeSXin Li    self.assertEquals([''],
4324*8c35d5eeSXin Li                      cpplint.PathSplitToList(os.path.join('')))
4325*8c35d5eeSXin Li
4326*8c35d5eeSXin Li    self.assertEquals(['.'],
4327*8c35d5eeSXin Li                      cpplint.PathSplitToList(os.path.join('.')))
4328*8c35d5eeSXin Li
4329*8c35d5eeSXin Li    self.assertEquals(['..'],
4330*8c35d5eeSXin Li                      cpplint.PathSplitToList(os.path.join('..')))
4331*8c35d5eeSXin Li
4332*8c35d5eeSXin Li    self.assertEquals(['..', 'a', 'b'],
4333*8c35d5eeSXin Li                      cpplint.PathSplitToList(os.path.join('..', 'a', 'b')))
4334*8c35d5eeSXin Li
4335*8c35d5eeSXin Li    self.assertEquals(['a', 'b', 'c', 'd'],
4336*8c35d5eeSXin Li                      cpplint.PathSplitToList(os.path.join('a', 'b', 'c', 'd')))
4337*8c35d5eeSXin Li
4338*8c35d5eeSXin Li  def testBuildInclude(self):
4339*8c35d5eeSXin Li    # Test that include statements have slashes in them.
4340*8c35d5eeSXin Li    self.TestLint('#include "foo.h"',
4341*8c35d5eeSXin Li                  'Include the directory when naming .h files'
4342*8c35d5eeSXin Li                  '  [build/include] [4]')
4343*8c35d5eeSXin Li    self.TestLint('#include "Python.h"', '')
4344*8c35d5eeSXin Li    self.TestLint('#include "lua.h"', '')
4345*8c35d5eeSXin Li
4346*8c35d5eeSXin Li  def testBuildPrintfFormat(self):
4347*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4348*8c35d5eeSXin Li    cpplint.ProcessFileData(
4349*8c35d5eeSXin Li        'foo.cc', 'cc',
4350*8c35d5eeSXin Li        [r'printf("\%%d", value);',
4351*8c35d5eeSXin Li         r'snprintf(buffer, sizeof(buffer), "\[%d", value);',
4352*8c35d5eeSXin Li         r'fprintf(file, "\(%d", value);',
4353*8c35d5eeSXin Li         r'vsnprintf(buffer, sizeof(buffer), "\\\{%d", ap);'],
4354*8c35d5eeSXin Li        error_collector)
4355*8c35d5eeSXin Li    self.assertEquals(
4356*8c35d5eeSXin Li        4,
4357*8c35d5eeSXin Li        error_collector.Results().count(
4358*8c35d5eeSXin Li            '%, [, (, and { are undefined character escapes.  Unescape them.'
4359*8c35d5eeSXin Li            '  [build/printf_format] [3]'))
4360*8c35d5eeSXin Li
4361*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4362*8c35d5eeSXin Li    cpplint.ProcessFileData(
4363*8c35d5eeSXin Li        'foo.cc', 'cc',
4364*8c35d5eeSXin Li        ['// Copyright 2014 Your Company.',
4365*8c35d5eeSXin Li         r'printf("\\%%%d", value);',
4366*8c35d5eeSXin Li         r'printf(R"(\[)");',
4367*8c35d5eeSXin Li         r'printf(R"(\[%s)", R"(\])");',
4368*8c35d5eeSXin Li         ''],
4369*8c35d5eeSXin Li        error_collector)
4370*8c35d5eeSXin Li    self.assertEquals('', error_collector.Results())
4371*8c35d5eeSXin Li
4372*8c35d5eeSXin Li  def testRuntimePrintfFormat(self):
4373*8c35d5eeSXin Li    self.TestLint(
4374*8c35d5eeSXin Li        r'fprintf(file, "%q", value);',
4375*8c35d5eeSXin Li        '%q in format strings is deprecated.  Use %ll instead.'
4376*8c35d5eeSXin Li        '  [runtime/printf_format] [3]')
4377*8c35d5eeSXin Li
4378*8c35d5eeSXin Li    self.TestLint(
4379*8c35d5eeSXin Li        r'aprintf(file, "The number is %12q", value);',
4380*8c35d5eeSXin Li        '%q in format strings is deprecated.  Use %ll instead.'
4381*8c35d5eeSXin Li        '  [runtime/printf_format] [3]')
4382*8c35d5eeSXin Li
4383*8c35d5eeSXin Li    self.TestLint(
4384*8c35d5eeSXin Li        r'printf(file, "The number is" "%-12q", value);',
4385*8c35d5eeSXin Li        '%q in format strings is deprecated.  Use %ll instead.'
4386*8c35d5eeSXin Li        '  [runtime/printf_format] [3]')
4387*8c35d5eeSXin Li
4388*8c35d5eeSXin Li    self.TestLint(
4389*8c35d5eeSXin Li        r'printf(file, "The number is" "%+12q", value);',
4390*8c35d5eeSXin Li        '%q in format strings is deprecated.  Use %ll instead.'
4391*8c35d5eeSXin Li        '  [runtime/printf_format] [3]')
4392*8c35d5eeSXin Li
4393*8c35d5eeSXin Li    self.TestLint(
4394*8c35d5eeSXin Li        r'printf(file, "The number is" "% 12q", value);',
4395*8c35d5eeSXin Li        '%q in format strings is deprecated.  Use %ll instead.'
4396*8c35d5eeSXin Li        '  [runtime/printf_format] [3]')
4397*8c35d5eeSXin Li
4398*8c35d5eeSXin Li    self.TestLint(
4399*8c35d5eeSXin Li        r'snprintf(file, "Never mix %d and %1$d parameters!", value);',
4400*8c35d5eeSXin Li        '%N$ formats are unconventional.  Try rewriting to avoid them.'
4401*8c35d5eeSXin Li        '  [runtime/printf_format] [2]')
4402*8c35d5eeSXin Li
4403*8c35d5eeSXin Li  def TestLintLogCodeOnError(self, code, expected_message):
4404*8c35d5eeSXin Li    # Special TestLint which logs the input code on error.
4405*8c35d5eeSXin Li    result = self.PerformSingleLineLint(code)
4406*8c35d5eeSXin Li    if result != expected_message:
4407*8c35d5eeSXin Li      self.fail('For code: "%s"\nGot: "%s"\nExpected: "%s"'
4408*8c35d5eeSXin Li                % (code, result, expected_message))
4409*8c35d5eeSXin Li
4410*8c35d5eeSXin Li  def testBuildStorageClass(self):
4411*8c35d5eeSXin Li    qualifiers = [None, 'const', 'volatile']
4412*8c35d5eeSXin Li    signs = [None, 'signed', 'unsigned']
4413*8c35d5eeSXin Li    types = ['void', 'char', 'int', 'float', 'double',
4414*8c35d5eeSXin Li             'schar', 'int8', 'uint8', 'int16', 'uint16',
4415*8c35d5eeSXin Li             'int32', 'uint32', 'int64', 'uint64']
4416*8c35d5eeSXin Li    storage_classes = ['extern', 'register', 'static', 'typedef']
4417*8c35d5eeSXin Li
4418*8c35d5eeSXin Li    build_storage_class_error_message = (
4419*8c35d5eeSXin Li        'Storage-class specifier (static, extern, typedef, etc) should be '
4420*8c35d5eeSXin Li        'at the beginning of the declaration.  [build/storage_class] [5]')
4421*8c35d5eeSXin Li
4422*8c35d5eeSXin Li    # Some explicit cases. Legal in C++, deprecated in C99.
4423*8c35d5eeSXin Li    self.TestLint('const int static foo = 5;',
4424*8c35d5eeSXin Li                  build_storage_class_error_message)
4425*8c35d5eeSXin Li
4426*8c35d5eeSXin Li    self.TestLint('char static foo;',
4427*8c35d5eeSXin Li                  build_storage_class_error_message)
4428*8c35d5eeSXin Li
4429*8c35d5eeSXin Li    self.TestLint('double const static foo = 2.0;',
4430*8c35d5eeSXin Li                  build_storage_class_error_message)
4431*8c35d5eeSXin Li
4432*8c35d5eeSXin Li    self.TestLint('uint64 typedef unsigned_long_long;',
4433*8c35d5eeSXin Li                  build_storage_class_error_message)
4434*8c35d5eeSXin Li
4435*8c35d5eeSXin Li    self.TestLint('int register foo = 0;',
4436*8c35d5eeSXin Li                  build_storage_class_error_message)
4437*8c35d5eeSXin Li
4438*8c35d5eeSXin Li    # Since there are a very large number of possibilities, randomly
4439*8c35d5eeSXin Li    # construct declarations.
4440*8c35d5eeSXin Li    # Make sure that the declaration is logged if there's an error.
4441*8c35d5eeSXin Li    # Seed generator with an integer for absolute reproducibility.
4442*8c35d5eeSXin Li    random.seed(25)
4443*8c35d5eeSXin Li    for unused_i in range(10):
4444*8c35d5eeSXin Li      # Build up random list of non-storage-class declaration specs.
4445*8c35d5eeSXin Li      other_decl_specs = [random.choice(qualifiers), random.choice(signs),
4446*8c35d5eeSXin Li                          random.choice(types)]
4447*8c35d5eeSXin Li      # remove None
4448*8c35d5eeSXin Li      other_decl_specs = [x for x in other_decl_specs if x is not None]
4449*8c35d5eeSXin Li
4450*8c35d5eeSXin Li      # shuffle
4451*8c35d5eeSXin Li      random.shuffle(other_decl_specs)
4452*8c35d5eeSXin Li
4453*8c35d5eeSXin Li      # insert storage class after the first
4454*8c35d5eeSXin Li      storage_class = random.choice(storage_classes)
4455*8c35d5eeSXin Li      insertion_point = random.randint(1, len(other_decl_specs))
4456*8c35d5eeSXin Li      decl_specs = (other_decl_specs[0:insertion_point]
4457*8c35d5eeSXin Li                    + [storage_class]
4458*8c35d5eeSXin Li                    + other_decl_specs[insertion_point:])
4459*8c35d5eeSXin Li
4460*8c35d5eeSXin Li      self.TestLintLogCodeOnError(
4461*8c35d5eeSXin Li          ' '.join(decl_specs) + ';',
4462*8c35d5eeSXin Li          build_storage_class_error_message)
4463*8c35d5eeSXin Li
4464*8c35d5eeSXin Li      # but no error if storage class is first
4465*8c35d5eeSXin Li      self.TestLintLogCodeOnError(
4466*8c35d5eeSXin Li          storage_class + ' ' + ' '.join(other_decl_specs),
4467*8c35d5eeSXin Li          '')
4468*8c35d5eeSXin Li
4469*8c35d5eeSXin Li  def testLegalCopyright(self):
4470*8c35d5eeSXin Li    legal_copyright_message = (
4471*8c35d5eeSXin Li        'No copyright message found.  '
4472*8c35d5eeSXin Li        'You should have a line: "Copyright [year] <Copyright Owner>"'
4473*8c35d5eeSXin Li        '  [legal/copyright] [5]')
4474*8c35d5eeSXin Li
4475*8c35d5eeSXin Li    copyright_line = '// Copyright 2014 Google Inc. All Rights Reserved.'
4476*8c35d5eeSXin Li
4477*8c35d5eeSXin Li    file_path = 'mydir/googleclient/foo.cc'
4478*8c35d5eeSXin Li
4479*8c35d5eeSXin Li    # There should be a copyright message in the first 10 lines
4480*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4481*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'cc', [], error_collector)
4482*8c35d5eeSXin Li    self.assertEquals(
4483*8c35d5eeSXin Li        1,
4484*8c35d5eeSXin Li        error_collector.ResultList().count(legal_copyright_message))
4485*8c35d5eeSXin Li
4486*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4487*8c35d5eeSXin Li    cpplint.ProcessFileData(
4488*8c35d5eeSXin Li        file_path, 'cc',
4489*8c35d5eeSXin Li        ['' for unused_i in range(10)] + [copyright_line],
4490*8c35d5eeSXin Li        error_collector)
4491*8c35d5eeSXin Li    self.assertEquals(
4492*8c35d5eeSXin Li        1,
4493*8c35d5eeSXin Li        error_collector.ResultList().count(legal_copyright_message))
4494*8c35d5eeSXin Li
4495*8c35d5eeSXin Li    # Test that warning isn't issued if Copyright line appears early enough.
4496*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4497*8c35d5eeSXin Li    cpplint.ProcessFileData(file_path, 'cc', [copyright_line], error_collector)
4498*8c35d5eeSXin Li    for message in error_collector.ResultList():
4499*8c35d5eeSXin Li      if message.find('legal/copyright') != -1:
4500*8c35d5eeSXin Li        self.fail('Unexpected error: %s' % message)
4501*8c35d5eeSXin Li
4502*8c35d5eeSXin Li    error_collector = ErrorCollector(self.assert_)
4503*8c35d5eeSXin Li    cpplint.ProcessFileData(
4504*8c35d5eeSXin Li        file_path, 'cc',
4505*8c35d5eeSXin Li        ['' for unused_i in range(9)] + [copyright_line],
4506*8c35d5eeSXin Li        error_collector)
4507*8c35d5eeSXin Li    for message in error_collector.ResultList():
4508*8c35d5eeSXin Li      if message.find('legal/copyright') != -1:
4509*8c35d5eeSXin Li        self.fail('Unexpected error: %s' % message)
4510*8c35d5eeSXin Li
4511*8c35d5eeSXin Li  def testInvalidIncrement(self):
4512*8c35d5eeSXin Li    self.TestLint('*count++;',
4513*8c35d5eeSXin Li                  'Changing pointer instead of value (or unused value of '
4514*8c35d5eeSXin Li                  'operator*).  [runtime/invalid_increment] [5]')
4515*8c35d5eeSXin Li
4516*8c35d5eeSXin Li  def testSnprintfSize(self):
4517*8c35d5eeSXin Li    self.TestLint('vsnprintf(NULL, 0, format)', '')
4518*8c35d5eeSXin Li    self.TestLint('snprintf(fisk, 1, format)',
4519*8c35d5eeSXin Li                  'If you can, use sizeof(fisk) instead of 1 as the 2nd arg '
4520*8c35d5eeSXin Li                  'to snprintf.  [runtime/printf] [3]')
4521*8c35d5eeSXin Liclass Cxx11Test(CpplintTestBase):
4522*8c35d5eeSXin Li
4523*8c35d5eeSXin Li  def Helper(self, package, extension, lines, count):
4524*8c35d5eeSXin Li    filename = package + '/foo.' + extension
4525*8c35d5eeSXin Li    lines = lines[:]
4526*8c35d5eeSXin Li
4527*8c35d5eeSXin Li    # Header files need to have an ifdef guard wrapped around their code.
4528*8c35d5eeSXin Li    if extension == 'h':
4529*8c35d5eeSXin Li      guard = filename.upper().replace('/', '_').replace('.', '_') + '_'
4530*8c35d5eeSXin Li      lines.insert(0, '#ifndef ' + guard)
4531*8c35d5eeSXin Li      lines.insert(1, '#define ' + guard)
4532*8c35d5eeSXin Li      lines.append('#endif  // ' + guard)
4533*8c35d5eeSXin Li
4534*8c35d5eeSXin Li    # All files need a final blank line.
4535*8c35d5eeSXin Li    lines.append('')
4536*8c35d5eeSXin Li
4537*8c35d5eeSXin Li    # Process the file and check resulting error count.
4538*8c35d5eeSXin Li    collector = ErrorCollector(self.assert_)
4539*8c35d5eeSXin Li    cpplint.ProcessFileData(filename, extension, lines, collector)
4540*8c35d5eeSXin Li    error_list = collector.ResultList()
4541*8c35d5eeSXin Li    self.assertEquals(count, len(error_list), error_list)
4542*8c35d5eeSXin Li
4543*8c35d5eeSXin Li  def TestCxx11Feature(self, code, expected_error):
4544*8c35d5eeSXin Li    lines = code.split('\n')
4545*8c35d5eeSXin Li    collector = ErrorCollector(self.assert_)
4546*8c35d5eeSXin Li    cpplint.RemoveMultiLineComments('foo.h', lines, collector)
4547*8c35d5eeSXin Li    clean_lines = cpplint.CleansedLines(lines)
4548*8c35d5eeSXin Li    cpplint.FlagCxx11Features('foo.cc', clean_lines, 0, collector)
4549*8c35d5eeSXin Li    self.assertEquals(expected_error, collector.Results())
4550*8c35d5eeSXin Li
4551*8c35d5eeSXin Li  def testBlockedHeaders(self):
4552*8c35d5eeSXin Li    self.TestCxx11Feature('#include <tr1/regex>',
4553*8c35d5eeSXin Li                          'C++ TR1 headers such as <tr1/regex> are '
4554*8c35d5eeSXin Li                          'unapproved.  [build/c++tr1] [5]')
4555*8c35d5eeSXin Li    self.TestCxx11Feature('#include <mutex>',
4556*8c35d5eeSXin Li                          '<mutex> is an unapproved C++11 header.'
4557*8c35d5eeSXin Li                          '  [build/c++11] [5]')
4558*8c35d5eeSXin Li
4559*8c35d5eeSXin Li  def testBlockedClasses(self):
4560*8c35d5eeSXin Li    self.TestCxx11Feature('std::alignment_of<T>',
4561*8c35d5eeSXin Li                          'std::alignment_of is an unapproved '
4562*8c35d5eeSXin Li                          'C++11 class or function.  Send c-style an example '
4563*8c35d5eeSXin Li                          'of where it would make your code more readable, '
4564*8c35d5eeSXin Li                          'and they may let you use it.'
4565*8c35d5eeSXin Li                          '  [build/c++11] [5]')
4566*8c35d5eeSXin Li    self.TestCxx11Feature('std::alignment_offer', '')
4567*8c35d5eeSXin Li    self.TestCxx11Feature('mystd::alignment_of', '')
4568*8c35d5eeSXin Li    self.TestCxx11Feature('std::binomial_distribution', '')
4569*8c35d5eeSXin Li
4570*8c35d5eeSXin Li  def testBlockedFunctions(self):
4571*8c35d5eeSXin Li    self.TestCxx11Feature('std::alignment_of<int>',
4572*8c35d5eeSXin Li                          'std::alignment_of is an unapproved '
4573*8c35d5eeSXin Li                          'C++11 class or function.  Send c-style an example '
4574*8c35d5eeSXin Li                          'of where it would make your code more readable, '
4575*8c35d5eeSXin Li                          'and they may let you use it.'
4576*8c35d5eeSXin Li                          '  [build/c++11] [5]')
4577*8c35d5eeSXin Li    # Missed because of the lack of "std::".  Compiles because ADL
4578*8c35d5eeSXin Li    # looks in the namespace of my_shared_ptr, which (presumably) is
4579*8c35d5eeSXin Li    # std::.  But there will be a lint error somewhere in this file
4580*8c35d5eeSXin Li    # since my_shared_ptr had to be defined.
4581*8c35d5eeSXin Li    self.TestCxx11Feature('static_pointer_cast<Base>(my_shared_ptr)', '')
4582*8c35d5eeSXin Li    self.TestCxx11Feature('std::declval<T>()', '')
4583*8c35d5eeSXin Li
4584*8c35d5eeSXin Li  def testExplicitMakePair(self):
4585*8c35d5eeSXin Li    self.TestLint('make_pair', '')
4586*8c35d5eeSXin Li    self.TestLint('make_pair(42, 42)', '')
4587*8c35d5eeSXin Li    self.TestLint('make_pair<',
4588*8c35d5eeSXin Li                  'For C++11-compatibility, omit template arguments from'
4589*8c35d5eeSXin Li                  ' make_pair OR use pair directly OR if appropriate,'
4590*8c35d5eeSXin Li                  ' construct a pair directly'
4591*8c35d5eeSXin Li                  '  [build/explicit_make_pair] [4]')
4592*8c35d5eeSXin Li    self.TestLint('make_pair <',
4593*8c35d5eeSXin Li                  'For C++11-compatibility, omit template arguments from'
4594*8c35d5eeSXin Li                  ' make_pair OR use pair directly OR if appropriate,'
4595*8c35d5eeSXin Li                  ' construct a pair directly'
4596*8c35d5eeSXin Li                  '  [build/explicit_make_pair] [4]')
4597*8c35d5eeSXin Li    self.TestLint('my_make_pair<int, int>', '')
4598*8c35d5eeSXin Li
4599*8c35d5eeSXin Liclass Cxx14Test(CpplintTestBase):
4600*8c35d5eeSXin Li
4601*8c35d5eeSXin Li  def TestCxx14Feature(self, code, expected_error):
4602*8c35d5eeSXin Li    lines = code.split('\n')
4603*8c35d5eeSXin Li    collector = ErrorCollector(self.assert_)
4604*8c35d5eeSXin Li    cpplint.RemoveMultiLineComments('foo.h', lines, collector)
4605*8c35d5eeSXin Li    clean_lines = cpplint.CleansedLines(lines)
4606*8c35d5eeSXin Li    cpplint.FlagCxx14Features('foo.cc', clean_lines, 0, collector)
4607*8c35d5eeSXin Li    self.assertEquals(expected_error, collector.Results())
4608*8c35d5eeSXin Li
4609*8c35d5eeSXin Li  def testBlockedHeaders(self):
4610*8c35d5eeSXin Li    self.TestCxx14Feature('#include <scoped_allocator>',
4611*8c35d5eeSXin Li                          '<scoped_allocator> is an unapproved C++14 header.'
4612*8c35d5eeSXin Li                           '  [build/c++14] [5]')
4613*8c35d5eeSXin Li    self.TestCxx14Feature('#include <shared_mutex>',
4614*8c35d5eeSXin Li                          '<shared_mutex> is an unapproved C++14 header.'
4615*8c35d5eeSXin Li                          '  [build/c++14] [5]')
4616*8c35d5eeSXin Li
4617*8c35d5eeSXin Li
4618*8c35d5eeSXin Liclass CleansedLinesTest(unittest.TestCase):
4619*8c35d5eeSXin Li
4620*8c35d5eeSXin Li  def testInit(self):
4621*8c35d5eeSXin Li    lines = ['Line 1',
4622*8c35d5eeSXin Li             'Line 2',
4623*8c35d5eeSXin Li             'Line 3 // Comment test',
4624*8c35d5eeSXin Li             'Line 4 /* Comment test */',
4625*8c35d5eeSXin Li             'Line 5 "foo"']
4626*8c35d5eeSXin Li
4627*8c35d5eeSXin Li    clean_lines = cpplint.CleansedLines(lines)
4628*8c35d5eeSXin Li    self.assertEquals(lines, clean_lines.raw_lines)
4629*8c35d5eeSXin Li    self.assertEquals(5, clean_lines.NumLines())
4630*8c35d5eeSXin Li
4631*8c35d5eeSXin Li    self.assertEquals(['Line 1',
4632*8c35d5eeSXin Li                       'Line 2',
4633*8c35d5eeSXin Li                       'Line 3',
4634*8c35d5eeSXin Li                       'Line 4',
4635*8c35d5eeSXin Li                       'Line 5 "foo"'],
4636*8c35d5eeSXin Li                      clean_lines.lines)
4637*8c35d5eeSXin Li
4638*8c35d5eeSXin Li    self.assertEquals(['Line 1',
4639*8c35d5eeSXin Li                       'Line 2',
4640*8c35d5eeSXin Li                       'Line 3',
4641*8c35d5eeSXin Li                       'Line 4',
4642*8c35d5eeSXin Li                       'Line 5 ""'],
4643*8c35d5eeSXin Li                      clean_lines.elided)
4644*8c35d5eeSXin Li
4645*8c35d5eeSXin Li  def testInitEmpty(self):
4646*8c35d5eeSXin Li    clean_lines = cpplint.CleansedLines([])
4647*8c35d5eeSXin Li    self.assertEquals([], clean_lines.raw_lines)
4648*8c35d5eeSXin Li    self.assertEquals(0, clean_lines.NumLines())
4649*8c35d5eeSXin Li
4650*8c35d5eeSXin Li  def testCollapseStrings(self):
4651*8c35d5eeSXin Li    collapse = cpplint.CleansedLines._CollapseStrings
4652*8c35d5eeSXin Li    self.assertEquals('""', collapse('""'))             # ""     (empty)
4653*8c35d5eeSXin Li    self.assertEquals('"""', collapse('"""'))           # """    (bad)
4654*8c35d5eeSXin Li    self.assertEquals('""', collapse('"xyz"'))          # "xyz"  (string)
4655*8c35d5eeSXin Li    self.assertEquals('""', collapse('"\\\""'))         # "\""   (string)
4656*8c35d5eeSXin Li    self.assertEquals('""', collapse('"\'"'))           # "'"    (string)
4657*8c35d5eeSXin Li    self.assertEquals('"\"', collapse('"\"'))           # "\"    (bad)
4658*8c35d5eeSXin Li    self.assertEquals('""', collapse('"\\\\"'))         # "\\"   (string)
4659*8c35d5eeSXin Li    self.assertEquals('"', collapse('"\\\\\\"'))        # "\\\"  (bad)
4660*8c35d5eeSXin Li    self.assertEquals('""', collapse('"\\\\\\\\"'))     # "\\\\" (string)
4661*8c35d5eeSXin Li
4662*8c35d5eeSXin Li    self.assertEquals('\'\'', collapse('\'\''))         # ''     (empty)
4663*8c35d5eeSXin Li    self.assertEquals('\'\'', collapse('\'a\''))        # 'a'    (char)
4664*8c35d5eeSXin Li    self.assertEquals('\'\'', collapse('\'\\\'\''))     # '\''   (char)
4665*8c35d5eeSXin Li    self.assertEquals('\'', collapse('\'\\\''))         # '\'    (bad)
4666*8c35d5eeSXin Li    self.assertEquals('', collapse('\\012'))            # '\012' (char)
4667*8c35d5eeSXin Li    self.assertEquals('', collapse('\\xfF0'))           # '\xfF0' (char)
4668*8c35d5eeSXin Li    self.assertEquals('', collapse('\\n'))              # '\n' (char)
4669*8c35d5eeSXin Li    self.assertEquals(r'\#', collapse('\\#'))           # '\#' (bad)
4670*8c35d5eeSXin Li
4671*8c35d5eeSXin Li    self.assertEquals('"" + ""', collapse('"\'" + "\'"'))
4672*8c35d5eeSXin Li    self.assertEquals("'', ''", collapse("'\"', '\"'"))
4673*8c35d5eeSXin Li    self.assertEquals('""[0b10]', collapse('"a\'b"[0b1\'0]'))
4674*8c35d5eeSXin Li
4675*8c35d5eeSXin Li    self.assertEquals('42', collapse("4'2"))
4676*8c35d5eeSXin Li    self.assertEquals('0b0101', collapse("0b0'1'0'1"))
4677*8c35d5eeSXin Li    self.assertEquals('1048576', collapse("1'048'576"))
4678*8c35d5eeSXin Li    self.assertEquals('0X100000', collapse("0X10'0000"))
4679*8c35d5eeSXin Li    self.assertEquals('0004000000', collapse("0'004'000'000"))
4680*8c35d5eeSXin Li    self.assertEquals('1.602176565e-19', collapse("1.602'176'565e-19"))
4681*8c35d5eeSXin Li    self.assertEquals('\'\' + 0xffff', collapse("'i' + 0xf'f'f'f"))
4682*8c35d5eeSXin Li    self.assertEquals('sizeof\'\' == 1', collapse("sizeof'x' == 1"))
4683*8c35d5eeSXin Li    self.assertEquals('0x.03p100', collapse('0x.0\'3p1\'0\'0'))
4684*8c35d5eeSXin Li    self.assertEquals('123.45', collapse('1\'23.4\'5'))
4685*8c35d5eeSXin Li
4686*8c35d5eeSXin Li    self.assertEquals('StringReplace(body, "", "");',
4687*8c35d5eeSXin Li                      collapse('StringReplace(body, "\\\\", "\\\\\\\\");'))
4688*8c35d5eeSXin Li    self.assertEquals('\'\' ""',
4689*8c35d5eeSXin Li                      collapse('\'"\' "foo"'))
4690*8c35d5eeSXin Li
4691*8c35d5eeSXin Li
4692*8c35d5eeSXin Liclass OrderOfIncludesTest(CpplintTestBase):
4693*8c35d5eeSXin Li
4694*8c35d5eeSXin Li  def setUp(self):
4695*8c35d5eeSXin Li    CpplintTestBase.setUp(self)
4696*8c35d5eeSXin Li    self.include_state = cpplint._IncludeState()
4697*8c35d5eeSXin Li    os.path.abspath = lambda value: value
4698*8c35d5eeSXin Li
4699*8c35d5eeSXin Li  def testCheckNextIncludeOrder_OtherThenCpp(self):
4700*8c35d5eeSXin Li    self.assertEqual('', self.include_state.CheckNextIncludeOrder(
4701*8c35d5eeSXin Li        cpplint._OTHER_HEADER))
4702*8c35d5eeSXin Li    self.assertEqual('Found C++ system header after other header',
4703*8c35d5eeSXin Li                     self.include_state.CheckNextIncludeOrder(
4704*8c35d5eeSXin Li                         cpplint._CPP_SYS_HEADER))
4705*8c35d5eeSXin Li
4706*8c35d5eeSXin Li  def testCheckNextIncludeOrder_CppThenC(self):
4707*8c35d5eeSXin Li    self.assertEqual('', self.include_state.CheckNextIncludeOrder(
4708*8c35d5eeSXin Li        cpplint._CPP_SYS_HEADER))
4709*8c35d5eeSXin Li    self.assertEqual('Found C system header after C++ system header',
4710*8c35d5eeSXin Li                     self.include_state.CheckNextIncludeOrder(
4711*8c35d5eeSXin Li                         cpplint._C_SYS_HEADER))
4712*8c35d5eeSXin Li
4713*8c35d5eeSXin Li  def testCheckNextIncludeOrder_LikelyThenCpp(self):
4714*8c35d5eeSXin Li    self.assertEqual('', self.include_state.CheckNextIncludeOrder(
4715*8c35d5eeSXin Li        cpplint._LIKELY_MY_HEADER))
4716*8c35d5eeSXin Li    self.assertEqual('', self.include_state.CheckNextIncludeOrder(
4717*8c35d5eeSXin Li        cpplint._CPP_SYS_HEADER))
4718*8c35d5eeSXin Li
4719*8c35d5eeSXin Li  def testCheckNextIncludeOrder_PossibleThenCpp(self):
4720*8c35d5eeSXin Li    self.assertEqual('', self.include_state.CheckNextIncludeOrder(
4721*8c35d5eeSXin Li        cpplint._POSSIBLE_MY_HEADER))
4722*8c35d5eeSXin Li    self.assertEqual('', self.include_state.CheckNextIncludeOrder(
4723*8c35d5eeSXin Li        cpplint._CPP_SYS_HEADER))
4724*8c35d5eeSXin Li
4725*8c35d5eeSXin Li  def testCheckNextIncludeOrder_CppThenLikely(self):
4726*8c35d5eeSXin Li    self.assertEqual('', self.include_state.CheckNextIncludeOrder(
4727*8c35d5eeSXin Li        cpplint._CPP_SYS_HEADER))
4728*8c35d5eeSXin Li    # This will eventually fail.
4729*8c35d5eeSXin Li    self.assertEqual('', self.include_state.CheckNextIncludeOrder(
4730*8c35d5eeSXin Li        cpplint._LIKELY_MY_HEADER))
4731*8c35d5eeSXin Li
4732*8c35d5eeSXin Li  def testCheckNextIncludeOrder_CppThenPossible(self):
4733*8c35d5eeSXin Li    self.assertEqual('', self.include_state.CheckNextIncludeOrder(
4734*8c35d5eeSXin Li        cpplint._CPP_SYS_HEADER))
4735*8c35d5eeSXin Li    self.assertEqual('', self.include_state.CheckNextIncludeOrder(
4736*8c35d5eeSXin Li        cpplint._POSSIBLE_MY_HEADER))
4737*8c35d5eeSXin Li
4738*8c35d5eeSXin Li  def testClassifyInclude(self):
4739*8c35d5eeSXin Li    file_info = cpplint.FileInfo
4740*8c35d5eeSXin Li    classify_include = cpplint._ClassifyInclude
4741*8c35d5eeSXin Li    self.assertEqual(cpplint._C_SYS_HEADER,
4742*8c35d5eeSXin Li                     classify_include(file_info('foo/foo.cc'),
4743*8c35d5eeSXin Li                                      'stdio.h',
4744*8c35d5eeSXin Li                                      True))
4745*8c35d5eeSXin Li    self.assertEqual(cpplint._CPP_SYS_HEADER,
4746*8c35d5eeSXin Li                     classify_include(file_info('foo/foo.cc'),
4747*8c35d5eeSXin Li                                      'string',
4748*8c35d5eeSXin Li                                      True))
4749*8c35d5eeSXin Li    self.assertEqual(cpplint._CPP_SYS_HEADER,
4750*8c35d5eeSXin Li                     classify_include(file_info('foo/foo.cc'),
4751*8c35d5eeSXin Li                                      'typeinfo',
4752*8c35d5eeSXin Li                                      True))
4753*8c35d5eeSXin Li    self.assertEqual(cpplint._OTHER_HEADER,
4754*8c35d5eeSXin Li                     classify_include(file_info('foo/foo.cc'),
4755*8c35d5eeSXin Li                                      'string',
4756*8c35d5eeSXin Li                                      False))
4757*8c35d5eeSXin Li
4758*8c35d5eeSXin Li    self.assertEqual(cpplint._LIKELY_MY_HEADER,
4759*8c35d5eeSXin Li                     classify_include(file_info('foo/foo.cc'),
4760*8c35d5eeSXin Li                                      'foo/foo-inl.h',
4761*8c35d5eeSXin Li                                      False))
4762*8c35d5eeSXin Li    self.assertEqual(cpplint._LIKELY_MY_HEADER,
4763*8c35d5eeSXin Li                     classify_include(file_info('foo/internal/foo.cc'),
4764*8c35d5eeSXin Li                                      'foo/public/foo.h',
4765*8c35d5eeSXin Li                                      False))
4766*8c35d5eeSXin Li    self.assertEqual(cpplint._POSSIBLE_MY_HEADER,
4767*8c35d5eeSXin Li                     classify_include(file_info('foo/internal/foo.cc'),
4768*8c35d5eeSXin Li                                      'foo/other/public/foo.h',
4769*8c35d5eeSXin Li                                      False))
4770*8c35d5eeSXin Li    self.assertEqual(cpplint._OTHER_HEADER,
4771*8c35d5eeSXin Li                     classify_include(file_info('foo/internal/foo.cc'),
4772*8c35d5eeSXin Li                                      'foo/other/public/foop.h',
4773*8c35d5eeSXin Li                                      False))
4774*8c35d5eeSXin Li
4775*8c35d5eeSXin Li  def testTryDropCommonSuffixes(self):
4776*8c35d5eeSXin Li    self.assertEqual('foo/foo', cpplint._DropCommonSuffixes('foo/foo-inl.h'))
4777*8c35d5eeSXin Li    self.assertEqual('foo/bar/foo',
4778*8c35d5eeSXin Li                     cpplint._DropCommonSuffixes('foo/bar/foo_inl.h'))
4779*8c35d5eeSXin Li    self.assertEqual('foo/foo', cpplint._DropCommonSuffixes('foo/foo.cc'))
4780*8c35d5eeSXin Li    self.assertEqual('foo/foo_unusualinternal',
4781*8c35d5eeSXin Li                     cpplint._DropCommonSuffixes('foo/foo_unusualinternal.h'))
4782*8c35d5eeSXin Li    self.assertEqual('',
4783*8c35d5eeSXin Li                     cpplint._DropCommonSuffixes('_test.cc'))
4784*8c35d5eeSXin Li    self.assertEqual('test',
4785*8c35d5eeSXin Li                     cpplint._DropCommonSuffixes('test.cc'))
4786*8c35d5eeSXin Li
4787*8c35d5eeSXin Li  def testRegression(self):
4788*8c35d5eeSXin Li    def Format(includes):
4789*8c35d5eeSXin Li      include_list = []
4790*8c35d5eeSXin Li      for item in includes:
4791*8c35d5eeSXin Li        if item.startswith('"') or item.startswith('<'):
4792*8c35d5eeSXin Li          include_list.append('#include %s\n' % item)
4793*8c35d5eeSXin Li        else:
4794*8c35d5eeSXin Li          include_list.append(item + '\n')
4795*8c35d5eeSXin Li      return ''.join(include_list)
4796*8c35d5eeSXin Li
4797*8c35d5eeSXin Li    # Test singleton cases first.
4798*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/foo.cc', Format(['"foo/foo.h"']), '')
4799*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/foo.cc', Format(['<stdio.h>']), '')
4800*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/foo.cc', Format(['<string>']), '')
4801*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/foo.cc', Format(['"foo/foo-inl.h"']), '')
4802*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/foo.cc', Format(['"bar/bar-inl.h"']), '')
4803*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/foo.cc', Format(['"bar/bar.h"']), '')
4804*8c35d5eeSXin Li
4805*8c35d5eeSXin Li    # Test everything in a good and new order.
4806*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/foo.cc',
4807*8c35d5eeSXin Li                                Format(['"foo/foo.h"',
4808*8c35d5eeSXin Li                                        '"foo/foo-inl.h"',
4809*8c35d5eeSXin Li                                        '<stdio.h>',
4810*8c35d5eeSXin Li                                        '<string>',
4811*8c35d5eeSXin Li                                        '<unordered_map>',
4812*8c35d5eeSXin Li                                        '"bar/bar-inl.h"',
4813*8c35d5eeSXin Li                                        '"bar/bar.h"']),
4814*8c35d5eeSXin Li                                '')
4815*8c35d5eeSXin Li
4816*8c35d5eeSXin Li    # Test bad orders.
4817*8c35d5eeSXin Li    self.TestLanguageRulesCheck(
4818*8c35d5eeSXin Li        'foo/foo.cc',
4819*8c35d5eeSXin Li        Format(['<string>', '<stdio.h>']),
4820*8c35d5eeSXin Li        'Found C system header after C++ system header.'
4821*8c35d5eeSXin Li        ' Should be: foo.h, c system, c++ system, other.'
4822*8c35d5eeSXin Li        '  [build/include_order] [4]')
4823*8c35d5eeSXin Li    self.TestLanguageRulesCheck(
4824*8c35d5eeSXin Li        'foo/foo.cc',
4825*8c35d5eeSXin Li        Format(['"foo/bar-inl.h"',
4826*8c35d5eeSXin Li                '"foo/foo-inl.h"']),
4827*8c35d5eeSXin Li        '')
4828*8c35d5eeSXin Li    self.TestLanguageRulesCheck(
4829*8c35d5eeSXin Li        'foo/foo.cc',
4830*8c35d5eeSXin Li        Format(['"foo/e.h"',
4831*8c35d5eeSXin Li                '"foo/b.h"',  # warning here (e>b)
4832*8c35d5eeSXin Li                '"foo/c.h"',
4833*8c35d5eeSXin Li                '"foo/d.h"',
4834*8c35d5eeSXin Li                '"foo/a.h"']),  # warning here (d>a)
4835*8c35d5eeSXin Li        ['Include "foo/b.h" not in alphabetical order'
4836*8c35d5eeSXin Li         '  [build/include_alpha] [4]',
4837*8c35d5eeSXin Li         'Include "foo/a.h" not in alphabetical order'
4838*8c35d5eeSXin Li         '  [build/include_alpha] [4]'])
4839*8c35d5eeSXin Li    # -inl.h headers are no longer special.
4840*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/foo.cc',
4841*8c35d5eeSXin Li                                Format(['"foo/foo-inl.h"', '<string>']),
4842*8c35d5eeSXin Li                                '')
4843*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/foo.cc',
4844*8c35d5eeSXin Li                                Format(['"foo/bar.h"', '"foo/bar-inl.h"']),
4845*8c35d5eeSXin Li                                '')
4846*8c35d5eeSXin Li    # Test componentized header.  OK to have my header in ../public dir.
4847*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/internal/foo.cc',
4848*8c35d5eeSXin Li                                Format(['"foo/public/foo.h"', '<string>']),
4849*8c35d5eeSXin Li                                '')
4850*8c35d5eeSXin Li    # OK to have my header in other dir (not stylistically, but
4851*8c35d5eeSXin Li    # cpplint isn't as good as a human).
4852*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/internal/foo.cc',
4853*8c35d5eeSXin Li                                Format(['"foo/other/public/foo.h"',
4854*8c35d5eeSXin Li                                        '<string>']),
4855*8c35d5eeSXin Li                                '')
4856*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/foo.cc',
4857*8c35d5eeSXin Li                                Format(['"foo/foo.h"',
4858*8c35d5eeSXin Li                                        '<string>',
4859*8c35d5eeSXin Li                                        '"base/google.h"',
4860*8c35d5eeSXin Li                                        '"base/flags.h"']),
4861*8c35d5eeSXin Li                                'Include "base/flags.h" not in alphabetical '
4862*8c35d5eeSXin Li                                'order  [build/include_alpha] [4]')
4863*8c35d5eeSXin Li    # According to the style, -inl.h should come before .h, but we don't
4864*8c35d5eeSXin Li    # complain about that.
4865*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/foo.cc',
4866*8c35d5eeSXin Li                                Format(['"foo/foo-inl.h"',
4867*8c35d5eeSXin Li                                        '"foo/foo.h"',
4868*8c35d5eeSXin Li                                        '"base/google.h"',
4869*8c35d5eeSXin Li                                        '"base/google-inl.h"']),
4870*8c35d5eeSXin Li                                '')
4871*8c35d5eeSXin Li    # Allow project includes to be separated by blank lines
4872*8c35d5eeSXin Li    self.TestLanguageRulesCheck('a/a.cc',
4873*8c35d5eeSXin Li                                Format(['"a/a.h"',
4874*8c35d5eeSXin Li                                        '<string>',
4875*8c35d5eeSXin Li                                        '"base/google.h"',
4876*8c35d5eeSXin Li                                        '',
4877*8c35d5eeSXin Li                                        '"b/c.h"',
4878*8c35d5eeSXin Li                                        '',
4879*8c35d5eeSXin Li                                        'MACRO',
4880*8c35d5eeSXin Li                                        '"a/b.h"']),
4881*8c35d5eeSXin Li                                '')
4882*8c35d5eeSXin Li    self.TestLanguageRulesCheck('a/a.cc',
4883*8c35d5eeSXin Li                                Format(['"a/a.h"',
4884*8c35d5eeSXin Li                                        '<string>',
4885*8c35d5eeSXin Li                                        '"base/google.h"',
4886*8c35d5eeSXin Li                                        '"a/b.h"']),
4887*8c35d5eeSXin Li                                'Include "a/b.h" not in alphabetical '
4888*8c35d5eeSXin Li                                'order  [build/include_alpha] [4]')
4889*8c35d5eeSXin Li
4890*8c35d5eeSXin Li    # Test conditional includes
4891*8c35d5eeSXin Li    self.TestLanguageRulesCheck(
4892*8c35d5eeSXin Li        'a/a.cc',
4893*8c35d5eeSXin Li        ''.join(['#include <string.h>\n',
4894*8c35d5eeSXin Li                 '#include "base/port.h"\n',
4895*8c35d5eeSXin Li                 '#include <initializer_list>\n']),
4896*8c35d5eeSXin Li        ('Found C++ system header after other header. '
4897*8c35d5eeSXin Li         'Should be: a.h, c system, c++ system, other.  '
4898*8c35d5eeSXin Li         '[build/include_order] [4]'))
4899*8c35d5eeSXin Li    self.TestLanguageRulesCheck(
4900*8c35d5eeSXin Li        'a/a.cc',
4901*8c35d5eeSXin Li        ''.join(['#include <string.h>\n',
4902*8c35d5eeSXin Li                 '#include "base/port.h"\n',
4903*8c35d5eeSXin Li                 '#ifdef LANG_CXX11\n',
4904*8c35d5eeSXin Li                 '#include <initializer_list>\n',
4905*8c35d5eeSXin Li                 '#endif  // LANG_CXX11\n']),
4906*8c35d5eeSXin Li        '')
4907*8c35d5eeSXin Li    self.TestLanguageRulesCheck(
4908*8c35d5eeSXin Li        'a/a.cc',
4909*8c35d5eeSXin Li        ''.join(['#include <string.h>\n',
4910*8c35d5eeSXin Li                 '#ifdef LANG_CXX11\n',
4911*8c35d5eeSXin Li                 '#include "base/port.h"\n',
4912*8c35d5eeSXin Li                 '#include <initializer_list>\n',
4913*8c35d5eeSXin Li                 '#endif  // LANG_CXX11\n']),
4914*8c35d5eeSXin Li        ('Found C++ system header after other header. '
4915*8c35d5eeSXin Li         'Should be: a.h, c system, c++ system, other.  '
4916*8c35d5eeSXin Li         '[build/include_order] [4]'))
4917*8c35d5eeSXin Li
4918*8c35d5eeSXin Li    # Third party headers are exempt from order checks
4919*8c35d5eeSXin Li    self.TestLanguageRulesCheck('foo/foo.cc',
4920*8c35d5eeSXin Li                                Format(['<string>', '"Python.h"', '<vector>']),
4921*8c35d5eeSXin Li                                '')
4922*8c35d5eeSXin Li
4923*8c35d5eeSXin Li
4924*8c35d5eeSXin Liclass CheckForFunctionLengthsTest(CpplintTestBase):
4925*8c35d5eeSXin Li
4926*8c35d5eeSXin Li  def setUp(self):
4927*8c35d5eeSXin Li    # Reducing these thresholds for the tests speeds up tests significantly.
4928*8c35d5eeSXin Li    self.old_normal_trigger = cpplint._FunctionState._NORMAL_TRIGGER
4929*8c35d5eeSXin Li    self.old_test_trigger = cpplint._FunctionState._TEST_TRIGGER
4930*8c35d5eeSXin Li
4931*8c35d5eeSXin Li    cpplint._FunctionState._NORMAL_TRIGGER = 10
4932*8c35d5eeSXin Li    cpplint._FunctionState._TEST_TRIGGER = 25
4933*8c35d5eeSXin Li
4934*8c35d5eeSXin Li  def tearDown(self):
4935*8c35d5eeSXin Li    cpplint._FunctionState._NORMAL_TRIGGER = self.old_normal_trigger
4936*8c35d5eeSXin Li    cpplint._FunctionState._TEST_TRIGGER = self.old_test_trigger
4937*8c35d5eeSXin Li
4938*8c35d5eeSXin Li  def TestFunctionLengthsCheck(self, code, expected_message):
4939*8c35d5eeSXin Li    """Check warnings for long function bodies are as expected.
4940*8c35d5eeSXin Li
4941*8c35d5eeSXin Li    Args:
4942*8c35d5eeSXin Li      code: C++ source code expected to generate a warning message.
4943*8c35d5eeSXin Li      expected_message: Message expected to be generated by the C++ code.
4944*8c35d5eeSXin Li    """
4945*8c35d5eeSXin Li    self.assertEquals(expected_message,
4946*8c35d5eeSXin Li                      self.PerformFunctionLengthsCheck(code))
4947*8c35d5eeSXin Li
4948*8c35d5eeSXin Li  def TriggerLines(self, error_level):
4949*8c35d5eeSXin Li    """Return number of lines needed to trigger a function length warning.
4950*8c35d5eeSXin Li
4951*8c35d5eeSXin Li    Args:
4952*8c35d5eeSXin Li      error_level: --v setting for cpplint.
4953*8c35d5eeSXin Li
4954*8c35d5eeSXin Li    Returns:
4955*8c35d5eeSXin Li      Number of lines needed to trigger a function length warning.
4956*8c35d5eeSXin Li    """
4957*8c35d5eeSXin Li    return cpplint._FunctionState._NORMAL_TRIGGER * 2**error_level
4958*8c35d5eeSXin Li
4959*8c35d5eeSXin Li  def TestLines(self, error_level):
4960*8c35d5eeSXin Li    """Return number of lines needed to trigger a test function length warning.
4961*8c35d5eeSXin Li
4962*8c35d5eeSXin Li    Args:
4963*8c35d5eeSXin Li      error_level: --v setting for cpplint.
4964*8c35d5eeSXin Li
4965*8c35d5eeSXin Li    Returns:
4966*8c35d5eeSXin Li      Number of lines needed to trigger a test function length warning.
4967*8c35d5eeSXin Li    """
4968*8c35d5eeSXin Li    return cpplint._FunctionState._TEST_TRIGGER * 2**error_level
4969*8c35d5eeSXin Li
4970*8c35d5eeSXin Li  def TestFunctionLengthCheckDefinition(self, lines, error_level):
4971*8c35d5eeSXin Li    """Generate long function definition and check warnings are as expected.
4972*8c35d5eeSXin Li
4973*8c35d5eeSXin Li    Args:
4974*8c35d5eeSXin Li      lines: Number of lines to generate.
4975*8c35d5eeSXin Li      error_level:  --v setting for cpplint.
4976*8c35d5eeSXin Li    """
4977*8c35d5eeSXin Li    trigger_level = self.TriggerLines(cpplint._VerboseLevel())
4978*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
4979*8c35d5eeSXin Li        'void test(int x)' + self.FunctionBody(lines),
4980*8c35d5eeSXin Li        ('Small and focused functions are preferred: '
4981*8c35d5eeSXin Li         'test() has %d non-comment lines '
4982*8c35d5eeSXin Li         '(error triggered by exceeding %d lines).'
4983*8c35d5eeSXin Li         '  [readability/fn_size] [%d]'
4984*8c35d5eeSXin Li         % (lines, trigger_level, error_level)))
4985*8c35d5eeSXin Li
4986*8c35d5eeSXin Li  def TestFunctionLengthCheckDefinitionOK(self, lines):
4987*8c35d5eeSXin Li    """Generate shorter function definition and check no warning is produced.
4988*8c35d5eeSXin Li
4989*8c35d5eeSXin Li    Args:
4990*8c35d5eeSXin Li      lines: Number of lines to generate.
4991*8c35d5eeSXin Li    """
4992*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
4993*8c35d5eeSXin Li        'void test(int x)' + self.FunctionBody(lines),
4994*8c35d5eeSXin Li        '')
4995*8c35d5eeSXin Li
4996*8c35d5eeSXin Li  def TestFunctionLengthCheckAtErrorLevel(self, error_level):
4997*8c35d5eeSXin Li    """Generate and check function at the trigger level for --v setting.
4998*8c35d5eeSXin Li
4999*8c35d5eeSXin Li    Args:
5000*8c35d5eeSXin Li      error_level: --v setting for cpplint.
5001*8c35d5eeSXin Li    """
5002*8c35d5eeSXin Li    self.TestFunctionLengthCheckDefinition(self.TriggerLines(error_level),
5003*8c35d5eeSXin Li                                           error_level)
5004*8c35d5eeSXin Li
5005*8c35d5eeSXin Li  def TestFunctionLengthCheckBelowErrorLevel(self, error_level):
5006*8c35d5eeSXin Li    """Generate and check function just below the trigger level for --v setting.
5007*8c35d5eeSXin Li
5008*8c35d5eeSXin Li    Args:
5009*8c35d5eeSXin Li      error_level: --v setting for cpplint.
5010*8c35d5eeSXin Li    """
5011*8c35d5eeSXin Li    self.TestFunctionLengthCheckDefinition(self.TriggerLines(error_level)-1,
5012*8c35d5eeSXin Li                                           error_level-1)
5013*8c35d5eeSXin Li
5014*8c35d5eeSXin Li  def TestFunctionLengthCheckAboveErrorLevel(self, error_level):
5015*8c35d5eeSXin Li    """Generate and check function just above the trigger level for --v setting.
5016*8c35d5eeSXin Li
5017*8c35d5eeSXin Li    Args:
5018*8c35d5eeSXin Li      error_level: --v setting for cpplint.
5019*8c35d5eeSXin Li    """
5020*8c35d5eeSXin Li    self.TestFunctionLengthCheckDefinition(self.TriggerLines(error_level)+1,
5021*8c35d5eeSXin Li                                           error_level)
5022*8c35d5eeSXin Li
5023*8c35d5eeSXin Li  def FunctionBody(self, number_of_lines):
5024*8c35d5eeSXin Li    return ' {\n' + '    this_is_just_a_test();\n'*number_of_lines + '}'
5025*8c35d5eeSXin Li
5026*8c35d5eeSXin Li  def FunctionBodyWithBlankLines(self, number_of_lines):
5027*8c35d5eeSXin Li    return ' {\n' + '    this_is_just_a_test();\n\n'*number_of_lines + '}'
5028*8c35d5eeSXin Li
5029*8c35d5eeSXin Li  def FunctionBodyWithNoLints(self, number_of_lines):
5030*8c35d5eeSXin Li    return (' {\n' +
5031*8c35d5eeSXin Li            '    this_is_just_a_test();  // NOLINT\n'*number_of_lines + '}')
5032*8c35d5eeSXin Li
5033*8c35d5eeSXin Li  # Test line length checks.
5034*8c35d5eeSXin Li  def testFunctionLengthCheckDeclaration(self):
5035*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5036*8c35d5eeSXin Li        'void test();',  # Not a function definition
5037*8c35d5eeSXin Li        '')
5038*8c35d5eeSXin Li
5039*8c35d5eeSXin Li  def testFunctionLengthCheckDeclarationWithBlockFollowing(self):
5040*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5041*8c35d5eeSXin Li        ('void test();\n'
5042*8c35d5eeSXin Li         + self.FunctionBody(66)),  # Not a function definition
5043*8c35d5eeSXin Li        '')
5044*8c35d5eeSXin Li
5045*8c35d5eeSXin Li  def testFunctionLengthCheckClassDefinition(self):
5046*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(  # Not a function definition
5047*8c35d5eeSXin Li        'class Test' + self.FunctionBody(66) + ';',
5048*8c35d5eeSXin Li        '')
5049*8c35d5eeSXin Li
5050*8c35d5eeSXin Li  def testFunctionLengthCheckTrivial(self):
5051*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5052*8c35d5eeSXin Li        'void test() {}',  # Not counted
5053*8c35d5eeSXin Li        '')
5054*8c35d5eeSXin Li
5055*8c35d5eeSXin Li  def testFunctionLengthCheckEmpty(self):
5056*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5057*8c35d5eeSXin Li        'void test() {\n}',
5058*8c35d5eeSXin Li        '')
5059*8c35d5eeSXin Li
5060*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionBelowSeverity0(self):
5061*8c35d5eeSXin Li    old_verbosity = cpplint._SetVerboseLevel(0)
5062*8c35d5eeSXin Li    self.TestFunctionLengthCheckDefinitionOK(self.TriggerLines(0)-1)
5063*8c35d5eeSXin Li    cpplint._SetVerboseLevel(old_verbosity)
5064*8c35d5eeSXin Li
5065*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionAtSeverity0(self):
5066*8c35d5eeSXin Li    old_verbosity = cpplint._SetVerboseLevel(0)
5067*8c35d5eeSXin Li    self.TestFunctionLengthCheckDefinitionOK(self.TriggerLines(0))
5068*8c35d5eeSXin Li    cpplint._SetVerboseLevel(old_verbosity)
5069*8c35d5eeSXin Li
5070*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionAboveSeverity0(self):
5071*8c35d5eeSXin Li    old_verbosity = cpplint._SetVerboseLevel(0)
5072*8c35d5eeSXin Li    self.TestFunctionLengthCheckAboveErrorLevel(0)
5073*8c35d5eeSXin Li    cpplint._SetVerboseLevel(old_verbosity)
5074*8c35d5eeSXin Li
5075*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionBelowSeverity1v0(self):
5076*8c35d5eeSXin Li    old_verbosity = cpplint._SetVerboseLevel(0)
5077*8c35d5eeSXin Li    self.TestFunctionLengthCheckBelowErrorLevel(1)
5078*8c35d5eeSXin Li    cpplint._SetVerboseLevel(old_verbosity)
5079*8c35d5eeSXin Li
5080*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionAtSeverity1v0(self):
5081*8c35d5eeSXin Li    old_verbosity = cpplint._SetVerboseLevel(0)
5082*8c35d5eeSXin Li    self.TestFunctionLengthCheckAtErrorLevel(1)
5083*8c35d5eeSXin Li    cpplint._SetVerboseLevel(old_verbosity)
5084*8c35d5eeSXin Li
5085*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionBelowSeverity1(self):
5086*8c35d5eeSXin Li    self.TestFunctionLengthCheckDefinitionOK(self.TriggerLines(1)-1)
5087*8c35d5eeSXin Li
5088*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionAtSeverity1(self):
5089*8c35d5eeSXin Li    self.TestFunctionLengthCheckDefinitionOK(self.TriggerLines(1))
5090*8c35d5eeSXin Li
5091*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionAboveSeverity1(self):
5092*8c35d5eeSXin Li    self.TestFunctionLengthCheckAboveErrorLevel(1)
5093*8c35d5eeSXin Li
5094*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionSeverity1PlusBlanks(self):
5095*8c35d5eeSXin Li    error_level = 1
5096*8c35d5eeSXin Li    error_lines = self.TriggerLines(error_level) + 1
5097*8c35d5eeSXin Li    trigger_level = self.TriggerLines(cpplint._VerboseLevel())
5098*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5099*8c35d5eeSXin Li        'void test_blanks(int x)' + self.FunctionBody(error_lines),
5100*8c35d5eeSXin Li        ('Small and focused functions are preferred: '
5101*8c35d5eeSXin Li         'test_blanks() has %d non-comment lines '
5102*8c35d5eeSXin Li         '(error triggered by exceeding %d lines).'
5103*8c35d5eeSXin Li         '  [readability/fn_size] [%d]')
5104*8c35d5eeSXin Li        % (error_lines, trigger_level, error_level))
5105*8c35d5eeSXin Li
5106*8c35d5eeSXin Li  def testFunctionLengthCheckComplexDefinitionSeverity1(self):
5107*8c35d5eeSXin Li    error_level = 1
5108*8c35d5eeSXin Li    error_lines = self.TriggerLines(error_level) + 1
5109*8c35d5eeSXin Li    trigger_level = self.TriggerLines(cpplint._VerboseLevel())
5110*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5111*8c35d5eeSXin Li        ('my_namespace::my_other_namespace::MyVeryLongTypeName*\n'
5112*8c35d5eeSXin Li         'my_namespace::my_other_namespace::MyFunction(int arg1, char* arg2)'
5113*8c35d5eeSXin Li         + self.FunctionBody(error_lines)),
5114*8c35d5eeSXin Li        ('Small and focused functions are preferred: '
5115*8c35d5eeSXin Li         'my_namespace::my_other_namespace::MyFunction()'
5116*8c35d5eeSXin Li         ' has %d non-comment lines '
5117*8c35d5eeSXin Li         '(error triggered by exceeding %d lines).'
5118*8c35d5eeSXin Li         '  [readability/fn_size] [%d]')
5119*8c35d5eeSXin Li        % (error_lines, trigger_level, error_level))
5120*8c35d5eeSXin Li
5121*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionSeverity1ForTest(self):
5122*8c35d5eeSXin Li    error_level = 1
5123*8c35d5eeSXin Li    error_lines = self.TestLines(error_level) + 1
5124*8c35d5eeSXin Li    trigger_level = self.TestLines(cpplint._VerboseLevel())
5125*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5126*8c35d5eeSXin Li        'TEST_F(Test, Mutator)' + self.FunctionBody(error_lines),
5127*8c35d5eeSXin Li        ('Small and focused functions are preferred: '
5128*8c35d5eeSXin Li         'TEST_F(Test, Mutator) has %d non-comment lines '
5129*8c35d5eeSXin Li         '(error triggered by exceeding %d lines).'
5130*8c35d5eeSXin Li         '  [readability/fn_size] [%d]')
5131*8c35d5eeSXin Li        % (error_lines, trigger_level, error_level))
5132*8c35d5eeSXin Li
5133*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionSeverity1ForSplitLineTest(self):
5134*8c35d5eeSXin Li    error_level = 1
5135*8c35d5eeSXin Li    error_lines = self.TestLines(error_level) + 1
5136*8c35d5eeSXin Li    trigger_level = self.TestLines(cpplint._VerboseLevel())
5137*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5138*8c35d5eeSXin Li        ('TEST_F(GoogleUpdateRecoveryRegistryProtectedTest,\n'
5139*8c35d5eeSXin Li         '    FixGoogleUpdate_AllValues_MachineApp)'  # note: 4 spaces
5140*8c35d5eeSXin Li         + self.FunctionBody(error_lines)),
5141*8c35d5eeSXin Li        ('Small and focused functions are preferred: '
5142*8c35d5eeSXin Li         'TEST_F(GoogleUpdateRecoveryRegistryProtectedTest, '  # 1 space
5143*8c35d5eeSXin Li         'FixGoogleUpdate_AllValues_MachineApp) has %d non-comment lines '
5144*8c35d5eeSXin Li         '(error triggered by exceeding %d lines).'
5145*8c35d5eeSXin Li         '  [readability/fn_size] [%d]')
5146*8c35d5eeSXin Li        % (error_lines+1, trigger_level, error_level))
5147*8c35d5eeSXin Li
5148*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionSeverity1ForBadTestDoesntBreak(self):
5149*8c35d5eeSXin Li    error_level = 1
5150*8c35d5eeSXin Li    error_lines = self.TestLines(error_level) + 1
5151*8c35d5eeSXin Li    trigger_level = self.TestLines(cpplint._VerboseLevel())
5152*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5153*8c35d5eeSXin Li        ('TEST_F('
5154*8c35d5eeSXin Li         + self.FunctionBody(error_lines)),
5155*8c35d5eeSXin Li        ('Small and focused functions are preferred: '
5156*8c35d5eeSXin Li         'TEST_F has %d non-comment lines '
5157*8c35d5eeSXin Li         '(error triggered by exceeding %d lines).'
5158*8c35d5eeSXin Li         '  [readability/fn_size] [%d]')
5159*8c35d5eeSXin Li        % (error_lines, trigger_level, error_level))
5160*8c35d5eeSXin Li
5161*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionSeverity1WithEmbeddedNoLints(self):
5162*8c35d5eeSXin Li    error_level = 1
5163*8c35d5eeSXin Li    error_lines = self.TriggerLines(error_level)+1
5164*8c35d5eeSXin Li    trigger_level = self.TriggerLines(cpplint._VerboseLevel())
5165*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5166*8c35d5eeSXin Li        'void test(int x)' + self.FunctionBodyWithNoLints(error_lines),
5167*8c35d5eeSXin Li        ('Small and focused functions are preferred: '
5168*8c35d5eeSXin Li         'test() has %d non-comment lines '
5169*8c35d5eeSXin Li         '(error triggered by exceeding %d lines).'
5170*8c35d5eeSXin Li         '  [readability/fn_size] [%d]')
5171*8c35d5eeSXin Li        % (error_lines, trigger_level, error_level))
5172*8c35d5eeSXin Li
5173*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionSeverity1WithNoLint(self):
5174*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5175*8c35d5eeSXin Li        ('void test(int x)' + self.FunctionBody(self.TriggerLines(1))
5176*8c35d5eeSXin Li         + '  // NOLINT -- long function'),
5177*8c35d5eeSXin Li        '')
5178*8c35d5eeSXin Li
5179*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionBelowSeverity2(self):
5180*8c35d5eeSXin Li    self.TestFunctionLengthCheckBelowErrorLevel(2)
5181*8c35d5eeSXin Li
5182*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionSeverity2(self):
5183*8c35d5eeSXin Li    self.TestFunctionLengthCheckAtErrorLevel(2)
5184*8c35d5eeSXin Li
5185*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionAboveSeverity2(self):
5186*8c35d5eeSXin Li    self.TestFunctionLengthCheckAboveErrorLevel(2)
5187*8c35d5eeSXin Li
5188*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionBelowSeverity3(self):
5189*8c35d5eeSXin Li    self.TestFunctionLengthCheckBelowErrorLevel(3)
5190*8c35d5eeSXin Li
5191*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionSeverity3(self):
5192*8c35d5eeSXin Li    self.TestFunctionLengthCheckAtErrorLevel(3)
5193*8c35d5eeSXin Li
5194*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionAboveSeverity3(self):
5195*8c35d5eeSXin Li    self.TestFunctionLengthCheckAboveErrorLevel(3)
5196*8c35d5eeSXin Li
5197*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionBelowSeverity4(self):
5198*8c35d5eeSXin Li    self.TestFunctionLengthCheckBelowErrorLevel(4)
5199*8c35d5eeSXin Li
5200*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionSeverity4(self):
5201*8c35d5eeSXin Li    self.TestFunctionLengthCheckAtErrorLevel(4)
5202*8c35d5eeSXin Li
5203*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionAboveSeverity4(self):
5204*8c35d5eeSXin Li    self.TestFunctionLengthCheckAboveErrorLevel(4)
5205*8c35d5eeSXin Li
5206*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionBelowSeverity5(self):
5207*8c35d5eeSXin Li    self.TestFunctionLengthCheckBelowErrorLevel(5)
5208*8c35d5eeSXin Li
5209*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionAtSeverity5(self):
5210*8c35d5eeSXin Li    self.TestFunctionLengthCheckAtErrorLevel(5)
5211*8c35d5eeSXin Li
5212*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionAboveSeverity5(self):
5213*8c35d5eeSXin Li    self.TestFunctionLengthCheckAboveErrorLevel(5)
5214*8c35d5eeSXin Li
5215*8c35d5eeSXin Li  def testFunctionLengthCheckDefinitionHugeLines(self):
5216*8c35d5eeSXin Li    # 5 is the limit
5217*8c35d5eeSXin Li    self.TestFunctionLengthCheckDefinition(self.TriggerLines(10), 5)
5218*8c35d5eeSXin Li
5219*8c35d5eeSXin Li  def testFunctionLengthNotDeterminable(self):
5220*8c35d5eeSXin Li    # Macro invocation without terminating semicolon.
5221*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5222*8c35d5eeSXin Li        'MACRO(arg)',
5223*8c35d5eeSXin Li        '')
5224*8c35d5eeSXin Li
5225*8c35d5eeSXin Li    # Macro with underscores
5226*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5227*8c35d5eeSXin Li        'MACRO_WITH_UNDERSCORES(arg1, arg2, arg3)',
5228*8c35d5eeSXin Li        '')
5229*8c35d5eeSXin Li
5230*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5231*8c35d5eeSXin Li        'NonMacro(arg)',
5232*8c35d5eeSXin Li        'Lint failed to find start of function body.'
5233*8c35d5eeSXin Li        '  [readability/fn_size] [5]')
5234*8c35d5eeSXin Li
5235*8c35d5eeSXin Li  def testFunctionLengthCheckWithNamespace(self):
5236*8c35d5eeSXin Li    old_verbosity = cpplint._SetVerboseLevel(1)
5237*8c35d5eeSXin Li    self.TestFunctionLengthsCheck(
5238*8c35d5eeSXin Li        ('namespace {\n'
5239*8c35d5eeSXin Li         'void CodeCoverageCL35256059() {\n' +
5240*8c35d5eeSXin Li         ('  X++;\n' * 3000) +
5241*8c35d5eeSXin Li         '}\n'
5242*8c35d5eeSXin Li         '}  // namespace\n'),
5243*8c35d5eeSXin Li        ('Small and focused functions are preferred: '
5244*8c35d5eeSXin Li         'CodeCoverageCL35256059() has 3000 non-comment lines '
5245*8c35d5eeSXin Li         '(error triggered by exceeding 20 lines).'
5246*8c35d5eeSXin Li         '  [readability/fn_size] [5]'))
5247*8c35d5eeSXin Li    cpplint._SetVerboseLevel(old_verbosity)
5248*8c35d5eeSXin Li
5249*8c35d5eeSXin Li
5250*8c35d5eeSXin Lidef TrimExtraIndent(text_block):
5251*8c35d5eeSXin Li  """Trim a uniform amount of whitespace off of each line in a string.
5252*8c35d5eeSXin Li
5253*8c35d5eeSXin Li  Compute the minimum indent on all non blank lines and trim that from each, so
5254*8c35d5eeSXin Li  that the block of text has no extra indentation.
5255*8c35d5eeSXin Li
5256*8c35d5eeSXin Li  Args:
5257*8c35d5eeSXin Li    text_block: a multiline string
5258*8c35d5eeSXin Li
5259*8c35d5eeSXin Li  Returns:
5260*8c35d5eeSXin Li    text_block with the common whitespace indent of each line removed.
5261*8c35d5eeSXin Li  """
5262*8c35d5eeSXin Li
5263*8c35d5eeSXin Li  def CountLeadingWhitespace(s):
5264*8c35d5eeSXin Li    count = 0
5265*8c35d5eeSXin Li    for c in s:
5266*8c35d5eeSXin Li      if not c.isspace():
5267*8c35d5eeSXin Li        break
5268*8c35d5eeSXin Li      count += 1
5269*8c35d5eeSXin Li    return count
5270*8c35d5eeSXin Li  # find the minimum indent (except for blank lines)
5271*8c35d5eeSXin Li  min_indent = min([CountLeadingWhitespace(line)
5272*8c35d5eeSXin Li                    for line in text_block.split('\n') if line])
5273*8c35d5eeSXin Li  return '\n'.join([line[min_indent:] for line in text_block.split('\n')])
5274*8c35d5eeSXin Li
5275*8c35d5eeSXin Li
5276*8c35d5eeSXin Liclass CloseExpressionTest(unittest.TestCase):
5277*8c35d5eeSXin Li
5278*8c35d5eeSXin Li  def setUp(self):
5279*8c35d5eeSXin Li    self.lines = cpplint.CleansedLines(
5280*8c35d5eeSXin Li        #           1         2         3         4         5
5281*8c35d5eeSXin Li        # 0123456789012345678901234567890123456789012345678901234567890
5282*8c35d5eeSXin Li        ['// Line 0',
5283*8c35d5eeSXin Li         'inline RCULocked<X>::ReadPtr::ReadPtr(const RCULocked* rcu) {',
5284*8c35d5eeSXin Li         '  DCHECK(!(data & kFlagMask)) << "Error";',
5285*8c35d5eeSXin Li         '}',
5286*8c35d5eeSXin Li         '// Line 4',
5287*8c35d5eeSXin Li         'RCULocked<X>::WritePtr::WritePtr(RCULocked* rcu)',
5288*8c35d5eeSXin Li         '    : lock_(&rcu_->mutex_) {',
5289*8c35d5eeSXin Li         '}',
5290*8c35d5eeSXin Li         '// Line 8',
5291*8c35d5eeSXin Li         'template <typename T, typename... A>',
5292*8c35d5eeSXin Li         'typename std::enable_if<',
5293*8c35d5eeSXin Li         '    std::is_array<T>::value && (std::extent<T>::value > 0)>::type',
5294*8c35d5eeSXin Li         'MakeUnique(A&&... a) = delete;',
5295*8c35d5eeSXin Li         '// Line 13',
5296*8c35d5eeSXin Li         'auto x = []() {};',
5297*8c35d5eeSXin Li         '// Line 15',
5298*8c35d5eeSXin Li         'template <typename U>',
5299*8c35d5eeSXin Li         'friend bool operator==(const reffed_ptr& a,',
5300*8c35d5eeSXin Li         '                       const reffed_ptr<U>& b) {',
5301*8c35d5eeSXin Li         '  return a.get() == b.get();',
5302*8c35d5eeSXin Li         '}',
5303*8c35d5eeSXin Li         '// Line 21'])
5304*8c35d5eeSXin Li
5305*8c35d5eeSXin Li  def testCloseExpression(self):
5306*8c35d5eeSXin Li    # List of positions to test:
5307*8c35d5eeSXin Li    # (start line, start position, end line, end position + 1)
5308*8c35d5eeSXin Li    positions = [(1, 16, 1, 19),
5309*8c35d5eeSXin Li                 (1, 37, 1, 59),
5310*8c35d5eeSXin Li                 (1, 60, 3, 1),
5311*8c35d5eeSXin Li                 (2, 8, 2, 29),
5312*8c35d5eeSXin Li                 (2, 30, 22, -1),  # Left shift operator
5313*8c35d5eeSXin Li                 (9, 9, 9, 36),
5314*8c35d5eeSXin Li                 (10, 23, 11, 59),
5315*8c35d5eeSXin Li                 (11, 54, 22, -1),  # Greater than operator
5316*8c35d5eeSXin Li                 (14, 9, 14, 11),
5317*8c35d5eeSXin Li                 (14, 11, 14, 13),
5318*8c35d5eeSXin Li                 (14, 14, 14, 16),
5319*8c35d5eeSXin Li                 (17, 22, 18, 46),
5320*8c35d5eeSXin Li                 (18, 47, 20, 1)]
5321*8c35d5eeSXin Li    for p in positions:
5322*8c35d5eeSXin Li      (_, line, column) = cpplint.CloseExpression(self.lines, p[0], p[1])
5323*8c35d5eeSXin Li      self.assertEquals((p[2], p[3]), (line, column))
5324*8c35d5eeSXin Li
5325*8c35d5eeSXin Li  def testReverseCloseExpression(self):
5326*8c35d5eeSXin Li    # List of positions to test:
5327*8c35d5eeSXin Li    # (end line, end position, start line, start position)
5328*8c35d5eeSXin Li    positions = [(1, 18, 1, 16),
5329*8c35d5eeSXin Li                 (1, 58, 1, 37),
5330*8c35d5eeSXin Li                 (2, 27, 2, 10),
5331*8c35d5eeSXin Li                 (2, 28, 2, 8),
5332*8c35d5eeSXin Li                 (6, 18, 0, -1),  # -> operator
5333*8c35d5eeSXin Li                 (9, 35, 9, 9),
5334*8c35d5eeSXin Li                 (11, 54, 0, -1),  # Greater than operator
5335*8c35d5eeSXin Li                 (11, 57, 11, 31),
5336*8c35d5eeSXin Li                 (14, 10, 14, 9),
5337*8c35d5eeSXin Li                 (14, 12, 14, 11),
5338*8c35d5eeSXin Li                 (14, 15, 14, 14),
5339*8c35d5eeSXin Li                 (18, 45, 17, 22),
5340*8c35d5eeSXin Li                 (20, 0, 18, 47)]
5341*8c35d5eeSXin Li    for p in positions:
5342*8c35d5eeSXin Li      (_, line, column) = cpplint.ReverseCloseExpression(self.lines, p[0], p[1])
5343*8c35d5eeSXin Li      self.assertEquals((p[2], p[3]), (line, column))
5344*8c35d5eeSXin Li
5345*8c35d5eeSXin Li
5346*8c35d5eeSXin Liclass NestingStateTest(unittest.TestCase):
5347*8c35d5eeSXin Li
5348*8c35d5eeSXin Li  def setUp(self):
5349*8c35d5eeSXin Li    self.nesting_state = cpplint.NestingState()
5350*8c35d5eeSXin Li    self.error_collector = ErrorCollector(self.assert_)
5351*8c35d5eeSXin Li
5352*8c35d5eeSXin Li  def UpdateWithLines(self, lines):
5353*8c35d5eeSXin Li    clean_lines = cpplint.CleansedLines(lines)
5354*8c35d5eeSXin Li    for line in xrange(clean_lines.NumLines()):
5355*8c35d5eeSXin Li      self.nesting_state.Update('test.cc',
5356*8c35d5eeSXin Li                                clean_lines, line, self.error_collector)
5357*8c35d5eeSXin Li
5358*8c35d5eeSXin Li  def testEmpty(self):
5359*8c35d5eeSXin Li    self.UpdateWithLines([])
5360*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack, [])
5361*8c35d5eeSXin Li
5362*8c35d5eeSXin Li  def testNamespace(self):
5363*8c35d5eeSXin Li    self.UpdateWithLines(['namespace {'])
5364*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5365*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0],
5366*8c35d5eeSXin Li                               cpplint._NamespaceInfo))
5367*8c35d5eeSXin Li    self.assertTrue(self.nesting_state.stack[0].seen_open_brace)
5368*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, '')
5369*8c35d5eeSXin Li
5370*8c35d5eeSXin Li    self.UpdateWithLines(['namespace outer { namespace inner'])
5371*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 3)
5372*8c35d5eeSXin Li    self.assertTrue(self.nesting_state.stack[0].seen_open_brace)
5373*8c35d5eeSXin Li    self.assertTrue(self.nesting_state.stack[1].seen_open_brace)
5374*8c35d5eeSXin Li    self.assertFalse(self.nesting_state.stack[2].seen_open_brace)
5375*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, '')
5376*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[1].name, 'outer')
5377*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[2].name, 'inner')
5378*8c35d5eeSXin Li
5379*8c35d5eeSXin Li    self.UpdateWithLines(['{'])
5380*8c35d5eeSXin Li    self.assertTrue(self.nesting_state.stack[2].seen_open_brace)
5381*8c35d5eeSXin Li
5382*8c35d5eeSXin Li    self.UpdateWithLines(['}', '}}'])
5383*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5384*8c35d5eeSXin Li
5385*8c35d5eeSXin Li  def testClass(self):
5386*8c35d5eeSXin Li    self.UpdateWithLines(['class A {'])
5387*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5388*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5389*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'A')
5390*8c35d5eeSXin Li    self.assertFalse(self.nesting_state.stack[0].is_derived)
5391*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].class_indent, 0)
5392*8c35d5eeSXin Li
5393*8c35d5eeSXin Li    self.UpdateWithLines(['};',
5394*8c35d5eeSXin Li                          'struct B : public A {'])
5395*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5396*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5397*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'B')
5398*8c35d5eeSXin Li    self.assertTrue(self.nesting_state.stack[0].is_derived)
5399*8c35d5eeSXin Li
5400*8c35d5eeSXin Li    self.UpdateWithLines(['};',
5401*8c35d5eeSXin Li                          'class C',
5402*8c35d5eeSXin Li                          ': public A {'])
5403*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5404*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5405*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'C')
5406*8c35d5eeSXin Li    self.assertTrue(self.nesting_state.stack[0].is_derived)
5407*8c35d5eeSXin Li
5408*8c35d5eeSXin Li    self.UpdateWithLines(['};',
5409*8c35d5eeSXin Li                          'template<T>'])
5410*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5411*8c35d5eeSXin Li
5412*8c35d5eeSXin Li    self.UpdateWithLines(['class D {', '  class E {'])
5413*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 2)
5414*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5415*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'D')
5416*8c35d5eeSXin Li    self.assertFalse(self.nesting_state.stack[0].is_derived)
5417*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[1], cpplint._ClassInfo))
5418*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[1].name, 'E')
5419*8c35d5eeSXin Li    self.assertFalse(self.nesting_state.stack[1].is_derived)
5420*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[1].class_indent, 2)
5421*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.InnermostClass().name, 'E')
5422*8c35d5eeSXin Li
5423*8c35d5eeSXin Li    self.UpdateWithLines(['}', '}'])
5424*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5425*8c35d5eeSXin Li
5426*8c35d5eeSXin Li  def testClassAccess(self):
5427*8c35d5eeSXin Li    self.UpdateWithLines(['class A {'])
5428*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5429*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5430*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].access, 'private')
5431*8c35d5eeSXin Li
5432*8c35d5eeSXin Li    self.UpdateWithLines([' public:'])
5433*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].access, 'public')
5434*8c35d5eeSXin Li    self.UpdateWithLines([' protracted:'])
5435*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].access, 'public')
5436*8c35d5eeSXin Li    self.UpdateWithLines([' protected:'])
5437*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].access, 'protected')
5438*8c35d5eeSXin Li    self.UpdateWithLines([' private:'])
5439*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].access, 'private')
5440*8c35d5eeSXin Li
5441*8c35d5eeSXin Li    self.UpdateWithLines(['  struct B {'])
5442*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 2)
5443*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[1], cpplint._ClassInfo))
5444*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[1].access, 'public')
5445*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].access, 'private')
5446*8c35d5eeSXin Li
5447*8c35d5eeSXin Li    self.UpdateWithLines(['   protected  :'])
5448*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[1].access, 'protected')
5449*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].access, 'private')
5450*8c35d5eeSXin Li
5451*8c35d5eeSXin Li    self.UpdateWithLines(['  }', '}'])
5452*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5453*8c35d5eeSXin Li
5454*8c35d5eeSXin Li  def testStruct(self):
5455*8c35d5eeSXin Li    self.UpdateWithLines(['struct A {'])
5456*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5457*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5458*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'A')
5459*8c35d5eeSXin Li    self.assertFalse(self.nesting_state.stack[0].is_derived)
5460*8c35d5eeSXin Li
5461*8c35d5eeSXin Li    self.UpdateWithLines(['}',
5462*8c35d5eeSXin Li                          'void Func(struct B arg) {'])
5463*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5464*8c35d5eeSXin Li    self.assertFalse(isinstance(self.nesting_state.stack[0],
5465*8c35d5eeSXin Li                                cpplint._ClassInfo))
5466*8c35d5eeSXin Li
5467*8c35d5eeSXin Li    self.UpdateWithLines(['}'])
5468*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5469*8c35d5eeSXin Li
5470*8c35d5eeSXin Li  def testPreprocessor(self):
5471*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.pp_stack), 0)
5472*8c35d5eeSXin Li    self.UpdateWithLines(['#if MACRO1'])
5473*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.pp_stack), 1)
5474*8c35d5eeSXin Li    self.UpdateWithLines(['#endif'])
5475*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.pp_stack), 0)
5476*8c35d5eeSXin Li
5477*8c35d5eeSXin Li    self.UpdateWithLines(['#ifdef MACRO2'])
5478*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.pp_stack), 1)
5479*8c35d5eeSXin Li    self.UpdateWithLines(['#else'])
5480*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.pp_stack), 1)
5481*8c35d5eeSXin Li    self.UpdateWithLines(['#ifdef MACRO3'])
5482*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.pp_stack), 2)
5483*8c35d5eeSXin Li    self.UpdateWithLines(['#elif MACRO4'])
5484*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.pp_stack), 2)
5485*8c35d5eeSXin Li    self.UpdateWithLines(['#endif'])
5486*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.pp_stack), 1)
5487*8c35d5eeSXin Li    self.UpdateWithLines(['#endif'])
5488*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.pp_stack), 0)
5489*8c35d5eeSXin Li
5490*8c35d5eeSXin Li    self.UpdateWithLines(['#ifdef MACRO5',
5491*8c35d5eeSXin Li                          'class A {',
5492*8c35d5eeSXin Li                          '#elif MACRO6',
5493*8c35d5eeSXin Li                          'class B {',
5494*8c35d5eeSXin Li                          '#else',
5495*8c35d5eeSXin Li                          'class C {',
5496*8c35d5eeSXin Li                          '#endif'])
5497*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.pp_stack), 0)
5498*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5499*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5500*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'A')
5501*8c35d5eeSXin Li    self.UpdateWithLines(['};'])
5502*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5503*8c35d5eeSXin Li
5504*8c35d5eeSXin Li    self.UpdateWithLines(['class D',
5505*8c35d5eeSXin Li                          '#ifdef MACRO7'])
5506*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.pp_stack), 1)
5507*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5508*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5509*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'D')
5510*8c35d5eeSXin Li    self.assertFalse(self.nesting_state.stack[0].is_derived)
5511*8c35d5eeSXin Li
5512*8c35d5eeSXin Li    self.UpdateWithLines(['#elif MACRO8',
5513*8c35d5eeSXin Li                          ': public E'])
5514*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5515*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'D')
5516*8c35d5eeSXin Li    self.assertTrue(self.nesting_state.stack[0].is_derived)
5517*8c35d5eeSXin Li    self.assertFalse(self.nesting_state.stack[0].seen_open_brace)
5518*8c35d5eeSXin Li
5519*8c35d5eeSXin Li    self.UpdateWithLines(['#else',
5520*8c35d5eeSXin Li                          '{'])
5521*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5522*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'D')
5523*8c35d5eeSXin Li    self.assertFalse(self.nesting_state.stack[0].is_derived)
5524*8c35d5eeSXin Li    self.assertTrue(self.nesting_state.stack[0].seen_open_brace)
5525*8c35d5eeSXin Li
5526*8c35d5eeSXin Li    self.UpdateWithLines(['#endif'])
5527*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.pp_stack), 0)
5528*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5529*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'D')
5530*8c35d5eeSXin Li    self.assertFalse(self.nesting_state.stack[0].is_derived)
5531*8c35d5eeSXin Li    self.assertFalse(self.nesting_state.stack[0].seen_open_brace)
5532*8c35d5eeSXin Li
5533*8c35d5eeSXin Li    self.UpdateWithLines([';'])
5534*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5535*8c35d5eeSXin Li
5536*8c35d5eeSXin Li  def testTemplate(self):
5537*8c35d5eeSXin Li    self.UpdateWithLines(['template <T,',
5538*8c35d5eeSXin Li                          '          class Arg1 = tmpl<T> >'])
5539*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5540*8c35d5eeSXin Li    self.UpdateWithLines(['class A {'])
5541*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5542*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5543*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'A')
5544*8c35d5eeSXin Li
5545*8c35d5eeSXin Li    self.UpdateWithLines(['};',
5546*8c35d5eeSXin Li                          'template <T,',
5547*8c35d5eeSXin Li                          '  template <typename, typename> class B>',
5548*8c35d5eeSXin Li                          'class C'])
5549*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5550*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5551*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'C')
5552*8c35d5eeSXin Li    self.UpdateWithLines([';'])
5553*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5554*8c35d5eeSXin Li
5555*8c35d5eeSXin Li    self.UpdateWithLines(['class D : public Tmpl<E>'])
5556*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5557*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5558*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'D')
5559*8c35d5eeSXin Li
5560*8c35d5eeSXin Li    self.UpdateWithLines(['{', '};'])
5561*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5562*8c35d5eeSXin Li
5563*8c35d5eeSXin Li    self.UpdateWithLines(['template <class F,',
5564*8c35d5eeSXin Li                          '          class G,',
5565*8c35d5eeSXin Li                          '          class H,',
5566*8c35d5eeSXin Li                          '          typename I>',
5567*8c35d5eeSXin Li                          'static void Func() {'])
5568*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5569*8c35d5eeSXin Li    self.assertFalse(isinstance(self.nesting_state.stack[0],
5570*8c35d5eeSXin Li                                cpplint._ClassInfo))
5571*8c35d5eeSXin Li    self.UpdateWithLines(['}',
5572*8c35d5eeSXin Li                          'template <class J> class K {'])
5573*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5574*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5575*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'K')
5576*8c35d5eeSXin Li
5577*8c35d5eeSXin Li  def testTemplateInnerClass(self):
5578*8c35d5eeSXin Li    self.UpdateWithLines(['class A {',
5579*8c35d5eeSXin Li                          ' public:'])
5580*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5581*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5582*8c35d5eeSXin Li
5583*8c35d5eeSXin Li    self.UpdateWithLines(['  template <class B>',
5584*8c35d5eeSXin Li                          '  class C<alloc<B> >',
5585*8c35d5eeSXin Li                          '      : public A {'])
5586*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 2)
5587*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[1], cpplint._ClassInfo))
5588*8c35d5eeSXin Li
5589*8c35d5eeSXin Li  def testArguments(self):
5590*8c35d5eeSXin Li    self.UpdateWithLines(['class A {'])
5591*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5592*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5593*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'A')
5594*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
5595*8c35d5eeSXin Li
5596*8c35d5eeSXin Li    self.UpdateWithLines(['  void Func(',
5597*8c35d5eeSXin Li                          '    struct X arg1,'])
5598*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5599*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
5600*8c35d5eeSXin Li    self.UpdateWithLines(['    struct X *arg2);'])
5601*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5602*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
5603*8c35d5eeSXin Li
5604*8c35d5eeSXin Li    self.UpdateWithLines(['};'])
5605*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5606*8c35d5eeSXin Li
5607*8c35d5eeSXin Li    self.UpdateWithLines(['struct B {'])
5608*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5609*8c35d5eeSXin Li    self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
5610*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[0].name, 'B')
5611*8c35d5eeSXin Li
5612*8c35d5eeSXin Li    self.UpdateWithLines(['#ifdef MACRO',
5613*8c35d5eeSXin Li                          '  void Func(',
5614*8c35d5eeSXin Li                          '    struct X arg1'])
5615*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5616*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
5617*8c35d5eeSXin Li    self.UpdateWithLines(['#else'])
5618*8c35d5eeSXin Li
5619*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5620*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
5621*8c35d5eeSXin Li    self.UpdateWithLines(['  void Func(',
5622*8c35d5eeSXin Li                          '    struct X arg1'])
5623*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5624*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
5625*8c35d5eeSXin Li
5626*8c35d5eeSXin Li    self.UpdateWithLines(['#endif'])
5627*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5628*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
5629*8c35d5eeSXin Li    self.UpdateWithLines(['    struct X *arg2);'])
5630*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5631*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
5632*8c35d5eeSXin Li
5633*8c35d5eeSXin Li    self.UpdateWithLines(['};'])
5634*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5635*8c35d5eeSXin Li
5636*8c35d5eeSXin Li  def testInlineAssembly(self):
5637*8c35d5eeSXin Li    self.UpdateWithLines(['void CopyRow_SSE2(const uint8* src, uint8* dst,',
5638*8c35d5eeSXin Li                          '                  int count) {'])
5639*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5640*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
5641*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].inline_asm, cpplint._NO_ASM)
5642*8c35d5eeSXin Li
5643*8c35d5eeSXin Li    self.UpdateWithLines(['  asm volatile ('])
5644*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5645*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
5646*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].inline_asm,
5647*8c35d5eeSXin Li                      cpplint._INSIDE_ASM)
5648*8c35d5eeSXin Li
5649*8c35d5eeSXin Li    self.UpdateWithLines(['    "sub        %0,%1                         \\n"',
5650*8c35d5eeSXin Li                          '  "1:                                         \\n"',
5651*8c35d5eeSXin Li                          '    "movdqa    (%0),%%xmm0                    \\n"',
5652*8c35d5eeSXin Li                          '    "movdqa    0x10(%0),%%xmm1                \\n"',
5653*8c35d5eeSXin Li                          '    "movdqa    %%xmm0,(%0,%1)                 \\n"',
5654*8c35d5eeSXin Li                          '    "movdqa    %%xmm1,0x10(%0,%1)             \\n"',
5655*8c35d5eeSXin Li                          '    "lea       0x20(%0),%0                    \\n"',
5656*8c35d5eeSXin Li                          '    "sub       $0x20,%2                       \\n"',
5657*8c35d5eeSXin Li                          '    "jg        1b                             \\n"',
5658*8c35d5eeSXin Li                          '  : "+r"(src),   // %0',
5659*8c35d5eeSXin Li                          '    "+r"(dst),   // %1',
5660*8c35d5eeSXin Li                          '    "+r"(count)  // %2',
5661*8c35d5eeSXin Li                          '  :',
5662*8c35d5eeSXin Li                          '  : "memory", "cc"'])
5663*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5664*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
5665*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].inline_asm,
5666*8c35d5eeSXin Li                      cpplint._INSIDE_ASM)
5667*8c35d5eeSXin Li
5668*8c35d5eeSXin Li    self.UpdateWithLines(['#if defined(__SSE2__)',
5669*8c35d5eeSXin Li                          '    , "xmm0", "xmm1"'])
5670*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5671*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
5672*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].inline_asm,
5673*8c35d5eeSXin Li                      cpplint._INSIDE_ASM)
5674*8c35d5eeSXin Li
5675*8c35d5eeSXin Li    self.UpdateWithLines(['#endif'])
5676*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5677*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 1)
5678*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].inline_asm,
5679*8c35d5eeSXin Li                      cpplint._INSIDE_ASM)
5680*8c35d5eeSXin Li
5681*8c35d5eeSXin Li    self.UpdateWithLines(['  );'])
5682*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5683*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
5684*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].inline_asm, cpplint._END_ASM)
5685*8c35d5eeSXin Li
5686*8c35d5eeSXin Li    self.UpdateWithLines(['__asm {'])
5687*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 2)
5688*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].open_parentheses, 0)
5689*8c35d5eeSXin Li    self.assertEquals(self.nesting_state.stack[-1].inline_asm,
5690*8c35d5eeSXin Li                      cpplint._BLOCK_ASM)
5691*8c35d5eeSXin Li
5692*8c35d5eeSXin Li    self.UpdateWithLines(['}'])
5693*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 1)
5694*8c35d5eeSXin Li
5695*8c35d5eeSXin Li    self.UpdateWithLines(['}'])
5696*8c35d5eeSXin Li    self.assertEquals(len(self.nesting_state.stack), 0)
5697*8c35d5eeSXin Li
5698*8c35d5eeSXin Li
5699*8c35d5eeSXin Liclass QuietTest(unittest.TestCase):
5700*8c35d5eeSXin Li
5701*8c35d5eeSXin Li  def setUp(self):
5702*8c35d5eeSXin Li    self.this_dir_path = os.path.dirname(os.path.abspath(__file__))
5703*8c35d5eeSXin Li    self.python_executable = sys.executable or 'python'
5704*8c35d5eeSXin Li    self.cpplint_test_h = os.path.join(self.this_dir_path,
5705*8c35d5eeSXin Li                                       'cpplint_test_header.h')
5706*8c35d5eeSXin Li
5707*8c35d5eeSXin Li  def _runCppLint(self, *args):
5708*8c35d5eeSXin Li    cpplint_abspath = os.path.join(self.this_dir_path, 'cpplint.py')
5709*8c35d5eeSXin Li
5710*8c35d5eeSXin Li    cmd_line = [self.python_executable, cpplint_abspath] +                     \
5711*8c35d5eeSXin Li        list(args) +                                                           \
5712*8c35d5eeSXin Li        [ self.cpplint_test_h ]
5713*8c35d5eeSXin Li
5714*8c35d5eeSXin Li    return_code = 0
5715*8c35d5eeSXin Li    try:
5716*8c35d5eeSXin Li      output = subprocess.check_output(cmd_line,
5717*8c35d5eeSXin Li                                       stderr=subprocess.STDOUT)
5718*8c35d5eeSXin Li    except subprocess.CalledProcessError as err:
5719*8c35d5eeSXin Li      return_code = err.returncode
5720*8c35d5eeSXin Li      output = err.output
5721*8c35d5eeSXin Li
5722*8c35d5eeSXin Li    return (return_code, output)
5723*8c35d5eeSXin Li
5724*8c35d5eeSXin Li  def testNonQuietWithErrors(self):
5725*8c35d5eeSXin Li    # This will fail: the test header is missing a copyright and header guard.
5726*8c35d5eeSXin Li    (return_code, output) = self._runCppLint()
5727*8c35d5eeSXin Li    self.assertEquals(1, return_code)
5728*8c35d5eeSXin Li    # Always-on behavior: Print error messages as they come up.
5729*8c35d5eeSXin Li    self.assertIn("[legal/copyright]", output)
5730*8c35d5eeSXin Li    self.assertIn("[build/header_guard]", output)
5731*8c35d5eeSXin Li    # If --quiet was unspecified: Print 'Done processing' and 'Total errors..'
5732*8c35d5eeSXin Li    self.assertIn("Done processing", output)
5733*8c35d5eeSXin Li    self.assertIn("Total errors found:", output)
5734*8c35d5eeSXin Li
5735*8c35d5eeSXin Li  def testQuietWithErrors(self):
5736*8c35d5eeSXin Li    # When there are errors, behavior is identical to not passing --quiet.
5737*8c35d5eeSXin Li    (return_code, output) = self._runCppLint('--quiet')
5738*8c35d5eeSXin Li    self.assertEquals(1, return_code)
5739*8c35d5eeSXin Li    self.assertIn("[legal/copyright]", output)
5740*8c35d5eeSXin Li    self.assertIn("[build/header_guard]", output)
5741*8c35d5eeSXin Li    # Even though --quiet was used, print these since there were errors.
5742*8c35d5eeSXin Li    self.assertIn("Done processing", output)
5743*8c35d5eeSXin Li    self.assertIn("Total errors found:", output)
5744*8c35d5eeSXin Li
5745*8c35d5eeSXin Li  def testNonQuietWithoutErrors(self):
5746*8c35d5eeSXin Li    # This will succeed. We filtered out all the known errors for that file.
5747*8c35d5eeSXin Li    (return_code, output) = self._runCppLint('--filter=' +
5748*8c35d5eeSXin Li                                                '-legal/copyright,' +
5749*8c35d5eeSXin Li                                                '-build/header_guard')
5750*8c35d5eeSXin Li    self.assertEquals(0, return_code, output)
5751*8c35d5eeSXin Li    # No cpplint errors are printed since there were no errors.
5752*8c35d5eeSXin Li    self.assertNotIn("[legal/copyright]", output)
5753*8c35d5eeSXin Li    self.assertNotIn("[build/header_guard]", output)
5754*8c35d5eeSXin Li    # Print 'Done processing' and 'Total errors found' since
5755*8c35d5eeSXin Li    # --quiet was not specified.
5756*8c35d5eeSXin Li    self.assertIn("Done processing", output)
5757*8c35d5eeSXin Li    self.assertIn("Total errors found:", output)
5758*8c35d5eeSXin Li
5759*8c35d5eeSXin Li  def testQuietWithoutErrors(self):
5760*8c35d5eeSXin Li    # This will succeed. We filtered out all the known errors for that file.
5761*8c35d5eeSXin Li    (return_code, output) = self._runCppLint('--quiet',
5762*8c35d5eeSXin Li                                             '--filter=' +
5763*8c35d5eeSXin Li                                                 '-legal/copyright,' +
5764*8c35d5eeSXin Li                                                 '-build/header_guard')
5765*8c35d5eeSXin Li    self.assertEquals(0, return_code, output)
5766*8c35d5eeSXin Li    # No cpplint errors are printed since there were no errors.
5767*8c35d5eeSXin Li    self.assertNotIn("[legal/copyright]", output)
5768*8c35d5eeSXin Li    self.assertNotIn("[build/header_guard]", output)
5769*8c35d5eeSXin Li    # --quiet was specified and there were no errors:
5770*8c35d5eeSXin Li    # skip the printing of 'Done processing' and 'Total errors..'
5771*8c35d5eeSXin Li    self.assertNotIn("Done processing", output)
5772*8c35d5eeSXin Li    self.assertNotIn("Total errors found:", output)
5773*8c35d5eeSXin Li    # Output with no errors must be completely blank!
5774*8c35d5eeSXin Li    self.assertEquals("", output)
5775*8c35d5eeSXin Li
5776*8c35d5eeSXin Li# pylint: disable-msg=C6409
5777*8c35d5eeSXin Lidef setUp():
5778*8c35d5eeSXin Li  """Runs before all tests are executed.
5779*8c35d5eeSXin Li  """
5780*8c35d5eeSXin Li  # Enable all filters, so we don't miss anything that is off by default.
5781*8c35d5eeSXin Li  cpplint._DEFAULT_FILTERS = []
5782*8c35d5eeSXin Li  cpplint._cpplint_state.SetFilters('')
5783*8c35d5eeSXin Li
5784*8c35d5eeSXin Li
5785*8c35d5eeSXin Li# pylint: disable-msg=C6409
5786*8c35d5eeSXin Lidef tearDown():
5787*8c35d5eeSXin Li  """A global check to make sure all error-categories have been tested.
5788*8c35d5eeSXin Li
5789*8c35d5eeSXin Li  The main tearDown() routine is the only code we can guarantee will be
5790*8c35d5eeSXin Li  run after all other tests have been executed.
5791*8c35d5eeSXin Li  """
5792*8c35d5eeSXin Li  try:
5793*8c35d5eeSXin Li    if _run_verifyallcategoriesseen:
5794*8c35d5eeSXin Li      ErrorCollector(None).VerifyAllCategoriesAreSeen()
5795*8c35d5eeSXin Li  except NameError:
5796*8c35d5eeSXin Li    # If nobody set the global _run_verifyallcategoriesseen, then
5797*8c35d5eeSXin Li    # we assume we should silently not run the test
5798*8c35d5eeSXin Li    pass
5799*8c35d5eeSXin Li
5800*8c35d5eeSXin Li
5801*8c35d5eeSXin Liif __name__ == '__main__':
5802*8c35d5eeSXin Li  # We don't want to run the VerifyAllCategoriesAreSeen() test unless
5803*8c35d5eeSXin Li  # we're running the full test suite: if we only run one test,
5804*8c35d5eeSXin Li  # obviously we're not going to see all the error categories.  So we
5805*8c35d5eeSXin Li  # only run VerifyAllCategoriesAreSeen() when no commandline flags
5806*8c35d5eeSXin Li  # are passed in.
5807*8c35d5eeSXin Li  global _run_verifyallcategoriesseen
5808*8c35d5eeSXin Li  _run_verifyallcategoriesseen = (len(sys.argv) == 1)
5809*8c35d5eeSXin Li
5810*8c35d5eeSXin Li  setUp()
5811*8c35d5eeSXin Li  unittest.main()
5812*8c35d5eeSXin Li  tearDown()
5813