1d0825bca7fe65beaee391d30da42e937db621564Steve Block# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
2d0825bca7fe65beaee391d30da42e937db621564Steve Block#
3d0825bca7fe65beaee391d30da42e937db621564Steve Block# Redistribution and use in source and binary forms, with or without
4d0825bca7fe65beaee391d30da42e937db621564Steve Block# modification, are permitted provided that the following conditions
5d0825bca7fe65beaee391d30da42e937db621564Steve Block# are met:
6d0825bca7fe65beaee391d30da42e937db621564Steve Block# 1.  Redistributions of source code must retain the above copyright
7d0825bca7fe65beaee391d30da42e937db621564Steve Block#     notice, this list of conditions and the following disclaimer.
8d0825bca7fe65beaee391d30da42e937db621564Steve Block# 2.  Redistributions in binary form must reproduce the above copyright
9d0825bca7fe65beaee391d30da42e937db621564Steve Block#     notice, this list of conditions and the following disclaimer in the
10d0825bca7fe65beaee391d30da42e937db621564Steve Block#     documentation and/or other materials provided with the distribution.
11d0825bca7fe65beaee391d30da42e937db621564Steve Block#
12d0825bca7fe65beaee391d30da42e937db621564Steve Block# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
13d0825bca7fe65beaee391d30da42e937db621564Steve Block# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14d0825bca7fe65beaee391d30da42e937db621564Steve Block# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15d0825bca7fe65beaee391d30da42e937db621564Steve Block# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
16d0825bca7fe65beaee391d30da42e937db621564Steve Block# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17d0825bca7fe65beaee391d30da42e937db621564Steve Block# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18d0825bca7fe65beaee391d30da42e937db621564Steve Block# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19d0825bca7fe65beaee391d30da42e937db621564Steve Block# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20d0825bca7fe65beaee391d30da42e937db621564Steve Block# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21d0825bca7fe65beaee391d30da42e937db621564Steve Block# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22d0825bca7fe65beaee391d30da42e937db621564Steve Block
23d0825bca7fe65beaee391d30da42e937db621564Steve Block"""Unit tests for error_handlers.py."""
24d0825bca7fe65beaee391d30da42e937db621564Steve Block
25d0825bca7fe65beaee391d30da42e937db621564Steve Block
26d0825bca7fe65beaee391d30da42e937db621564Steve Blockimport unittest
27d0825bca7fe65beaee391d30da42e937db621564Steve Block
28d0825bca7fe65beaee391d30da42e937db621564Steve Blockfrom .. style_references import parse_patch
29d0825bca7fe65beaee391d30da42e937db621564Steve Blockfrom checker import ProcessorOptions
30d0825bca7fe65beaee391d30da42e937db621564Steve Blockfrom error_handlers import DefaultStyleErrorHandler
31d0825bca7fe65beaee391d30da42e937db621564Steve Blockfrom error_handlers import PatchStyleErrorHandler
32d0825bca7fe65beaee391d30da42e937db621564Steve Block
33d0825bca7fe65beaee391d30da42e937db621564Steve Block
34d0825bca7fe65beaee391d30da42e937db621564Steve Blockclass StyleErrorHandlerTestBase(unittest.TestCase):
35d0825bca7fe65beaee391d30da42e937db621564Steve Block
36d0825bca7fe65beaee391d30da42e937db621564Steve Block    def setUp(self):
37d0825bca7fe65beaee391d30da42e937db621564Steve Block        self._error_messages = ""
38d0825bca7fe65beaee391d30da42e937db621564Steve Block        self._error_count = 0
39d0825bca7fe65beaee391d30da42e937db621564Steve Block
40d0825bca7fe65beaee391d30da42e937db621564Steve Block    def _mock_increment_error_count(self):
41d0825bca7fe65beaee391d30da42e937db621564Steve Block        self._error_count += 1
42d0825bca7fe65beaee391d30da42e937db621564Steve Block
43d0825bca7fe65beaee391d30da42e937db621564Steve Block    def _mock_stderr_write(self, message):
44d0825bca7fe65beaee391d30da42e937db621564Steve Block        self._error_messages += message
45d0825bca7fe65beaee391d30da42e937db621564Steve Block
46d0825bca7fe65beaee391d30da42e937db621564Steve Block
47d0825bca7fe65beaee391d30da42e937db621564Steve Blockclass DefaultStyleErrorHandlerTest(StyleErrorHandlerTestBase):
48d0825bca7fe65beaee391d30da42e937db621564Steve Block
49d0825bca7fe65beaee391d30da42e937db621564Steve Block    """Tests DefaultStyleErrorHandler class."""
50d0825bca7fe65beaee391d30da42e937db621564Steve Block
518a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    _file_path = "foo.h"
528a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
53d0825bca7fe65beaee391d30da42e937db621564Steve Block    _category = "whitespace/tab"
54d0825bca7fe65beaee391d30da42e937db621564Steve Block
55d0825bca7fe65beaee391d30da42e937db621564Steve Block    def _error_handler(self, options):
568a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        return DefaultStyleErrorHandler(self._file_path,
57d0825bca7fe65beaee391d30da42e937db621564Steve Block                                        options,
58d0825bca7fe65beaee391d30da42e937db621564Steve Block                                        self._mock_increment_error_count,
59d0825bca7fe65beaee391d30da42e937db621564Steve Block                                        self._mock_stderr_write)
60d0825bca7fe65beaee391d30da42e937db621564Steve Block
615e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    def _check_initialized(self):
625e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        """Check that count and error messages are initialized."""
63d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(0, self._error_count)
64d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals("", self._error_messages)
65d0825bca7fe65beaee391d30da42e937db621564Steve Block
665e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    def _call(self, handle_error, options, confidence):
675e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        """Handle an error with the given error handler."""
68d0825bca7fe65beaee391d30da42e937db621564Steve Block        line_number = 100
69d0825bca7fe65beaee391d30da42e937db621564Steve Block        message = "message"
70d0825bca7fe65beaee391d30da42e937db621564Steve Block
71d0825bca7fe65beaee391d30da42e937db621564Steve Block        handle_error(line_number, self._category, confidence, message)
72d0825bca7fe65beaee391d30da42e937db621564Steve Block
735e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    def _call_error_handler(self, options, confidence):
745e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        """Handle an error using a new error handler."""
755e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        handle_error = self._error_handler(options)
765e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self._call(handle_error, options, confidence)
775e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
78d0825bca7fe65beaee391d30da42e937db621564Steve Block    def test_call_non_reportable(self):
79d0825bca7fe65beaee391d30da42e937db621564Steve Block        """Test __call__() method with a non-reportable error."""
80d0825bca7fe65beaee391d30da42e937db621564Steve Block        confidence = 1
815e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        options = ProcessorOptions(verbosity=3)
825e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self._check_initialized()
83d0825bca7fe65beaee391d30da42e937db621564Steve Block
84d0825bca7fe65beaee391d30da42e937db621564Steve Block        # Confirm the error is not reportable.
858a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        self.assertFalse(options.is_reportable(self._category,
868a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block                                               confidence,
878a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block                                               self._file_path))
88d0825bca7fe65beaee391d30da42e937db621564Steve Block
89d0825bca7fe65beaee391d30da42e937db621564Steve Block        self._call_error_handler(options, confidence)
90d0825bca7fe65beaee391d30da42e937db621564Steve Block
91d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(0, self._error_count)
92d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals("", self._error_messages)
93d0825bca7fe65beaee391d30da42e937db621564Steve Block
94d0825bca7fe65beaee391d30da42e937db621564Steve Block    def test_call_reportable_emacs(self):
95d0825bca7fe65beaee391d30da42e937db621564Steve Block        """Test __call__() method with a reportable error and emacs format."""
96d0825bca7fe65beaee391d30da42e937db621564Steve Block        confidence = 5
975e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        options = ProcessorOptions(verbosity=3, output_format="emacs")
985e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self._check_initialized()
99d0825bca7fe65beaee391d30da42e937db621564Steve Block
100d0825bca7fe65beaee391d30da42e937db621564Steve Block        self._call_error_handler(options, confidence)
101d0825bca7fe65beaee391d30da42e937db621564Steve Block
102d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(1, self._error_count)
103d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(self._error_messages,
104d0825bca7fe65beaee391d30da42e937db621564Steve Block                          "foo.h:100:  message  [whitespace/tab] [5]\n")
105d0825bca7fe65beaee391d30da42e937db621564Steve Block
106d0825bca7fe65beaee391d30da42e937db621564Steve Block    def test_call_reportable_vs7(self):
107d0825bca7fe65beaee391d30da42e937db621564Steve Block        """Test __call__() method with a reportable error and vs7 format."""
108d0825bca7fe65beaee391d30da42e937db621564Steve Block        confidence = 5
1095e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        options = ProcessorOptions(verbosity=3, output_format="vs7")
1105e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self._check_initialized()
111d0825bca7fe65beaee391d30da42e937db621564Steve Block
112d0825bca7fe65beaee391d30da42e937db621564Steve Block        self._call_error_handler(options, confidence)
113d0825bca7fe65beaee391d30da42e937db621564Steve Block
114d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(1, self._error_count)
115d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(self._error_messages,
116d0825bca7fe65beaee391d30da42e937db621564Steve Block                          "foo.h(100):  message  [whitespace/tab] [5]\n")
117d0825bca7fe65beaee391d30da42e937db621564Steve Block
1185e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    def test_call_max_reports_per_category(self):
1195e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        """Test error report suppression in __call__() method."""
1205e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        confidence = 5
1215e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        options = ProcessorOptions(verbosity=3,
1225e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block                                   max_reports_per_category={self._category: 2})
1235e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        error_handler = self._error_handler(options)
1245e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
1255e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self._check_initialized()
1265e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
1275e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        # First call: usual reporting.
1285e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self._call(error_handler, options, confidence)
1295e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self.assertEquals(1, self._error_count)
1305e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self.assertEquals(self._error_messages,
1315e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block                          "foo.h:100:  message  [whitespace/tab] [5]\n")
1325e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
1335e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        # Second call: suppression message reported.
1345e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self._error_messages = ""
1355e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self._call(error_handler, options, confidence)
1365e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self.assertEquals(2, self._error_count)
1375e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self.assertEquals(self._error_messages,
1385e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block                          "foo.h:100:  message  [whitespace/tab] [5]\n"
1395e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block                          "Suppressing further [%s] reports for this file.\n"
1405e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block                          % self._category)
1415e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
1425e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        # Third call: no report.
1435e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self._error_messages = ""
1445e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self._call(error_handler, options, confidence)
1455e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self.assertEquals(3, self._error_count)
1465e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self.assertEquals(self._error_messages, "")
1475e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
148d0825bca7fe65beaee391d30da42e937db621564Steve Block
149d0825bca7fe65beaee391d30da42e937db621564Steve Blockclass PatchStyleErrorHandlerTest(StyleErrorHandlerTestBase):
150d0825bca7fe65beaee391d30da42e937db621564Steve Block
151d0825bca7fe65beaee391d30da42e937db621564Steve Block    """Tests PatchStyleErrorHandler class."""
152d0825bca7fe65beaee391d30da42e937db621564Steve Block
1538a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    _file_path = "__init__.py"
154d0825bca7fe65beaee391d30da42e937db621564Steve Block
1558a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    _patch_string = """diff --git a/__init__.py b/__init__.py
156d0825bca7fe65beaee391d30da42e937db621564Steve Blockindex ef65bee..e3db70e 100644
157d0825bca7fe65beaee391d30da42e937db621564Steve Block--- a/__init__.py
158d0825bca7fe65beaee391d30da42e937db621564Steve Block+++ b/__init__.py
159d0825bca7fe65beaee391d30da42e937db621564Steve Block@@ -1 +1,2 @@
160d0825bca7fe65beaee391d30da42e937db621564Steve Block # Required for Python to search this directory for module files
161d0825bca7fe65beaee391d30da42e937db621564Steve Block+# New line
162d0825bca7fe65beaee391d30da42e937db621564Steve Block
163d0825bca7fe65beaee391d30da42e937db621564Steve Block"""
164d0825bca7fe65beaee391d30da42e937db621564Steve Block
165d0825bca7fe65beaee391d30da42e937db621564Steve Block    def test_call(self):
1668a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        patch_files = parse_patch(self._patch_string)
1678a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        diff = patch_files[self._file_path]
168d0825bca7fe65beaee391d30da42e937db621564Steve Block
169d0825bca7fe65beaee391d30da42e937db621564Steve Block        options = ProcessorOptions(verbosity=3)
170d0825bca7fe65beaee391d30da42e937db621564Steve Block
171d0825bca7fe65beaee391d30da42e937db621564Steve Block        handle_error = PatchStyleErrorHandler(diff,
1728a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block                                              self._file_path,
173d0825bca7fe65beaee391d30da42e937db621564Steve Block                                              options,
174d0825bca7fe65beaee391d30da42e937db621564Steve Block                                              self._mock_increment_error_count,
175d0825bca7fe65beaee391d30da42e937db621564Steve Block                                              self._mock_stderr_write)
176d0825bca7fe65beaee391d30da42e937db621564Steve Block
177d0825bca7fe65beaee391d30da42e937db621564Steve Block        category = "whitespace/tab"
178d0825bca7fe65beaee391d30da42e937db621564Steve Block        confidence = 5
179d0825bca7fe65beaee391d30da42e937db621564Steve Block        message = "message"
180d0825bca7fe65beaee391d30da42e937db621564Steve Block
181d0825bca7fe65beaee391d30da42e937db621564Steve Block        # Confirm error is reportable.
1828a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        self.assertTrue(options.is_reportable(category,
1838a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block                                              confidence,
1848a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block                                              self._file_path))
185d0825bca7fe65beaee391d30da42e937db621564Steve Block
186d0825bca7fe65beaee391d30da42e937db621564Steve Block        # Confirm error count initialized to zero.
187d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(0, self._error_count)
188d0825bca7fe65beaee391d30da42e937db621564Steve Block
189d0825bca7fe65beaee391d30da42e937db621564Steve Block        # Test error in unmodified line (error count does not increment).
190d0825bca7fe65beaee391d30da42e937db621564Steve Block        handle_error(1, category, confidence, message)
191d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(0, self._error_count)
192d0825bca7fe65beaee391d30da42e937db621564Steve Block
193d0825bca7fe65beaee391d30da42e937db621564Steve Block        # Test error in modified line (error count increments).
194d0825bca7fe65beaee391d30da42e937db621564Steve Block        handle_error(2, category, confidence, message)
195d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(1, self._error_count)
196d0825bca7fe65beaee391d30da42e937db621564Steve Block
197