1""" 2A very crude emulator of dejagnu, just enough to integrate the libbfi 3unittests into the pyobjc ones. 4""" 5import os 6import re 7import sys 8import signal 9from fnmatch import fnmatch 10import unittest 11from distutils.util import get_platform 12from distutils.sysconfig import get_config_var 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 def runTest(self): 67 script = parseDG(open(self.filename).read()) 68 output = [] 69 70 for command, data in script: 71 if command == 'run': 72 action = 'run' 73 action_data = data 74 if command == 'expect': 75 output.append(data) 76 output = ''.join(output) 77 output = output.replace('\\', '') 78 79 d = action_data.split() 80 if d and d[1] == 'target': 81 for item in d[2:]: 82 if platform_matches(item): 83 break 84 85 else: 86 # Test shouldn't be run on this platform 87 return 88 89 # NOTE: We're ignoring the xfail data for now, none of the 90 # testcases are supposed to fail on darwin. 91 92 self.compileTestCase() 93 data = self.runTestCase() 94 95 if output != '': 96 self.assertEquals(data.rstrip(), output.rstrip()) 97 os.unlink('/tmp/test.bin') 98 99 100 def shortDescription(self): 101 fn = os.path.basename(self.filename)[:-2] 102 dn = os.path.basename(os.path.dirname(self.filename)) 103 return "dejagnu.%s.%s"%(dn, fn) 104 105 def compileTestCase(self): 106 libdir = os.path.join('build', 'temp.%s-%d.%d'%(get_platform(), sys.version_info[0], sys.version_info[1]), 'libffi-src') 107 libffiobjects = self.object_files(libdir) 108 109 if self.filename.endswith('.m'): 110 extra_link = '-framework Foundation' 111 else: 112 extra_link = '' 113 114 commandline='MACOSX_DEPLPOYMENT_TARGET=%s cc %s -g -DMACOSX -Ilibffi-src/include -Ilibffi-src/powerpc -o /tmp/test.bin %s %s %s 2>&1'%( 115 get_config_var('MACOSX_DEPLOYMENT_TARGET'), 116 get_config_var('CFLAGS'), self.filename, ' '.join(libffiobjects), 117 extra_link) 118 119 fp = os.popen(commandline) 120 data = fp.read() 121 xit = fp.close() 122 if xit != None: 123 self.fail("Compile failed[%s]:\n%s"%(xit, data)) 124 125 126 def runTestCase(self): 127 os.environ['DYLD_BIND_AT_LAUNCH'] = '1' 128 fp = os.popen('/tmp/test.bin', 'r') 129 del os.environ['DYLD_BIND_AT_LAUNCH'] 130 data = fp.read() 131 xit = fp.close() 132 if xit != None: 133 self.fail("Running failed (%s)"%(exitCode2Description(xit),)) 134 return data 135 136 137 def object_files(self, basedir): 138 result = [] 139 for dirpath, dirnames, filenames in os.walk(basedir): 140 for fn in filenames: 141 if fn.endswith('.o'): 142 result.append(os.path.join(dirpath, fn)) 143 return result 144 145 146def testSuiteForDirectory(dirname): 147 tests = [] 148 for fn in os.listdir(dirname): 149 if not fn.endswith('.c') and not fn.endswith('.m'): continue 150 tst = DgTestCase(os.path.join(dirname, fn)) 151 if alltests and tst.shortDescription() not in alltests: 152 continue 153 tests.append(tst) 154 155 return unittest.TestSuite(tests) 156 157 158alltests = [] 159if __name__ == "__main__": 160 alltests = sys.argv[1:] 161 runner = unittest.TextTestRunner(verbosity=2) 162 runner.run(testSuiteForDirectory('libffi-src/tests/testsuite/libffi.call')) 163