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
2821939df44de1705786c545cd1bf519d47250322dBen Murdochfrom checker import StyleProcessorConfiguration
29d0825bca7fe65beaee391d30da42e937db621564Steve Blockfrom error_handlers import DefaultStyleErrorHandler
30692e5dbf12901edacf14812a6fae25462920af42Steve Blockfrom filter import FilterConfiguration
31d0825bca7fe65beaee391d30da42e937db621564Steve Block
32dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
33dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockclass DefaultStyleErrorHandlerTest(unittest.TestCase):
34dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
35dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    """Tests the DefaultStyleErrorHandler class."""
36d0825bca7fe65beaee391d30da42e937db621564Steve Block
37d0825bca7fe65beaee391d30da42e937db621564Steve Block    def setUp(self):
38692e5dbf12901edacf14812a6fae25462920af42Steve Block        self._error_messages = []
39d0825bca7fe65beaee391d30da42e937db621564Steve Block        self._error_count = 0
40d0825bca7fe65beaee391d30da42e937db621564Steve Block
41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    _category = "whitespace/tab"
42dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    """The category name for the tests in this class."""
43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
44dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    _file_path = "foo.h"
45dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    """The file path for the tests in this class."""
46dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
47d0825bca7fe65beaee391d30da42e937db621564Steve Block    def _mock_increment_error_count(self):
48d0825bca7fe65beaee391d30da42e937db621564Steve Block        self._error_count += 1
49d0825bca7fe65beaee391d30da42e937db621564Steve Block
50d0825bca7fe65beaee391d30da42e937db621564Steve Block    def _mock_stderr_write(self, message):
51692e5dbf12901edacf14812a6fae25462920af42Steve Block        self._error_messages.append(message)
52692e5dbf12901edacf14812a6fae25462920af42Steve Block
53692e5dbf12901edacf14812a6fae25462920af42Steve Block    def _style_checker_configuration(self):
5421939df44de1705786c545cd1bf519d47250322dBen Murdoch        """Return a StyleProcessorConfiguration instance for testing."""
55692e5dbf12901edacf14812a6fae25462920af42Steve Block        base_rules = ["-whitespace", "+whitespace/tab"]
56692e5dbf12901edacf14812a6fae25462920af42Steve Block        filter_configuration = FilterConfiguration(base_rules=base_rules)
57692e5dbf12901edacf14812a6fae25462920af42Steve Block
5821939df44de1705786c545cd1bf519d47250322dBen Murdoch        return StyleProcessorConfiguration(
59692e5dbf12901edacf14812a6fae25462920af42Steve Block                   filter_configuration=filter_configuration,
60692e5dbf12901edacf14812a6fae25462920af42Steve Block                   max_reports_per_category={"whitespace/tab": 2},
61dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                   min_confidence=3,
62692e5dbf12901edacf14812a6fae25462920af42Steve Block                   output_format="vs7",
63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                   stderr_write=self._mock_stderr_write)
64d0825bca7fe65beaee391d30da42e937db621564Steve Block
65dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    def _error_handler(self, configuration, line_numbers=None):
66dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return DefaultStyleErrorHandler(configuration=configuration,
67dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                   file_path=self._file_path,
68dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                   increment_error_count=self._mock_increment_error_count,
69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                   line_numbers=line_numbers)
70d0825bca7fe65beaee391d30da42e937db621564Steve Block
715e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    def _check_initialized(self):
725e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        """Check that count and error messages are initialized."""
73d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(0, self._error_count)
74692e5dbf12901edacf14812a6fae25462920af42Steve Block        self.assertEquals(0, len(self._error_messages))
75692e5dbf12901edacf14812a6fae25462920af42Steve Block
76dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    def _call_error_handler(self, handle_error, confidence, line_number=100):
77692e5dbf12901edacf14812a6fae25462920af42Steve Block        """Call the given error handler with a test error."""
78dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        handle_error(line_number=line_number,
79692e5dbf12901edacf14812a6fae25462920af42Steve Block                     category=self._category,
80692e5dbf12901edacf14812a6fae25462920af42Steve Block                     confidence=confidence,
81692e5dbf12901edacf14812a6fae25462920af42Steve Block                     message="message")
82692e5dbf12901edacf14812a6fae25462920af42Steve Block
83dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    def test_eq__true_return_value(self):
84dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        """Test the __eq__() method for the return value of True."""
85dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        handler1 = self._error_handler(configuration=None)
86dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        handler2 = self._error_handler(configuration=None)
87dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
88dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        self.assertTrue(handler1.__eq__(handler2))
89dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
90dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    def test_eq__false_return_value(self):
91dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        """Test the __eq__() method for the return value of False."""
92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        def make_handler(configuration=self._style_checker_configuration(),
93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                file_path='foo.txt', increment_error_count=lambda: True,
94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                line_numbers=[100]):
95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return DefaultStyleErrorHandler(configuration=configuration,
96dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                       file_path=file_path,
97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                       increment_error_count=increment_error_count,
98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                       line_numbers=line_numbers)
99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        handler = make_handler()
101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # Establish a baseline for our comparisons below.
103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        self.assertTrue(handler.__eq__(make_handler()))
104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # Verify that a difference in any argument causes equality to fail.
106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        self.assertFalse(handler.__eq__(make_handler(configuration=None)))
107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        self.assertFalse(handler.__eq__(make_handler(file_path='bar.txt')))
108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        self.assertFalse(handler.__eq__(make_handler(increment_error_count=None)))
109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        self.assertFalse(handler.__eq__(make_handler(line_numbers=[50])))
110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    def test_ne(self):
112dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        """Test the __ne__() method."""
113dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # By default, __ne__ always returns true on different objects.
114dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # Thus, check just the distinguishing case to verify that the
115dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # code defines __ne__.
116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        handler1 = self._error_handler(configuration=None)
117dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        handler2 = self._error_handler(configuration=None)
118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
119dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        self.assertFalse(handler1.__ne__(handler2))
120dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
121692e5dbf12901edacf14812a6fae25462920af42Steve Block    def test_non_reportable_error(self):
122692e5dbf12901edacf14812a6fae25462920af42Steve Block        """Test __call__() with a non-reportable error."""
1235e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self._check_initialized()
124692e5dbf12901edacf14812a6fae25462920af42Steve Block        configuration = self._style_checker_configuration()
125d0825bca7fe65beaee391d30da42e937db621564Steve Block
126692e5dbf12901edacf14812a6fae25462920af42Steve Block        confidence = 1
127d0825bca7fe65beaee391d30da42e937db621564Steve Block        # Confirm the error is not reportable.
128692e5dbf12901edacf14812a6fae25462920af42Steve Block        self.assertFalse(configuration.is_reportable(self._category,
129692e5dbf12901edacf14812a6fae25462920af42Steve Block                                                     confidence,
130692e5dbf12901edacf14812a6fae25462920af42Steve Block                                                     self._file_path))
131692e5dbf12901edacf14812a6fae25462920af42Steve Block        error_handler = self._error_handler(configuration)
132692e5dbf12901edacf14812a6fae25462920af42Steve Block        self._call_error_handler(error_handler, confidence)
133d0825bca7fe65beaee391d30da42e937db621564Steve Block
134d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(0, self._error_count)
135692e5dbf12901edacf14812a6fae25462920af42Steve Block        self.assertEquals([], self._error_messages)
136d0825bca7fe65beaee391d30da42e937db621564Steve Block
137692e5dbf12901edacf14812a6fae25462920af42Steve Block    # Also serves as a reportable error test.
138692e5dbf12901edacf14812a6fae25462920af42Steve Block    def test_max_reports_per_category(self):
139692e5dbf12901edacf14812a6fae25462920af42Steve Block        """Test error report suppression in __call__() method."""
1405e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self._check_initialized()
141692e5dbf12901edacf14812a6fae25462920af42Steve Block        configuration = self._style_checker_configuration()
142692e5dbf12901edacf14812a6fae25462920af42Steve Block        error_handler = self._error_handler(configuration)
143d0825bca7fe65beaee391d30da42e937db621564Steve Block
1445e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        confidence = 5
1455e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
1465e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        # First call: usual reporting.
147692e5dbf12901edacf14812a6fae25462920af42Steve Block        self._call_error_handler(error_handler, confidence)
1485e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self.assertEquals(1, self._error_count)
149692e5dbf12901edacf14812a6fae25462920af42Steve Block        self.assertEquals(1, len(self._error_messages))
1505e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self.assertEquals(self._error_messages,
151692e5dbf12901edacf14812a6fae25462920af42Steve Block                          ["foo.h(100):  message  [whitespace/tab] [5]\n"])
1525e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
1535e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        # Second call: suppression message reported.
154692e5dbf12901edacf14812a6fae25462920af42Steve Block        self._call_error_handler(error_handler, confidence)
155692e5dbf12901edacf14812a6fae25462920af42Steve Block        # The "Suppressing further..." message counts as an additional
156692e5dbf12901edacf14812a6fae25462920af42Steve Block        # message (but not as an addition to the error count).
1575e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self.assertEquals(2, self._error_count)
158692e5dbf12901edacf14812a6fae25462920af42Steve Block        self.assertEquals(3, len(self._error_messages))
159692e5dbf12901edacf14812a6fae25462920af42Steve Block        self.assertEquals(self._error_messages[-2],
160692e5dbf12901edacf14812a6fae25462920af42Steve Block                          "foo.h(100):  message  [whitespace/tab] [5]\n")
161692e5dbf12901edacf14812a6fae25462920af42Steve Block        self.assertEquals(self._error_messages[-1],
162692e5dbf12901edacf14812a6fae25462920af42Steve Block                          "Suppressing further [whitespace/tab] reports "
163692e5dbf12901edacf14812a6fae25462920af42Steve Block                          "for this file.\n")
1645e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
1655e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        # Third call: no report.
166692e5dbf12901edacf14812a6fae25462920af42Steve Block        self._call_error_handler(error_handler, confidence)
1675e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        self.assertEquals(3, self._error_count)
168692e5dbf12901edacf14812a6fae25462920af42Steve Block        self.assertEquals(3, len(self._error_messages))
1695e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
170dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    def test_line_numbers(self):
171dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        """Test the line_numbers parameter."""
172dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        self._check_initialized()
173692e5dbf12901edacf14812a6fae25462920af42Steve Block        configuration = self._style_checker_configuration()
174dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        error_handler = self._error_handler(configuration,
175dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                                            line_numbers=[50])
176d0825bca7fe65beaee391d30da42e937db621564Steve Block        confidence = 5
177d0825bca7fe65beaee391d30da42e937db621564Steve Block
178dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # Error on non-modified line: no error.
179dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        self._call_error_handler(error_handler, confidence, line_number=60)
180d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(0, self._error_count)
181dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        self.assertEquals([], self._error_messages)
182d0825bca7fe65beaee391d30da42e937db621564Steve Block
183dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # Error on modified line: error.
184dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        self._call_error_handler(error_handler, confidence, line_number=50)
185d0825bca7fe65beaee391d30da42e937db621564Steve Block        self.assertEquals(1, self._error_count)
186dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        self.assertEquals(self._error_messages,
187dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                          ["foo.h(50):  message  [whitespace/tab] [5]\n"])
188