Home | History | Annotate | Download | only in style
      1 #!/usr/bin/python
      2 # -*- coding: utf-8; -*-
      3 #
      4 # Copyright (C) 2009 Google Inc. All rights reserved.
      5 # Copyright (C) 2009 Torch Mobile Inc.
      6 # Copyright (C) 2009 Apple Inc. All rights reserved.
      7 # Copyright (C) 2010 Chris Jerdonek (chris.jerdonek (at] gmail.com)
      8 #
      9 # Redistribution and use in source and binary forms, with or without
     10 # modification, are permitted provided that the following conditions are
     11 # met:
     12 #
     13 #    * Redistributions of source code must retain the above copyright
     14 # notice, this list of conditions and the following disclaimer.
     15 #    * Redistributions in binary form must reproduce the above
     16 # copyright notice, this list of conditions and the following disclaimer
     17 # in the documentation and/or other materials provided with the
     18 # distribution.
     19 #    * Neither the name of Google Inc. nor the names of its
     20 # contributors may be used to endorse or promote products derived from
     21 # this software without specific prior written permission.
     22 #
     23 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     24 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     25 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     26 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     27 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     28 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     29 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     30 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     31 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     32 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     33 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     34 
     35 """Unit tests for style.py."""
     36 
     37 import unittest
     38 
     39 import checker as style
     40 from checker import _PATH_RULES_SPECIFIER as PATH_RULES_SPECIFIER
     41 from checker import style_categories
     42 from checker import ProcessorDispatcher
     43 from checker import ProcessorOptions
     44 from checker import StyleChecker
     45 from filter import validate_filter_rules
     46 from filter import FilterConfiguration
     47 from processors.cpp import CppProcessor
     48 from processors.text import TextProcessor
     49 
     50 
     51 class ProcessorOptionsTest(unittest.TestCase):
     52 
     53     """Tests ProcessorOptions class."""
     54 
     55     def test_init(self):
     56         """Test __init__ constructor."""
     57         # Check default parameters.
     58         options = ProcessorOptions()
     59         self.assertEquals(options.extra_flag_values, {})
     60         self.assertEquals(options.filter_configuration, FilterConfiguration())
     61         self.assertEquals(options.git_commit, None)
     62         self.assertEquals(options.max_reports_per_category, {})
     63         self.assertEquals(options.output_format, "emacs")
     64         self.assertEquals(options.verbosity, 1)
     65 
     66         # Check argument validation.
     67         self.assertRaises(ValueError, ProcessorOptions, output_format="bad")
     68         ProcessorOptions(output_format="emacs") # No ValueError: works
     69         ProcessorOptions(output_format="vs7") # works
     70         self.assertRaises(ValueError, ProcessorOptions, verbosity=0)
     71         self.assertRaises(ValueError, ProcessorOptions, verbosity=6)
     72         ProcessorOptions(verbosity=1) # works
     73         ProcessorOptions(verbosity=5) # works
     74 
     75         # Check attributes.
     76         filter_configuration = FilterConfiguration(base_rules=["+"])
     77         options = ProcessorOptions(extra_flag_values={"extra_value" : 2},
     78                                    filter_configuration=filter_configuration,
     79                                    git_commit="commit",
     80                                    max_reports_per_category={"category": 3},
     81                                    output_format="vs7",
     82                                    verbosity=3)
     83         self.assertEquals(options.extra_flag_values, {"extra_value" : 2})
     84         self.assertEquals(options.filter_configuration, filter_configuration)
     85         self.assertEquals(options.git_commit, "commit")
     86         self.assertEquals(options.max_reports_per_category, {"category": 3})
     87         self.assertEquals(options.output_format, "vs7")
     88         self.assertEquals(options.verbosity, 3)
     89 
     90     def test_eq(self):
     91         """Test __eq__ equality function."""
     92         # == calls __eq__.
     93         self.assertTrue(ProcessorOptions() == ProcessorOptions())
     94 
     95         # Verify that a difference in any argument causes equality to fail.
     96         filter_configuration = FilterConfiguration(base_rules=["+"])
     97         options = ProcessorOptions(extra_flag_values={"extra_value" : 1},
     98                                    filter_configuration=filter_configuration,
     99                                    git_commit="commit",
    100                                    max_reports_per_category={"category": 3},
    101                                    output_format="vs7",
    102                                    verbosity=1)
    103         self.assertFalse(options == ProcessorOptions(extra_flag_values={"extra_value" : 2}))
    104         new_config = FilterConfiguration(base_rules=["-"])
    105         self.assertFalse(options ==
    106                          ProcessorOptions(filter_configuration=new_config))
    107         self.assertFalse(options == ProcessorOptions(git_commit="commit2"))
    108         self.assertFalse(options == ProcessorOptions(max_reports_per_category=
    109                                                      {"category": 2}))
    110         self.assertFalse(options == ProcessorOptions(output_format="emacs"))
    111         self.assertFalse(options == ProcessorOptions(verbosity=2))
    112 
    113     def test_ne(self):
    114         """Test __ne__ inequality function."""
    115         # != calls __ne__.
    116         # By default, __ne__ always returns true on different objects.
    117         # Thus, just check the distinguishing case to verify that the
    118         # code defines __ne__.
    119         self.assertFalse(ProcessorOptions() != ProcessorOptions())
    120 
    121     def test_is_reportable(self):
    122         """Test is_reportable()."""
    123         filter_configuration = FilterConfiguration(base_rules=["-xyz"])
    124         options = ProcessorOptions(filter_configuration=filter_configuration,
    125                                    verbosity=3)
    126 
    127         # Test verbosity
    128         self.assertTrue(options.is_reportable("abc", 3, "foo.h"))
    129         self.assertFalse(options.is_reportable("abc", 2, "foo.h"))
    130 
    131         # Test filter
    132         self.assertTrue(options.is_reportable("xy", 3, "foo.h"))
    133         self.assertFalse(options.is_reportable("xyz", 3, "foo.h"))
    134 
    135 
    136 class GlobalVariablesTest(unittest.TestCase):
    137 
    138     """Tests validity of the global variables."""
    139 
    140     def _all_categories(self):
    141         return style.style_categories()
    142 
    143     def defaults(self):
    144         return style.webkit_argument_defaults()
    145 
    146     def test_filter_rules(self):
    147         defaults = self.defaults()
    148         already_seen = []
    149         validate_filter_rules(defaults.base_filter_rules,
    150                               self._all_categories())
    151         # Also do some additional checks.
    152         for rule in defaults.base_filter_rules:
    153             # Check no leading or trailing white space.
    154             self.assertEquals(rule, rule.strip())
    155             # All categories are on by default, so defaults should
    156             # begin with -.
    157             self.assertTrue(rule.startswith('-'))
    158             # Check no rule occurs twice.
    159             self.assertFalse(rule in already_seen)
    160             already_seen.append(rule)
    161 
    162     def test_defaults(self):
    163         """Check that default arguments are valid."""
    164         defaults = self.defaults()
    165 
    166         # FIXME: We should not need to call parse() to determine
    167         #        whether the default arguments are valid.
    168         parser = style.ArgumentParser(defaults)
    169         # No need to test the return value here since we test parse()
    170         # on valid arguments elsewhere.
    171         parser.parse([]) # arguments valid: no error or SystemExit
    172 
    173     def test_path_rules_specifier(self):
    174         all_categories = style_categories()
    175         for (sub_paths, path_rules) in PATH_RULES_SPECIFIER:
    176             self.assertTrue(isinstance(path_rules, tuple),
    177                             "Checking: " + str(path_rules))
    178             validate_filter_rules(path_rules, self._all_categories())
    179 
    180         # Try using the path specifier (as an "end-to-end" check).
    181         config = FilterConfiguration(path_specific=PATH_RULES_SPECIFIER)
    182         self.assertTrue(config.should_check("xxx_any_category",
    183                                             "xxx_non_matching_path"))
    184         self.assertTrue(config.should_check("xxx_any_category",
    185                                             "WebKitTools/WebKitAPITest/"))
    186         self.assertFalse(config.should_check("build/include",
    187                                              "WebKitTools/WebKitAPITest/"))
    188         self.assertFalse(config.should_check("readability/naming",
    189                              "WebKit/qt/tests/qwebelement/tst_qwebelement.cpp"))
    190 
    191     def test_max_reports_per_category(self):
    192         """Check that MAX_REPORTS_PER_CATEGORY is valid."""
    193         all_categories = self._all_categories()
    194         for category in style.MAX_REPORTS_PER_CATEGORY.iterkeys():
    195             self.assertTrue(category in all_categories,
    196                             'Key "%s" is not a category' % category)
    197 
    198 
    199 class ArgumentPrinterTest(unittest.TestCase):
    200 
    201     """Tests the ArgumentPrinter class."""
    202 
    203     _printer = style.ArgumentPrinter()
    204 
    205     def _create_options(self,
    206                         output_format='emacs',
    207                         verbosity=3,
    208                         user_rules=[],
    209                         git_commit=None,
    210                         extra_flag_values={}):
    211         filter_configuration = FilterConfiguration(user_rules=user_rules)
    212         return style.ProcessorOptions(extra_flag_values=extra_flag_values,
    213                                       filter_configuration=filter_configuration,
    214                                       git_commit=git_commit,
    215                                       output_format=output_format,
    216                                       verbosity=verbosity)
    217 
    218     def test_to_flag_string(self):
    219         options = self._create_options('vs7', 5, ['+foo', '-bar'], 'git',
    220                                        {'a': 0, 'z': 1})
    221         self.assertEquals('--a=0 --filter=+foo,-bar --git-commit=git '
    222                           '--output=vs7 --verbose=5 --z=1',
    223                           self._printer.to_flag_string(options))
    224 
    225         # This is to check that --filter and --git-commit do not
    226         # show up when not user-specified.
    227         options = self._create_options()
    228         self.assertEquals('--output=emacs --verbose=3',
    229                           self._printer.to_flag_string(options))
    230 
    231 
    232 class ArgumentParserTest(unittest.TestCase):
    233 
    234     """Test the ArgumentParser class."""
    235 
    236     def _parse(self):
    237         """Return a default parse() function for testing."""
    238         return self._create_parser().parse
    239 
    240     def _create_defaults(self, default_output_format='vs7',
    241                          default_verbosity=3,
    242                          default_filter_rules=['-', '+whitespace']):
    243         """Return a default ArgumentDefaults instance for testing."""
    244         return style.ArgumentDefaults(default_output_format,
    245                                       default_verbosity,
    246                                       default_filter_rules)
    247 
    248     def _create_parser(self, defaults=None):
    249         """Return an ArgumentParser instance for testing."""
    250         def create_usage(_defaults):
    251             """Return a usage string for testing."""
    252             return "usage"
    253 
    254         def doc_print(message):
    255             # We do not want the usage string or style categories
    256             # to print during unit tests, so print nothing.
    257             return
    258 
    259         if defaults is None:
    260             defaults = self._create_defaults()
    261 
    262         return style.ArgumentParser(defaults, create_usage, doc_print)
    263 
    264     def test_parse_documentation(self):
    265         parse = self._parse()
    266 
    267         # FIXME: Test both the printing of the usage string and the
    268         #        filter categories help.
    269 
    270         # Request the usage string.
    271         self.assertRaises(SystemExit, parse, ['--help'])
    272         # Request default filter rules and available style categories.
    273         self.assertRaises(SystemExit, parse, ['--filter='])
    274 
    275     def test_parse_bad_values(self):
    276         parse = self._parse()
    277 
    278         # Pass an unsupported argument.
    279         self.assertRaises(SystemExit, parse, ['--bad'])
    280 
    281         self.assertRaises(ValueError, parse, ['--verbose=bad'])
    282         self.assertRaises(ValueError, parse, ['--verbose=0'])
    283         self.assertRaises(ValueError, parse, ['--verbose=6'])
    284         parse(['--verbose=1']) # works
    285         parse(['--verbose=5']) # works
    286 
    287         self.assertRaises(ValueError, parse, ['--output=bad'])
    288         parse(['--output=vs7']) # works
    289 
    290         # Pass a filter rule not beginning with + or -.
    291         self.assertRaises(ValueError, parse, ['--filter=build'])
    292         parse(['--filter=+build']) # works
    293         # Pass files and git-commit at the same time.
    294         self.assertRaises(SystemExit, parse, ['--git-commit=', 'file.txt'])
    295         # Pass an extra flag already supported.
    296         self.assertRaises(ValueError, parse, [], ['filter='])
    297         parse([], ['extra=']) # works
    298         # Pass an extra flag with typo.
    299         self.assertRaises(SystemExit, parse, ['--extratypo='], ['extra='])
    300         parse(['--extra='], ['extra=']) # works
    301         self.assertRaises(ValueError, parse, [], ['extra=', 'extra='])
    302 
    303 
    304     def test_parse_default_arguments(self):
    305         parse = self._parse()
    306 
    307         (files, options) = parse([])
    308 
    309         self.assertEquals(files, [])
    310 
    311         self.assertEquals(options.output_format, 'vs7')
    312         self.assertEquals(options.verbosity, 3)
    313         self.assertEquals(options.filter_configuration,
    314                           FilterConfiguration(base_rules=["-", "+whitespace"],
    315                               path_specific=PATH_RULES_SPECIFIER))
    316         self.assertEquals(options.git_commit, None)
    317 
    318     def test_parse_explicit_arguments(self):
    319         parse = self._parse()
    320 
    321         # Pass non-default explicit values.
    322         (files, options) = parse(['--output=emacs'])
    323         self.assertEquals(options.output_format, 'emacs')
    324         (files, options) = parse(['--verbose=4'])
    325         self.assertEquals(options.verbosity, 4)
    326         (files, options) = parse(['--git-commit=commit'])
    327         self.assertEquals(options.git_commit, 'commit')
    328 
    329         # Pass user_rules.
    330         (files, options) = parse(['--filter=+build,-whitespace'])
    331         config = options.filter_configuration
    332         self.assertEquals(options.filter_configuration,
    333                           FilterConfiguration(base_rules=["-", "+whitespace"],
    334                               path_specific=PATH_RULES_SPECIFIER,
    335                               user_rules=["+build", "-whitespace"]))
    336 
    337         # Pass spurious white space in user rules.
    338         (files, options) = parse(['--filter=+build, -whitespace'])
    339         self.assertEquals(options.filter_configuration,
    340                           FilterConfiguration(base_rules=["-", "+whitespace"],
    341                               path_specific=PATH_RULES_SPECIFIER,
    342                               user_rules=["+build", "-whitespace"]))
    343 
    344         # Pass extra flag values.
    345         (files, options) = parse(['--extra'], ['extra'])
    346         self.assertEquals(options.extra_flag_values, {'--extra': ''})
    347         (files, options) = parse(['--extra='], ['extra='])
    348         self.assertEquals(options.extra_flag_values, {'--extra': ''})
    349         (files, options) = parse(['--extra=x'], ['extra='])
    350         self.assertEquals(options.extra_flag_values, {'--extra': 'x'})
    351 
    352     def test_parse_files(self):
    353         parse = self._parse()
    354 
    355         (files, options) = parse(['foo.cpp'])
    356         self.assertEquals(files, ['foo.cpp'])
    357 
    358         # Pass multiple files.
    359         (files, options) = parse(['--output=emacs', 'foo.cpp', 'bar.cpp'])
    360         self.assertEquals(files, ['foo.cpp', 'bar.cpp'])
    361 
    362 
    363 class ProcessorDispatcherSkipTest(unittest.TestCase):
    364 
    365     """Tests the "should skip" methods of the ProcessorDispatcher class."""
    366 
    367     def test_should_skip_with_warning(self):
    368         """Test should_skip_with_warning()."""
    369         dispatcher = ProcessorDispatcher()
    370 
    371         # Check a non-skipped file.
    372         self.assertFalse(dispatcher.should_skip_with_warning("foo.txt"))
    373 
    374         # Check skipped files.
    375         paths_to_skip = [
    376            "gtk2drawing.c",
    377            "gtk2drawing.h",
    378            "JavaScriptCore/qt/api/qscriptengine_p.h",
    379            "WebCore/platform/gtk/gtk2drawing.c",
    380            "WebCore/platform/gtk/gtk2drawing.h",
    381            "WebKit/gtk/tests/testatk.c",
    382            "WebKit/qt/Api/qwebpage.h",
    383            "WebKit/qt/tests/qwebsecurityorigin/tst_qwebsecurityorigin.cpp",
    384             ]
    385 
    386         for path in paths_to_skip:
    387             self.assertTrue(dispatcher.should_skip_with_warning(path),
    388                             "Checking: " + path)
    389 
    390     def test_should_skip_without_warning(self):
    391         """Test should_skip_without_warning()."""
    392         dispatcher = ProcessorDispatcher()
    393 
    394         # Check a non-skipped file.
    395         self.assertFalse(dispatcher.should_skip_without_warning("foo.txt"))
    396 
    397         # Check skipped files.
    398         paths_to_skip = [
    399            # LayoutTests folder
    400            "LayoutTests/foo.txt",
    401             ]
    402 
    403         for path in paths_to_skip:
    404             self.assertTrue(dispatcher.should_skip_without_warning(path),
    405                             "Checking: " + path)
    406 
    407 
    408 class ProcessorDispatcherDispatchTest(unittest.TestCase):
    409 
    410     """Tests dispatch_processor() method of ProcessorDispatcher class."""
    411 
    412     def mock_handle_style_error(self):
    413         pass
    414 
    415     def dispatch_processor(self, file_path):
    416         """Call dispatch_processor() with the given file path."""
    417         dispatcher = ProcessorDispatcher()
    418         processor = dispatcher.dispatch_processor(file_path,
    419                                                   self.mock_handle_style_error,
    420                                                   verbosity=3)
    421         return processor
    422 
    423     def assert_processor_none(self, file_path):
    424         """Assert that the dispatched processor is None."""
    425         processor = self.dispatch_processor(file_path)
    426         self.assertTrue(processor is None, 'Checking: "%s"' % file_path)
    427 
    428     def assert_processor(self, file_path, expected_class):
    429         """Assert the type of the dispatched processor."""
    430         processor = self.dispatch_processor(file_path)
    431         got_class = processor.__class__
    432         self.assertEquals(got_class, expected_class,
    433                           'For path "%(file_path)s" got %(got_class)s when '
    434                           "expecting %(expected_class)s."
    435                           % {"file_path": file_path,
    436                              "got_class": got_class,
    437                              "expected_class": expected_class})
    438 
    439     def assert_processor_cpp(self, file_path):
    440         """Assert that the dispatched processor is a CppProcessor."""
    441         self.assert_processor(file_path, CppProcessor)
    442 
    443     def assert_processor_text(self, file_path):
    444         """Assert that the dispatched processor is a TextProcessor."""
    445         self.assert_processor(file_path, TextProcessor)
    446 
    447     def test_cpp_paths(self):
    448         """Test paths that should be checked as C++."""
    449         paths = [
    450             "-",
    451             "foo.c",
    452             "foo.cpp",
    453             "foo.h",
    454             ]
    455 
    456         for path in paths:
    457             self.assert_processor_cpp(path)
    458 
    459         # Check processor attributes on a typical input.
    460         file_base = "foo"
    461         file_extension = "c"
    462         file_path = file_base + "." + file_extension
    463         self.assert_processor_cpp(file_path)
    464         processor = self.dispatch_processor(file_path)
    465         self.assertEquals(processor.file_extension, file_extension)
    466         self.assertEquals(processor.file_path, file_path)
    467         self.assertEquals(processor.handle_style_error, self.mock_handle_style_error)
    468         self.assertEquals(processor.verbosity, 3)
    469         # Check "-" for good measure.
    470         file_base = "-"
    471         file_extension = ""
    472         file_path = file_base
    473         self.assert_processor_cpp(file_path)
    474         processor = self.dispatch_processor(file_path)
    475         self.assertEquals(processor.file_extension, file_extension)
    476         self.assertEquals(processor.file_path, file_path)
    477 
    478     def test_text_paths(self):
    479         """Test paths that should be checked as text."""
    480         paths = [
    481            "ChangeLog",
    482            "foo.css",
    483            "foo.html",
    484            "foo.idl",
    485            "foo.js",
    486            "foo.mm",
    487            "foo.php",
    488            "foo.pm",
    489            "foo.py",
    490            "foo.txt",
    491            "FooChangeLog.bak",
    492            "WebCore/ChangeLog",
    493            "WebCore/inspector/front-end/inspector.js",
    494            "WebKitTools/Scripts/check-webkit=style",
    495            "WebKitTools/Scripts/modules/text_style.py",
    496             ]
    497 
    498         for path in paths:
    499             self.assert_processor_text(path)
    500 
    501         # Check processor attributes on a typical input.
    502         file_base = "foo"
    503         file_extension = "css"
    504         file_path = file_base + "." + file_extension
    505         self.assert_processor_text(file_path)
    506         processor = self.dispatch_processor(file_path)
    507         self.assertEquals(processor.file_path, file_path)
    508         self.assertEquals(processor.handle_style_error, self.mock_handle_style_error)
    509 
    510     def test_none_paths(self):
    511         """Test paths that have no file type.."""
    512         paths = [
    513            "Makefile",
    514            "foo.png",
    515            "foo.exe",
    516             ]
    517 
    518         for path in paths:
    519             self.assert_processor_none(path)
    520 
    521 
    522 class StyleCheckerTest(unittest.TestCase):
    523 
    524     """Test the StyleChecker class.
    525 
    526     Attributes:
    527       error_messages: A string containing all of the warning messages
    528                       written to the mock_stderr_write method of
    529                       this class.
    530 
    531     """
    532 
    533     def _mock_stderr_write(self, message):
    534         pass
    535 
    536     def _style_checker(self, options):
    537         return StyleChecker(options, self._mock_stderr_write)
    538 
    539     def test_init(self):
    540         """Test __init__ constructor."""
    541         options = ProcessorOptions()
    542         style_checker = self._style_checker(options)
    543 
    544         self.assertEquals(style_checker.error_count, 0)
    545         self.assertEquals(style_checker.options, options)
    546 
    547 
    548 class StyleCheckerCheckFileTest(unittest.TestCase):
    549 
    550     """Test the check_file() method of the StyleChecker class.
    551 
    552     The check_file() method calls its process_file parameter when
    553     given a file that should not be skipped.
    554 
    555     The "got_*" attributes of this class are the parameters passed
    556     to process_file by calls to check_file() made by this test
    557     class. These attributes allow us to check the parameter values
    558     passed internally to the process_file function.
    559 
    560     Attributes:
    561       got_file_path: The file_path parameter passed by check_file()
    562                      to its process_file parameter.
    563       got_handle_style_error: The handle_style_error parameter passed
    564                               by check_file() to its process_file
    565                               parameter.
    566       got_processor: The processor parameter passed by check_file() to
    567                      its process_file parameter.
    568       warning_messages: A string containing all of the warning messages
    569                         written to the mock_stderr_write method of
    570                         this class.
    571 
    572     """
    573     def setUp(self):
    574         self.got_file_path = None
    575         self.got_handle_style_error = None
    576         self.got_processor = None
    577         self.warning_messages = ""
    578 
    579     def mock_stderr_write(self, warning_message):
    580         self.warning_messages += warning_message
    581 
    582     def mock_handle_style_error(self):
    583         pass
    584 
    585     def mock_process_file(self, processor, file_path, handle_style_error):
    586         """A mock _process_file().
    587 
    588         See the documentation for this class for more information
    589         on this function.
    590 
    591         """
    592         self.got_file_path = file_path
    593         self.got_handle_style_error = handle_style_error
    594         self.got_processor = processor
    595 
    596     def assert_attributes(self,
    597                           expected_file_path,
    598                           expected_handle_style_error,
    599                           expected_processor,
    600                           expected_warning_messages):
    601         """Assert that the attributes of this class equal the given values."""
    602         self.assertEquals(self.got_file_path, expected_file_path)
    603         self.assertEquals(self.got_handle_style_error, expected_handle_style_error)
    604         self.assertEquals(self.got_processor, expected_processor)
    605         self.assertEquals(self.warning_messages, expected_warning_messages)
    606 
    607     def call_check_file(self, file_path):
    608         """Call the check_file() method of a test StyleChecker instance."""
    609         # Confirm that the attributes are reset.
    610         self.assert_attributes(None, None, None, "")
    611 
    612         # Create a test StyleChecker instance.
    613         #
    614         # The verbosity attribute is the only ProcessorOptions
    615         # attribute that needs to be checked in this test.
    616         # This is because it is the only option is directly
    617         # passed to the constructor of a style processor.
    618         options = ProcessorOptions(verbosity=3)
    619 
    620         style_checker = StyleChecker(options, self.mock_stderr_write)
    621 
    622         style_checker.check_file(file_path,
    623                                  self.mock_handle_style_error,
    624                                  self.mock_process_file)
    625 
    626     def test_check_file_on_skip_without_warning(self):
    627         """Test check_file() for a skipped-without-warning file."""
    628 
    629         file_path = "LayoutTests/foo.txt"
    630 
    631         dispatcher = ProcessorDispatcher()
    632         # Confirm that the input file is truly a skipped-without-warning file.
    633         self.assertTrue(dispatcher.should_skip_without_warning(file_path))
    634 
    635         # Check the outcome.
    636         self.call_check_file(file_path)
    637         self.assert_attributes(None, None, None, "")
    638 
    639     def test_check_file_on_skip_with_warning(self):
    640         """Test check_file() for a skipped-with-warning file."""
    641 
    642         file_path = "gtk2drawing.c"
    643 
    644         dispatcher = ProcessorDispatcher()
    645         # Check that the input file is truly a skipped-with-warning file.
    646         self.assertTrue(dispatcher.should_skip_with_warning(file_path))
    647 
    648         # Check the outcome.
    649         self.call_check_file(file_path)
    650         self.assert_attributes(None, None, None,
    651                                'Ignoring "gtk2drawing.c": this file is exempt from the style guide.\n')
    652 
    653     def test_check_file_on_non_skipped(self):
    654 
    655         # We use a C++ file since by using a CppProcessor, we can check
    656         # that all of the possible information is getting passed to
    657         # process_file (in particular, the verbosity).
    658         file_base = "foo"
    659         file_extension = "cpp"
    660         file_path = file_base + "." + file_extension
    661 
    662         dispatcher = ProcessorDispatcher()
    663         # Check that the input file is truly a C++ file.
    664         self.assertEquals(dispatcher._file_type(file_path), style.FileType.CPP)
    665 
    666         # Check the outcome.
    667         self.call_check_file(file_path)
    668 
    669         expected_processor = CppProcessor(file_path, file_extension, self.mock_handle_style_error, 3)
    670 
    671         self.assert_attributes(file_path,
    672                                self.mock_handle_style_error,
    673                                expected_processor,
    674                                "")
    675 
    676 
    677 if __name__ == '__main__':
    678     import sys
    679 
    680     unittest.main()
    681 
    682