# Copyright (c) 2021 Arm Limited
# All rights reserved
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2017 Mark D. Hill and David A. Wood
# Copyright (c) 2021 Huawei International
# 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 the copyright holders 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.

"""
Built in test cases that verify particular details about a gem5 run.
"""
import re
import os
import json

from testlib import test_util
from testlib.configuration import constants
from testlib.helper import joinpath, diff_out_file


class Verifier(object):
    def __init__(self, fixtures=tuple()):
        self.fixtures = fixtures

    def _test(self, *args, **kwargs):
        # Use a callback wrapper to make stack
        # traces easier to understand.
        self.test(*args, **kwargs)

    def instantiate_test(self, name_pfx):
        name = "-".join([name_pfx, self.__class__.__name__])
        return test_util.TestFunction(
            self._test, name=name, fixtures=self.fixtures
        )


class CheckH5StatsExist(Verifier):
    def __init__(self, stats_file="stats.h5"):
        super(CheckH5StatsExist, self).__init__()
        self.stats_file = stats_file

    def test(self, params):
        tempdir = params.fixtures[constants.tempdir_fixture_name].path
        h5_file = joinpath(tempdir, self.stats_file)
        if not os.path.isfile(h5_file):
            test_util.fail("Could not find h5 stats file %s", h5_file)


class MatchGoldStandard(Verifier):
    """
    Compares a standard output to the test output and passes if they match,
    fails if they do not.
    """

    def __init__(
        self, standard_filename, ignore_regex=None, test_filename="simout"
    ):
        """
        :param standard_filename: The path of the standard file to compare
        output to.

        :param ignore_regex: A string, compiled regex, or iterable containing
        either which will be ignored in 'standard' and test output files when
        diffing.
        """
        super(MatchGoldStandard, self).__init__()
        self.standard_filename = standard_filename
        self.test_filename = test_filename

        self.ignore_regex = _iterable_regex(ignore_regex)

    def test(self, params):
        # We need a tempdir fixture from our parent verifier suite.
        fixtures = params.fixtures
        # Get the file from the tempdir of the test.
        tempdir = fixtures[constants.tempdir_fixture_name].path
        self.test_filename = joinpath(tempdir, self.test_filename)

        diff = diff_out_file(
            self.standard_filename,
            self.test_filename,
            ignore_regexes=self.ignore_regex,
            logger=params.log,
        )
        if diff is not None:
            test_util.fail(
                "Stdout did not match:\n%s\nSee %s for full results"
                % (diff, tempdir)
            )

    def _generic_instance_warning(self, kwargs):
        """
        Method for helper classes to tell users to use this more generic class
        if they are going to manually override the test_filename param.
        """
        if "test_filename" in kwargs:
            raise ValueError(
                "If you are setting test_filename use the more"
                " generic %s"
                " instead" % MatchGoldStandard.__name__
            )


class DerivedGoldStandard(MatchGoldStandard):
    __ignore_regex_sentinel = object()
    _file = None
    _default_ignore_regex = []

    def __init__(
        self, standard_filename, ignore_regex=__ignore_regex_sentinel, **kwargs
    ):

        if ignore_regex == self.__ignore_regex_sentinel:
            ignore_regex = self._default_ignore_regex

        self._generic_instance_warning(kwargs)

        super(DerivedGoldStandard, self).__init__(
            standard_filename,
            test_filename=self._file,
            ignore_regex=ignore_regex,
            **kwargs,
        )


class MatchStdout(DerivedGoldStandard):
    _file = constants.gem5_simulation_stdout
    _default_ignore_regex = [
        re.compile("^\s+$"),  # Remove blank lines.
        re.compile("^gem5 Simulator System"),
        re.compile("^gem5 is copyrighted software"),
        re.compile("^Redirecting (stdout|stderr) to"),
        re.compile("^gem5 version "),
        re.compile("^gem5 compiled "),
        re.compile("^gem5 started "),
        re.compile("^gem5 executing on "),
        re.compile("^command line:"),
        re.compile("^Couldn't import dot_parser,"),
        re.compile("^info: kernel located at:"),
        re.compile("^info: Standard input is not a terminal"),
        re.compile("^Couldn't unlink "),
        re.compile("^Using GPU kernel code file\(s\) "),
        re.compile("^.* not found locally\. Downloading"),
        re.compile("^Finished downloading"),
    ]


class MatchStdoutNoPerf(MatchStdout):
    _file = constants.gem5_simulation_stdout
    _default_ignore_regex = MatchStdout._default_ignore_regex + [
        re.compile("^Exiting @ tick")
    ]


class MatchStderr(DerivedGoldStandard):
    _file = constants.gem5_simulation_stderr
    _default_ignore_regex = []


