# Copyright (C) 2011 Google 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:
# 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 COMPUTER, INC. ``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 COMPUTER, INC. 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.
#

from contextlib import contextmanager
import filecmp
import fnmatch
import os
import shutil
import tempfile

from webkitpy.common.system.executive import Executive

from webkitpy.common import webkit_finder
webkit_finder.add_bindings_scripts_dir_to_sys_path()

from code_generator_v8 import CodeGeneratorDictionaryImpl
from code_generator_v8 import CodeGeneratorV8
from code_generator_v8 import CodeGeneratorUnionType
from code_generator_v8 import CodeGeneratorCallbackFunction
from code_generator_web_agent_api import CodeGeneratorWebAgentAPI
from compute_interfaces_info_individual import InterfaceInfoCollector
from compute_interfaces_info_overall import (compute_interfaces_info_overall,
                                             interfaces_info)
from idl_compiler import (generate_bindings,
                          generate_union_type_containers,
                          generate_dictionary_impl,
                          generate_callback_function_impl)
from utilities import ComponentInfoProviderCobalt
from utilities import ComponentInfoProviderCore
from utilities import ComponentInfoProviderModules


PASS_MESSAGE = 'All tests PASS!'
FAIL_MESSAGE = """Some tests FAIL!
To update the reference files, execute:
    run-bindings-tests --reset-results

If the failures are not due to your changes, test results may be out of sync;
please rebaseline them in a separate CL, after checking that tests fail in ToT.
In CL, please set:
NOTRY=true
TBR=(someone in Source/bindings/OWNERS or WATCHLISTS:bindings)
"""

DEPENDENCY_IDL_FILES = frozenset([
    'TestImplements.idl',
    'TestImplements2.idl',
    'TestImplements3.idl',
    'TestInterfacePartial.idl',
    'TestInterfacePartial2.idl',
    'TestInterfacePartial3.idl',
    'TestInterfacePartial4.idl',
    'TestInterfacePartialSecureContext.idl',
    'TestInterface2Partial.idl',
    'TestInterface2Partial2.idl',
])

# core/inspector/InspectorInstrumentation.idl is not a valid Blink IDL.
NON_BLINK_IDL_FILES = frozenset([
    'InspectorInstrumentation.idl',
])

COMPONENT_DIRECTORY = frozenset(['core', 'modules'])

SOURCE_PATH = webkit_finder.get_source_dir()
TEST_INPUT_DIRECTORY = os.path.join(SOURCE_PATH, 'bindings', 'tests', 'idls')
REFERENCE_DIRECTORY = os.path.join(SOURCE_PATH, 'bindings', 'tests', 'results')

@contextmanager
def TemporaryDirectory():
    """Wrapper for tempfile.mkdtemp() so it's usable with 'with' statement.

    Simple backport of tempfile.TemporaryDirectory from Python 3.2.
    """
    name = tempfile.mkdtemp()
    try:
        yield name
    finally:
        shutil.rmtree(name)


