error_handlers_unittest.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. # Copyright (C) 2010 Chris Jerdonek (cjerdonek@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. """Unit tests for error_handlers.py."""
  23. import unittest2 as unittest
  24. from checker import StyleProcessorConfiguration
  25. from error_handlers import DefaultStyleErrorHandler
  26. from filter import FilterConfiguration
  27. class DefaultStyleErrorHandlerTest(unittest.TestCase):
  28. """Tests the DefaultStyleErrorHandler class."""
  29. def setUp(self):
  30. self._error_messages = []
  31. self._error_count = 0
  32. _category = "whitespace/tab"
  33. """The category name for the tests in this class."""
  34. _file_path = "foo.h"
  35. """The file path for the tests in this class."""
  36. def _mock_increment_error_count(self):
  37. self._error_count += 1
  38. def _mock_stderr_write(self, message):
  39. self._error_messages.append(message)
  40. def _style_checker_configuration(self):
  41. """Return a StyleProcessorConfiguration instance for testing."""
  42. base_rules = ["-whitespace", "+whitespace/tab"]
  43. filter_configuration = FilterConfiguration(base_rules=base_rules)
  44. return StyleProcessorConfiguration(
  45. filter_configuration=filter_configuration,
  46. max_reports_per_category={"whitespace/tab": 2},
  47. min_confidence=3,
  48. output_format="vs7",
  49. stderr_write=self._mock_stderr_write)
  50. def _error_handler(self, configuration, line_numbers=None):
  51. return DefaultStyleErrorHandler(configuration=configuration,
  52. file_path=self._file_path,
  53. increment_error_count=self._mock_increment_error_count,
  54. line_numbers=line_numbers)
  55. def _check_initialized(self):
  56. """Check that count and error messages are initialized."""
  57. self.assertEqual(0, self._error_count)
  58. self.assertEqual(0, len(self._error_messages))
  59. def _call_error_handler(self, handle_error, confidence, line_number=100):
  60. """Call the given error handler with a test error."""
  61. handle_error(line_number=line_number,
  62. category=self._category,
  63. confidence=confidence,
  64. message="message")
  65. def test_eq__true_return_value(self):
  66. """Test the __eq__() method for the return value of True."""
  67. handler1 = self._error_handler(configuration=None)
  68. handler2 = self._error_handler(configuration=None)
  69. self.assertTrue(handler1.__eq__(handler2))
  70. def test_eq__false_return_value(self):
  71. """Test the __eq__() method for the return value of False."""
  72. def make_handler(configuration=self._style_checker_configuration(),
  73. file_path='foo.txt', increment_error_count=lambda: True,
  74. line_numbers=[100]):
  75. return DefaultStyleErrorHandler(configuration=configuration,
  76. file_path=file_path,
  77. increment_error_count=increment_error_count,
  78. line_numbers=line_numbers)
  79. handler = make_handler()
  80. # Establish a baseline for our comparisons below.
  81. self.assertTrue(handler.__eq__(make_handler()))
  82. # Verify that a difference in any argument causes equality to fail.
  83. self.assertFalse(handler.__eq__(make_handler(configuration=None)))
  84. self.assertFalse(handler.__eq__(make_handler(file_path='bar.txt')))
  85. self.assertFalse(handler.__eq__(make_handler(increment_error_count=None)))
  86. self.assertFalse(handler.__eq__(make_handler(line_numbers=[50])))
  87. def test_ne(self):
  88. """Test the __ne__() method."""
  89. # By default, __ne__ always returns true on different objects.
  90. # Thus, check just the distinguishing case to verify that the
  91. # code defines __ne__.
  92. handler1 = self._error_handler(configuration=None)
  93. handler2 = self._error_handler(configuration=None)
  94. self.assertFalse(handler1.__ne__(handler2))
  95. def test_non_reportable_error(self):
  96. """Test __call__() with a non-reportable error."""
  97. self._check_initialized()
  98. configuration = self._style_checker_configuration()
  99. confidence = 1
  100. # Confirm the error is not reportable.
  101. self.assertFalse(configuration.is_reportable(self._category,
  102. confidence,
  103. self._file_path))
  104. error_handler = self._error_handler(configuration)
  105. self._call_error_handler(error_handler, confidence)
  106. self.assertEqual(0, self._error_count)
  107. self.assertEqual([], self._error_messages)
  108. # Also serves as a reportable error test.
  109. def test_max_reports_per_category(self):
  110. """Test error report suppression in __call__() method."""
  111. self._check_initialized()
  112. configuration = self._style_checker_configuration()
  113. error_handler = self._error_handler(configuration)
  114. confidence = 5
  115. # First call: usual reporting.
  116. self._call_error_handler(error_handler, confidence)
  117. self.assertEqual(1, self._error_count)
  118. self.assertEqual(1, len(self._error_messages))
  119. self.assertEqual(self._error_messages,
  120. ["foo.h(100): message [whitespace/tab] [5]\n"])
  121. # Second call: suppression message reported.
  122. self._call_error_handler(error_handler, confidence)
  123. # The "Suppressing further..." message counts as an additional
  124. # message (but not as an addition to the error count).
  125. self.assertEqual(2, self._error_count)
  126. self.assertEqual(3, len(self._error_messages))
  127. self.assertEqual(self._error_messages[-2],
  128. "foo.h(100): message [whitespace/tab] [5]\n")
  129. self.assertEqual(self._error_messages[-1],
  130. "Suppressing further [whitespace/tab] reports "
  131. "for this file.\n")
  132. # Third call: no report.
  133. self._call_error_handler(error_handler, confidence)
  134. self.assertEqual(3, self._error_count)
  135. self.assertEqual(3, len(self._error_messages))
  136. def test_line_numbers(self):
  137. """Test the line_numbers parameter."""
  138. self._check_initialized()
  139. configuration = self._style_checker_configuration()
  140. error_handler = self._error_handler(configuration,
  141. line_numbers=[50])
  142. confidence = 5
  143. # Error on non-modified line: no error.
  144. self._call_error_handler(error_handler, confidence, line_number=60)
  145. self.assertEqual(0, self._error_count)
  146. self.assertEqual([], self._error_messages)
  147. # Error on modified line: error.
  148. self._call_error_handler(error_handler, confidence, line_number=50)
  149. self.assertEqual(1, self._error_count)
  150. self.assertEqual(self._error_messages,
  151. ["foo.h(50): message [whitespace/tab] [5]\n"])
  152. # Error on non-modified line after turning off line filtering: error.
  153. error_handler.turn_off_line_filtering()
  154. self._call_error_handler(error_handler, confidence, line_number=60)
  155. self.assertEqual(2, self._error_count)
  156. self.assertEqual(self._error_messages,
  157. ['foo.h(50): message [whitespace/tab] [5]\n',
  158. 'foo.h(60): message [whitespace/tab] [5]\n',
  159. 'Suppressing further [whitespace/tab] reports for this file.\n'])