#!/usr/bin/env python
# Copyright 2021 The IREE Authors
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""Generates runners for a matrix of test configurations.

This tool is used for sources under test which should be run in a matrix of
different real-world configurations. It is aimed at integration tests which
typically need a greater degree of flexibility and less "framework-ness"
compared to (for example), lit-tests or more classic unit tests.

As with all modern things, it starts with directories that contain
test_matrix.yaml files, which describe tests.

Conceptually, the test_matrix.yaml file declares a list of test_groups
at the top-level. Each test group has an interpolated "id" which is unique
in the scope of all tests. Example:

  test_groups:
    - id: "math_real_{backend}_vs_{ref_backend}_{function}_dyndims_{dyndims}"

Interpolation is done relative to placeholders declared in a "matrix", where
one concrete test is instantiated for the cartesian product of all combinations
in the matrix. Here is an example matrix:

  matrix:
    backend: *BACKENDS
    ref_backend: *REF_BACKENDS
    function: *MATH_FUNCTIONS
    dyndims: ["true", "false"]

Each key in the matrix expands to a list (or list of lists that are flattened)
of string values. Note in the above that we have used YAML references to
include fragments defined elsewhere in the file.

Each concrete test is then generated according to one or more runners, which
are responsible for creating actual generated test sources. Example:

  runner:
    - type: tfhost
      main: math_test.py
      args:
        - "--functions={function}"
        - "--target_backends={backend}"
        - "--reference_backend={ref_backend}"
        - "--dynamic_dims={dyndims}"

The type of runner is a hard-coded feature of this script. See the
implementations at the end.

By default, every expanded combination is included in the test suite and is
expected to pass. This can be changed by including 'xfail' and/or 'xpass'
lists. A test will be marked expected-failing if it matches any of the
predicates in xfail and none of the predicates in xpass.

Example:
  xfail:
    # Vulkan is currently structurally broken with dyndims.
    - matrix.backend: iree_vulkan
      matrix.dyndims: "true"
  xpass:
    # Some dynamic dim functions pass on vulkan regardless of overall
    # broken support.
    - matrix.backend: iree_vulkan
      matrix.function: *VULKAN_DYNDIM_PASS_MATH_FUNCTIONS
      matrix.dyndims: "true"

Note that each entry in xfail/xpass is a mapping of key/value pairs. Any keys
that start with 'matrix.' are taken to match an expanded matrix placeholder.
A mapping predicate is evaluated as a product-of-sums where the overall
predicate is true if all of the listed keys have a match for any of their
values.

TODO: Add support for skipping combinations.
TODO: Add support for annotating combinations with 'requires' for env feature
  checking.
