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