1#!/usr/bin/python 2""" 3A very crude emulator of dejagnu, just enough to integrate the libbfi 4unittests into the pyobjc ones. 5""" 6import os 7import re 8import sys 9import signal 10from fnmatch import fnmatch 11import unittest 12from distutils.util import get_platform 13 14gDgCommands=re.compile(r''' 15 (?:{\s*(dg-do)\s*run\s*({[^}]*})?\s*}) 16 | 17 (?:{\s*(dg-output)\s*"([^"]*)"\s*}) 18 ''', 19 re.VERBOSE|re.MULTILINE) 20 21def signame(code): 22 for nm in dir(signal): 23 if nm.startswith('SIG') and nm[3] != '_' \ 24 and getattr(signal, nm) == code: 25 return nm 26 return code 27 28def exitCode2Description(code): 29 """ 30 Convert the exit code as returned by os.popen().close() to a string 31 """ 32 if os.WIFEXITED(code): 33 return 'exited with status %s'%(os.WEXITSTATUS(code),) 34 35 elif os.WIFSIGNALED(code): 36 sig = os.WTERMSIG(code) 37 return 'crashed with signal %s [%s]'%(signame(sig), sig) 38 39 else: 40 return 'exit code %s'%(code,) 41 42def platform_matches(matchstr): 43 # This is a hack 44 if sys.byteorder == 'little': 45 platform = 'i386-apple-darwin' 46 else: 47 platform = 'powerpc-apple-darwin' 48 49 return fnmatch(platform, matchstr) 50 51def parseDG(fdata): 52 result = [] 53 for item in gDgCommands.findall(fdata): 54 if item[0] == 'dg-do': 55 result.append(('run', item[1])) 56 elif item[2] == 'dg-output': 57 result.append(('expect', item[3].decode('string_escape'))) 58 return result 59 60 61class DgTestCase (unittest.TestCase): 62 def __init__(self, filename): 63 unittest.TestCase.__init__(self) 64 self.filename = filename 65 66 #archOption = "-arch ppc" 67 #archOption = "-arch ppc64" 68 #archOption = "-arch i386" 69 archOption = "-arch x86_64" 70 #archOption = "" 71 compileOptionsBase = "-g -DMACOSX -Iinclude -o /tmp/test.bin -lffi" 72 compileOptionsList = ( # HACK ALERT: Yes, there are better ways to do this, but this is easy and extremely flexible 73 "%s %s %s" % (compileOptionsBase, archOption, "-O0"), 74 "%s %s %s" % (compileOptionsBase, archOption, "-O1"), 75 "%s %s %s" % (compileOptionsBase, archOption, "-O2"), 76 "%s %s %s" % (compileOptionsBase, archOption, "-O3"), 77 "%s %s %s" % (compileOptionsBase, archOption, "-Os"), 78 "%s %s %s" % (compileOptionsBase, archOption, "-Oz"), # Note: Apple-Only, see gcc man page for details 79 ) 80 def runTest(self): 81 script = parseDG(open(self.filename).read()) 82 output = [] 83 84 for command, data in script: 85 if command == 'run': 86 action = 'run' 87 action_data = data 88 if command == 'expect': 89 output.append(data) 90 output = ''.join(output) 91 output = output.replace('\\', '') 92 93 d = action_data.split() 94 if d and d[1] == 'target': 95 for item in d[2:]: 96 if platform_matches(item): 97 break 98 99 else: 100 # Test shouldn't be run on this platform 101 return 102 103 # NOTE: We're ignoring the xfail data for now, none of the 104 # testcases are supposed to fail on darwin. 105 106 for compileOptions in self.compileOptionsList: 107 self.compileTestCase(compileOptions) 108 data = self.runTestCase() 109 110 if output != '': 111 self.assertEquals(data.rstrip(), output.rstrip()) 112 os.unlink('/tmp/test.bin') 113 114 115 def shortDescription(self): 116 fn = os.path.basename(self.filename)[:-2] 117 dn = os.path.basename(os.path.dirname(self.filename)) 118 return "dejagnu.%s.%s"%(dn, fn) 119 120 def compileTestCase(self, compileOptions): 121 # libdir = os.path.join('build', 'temp.%s-%d.%d'%(get_platform(), sys.version_info[0], sys.version_info[1]), 'libffi-src') 122 # libffiobjects = self.object_files(libdir) 123 124 commandline='cc %s %s 2>&1' % (compileOptions, self.filename) 125 fp = os.popen(commandline) 126 data = fp.read() 127 xit = fp.close() 128 if xit != None: 129 self.fail("Compile failed[%s]:\n%s"%(xit, data)) 130 131 132 def runTestCase(self): 133 os.environ['DYLD_BIND_AT_LAUNCH'] = '1' 134 fp = os.popen('/tmp/test.bin', 'r') 135 del os.environ['DYLD_BIND_AT_LAUNCH'] 136 data = fp.read() 137 xit = fp.close() 138 if xit != None: 139 self.fail("Running failed (%s)"%(exitCode2Description(xit),)) 140 return data 141 142 143 def object_files(self, basedir): 144 result = [] 145 for dirpath, dirnames, filenames in os.walk(basedir): 146 for fn in filenames: 147 if fn.endswith('.o'): 148 result.append(os.path.join(dirpath, fn)) 149 return result 150 151 152def testSuiteForDirectory(dirname): 153 tests = [] 154 for fn in os.listdir(dirname): 155 if not fn.endswith('.c'): continue 156 tst = DgTestCase(os.path.join(dirname, fn)) 157 if alltests and tst.shortDescription() not in alltests: 158 continue 159 tests.append(tst) 160 161 return unittest.TestSuite(tests) 162 163alltests = [] 164if __name__ == "__main__": 165 alltests = sys.argv[1:] 166 runner = unittest.TextTestRunner(verbosity=2) 167 runner.run(testSuiteForDirectory('tests/testsuite/libffi.call')) 168