# -*- coding: utf-8 -*-
# Copyright (c) 2016, University of Kaiserslautern
# 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.
#
# 3. Neither the name of the copyright holder 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 HOLDER
# 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.
#
# Authors: Éder F. Zulian
#

import unittest
import subprocess
import os
import shutil
import multiprocessing
import sys
import tempfile
from memutil import *


devnull = None
# If you want to change the standard output and/or standard error output do
# that in the top-level script environment (the '__main__' at the very bottom
# of this file.
out = None
errout = None

rootdir = '../../..'
workingdir = os.getcwd()
tempfile.tempdir = workingdir + '/' + rootdir
builddir = tempfile.mkdtemp()
simdir = builddir + '/simulator'

mcConfigPath = rootdir + '/DRAMSys/library/resources/configs/mcconfigs'
memSpecsPath = rootdir + '/DRAMSys/library/resources/configs/memspecs'
baseConfigPath = workingdir + '/baseconfig.xml'
qmakeProjFile = '../DRAMSys/DRAMSys.pro'


def build_project():
    if os.path.exists(builddir):
        shutil.rmtree(builddir)
    os.makedirs(builddir)
    os.chdir(builddir)
    subprocess.call(['qmake', qmakeProjFile], stdout=out, stderr=errout)
    makejobs = '-j' + str(multiprocessing.cpu_count())
    ret = subprocess.call(['make', makejobs], stdout=out, stderr=errout)
    return ret


class TestBuild(unittest.TestCase):
    def test_build_project(self):
        """ The project's build process should succeed """
        self.assertEqual(build_project(), 0)

    def tearDown(self):
        shutil.rmtree(builddir)


class TestRun(unittest.TestCase):
    def setUp(self):
        build_project()

    def test_run_without_arguments(self):
        """ running dramSys without arguments returns 0 """
        os.chdir(simdir)
        self.assertEqual(subprocess.call(['./DRAMSys'], stdout=out), 0)

    def tearDown(self):
        shutil.rmtree(builddir)


@unittest.skip("skipping this")
class TestOutput(unittest.TestCase):
    def setUp(self):
        self.tfd, self.tfpath = tempfile.mkstemp()
        self.outrefpath = workingdir + '/baseconfig_expected.out'
        build_project()

    def filter_output(self, fname):
        with open(fname, 'r') as f:
            lines = f.readlines()
        f.close()
        return [l for l in lines if l.startswith('sim.dram')]

    def test_run_with_base_config(self):
        """ running dramSys with base config, output match reference """
        os.chdir(simdir)
        with open(self.tfpath, 'w') as f:
            self.assertEqual(subprocess.call(['./DRAMSys', baseConfigPath],
                             stdout=f), 0)
        f.close()
        tout = self.filter_output(self.tfpath)
        tref = self.filter_output(self.outrefpath)
        self.assertListEqual(tout, tref)

    def tearDown(self):
        shutil.rmtree(builddir)
        os.unlink(self.tfpath)


# This is an example that shows how to skip a test.
@unittest.skip("skipping this")
class TestDummy(unittest.TestCase):
    def setUp(self):
        os.chdir(workingdir)

    def test_list_files(self):
        """ Test that lists some configuration files with XML extension """
        print('\nPath is: {}\n'.format(mcConfigPath))
        for file in os.listdir(mcConfigPath):
            if file.endswith(".xml"):
                print(file)
        print('\nPath is: {}\n'.format(memSpecsPath))
        for file in os.listdir(memSpecsPath):
            if file.endswith(".xml"):
                print(file)


if __name__ == '__main__':
    with open(os.devnull, 'wb') as devnull:
        out = devnull
        errout = devnull
        # out = sys.stdout
        # errout = sys.stderr
        unittest.main()