def generate_interface_dependencies(test_input_directory, component_directories, ignore_idl_files, root_directory, extended_attributes_path):
    def idl_paths_recursive(directory):
        # This is slow, especially on Windows, due to os.walk making
        # excess stat() calls. Faster versions may appear in Python 3.5 or
        # later:
        # https://github.com/benhoyt/scandir
        # http://bugs.python.org/issue11406
        idl_paths = []
        for dirpath, _, files in os.walk(directory):
            idl_paths.extend(os.path.join(dirpath, filename)
                             for filename in fnmatch.filter(files, '*.idl'))
        return idl_paths

    def collect_blink_idl_paths():
        """Returns IDL file paths which blink actually uses."""
        idl_paths = []
        for component in component_directories:
            directory = os.path.join(SOURCE_PATH, component)
            idl_paths.extend(idl_paths_recursive(directory))
        return idl_paths

    def collect_interfaces_info(idl_path_list):
        info_collector = InterfaceInfoCollector(root_directory, extended_attributes_path)
        for idl_path in idl_path_list:
            if os.path.basename(idl_path) in ignore_idl_files:
                continue
            info_collector.collect_info(idl_path)
        info = info_collector.get_info_as_dict()
        # TestDictionary.{h,cpp} are placed under
        # Source/bindings/tests/idls/core. However, IdlCompiler generates
        # TestDictionary.{h,cpp} by using relative_dir.
        # So the files will be generated under
        # output_dir/core/bindings/tests/idls/core.
        # To avoid this issue, we need to clear relative_dir here.
        for value in info['interfaces_info'].itervalues():
            value['relative_dir'] = ''
        component_info = info_collector.get_component_info_as_dict()
        return info, component_info

    # We compute interfaces info for *all* IDL files, not just test IDL
    # files, as code generator output depends on inheritance (both ancestor
    # chain and inherited extended attributes), and some real interfaces
    # are special-cased, such as Node.
    #
    # For example, when testing the behavior of interfaces that inherit
    # from Node, we also need to know that these inherit from EventTarget,
    # since this is also special-cased and Node inherits from EventTarget,
    # but this inheritance information requires computing dependencies for
    # the real Node.idl file.
    non_test_idl_paths = collect_blink_idl_paths()
    # For bindings test IDL files, we collect interfaces info for each
    # component so that we can generate union type containers separately.
    test_idl_paths = {}
    for component in component_directories:
        test_idl_paths[component] = idl_paths_recursive(
            os.path.join(test_input_directory, component))
    # 2nd-stage computation: individual, then overall
    #
    # Properly should compute separately by component (currently test
    # includes are invalid), but that's brittle (would need to update this file
    # for each new component) and doesn't test the code generator any better
    # than using a single component.
    non_test_interfaces_info, non_test_component_info = collect_interfaces_info(non_test_idl_paths)
    test_interfaces_info = {}
    test_component_info = {}
    for component, paths in test_idl_paths.iteritems():
        test_interfaces_info[component], test_component_info[component] = collect_interfaces_info(paths)


    # Cobalt change: Just merge everything together, since we don't really care
    # about components. Return the ComponentInfoProvider instead of setting
    # a global.
    all_component_info = {}
    all_component_info.update(non_test_component_info)
    for component, paths in test_idl_paths.iteritems():
        all_component_info.update(test_component_info[component])
    info_individuals = [non_test_interfaces_info] + test_interfaces_info.values()
    compute_interfaces_info_overall(info_individuals)
    return ComponentInfoProviderCobalt(interfaces_info, all_component_info)


class IdlCompilerOptions(object):
    def __init__(self, output_directory, cache_directory, impl_output_directory,
                 target_component):
        self.output_directory = output_directory
        self.cache_directory = cache_directory
        self.impl_output_directory = impl_output_directory
        self.target_component = target_component


