1from __future__ import print_function 2## @file 3# Utility functions and classes for BaseTools unit tests 4# 5# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR> 6# 7# SPDX-License-Identifier: BSD-2-Clause-Patent 8# 9 10## 11# Import Modules 12# 13import base64 14import os 15import os.path 16import random 17import shutil 18import subprocess 19import sys 20import unittest 21import codecs 22 23TestsDir = os.path.realpath(os.path.split(sys.argv[0])[0]) 24BaseToolsDir = os.path.realpath(os.path.join(TestsDir, '..')) 25CSourceDir = os.path.join(BaseToolsDir, 'Source', 'C') 26PythonSourceDir = os.path.join(BaseToolsDir, 'Source', 'Python') 27TestTempDir = os.path.join(TestsDir, 'TestTempDir') 28 29if PythonSourceDir not in sys.path: 30 # 31 # Allow unit tests to import BaseTools python modules. This is very useful 32 # for writing unit tests. 33 # 34 sys.path.append(PythonSourceDir) 35 36def MakeTheTestSuite(localItems): 37 tests = [] 38 for name, item in localItems.items(): 39 if isinstance(item, type): 40 if issubclass(item, unittest.TestCase): 41 tests.append(unittest.TestLoader().loadTestsFromTestCase(item)) 42 elif issubclass(item, unittest.TestSuite): 43 tests.append(item()) 44 return lambda: unittest.TestSuite(tests) 45 46def GetBaseToolsPaths(): 47 if sys.platform in ('win32', 'win64'): 48 return [ os.path.join(BaseToolsDir, 'Bin', sys.platform.title()) ] 49 else: 50 uname = os.popen('uname -sm').read().strip() 51 for char in (' ', '/'): 52 uname = uname.replace(char, '-') 53 return [ 54 os.path.join(BaseToolsDir, 'Bin', uname), 55 os.path.join(BaseToolsDir, 'BinWrappers', uname), 56 os.path.join(BaseToolsDir, 'BinWrappers', 'PosixLike') 57 ] 58 59BaseToolsBinPaths = GetBaseToolsPaths() 60 61class BaseToolsTest(unittest.TestCase): 62 63 def cleanOutDir(self, dir): 64 for dirItem in os.listdir(dir): 65 if dirItem in ('.', '..'): continue 66 dirItem = os.path.join(dir, dirItem) 67 self.RemoveFileOrDir(dirItem) 68 69 def CleanUpTmpDir(self): 70 if os.path.exists(self.testDir): 71 self.cleanOutDir(self.testDir) 72 73 def HandleTreeDeleteError(self, function, path, excinfo): 74 os.chmod(path, stat.S_IWRITE) 75 function(path) 76 77 def RemoveDir(self, dir): 78 shutil.rmtree(dir, False, self.HandleTreeDeleteError) 79 80 def RemoveFileOrDir(self, path): 81 if not os.path.exists(path): 82 return 83 elif os.path.isdir(path): 84 self.RemoveDir(path) 85 else: 86 os.remove(path) 87 88 def DisplayBinaryData(self, description, data): 89 print(description, '(base64 encoded):') 90 b64data = base64.b64encode(data) 91 print(b64data) 92 93 def DisplayFile(self, fileName): 94 sys.stdout.write(self.ReadTmpFile(fileName)) 95 sys.stdout.flush() 96 97 def FindToolBin(self, toolName): 98 for binPath in BaseToolsBinPaths: 99 bin = os.path.join(binPath, toolName) 100 if os.path.exists(bin): 101 break 102 assert os.path.exists(bin) 103 return bin 104 105 def RunTool(self, *args, **kwd): 106 if 'toolName' in kwd: toolName = kwd['toolName'] 107 else: toolName = None 108 if 'logFile' in kwd: logFile = kwd['logFile'] 109 else: logFile = None 110 111 if toolName is None: toolName = self.toolName 112 bin = self.FindToolBin(toolName) 113 if logFile is not None: 114 logFile = open(os.path.join(self.testDir, logFile), 'w') 115 popenOut = logFile 116 else: 117 popenOut = subprocess.PIPE 118 119 args = [toolName] + list(args) 120 121 Proc = subprocess.Popen( 122 args, executable=bin, 123 stdout=popenOut, stderr=subprocess.STDOUT 124 ) 125 126 if logFile is None: 127 Proc.stdout.read() 128 129 return Proc.wait() 130 131 def GetTmpFilePath(self, fileName): 132 return os.path.join(self.testDir, fileName) 133 134 def OpenTmpFile(self, fileName, mode = 'r'): 135 return open(os.path.join(self.testDir, fileName), mode) 136 137 def ReadTmpFile(self, fileName): 138 f = open(self.GetTmpFilePath(fileName), 'r') 139 data = f.read() 140 f.close() 141 return data 142 143 def WriteTmpFile(self, fileName, data): 144 if isinstance(data, bytes): 145 with open(self.GetTmpFilePath(fileName), 'wb') as f: 146 f.write(data) 147 else: 148 with codecs.open(self.GetTmpFilePath(fileName), 'w', encoding='utf-8') as f: 149 f.write(data) 150 151 def GenRandomFileData(self, fileName, minlen = None, maxlen = None): 152 if maxlen is None: maxlen = minlen 153 f = self.OpenTmpFile(fileName, 'w') 154 f.write(self.GetRandomString(minlen, maxlen)) 155 f.close() 156 157 def GetRandomString(self, minlen = None, maxlen = None): 158 if minlen is None: minlen = 1024 159 if maxlen is None: maxlen = minlen 160 return ''.join( 161 [chr(random.randint(0, 255)) 162 for x in range(random.randint(minlen, maxlen)) 163 ]) 164 165 def setUp(self): 166 self.savedEnvPath = os.environ['PATH'] 167 self.savedSysPath = sys.path[:] 168 169 for binPath in BaseToolsBinPaths: 170 os.environ['PATH'] = \ 171 os.path.pathsep.join((os.environ['PATH'], binPath)) 172 173 self.testDir = TestTempDir 174 if not os.path.exists(self.testDir): 175 os.mkdir(self.testDir) 176 else: 177 self.cleanOutDir(self.testDir) 178 179 def tearDown(self): 180 self.RemoveFileOrDir(self.testDir) 181 182 os.environ['PATH'] = self.savedEnvPath 183 sys.path = self.savedSysPath 184 185