class MatchStats(DerivedGoldStandard):
    # TODO: Likely will want to change this verifier since we have the weird
    # perl script right now. A simple diff probably isn't going to work.
    _file = constants.gem5_simulation_stats
    _default_ignore_regex = []


class MatchConfigINI(DerivedGoldStandard):
    _file = constants.gem5_simulation_config_ini
    _default_ignore_regex = (
        re.compile("^(executable|readfile|kernel|image_file)="),
        re.compile("^(cwd|input|codefile)="),
    )


class MatchConfigJSON(DerivedGoldStandard):
    _file = constants.gem5_simulation_config_json
    _default_ignore_regex = (
        re.compile(r"""^\s*"(executable|readfile|kernel|image_file)":"""),
        re.compile(r"""^\s*"(cwd|input|codefile)":"""),
    )


class MatchFileRegex(Verifier):
    """
    Looking for a match between a regex pattern and the content of a list
    of files. Verifier will pass as long as the pattern is found in at least
    one of the files.
    """

    def __init__(self, regex, filenames):
        super(MatchFileRegex, self).__init__()
        self.regex = _iterable_regex(regex)
        self.filenames = filenames

    def parse_file(self, fname):
        with open(fname, "r") as file_:
            for line in file_:
                for regex in self.regex:
                    if re.match(regex, line):
                        return True

    def test(self, params):
        fixtures = params.fixtures
        # Get the file from the tempdir of the test.
        tempdir = fixtures[constants.tempdir_fixture_name].path

        for fname in self.filenames:
            if self.parse_file(joinpath(tempdir, fname)):
                return  # Success

        test_util.fail("Could not match regex.")


class MatchRegex(MatchFileRegex):
    """
    Looking for a match between a regex pattern and stdout/stderr.
    """

    def __init__(self, regex, match_stderr=True, match_stdout=True):
        filenames = list()
        if match_stdout:
            filenames.append(constants.gem5_simulation_stdout)
        if match_stderr:
            filenames.append(constants.gem5_simulation_stderr)
        super(MatchRegex, self).__init__(regex, filenames)


class NoMatchRegex(MatchRegex):
    """
    Checks that the given pattern does *not* match
    """

    def __init__(self, regex, match_stderr=True, match_stdout=True):
        super(NoMatchRegex, self).__init__(regex, match_stderr, match_stdout)

    def test(self, params):
        fixtures = params.fixtures
        tempdir = fixtures[constants.tempdir_fixture_name].path

        for fname in self.filenames:
            if self.parse_file(joinpath(tempdir, fname)):
                test_util.fail("Could not match regex.")


class MatchJSONStats(Verifier):
    """
    Verifer to check the correctness of stats reported by gem5. It uses
    gem5stats to store the stastistics as json files and does the comparison.
    """

    def __init__(
        self,
        truth_name: str,
        test_name: str,
        test_name_in_outdir: bool = False,
    ):
        """
        :param truth_dir: The path to the directory including the trusted_stats
        for this test.
        :param test_name_in_m5out: True if the 'test_name' dir is to found in
        the `m5.options.outdir`.
        """
        super(MatchJSONStats, self).__init__()
        self.truth_name = truth_name
        self.test_name = test_name
        self.test_name_in_outdir = test_name_in_outdir

    def _compare_stats(self, trusted_file, test_file):
        trusted_stats = json.load(trusted_file)
        test_stats = json.load(test_file)
        is_subset = trusted_stats.items() <= test_stats.items()
        if is_subset:
            err = (
                "Following differences found between "
                + f"{self.truth_name} and {self.test_name}.\n"
            )
            diffs = set(trusted_stats.items()) - set(test_stats.items())
            for diff in diffs:
                trusted_value = trusted_stats[diff[0]]
                test_value = None
                if diff[0] in test_stats.keys():
                    test_value = test_stats[diff[0]]
                err += f"{diff[0]}:\n"
                err += (
                    f"trusted_value: {trusted_value}, "
                    + f"test_value: {test_value}"
                )
            test_util.fail(err)

    def test(self, params):
        trusted_file = open(self.truth_name, "r")
        if self.test_name_in_outdir:
            fixtures = params.fixtures
            tempdir = fixtures[constants.tempdir_fixture_name].path
            test_file = open(joinpath(tempdir, self.test_name), "r")
        else:
            test_file = open(self.test_name, "r")

        return self._compare_stats(trusted_file, test_file)


_re_type = type(re.compile(""))


def _iterable_regex(regex):
    if not regex:
        return ()  # If no regex we return an empty tuple.
    if isinstance(regex, _re_type) or isinstance(regex, str):
        regex = (regex,)
    return regex
