#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
#

# Cache Key Test Instructions
#
# Adding Tests
# ~~~~~~~~~~~~
# Cache key tests are bst element files created created in such a way
# to exercise a feature which would cause the cache key for an element
# or source to be calculated differently.
#
# Adding tests is a matter to adding files to the project found in the
# 'project' subdirectory of this test case. Any files should be depended
# on by the main `target.bst` in the toplevel of the project.
#
# One test is comprised of one `<element-name>.bst` file and one
# '<element-name>.expected' file in the same directory, containing the
# expected cache key.
#
# Running the cache key test once will reveal what the new element's
# cache key should be and will also cause the depending elements to
# change cache keys.
#
#
# Updating tests
# ~~~~~~~~~~~~~~
# When a test fails it will come with a summary of which cache keys
# in the test project have mismatched.
#
# Also, in the case that the tests have changed or the artifact
# versions have changed in some way and the test needs to be
# updated; the expected cache keys for the given run are dumped to
# '<element-name>.actual' files beside the corresponding
# '<element-name>.expected' files they mismatched with, all inside
# a temporary test directory.
#
# One can now easily copy over the .actual files from a failed
# run over to the corresponding .expected source files and commit
# the result.
#

# Pylint doesn't play well with fixtures and dependency injection from pytest
# pylint: disable=redefined-outer-name

import os

import pytest

from buildstream._testing._cachekeys import check_cache_key_stability, _parse_output_keys
from buildstream._testing.runcli import cli  # pylint: disable=unused-import
from buildstream._testing._utils.site import HAVE_BZR, HAVE_GIT, IS_LINUX, MACHINE_ARCH
from buildstream.plugin import CoreWarnings
from buildstream import _yaml


# Project directory
DATA_DIR = os.path.join(
    os.path.dirname(os.path.realpath(__file__)),
    "project",
)


# The cache key test uses a project which exercises all plugins,
# so we cant run it at all if we dont have them installed.
#
@pytest.mark.skipif(MACHINE_ARCH != "x86-64", reason="Cache keys depend on architecture")
@pytest.mark.skipif(not IS_LINUX, reason="Only available on linux")
@pytest.mark.skipif(HAVE_BZR is False, reason="bzr is not available")
@pytest.mark.skipif(HAVE_GIT is False, reason="git is not available")
@pytest.mark.datafiles(DATA_DIR)
def test_cache_key(datafiles, cli):
    project = str(datafiles)

    # Workaround bug in recent versions of setuptools: newer
    # versions of setuptools fail to preserve symbolic links
    # when creating a source distribution, causing this test
    # to fail from a dist tarball.
    goodbye_link = os.path.join(project, "files", "local", "usr", "bin", "goodbye")
    os.unlink(goodbye_link)
    os.symlink("hello", goodbye_link)
    # pytest-datafiles does not copy mode bits
    # https://github.com/omarkohl/pytest-datafiles/issues/11
    os.chmod(goodbye_link, 0o755)

    check_cache_key_stability(project, cli)


@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize(
    "first_warnings, second_warnings, identical_keys",
    [
        [[], [], True],
        [[], [CoreWarnings.REF_NOT_IN_TRACK], False],
        [[CoreWarnings.REF_NOT_IN_TRACK], [], False],
        [[CoreWarnings.REF_NOT_IN_TRACK], [CoreWarnings.REF_NOT_IN_TRACK], True],
        [
            [CoreWarnings.REF_NOT_IN_TRACK, CoreWarnings.OVERLAPS],
            [CoreWarnings.OVERLAPS, CoreWarnings.REF_NOT_IN_TRACK],
            True,
        ],
    ],
)
def test_cache_key_fatal_warnings(cli, tmpdir, first_warnings, second_warnings, identical_keys):

    # Builds project, Runs bst show, gathers cache keys
    def run_get_cache_key(project_name, warnings):
        config = {"name": "test", "min-version": "2.0", "element-path": "elements", "fatal-warnings": warnings}

        project_dir = tmpdir.mkdir(project_name)
        project_config_file = str(project_dir.join("project.conf"))
        _yaml.roundtrip_dump(config, file=project_config_file)

        elem_dir = project_dir.mkdir("elements")
        element_file = str(elem_dir.join("stack.bst"))
        _yaml.roundtrip_dump({"kind": "stack"}, file=element_file)

        result = cli.run(project=str(project_dir), args=["show", "--format", "%{name}::%{full-key}", "stack.bst"])
        return result.output

    # Returns true if all keys are identical
    def compare_cache_keys(first_keys, second_keys):
        return not any((x != y for x, y in zip(first_keys, second_keys)))

    first_keys = run_get_cache_key("first", first_warnings)
    second_keys = run_get_cache_key("second", second_warnings)

    assert compare_cache_keys(first_keys, second_keys) == identical_keys


@pytest.mark.datafiles(DATA_DIR)
def test_keys_stable_over_targets(cli, datafiles):
    root_element = "elements/key-stability/top-level.bst"
    target1 = "elements/key-stability/t1.bst"
    target2 = "elements/key-stability/t2.bst"

    project = str(datafiles)
    full_graph_result = cli.run(project=project, args=["show", "--format", "%{name}::%{full-key}", root_element])
    full_graph_result.assert_success()
    all_cache_keys = _parse_output_keys(full_graph_result.output)

    ordering1_result = cli.run(project=project, args=["show", "--format", "%{name}::%{full-key}", target1, target2])
    ordering1_result.assert_success()
    ordering1_cache_keys = _parse_output_keys(ordering1_result.output)

    ordering2_result = cli.run(project=project, args=["show", "--format", "%{name}::%{full-key}", target2, target1])
    ordering2_result.assert_success()
    ordering2_cache_keys = _parse_output_keys(ordering2_result.output)

    elements = ordering1_cache_keys.keys()

    assert {key: ordering2_cache_keys[key] for key in elements} == ordering1_cache_keys
    assert {key: all_cache_keys[key] for key in elements} == ordering1_cache_keys
