#!/usr/bin/env python
#
# Copyright (C) 2011 Igalia S.L.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; see the file COPYING.LIB.  If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.

from webkitpy.common.system.executive import Executive
import subprocess
import os, sys

class TestRunner:

    TEST_DIRS = [ "unittests", "WebKit2APITests" ]
    # FIXME: https://bugs.webkit.org/show_bug.cgi?id=74717
    SKIPPED = [ "unittests/testdownload", "unittests/testwebview", "unittests/testwebresource",
                # WebKit2APITests/TestDownloads is consistently timing
                # out on the 32bit release and 64bit debug bots.
                # https://bugs.webkit.org/show_bug.cgi?id=76910
                "WebKit2APITests/TestDownloads" ]

    def __init__(self):
        self._executive = Executive()

        # FIXME: webkit-build-directory --configuration always returns
        # Release because we never call set-webkit-configuration.
        #build_directory_script = os.path.join(os.path.dirname(__file__), "webkit-build-directory")
        #build_directory = self._executive.run_command([build_directory_script, "--configuration"]).rstrip()

        def is_valid_build_directory(build_dir):
            return os.path.exists(os.path.join(build_dir, ".libs"))

        script_dir = os.path.dirname(__file__)
        top_level = os.path.normpath(os.path.join(script_dir, "..", ".."))
        build_directory = os.path.join(top_level, 'WebKitBuild', 'Release')
        if not is_valid_build_directory(build_directory):
            build_directory = os.path.join(top_level, 'WebKitBuild', 'Debug')

        self._gtk_tools_directory = os.path.join(top_level, "Tools", "gtk")
        self._programs_path = os.path.join(build_directory, "Programs")
        self._tests = []
        for test_dir in self.TEST_DIRS:
            absolute_test_dir = os.path.join(self._programs_path, test_dir)
            if not os.path.isdir(absolute_test_dir):
                continue
            for test_file in os.listdir(absolute_test_dir):
                if not test_file.lower().startswith("test"):
                    continue
                test_relative_path = os.path.join(test_dir, test_file)
                if test_relative_path in self.SKIPPED:
                    sys.stdout.write("Skipping test %s\n" % (test_relative_path))
                    sys.stdout.flush()
                    continue

                test_path = os.path.join(self._programs_path, test_relative_path)
                if os.path.isfile(test_path) and os.access(test_path, os.X_OK):
                    self._tests.append(test_path)

    def _lookup_atspi2_binary(self, jhbuild_path, filename):
        exec_prefix = self._executive.run_command([jhbuild_path ,'pkg-config', '--variable=exec_prefix', 'atspi-2']).rstrip('\r\n')
        paths_to_check = [ 'libexec',
                           'lib/at-spi2-core',
                           'lib32/at-spi2-core'
                           'lib64/at-spi2-core' ]
        for path in paths_to_check:
            filepath = os.path.join(exec_prefix, path, filename)
            if os.path.isfile(filepath):
                return filepath

        return None

    def run(self):
        if not self._tests:
            sys.stderr.write("ERROR: tests not found in %s.\n" % (self._programs_path))
            sys.stderr.flush()
            return 1

        test_env = os.environ
        test_env["DISPLAY"] = ":55"

        exit_status = [0]
        def _error_handler(error):
            exit_status[0] = error.exit_code

        jhbuild_path = os.path.join(self._gtk_tools_directory, "run-with-jhbuild")

        # Make sure the accessibility bus is launched.
        a11y_bus_launched = False
        a11y_bus_launcher_path = self._lookup_atspi2_binary(jhbuild_path, 'at-spi-bus-launcher')
        if a11y_bus_launcher_path:
            try:
                a11y_bus_launcher = Executive().popen([a11y_bus_launcher_path], env=test_env)
                a11y_bus_launched = True
            except:
                sys.stderr.write("Failed to launch the accessibility bus\n")
                sys.stderr.flush()

        # Make sure the accessibility registry daemon is running.
        a11y_registryd_running = False
        a11y_registryd_path = self._lookup_atspi2_binary(jhbuild_path, 'at-spi2-registryd')
        if a11y_registryd_path:
            try:
                a11y_registryd = Executive().popen([a11y_registryd_path], env=test_env)
                a11y_registryd_running = True
            except:
                sys.stderr.write("Failed to run the accessibility registry\n")
                sys.stderr.flush()

        for test in self._tests:
            out = self._executive.run_command([jhbuild_path ,'gtester', test], env=test_env,
                                              error_handler=_error_handler)
            sys.stdout.write(out)
            sys.stdout.flush()

        if a11y_registryd_running:
            a11y_registryd.kill()
        if a11y_bus_launched:
            a11y_bus_launcher.kill()

        if exit_status[0]:
            sys.stdout.write("Tests failed\n")
            sys.stdout.flush()

        return exit_status[0]

if __name__ == "__main__":
    try:
        xvfb = Executive().popen(["Xvfb", ":55", "-screen", "0", "800x600x24", "-nolisten", "tcp"],
                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    except:
        sys.stderr.write("Failed to run Xvfb\n")
        sys.stderr.flush()
        sys.exit(1)

    try:
        sys.exit(TestRunner().run())
    finally:
        xvfb.kill()