"""

from typing import Set, Tuple

import argparse
from contextlib import contextmanager
import os
import shutil

try:
    import yaml
except ModuleNotFoundError as e:
    raise RuntimeError(
        f"PyYAML is not installed. Typically: 'python -m pip install PyYAML"
    ) from e

################################################################################
# Base classes and types
################################################################################


class Environment:
    """Runtime environment for processing a directory."""

    def __init__(self, args, root_dir: str, output_dir: str):
        self.args = args
        self.root_dir = root_dir
        self.output_dir = output_dir
        # Set of directories containing purely generated files.
        self.gen_dirs = set()  # type: Set[str]
        # Set of (gen_dir, file_name) for all files in a given directory that have
        # been generated.
        self.gen_files = set()  # type: Set[Tuple[str, str]]

    def remember_gen_file(self, gen_file_path: str):
        gen_dir = os.path.dirname(gen_file_path)
        gen_file = os.path.basename(gen_file_path)
        self.gen_dirs.add(gen_dir)
        self.gen_files.add((gen_dir, gen_file))

    def prune_gen_files(self):
        found_gen_files = set()
        for gen_dir in self.gen_dirs:
            dir_listing = os.listdir(gen_dir)
            for fname in dir_listing:
                found_gen_files.add((gen_dir, fname))
        obsolete_gen_files = found_gen_files - self.gen_files
        if obsolete_gen_files:
            for gen_dir, fname in obsolete_gen_files:
                obsolete_path = os.path.join(gen_dir, fname)
                log(f"Removing obsolete file {obsolete_path}")
                if os.path.isdir(obsolete_path):
                    shutil.rmtree(obsolete_path)
                else:
                    os.remove(obsolete_path)


class Runner:
    """Base class for a runner."""

    RUNNER_IDENT = None

    def __init__(self, env: Environment, test_id: str):
        self.env = env
        self.test_id = test_id
        self.gen_dir = os.path.join(self.env.output_dir, "generated")
        self.xfail = False

    @property
    def runner_ident(self) -> str:
        assert self.RUNNER_IDENT, "Must define RUNNER_IDENT"
        return self.RUNNER_IDENT

    def create_gen_file(self, file_name: str, mode: str = "wt"):
        os.makedirs(self.gen_dir, exist_ok=True)
        full_path = os.path.join(self.gen_dir, file_name)
        handle = open(full_path, mode)
        self.env.remember_gen_file(full_path)
        return handle

    def link_file(self, from_path: str, to_path: str):
        if from_path == to_path:
            return
        from_path = os.path.realpath(from_path)
        os.makedirs(os.path.dirname(to_path), exist_ok=True)
        if os.path.exists(to_path):
            os.remove(to_path)
        os.symlink(from_path, to_path)

    def generate(self):
        raise NotImplementedError(f"Generate not implemented for {self.__class__}")


################################################################################
# Main logic
################################################################################


def parse_arguments():
    parser = argparse.ArgumentParser(description="Test matrix generator")
    parser.add_argument("--dir", required=True, type=str, help="Directory to process")
    parser.add_argument(
        "--output_dir", required=True, type=str, help="Output directory"
    )
    args = parser.parse_args()
    return args


def main(args):
    env = Environment(args, args.dir, args.output_dir)
    process_directory(env)


def process_directory(env: Environment):
    dir = os.path.realpath(env.root_dir)
    try:
        config_sections = read_directory_config(dir)
    except Exception as e:
        raise RuntimeError(f"Could not read configuration from {dir}") from e
    for section in config_sections:
        require_mapping(section)
        for config_key, config_value in section.items():
            if config_key == "lists":
                # Ignore: a place to stash anchors and references.
                pass
            elif config_key == "test_groups":
                require_list(config_value)
                for test_group in config_value:
                    require_mapping(test_group)
                    process_test_group(env, test_group)
            else:
                raise ValueError(f"Unexpected top-level section {config_key}")

    env.prune_gen_files()


def process_test_group(env: Environment, test_group):
    group_id = get_mapping_key(test_group, "id", require_str)
    matrix = generate_matrix(get_mapping_key(test_group, "matrix", require_mapping))
    matrix_id_map = {group_id.format(**m): m for m in matrix}
    for runner_map in get_mapping_key(test_group, "runner", require_list):
        for matrix_id, matrix_map in matrix_id_map.items():
            runner = create_runner(env, matrix_id, runner_map, matrix_map)
            runner.xfail = evaluate_xfail(
                test_group, matrix_map
            ) and not evaluate_xpass(test_group, matrix_map)
            runner.generate()


def evaluate_xfail(test_group, matrix_map) -> bool:
    try:
        xfail_list = flatten_lists(require_list(test_group["xfail"]))
    except KeyError:
        return False
    for xfail_group in xfail_list:
        if evaluate_matrix_map_predicate(matrix_map, xfail_group):
            return True
    return False


def evaluate_xpass(test_group, matrix_map) -> bool:
    try:
        xpass_list = flatten_lists(require_list(test_group["xpass"]))
    except KeyError:
        return False
    for xpass_group in xpass_list:
        if evaluate_matrix_map_predicate(matrix_map, xpass_group):
            return True
    return False


def evaluate_matrix_map_predicate(matrix_map, predicate_group) -> bool:
    # Each key is something like 'matrix.<key>' which are and'ed
    # together. Each value is either a literal or a list that is
    # or'd together.
    for pred_key, pred_value in predicate_group.items():
        match_value = None
        if pred_key.startswith("matrix."):
            try:
                match_value = matrix_map[pred_key[len("matrix.") :]]
            except KeyError:
                raise ValueError(
                    f"Could not match matrix predicate to matrix value: {pred_key}"
                )
        else:
            raise ValueError(
                f"Expected a matrix predicate (i.e. matrix.) but got {pred_key}"
            )
        # Match list (OR) or literal (==)
        if isinstance(pred_value, list):
            if match_value not in flatten_lists(pred_value):
                return False
        else:
            if pred_value != match_value:
                return False
    return True


################################################################################
# Utilities
################################################################################


def generate_matrix(matrix_map):
    # List of (key, [value, value, ...])
    matrix_entries = [(k, flatten_lists(v)) for k, v in matrix_map.items()]
    # Permute.
    permuted = []

    def accumulate(prior: dict, i: int):
        if i == len(matrix_entries):
            permuted.append(prior)
            return
        next_key, next_values = matrix_entries[i]
        for next_value in next_values:
            current = dict(prior)
            current[next_key] = next_value
            accumulate(current, i + 1)

    accumulate({}, 0)
    return permuted


def read_directory_config(dir: str) -> list:
    sections = []
    matrix_path = os.path.join(dir, "test_matrix.yaml")
    with open(matrix_path, "r") as stream:
        for section in yaml.safe_load_all(stream):
            sections.append(section)
    return sections


INDENT = 0


def log(msg: str):
    print("  " * INDENT + msg)


@contextmanager
def indent():
    global INDENT
    INDENT += 1
    yield
    INDENT -= 1


def flatten_lists(l):
    results = list()
    for item in l:
        if isinstance(item, list):
            results.extend(flatten_lists(item))
        else:
            results.append(item)
    return results


def require_mapping(v):
    if isinstance(v, dict):
        return v
    raise ValueError(f"Expected a YAML mapping for {v}")


def require_list(v):
    if isinstance(v, list):
        return v
    raise ValueError(f"Expected YAML list for {v}")


def require_str(v):
    if isinstance(v, str):
        return v
    raise ValueError(f"Expected str for {v}")


def get_mapping_key(mapping, key: str, checker=None):
    if key not in mapping:
        raise ValueError(f"Expected key '{key}' in {mapping}")
    value = mapping[key]
    if checker:
        checker(value)
    return value


################################################################################
# Runners
################################################################################

PYRUNNER_STUB = r"""
import importlib
import os
import sys
resolved_imports = False
for _ in range(2):
  try:
    for impname in REQUIRE_IMPORTS:
      importlib.import_module(impname)
    resolved_imports = True
  except ModuleNotFoundError as e:
    if os.path.exists(os.path.join(os.getcwd(), "CMakeCache.txt")):
      d = os.path.join(os.getcwd(), "bindings", "python")
      if os.path.exists(d):
        print(f"Added {d} to sys.path", file=sys.stderr)
        sys.path.append(d)