def bindings_tests(output_directory, verbose, reference_directory,
                   test_input_directory, idl_compiler_constructor,
                   code_generator_constructor,
                   component_directories, ignore_idl_files,
                   dependency_idl_files, root_directory,
                   extended_attributes_path, generate_union_containers):
    executive = Executive()

    def list_files(directory):
        all_files = []
        for component in os.listdir(directory):
            if component not in component_directories:
                continue
            for root, _, files in os.walk(os.path.join(directory, component)):
                all_files.extend([os.path.join(root, file) for file in files])
        return all_files

    def diff(filename1, filename2):
        # Python's difflib module is too slow, especially on long output, so
        # run external diff(1) command
        cmd = ['diff',
               '-u',  # unified format
               '-N',  # treat absent files as empty
               filename1,
               filename2]
        # Return output and don't raise exception, even though diff(1) has
        # non-zero exit if files differ.
        return executive.run_command(cmd, error_handler=lambda x: None)

    def is_cache_file(filename):
        return filename.endswith('.cache')

    def delete_cache_files():
        # FIXME: Instead of deleting cache files, don't generate them.
        cache_files = []
        for root, _, files in os.walk(output_directory):
            cache_files.extend([os.path.join(root, path) for path in files
                       if is_cache_file(path)])
        for cache_file in cache_files:
            os.remove(cache_file)

    def identical_file(reference_filename, output_filename):
        reference_basename = os.path.basename(reference_filename)

        if not os.path.isfile(reference_filename):
            print 'Missing reference file!'
            print '(if adding new test, update reference files)'
            print reference_basename
            print
            return False

        if not filecmp.cmp(reference_filename, output_filename):
            # cmp is much faster than diff, and usual case is "no difference",
            # so only run diff if cmp detects a difference
            print 'FAIL: %s' % reference_basename
            print diff(reference_filename, output_filename)
            return False

        if verbose:
            print 'PASS: %s' % reference_basename
        return True

    def identical_output_files(output_files):
        reference_files = [os.path.join(reference_directory,
                                        os.path.relpath(path, output_directory))
                           for path in output_files]
        return all([identical_file(reference_filename, output_filename)
                    for (reference_filename, output_filename) in zip(reference_files, output_files)])

    def no_excess_files(output_files):
        generated_files = set([os.path.relpath(path, output_directory)
                               for path in output_files])
        # Add subversion working copy directories in core and modules.
        for component in component_directories:
            generated_files.add(os.path.join(component, '.svn'))

        excess_files = []
        for path in list_files(reference_directory):
            relpath = os.path.relpath(path, reference_directory)
            if relpath not in generated_files:
                excess_files.append(relpath)
        if excess_files:
            print ('Excess reference files! '
                   '(probably cruft from renaming or deleting):\n' +
                   '\n'.join(excess_files))
            return False
        return True

    try:
        info_provider = generate_interface_dependencies(test_input_directory, component_directories, ignore_idl_files, root_directory, extended_attributes_path)
        for component in component_directories:
            output_dir = os.path.join(output_directory, component)
            if not os.path.exists(output_dir):
                os.makedirs(output_dir)

            options = IdlCompilerOptions(
                output_directory=output_dir,
                impl_output_directory=output_dir,
                cache_directory=None,
                target_component=component)

            if component == 'core':
                partial_interface_output_dir = os.path.join(output_directory,
                                                            'modules')
                if not os.path.exists(partial_interface_output_dir):
                    os.makedirs(partial_interface_output_dir)
                partial_interface_options = IdlCompilerOptions(
                    output_directory=partial_interface_output_dir,
                    impl_output_directory=None,
                    cache_directory=None,
                    target_component='modules')

            idl_filenames = []
            dictionary_impl_filenames = []
            partial_interface_filenames = []
            input_directory = os.path.join(test_input_directory, component)
            for filename in os.listdir(input_directory):
                if (filename.endswith('.idl') and
                        # Dependencies aren't built
                        # (they are used by the dependent)
                        filename not in dependency_idl_files):
                    idl_path = os.path.realpath(
                        os.path.join(input_directory, filename))
                    idl_filenames.append(idl_path)
                    idl_basename = os.path.basename(idl_path)
                    definition_name, _ = os.path.splitext(idl_basename)
                    if definition_name in interfaces_info:
                        interface_info = interfaces_info[definition_name]
                        if interface_info['is_dictionary']:
                            dictionary_impl_filenames.append(idl_path)
                        if component == 'core' and interface_info[
                                'dependencies_other_component_full_paths']:
                            partial_interface_filenames.append(idl_path)

            # Cobalt change: The same code generator is used for everything.
            generate_bindings(
                code_generator_constructor,
                info_provider,
                options,
                idl_filenames)

    finally:
        delete_cache_files()

    # Detect all changes
    output_files = list_files(output_directory)
    passed = identical_output_files(output_files)
    passed &= no_excess_files(output_files)

    if passed:
        if verbose:
            print
            print PASS_MESSAGE
        return 0
    print
    print FAIL_MESSAGE
    return 1


def run_bindings_tests(reset_results, verbose, args=None):
    # Generate output into the reference directory if resetting results, or
    # a temp directory if not.
    if not args:
        # Default args for blink
        args = {
            'idl_compiler_constructor': IdlCompilerV8,
            'test_input_directory': test_input_directory,
            'reference_directory': reference_directory,
            'component_directories': COMPONENT_DIRECTORY,
            'ignore_idl_files': NON_BLINK_IDL_FILES,
            'dependency_idl_files': DEPENDENCY_IDL_FILES,
            'generate_union_containers': True,
        }
    if reset_results:
        print 'Resetting results'
        return bindings_tests(args['reference_directory'], verbose, **args)
    with TemporaryDirectory() as temp_dir:
        return bindings_tests(temp_dir, verbose, **args)
