# Copyright (c) 2009 Google Inc. All rights reserved.
# Copyright (c) 2009, 2017 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * 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.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
# OWNER OR 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.

import codecs
import logging
import os
import re
import sys
import time
import traceback

from optparse import make_option

from webkitpy.common.config.committervalidator import CommitterValidator
from webkitpy.common.config.ports import DeprecatedPort
from webkitpy.common.net.bugzilla import Bugzilla, Attachment
from webkitpy.common.system.executive import ScriptError
from webkitpy.common.unicode_compatibility import BytesIO
from webkitpy.tool.bot.botinfo import BotInfo
from webkitpy.tool.bot.commitqueuetask import CommitQueueTask, CommitQueueTaskDelegate
from webkitpy.tool.bot.feeders import CommitQueueFeeder, EWSFeeder
from webkitpy.tool.bot.flakytestreporter import FlakyTestReporter
from webkitpy.tool.bot.layouttestresultsreader import LayoutTestResultsReader
from webkitpy.tool.bot.patchanalysistask import UnableToApplyPatch, PatchIsNotValid
from webkitpy.tool.bot.queueengine import QueueEngine, QueueEngineDelegate
from webkitpy.tool.bot.stylequeuetask import StyleQueueTask, StyleQueueTaskDelegate
from webkitpy.tool.commands.stepsequence import StepSequenceErrorHandler
from webkitpy.tool.multicommandtool import Command, TryAgain

_log = logging.getLogger(__name__)


class AbstractQueue(Command, QueueEngineDelegate):
    watchers = [
    ]

    _skip_status = "Skip"
    _pass_status = "Pass"
    _fail_status = "Fail"
    _error_status = "Error"

    def __init__(self, options=None):  # Default values should never be collections (like []) as default values are shared between invocations
        options_list = (options or []) + [
            make_option("--no-confirm", action="store_false", dest="confirm", default=True, help="Do not ask the user for confirmation before running the queue.  Dangerous!"),
            make_option("--exit-after-iteration", action="store", type="int", dest="iterations", default=None, help="Stop running the queue after iterating this number of times."),
        ]
        self.help_text = "Run the %s" % self.name
        Command.__init__(self, options=options_list)
        self._iteration_count = 0
        if not hasattr(self, 'architecture'):
            self.architecture = None

    def _cc_watchers(self, bug_id):
        try:
            self._tool.bugs.add_cc_to_bug(bug_id, self.watchers)
        except Exception as e:
            traceback.print_exc()
            _log.error("Failed to CC watchers.")

    def run_webkit_patch(self, args):
        webkit_patch_args = [self._tool.path()]
        # FIXME: This is a hack, we should have a more general way to pass global options.
        # FIXME: We must always pass global options and their value in one argument
        # because our global option code looks for the first argument which does
        # not begin with "-" and assumes that is the command name.
        webkit_patch_args += ["--status-host=%s" % self._tool.status_server.host]
        if not self._tool.status_server.use_https:
            webkit_patch_args += ['--status-host-uses-http']
        if self._tool.status_server.bot_id:
            webkit_patch_args += ["--bot-id=%s" % self._tool.status_server.bot_id]
        if self._options.port:
            webkit_patch_args += ["--port=%s" % self._options.port]
        webkit_patch_args.extend(args)

        try:
            args_for_printing = list(webkit_patch_args)
            args_for_printing[0] = 'webkit-patch'  # Printing our path for each log is redundant.
            _log.info("Running: %s" % self._tool.executive.command_for_printing(args_for_printing))
            command_output = self._tool.executive.run_command(webkit_patch_args, cwd=self._tool.scm().checkout_root)
        except ScriptError as e:
            # Make sure the whole output gets printed if the command failed.
            _log.error(e.message_with_output(output_limit=None))
            raise
        return command_output

    def _log_directory(self):
        return os.path.join("..", "%s-logs" % self.name)

    # QueueEngineDelegate methods

    def queue_log_path(self):
        return os.path.join(self._log_directory(), "%s.log" % self.name)

    def work_item_log_path(self, work_item):
        raise NotImplementedError('subclasses must implement')

    def begin_work_queue(self):
        _log.info("CAUTION: %s will discard all local changes in \"%s\"" % (self.name, self._tool.scm().checkout_root))
        if self._options.confirm:
            response = self._tool.user.prompt("Are you sure?  Type \"yes\" to continue: ")
            if (response != "yes"):
                _log.error("User declined.")
                sys.exit(1)
        _log.info("Running WebKit %s." % self.name)
        self._tool.status_server.update_status(self.name, "Starting Queue")

    def stop_work_queue(self, reason):
        self._tool.status_server.update_status(self.name, "Stopping Queue, reason: %s" % reason)

    def should_continue_work_queue(self):
        self._iteration_count += 1
        if not isinstance(self._options.iterations, int):
            return True
        return not self._options.iterations or self._iteration_count <= self._options.iterations

    def next_work_item(self):
        raise NotImplementedError('subclasses must implement')

    def process_work_item(self, work_item):
        raise NotImplementedError('subclasses must implement')

    def handle_unexpected_error(self, work_item, message):
        raise NotImplementedError('subclasses must implement')

    # Command methods

    def execute(self, options, args, tool, engine=QueueEngine):
        self._options = options  # FIXME: This code is wrong.  Command.options is a list, this assumes an Options element!
        self._tool = tool  # FIXME: This code is wrong too!  Command.bind_to_tool handles this!
        return engine(self.name, self, self._tool.wakeup_event, self._options.seconds_to_sleep).run()

    @classmethod
    def _log_from_script_error_for_upload(cls, script_error, output_limit=None):
        # We have seen request timeouts with app engine due to large
        # log uploads.  Trying only the last 512k.
        if not output_limit:
            output_limit = 512 * 1024  # 512k
        output = script_error.message_with_output(output_limit=output_limit)
        # We pre-encode the string to a byte array before passing it
        # to status_server, because ClientForm (part of mechanize)
        # wants a file-like object with pre-encoded data.
        return BytesIO(output.encode("utf-8"))

    @classmethod
    def _update_status_for_script_error(cls, tool, state, script_error, is_error=False):
        message = str(script_error)
        if is_error:
            message = "Error: %s" % message
        failure_log = cls._log_from_script_error_for_upload(script_error)
        return tool.status_server.update_status(cls.name, message, state["patch"], failure_log)


