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