1#!/usr/bin/env python2 2 3import os 4import sys 5import time 6from glob import glob 7 8from TestCommon import * 9 10startTime = time.time() 11 12 13class RunError(Exception): 14 """Test Run Error. 15 16 Raised by Test.run() if the process exits with a non-zero status, 17 which indicates an error. 18 """ 19 20 21class Test(object): 22 23 24 ## Init ## 25 26 def __init__(self): 27 pass 28 29 30 ## Customization ## 31 32 def modelNames(self): 33 return self._modelNames 34 35 36 ## Testing ## 37 38 def main(self, args=sys.argv): 39 # The tests are listed explicitly rather than scanning for them (via glob) 40 # in order to perform them in a certain order (simplest to most complex) 41 self.readArgs(args) 42 results = [] 43 for self._modelName in self.modelNames(): 44 print '*** %s ***\n' % self._modelName 45 if not self._modelName.endswith('.mkmodel'): 46 self._modelName += '.mkmodel' 47 didFail = None 48 try: 49 if self.canRun(): 50 # support multiple config files for testing 51 configFilenames = glob(os.path.join( 52 self._modelName, 'Settings*.config')) 53 if configFilenames: 54 configFilenames = [os.path.basename(p) for p in configFilenames] 55 else: 56 configFilenames = ['Settings.config'] 57 for configFilename in configFilenames: 58 self.runCompletePath(configFilename) 59 else: 60 didFail = ' skipped' 61 except RunError: 62 didFail = '*** FAILED ***' 63 results.append((self._modelName, didFail)) 64 65 self.printInfo() 66 self.printResults(results) 67 68 # print duration for curiosity's sake 69 print 70 duration = time.time() - startTime 71 print '%.0f seconds' % (duration) 72 73 def readArgs(self, args): 74 if len(args) > 1: 75 self._modelNames = args[1:] 76 else: 77 self._modelNames = ''' 78 MKBasic MKNone MKString MKDateTime MKEnums MKDefaultMinMax 79 MKTypeValueChecking MKInheritance MKInheritanceAbstract 80 MKList MKObjRef MKObjRefReuse MKDelete MKDeleteMark 81 MKMultipleStores MKMultipleThreads 82 MKModelInh1 MKModelInh2 MKModelInh3 83 MKExcel 84 '''.split() 85 86 def canRun(self): 87 path = os.path.join(self._modelName, 'CanRun.py') 88 if os.path.exists(path): 89 file = open(path) 90 names = {} 91 exec file in names 92 assert 'CanRun' in names, 'expecting a CanRun() function' 93 return names['CanRun']() 94 else: 95 return True 96 97 def runCompletePath(self, configFilename='Settings.config'): 98 self._configFilename = configFilename 99 self.testDesign() 100 self.testEmpty() 101 self.insertSamples() 102 self.testSamples() 103 rmdir(workDir) 104 print '\n' 105 106 def testEmpty(self): 107 """Run all TestEmpty*.py files in the model, in alphabetical order.""" 108 names = glob(os.path.join(self._modelName, 'TestEmpty*.py')) 109 if names: 110 for name in sorted(names): 111 self.createDatabase() 112 self.testRun(os.path.basename(name), deleteData=False) 113 else: 114 self.createDatabase() 115 116 def testSamples(self): 117 self.testRun('TestSamples.py', deleteData=False) 118 119 def testRun(self, pyFile, deleteData): 120 if os.path.exists(os.path.join(self._modelName, pyFile)): 121 print '%s:' % pyFile 122 deleteData = 'yes' if deleteData else 'no' 123 self.run('python TestRun.py %s %s %s delete=%s' % ( 124 self._modelName, self._configFilename, pyFile, deleteData)) 125 else: 126 print 'NO %s TO TEST.' % pyFile 127 128 def testDesign(self): 129 self.run('python TestDesign.py %s %s' % ( 130 self._modelName, self._configFilename)) 131 132 def executeFile(self, filename): 133 filename = os.path.normpath(filename) 134 if os.path.exists(filename): 135 if '%s' in sqlCommand: 136 cmd = sqlCommand % filename 137 else: 138 cmd = '%s < %s' % (sqlCommand, filename) 139 self.run(cmd) 140 141 def createDatabase(self): 142 self.executeFile(workDir + '/GeneratedSQL/Create.sql') 143 144 def insertSamples(self): 145 self.createDatabase() 146 self.executeFile(workDir + '/GeneratedSQL/InsertSamples.sql') 147 148 def printInfo(self): 149 print 150 print 'SYSTEM INFO' 151 print '-----------' 152 print 'sys.version =', sys.version 153 print 'sys.platform =', sys.platform 154 print 'os.name =', os.name 155 if hasattr(sys, 'getwindowsversion'): 156 print 'sys.getwindowsversion() =', sys.getwindowsversion() 157 print 'os.getcwd() =', os.getcwd() 158 print 'dbName =', dbName 159 if sqlVersionCommand: 160 self.run(sqlVersionCommand) 161 162 # Since Test.py runs things via os.system() it won't actually have 163 # the DB API module loaded. But that's really desireable so its 164 # version number can be printed out, so import the store: 165 objStoreName = dbName + 'ObjectStore' 166 values = {} 167 exec 'import MiddleKit.Run.' + objStoreName in values 168 169 out = sys.stdout 170 out.write('modules with versions:\n') 171 modules = sorted((m for m in sys.modules.values() 172 if m is not None and m.__name__ != 'sys'), 173 key=lambda m: m.__name__) 174 for mod in modules: 175 ver = getattr(mod, 'version', None) 176 verInfo = getattr(mod, 'version_info', None) 177 if ver or verInfo: 178 out.write(' %s' % mod.__name__) 179 if verInfo: 180 out.write(', %s' % (verInfo,)) 181 if ver: 182 out.write(', %r' % ver) 183 out.write(', %s' % getattr(mod, '__file__', '(built-in)')) 184 out.write('\n') 185 186 def printResults(self, results): 187 """Summarize the results of each test.""" 188 print 189 print 'RESULTS' 190 print '-------' 191 for name, outcome in results: 192 if not outcome: 193 outcome = ' succeeded' 194 print outcome, name 195 196 197 ## Self utility ## 198 199 def run(self, cmd): 200 """Self utility method to run a system command. 201 202 If the command has a non-zero exit status, raises RunError. 203 Otherwise, returns 0. 204 205 Note that on Windows ME, os.system() always returns 0 even if the 206 program was a Python program that exited via sys.exit(1) or an 207 uncaught exception. On Windows XP Pro SP 1, this problem does not 208 occur. Windows ME has plenty of other problems as well; avoid it. 209 """ 210 print '<cmd>', cmd 211 sys.stdout.flush() 212 sys.stderr.flush() 213 returnCode = os.system(cmd) 214 sys.stdout.flush() 215 sys.stderr.flush() 216 217 if returnCode: 218 raise RunError(returnCode) 219 220 # print '>> RETURN CODE =', returnCode 221 return returnCode 222 223 224if __name__ == '__main__': 225 Test().main() 226