class FeederQueue(AbstractQueue):
    name = "feeder-queue"

    _sleep_duration = 30  # seconds

    # AbstractQueue methods

    def begin_work_queue(self):
        AbstractQueue.begin_work_queue(self)
        self.feeders = [
            CommitQueueFeeder(self._tool),
            EWSFeeder(self._tool),
        ]

    def next_work_item(self):
        # This really show inherit from some more basic class that doesn't
        # understand work items, but the base class in the heirarchy currently
        # understands work items.
        return "synthetic-work-item"

    def process_work_item(self, work_item):
        for feeder in self.feeders:
            feeder.feed()
        time.sleep(self._sleep_duration)
        return True

    def work_item_log_path(self, work_item):
        return None

    def handle_unexpected_error(self, work_item, message):
        _log.error(message)


class AbstractPatchQueue(AbstractQueue):
    def _update_status(self, message, patch=None, results_file=None):
        return self._tool.status_server.update_status(self.name, message, patch, results_file)

    def _next_patch(self):
        # FIXME: Bugzilla accessibility should be checked here; if it's unaccessible,
        # it should return None.
        patch = None
        while not patch:
            patch_id = self._tool.status_server.next_work_item(self.name)
            if not patch_id:
                return None
            try:
                patch = self._tool.bugs.fetch_attachment(patch_id, throw_on_access_error=True)
            except Bugzilla.AccessError as e:
                if e.error_code == Bugzilla.AccessError.NOT_PERMITTED:
                    patch = self._tool.status_server.fetch_attachment(patch_id)
            if not patch:
                # FIXME: Using a fake patch because release_work_item has the wrong API.
                # We also don't really need to release the lock (although that's fine),
                # mostly we just need to remove this bogus patch from our queue.
                # If for some reason bugzilla is just down, then it will be re-fed later.
                fake_patch = Attachment({'id': patch_id}, None)
                self._did_skip(fake_patch)
        return patch

    def _release_work_item(self, patch):
        self._tool.status_server.release_work_item(self.name, patch)

    def _did_pass(self, patch):
        self._update_status(self._pass_status, patch)
        self._release_work_item(patch)

    def _did_fail(self, patch):
        self._update_status(self._fail_status, patch)
        self._release_work_item(patch)

    def _did_error(self, patch, reason):
        message = "%s: %s" % (self._error_status, reason)
        self._update_status(message, patch)
        self._release_work_item(patch)

    def _did_skip(self, patch):
        self._update_status(self._skip_status, patch)
        self._release_work_item(patch)

    def _unlock_patch(self, patch):
        self._tool.status_server.release_lock(self.name, patch)

    def work_item_log_path(self, patch):
        return os.path.join(self._log_directory(), "%s.log" % patch.bug_id())

    def build_style(self):
        return "release"


