from __future__ import print_function
## @file
# Utility functions and classes for BaseTools unit tests
#
#  Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
#
#  SPDX-License-Identifier: BSD-2-Clause-Patent
#

##
# Import Modules
#
import base64
import os
import os.path
import random
import shutil
import subprocess
import sys
import unittest
import codecs

TestsDir = os.path.realpath(os.path.split(sys.argv[0])[0])
BaseToolsDir = os.path.realpath(os.path.join(TestsDir, '..'))
CSourceDir = os.path.join(BaseToolsDir, 'Source', 'C')
PythonSourceDir = os.path.join(BaseToolsDir, 'Source', 'Python')
TestTempDir = os.path.join(TestsDir, 'TestTempDir')

if PythonSourceDir not in sys.path:
    #
    # Allow unit tests to import BaseTools python modules. This is very useful
    # for writing unit tests.
    #
    sys.path.append(PythonSourceDir)

def MakeTheTestSuite(localItems):
    tests = []
    for name, item in localItems.items():
        if isinstance(item, type):
            if issubclass(item, unittest.TestCase):
                tests.append(unittest.TestLoader().loadTestsFromTestCase(item))
            elif issubclass(item, unittest.TestSuite):
                tests.append(item())
    return lambda: unittest.TestSuite(tests)

def GetBaseToolsPaths():
    if sys.platform in ('win32', 'win64'):
        return [ os.path.join(BaseToolsDir, 'Bin', sys.platform.title()) ]
    else:
        uname = os.popen('uname -sm').read().strip()
        for char in (' ', '/'):
            uname = uname.replace(char, '-')
        return [
                os.path.join(BaseToolsDir, 'Bin', uname),
                os.path.join(BaseToolsDir, 'BinWrappers', uname),
                os.path.join(BaseToolsDir, 'BinWrappers', 'PosixLike')
            ]

BaseToolsBinPaths = GetBaseToolsPaths()

class BaseToolsTest(unittest.TestCase):

    def cleanOutDir(self, dir):
        for dirItem in os.listdir(dir):
            if dirItem in ('.', '..'): continue
            dirItem = os.path.join(dir, dirItem)
            self.RemoveFileOrDir(dirItem)

    def CleanUpTmpDir(self):
        if os.path.exists(self.testDir):
            self.cleanOutDir(self.testDir)

    def HandleTreeDeleteError(self, function, path, excinfo):
        os.chmod(path, stat.S_IWRITE)
        function(path)

    def RemoveDir(self, dir):
        shutil.rmtree(dir, False, self.HandleTreeDeleteError)

    def RemoveFileOrDir(self, path):
        if not os.path.exists(path):
            return
        elif os.path.isdir(path):
            self.RemoveDir(path)
        else:
            os.remove(path)

    def DisplayBinaryData(self, description, data):
        print(description, '(base64 encoded):')
        b64data = base64.b64encode(data)
        print(b64data)

    def DisplayFile(self, fileName):
        sys.stdout.write(self.ReadTmpFile(fileName))
        sys.stdout.flush()

    def FindToolBin(self, toolName):
        for binPath in BaseToolsBinPaths:
            bin = os.path.join(binPath, toolName)
            if os.path.exists(bin):
                break
        assert os.path.exists(bin)
        return bin

    def RunTool(self, *args, **kwd):
        if 'toolName' in kwd: toolName = kwd['toolName']
        else: toolName = None
        if 'logFile' in kwd: logFile = kwd['logFile']
        else: logFile = None

        if toolName is None: toolName = self.toolName
        bin = self.FindToolBin(toolName)
        if logFile is not None:
            logFile = open(os.path.join(self.testDir, logFile), 'w')
            popenOut = logFile
        else:
            popenOut = subprocess.PIPE

        args = [toolName] + list(args)

        Proc = subprocess.Popen(
            args, executable=bin,
            stdout=popenOut, stderr=subprocess.STDOUT
            )

        if logFile is None:
            Proc.stdout.read()

        return Proc.wait()

    def GetTmpFilePath(self, fileName):
        return os.path.join(self.testDir, fileName)

    def OpenTmpFile(self, fileName, mode = 'r'):
        return open(os.path.join(self.testDir, fileName), mode)

    def ReadTmpFile(self, fileName):
        f = open(self.GetTmpFilePath(fileName), 'r')
        data = f.read()
        f.close()
        return data

    def WriteTmpFile(self, fileName, data):
        if isinstance(data, bytes):
            with open(self.GetTmpFilePath(fileName), 'wb') as f:
                f.write(data)
        else:
            with codecs.open(self.GetTmpFilePath(fileName), 'w', encoding='utf-8') as f:
                f.write(data)

    def GenRandomFileData(self, fileName, minlen = None, maxlen = None):
        if maxlen is None: maxlen = minlen
        f = self.OpenTmpFile(fileName, 'w')
        f.write(self.GetRandomString(minlen, maxlen))
        f.close()

    def GetRandomString(self, minlen = None, maxlen = None):
        if minlen is None: minlen = 1024
        if maxlen is None: maxlen = minlen
        return ''.join(
            [chr(random.randint(0, 255))
             for x in range(random.randint(minlen, maxlen))
            ])

    def setUp(self):
        self.savedEnvPath = os.environ['PATH']
        self.savedSysPath = sys.path[:]

        for binPath in BaseToolsBinPaths:
            os.environ['PATH'] = \
                os.path.pathsep.join((os.environ['PATH'], binPath))

        self.testDir = TestTempDir
        if not os.path.exists(self.testDir):
            os.mkdir(self.testDir)
        else:
            self.cleanOutDir(self.testDir)

    def tearDown(self):
        self.RemoveFileOrDir(self.testDir)

        os.environ['PATH'] = self.savedEnvPath
        sys.path = self.savedSysPath

