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 | |