# Used to share code between the EWS and commit-queue.
class PatchProcessingQueue(AbstractPatchQueue):
    # Subclasses must override.
    port_name = None

    def __init__(self, options=None):
        self._port = None  # We can't instantiate port here because tool isn't avaialble.
        AbstractPatchQueue.__init__(self, options)

    # FIXME: This is a hack to map between the old port names and the new port names.
    def _new_port_name_from_old(self, port_name, platform):
        # ApplePort.determine_full_port_name asserts if the name doesn't include version.
        if port_name == 'mac':
            return 'mac-' + platform.os_version_name().lower().replace(' ', '')
        if port_name == 'win':
            return 'win-future'
        return port_name

    def _create_port(self):
        self._port = self._tool.port_factory.get(self._new_port_name_from_old(self.port_name, self._tool.platform))
        if self.architecture:
            self._port.set_architecture(self.architecture)
        if self.build_style() == "debug":
            self._port.set_option("configuration", "Debug")
        else:
            self._port.set_option("configuration", "Release")

    def begin_work_queue(self):
        AbstractPatchQueue.begin_work_queue(self)
        if not self.port_name:
            return
        # FIXME: This is only used for self._deprecated_port.flag()
        self._deprecated_port = DeprecatedPort.port(self.port_name)
        # FIXME: This violates abstraction
        self._tool._deprecated_port = self._deprecated_port

        self._create_port()

    # FIXME: Bugzilla member functions should perform this check as they can do it as part of the same
    # network request. This would also avoid bugs where the access of the Bugzilla bug changes between
    # the time-of-check (calling this function) and time-of-use (when we ask Bugzilla to perform the
    # actual operation).
    def _can_access_bug(self, bug_id):
        return bool(self._tool.bugs.fetch_bug(bug_id))

    def _upload_results_archive_for_patch(self, patch, results_archive_zip):
        if not self._port:
            self._create_port()

        bot_id = self._tool.status_server.bot_id or "bot"
        description = "Archive of layout-test-results from %s for %s" % (bot_id, self._port.name())
        # results_archive is a ZipFile object, grab the File object (.fp) to pass to Mechanize for uploading.
        results_archive_file = results_archive_zip.fp
        # Rewind the file object to start (since Mechanize won't do that automatically)
        # See https://bugs.webkit.org/show_bug.cgi?id=54593
        results_archive_file.seek(0)
        # FIXME: This is a small lie to always say run-webkit-tests since Chromium uses new-run-webkit-tests.
        # We could make this code look up the test script name off the port.
        comment_text = "The attached test failures were seen while running run-webkit-tests on the %s.\n" % (self.name)
        # FIXME: We could easily list the test failures from the archive here,
        # currently callers do that separately.
        comment_text += BotInfo(self._tool, self._port.name()).summary_text()
        if self._can_access_bug(patch.bug_id()):
            self._tool.bugs.add_attachment_to_bug(patch.bug_id(), results_archive_file, description, filename="layout-test-results.zip", comment_text=comment_text)

    def _refetch_patch(self, patch):
        patch_id = patch.id()
        try:
            patch = self._tool.bugs.fetch_attachment(patch_id, throw_on_access_error=True)
        except Bugzilla.AccessError as e:
            # FIXME: Need a way to ask the status server to fetch the patch again. For now
            # we return the attachment as it was when it was originally uploaded to the
            # status server. See <https://bugs.webkit.org/show_bug.cgi?id=186817>.
            if e.error_code == Bugzilla.AccessError.NOT_PERMITTED:
                patch = self._tool.status_server.fetch_attachment(patch_id)
        return patch