if not resolved_imports:
  raise Exception(f"Cannot find required imports: {REQUIRE_IMPORTS}\n"
                  f"If running interactively, ensure that you are in the "
                  f"build directory or have packages installed")

sys.argv = [sys.argv[0]] + ARGS + sys.argv[1:]
with open(MAIN, "rt") as f:
  script = f.read()
FAILED = False
try:
  exec(script, globals())
except SystemExit as exitex:
  # unittest like to sys.exit() itself. Catch that here so we can
  # process XFAIL properly.
  if exitex.code: FAILED = True
except:
  FAILED = True
  import traceback
  traceback.print_exc()
  if not XFAIL:
    raise

if XFAIL:
  if FAILED:
    print("=== TEST FAILED AS EXPECTED ===", file=sys.stderr)
    sys.exit(0)
  else:
    print("=== TEST PASSED BUT WAS EXPECTED TO FAIL ===", file=sys.stderr)
    sys.exit(1)

if FAILED:
  sys.exit(1)
"""


class TfHostRunner(Runner):
    """Runner for tf e2e host tests."""

    RUNNER_IDENT = "tfhost"

    def __init__(
        self, env: Environment, test_id: str, runner_map: dict, matrix_map: dict
    ):
        super().__init__(env=env, test_id=test_id)
        self.main_file = get_mapping_key(runner_map, "main", require_str)
        raw_arg_list = get_mapping_key(runner_map, "args", require_list)
        self.args = [
            require_str(raw_arg).format(**matrix_map) for raw_arg in raw_arg_list
        ]

    def generate(self):
        # Generate the runner script.
        file_name = (
            f"{'XFAIL_' if self.xfail else ''}{self.test_id}_{self.runner_ident}.py"
        )
        with self.create_gen_file(file_name) as f:
            parts = [
                "import os",
                "import sys",
                "REQUIRE_IMPORTS = ['iree.tf.support.tf_utils', 'iree.tf.support.tf_test_utils']",
                f"ARGS = {repr(self.args)}",
                f"MAIN = os.path.join(os.path.dirname(__file__), '..', {repr(self.main_file)})",
                f"XFAIL = {self.xfail}",
                PYRUNNER_STUB,
            ]
            f.write("\n".join(parts))

        # Copy/link the main file.
        main_file_src_path = os.path.join(self.env.root_dir, self.main_file)
        main_file_dst_path = os.path.join(self.env.output_dir, self.main_file)
        if not os.path.exists(main_file_src_path):
            raise RuntimeError(
                f"Referenced main file '{main_file_src_path}' does not exist"
            )
        self.link_file(main_file_src_path, main_file_dst_path)


RUNNER_CLASSES = {
    "tfhost": TfHostRunner,
}


def create_runner(env: Environment, test_id: str, runner_map: dict, matrix_map: dict):
    runner_type = get_mapping_key(runner_map, "type", require_str)
    try:
        runner_class = RUNNER_CLASSES[runner_type]
    except KeyError:
        raise ValueError(f"Unknown runner type '{runner_type}'")
    return runner_class(
        env=env, test_id=test_id, runner_map=runner_map, matrix_map=matrix_map
    )


if __name__ == "__main__":
    main(parse_arguments())
