Home | History | Annotate | Download | only in style
      1 # Copyright (C) 2010 Chris Jerdonek (cjerdonek (at] webkit.org)
      2 #
      3 # Redistribution and use in source and binary forms, with or without
      4 # modification, are permitted provided that the following conditions
      5 # are met:
      6 # 1.  Redistributions of source code must retain the above copyright
      7 #     notice, this list of conditions and the following disclaimer.
      8 # 2.  Redistributions in binary form must reproduce the above copyright
      9 #     notice, this list of conditions and the following disclaimer in the
     10 #     documentation and/or other materials provided with the distribution.
     11 #
     12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     13 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     14 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     15 # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     16 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     17 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     18 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     19 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     20 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     21 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     22 
     23 """Unit tests for error_handlers.py."""
     24 
     25 import unittest
     26 
     27 from checker import StyleProcessorConfiguration
     28 from error_handlers import DefaultStyleErrorHandler
     29 from filter import FilterConfiguration
     30 
     31 
     32 class DefaultStyleErrorHandlerTest(unittest.TestCase):
     33 
     34     """Tests the DefaultStyleErrorHandler class."""
     35 
     36     def setUp(self):
     37         self._error_messages = []
     38         self._error_count = 0
     39 
     40     _category = "whitespace/tab"
     41     """The category name for the tests in this class."""
     42 
     43     _file_path = "foo.h"
     44     """The file path for the tests in this class."""
     45 
     46     def _mock_increment_error_count(self):
     47         self._error_count += 1
     48 
     49     def _mock_stderr_write(self, message):
     50         self._error_messages.append(message)
     51 
     52     def _style_checker_configuration(self):
     53         """Return a StyleProcessorConfiguration instance for testing."""
     54         base_rules = ["-whitespace", "+whitespace/tab"]
     55         filter_configuration = FilterConfiguration(base_rules=base_rules)
     56 
     57         return StyleProcessorConfiguration(
     58                    filter_configuration=filter_configuration,
     59                    max_reports_per_category={"whitespace/tab": 2},
     60                    min_confidence=3,
     61                    output_format="vs7",
     62                    stderr_write=self._mock_stderr_write)
     63 
     64     def _error_handler(self, configuration, line_numbers=None):
     65         return DefaultStyleErrorHandler(configuration=configuration,
     66                    file_path=self._file_path,
     67                    increment_error_count=self._mock_increment_error_count,
     68                    line_numbers=line_numbers)
     69 
     70     def _check_initialized(self):
     71         """Check that count and error messages are initialized."""
     72         self.assertEqual(0, self._error_count)
     73         self.assertEqual(0, len(self._error_messages))
     74 
     75     def _call_error_handler(self, handle_error, confidence, line_number=100):
     76         """Call the given error handler with a test error."""
     77         handle_error(line_number=line_number,
     78                      category=self._category,
     79                      confidence=confidence,
     80                      message="message")
     81 
     82     def test_eq__true_return_value(self):
     83         """Test the __eq__() method for the return value of True."""
     84         handler1 = self._error_handler(configuration=None)
     85         handler2 = self._error_handler(configuration=None)
     86 
     87         self.assertTrue(handler1.__eq__(handler2))
     88 
     89     def test_eq__false_return_value(self):
     90         """Test the __eq__() method for the return value of False."""
     91         def make_handler(configuration=self._style_checker_configuration(),
     92                 file_path='foo.txt', increment_error_count=lambda: True,
     93                 line_numbers=[100]):
     94             return DefaultStyleErrorHandler(configuration=configuration,
     95                        file_path=file_path,
     96                        increment_error_count=increment_error_count,
     97                        line_numbers=line_numbers)
     98 
     99         handler = make_handler()
    100 
    101         # Establish a baseline for our comparisons below.
    102         self.assertTrue(handler.__eq__(make_handler()))
    103 
    104         # Verify that a difference in any argument causes equality to fail.
    105         self.assertFalse(handler.__eq__(make_handler(configuration=None)))
    106         self.assertFalse(handler.__eq__(make_handler(file_path='bar.txt')))
    107         self.assertFalse(handler.__eq__(make_handler(increment_error_count=None)))
    108         self.assertFalse(handler.__eq__(make_handler(line_numbers=[50])))
    109 
    110     def test_ne(self):
    111         """Test the __ne__() method."""
    112         # By default, __ne__ always returns true on different objects.
    113         # Thus, check just the distinguishing case to verify that the
    114         # code defines __ne__.
    115         handler1 = self._error_handler(configuration=None)
    116         handler2 = self._error_handler(configuration=None)
    117 
    118         self.assertFalse(handler1.__ne__(handler2))
    119 
    120     def test_non_reportable_error(self):
    121         """Test __call__() with a non-reportable error."""
    122         self._check_initialized()
    123         configuration = self._style_checker_configuration()
    124 
    125         confidence = 1
    126         # Confirm the error is not reportable.
    127         self.assertFalse(configuration.is_reportable(self._category,
    128                                                      confidence,
    129                                                      self._file_path))
    130         error_handler = self._error_handler(configuration)
    131         self._call_error_handler(error_handler, confidence)
    132 
    133         self.assertEqual(0, self._error_count)
    134         self.assertEqual([], self._error_messages)
    135 
    136     # Also serves as a reportable error test.
    137     def test_max_reports_per_category(self):
    138         """Test error report suppression in __call__() method."""
    139         self._check_initialized()
    140         configuration = self._style_checker_configuration()
    141         error_handler = self._error_handler(configuration)
    142 
    143         confidence = 5
    144 
    145         # First call: usual reporting.
    146         self._call_error_handler(error_handler, confidence)
    147         self.assertEqual(1, self._error_count)
    148         self.assertEqual(1, len(self._error_messages))
    149         self.assertEqual(self._error_messages,
    150                           ["foo.h(100):  message  [whitespace/tab] [5]\n"])
    151 
    152         # Second call: suppression message reported.
    153         self._call_error_handler(error_handler, confidence)
    154         # The "Suppressing further..." message counts as an additional
    155         # message (but not as an addition to the error count).
    156         self.assertEqual(2, self._error_count)
    157         self.assertEqual(3, len(self._error_messages))
    158         self.assertEqual(self._error_messages[-2],
    159                           "foo.h(100):  message  [whitespace/tab] [5]\n")
    160         self.assertEqual(self._error_messages[-1],
    161                           "Suppressing further [whitespace/tab] reports "
    162                           "for this file.\n")
    163 
    164         # Third call: no report.
    165         self._call_error_handler(error_handler, confidence)
    166         self.assertEqual(3, self._error_count)
    167         self.assertEqual(3, len(self._error_messages))
    168 
    169     def test_line_numbers(self):
    170         """Test the line_numbers parameter."""
    171         self._check_initialized()
    172         configuration = self._style_checker_configuration()
    173         error_handler = self._error_handler(configuration,
    174                                             line_numbers=[50])
    175         confidence = 5
    176 
    177         # Error on non-modified line: no error.
    178         self._call_error_handler(error_handler, confidence, line_number=60)
    179         self.assertEqual(0, self._error_count)
    180         self.assertEqual([], self._error_messages)
    181 
    182         # Error on modified line: error.
    183         self._call_error_handler(error_handler, confidence, line_number=50)
    184         self.assertEqual(1, self._error_count)
    185         self.assertEqual(self._error_messages,
    186                           ["foo.h(50):  message  [whitespace/tab] [5]\n"])
    187 
    188         # Error on non-modified line after turning off line filtering: error.
    189         error_handler.turn_off_line_filtering()
    190         self._call_error_handler(error_handler, confidence, line_number=60)
    191         self.assertEqual(2, self._error_count)
    192         self.assertEqual(self._error_messages,
    193                           ['foo.h(50):  message  [whitespace/tab] [5]\n',
    194                            'foo.h(60):  message  [whitespace/tab] [5]\n',
    195                            'Suppressing further [whitespace/tab] reports for this file.\n'])
    196