diff options
Diffstat (limited to 'Lib/ctypes/test')
-rw-r--r-- | Lib/ctypes/test/test_byteswap.py | 70 | ||||
-rw-r--r-- | Lib/ctypes/test/test_cfuncs.py | 2 | ||||
-rw-r--r-- | Lib/ctypes/test/test_keeprefs.py | 5 | ||||
-rw-r--r-- | Lib/ctypes/test/test_loading.py | 80 | ||||
-rw-r--r-- | Lib/ctypes/test/test_pointers.py | 12 | ||||
-rw-r--r-- | Lib/ctypes/test/test_posix.py | 6 | ||||
-rw-r--r-- | Lib/ctypes/test/test_prototypes.py | 16 | ||||
-rw-r--r-- | Lib/ctypes/test/test_random_things.py | 10 | ||||
-rw-r--r-- | Lib/ctypes/test/test_sizes.py | 3 | ||||
-rw-r--r-- | Lib/ctypes/test/test_unaligned_structures.py | 45 |
10 files changed, 209 insertions, 40 deletions
diff --git a/Lib/ctypes/test/test_byteswap.py b/Lib/ctypes/test/test_byteswap.py index 1b31f90229..d0ada40229 100644 --- a/Lib/ctypes/test/test_byteswap.py +++ b/Lib/ctypes/test/test_byteswap.py @@ -149,7 +149,7 @@ class Test(unittest.TestCase): self.failUnless(c_char.__ctype_le__ is c_char) self.failUnless(c_char.__ctype_be__ is c_char) - def test_struct_fields(self): + def test_struct_fields_1(self): if sys.byteorder == "little": base = BigEndianStructure else: @@ -198,17 +198,20 @@ class Test(unittest.TestCase): pass self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)]) - # crashes on solaris with a core dump. - def X_test_struct_fields(self): + def test_struct_fields_2(self): + # standard packing in struct uses no alignment. + # So, we have to align using pad bytes. + # + # Unaligned accesses will crash Python (on those platforms that + # don't allow it, like sparc solaris). if sys.byteorder == "little": base = BigEndianStructure - fmt = ">bhid" + fmt = ">bxhid" else: base = LittleEndianStructure - fmt = "<bhid" + fmt = "<bxhid" class S(base): - _pack_ = 1 # struct with '<' or '>' uses standard alignment. _fields_ = [("b", c_byte), ("h", c_short), ("i", c_int), @@ -218,5 +221,60 @@ class Test(unittest.TestCase): s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14) self.failUnlessEqual(bin(s1), bin(s2)) + def test_unaligned_nonnative_struct_fields(self): + if sys.byteorder == "little": + base = BigEndianStructure + fmt = ">b h xi xd" + else: + base = LittleEndianStructure + fmt = "<b h xi xd" + + class S(base): + _pack_ = 1 + _fields_ = [("b", c_byte), + + ("h", c_short), + + ("_1", c_byte), + ("i", c_int), + + ("_2", c_byte), + ("d", c_double)] + + s1 = S() + s1.b = 0x12 + s1.h = 0x1234 + s1.i = 0x12345678 + s1.d = 3.14 + s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14) + self.failUnlessEqual(bin(s1), bin(s2)) + + def test_unaligned_native_struct_fields(self): + if sys.byteorder == "little": + fmt = "<b h xi xd" + else: + base = LittleEndianStructure + fmt = ">b h xi xd" + + class S(Structure): + _pack_ = 1 + _fields_ = [("b", c_byte), + + ("h", c_short), + + ("_1", c_byte), + ("i", c_int), + + ("_2", c_byte), + ("d", c_double)] + + s1 = S() + s1.b = 0x12 + s1.h = 0x1234 + s1.i = 0x12345678 + s1.d = 3.14 + s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14) + self.failUnlessEqual(bin(s1), bin(s2)) + if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_cfuncs.py b/Lib/ctypes/test/test_cfuncs.py index 7c2b28be7c..6e0798d1f4 100644 --- a/Lib/ctypes/test/test_cfuncs.py +++ b/Lib/ctypes/test/test_cfuncs.py @@ -179,7 +179,7 @@ else: def __getattr__(self, name): if name[:2] == '__' and name[-2:] == '__': raise AttributeError, name - func = self._FuncPtr("s_" + name, self) + func = self._FuncPtr(("s_" + name, self)) setattr(self, name, func) return func diff --git a/Lib/ctypes/test/test_keeprefs.py b/Lib/ctypes/test/test_keeprefs.py index 39e70e335c..7318f290e6 100644 --- a/Lib/ctypes/test/test_keeprefs.py +++ b/Lib/ctypes/test/test_keeprefs.py @@ -140,5 +140,10 @@ class PointerToStructure(unittest.TestCase): r.a[0].x = 42 r.a[0].y = 99 + # to avoid leaking when tests are run several times + # clean up the types left in the cache. + from ctypes import _pointer_type_cache + del _pointer_type_cache[POINT] + if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_loading.py b/Lib/ctypes/test/test_loading.py index 80564b8295..4558417518 100644 --- a/Lib/ctypes/test/test_loading.py +++ b/Lib/ctypes/test/test_loading.py @@ -2,40 +2,72 @@ from ctypes import * import sys, unittest import os, StringIO +libc_name = None +if os.name == "nt": + libc_name = "msvcrt" +elif os.name == "ce": + libc_name = "coredll" +elif sys.platform == "darwin": + libc_name = "libc.dylib" +elif sys.platform == "cygwin": + libc_name = "cygwin1.dll" +else: + for line in os.popen("ldd %s" % sys.executable): + if "libc.so" in line: + if sys.platform == "openbsd3": + libc_name = line.split()[4] + else: + libc_name = line.split()[2] +## print "libc_name is", libc_name + break + class LoaderTest(unittest.TestCase): unknowndll = "xxrandomnamexx" - def test_load(self): - if os.name == "nt": - name = "msvcrt" - elif os.name == "ce": - name = "coredll" - elif sys.platform == "darwin": - name = "libc.dylib" - elif sys.platform.startswith("freebsd"): - name = "libc.so" - elif sys.platform == "sunos5": - name = "libc.so" - else: - name = "libc.so.6" - cdll.load(name) - self.assertRaises(OSError, cdll.load, self.unknowndll) - - def test_load_version(self): - version = "6" - name = "c" - if sys.platform == "linux2": - cdll.load_version(name, version) + if libc_name is not None: + def test_load(self): + cdll.load(libc_name) + cdll.load(os.path.basename(libc_name)) + self.assertRaises(OSError, cdll.load, self.unknowndll) + + if libc_name is not None and os.path.basename(libc_name) == "libc.so.6": + def test_load_version(self): + cdll.load_version("c", "6") # linux uses version, libc 9 should not exist - self.assertRaises(OSError, cdll.load_version, name, "9") - self.assertRaises(OSError, cdll.load_version, self.unknowndll, "") + self.assertRaises(OSError, cdll.load_version, "c", "9") + self.assertRaises(OSError, cdll.load_version, self.unknowndll, "") - if os.name == "posix" and sys.platform != "sunos5": def test_find(self): name = "c" cdll.find(name) self.assertRaises(OSError, cdll.find, self.unknowndll) + if os.name in ("nt", "ce"): + def test_load_library(self): + if os.name == "nt": + windll.load_library("kernel32").GetModuleHandleW + windll.LoadLibrary("kernel32").GetModuleHandleW + WinDLL("kernel32").GetModuleHandleW + elif os.name == "ce": + windll.load_library("coredll").GetModuleHandleW + windll.LoadLibrary("coredll").GetModuleHandleW + WinDLL("coredll").GetModuleHandleW + + def test_load_ordinal_functions(self): + import _ctypes_test + dll = WinDLL(_ctypes_test.__file__) + # We load the same function both via ordinal and name + func_ord = dll[2] + func_name = dll.GetString + # addressof gets the address where the function pointer is stored + a_ord = addressof(func_ord) + a_name = addressof(func_name) + f_ord_addr = c_void_p.from_address(a_ord).value + f_name_addr = c_void_p.from_address(a_name).value + self.failUnlessEqual(hex(f_ord_addr), hex(f_name_addr)) + + self.failUnlessRaises(AttributeError, dll.__getitem__, 1234) + if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_pointers.py b/Lib/ctypes/test/test_pointers.py index 6172abb1f6..3a324a67c3 100644 --- a/Lib/ctypes/test/test_pointers.py +++ b/Lib/ctypes/test/test_pointers.py @@ -166,6 +166,18 @@ class PointersTestCase(unittest.TestCase): result = func( byref(argc), argv ) assert result == 'world', result + def test_bug_1467852(self): + # http://sourceforge.net/tracker/?func=detail&atid=532154&aid=1467852&group_id=71702 + x = c_int(5) + dummy = [] + for i in range(32000): + dummy.append(c_int(i)) + y = c_int(6) + p = pointer(x) + pp = pointer(p) + q = pointer(y) + pp[0] = q # <== + self.failUnlessEqual(p[0], 6) if __name__ == '__main__': unittest.main() diff --git a/Lib/ctypes/test/test_posix.py b/Lib/ctypes/test/test_posix.py index 2b4fdff17a..fe0a40a1ae 100644 --- a/Lib/ctypes/test/test_posix.py +++ b/Lib/ctypes/test/test_posix.py @@ -8,8 +8,10 @@ if os.name == "posix" and sys.platform == "linux2": class TestRTLD_GLOBAL(unittest.TestCase): def test_GL(self): - cdll.load('libGL.so', mode=RTLD_GLOBAL) - cdll.load('libGLU.so') + if os.path.exists('/usr/lib/libGL.so'): + cdll.load('libGL.so', mode=RTLD_GLOBAL) + if os.path.exists('/usr/lib/libGLU.so'): + cdll.load('libGLU.so') ##if os.name == "posix" and sys.platform != "darwin": diff --git a/Lib/ctypes/test/test_prototypes.py b/Lib/ctypes/test/test_prototypes.py index 2c3d75b522..47f5da1091 100644 --- a/Lib/ctypes/test/test_prototypes.py +++ b/Lib/ctypes/test/test_prototypes.py @@ -24,6 +24,19 @@ import unittest import _ctypes_test testdll = cdll.load(_ctypes_test.__file__) +# Return machine address `a` as a (possibly long) non-negative integer. +# Starting with Python 2.5, id(anything) is always non-negative, and +# the ctypes addressof() inherits that via PyLong_FromVoidPtr(). +def positive_address(a): + if a >= 0: + return a + # View the bits in `a` as unsigned instead. + import struct + num_bits = struct.calcsize("P") * 8 # num bits in native machine address + a += 1L << num_bits + assert a >= 0 + return a + def c_wbuffer(init): n = len(init) + 1 return (c_wchar * n)(*init) @@ -43,7 +56,8 @@ class CharPointersTestCase(unittest.TestCase): ci = c_int(0) func.argtypes = POINTER(c_int), - self.failUnlessEqual(addressof(ci), func(byref(ci))) + self.failUnlessEqual(positive_address(addressof(ci)), + positive_address(func(byref(ci)))) func.argtypes = c_char_p, self.assertRaises(ArgumentError, func, byref(ci)) diff --git a/Lib/ctypes/test/test_random_things.py b/Lib/ctypes/test/test_random_things.py index cd50ca8981..78a665bc5f 100644 --- a/Lib/ctypes/test/test_random_things.py +++ b/Lib/ctypes/test/test_random_things.py @@ -51,16 +51,14 @@ class CallbackTracbackTestCase(unittest.TestCase): def test_IntegerDivisionError(self): cb = CFUNCTYPE(c_int, c_int)(callback_func) out = self.capture_stderr(cb, 0) - self.failUnlessEqual(out.splitlines()[-1], - "ZeroDivisionError: " - "integer division or modulo by zero") + self.failUnlessEqual(out.splitlines()[-1][:19], + "ZeroDivisionError: ") def test_FloatDivisionError(self): cb = CFUNCTYPE(c_int, c_double)(callback_func) out = self.capture_stderr(cb, 0.0) - self.failUnlessEqual(out.splitlines()[-1], - "ZeroDivisionError: " - "float division") + self.failUnlessEqual(out.splitlines()[-1][:19], + "ZeroDivisionError: ") def test_TypeErrorDivisionError(self): cb = CFUNCTYPE(c_int, c_char_p)(callback_func) diff --git a/Lib/ctypes/test/test_sizes.py b/Lib/ctypes/test/test_sizes.py index 6fb9ca0377..208c00efcb 100644 --- a/Lib/ctypes/test/test_sizes.py +++ b/Lib/ctypes/test/test_sizes.py @@ -20,5 +20,8 @@ class SizesTestCase(unittest.TestCase): self.failUnlessEqual(8, sizeof(c_int64)) self.failUnlessEqual(8, sizeof(c_uint64)) + def test_size_t(self): + self.failUnlessEqual(sizeof(c_void_p), sizeof(c_size_t)) + if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_unaligned_structures.py b/Lib/ctypes/test/test_unaligned_structures.py new file mode 100644 index 0000000000..89343ba48e --- /dev/null +++ b/Lib/ctypes/test/test_unaligned_structures.py @@ -0,0 +1,45 @@ +import sys, unittest +from ctypes import * + +structures = [] +byteswapped_structures = [] + + +if sys.byteorder == "little": + SwappedStructure = BigEndianStructure +else: + SwappedStructure = LittleEndianStructure + +for typ in [c_short, c_int, c_long, c_longlong, + c_float, c_double, + c_ushort, c_uint, c_ulong, c_ulonglong]: + class X(Structure): + _pack_ = 1 + _fields_ = [("pad", c_byte), + ("value", typ)] + class Y(SwappedStructure): + _pack_ = 1 + _fields_ = [("pad", c_byte), + ("value", typ)] + structures.append(X) + byteswapped_structures.append(Y) + +class TestStructures(unittest.TestCase): + def test_native(self): + for typ in structures: +## print typ.value + self.failUnlessEqual(typ.value.offset, 1) + o = typ() + o.value = 4 + self.failUnlessEqual(o.value, 4) + + def test_swapped(self): + for typ in byteswapped_structures: +## print >> sys.stderr, typ.value + self.failUnlessEqual(typ.value.offset, 1) + o = typ() + o.value = 4 + self.failUnlessEqual(o.value, 4) + +if __name__ == '__main__': + unittest.main() |