class CommitQueue(PatchProcessingQueue, StepSequenceErrorHandler, CommitQueueTaskDelegate):
    def __init__(self, commit_queue_task_class=CommitQueueTask):
        self._commit_queue_task_class = commit_queue_task_class
        PatchProcessingQueue.__init__(self)

    name = "commit-queue"
    port_name = "mac"

    # AbstractPatchQueue methods

    def begin_work_queue(self):
        PatchProcessingQueue.begin_work_queue(self)
        self.committer_validator = CommitterValidator(self._tool)
        self._layout_test_results_reader = LayoutTestResultsReader(self._tool, self._port.results_directory(), self._log_directory())

    def next_work_item(self):
        return self._next_patch()

    def process_work_item(self, patch):
        self._cc_watchers(patch.bug_id())
        task = self._commit_queue_task_class(self, patch)
        try:
            if task.run():
                self._did_pass(patch)
                return True
            self._unlock_patch(patch)
            return False
        except PatchIsNotValid as error:
            self._did_error(patch, "%s did not process patch. Reason: %s" % (self.name, error.failure_message))
            return False
        except ScriptError as e:
            if self._can_access_bug(patch.bug_id()):
                validator = CommitterValidator(self._tool)
                validator.reject_patch_from_commit_queue(patch.id(), self._error_message_for_bug(task, patch, e))
            results_archive = task.results_archive_from_patch_test_run(patch)
            if results_archive:
                self._upload_results_archive_for_patch(patch, results_archive)
            self._did_fail(patch)
            return False

    def _failing_tests_message(self, task, patch):
        results = task.results_from_patch_test_run(patch)

        if not results:
            return None

        if results.did_exceed_test_failure_limit():
            return "Number of test failures exceeded the failure limit."
        return "New failing tests:\n%s" % "\n".join(results.failing_tests())

    def _error_message_for_bug(self, task, patch, script_error):
        message = self._failing_tests_message(task, patch)
        if not message:
            message = script_error.message_with_output(output_limit=5000)
        results_link = self._tool.status_server.results_url_for_status(task.failure_status_id)
        return "%s\nFull output: %s" % (message, results_link)

    def handle_unexpected_error(self, patch, message):
        self.committer_validator.reject_patch_from_commit_queue(patch.id(), message)

    # CommitQueueTaskDelegate methods

    def run_command(self, command):
        self.run_webkit_patch(command + [self._deprecated_port.flag()])

    def command_passed(self, message, patch):
        self._update_status(message, patch=patch)

    def command_failed(self, message, script_error, patch):
        failure_log = self._log_from_script_error_for_upload(script_error)
        return self._update_status(message, patch=patch, results_file=failure_log)

    def expected_failures(self):
        return self._expected_failures

    def test_results(self):
        return self._layout_test_results_reader.results()

    def archive_last_test_results(self, patch):
        return self._layout_test_results_reader.archive(patch)

    def refetch_patch(self, patch):
        return self._tool.bugs.fetch_attachment(patch.id())

    def report_flaky_tests(self, patch, flaky_test_results, results_archive=None):
        reporter = FlakyTestReporter(self._tool, self.name)
        reporter.report_flaky_tests(patch, flaky_test_results, results_archive)

    def did_pass_testing_ews(self, patch):
        # Only Mac and Mac WK2 run tests
        # FIXME: We shouldn't have to hard-code it here.
        patch_status = self._tool.status_server.patch_status
        return patch_status("mac-ews", patch.id()) == self._pass_status or patch_status("mac-wk2-ews", patch.id()) == self._pass_status

    # StepSequenceErrorHandler methods

    @classmethod
    def handle_script_error(cls, tool, state, script_error):
        # Hitting this error handler should be pretty rare.  It does occur,
        # however, when a patch no longer applies to top-of-tree in the final
        # land step.
        _log.error(script_error.message_with_output(output_limit=5000))

    @classmethod
    def handle_checkout_needs_update(cls, tool, state, options, error):
        message = "Tests passed, but commit failed (checkout out of date).  Updating, then landing without building or re-running tests."
        tool.status_server.update_status(cls.name, message, state["patch"])
        # The only time when we find out that out checkout needs update is
        # when we were ready to actually pull the trigger and land the patch.
        # Rather than spinning in the master process, we retry without
        # building or testing, which is much faster.
        options.build = False
        options.test = False
        options.update = True
        raise TryAgain()


