# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Unit tests for error_handlers.py."""


import unittest

from checker import StyleProcessorConfiguration
from error_handlers import DefaultStyleErrorHandler
from filter import FilterConfiguration
from webkitpy.common.system.logtesting import LoggingTestCase


class DefaultStyleErrorHandlerTest(LoggingTestCase):

    """Tests the DefaultStyleErrorHandler class."""

    def setUp(self):
        super(DefaultStyleErrorHandlerTest, self).setUp()
        self._error_count = 0

    _category = "whitespace/tab"
    """The category name for the tests in this class."""

    _file_path = "foo.h"
    """The file path for the tests in this class."""

    def _mock_increment_error_count(self):
        self._error_count += 1

    def _style_checker_configuration(self):
        """Return a StyleProcessorConfiguration instance for testing."""
        base_rules = ["-whitespace", "+whitespace/tab"]
        filter_configuration = FilterConfiguration(base_rules=base_rules)

        return StyleProcessorConfiguration(
                   filter_configuration=filter_configuration,
                   max_reports_per_category={"whitespace/tab": 2},
                   min_confidence=3,
                   output_format="vs7",
                   commit_queue=False)

    def _error_handler(self, configuration, line_numbers=None):
        return DefaultStyleErrorHandler(configuration=configuration,
                   file_path=self._file_path,
                   increment_error_count=self._mock_increment_error_count,
                   line_numbers=line_numbers)

    def _check_initialized(self):
        """Check that count and error messages are initialized."""
        self.assertEqual(0, self._error_count)

    def _call_error_handler(self, handle_error, confidence, line_number=100):
        """Call the given error handler with a test error."""
        handle_error(line_number=line_number,
                     category=self._category,
                     confidence=confidence,
                     message="message")

    def test_eq__true_return_value(self):
        """Test the __eq__() method for the return value of True."""
        handler1 = self._error_handler(configuration=None)
        handler2 = self._error_handler(configuration=None)

        self.assertTrue(handler1.__eq__(handler2))

    def test_eq__false_return_value(self):
        """Test the __eq__() method for the return value of False."""
        def make_handler(configuration=self._style_checker_configuration(),
                file_path='foo.txt', increment_error_count=lambda: True,
                line_numbers=[100]):
            return DefaultStyleErrorHandler(configuration=configuration,
                       file_path=file_path,
                       increment_error_count=increment_error_count,
                       line_numbers=line_numbers)

        handler = make_handler()

        # Establish a baseline for our comparisons below.
        self.assertTrue(handler.__eq__(make_handler()))

        # Verify that a difference in any argument causes equality to fail.
        self.assertFalse(handler.__eq__(make_handler(configuration=None)))
        self.assertFalse(handler.__eq__(make_handler(file_path='bar.txt')))
        self.assertFalse(handler.__eq__(make_handler(increment_error_count=None)))
        self.assertFalse(handler.__eq__(make_handler(line_numbers=[50])))

    def test_ne(self):
        """Test the __ne__() method."""
        # By default, __ne__ always returns true on different objects.
        # Thus, check just the distinguishing case to verify that the
        # code defines __ne__.
        handler1 = self._error_handler(configuration=None)
        handler2 = self._error_handler(configuration=None)

        self.assertFalse(handler1.__ne__(handler2))

    def test_non_reportable_error(self):
        """Test __call__() with a non-reportable error."""
        self._check_initialized()
        configuration = self._style_checker_configuration()

        confidence = 1
        # Confirm the error is not reportable.
        self.assertFalse(configuration.is_reportable(self._category,
                                                     confidence,
                                                     self._file_path))
        error_handler = self._error_handler(configuration)
        self._call_error_handler(error_handler, confidence)

        self.assertEqual(0, self._error_count)

    # Also serves as a reportable error test.
    def test_max_reports_per_category(self):
        """Test error report suppression in __call__() method."""
        self._check_initialized()
        configuration = self._style_checker_configuration()
        error_handler = self._error_handler(configuration)

        confidence = 5

        # First call: usual reporting.
        self._call_error_handler(error_handler, confidence)
        self.assertEqual(1, self._error_count)
        self.assertLog(["ERROR: foo.h(100):  message  [whitespace/tab] [5]\n"])

        # Second call: suppression message reported.
        self._call_error_handler(error_handler, confidence)
        # The "Suppressing further..." message counts as an additional
        # message (but not as an addition to the error count).
        self.assertEqual(2, self._error_count)
        expected_message = ["ERROR: foo.h(100):  message  [whitespace/tab] [5]\n",
                            "ERROR: Suppressing further [whitespace/tab] reports for this file.\n"]
        self.assertLog(expected_message)

        # Third call: no report.
        self._call_error_handler(error_handler, confidence)
        self.assertEqual(3, self._error_count)
        self.assertLog([])

    def test_line_numbers(self):
        """Test the line_numbers parameter."""
        self._check_initialized()
        configuration = self._style_checker_configuration()
        error_handler = self._error_handler(configuration,
                                            line_numbers=[50])
        confidence = 5

        # Error on non-modified line: no error.
        self._call_error_handler(error_handler, confidence, line_number=60)
        self.assertEqual(0, self._error_count)
        self.assertLog([])

        # Error on modified line: error.
        self._call_error_handler(error_handler, confidence, line_number=50)
        self.assertEqual(1, self._error_count)
        self.assertLog(["ERROR: foo.h(50):  message  [whitespace/tab] [5]\n"])

        # Error on non-modified line after turning off line filtering: error.
        error_handler.turn_off_line_filtering()
        self._call_error_handler(error_handler, confidence, line_number=60)
        self.assertEqual(2, self._error_count)
        self.assertLog(['ERROR: foo.h(60):  message  [whitespace/tab] [5]\n',
                        'ERROR: Suppressing further [whitespace/tab] reports for this file.\n'])
