# Copyright (c) 2020 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
# 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.

import os
import copy
import subprocess
import sys

from testlib.test_util import TestFunction
from testlib.suite import TestSuite
from testlib.helper import log_call
from testlib.configuration import constants, config
from .fixture import TempdirFixture, Gem5Fixture, VariableFixture

from . import verifier

def gem5_verify_config(name,
                       config,
                       config_args,
                       verifiers,
                       gem5_args=tuple(),
                       fixtures=[],
                       valid_isas=constants.supported_isas,
                       valid_variants=constants.supported_variants,
                       length=constants.supported_lengths[0],
                       valid_hosts=constants.supported_hosts,
                       protocol=None):
    '''
    Helper class to generate common gem5 tests using verifiers.

    The generated TestSuite will run gem5 with the provided config and
    config_args. After that it will run any provided verifiers to verify
    details about the gem5 run.

    .. seealso::  For the verifiers see :mod:`testlib.gem5.verifier`

    :param name: Name of the test.
    :param config: The config to give gem5.
    :param config_args: A list of arguments to pass to the given config.

    :param verifiers: An iterable with Verifier instances which will be placed
        into a suite that will be ran after a gem5 run.

    :param gem5_args: An iterable with arguments to give to gem5. (Arguments
        that would normally go before the config path.)

    :param valid_isas: An iterable with the isas that this test can be ran
        for. If None given, will run for all supported_isas.

    :param valid_variants: An iterable with the variant levels that
        this test can be ran for. (E.g. opt, debug)
    '''
    fixtures = list(fixtures)
    testsuites = []

    for host in valid_hosts:
        for opt in valid_variants:
            for isa in valid_isas:

                # Create a tempdir fixture to be shared throughout the test.
                tempdir = TempdirFixture()
                gem5_returncode = VariableFixture(
                        name=constants.gem5_returncode_fixture_name)

                # Common name of this generated testcase.
                _name = '{given_name}-{isa}-{host}-{opt}'.format(
                        given_name=name,
                        isa=isa,
                        host=host,
                        opt=opt)
                if protocol:
                    _name += '-'+protocol

                # Create the running of gem5 subtest.  NOTE: We specifically
                # create this test before our verifiers so this is listed
                # first.
                tests = []
                gem5_execution = TestFunction(
                        _create_test_run_gem5(config, config_args, gem5_args),
                        name=_name)
                tests.append(gem5_execution)

                # Create copies of the verifier subtests for this isa and
                # variant.
                for verifier in verifiers:
                    tests.append(verifier.instantiate_test(_name))

                # Add the isa and variant to tags list.
                tags = [isa, opt, length, host]

                # Create the gem5 target for the specific architecture and
                # variant.
                _fixtures = copy.copy(fixtures)
                _fixtures.append(Gem5Fixture(isa, opt, protocol))
                _fixtures.append(tempdir)
                _fixtures.append(gem5_returncode)

                # Finally construct the self contained TestSuite out of our
                # tests.
                testsuites.append(TestSuite(
                    name=_name,
                    fixtures=_fixtures,
                    tags=tags,
                    tests=tests))
    return testsuites

def _create_test_run_gem5(config, config_args, gem5_args):
    def test_run_gem5(params):
        '''
        Simple \'test\' which runs gem5 and saves the result into a tempdir.

        NOTE: Requires fixtures: tempdir, gem5
        '''
        fixtures = params.fixtures

        if gem5_args is None:
            _gem5_args = tuple()
        elif isinstance(gem5_args, str):
            # If just a single str, place it in an iterable
            _gem5_args = (gem5_args,)
        else:
            _gem5_args = gem5_args

        # FIXME/TODO: I don't like the idea of having to modify this test run
        # or always collect results even if not using a verifier. There should
        # be some configuration in here that only gathers certain results for
        # certain verifiers.
        #
        # I.E. Only the returncode verifier will use the gem5_returncode
        # fixture, but we always require it even if that verifier isn't being
        # ran.
        tempdir = fixtures[constants.tempdir_fixture_name].path
        gem5 = fixtures[constants.gem5_binary_fixture_name].path
        command = [
            gem5,
            '-d', # Set redirect dir to tempdir.
            tempdir,
            '-re', # TODO: Change to const. Redirect stdout and stderr
            '--silent-redirect',
        ]
        command.extend(_gem5_args)
        command.append(config)
        # Config_args should set up the program args.
        command.extend(config_args)
        log_call(params.log, command, time=params.time,
            stdout=sys.stdout, stderr=sys.stderr)

    return test_run_gem5