class AbstractReviewQueue(PatchProcessingQueue, StepSequenceErrorHandler):
    """This is the base-class for the EWS queues and the style-queue."""
    def __init__(self, options=None):
        PatchProcessingQueue.__init__(self, options)

    def review_patch(self, patch):
        raise NotImplementedError("subclasses must implement")

    # AbstractPatchQueue methods

    def begin_work_queue(self):
        PatchProcessingQueue.begin_work_queue(self)

    def next_work_item(self):
        return self._next_patch()

    def process_work_item(self, patch):
        self._update_status("Started processing patch", patch)
        passed = self.review_patch(patch)
        if passed:
            self._did_pass(patch)
        return passed

    def handle_unexpected_error(self, patch, message):
        _log.error(message)

    # StepSequenceErrorHandler methods

    @classmethod
    def handle_script_error(cls, tool, state, script_error):
        _log.error(script_error.output)


class StyleQueue(AbstractReviewQueue, StyleQueueTaskDelegate):
    name = "style-queue"

    def __init__(self):
        AbstractReviewQueue.__init__(self)

    def review_patch(self, patch):
        task = StyleQueueTask(self, patch)
        try:
            style_check_succeeded = task.run()
            if not style_check_succeeded:
                # Caller unlocks when review_patch returns True, so we only need to unlock on transient failure.
                self._unlock_patch(patch)
            return style_check_succeeded
        except UnableToApplyPatch as e:
            self._did_error(patch, "%s unable to apply patch." % self.name)
            return False
        except PatchIsNotValid as error:
            self._did_error(patch, "%s did not process patch. Reason: %s" % (self.name, error.failure_message))
            return False
        except ScriptError as e:
            output = re.sub(r'Failed to run .+ exit_code: 1', '', e.output)
            message = "Attachment %s did not pass %s:\n\n%s\n\nIf any of these errors are false positives, please file a bug against check-webkit-style." % (patch.id(), self.name, output)
            self._tool.bugs.post_comment_to_bug(patch.bug_id(), message, cc=self.watchers)
            self._did_fail(patch)
            return False
        return True

    # StyleQueueTaskDelegate methods

    def run_command(self, command):
        self.run_webkit_patch(command)

    def command_passed(self, message, patch):
        self._update_status(message, patch=patch)

    def command_failed(self, message, script_error, patch):
        failure_log = self._log_from_script_error_for_upload(script_error)
        return self._update_status(message, patch=patch, results_file=failure_log)

    def expected_failures(self):
        return None

    def refetch_patch(self, patch):
        return super(StyleQueue, self)._refetch_patch(patch)
