Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(417)

Side by Side Diff: Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py

Issue 32663002: Remove _unit_test_config hack, instead use FileSystem() in cpp.py & cpp_unittest.py (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Updated to ToT, patch for landing! Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # -*- coding: utf-8; -*- 1 # -*- coding: utf-8; -*-
2 # 2 #
3 # Copyright (C) 2011 Google Inc. All rights reserved. 3 # Copyright (C) 2011 Google Inc. All rights reserved.
4 # Copyright (C) 2009 Torch Mobile Inc. 4 # Copyright (C) 2009 Torch Mobile Inc.
5 # Copyright (C) 2009 Apple Inc. All rights reserved. 5 # Copyright (C) 2009 Apple Inc. All rights reserved.
6 # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org) 6 # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
7 # 7 #
8 # Redistribution and use in source and binary forms, with or without 8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions are 9 # modification, are permitted provided that the following conditions are
10 # met: 10 # met:
(...skipping 17 matching lines...) Expand all
28 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 33
34 """Unit test for cpp_style.py.""" 34 """Unit test for cpp_style.py."""
35 35
36 # FIXME: Add a good test that tests UpdateIncludeState. 36 # FIXME: Add a good test that tests UpdateIncludeState.
37 37
38 import codecs
39 import os 38 import os
40 import random 39 import random
41 import re 40 import re
42 import webkitpy.thirdparty.unittest2 as unittest 41 import webkitpy.thirdparty.unittest2 as unittest
43 import cpp as cpp_style 42 import cpp as cpp_style
44 from cpp import CppChecker 43 from cpp import CppChecker
45 from ..filter import FilterConfiguration 44 from ..filter import FilterConfiguration
45 from webkitpy.common.system.filesystem import FileSystem
46 46
47 # This class works as an error collector and replaces cpp_style.Error 47 # This class works as an error collector and replaces cpp_style.Error
48 # function for the unit tests. We also verify each category we see 48 # function for the unit tests. We also verify each category we see
49 # is in STYLE_CATEGORIES, to help keep that list up to date. 49 # is in STYLE_CATEGORIES, to help keep that list up to date.
50 class ErrorCollector: 50 class ErrorCollector:
51 _all_style_categories = CppChecker.categories 51 _all_style_categories = CppChecker.categories
52 # This is a list including all categories seen in any unit test. 52 # This is a list including all categories seen in any unit test.
53 _seen_style_categories = {} 53 _seen_style_categories = {}
54 54
55 def __init__(self, assert_fn, filter=None, lines_to_check=None): 55 def __init__(self, assert_fn, filter=None, lines_to_check=None):
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 this isn't called from within the normal unittest framework, we 92 this isn't called from within the normal unittest framework, we
93 can't use the normal unittest assert macros. Instead we just exit 93 can't use the normal unittest assert macros. Instead we just exit
94 when we see an error. Good thing this test is always run last! 94 when we see an error. Good thing this test is always run last!
95 """ 95 """
96 for category in self._all_style_categories: 96 for category in self._all_style_categories:
97 if category not in self._seen_style_categories: 97 if category not in self._seen_style_categories:
98 import sys 98 import sys
99 sys.exit('FATAL ERROR: There are no tests for category "%s"' % c ategory) 99 sys.exit('FATAL ERROR: There are no tests for category "%s"' % c ategory)
100 100
101 101
102 # This class is a lame mock of codecs. We do not verify filename, mode, or
103 # encoding, but for the current use case it is not needed.
104 class MockIo:
105 def __init__(self, mock_file):
106 self.mock_file = mock_file
107
108 def open(self, unused_filename, unused_mode, unused_encoding, _): # NOLINT
109 # (lint doesn't like open as a method name)
110 return self.mock_file
111
112
113 class CppFunctionsTest(unittest.TestCase): 102 class CppFunctionsTest(unittest.TestCase):
114 103
115 """Supports testing functions that do not need CppStyleTestBase.""" 104 """Supports testing functions that do not need CppStyleTestBase."""
116 105
117 def test_convert_to_lower_with_underscores(self): 106 def test_convert_to_lower_with_underscores(self):
118 self.assertEqual(cpp_style._convert_to_lower_with_underscores('ABC'), 'a bc') 107 self.assertEqual(cpp_style._convert_to_lower_with_underscores('ABC'), 'a bc')
119 self.assertEqual(cpp_style._convert_to_lower_with_underscores('aB'), 'a_ b') 108 self.assertEqual(cpp_style._convert_to_lower_with_underscores('aB'), 'a_ b')
120 self.assertEqual(cpp_style._convert_to_lower_with_underscores('isAName') , 'is_a_name') 109 self.assertEqual(cpp_style._convert_to_lower_with_underscores('isAName') , 'is_a_name')
121 self.assertEqual(cpp_style._convert_to_lower_with_underscores('AnotherTe st'), 'another_test') 110 self.assertEqual(cpp_style._convert_to_lower_with_underscores('AnotherTe st'), 'another_test')
122 self.assertEqual(cpp_style._convert_to_lower_with_underscores('PassRefPt r<MyClass>'), 'pass_ref_ptr<my_class>') 111 self.assertEqual(cpp_style._convert_to_lower_with_underscores('PassRefPt r<MyClass>'), 'pass_ref_ptr<my_class>')
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 level for the tests. 228 level for the tests.
240 229
241 """ 230 """
242 231
243 # FIXME: Refactor the unit tests so the confidence level is passed 232 # FIXME: Refactor the unit tests so the confidence level is passed
244 # explicitly, just like it is in the real code. 233 # explicitly, just like it is in the real code.
245 min_confidence = 1; 234 min_confidence = 1;
246 235
247 # Helper function to avoid needing to explicitly pass confidence 236 # Helper function to avoid needing to explicitly pass confidence
248 # in all the unit test calls to cpp_style.process_file_data(). 237 # in all the unit test calls to cpp_style.process_file_data().
249 def process_file_data(self, filename, file_extension, lines, error, unit_tes t_config={}): 238 def process_file_data(self, filename, file_extension, lines, error, fs=None) :
250 """Call cpp_style.process_file_data() with the min_confidence.""" 239 """Call cpp_style.process_file_data() with the min_confidence."""
251 return cpp_style.process_file_data(filename, file_extension, lines, 240 return cpp_style.process_file_data(filename, file_extension, lines,
252 error, self.min_confidence, unit_test _config) 241 error, self.min_confidence, fs)
253 242
254 def perform_lint(self, code, filename, basic_error_rules, unit_test_config={ }, lines_to_check=None): 243 def perform_lint(self, code, filename, basic_error_rules, fs=None, lines_to_ check=None):
255 error_collector = ErrorCollector(self.assertTrue, FilterConfiguration(ba sic_error_rules), lines_to_check) 244 error_collector = ErrorCollector(self.assertTrue, FilterConfiguration(ba sic_error_rules), lines_to_check)
256 lines = code.split('\n') 245 lines = code.split('\n')
257 extension = filename.split('.')[1] 246 extension = filename.split('.')[1]
258 self.process_file_data(filename, extension, lines, error_collector, unit _test_config) 247 self.process_file_data(filename, extension, lines, error_collector, fs)
259 return error_collector.results() 248 return error_collector.results()
260 249
261 # Perform lint on single line of input and return the error message. 250 # Perform lint on single line of input and return the error message.
262 def perform_single_line_lint(self, code, filename): 251 def perform_single_line_lint(self, code, filename):
263 basic_error_rules = ('-build/header_guard', 252 basic_error_rules = ('-build/header_guard',
264 '-legal/copyright', 253 '-legal/copyright',
265 '-readability/fn_size', 254 '-readability/fn_size',
266 '-readability/parameter_name', 255 '-readability/parameter_name',
267 '-readability/pass_ptr', 256 '-readability/pass_ptr',
268 '-whitespace/ending_newline') 257 '-whitespace/ending_newline')
(...skipping 28 matching lines...) Expand all
297 '+readability/pass_ptr') 286 '+readability/pass_ptr')
298 return self.perform_lint(code, 'test.cpp', basic_error_rules) 287 return self.perform_lint(code, 'test.cpp', basic_error_rules)
299 288
300 # Only keep leaky pattern errors. 289 # Only keep leaky pattern errors.
301 def perform_leaky_pattern_check(self, code): 290 def perform_leaky_pattern_check(self, code):
302 basic_error_rules = ('-', 291 basic_error_rules = ('-',
303 '+runtime/leaky_pattern') 292 '+runtime/leaky_pattern')
304 return self.perform_lint(code, 'test.cpp', basic_error_rules) 293 return self.perform_lint(code, 'test.cpp', basic_error_rules)
305 294
306 # Only include what you use errors. 295 # Only include what you use errors.
307 def perform_include_what_you_use(self, code, filename='foo.h', io=codecs): 296 def perform_include_what_you_use(self, code, filename='foo.h', fs=None):
308 basic_error_rules = ('-', 297 basic_error_rules = ('-',
309 '+build/include_what_you_use') 298 '+build/include_what_you_use')
310 unit_test_config = {cpp_style.INCLUDE_IO_INJECTION_KEY: io} 299 return self.perform_lint(code, filename, basic_error_rules, fs)
311 return self.perform_lint(code, filename, basic_error_rules, unit_test_co nfig)
312 300
313 def perform_avoid_static_cast_of_objects(self, code, filename='foo.cpp', io= codecs): 301 def perform_avoid_static_cast_of_objects(self, code, filename='foo.cpp', fs= None):
314 basic_error_rules = ('-', 302 basic_error_rules = ('-',
315 '+runtime/casting') 303 '+runtime/casting')
316 unit_test_config = {cpp_style.INCLUDE_IO_INJECTION_KEY: io} 304 return self.perform_lint(code, filename, basic_error_rules, fs)
317 return self.perform_lint(code, filename, basic_error_rules, unit_test_co nfig)
318 305
319 # Perform lint and compare the error message with "expected_message". 306 # Perform lint and compare the error message with "expected_message".
320 def assert_lint(self, code, expected_message, file_name='foo.cpp'): 307 def assert_lint(self, code, expected_message, file_name='foo.cpp'):
321 self.assertEqual(expected_message, self.perform_single_line_lint(code, f ile_name)) 308 self.assertEqual(expected_message, self.perform_single_line_lint(code, f ile_name))
322 309
323 def assert_lint_one_of_many_errors_re(self, code, expected_message_re, file_ name='foo.cpp'): 310 def assert_lint_one_of_many_errors_re(self, code, expected_message_re, file_ name='foo.cpp'):
324 messages = self.perform_single_line_lint(code, file_name) 311 messages = self.perform_single_line_lint(code, file_name)
325 for message in messages: 312 for message in messages:
326 if re.search(expected_message_re, message): 313 if re.search(expected_message_re, message):
327 return 314 return
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after
766 'Do not use dynamic_cast<>. If you need to cast within a class ' 753 'Do not use dynamic_cast<>. If you need to cast within a class '
767 'hierarchy, use static_cast<> to upcast. Google doesn\'t support ' 754 'hierarchy, use static_cast<> to upcast. Google doesn\'t support '
768 'RTTI. [runtime/rtti] [5]') 755 'RTTI. [runtime/rtti] [5]')
769 # dynamic_cast is disallowed in most files. 756 # dynamic_cast is disallowed in most files.
770 self.assert_language_rules_check('foo.cpp', statement, error_message) 757 self.assert_language_rules_check('foo.cpp', statement, error_message)
771 self.assert_language_rules_check('foo.h', statement, error_message) 758 self.assert_language_rules_check('foo.h', statement, error_message)
772 759
773 # Tests for static_cast readability. 760 # Tests for static_cast readability.
774 def test_static_cast_on_objects_with_toFoo(self): 761 def test_static_cast_on_objects_with_toFoo(self):
775 mock_header_contents = ['inline Foo* toFoo(Bar* bar)'] 762 mock_header_contents = ['inline Foo* toFoo(Bar* bar)']
776 message = self.perform_avoid_static_cast_of_objects( 763 fs = FileSystem()
777 'Foo* x = static_cast<Foo*>(bar);', 764 orig_read_text_file_fn = fs.read_text_file
778 filename='casting.cpp', 765
779 io=MockIo(mock_header_contents)) 766 def mock_read_text_file_fn(path):
780 self.assertEqual(message, 'static_cast of class objects is not allowed. Use toFoo defined in Foo.h.' 767 return mock_header_contents
781 ' [runtime/casting] [4]') 768
769 try:
770 fs.read_text_file = mock_read_text_file_fn
771 message = self.perform_avoid_static_cast_of_objects(
772 'Foo* x = static_cast<Foo*>(bar);',
773 filename='casting.cpp',
774 fs=fs)
775 self.assertEqual(message, 'static_cast of class objects is not allow ed. Use toFoo defined in Foo.h.'
776 ' [runtime/casting] [4]')
777 finally:
778 fs.read_text_file = orig_read_text_file_fn
782 779
783 def test_static_cast_on_objects_without_toFoo(self): 780 def test_static_cast_on_objects_without_toFoo(self):
784 mock_header_contents = ['inline FooBar* toFooBar(Bar* bar)'] 781 mock_header_contents = ['inline FooBar* toFooBar(Bar* bar)']
785 message = self.perform_avoid_static_cast_of_objects( 782 fs = FileSystem()
786 'Foo* x = static_cast<Foo*>(bar);', 783 orig_read_text_file_fn = fs.read_text_file
787 filename='casting.cpp', 784
788 io=MockIo(mock_header_contents)) 785 def mock_read_text_file_fn(path):
789 self.assertEqual(message, 'static_cast of class objects is not allowed. Add toFoo in Foo.h and use it instead.' 786 return mock_header_contents
790 ' [runtime/casting] [4]') 787
788 try:
789 fs.read_text_file = mock_read_text_file_fn
790 message = self.perform_avoid_static_cast_of_objects(
791 'Foo* x = static_cast<Foo*>(bar);',
792 filename='casting.cpp',
793 fs=fs)
794 self.assertEqual(message, 'static_cast of class objects is not allow ed. Add toFoo in Foo.h and use it instead.'
795 ' [runtime/casting] [4]')
796 finally:
797 fs.read_text_file = orig_read_text_file_fn
791 798
792 # We cannot test this functionality because of difference of 799 # We cannot test this functionality because of difference of
793 # function definitions. Anyway, we may never enable this. 800 # function definitions. Anyway, we may never enable this.
794 # 801 #
795 # # Test for unnamed arguments in a method. 802 # # Test for unnamed arguments in a method.
796 # def test_check_for_unnamed_params(self): 803 # def test_check_for_unnamed_params(self):
797 # message = ('All parameters should be named in a function' 804 # message = ('All parameters should be named in a function'
798 # ' [readability/function] [3]') 805 # ' [readability/function] [3]')
799 # self.assert_lint('virtual void A(int*) const;', message) 806 # self.assert_lint('virtual void A(int*) const;', message)
800 # self.assert_lint('virtual void B(void (*fn)(int*));', message) 807 # self.assert_lint('virtual void B(void (*fn)(int*));', message)
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 'Add #include <limits> for numeric_limits<>' 1014 'Add #include <limits> for numeric_limits<>'
1008 ' [build/include_what_you_use] [4]') 1015 ' [build/include_what_you_use] [4]')
1009 self.assert_include_what_you_use( 1016 self.assert_include_what_you_use(
1010 '''#include <limits> 1017 '''#include <limits>
1011 int i = numeric_limits<int>::max() 1018 int i = numeric_limits<int>::max()
1012 ''', 1019 ''',
1013 '') 1020 '')
1014 1021
1015 # Test the UpdateIncludeState code path. 1022 # Test the UpdateIncludeState code path.
1016 mock_header_contents = ['#include "blah/foo.h"', '#include "blah/bar.h"' ] 1023 mock_header_contents = ['#include "blah/foo.h"', '#include "blah/bar.h"' ]
1017 message = self.perform_include_what_you_use( 1024 fs = FileSystem()
1018 '#include "config.h"\n' 1025 orig_read_text_file_fn = fs.read_text_file
1019 '#include "blah/a.h"\n',
1020 filename='blah/a.cpp',
1021 io=MockIo(mock_header_contents))
1022 self.assertEqual(message, '')
1023 1026
1024 mock_header_contents = ['#include <set>'] 1027 def mock_read_text_file_fn(path):
1025 message = self.perform_include_what_you_use( 1028 return mock_header_contents
1026 '''#include "config.h"
1027 #include "blah/a.h"
1028 1029
1029 std::set<int> foo;''', 1030 try:
1030 filename='blah/a.cpp', 1031 fs.read_text_file = mock_read_text_file_fn
1031 io=MockIo(mock_header_contents)) 1032 message = self.perform_include_what_you_use(
1032 self.assertEqual(message, '') 1033 '#include "config.h"\n'
1034 '#include "blah/a.h"\n',
1035 filename='blah/a.cpp',
1036 fs=fs)
1037 self.assertEqual(message, '')
1033 1038
1034 # If there's just a .cpp and the header can't be found then it's ok. 1039 mock_header_contents = ['#include <set>']
1035 message = self.perform_include_what_you_use( 1040 message = self.perform_include_what_you_use(
1036 '''#include "config.h" 1041 '''#include "config.h"
1037 #include "blah/a.h" 1042 #include "blah/a.h"
1038 1043
1039 std::set<int> foo;''', 1044 std::set<int> foo;''',
1040 filename='blah/a.cpp') 1045 filename='blah/a.cpp',
1041 self.assertEqual(message, '') 1046 fs=fs)
1047 self.assertEqual(message, '')
1042 1048
1043 # Make sure we find the headers with relative paths. 1049 # If there's just a .cpp and the header can't be found then it's ok.
1044 mock_header_contents = [''] 1050 message = self.perform_include_what_you_use(
1045 message = self.perform_include_what_you_use( 1051 '''#include "config.h"
1046 '''#include "config.h" 1052 #include "blah/a.h"
1047 #include "%s%sa.h"
1048 1053
1049 std::set<int> foo;''' % (os.path.basename(os.getcwd()), os.path.s ep), 1054 std::set<int> foo;''',
1050 filename='a.cpp', 1055 filename='blah/a.cpp')
1051 io=MockIo(mock_header_contents)) 1056 self.assertEqual(message, '')
1052 self.assertEqual(message, 'Add #include <set> for set<> ' 1057
1053 '[build/include_what_you_use] [4]') 1058 # Make sure we find the headers with relative paths.
1059 mock_header_contents = ['']
1060 message = self.perform_include_what_you_use(
1061 '''#include "config.h"
1062 #include "%s%sa.h"
1063
1064 std::set<int> foo;''' % (os.path.basename(os.getcwd()), os.pa th.sep),
1065 filename='a.cpp',
1066 fs=fs)
1067 self.assertEqual(message, 'Add #include <set> for set<> '
1068 '[build/include_what_you_use] [4]')
1069 finally:
1070 fs.read_text_file = orig_read_text_file_fn
1054 1071
1055 def test_files_belong_to_same_module(self): 1072 def test_files_belong_to_same_module(self):
1056 f = cpp_style.files_belong_to_same_module 1073 f = cpp_style.files_belong_to_same_module
1057 self.assertEqual((True, ''), f('a.cpp', 'a.h')) 1074 self.assertEqual((True, ''), f('a.cpp', 'a.h'))
1058 self.assertEqual((True, ''), f('base/google.cpp', 'base/google.h')) 1075 self.assertEqual((True, ''), f('base/google.cpp', 'base/google.h'))
1059 self.assertEqual((True, ''), f('base/google_test.cpp', 'base/google.h')) 1076 self.assertEqual((True, ''), f('base/google_test.cpp', 'base/google.h'))
1060 self.assertEqual((True, ''), 1077 self.assertEqual((True, ''),
1061 f('base/google_unittest.cpp', 'base/google.h')) 1078 f('base/google_unittest.cpp', 'base/google.h'))
1062 self.assertEqual((True, ''), 1079 self.assertEqual((True, ''),
1063 f('base/internal/google_unittest.cpp', 1080 f('base/internal/google_unittest.cpp',
(...skipping 4104 matching lines...) Expand 10 before | Expand all | Expand 10 after
5168 def test_ne(self): 5185 def test_ne(self):
5169 """Test __ne__ inequality function.""" 5186 """Test __ne__ inequality function."""
5170 checker1 = self._checker() 5187 checker1 = self._checker()
5171 checker2 = self._checker() 5188 checker2 = self._checker()
5172 5189
5173 # != calls __ne__. 5190 # != calls __ne__.
5174 # By default, __ne__ always returns true on different objects. 5191 # By default, __ne__ always returns true on different objects.
5175 # Thus, just check the distinguishing case to verify that the 5192 # Thus, just check the distinguishing case to verify that the
5176 # code defines __ne__. 5193 # code defines __ne__.
5177 self.assertFalse(checker1 != checker2) 5194 self.assertFalse(checker1 != checker2)
OLDNEW
« Tools/Scripts/webkitpy/style/checkers/cpp.py ('K') | « Tools/Scripts/webkitpy/style/checkers/cpp.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698