import os import sys import subprocess import collections import tempfile USAGE_STR = 'python_d.exe testBugsOrPatches.py bugs|patches' WINDOWS_ENCODING = 'utf-16' AssertFail = collections.namedtuple('AssertFail', 'assertLocationStr codeStr') ASSERT_FAILS_LIST = [ AssertFail('after call to PyType_stgdict in CDataType_from_buffer', codeStr='_ctypes.Structure.from_buffer()'), AssertFail('after call to PyType_stgdict in CDataType_from_buffer_copy', codeStr='_ctypes.Structure.from_buffer_copy()'), AssertFail('after call to PyType_stgdict in PyCPointerType_set_type', codeStr='_ctypes._Pointer.set_type(1)'), AssertFail('after call to PyType_stgdict in PyCPointerType_from_param', codeStr='_ctypes._Pointer.from_param(1)'), AssertFail('after call to PyType_stgdict in PyCSimpleType_from_param', codeStr='_ctypes._SimpleCData.from_param(1)'), AssertFail('after call to PyType_stgdict in _validate_paramflags ' '(which is called by PyCFuncPtr_FromVtblIndex)', codeStr='_ctypes.CFuncPtr(1, "name", 1, "iid")'), AssertFail('in PyCField_set (which is the tp_descr_set of PyCField_Type)', codeStr='class MyCStruct(_ctypes.Structure):\n' ' _fields_ = (("field", ctypes.c_int),)\n' 'MyCStruct.field.__set__(1, 1)'), AssertFail('in PyCField_get (which is the tp_descr_get of PyCField_Type)', codeStr='class MyCStruct(_ctypes.Structure):\n' ' _fields_ = (("field", ctypes.c_int),)\n' 'MyCStruct.field.__get__(1, 1)') ] def testBugsOrPatches(isBugsTest, assertFailsList): for assertLocationStr, codeStr in assertFailsList: if isBugsTest: if not does_ctypesAssertionFail(codeStr): print(assertLocationStr) return False else: if does_ctypesAssertionFail(codeStr): print(assertLocationStr) return False return True def does_ctypesAssertionFail(codeStr): namedScriptFile = tempfile.NamedTemporaryFile(delete=False) with open(namedScriptFile.name, 'w') as scriptFile: scriptFile.write('import _ctypes\n' 'import ctypes\n' + codeStr) namedScriptFile.file.close() try: subprocess.check_output('{} {}"'.format(sys.executable, scriptFile.name), stderr=subprocess.STDOUT) except subprocess.CalledProcessError as err: if err.output.startswith(b'Traceback'): hasAssertionFailed = False elif err.output.decode(WINDOWS_ENCODING).startswith('Assertion ' 'failed:'): print(err.output.decode(WINDOWS_ENCODING), end='') hasAssertionFailed = True else: raise RuntimeError('called process output was neither an ' 'assertion failure nor a Traceback.') else: raise RuntimeError('check_output didnt raise a CalledProcessError ' 'exception.') os.remove(namedScriptFile.name) return hasAssertionFailed if __name__ == '__main__': try: _, bugsOrPatches = sys.argv except ValueError: print(USAGE_STR) exit() if bugsOrPatches == 'bugs': hasTestPassed = testBugsOrPatches(True, ASSERT_FAILS_LIST) elif bugsOrPatches == 'patches': hasTestPassed = testBugsOrPatches(False, ASSERT_FAILS_LIST) else: print(USAGE_STR) exit() print('######################') print(bugsOrPatches, end=' ') if hasTestPassed: print('test succeeded.') else: print('test failed.') print('######################')