#!/usr/bin/env python
# Copyright (c) 2019 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 argparse
import logging
import os
import sys
import time

from webkitpy.common.host import Host
from webkitpy.common.system.executive import ScriptError
from webkitpy.common.system.logutils import configure_logging
from webkitpy.port.config import Config
from webkitpy.test.main import Tester

_log = logging.getLogger(__name__)

EXCEPTIONAL_EXIT_STATUS = -1


class NoAction(argparse.Action):
    def __init__(self, option_strings, dest, **kwargs):
        super(NoAction, self).__init__(option_strings, dest, nargs=0, **kwargs)

    def __call__(self, parser, namespace, values, option_string):
        setattr(namespace, self.dest, False if option_string.startswith('--no') else True)


class LldbTester(Tester):

    def parse_args(self):
        parser = argparse.ArgumentParser(description='A script which tests WebKit\'s lldb macros and integration')
        parser.add_argument('--build', '--no-build',
                            dest='build', action=NoAction,
                            default=None, help='Enable or disable calling build-lldbwebkittester before running the test (enabled by default). This will build the lldb test runner, bmalloc and WTF.')
        parser.add_argument('--root',
                            dest='root', action='store',
                            default=None, help='Path to a directory containing the binaries needed to run tests.')
        parser.add_argument('-v', '--verbose', action='count',
                            default=0, help='Verbose output (specify once for individual test results, twice for debug messages)')
        parser.add_argument('-t', '--timing', action='store_true',
                            default=False, help='Display per-test execution time (implies --verbose)')
        parser.add_argument('-q', '--quiet', action='store_true',
                            default=False, help='Run quietly (errors, warnings, and progress only)')
        parser.add_argument('-p', '--pass-through', action='store_true', default=False,
                            help='Be debugger friendly by passing captured output through to the system')
        parser.add_argument('--debug', const='debug',
                            dest='configuration', action='store_const',
                            default=None, help='Alias for configuration=debug.')
        parser.add_argument('--release', const='release',
                            dest='configuration', action='store_const',
                            default=None, help='Alias for configuration=release.')
        parser.add_argument('--configuration',
                            dest='configuration', action='store',
                            default=None, help='Set configuration (Debug/Release/ASan/ect.) to build and test the lldb test runner with.')
        parser.add_argument('names', nargs='*',
                            default=None, help='Name (or names) of test, or test suite, to be run. lldb_webkit_unittest.TestSummaryProviders and dump_class_layout_unittest.TestDumpClassLayout are two examples')
        return parser.parse_args()

    def run(self, host=None, webkit_root=None):
        configure_logging(logger=_log)
        host = host or Host()
        self._options = self.parse_args()
        self.printer.configure(self._options)
        self.finder.clean_trees()

        names = self.finder.find_names(self._options.names or [], True)
        if not names:
            _log.error('No tests to run')
            return False

        config = Config(host.executive, self.finder.filesystem)
        configuration_to_use = self._options.configuration or config.default_configuration()
        self.upload_style = configuration_to_use.lower()

        if (not self._options.root and self._options.build is None) or self._options.build:
            self.printer.write_update('Building lldbWebKitTester ...')
            build_lldbwebkittester = self.finder.filesystem.join(webkit_root, 'Tools', 'Scripts', 'build-lldbwebkittester')
            try:
                host.executive.run_and_throw_if_fail(
                    [build_lldbwebkittester, config.flag_for_configuration(configuration_to_use)],
                    quiet=(not bool(self._options.verbose)),
                )
            except ScriptError as e:
                _log.error(e.message_with_output(output_limit=None))
                return False

        os.environ['LLDB_WEBKIT_TESTER_EXECUTABLE'] = str(self.finder.filesystem.join(config.build_directory(configuration_to_use), 'lldbWebKitTester'))
        if not self.finder.filesystem.exists(os.environ['LLDB_WEBKIT_TESTER_EXECUTABLE']):
            _log.error('Failed to find lldbWebKitTester.')
            return False

        return self._run_tests(names)


def main():
    tester = LldbTester()
    host = Host()
    lldb_python_directory = host.path_to_lldb_python_directory()
    if not host.filesystem.isdir(lldb_python_directory):
        tester.parse_args()
        if not lldb_python_directory:
            print('lldb tests are only supported on macOS with XCode installed')
        else:
            print('Could not find {}, derived from running `xcrun lldb --python-path`'.format(lldb_python_directory))
        return 1

    up = host.filesystem.dirname
    webkit_root = up(up(up(host.filesystem.abspath(__file__))))

    if lldb_python_directory not in sys.path:
        sys.path.append(lldb_python_directory)
    tester.add_tree(host.filesystem.join(webkit_root, 'Tools', 'lldb'))

    return not tester.run(host=host, webkit_root=webkit_root)


if __name__ == '__main__':
    sys.exit(main())
