diff options
Diffstat (limited to 'c/test_c.py')
-rw-r--r-- | c/test_c.py | 4575 |
1 files changed, 0 insertions, 4575 deletions
diff --git a/c/test_c.py b/c/test_c.py deleted file mode 100644 index 654584d..0000000 --- a/c/test_c.py +++ /dev/null @@ -1,4575 +0,0 @@ -import py -import pytest - -def _setup_path(): - import os, sys - sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) -_setup_path() -from _cffi_backend import * -from _cffi_backend import _get_types, _get_common_types -try: - from _cffi_backend import _testfunc -except ImportError: - def _testfunc(num): - pytest.skip("_testunc() not available") -from _cffi_backend import __version__ - -# ____________________________________________________________ - -import sys -assert __version__ == "1.15.0", ("This test_c.py file is for testing a version" - " of cffi that differs from the one that we" - " get from 'import _cffi_backend'") -if sys.version_info < (3,): - type_or_class = "type" - mandatory_b_prefix = '' - mandatory_u_prefix = 'u' - bytechr = chr - bitem2bchr = lambda x: x - class U(object): - def __add__(self, other): - return eval('u'+repr(other).replace(r'\\u', r'\u') - .replace(r'\\U', r'\U')) - u = U() - str2bytes = str - strict_compare = False -else: - type_or_class = "class" - long = int - unicode = str - unichr = chr - mandatory_b_prefix = 'b' - mandatory_u_prefix = '' - bytechr = lambda n: bytes([n]) - bitem2bchr = bytechr - u = "" - str2bytes = lambda s: bytes(s, "ascii") - strict_compare = True - -def size_of_int(): - BInt = new_primitive_type("int") - return sizeof(BInt) - -def size_of_long(): - BLong = new_primitive_type("long") - return sizeof(BLong) - -def size_of_ptr(): - BInt = new_primitive_type("int") - BPtr = new_pointer_type(BInt) - return sizeof(BPtr) - - -def find_and_load_library(name, flags=RTLD_NOW): - import ctypes.util - if name is None: - path = None - else: - path = ctypes.util.find_library(name) - if path is None and name == 'c': - assert sys.platform == 'win32' - assert (sys.version_info >= (3,) or - '__pypy__' in sys.builtin_module_names) - py.test.skip("dlopen(None) cannot work on Windows " - "with PyPy or Python 3") - return load_library(path, flags) - -def test_load_library(): - x = find_and_load_library('c') - assert repr(x).startswith("<clibrary '") - x = find_and_load_library('c', RTLD_NOW | RTLD_GLOBAL) - assert repr(x).startswith("<clibrary '") - x = find_and_load_library('c', RTLD_LAZY) - assert repr(x).startswith("<clibrary '") - -def test_all_rtld_symbols(): - import sys - FFI_DEFAULT_ABI # these symbols must be defined - FFI_CDECL - RTLD_LAZY - RTLD_NOW - RTLD_GLOBAL - RTLD_LOCAL - if sys.platform.startswith("linux"): - RTLD_NODELETE - RTLD_NOLOAD - RTLD_DEEPBIND - -def test_new_primitive_type(): - py.test.raises(KeyError, new_primitive_type, "foo") - p = new_primitive_type("signed char") - assert repr(p) == "<ctype 'signed char'>" - -def check_dir(p, expected): - got = [name for name in dir(p) if not name.startswith('_')] - assert got == sorted(expected) - -def test_inspect_primitive_type(): - p = new_primitive_type("signed char") - assert p.kind == "primitive" - assert p.cname == "signed char" - check_dir(p, ['cname', 'kind']) - -def test_cast_to_signed_char(): - p = new_primitive_type("signed char") - x = cast(p, -65 + 17*256) - assert repr(x) == "<cdata 'signed char' -65>" - assert repr(type(x)) == "<%s '_cffi_backend._CDataBase'>" % type_or_class - assert int(x) == -65 - x = cast(p, -66 + (1<<199)*256) - assert repr(x) == "<cdata 'signed char' -66>" - assert int(x) == -66 - assert (x == cast(p, -66)) is True - assert (x != cast(p, -66)) is False - q = new_primitive_type("short") - assert (x == cast(q, -66)) is True - assert (x != cast(q, -66)) is False - -def test_sizeof_type(): - py.test.raises(TypeError, sizeof, 42.5) - p = new_primitive_type("short") - assert sizeof(p) == 2 - -def test_integer_types(): - for name in ['signed char', 'short', 'int', 'long', 'long long']: - p = new_primitive_type(name) - size = sizeof(p) - min = -(1 << (8*size-1)) - max = (1 << (8*size-1)) - 1 - assert int(cast(p, min)) == min - assert int(cast(p, max)) == max - assert int(cast(p, min - 1)) == max - assert int(cast(p, max + 1)) == min - py.test.raises(TypeError, cast, p, None) - assert long(cast(p, min - 1)) == max - assert int(cast(p, b'\x08')) == 8 - assert int(cast(p, u+'\x08')) == 8 - for name in ['char', 'short', 'int', 'long', 'long long']: - p = new_primitive_type('unsigned ' + name) - size = sizeof(p) - max = (1 << (8*size)) - 1 - assert int(cast(p, 0)) == 0 - assert int(cast(p, max)) == max - assert int(cast(p, -1)) == max - assert int(cast(p, max + 1)) == 0 - assert long(cast(p, -1)) == max - assert int(cast(p, b'\xFE')) == 254 - assert int(cast(p, u+'\xFE')) == 254 - -def test_no_float_on_int_types(): - p = new_primitive_type('long') - py.test.raises(TypeError, float, cast(p, 42)) - py.test.raises(TypeError, complex, cast(p, 42)) - -def test_float_types(): - INF = 1E200 * 1E200 - for name in ["float", "double"]: - p = new_primitive_type(name) - assert bool(cast(p, 0)) is False # since 1.7 - assert bool(cast(p, -0.0)) is False # since 1.7 - assert bool(cast(p, 1e-42)) is True - assert bool(cast(p, -1e-42)) is True - assert bool(cast(p, INF)) - assert bool(cast(p, -INF)) - assert bool(cast(p, float("nan"))) - assert int(cast(p, -150)) == -150 - assert int(cast(p, 61.91)) == 61 - assert long(cast(p, 61.91)) == 61 - assert type(int(cast(p, 61.91))) is int - assert type(int(cast(p, 1E22))) is long - assert type(long(cast(p, 61.91))) is long - assert type(long(cast(p, 1E22))) is long - py.test.raises(OverflowError, int, cast(p, INF)) - py.test.raises(OverflowError, int, cast(p, -INF)) - assert float(cast(p, 1.25)) == 1.25 - assert float(cast(p, INF)) == INF - assert float(cast(p, -INF)) == -INF - if name == "float": - assert float(cast(p, 1.1)) != 1.1 # rounding error - assert float(cast(p, 1E200)) == INF # limited range - - assert cast(p, -1.1) == cast(p, -1.1) - assert repr(float(cast(p, -0.0))) == '-0.0' - assert float(cast(p, b'\x09')) == 9.0 - assert float(cast(p, u+'\x09')) == 9.0 - assert float(cast(p, True)) == 1.0 - py.test.raises(TypeError, cast, p, None) - -def test_complex_types(): - INF = 1E200 * 1E200 - for name in ["float", "double"]: - p = new_primitive_type(name + " _Complex") - assert bool(cast(p, 0)) is False - assert bool(cast(p, INF)) - assert bool(cast(p, -INF)) - assert bool(cast(p, 0j)) is False - assert bool(cast(p, INF*1j)) - assert bool(cast(p, -INF*1j)) - # "can't convert complex to float", like CPython's "float(0j)" - py.test.raises(TypeError, int, cast(p, -150)) - py.test.raises(TypeError, long, cast(p, -150)) - py.test.raises(TypeError, float, cast(p, -150)) - assert complex(cast(p, 1.25)) == 1.25 - assert complex(cast(p, 1.25j)) == 1.25j - assert complex(cast(p, complex(0,INF))) == complex(0,INF) - assert complex(cast(p, -INF)) == -INF - if name == "float": - assert complex(cast(p, 1.1j)) != 1.1j # rounding error - assert complex(cast(p, 1E200+3j)) == INF+3j # limited range - assert complex(cast(p, complex(3,1E200))) == complex(3,INF) # limited range - - assert cast(p, -1.1j) == cast(p, -1.1j) - assert repr(complex(cast(p, -0.0)).real) == '-0.0' - #assert repr(complex(cast(p, -0j))) == '-0j' # http://bugs.python.org/issue29602 - assert complex(cast(p, b'\x09')) == 9.0 + 0j - assert complex(cast(p, u+'\x09')) == 9.0 + 0j - assert complex(cast(p, True)) == 1.0 + 0j - py.test.raises(TypeError, cast, p, None) - # - py.test.raises(TypeError, cast, new_primitive_type(name), 1+0j) - # - for basetype in ["char", "int", "uint64_t", "float", - "double", "long double"]: - baseobj = cast(new_primitive_type(basetype), 65) - py.test.raises(TypeError, complex, baseobj) - # - BArray = new_array_type(new_pointer_type(p), 10) - x = newp(BArray, None) - x[5] = 12.34 + 56.78j - assert type(x[5]) is complex - assert abs(x[5] - (12.34 + 56.78j)) < 1e-5 - assert (x[5] == 12.34 + 56.78j) == (name == "double") # rounding error - # - class Foo: - def __complex__(self): - return 2 + 3j - assert complex(Foo()) == 2 + 3j - assert complex(cast(p, Foo())) == 2 + 3j - py.test.raises(TypeError, cast, new_primitive_type("int"), 1+0j) - -def test_character_type(): - p = new_primitive_type("char") - assert bool(cast(p, 'A')) is True - assert bool(cast(p, '\x00')) is False # since 1.7 - assert cast(p, '\x00') == cast(p, -17*256) - assert int(cast(p, 'A')) == 65 - assert long(cast(p, 'A')) == 65 - assert type(int(cast(p, 'A'))) is int - assert type(long(cast(p, 'A'))) is long - assert str(cast(p, 'A')) == repr(cast(p, 'A')) - assert repr(cast(p, 'A')) == "<cdata 'char' %s'A'>" % mandatory_b_prefix - assert repr(cast(p, 255)) == r"<cdata 'char' %s'\xff'>" % mandatory_b_prefix - assert repr(cast(p, 0)) == r"<cdata 'char' %s'\x00'>" % mandatory_b_prefix - -def test_pointer_type(): - p = new_primitive_type("int") - assert repr(p) == "<ctype 'int'>" - p = new_pointer_type(p) - assert repr(p) == "<ctype 'int *'>" - p = new_pointer_type(p) - assert repr(p) == "<ctype 'int * *'>" - p = new_pointer_type(p) - assert repr(p) == "<ctype 'int * * *'>" - -def test_inspect_pointer_type(): - p1 = new_primitive_type("int") - p2 = new_pointer_type(p1) - assert p2.kind == "pointer" - assert p2.cname == "int *" - assert p2.item is p1 - check_dir(p2, ['cname', 'kind', 'item']) - p3 = new_pointer_type(p2) - assert p3.item is p2 - -def test_pointer_to_int(): - BInt = new_primitive_type("int") - py.test.raises(TypeError, newp, BInt) - py.test.raises(TypeError, newp, BInt, None) - BPtr = new_pointer_type(BInt) - p = newp(BPtr) - assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int() - p = newp(BPtr, None) - assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int() - p = newp(BPtr, 5000) - assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int() - q = cast(BPtr, p) - assert repr(q).startswith("<cdata 'int *' 0x") - assert p == q - assert hash(p) == hash(q) - e = py.test.raises(TypeError, newp, new_array_type(BPtr, None), None) - assert str(e.value) == ( - "expected new array length or list/tuple/str, not NoneType") - -def test_pointer_bool(): - BInt = new_primitive_type("int") - BPtr = new_pointer_type(BInt) - p = cast(BPtr, 0) - assert bool(p) is False - p = cast(BPtr, 42) - assert bool(p) is True - -def test_pointer_to_pointer(): - BInt = new_primitive_type("int") - BPtr = new_pointer_type(BInt) - BPtrPtr = new_pointer_type(BPtr) - p = newp(BPtrPtr, None) - assert repr(p) == "<cdata 'int * *' owning %d bytes>" % size_of_ptr() - -def test_reading_pointer_to_int(): - BInt = new_primitive_type("int") - BPtr = new_pointer_type(BInt) - p = newp(BPtr, None) - assert p[0] == 0 - p = newp(BPtr, 5000) - assert p[0] == 5000 - with pytest.raises(IndexError): - p[1] - with pytest.raises(IndexError): - p[-1] - -def test_reading_pointer_to_float(): - BFloat = new_primitive_type("float") - py.test.raises(TypeError, newp, BFloat, None) - BPtr = new_pointer_type(BFloat) - p = newp(BPtr, None) - assert p[0] == 0.0 and type(p[0]) is float - p = newp(BPtr, 1.25) - assert p[0] == 1.25 and type(p[0]) is float - p = newp(BPtr, 1.1) - assert p[0] != 1.1 and abs(p[0] - 1.1) < 1E-5 # rounding errors - -def test_cast_float_to_int(): - for type in ["int", "unsigned int", "long", "unsigned long", - "long long", "unsigned long long"]: - p = new_primitive_type(type) - assert int(cast(p, 4.2)) == 4 - py.test.raises(TypeError, newp, new_pointer_type(p), 4.2) - -def test_newp_integer_types(): - for name in ['signed char', 'short', 'int', 'long', 'long long']: - p = new_primitive_type(name) - pp = new_pointer_type(p) - size = sizeof(p) - min = -(1 << (8*size-1)) - max = (1 << (8*size-1)) - 1 - assert newp(pp, min)[0] == min - assert newp(pp, max)[0] == max - py.test.raises(OverflowError, newp, pp, min - 2 ** 32) - py.test.raises(OverflowError, newp, pp, min - 2 ** 64) - py.test.raises(OverflowError, newp, pp, max + 2 ** 32) - py.test.raises(OverflowError, newp, pp, max + 2 ** 64) - py.test.raises(OverflowError, newp, pp, min - 1) - py.test.raises(OverflowError, newp, pp, max + 1) - py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 32) - py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 64) - py.test.raises(OverflowError, newp, pp, max + 1) - py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 32) - py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 64) - py.test.raises(TypeError, newp, pp, 1.0) - for name in ['char', 'short', 'int', 'long', 'long long']: - p = new_primitive_type('unsigned ' + name) - pp = new_pointer_type(p) - size = sizeof(p) - max = (1 << (8*size)) - 1 - assert newp(pp, 0)[0] == 0 - assert newp(pp, max)[0] == max - py.test.raises(OverflowError, newp, pp, -1) - py.test.raises(OverflowError, newp, pp, max + 1) - -def test_reading_pointer_to_char(): - BChar = new_primitive_type("char") - py.test.raises(TypeError, newp, BChar, None) - BPtr = new_pointer_type(BChar) - p = newp(BPtr, None) - assert p[0] == b'\x00' - p = newp(BPtr, b'A') - assert p[0] == b'A' - py.test.raises(TypeError, newp, BPtr, 65) - py.test.raises(TypeError, newp, BPtr, b"foo") - py.test.raises(TypeError, newp, BPtr, u+"foo") - c = cast(BChar, b'A') - assert str(c) == repr(c) - assert int(c) == ord(b'A') - py.test.raises(TypeError, cast, BChar, b'foo') - py.test.raises(TypeError, cast, BChar, u+'foo') - e = py.test.raises(TypeError, newp, new_array_type(BPtr, None), 12.3) - assert str(e.value) == ( - "expected new array length or list/tuple/str, not float") - -def test_reading_pointer_to_pointer(): - BVoidP = new_pointer_type(new_void_type()) - BCharP = new_pointer_type(new_primitive_type("char")) - BInt = new_primitive_type("int") - BIntPtr = new_pointer_type(BInt) - BIntPtrPtr = new_pointer_type(BIntPtr) - q = newp(BIntPtr, 42) - assert q[0] == 42 - p = newp(BIntPtrPtr, None) - assert p[0] is not None - assert p[0] == cast(BVoidP, 0) - assert p[0] == cast(BCharP, 0) - assert p[0] != None - assert repr(p[0]) == "<cdata 'int *' NULL>" - p[0] = q - assert p[0] != cast(BVoidP, 0) - assert p[0] != cast(BCharP, 0) - assert p[0][0] == 42 - q[0] += 1 - assert p[0][0] == 43 - p = newp(BIntPtrPtr, q) - assert p[0][0] == 43 - -def test_load_standard_library(): - if sys.platform == "win32": - py.test.raises(OSError, find_and_load_library, None) - return - x = find_and_load_library(None) - BVoidP = new_pointer_type(new_void_type()) - assert x.load_function(BVoidP, 'strcpy') - py.test.raises(AttributeError, x.load_function, - BVoidP, 'xxx_this_function_does_not_exist') - # the next one is from 'libm', not 'libc', but we assume - # that it is already loaded too, so it should work - assert x.load_function(BVoidP, 'sqrt') - # - x.close_lib() - py.test.raises(ValueError, x.load_function, BVoidP, 'sqrt') - x.close_lib() - -def test_no_len_on_nonarray(): - p = new_primitive_type("int") - py.test.raises(TypeError, len, cast(p, 42)) - -def test_cmp_none(): - p = new_primitive_type("int") - x = cast(p, 42) - assert (x == None) is False - assert (x != None) is True - assert (x == ["hello"]) is False - assert (x != ["hello"]) is True - y = cast(p, 0) - assert (y == None) is False - -def test_invalid_indexing(): - p = new_primitive_type("int") - x = cast(p, 42) - with pytest.raises(TypeError): - x[0] - -def test_default_str(): - BChar = new_primitive_type("char") - x = cast(BChar, 42) - assert str(x) == repr(x) - BInt = new_primitive_type("int") - x = cast(BInt, 42) - assert str(x) == repr(x) - BArray = new_array_type(new_pointer_type(BInt), 10) - x = newp(BArray, None) - assert str(x) == repr(x) - -def test_default_unicode(): - BInt = new_primitive_type("int") - x = cast(BInt, 42) - assert unicode(x) == unicode(repr(x)) - BArray = new_array_type(new_pointer_type(BInt), 10) - x = newp(BArray, None) - assert unicode(x) == unicode(repr(x)) - -def test_cast_from_cdataint(): - BInt = new_primitive_type("int") - x = cast(BInt, 0) - y = cast(new_pointer_type(BInt), x) - assert bool(y) is False - # - x = cast(BInt, 42) - y = cast(BInt, x) - assert int(y) == 42 - y = cast(new_primitive_type("char"), x) - assert int(y) == 42 - y = cast(new_primitive_type("float"), x) - assert float(y) == 42.0 - # - z = cast(BInt, 42.5) - assert int(z) == 42 - z = cast(BInt, y) - assert int(z) == 42 - -def test_void_type(): - p = new_void_type() - assert p.kind == "void" - assert p.cname == "void" - check_dir(p, ['kind', 'cname']) - -def test_array_type(): - p = new_primitive_type("int") - assert repr(p) == "<ctype 'int'>" - # - py.test.raises(TypeError, new_array_type, new_pointer_type(p), "foo") - py.test.raises(ValueError, new_array_type, new_pointer_type(p), -42) - # - p1 = new_array_type(new_pointer_type(p), None) - assert repr(p1) == "<ctype 'int[]'>" - py.test.raises(ValueError, new_array_type, new_pointer_type(p1), 42) - # - p1 = new_array_type(new_pointer_type(p), 42) - p2 = new_array_type(new_pointer_type(p1), 25) - assert repr(p2) == "<ctype 'int[25][42]'>" - p2 = new_array_type(new_pointer_type(p1), None) - assert repr(p2) == "<ctype 'int[][42]'>" - # - py.test.raises(OverflowError, - new_array_type, new_pointer_type(p), sys.maxsize+1) - py.test.raises(OverflowError, - new_array_type, new_pointer_type(p), sys.maxsize // 3) - -def test_inspect_array_type(): - p = new_primitive_type("int") - p1 = new_array_type(new_pointer_type(p), None) - assert p1.kind == "array" - assert p1.cname == "int[]" - assert p1.item is p - assert p1.length is None - check_dir(p1, ['cname', 'kind', 'item', 'length']) - p1 = new_array_type(new_pointer_type(p), 42) - assert p1.kind == "array" - assert p1.cname == "int[42]" - assert p1.item is p - assert p1.length == 42 - check_dir(p1, ['cname', 'kind', 'item', 'length']) - -def test_array_instance(): - LENGTH = 1423 - p = new_primitive_type("int") - p1 = new_array_type(new_pointer_type(p), LENGTH) - a = newp(p1, None) - assert repr(a) == "<cdata 'int[%d]' owning %d bytes>" % ( - LENGTH, LENGTH * size_of_int()) - assert len(a) == LENGTH - for i in range(LENGTH): - assert a[i] == 0 - with pytest.raises(IndexError): - a[LENGTH] - with pytest.raises(IndexError): - a[-1] - for i in range(LENGTH): - a[i] = i * i + 1 - for i in range(LENGTH): - assert a[i] == i * i + 1 - with pytest.raises(IndexError) as e: - a[LENGTH+100] = 500 - assert ('(expected %d < %d)' % (LENGTH+100, LENGTH)) in str(e.value) - py.test.raises(TypeError, int, a) - -def test_array_of_unknown_length_instance(): - p = new_primitive_type("int") - p1 = new_array_type(new_pointer_type(p), None) - py.test.raises(TypeError, newp, p1, None) - py.test.raises(ValueError, newp, p1, -42) - a = newp(p1, 42) - assert len(a) == 42 - for i in range(42): - a[i] -= i - for i in range(42): - assert a[i] == -i - with pytest.raises(IndexError): - a[42] - with pytest.raises(IndexError): - a[-1] - with pytest.raises(IndexError): - a[42] = 123 - with pytest.raises(IndexError): - a[-1] = 456 - -def test_array_of_unknown_length_instance_with_initializer(): - p = new_primitive_type("int") - p1 = new_array_type(new_pointer_type(p), None) - a = newp(p1, list(range(42))) - assert len(a) == 42 - a = newp(p1, tuple(range(142))) - assert len(a) == 142 - -def test_array_initializer(): - p = new_primitive_type("int") - p1 = new_array_type(new_pointer_type(p), None) - a = newp(p1, list(range(100, 142))) - for i in range(42): - assert a[i] == 100 + i - # - p2 = new_array_type(new_pointer_type(p), 43) - a = newp(p2, tuple(range(100, 142))) - for i in range(42): - assert a[i] == 100 + i - assert a[42] == 0 # extra uninitialized item - -def test_array_add(): - p = new_primitive_type("int") - p1 = new_array_type(new_pointer_type(p), 5) # int[5] - p2 = new_array_type(new_pointer_type(p1), 3) # int[3][5] - a = newp(p2, [list(range(n, n+5)) for n in [100, 200, 300]]) - assert repr(a) == "<cdata 'int[3][5]' owning %d bytes>" % ( - 3*5*size_of_int(),) - assert repr(a + 0).startswith("<cdata 'int(*)[5]' 0x") - assert 0 + a == a + 0 != 1 + a == a + 1 - assert repr(a[0]).startswith("<cdata 'int[5]' 0x") - assert repr((a + 0)[0]).startswith("<cdata 'int[5]' 0x") - assert repr(a[0] + 0).startswith("<cdata 'int *' 0x") - assert type(a[0][0]) is int - assert type((a[0] + 0)[0]) is int - -def test_array_sub(): - BInt = new_primitive_type("int") - BArray = new_array_type(new_pointer_type(BInt), 5) # int[5] - a = newp(BArray, None) - p = a + 1 - assert p - a == 1 - assert p - (a+0) == 1 - assert a == (p - 1) - BPtr = new_pointer_type(new_primitive_type("short")) - q = newp(BPtr, None) - with pytest.raises(TypeError): - p - q - with pytest.raises(TypeError): - q - p - with pytest.raises(TypeError): - a - q - with pytest.raises(TypeError) as e: - q - a - assert str(e.value) == "cannot subtract cdata 'short *' and cdata 'int *'" - -def test_ptr_sub_unaligned(): - BInt = new_primitive_type("int") - BIntPtr = new_pointer_type(BInt) - a = cast(BIntPtr, 1240) - for bi in range(1430, 1438): - b = cast(BIntPtr, bi) - if ((bi - 1240) % size_of_int()) == 0: - assert b - a == (bi - 1240) // size_of_int() - assert a - b == (1240 - bi) // size_of_int() - else: - with pytest.raises(ValueError): - b - a - with pytest.raises(ValueError): - a - b - -def test_cast_primitive_from_cdata(): - p = new_primitive_type("int") - n = cast(p, cast(p, -42)) - assert int(n) == -42 - # - p = new_primitive_type("unsigned int") - n = cast(p, cast(p, 42)) - assert int(n) == 42 - # - p = new_primitive_type("long long") - n = cast(p, cast(p, -(1<<60))) - assert int(n) == -(1<<60) - # - p = new_primitive_type("unsigned long long") - n = cast(p, cast(p, 1<<63)) - assert int(n) == 1<<63 - # - p = new_primitive_type("float") - n = cast(p, cast(p, 42.5)) - assert float(n) == 42.5 - # - p = new_primitive_type("char") - n = cast(p, cast(p, "A")) - assert int(n) == ord("A") - -def test_new_primitive_from_cdata(): - p = new_primitive_type("int") - p1 = new_pointer_type(p) - n = newp(p1, cast(p, -42)) - assert n[0] == -42 - # - p = new_primitive_type("unsigned int") - p1 = new_pointer_type(p) - n = newp(p1, cast(p, 42)) - assert n[0] == 42 - # - p = new_primitive_type("float") - p1 = new_pointer_type(p) - n = newp(p1, cast(p, 42.5)) - assert n[0] == 42.5 - # - p = new_primitive_type("char") - p1 = new_pointer_type(p) - n = newp(p1, cast(p, "A")) - assert n[0] == b"A" - -def test_cast_between_pointers(): - BIntP = new_pointer_type(new_primitive_type("int")) - BIntA = new_array_type(BIntP, None) - a = newp(BIntA, [40, 41, 42, 43, 44]) - BShortP = new_pointer_type(new_primitive_type("short")) - b = cast(BShortP, a) - c = cast(BIntP, b) - assert c[3] == 43 - BLongLong = new_primitive_type("long long") - d = cast(BLongLong, c) - e = cast(BIntP, d) - assert e[3] == 43 - f = cast(BIntP, int(d)) - assert f[3] == 43 - # - b = cast(BShortP, 0) - assert not b - c = cast(BIntP, b) - assert not c - assert int(cast(BLongLong, c)) == 0 - -def test_alignof(): - BInt = new_primitive_type("int") - assert alignof(BInt) == sizeof(BInt) - BPtr = new_pointer_type(BInt) - assert alignof(BPtr) == sizeof(BPtr) - BArray = new_array_type(BPtr, None) - assert alignof(BArray) == alignof(BInt) - -def test_new_struct_type(): - BStruct = new_struct_type("foo") - assert repr(BStruct) == "<ctype 'foo'>" - BStruct = new_struct_type("struct foo") - assert repr(BStruct) == "<ctype 'struct foo'>" - BPtr = new_pointer_type(BStruct) - assert repr(BPtr) == "<ctype 'struct foo *'>" - py.test.raises(ValueError, sizeof, BStruct) - py.test.raises(ValueError, alignof, BStruct) - -def test_new_union_type(): - BUnion = new_union_type("union foo") - assert repr(BUnion) == "<ctype 'union foo'>" - BPtr = new_pointer_type(BUnion) - assert repr(BPtr) == "<ctype 'union foo *'>" - -def test_complete_struct(): - BLong = new_primitive_type("long") - BChar = new_primitive_type("char") - BShort = new_primitive_type("short") - BStruct = new_struct_type("struct foo") - assert BStruct.kind == "struct" - assert BStruct.cname == "struct foo" - assert BStruct.fields is None - check_dir(BStruct, ['cname', 'kind', 'fields']) - # - complete_struct_or_union(BStruct, [('a1', BLong, -1), - ('a2', BChar, -1), - ('a3', BShort, -1)]) - d = BStruct.fields - assert len(d) == 3 - assert d[0][0] == 'a1' - assert d[0][1].type is BLong - assert d[0][1].offset == 0 - assert d[0][1].bitshift == -1 - assert d[0][1].bitsize == -1 - assert d[1][0] == 'a2' - assert d[1][1].type is BChar - assert d[1][1].offset == sizeof(BLong) - assert d[1][1].bitshift == -1 - assert d[1][1].bitsize == -1 - assert d[2][0] == 'a3' - assert d[2][1].type is BShort - assert d[2][1].offset == sizeof(BLong) + sizeof(BShort) - assert d[2][1].bitshift == -1 - assert d[2][1].bitsize == -1 - assert sizeof(BStruct) == 2 * sizeof(BLong) - assert alignof(BStruct) == alignof(BLong) - -def test_complete_union(): - BLong = new_primitive_type("long") - BChar = new_primitive_type("char") - BUnion = new_union_type("union foo") - assert BUnion.kind == "union" - assert BUnion.cname == "union foo" - assert BUnion.fields is None - complete_struct_or_union(BUnion, [('a1', BLong, -1), - ('a2', BChar, -1)]) - d = BUnion.fields - assert len(d) == 2 - assert d[0][0] == 'a1' - assert d[0][1].type is BLong - assert d[0][1].offset == 0 - assert d[1][0] == 'a2' - assert d[1][1].type is BChar - assert d[1][1].offset == 0 - assert sizeof(BUnion) == sizeof(BLong) - assert alignof(BUnion) == alignof(BLong) - -def test_struct_instance(): - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - p = cast(BStructPtr, 42) - with pytest.raises(AttributeError) as e: - p.a1 # opaque - assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: " - "cannot read fields") - with pytest.raises(AttributeError) as e: - p.a1 = 10 # opaque - assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: " - "cannot write fields") - - complete_struct_or_union(BStruct, [('a1', BInt, -1), - ('a2', BInt, -1)]) - p = newp(BStructPtr, None) - s = p[0] - assert s.a1 == 0 - s.a2 = 123 - assert s.a1 == 0 - assert s.a2 == 123 - with pytest.raises(OverflowError): - s.a1 = sys.maxsize+1 - assert s.a1 == 0 - with pytest.raises(AttributeError) as e: - p.foobar - assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'" - with pytest.raises(AttributeError) as e: - p.foobar = 42 - assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'" - with pytest.raises(AttributeError) as e: - s.foobar - assert str(e.value) == "cdata 'struct foo' has no field 'foobar'" - with pytest.raises(AttributeError) as e: - s.foobar = 42 - assert str(e.value) == "cdata 'struct foo' has no field 'foobar'" - j = cast(BInt, 42) - with pytest.raises(AttributeError) as e: - j.foobar - assert str(e.value) == "cdata 'int' has no attribute 'foobar'" - with pytest.raises(AttributeError) as e: - j.foobar = 42 - assert str(e.value) == "cdata 'int' has no attribute 'foobar'" - j = cast(new_pointer_type(BInt), 42) - with pytest.raises(AttributeError) as e: - j.foobar - assert str(e.value) == "cdata 'int *' has no attribute 'foobar'" - with pytest.raises(AttributeError) as e: - j.foobar = 42 - assert str(e.value) == "cdata 'int *' has no attribute 'foobar'" - pp = newp(new_pointer_type(BStructPtr), p) - with pytest.raises(AttributeError) as e: - pp.a1 - assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'" - with pytest.raises(AttributeError) as e: - pp.a1 = 42 - assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'" - -def test_union_instance(): - BInt = new_primitive_type("int") - BUInt = new_primitive_type("unsigned int") - BUnion = new_union_type("union bar") - complete_struct_or_union(BUnion, [('a1', BInt, -1), ('a2', BUInt, -1)]) - p = newp(new_pointer_type(BUnion), [-42]) - bigval = -42 + (1 << (8*size_of_int())) - assert p.a1 == -42 - assert p.a2 == bigval - p = newp(new_pointer_type(BUnion), {'a2': bigval}) - assert p.a1 == -42 - assert p.a2 == bigval - py.test.raises(OverflowError, newp, new_pointer_type(BUnion), - {'a1': bigval}) - p = newp(new_pointer_type(BUnion), []) - assert p.a1 == p.a2 == 0 - -def test_struct_pointer(): - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BInt, -1), - ('a2', BInt, -1)]) - p = newp(BStructPtr, None) - assert p.a1 == 0 # read/write via the pointer (C equivalent: '->') - p.a2 = 123 - assert p.a1 == 0 - assert p.a2 == 123 - -def test_struct_init_list(): - BVoidP = new_pointer_type(new_void_type()) - BInt = new_primitive_type("int") - BIntPtr = new_pointer_type(BInt) - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BInt, -1), - ('a2', BInt, -1), - ('a3', BInt, -1), - ('p4', BIntPtr, -1)]) - s = newp(BStructPtr, [123, 456]) - assert s.a1 == 123 - assert s.a2 == 456 - assert s.a3 == 0 - assert s.p4 == cast(BVoidP, 0) - assert s.p4 != 0 - # - s = newp(BStructPtr, {'a2': 41122, 'a3': -123}) - assert s.a1 == 0 - assert s.a2 == 41122 - assert s.a3 == -123 - assert s.p4 == cast(BVoidP, 0) - # - py.test.raises(KeyError, newp, BStructPtr, {'foobar': 0}) - # - p = newp(BIntPtr, 14141) - s = newp(BStructPtr, [12, 34, 56, p]) - assert s.p4 == p - assert s.p4 - # - s = newp(BStructPtr, [12, 34, 56, cast(BVoidP, 0)]) - assert s.p4 == cast(BVoidP, 0) - assert not s.p4 - # - py.test.raises(TypeError, newp, BStructPtr, [12, 34, 56, None]) - -def test_array_in_struct(): - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - BArrayInt5 = new_array_type(new_pointer_type(BInt), 5) - complete_struct_or_union(BStruct, [('a1', BArrayInt5, -1)]) - s = newp(new_pointer_type(BStruct), [[20, 24, 27, 29, 30]]) - assert s.a1[2] == 27 - assert repr(s.a1).startswith("<cdata 'int[5]' 0x") - -def test_offsetof(): - def offsetof(BType, fieldname): - return typeoffsetof(BType, fieldname)[1] - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - py.test.raises(TypeError, offsetof, BInt, "abc") - py.test.raises(TypeError, offsetof, BStruct, "abc") - complete_struct_or_union(BStruct, [('abc', BInt, -1), ('def', BInt, -1)]) - assert offsetof(BStruct, 'abc') == 0 - assert offsetof(BStruct, 'def') == size_of_int() - py.test.raises(KeyError, offsetof, BStruct, "ghi") - assert offsetof(new_pointer_type(BStruct), "def") == size_of_int() - -def test_function_type(): - BInt = new_primitive_type("int") - BFunc = new_function_type((BInt, BInt), BInt, False) - assert repr(BFunc) == "<ctype 'int(*)(int, int)'>" - BFunc2 = new_function_type((), BFunc, False) - assert repr(BFunc2) == "<ctype 'int(*(*)())(int, int)'>" - -def test_inspect_function_type(): - BInt = new_primitive_type("int") - BFunc = new_function_type((BInt, BInt), BInt, False) - assert BFunc.kind == "function" - assert BFunc.cname == "int(*)(int, int)" - assert BFunc.args == (BInt, BInt) - assert BFunc.result is BInt - assert BFunc.ellipsis is False - assert BFunc.abi == FFI_DEFAULT_ABI - -def test_function_type_taking_struct(): - BChar = new_primitive_type("char") - BShort = new_primitive_type("short") - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('a1', BChar, -1), - ('a2', BShort, -1)]) - BFunc = new_function_type((BStruct,), BShort, False) - assert repr(BFunc) == "<ctype 'short(*)(struct foo)'>" - -def test_function_void_result(): - BVoid = new_void_type() - BInt = new_primitive_type("int") - BFunc = new_function_type((BInt, BInt), BVoid, False) - assert repr(BFunc) == "<ctype 'void(*)(int, int)'>" - -def test_function_void_arg(): - BVoid = new_void_type() - BInt = new_primitive_type("int") - py.test.raises(TypeError, new_function_type, (BVoid,), BInt, False) - -def test_call_function_0(): - BSignedChar = new_primitive_type("signed char") - BFunc0 = new_function_type((BSignedChar, BSignedChar), BSignedChar, False) - f = cast(BFunc0, _testfunc(0)) - assert f(40, 2) == 42 - assert f(-100, -100) == -200 + 256 - py.test.raises(OverflowError, f, 128, 0) - py.test.raises(OverflowError, f, 0, 128) - -def test_call_function_0_pretend_bool_result(): - BSignedChar = new_primitive_type("signed char") - BBool = new_primitive_type("_Bool") - BFunc0 = new_function_type((BSignedChar, BSignedChar), BBool, False) - f = cast(BFunc0, _testfunc(0)) - assert f(40, -39) is True - assert f(40, -40) is False - py.test.raises(ValueError, f, 40, 2) - -def test_call_function_1(): - BInt = new_primitive_type("int") - BLong = new_primitive_type("long") - BFunc1 = new_function_type((BInt, BLong), BLong, False) - f = cast(BFunc1, _testfunc(1)) - assert f(40, 2) == 42 - assert f(-100, -100) == -200 - int_max = (1 << (8*size_of_int()-1)) - 1 - long_max = (1 << (8*size_of_long()-1)) - 1 - if int_max == long_max: - assert f(int_max, 1) == - int_max - 1 - else: - assert f(int_max, 1) == int_max + 1 - -def test_call_function_2(): - BLongLong = new_primitive_type("long long") - BFunc2 = new_function_type((BLongLong, BLongLong), BLongLong, False) - f = cast(BFunc2, _testfunc(2)) - longlong_max = (1 << (8*sizeof(BLongLong)-1)) - 1 - assert f(longlong_max - 42, 42) == longlong_max - assert f(43, longlong_max - 42) == - longlong_max - 1 - -def test_call_function_3(): - BFloat = new_primitive_type("float") - BDouble = new_primitive_type("double") - BFunc3 = new_function_type((BFloat, BDouble), BDouble, False) - f = cast(BFunc3, _testfunc(3)) - assert f(1.25, 5.1) == 1.25 + 5.1 # exact - res = f(1.3, 5.1) - assert res != 6.4 and abs(res - 6.4) < 1E-5 # inexact - -def test_call_function_4(): - BFloat = new_primitive_type("float") - BDouble = new_primitive_type("double") - BFunc4 = new_function_type((BFloat, BDouble), BFloat, False) - f = cast(BFunc4, _testfunc(4)) - res = f(1.25, 5.1) - assert res != 6.35 and abs(res - 6.35) < 1E-5 # inexact - -def test_call_function_5(): - BVoid = new_void_type() - BFunc5 = new_function_type((), BVoid, False) - f = cast(BFunc5, _testfunc(5)) - f() # did not crash - -def test_call_function_6(): - BInt = new_primitive_type("int") - BIntPtr = new_pointer_type(BInt) - BFunc6 = new_function_type((BIntPtr,), BIntPtr, False) - f = cast(BFunc6, _testfunc(6)) - x = newp(BIntPtr, 42) - res = f(x) - assert typeof(res) is BIntPtr - assert res[0] == 42 - 1000 - # - BIntArray = new_array_type(BIntPtr, None) - BFunc6bis = new_function_type((BIntArray,), BIntPtr, False) - f = cast(BFunc6bis, _testfunc(6)) - # - res = f([142]) - assert typeof(res) is BIntPtr - assert res[0] == 142 - 1000 - # - res = f((143,)) - assert typeof(res) is BIntPtr - assert res[0] == 143 - 1000 - # - x = newp(BIntArray, [242]) - res = f(x) - assert typeof(res) is BIntPtr - assert res[0] == 242 - 1000 - # - py.test.raises(TypeError, f, 123456) - py.test.raises(TypeError, f, "foo") - py.test.raises(TypeError, f, u+"bar") - -def test_call_function_7(): - BChar = new_primitive_type("char") - BShort = new_primitive_type("short") - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BChar, -1), - ('a2', BShort, -1)]) - BFunc7 = new_function_type((BStruct,), BShort, False) - f = cast(BFunc7, _testfunc(7)) - res = f({'a1': b'A', 'a2': -4042}) - assert res == -4042 + ord(b'A') - # - x = newp(BStructPtr, {'a1': b'A', 'a2': -4042}) - res = f(x[0]) - assert res == -4042 + ord(b'A') - -def test_call_function_20(): - BChar = new_primitive_type("char") - BShort = new_primitive_type("short") - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BChar, -1), - ('a2', BShort, -1)]) - BFunc20 = new_function_type((BStructPtr,), BShort, False) - f = cast(BFunc20, _testfunc(20)) - x = newp(BStructPtr, {'a1': b'A', 'a2': -4042}) - # can't pass a 'struct foo' - py.test.raises(TypeError, f, x[0]) - -def test_call_function_21(): - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('a', BInt, -1), - ('b', BInt, -1), - ('c', BInt, -1), - ('d', BInt, -1), - ('e', BInt, -1), - ('f', BInt, -1), - ('g', BInt, -1), - ('h', BInt, -1), - ('i', BInt, -1), - ('j', BInt, -1)]) - BFunc21 = new_function_type((BStruct,), BInt, False) - f = cast(BFunc21, _testfunc(21)) - res = f(list(range(13, 3, -1))) - lst = [(n << i) for (i, n) in enumerate(range(13, 3, -1))] - assert res == sum(lst) - -def test_call_function_22(): - BInt = new_primitive_type("int") - BArray10 = new_array_type(new_pointer_type(BInt), 10) - BStruct = new_struct_type("struct foo") - BStructP = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a', BArray10, -1)]) - BFunc22 = new_function_type((BStruct, BStruct), BStruct, False) - f = cast(BFunc22, _testfunc(22)) - p1 = newp(BStructP, {'a': list(range(100, 110))}) - p2 = newp(BStructP, {'a': list(range(1000, 1100, 10))}) - res = f(p1[0], p2[0]) - for i in range(10): - assert res.a[i] == p1.a[i] - p2.a[i] - -def test_call_function_23(): - BVoid = new_void_type() # declaring the function as int(void*) - BVoidP = new_pointer_type(BVoid) - BInt = new_primitive_type("int") - BFunc23 = new_function_type((BVoidP,), BInt, False) - f = cast(BFunc23, _testfunc(23)) - res = f(b"foo") - assert res == 1000 * ord(b'f') - res = f(cast(BVoidP, 0)) # NULL - assert res == -42 - py.test.raises(TypeError, f, None) - py.test.raises(TypeError, f, 0) - py.test.raises(TypeError, f, 0.0) - -def test_call_function_23_bis(): - # declaring the function as int(unsigned char*) - BUChar = new_primitive_type("unsigned char") - BUCharP = new_pointer_type(BUChar) - BInt = new_primitive_type("int") - BFunc23 = new_function_type((BUCharP,), BInt, False) - f = cast(BFunc23, _testfunc(23)) - res = f(b"foo") - assert res == 1000 * ord(b'f') - -def test_call_function_23_bool_array(): - # declaring the function as int(_Bool*) - BBool = new_primitive_type("_Bool") - BBoolP = new_pointer_type(BBool) - BInt = new_primitive_type("int") - BFunc23 = new_function_type((BBoolP,), BInt, False) - f = cast(BFunc23, _testfunc(23)) - res = f(b"\x01\x01") - assert res == 1000 - py.test.raises(ValueError, f, b"\x02\x02") - -def test_cannot_pass_struct_with_array_of_length_0(): - BInt = new_primitive_type("int") - BArray0 = new_array_type(new_pointer_type(BInt), 0) - BStruct = new_struct_type("struct foo") - BStructP = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a', BArray0)]) - BFunc = new_function_type((BStruct,), BInt, False) - py.test.raises(NotImplementedError, cast(BFunc, 123), cast(BStructP, 123)) - BFunc2 = new_function_type((BInt,), BStruct, False) - py.test.raises(NotImplementedError, cast(BFunc2, 123), 123) - -def test_call_function_9(): - BInt = new_primitive_type("int") - BFunc9 = new_function_type((BInt,), BInt, True) # vararg - f = cast(BFunc9, _testfunc(9)) - assert f(0) == 0 - assert f(1, cast(BInt, 42)) == 42 - assert f(2, cast(BInt, 40), cast(BInt, 2)) == 42 - py.test.raises(TypeError, f, 1, 42) - py.test.raises(TypeError, f, 2, None) - # promotion of chars and shorts to ints - BSChar = new_primitive_type("signed char") - BUChar = new_primitive_type("unsigned char") - BSShort = new_primitive_type("short") - assert f(3, cast(BSChar, -3), cast(BUChar, 200), cast(BSShort, -5)) == 192 - -def test_call_function_24(): - BFloat = new_primitive_type("float") - BFloatComplex = new_primitive_type("float _Complex") - BFunc3 = new_function_type((BFloat, BFloat), BFloatComplex, False) - if 0: # libffi returning nonsense silently, so logic disabled for now - f = cast(BFunc3, _testfunc(24)) - result = f(1.25, 5.1) - assert type(result) == complex - assert result.real == 1.25 # exact - assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-5) # inexact - else: - f = cast(BFunc3, _testfunc(9)) - py.test.raises(NotImplementedError, f, 12.3, 34.5) - -def test_call_function_25(): - BDouble = new_primitive_type("double") - BDoubleComplex = new_primitive_type("double _Complex") - BFunc3 = new_function_type((BDouble, BDouble), BDoubleComplex, False) - if 0: # libffi returning nonsense silently, so logic disabled for now - f = cast(BFunc3, _testfunc(25)) - result = f(1.25, 5.1) - assert type(result) == complex - assert result.real == 1.25 # exact - assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-10) # inexact - else: - f = cast(BFunc3, _testfunc(9)) - py.test.raises(NotImplementedError, f, 12.3, 34.5) - -def test_cannot_call_with_a_autocompleted_struct(): - BSChar = new_primitive_type("signed char") - BDouble = new_primitive_type("double") - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('c', BDouble, -1, 8), - ('a', BSChar, -1, 2), - ('b', BSChar, -1, 0)]) - BFunc = new_function_type((BStruct,), BDouble) # internally not callable - dummy_func = cast(BFunc, 42) - e = py.test.raises(NotImplementedError, dummy_func, "?") - msg = ("ctype 'struct foo' not supported as argument. It is a struct " - 'declared with "...;", but the C calling convention may depend ' - "on the missing fields; or, it contains anonymous struct/unions. " - "Such structs are only supported as argument if the function is " - "'API mode' and non-variadic (i.e. declared inside ffibuilder." - "cdef()+ffibuilder.set_source() and not taking a final '...' " - "argument)") - assert str(e.value) == msg - -def test_new_charp(): - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - x = newp(BCharA, 42) - assert len(x) == 42 - x = newp(BCharA, b"foobar") - assert len(x) == 7 - -def test_load_and_call_function(): - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BLong = new_primitive_type("long") - BFunc = new_function_type((BCharP,), BLong, False) - ll = find_and_load_library('c') - strlen = ll.load_function(BFunc, "strlen") - input = newp(new_array_type(BCharP, None), b"foobar") - assert strlen(input) == 6 - # - assert strlen(b"foobarbaz") == 9 - # - BVoidP = new_pointer_type(new_void_type()) - strlenaddr = ll.load_function(BVoidP, "strlen") - assert strlenaddr == cast(BVoidP, strlen) - -def test_read_variable(): - ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard - ## https://bugs.pypy.org/issue1643 - if not sys.platform.startswith("linux"): - py.test.skip("untested") - BVoidP = new_pointer_type(new_void_type()) - ll = find_and_load_library('c') - stderr = ll.read_variable(BVoidP, "stderr") - assert stderr == cast(BVoidP, _testfunc(8)) - # - ll.close_lib() - py.test.raises(ValueError, ll.read_variable, BVoidP, "stderr") - -def test_read_variable_as_unknown_length_array(): - ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard - ## https://bugs.pypy.org/issue1643 - if not sys.platform.startswith("linux"): - py.test.skip("untested") - BCharP = new_pointer_type(new_primitive_type("char")) - BArray = new_array_type(BCharP, None) - ll = find_and_load_library('c') - stderr = ll.read_variable(BArray, "stderr") - assert repr(stderr).startswith("<cdata 'char *' 0x") - # ^^ and not 'char[]', which is basically not allowed and would crash - -def test_write_variable(): - ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard - ## https://bugs.pypy.org/issue1643 - if not sys.platform.startswith("linux"): - py.test.skip("untested") - BVoidP = new_pointer_type(new_void_type()) - ll = find_and_load_library('c') - stderr = ll.read_variable(BVoidP, "stderr") - ll.write_variable(BVoidP, "stderr", cast(BVoidP, 0)) - assert ll.read_variable(BVoidP, "stderr") is not None - assert not ll.read_variable(BVoidP, "stderr") - ll.write_variable(BVoidP, "stderr", stderr) - assert ll.read_variable(BVoidP, "stderr") == stderr - # - ll.close_lib() - py.test.raises(ValueError, ll.write_variable, BVoidP, "stderr", stderr) - -def test_callback(): - BInt = new_primitive_type("int") - def make_callback(): - def cb(n): - return n + 1 - BFunc = new_function_type((BInt,), BInt, False) - return callback(BFunc, cb, 42) # 'cb' and 'BFunc' go out of scope - f = make_callback() - assert f(-142) == -141 - assert repr(f).startswith( - "<cdata 'int(*)(int)' calling <function ") - assert "cb at 0x" in repr(f) - e = py.test.raises(TypeError, f) - assert str(e.value) == "'int(*)(int)' expects 1 arguments, got 0" - -def test_callback_exception(): - try: - import cStringIO - except ImportError: - import io as cStringIO # Python 3 - import linecache - def matches(istr, ipattern, ipattern38): - if sys.version_info >= (3, 8): - ipattern = ipattern38 - str, pattern = istr, ipattern - while '$' in pattern: - i = pattern.index('$') - assert str[:i] == pattern[:i] - j = str.find(pattern[i+1], i) - assert i + 1 <= j <= str.find('\n', i) - str = str[j:] - pattern = pattern[i+1:] - assert str == pattern - return True - def check_value(x): - if x == 10000: - raise ValueError(42) - def Zcb1(x): - check_value(x) - return x * 3 - BShort = new_primitive_type("short") - BFunc = new_function_type((BShort,), BShort, False) - f = callback(BFunc, Zcb1, -42) - # - seen = [] - oops_result = None - def oops(*args): - seen.append(args) - return oops_result - ff = callback(BFunc, Zcb1, -42, oops) - # - orig_stderr = sys.stderr - orig_getline = linecache.getline - try: - linecache.getline = lambda *args: 'LINE' # hack: speed up PyPy tests - sys.stderr = cStringIO.StringIO() - if hasattr(sys, '__unraisablehook__'): # work around pytest - sys.unraisablehook = sys.__unraisablehook__ # on recent CPythons - assert f(100) == 300 - assert sys.stderr.getvalue() == '' - assert f(10000) == -42 - assert matches(sys.stderr.getvalue(), """\ -From cffi callback <function$Zcb1 at 0x$>: -Traceback (most recent call last): - File "$", line $, in Zcb1 - $ - File "$", line $, in check_value - $ -ValueError: 42 -""", """\ -Exception ignored from cffi callback <function$Zcb1 at 0x$>: -Traceback (most recent call last): - File "$", line $, in Zcb1 - $ - File "$", line $, in check_value - $ -ValueError: 42 -""") - sys.stderr = cStringIO.StringIO() - bigvalue = 20000 - assert f(bigvalue) == -42 - assert matches(sys.stderr.getvalue(), """\ -From cffi callback <function$Zcb1 at 0x$>: -Trying to convert the result back to C: -OverflowError: integer 60000 does not fit 'short' -""", """\ -Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C: -Traceback (most recent call last): - File "$", line $, in test_callback_exception - $ -OverflowError: integer 60000 does not fit 'short' -""") - sys.stderr = cStringIO.StringIO() - bigvalue = 20000 - assert len(seen) == 0 - assert ff(bigvalue) == -42 - assert sys.stderr.getvalue() == "" - assert len(seen) == 1 - exc, val, tb = seen[0] - assert exc is OverflowError - assert str(val) == "integer 60000 does not fit 'short'" - # - sys.stderr = cStringIO.StringIO() - bigvalue = 20000 - del seen[:] - oops_result = 81 - assert ff(bigvalue) == 81 - oops_result = None - assert sys.stderr.getvalue() == "" - assert len(seen) == 1 - exc, val, tb = seen[0] - assert exc is OverflowError - assert str(val) == "integer 60000 does not fit 'short'" - # - sys.stderr = cStringIO.StringIO() - bigvalue = 20000 - del seen[:] - oops_result = "xy" # not None and not an int! - assert ff(bigvalue) == -42 - oops_result = None - assert matches(sys.stderr.getvalue(), """\ -From cffi callback <function$Zcb1 at 0x$>: -Trying to convert the result back to C: -OverflowError: integer 60000 does not fit 'short' - -During the call to 'onerror', another exception occurred: - -TypeError: $integer$ -""", """\ -Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C: -Traceback (most recent call last): - File "$", line $, in test_callback_exception - $ -OverflowError: integer 60000 does not fit 'short' -Exception ignored during handling of the above exception by 'onerror': -Traceback (most recent call last): - File "$", line $, in test_callback_exception - $ -TypeError: $integer$ -""") - # - sys.stderr = cStringIO.StringIO() - seen = "not a list" # this makes the oops() function crash - assert ff(bigvalue) == -42 - # the $ after the AttributeError message are for the suggestions that - # will be added in Python 3.10 - assert matches(sys.stderr.getvalue(), """\ -From cffi callback <function$Zcb1 at 0x$>: -Trying to convert the result back to C: -OverflowError: integer 60000 does not fit 'short' - -During the call to 'onerror', another exception occurred: - -Traceback (most recent call last): - File "$", line $, in oops - $ -AttributeError: 'str' object has no attribute 'append$ -""", """\ -Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C: -Traceback (most recent call last): - File "$", line $, in test_callback_exception - $ -OverflowError: integer 60000 does not fit 'short' -Exception ignored during handling of the above exception by 'onerror': -Traceback (most recent call last): - File "$", line $, in oops - $ -AttributeError: 'str' object has no attribute 'append$ -""") - finally: - sys.stderr = orig_stderr - linecache.getline = orig_getline - -def test_callback_return_type(): - for rettype in ["signed char", "short", "int", "long", "long long", - "unsigned char", "unsigned short", "unsigned int", - "unsigned long", "unsigned long long"]: - BRet = new_primitive_type(rettype) - def cb(n): - return n + 1 - BFunc = new_function_type((BRet,), BRet) - f = callback(BFunc, cb, 42) - assert f(41) == 42 - if rettype.startswith("unsigned "): - min = 0 - max = (1 << (8*sizeof(BRet))) - 1 - else: - min = -(1 << (8*sizeof(BRet)-1)) - max = (1 << (8*sizeof(BRet)-1)) - 1 - assert f(min) == min + 1 - assert f(max - 1) == max - assert f(max) == 42 - -def test_a_lot_of_callbacks(): - BIGNUM = 10000 - if 'PY_DOT_PY' in globals(): BIGNUM = 100 # tests on py.py - # - BInt = new_primitive_type("int") - BFunc = new_function_type((BInt,), BInt, False) - def make_callback(m): - def cb(n): - return n + m - return callback(BFunc, cb, 42) # 'cb' goes out of scope - # - flist = [make_callback(i) for i in range(BIGNUM)] - for i, f in enumerate(flist): - assert f(-142) == -142 + i - -def test_callback_receiving_tiny_struct(): - BSChar = new_primitive_type("signed char") - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a', BSChar, -1), - ('b', BSChar, -1)]) - def cb(s): - return s.a + 10 * s.b - BFunc = new_function_type((BStruct,), BInt) - f = callback(BFunc, cb) - p = newp(BStructPtr, [-2, -4]) - n = f(p[0]) - assert n == -42 - -def test_callback_returning_tiny_struct(): - BSChar = new_primitive_type("signed char") - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a', BSChar, -1), - ('b', BSChar, -1)]) - def cb(n): - return newp(BStructPtr, [-n, -3*n])[0] - BFunc = new_function_type((BInt,), BStruct) - f = callback(BFunc, cb) - s = f(10) - assert typeof(s) is BStruct - assert repr(s) == "<cdata 'struct foo' owning 2 bytes>" - assert s.a == -10 - assert s.b == -30 - -def test_callback_receiving_struct(): - BSChar = new_primitive_type("signed char") - BInt = new_primitive_type("int") - BDouble = new_primitive_type("double") - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a', BSChar, -1), - ('b', BDouble, -1)]) - def cb(s): - return s.a + int(s.b) - BFunc = new_function_type((BStruct,), BInt) - f = callback(BFunc, cb) - p = newp(BStructPtr, [-2, 44.444]) - n = f(p[0]) - assert n == 42 - -def test_callback_returning_struct(): - BSChar = new_primitive_type("signed char") - BInt = new_primitive_type("int") - BDouble = new_primitive_type("double") - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a', BSChar, -1), - ('b', BDouble, -1)]) - def cb(n): - return newp(BStructPtr, [-n, 1E-42])[0] - BFunc = new_function_type((BInt,), BStruct) - f = callback(BFunc, cb) - s = f(10) - assert typeof(s) is BStruct - assert repr(s) in ["<cdata 'struct foo' owning 12 bytes>", - "<cdata 'struct foo' owning 16 bytes>"] - assert s.a == -10 - assert s.b == 1E-42 - -def test_callback_receiving_big_struct(): - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a', BInt, -1), - ('b', BInt, -1), - ('c', BInt, -1), - ('d', BInt, -1), - ('e', BInt, -1), - ('f', BInt, -1), - ('g', BInt, -1), - ('h', BInt, -1), - ('i', BInt, -1), - ('j', BInt, -1)]) - def cb(s): - for i, name in enumerate("abcdefghij"): - assert getattr(s, name) == 13 - i - return 42 - BFunc = new_function_type((BStruct,), BInt) - f = callback(BFunc, cb) - p = newp(BStructPtr, list(range(13, 3, -1))) - n = f(p[0]) - assert n == 42 - -def test_callback_returning_big_struct(): - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a', BInt, -1), - ('b', BInt, -1), - ('c', BInt, -1), - ('d', BInt, -1), - ('e', BInt, -1), - ('f', BInt, -1), - ('g', BInt, -1), - ('h', BInt, -1), - ('i', BInt, -1), - ('j', BInt, -1)]) - def cb(): - return newp(BStructPtr, list(range(13, 3, -1)))[0] - BFunc = new_function_type((), BStruct) - f = callback(BFunc, cb) - s = f() - assert typeof(s) is BStruct - assert repr(s) in ["<cdata 'struct foo' owning 40 bytes>", - "<cdata 'struct foo' owning 80 bytes>"] - for i, name in enumerate("abcdefghij"): - assert getattr(s, name) == 13 - i - -def test_callback_returning_void(): - BVoid = new_void_type() - BFunc = new_function_type((), BVoid, False) - def cb(): - seen.append(42) - f = callback(BFunc, cb) - seen = [] - f() - assert seen == [42] - py.test.raises(TypeError, callback, BFunc, cb, -42) - -def test_enum_type(): - BUInt = new_primitive_type("unsigned int") - BEnum = new_enum_type("foo", (), (), BUInt) - assert repr(BEnum) == "<ctype 'foo'>" - assert BEnum.kind == "enum" - assert BEnum.cname == "foo" - assert BEnum.elements == {} - # - BInt = new_primitive_type("int") - BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt) - assert BEnum.kind == "enum" - assert BEnum.cname == "enum foo" - assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'} - # 'elements' is not the real dict, but merely a copy - BEnum.elements[2] = '??' - assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'} - # - BEnum = new_enum_type("enum bar", ('ab', 'cd'), (5, 5), BUInt) - assert BEnum.elements == {5: 'ab'} - assert BEnum.relements == {'ab': 5, 'cd': 5} - -def test_cast_to_enum(): - BInt = new_primitive_type("int") - BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt) - assert sizeof(BEnum) == sizeof(BInt) - e = cast(BEnum, 0) - assert repr(e) == "<cdata 'enum foo' 0: def>" - assert repr(cast(BEnum, -42)) == "<cdata 'enum foo' -42>" - assert repr(cast(BEnum, -20)) == "<cdata 'enum foo' -20: ab>" - assert string(e) == 'def' - assert string(cast(BEnum, -20)) == 'ab' - assert int(cast(BEnum, 1)) == 1 - assert int(cast(BEnum, 0)) == 0 - assert int(cast(BEnum, -242 + 2**128)) == -242 - assert string(cast(BEnum, -242 + 2**128)) == '-242' - # - BUInt = new_primitive_type("unsigned int") - BEnum = new_enum_type("enum bar", ('def', 'c', 'ab'), (0, 1, 20), BUInt) - e = cast(BEnum, -1) - assert repr(e) == "<cdata 'enum bar' 4294967295>" # unsigned int - # - BLong = new_primitive_type("long") - BEnum = new_enum_type("enum baz", (), (), BLong) - assert sizeof(BEnum) == sizeof(BLong) - e = cast(BEnum, -1) - assert repr(e) == "<cdata 'enum baz' -1>" - -def test_enum_with_non_injective_mapping(): - BInt = new_primitive_type("int") - BEnum = new_enum_type("enum foo", ('ab', 'cd'), (7, 7), BInt) - e = cast(BEnum, 7) - assert repr(e) == "<cdata 'enum foo' 7: ab>" - assert string(e) == 'ab' - -def test_enum_in_struct(): - BInt = new_primitive_type("int") - BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt) - BStruct = new_struct_type("struct bar") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BEnum, -1)]) - p = newp(BStructPtr, [-20]) - assert p.a1 == -20 - p = newp(BStructPtr, [12]) - assert p.a1 == 12 - e = py.test.raises(TypeError, newp, BStructPtr, [None]) - msg = str(e.value) - assert ("an integer is required" in msg or # CPython - "unsupported operand type for int(): 'NoneType'" in msg or # old PyPys - "expected integer, got NoneType object" in msg) # newer PyPys - with pytest.raises(TypeError): - p.a1 = "def" - if sys.version_info < (3,): - BEnum2 = new_enum_type(unicode("foo"), (unicode('abc'),), (5,), BInt) - assert string(cast(BEnum2, 5)) == 'abc' - assert type(string(cast(BEnum2, 5))) is str - -def test_enum_overflow(): - max_uint = 2 ** (size_of_int()*8) - 1 - max_int = max_uint // 2 - max_ulong = 2 ** (size_of_long()*8) - 1 - max_long = max_ulong // 2 - for BPrimitive in [new_primitive_type("int"), - new_primitive_type("unsigned int"), - new_primitive_type("long"), - new_primitive_type("unsigned long")]: - for x in [max_uint, max_int, max_ulong, max_long]: - for testcase in [x, x+1, -x-1, -x-2]: - if int(cast(BPrimitive, testcase)) == testcase: - # fits - BEnum = new_enum_type("foo", ("AA",), (testcase,), - BPrimitive) - assert int(cast(BEnum, testcase)) == testcase - else: - # overflows - py.test.raises(OverflowError, new_enum_type, - "foo", ("AA",), (testcase,), BPrimitive) - -def test_callback_returning_enum(): - BInt = new_primitive_type("int") - BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20), BInt) - def cb(n): - if n & 1: - return cast(BEnum, n) - else: - return n - BFunc = new_function_type((BInt,), BEnum) - f = callback(BFunc, cb) - assert f(0) == 0 - assert f(1) == 1 - assert f(-20) == -20 - assert f(20) == 20 - assert f(21) == 21 - -def test_callback_returning_enum_unsigned(): - BInt = new_primitive_type("int") - BUInt = new_primitive_type("unsigned int") - BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, 20), BUInt) - def cb(n): - if n & 1: - return cast(BEnum, n) - else: - return n - BFunc = new_function_type((BInt,), BEnum) - f = callback(BFunc, cb) - assert f(0) == 0 - assert f(1) == 1 - assert f(-21) == 2**32 - 21 - assert f(20) == 20 - assert f(21) == 21 - -def test_callback_returning_char(): - BInt = new_primitive_type("int") - BChar = new_primitive_type("char") - def cb(n): - return bytechr(n) - BFunc = new_function_type((BInt,), BChar) - f = callback(BFunc, cb) - assert f(0) == b'\x00' - assert f(255) == b'\xFF' - -def _hacked_pypy_uni4(): - pyuni4 = {1: True, 2: False}[len(u+'\U00012345')] - return 'PY_DOT_PY' in globals() and not pyuni4 - -def test_callback_returning_wchar_t(): - BInt = new_primitive_type("int") - BWChar = new_primitive_type("wchar_t") - def cb(n): - if n == -1: - return u+'\U00012345' - if n == -2: - raise ValueError - return unichr(n) - BFunc = new_function_type((BInt,), BWChar) - f = callback(BFunc, cb) - assert f(0) == unichr(0) - assert f(255) == unichr(255) - assert f(0x1234) == u+'\u1234' - if sizeof(BWChar) == 4 and not _hacked_pypy_uni4(): - assert f(-1) == u+'\U00012345' - assert f(-2) == u+'\x00' # and an exception printed to stderr - -def test_struct_with_bitfields(): - BLong = new_primitive_type("long") - BStruct = new_struct_type("struct foo") - LONGBITS = 8 * sizeof(BLong) - complete_struct_or_union(BStruct, [('a1', BLong, 1), - ('a2', BLong, 2), - ('a3', BLong, 3), - ('a4', BLong, LONGBITS - 5)]) - d = BStruct.fields - assert d[0][1].offset == d[1][1].offset == d[2][1].offset == 0 - assert d[3][1].offset == sizeof(BLong) - def f(m, r): - if sys.byteorder == 'little': - return r - else: - return LONGBITS - m - r - assert d[0][1].bitshift == f(1, 0) - assert d[0][1].bitsize == 1 - assert d[1][1].bitshift == f(2, 1) - assert d[1][1].bitsize == 2 - assert d[2][1].bitshift == f(3, 3) - assert d[2][1].bitsize == 3 - assert d[3][1].bitshift == f(LONGBITS - 5, 0) - assert d[3][1].bitsize == LONGBITS - 5 - assert sizeof(BStruct) == 2 * sizeof(BLong) - assert alignof(BStruct) == alignof(BLong) - -def test_bitfield_instance(): - BInt = new_primitive_type("int") - BUnsignedInt = new_primitive_type("unsigned int") - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('a1', BInt, 1), - ('a2', BUnsignedInt, 2), - ('a3', BInt, 3)]) - p = newp(new_pointer_type(BStruct), None) - p.a1 = -1 - assert p.a1 == -1 - p.a1 = 0 - with pytest.raises(OverflowError): - p.a1 = 2 - assert p.a1 == 0 - # - p.a1 = -1 - p.a2 = 3 - p.a3 = -4 - with pytest.raises(OverflowError): - p.a3 = 4 - with pytest.raises(OverflowError) as e: - p.a3 = -5 - assert str(e.value) == ("value -5 outside the range allowed by the " - "bit field width: -4 <= x <= 3") - assert p.a1 == -1 and p.a2 == 3 and p.a3 == -4 - # - # special case for convenience: "int x:1", while normally signed, - # allows also setting the value "1" (it still gets read back as -1) - p.a1 = 1 - assert p.a1 == -1 - with pytest.raises(OverflowError) as e: - p.a1 = -2 - assert str(e.value) == ("value -2 outside the range allowed by the " - "bit field width: -1 <= x <= 1") - -def test_bitfield_instance_init(): - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('a1', BInt, 1)]) - p = newp(new_pointer_type(BStruct), [-1]) - assert p.a1 == -1 - p = newp(new_pointer_type(BStruct), {'a1': -1}) - assert p.a1 == -1 - # - BUnion = new_union_type("union bar") - complete_struct_or_union(BUnion, [('a1', BInt, 1)]) - p = newp(new_pointer_type(BUnion), [-1]) - assert p.a1 == -1 - -def test_weakref(): - import _weakref - BInt = new_primitive_type("int") - BPtr = new_pointer_type(BInt) - rlist = [_weakref.ref(BInt), - _weakref.ref(newp(BPtr, 42)), - _weakref.ref(cast(BPtr, 42)), - _weakref.ref(cast(BInt, 42)), - _weakref.ref(buffer(newp(BPtr, 42))), - ] - for i in range(5): - import gc; gc.collect() - if [r() for r in rlist] == [None for r in rlist]: - break - -def test_no_inheritance(): - BInt = new_primitive_type("int") - try: - class foo(type(BInt)): pass - except TypeError: - pass - else: - raise AssertionError - x = cast(BInt, 42) - try: - class foo(type(x)): pass - except TypeError: - pass - else: - raise AssertionError - -def test_assign_string(): - BChar = new_primitive_type("char") - BArray1 = new_array_type(new_pointer_type(BChar), 5) - BArray2 = new_array_type(new_pointer_type(BArray1), 5) - a = newp(BArray2, [b"abc", b"de", b"ghij"]) - assert string(a[1]) == b"de" - assert string(a[2]) == b"ghij" - a[2] = b"." - assert string(a[2]) == b"." - a[2] = b"12345" - assert string(a[2]) == b"12345" - with pytest.raises(IndexError) as e: - a[2] = b"123456" - assert 'char[5]' in str(e.value) - assert 'got 6 characters' in str(e.value) - -def test_add_error(): - x = cast(new_primitive_type("int"), 42) - with pytest.raises(TypeError): - x + 1 - with pytest.raises(TypeError): - x - 1 - -def test_void_errors(): - py.test.raises(ValueError, alignof, new_void_type()) - py.test.raises(TypeError, newp, new_pointer_type(new_void_type()), None) - -def test_too_many_items(): - BChar = new_primitive_type("char") - BArray = new_array_type(new_pointer_type(BChar), 5) - py.test.raises(IndexError, newp, BArray, tuple(b'123456')) - py.test.raises(IndexError, newp, BArray, list(b'123456')) - py.test.raises(IndexError, newp, BArray, b'123456') - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, []) - py.test.raises(TypeError, newp, new_pointer_type(BStruct), b'') - py.test.raises(ValueError, newp, new_pointer_type(BStruct), [b'1']) - -def test_more_type_errors(): - BInt = new_primitive_type("int") - BChar = new_primitive_type("char") - BArray = new_array_type(new_pointer_type(BChar), 5) - py.test.raises(TypeError, newp, BArray, 12.34) - BArray = new_array_type(new_pointer_type(BInt), 5) - py.test.raises(TypeError, newp, BArray, 12.34) - BFloat = new_primitive_type("float") - py.test.raises(TypeError, cast, BFloat, newp(BArray, None)) - -def test_more_overflow_errors(): - BUInt = new_primitive_type("unsigned int") - py.test.raises(OverflowError, newp, new_pointer_type(BUInt), -1) - py.test.raises(OverflowError, newp, new_pointer_type(BUInt), 2**32) - -def test_newp_copying(): - """Test that we can do newp(<type>, <cdata of the given type>) for most - types, including same-type arrays. - """ - BInt = new_primitive_type("int") - p = newp(new_pointer_type(BInt), cast(BInt, 42)) - assert p[0] == 42 - # - BUInt = new_primitive_type("unsigned int") - p = newp(new_pointer_type(BUInt), cast(BUInt, 42)) - assert p[0] == 42 - # - BChar = new_primitive_type("char") - p = newp(new_pointer_type(BChar), cast(BChar, '!')) - assert p[0] == b'!' - # - BFloat = new_primitive_type("float") - p = newp(new_pointer_type(BFloat), cast(BFloat, 12.25)) - assert p[0] == 12.25 - # - BStruct = new_struct_type("struct foo_s") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BInt, -1)]) - s1 = newp(BStructPtr, [42]) - p1 = newp(new_pointer_type(BStructPtr), s1) - assert p1[0] == s1 - # - BArray = new_array_type(new_pointer_type(BInt), None) - a1 = newp(BArray, [1, 2, 3, 4]) - py.test.raises(TypeError, newp, BArray, a1) - BArray6 = new_array_type(new_pointer_type(BInt), 6) - a1 = newp(BArray6, [10, 20, 30]) - a2 = newp(BArray6, a1) - assert list(a2) == [10, 20, 30, 0, 0, 0] - # - s1 = newp(BStructPtr, [42]) - s2 = newp(BStructPtr, s1[0]) - assert s2.a1 == 42 - # - BUnion = new_union_type("union foo_u") - BUnionPtr = new_pointer_type(BUnion) - complete_struct_or_union(BUnion, [('a1', BInt, -1)]) - u1 = newp(BUnionPtr, [42]) - u2 = newp(BUnionPtr, u1[0]) - assert u2.a1 == 42 - # - BFunc = new_function_type((BInt,), BUInt) - p1 = cast(BFunc, 42) - p2 = newp(new_pointer_type(BFunc), p1) - assert p2[0] == p1 - -def test_string(): - BChar = new_primitive_type("char") - assert string(cast(BChar, 42)) == b'*' - assert string(cast(BChar, 0)) == b'\x00' - BCharP = new_pointer_type(BChar) - BArray = new_array_type(BCharP, 10) - a = newp(BArray, b"hello") - assert len(a) == 10 - assert string(a) == b"hello" - p = a + 2 - assert string(p) == b"llo" - assert string(newp(new_array_type(BCharP, 4), b"abcd")) == b"abcd" - py.test.raises(RuntimeError, string, cast(BCharP, 0)) - assert string(a, 4) == b"hell" - assert string(a, 5) == b"hello" - assert string(a, 6) == b"hello" - -def test_string_byte(): - BByte = new_primitive_type("signed char") - assert string(cast(BByte, 42)) == b'*' - assert string(cast(BByte, 0)) == b'\x00' - BArray = new_array_type(new_pointer_type(BByte), None) - a = newp(BArray, [65, 66, 67]) - assert type(string(a)) is bytes and string(a) == b'ABC' - # - BByte = new_primitive_type("unsigned char") - assert string(cast(BByte, 42)) == b'*' - assert string(cast(BByte, 0)) == b'\x00' - BArray = new_array_type(new_pointer_type(BByte), None) - a = newp(BArray, [65, 66, 67]) - assert type(string(a)) is bytes and string(a) == b'ABC' - if 'PY_DOT_PY' not in globals() and sys.version_info < (3,): - assert string(a, 8).startswith(b'ABC') # may contain additional garbage - -def test_string_wchar(): - for typename in ["wchar_t", "char16_t", "char32_t"]: - _test_string_wchar_variant(typename) - -def _test_string_wchar_variant(typename): - BWChar = new_primitive_type(typename) - assert string(cast(BWChar, 42)) == u+'*' - assert string(cast(BWChar, 0x4253)) == u+'\u4253' - assert string(cast(BWChar, 0)) == u+'\x00' - BArray = new_array_type(new_pointer_type(BWChar), None) - a = newp(BArray, [u+'A', u+'B', u+'C']) - assert type(string(a)) is unicode and string(a) == u+'ABC' - if 'PY_DOT_PY' not in globals() and sys.version_info < (3,): - try: - # may contain additional garbage - assert string(a, 8).startswith(u+'ABC') - except ValueError: # garbage contains values > 0x10FFFF - assert sizeof(BWChar) == 4 - -def test_string_typeerror(): - BShort = new_primitive_type("short") - BArray = new_array_type(new_pointer_type(BShort), None) - a = newp(BArray, [65, 66, 67]) - py.test.raises(TypeError, string, a) - -def test_bug_convert_to_ptr(): - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BDouble = new_primitive_type("double") - x = cast(BDouble, 42) - py.test.raises(TypeError, newp, new_pointer_type(BCharP), x) - -def test_set_struct_fields(): - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharArray10 = new_array_type(BCharP, 10) - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BCharArray10, -1)]) - p = newp(BStructPtr, None) - assert string(p.a1) == b'' - p.a1 = b'foo' - assert string(p.a1) == b'foo' - assert list(p.a1) == [b'f', b'o', b'o'] + [b'\x00'] * 7 - p.a1 = [b'x', b'y'] - assert string(p.a1) == b'xyo' - -def test_invalid_function_result_types(): - BFunc = new_function_type((), new_void_type()) - BArray = new_array_type(new_pointer_type(BFunc), 5) # works - new_function_type((), BFunc) # works - new_function_type((), new_primitive_type("int")) - new_function_type((), new_pointer_type(BFunc)) - BUnion = new_union_type("union foo_u") - complete_struct_or_union(BUnion, []) - BFunc = new_function_type((), BUnion) - py.test.raises(NotImplementedError, cast(BFunc, 123)) - py.test.raises(TypeError, new_function_type, (), BArray) - -def test_struct_return_in_func(): - BChar = new_primitive_type("char") - BShort = new_primitive_type("short") - BFloat = new_primitive_type("float") - BDouble = new_primitive_type("double") - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo_s") - complete_struct_or_union(BStruct, [('a1', BChar, -1), - ('a2', BShort, -1)]) - BFunc10 = new_function_type((BInt,), BStruct) - f = cast(BFunc10, _testfunc(10)) - s = f(40) - assert repr(s) == "<cdata 'struct foo_s' owning 4 bytes>" - assert s.a1 == bytechr(40) - assert s.a2 == 40 * 40 - # - BStruct11 = new_struct_type("struct test11") - complete_struct_or_union(BStruct11, [('a1', BInt, -1), - ('a2', BInt, -1)]) - BFunc11 = new_function_type((BInt,), BStruct11) - f = cast(BFunc11, _testfunc(11)) - s = f(40) - assert repr(s) == "<cdata 'struct test11' owning 8 bytes>" - assert s.a1 == 40 - assert s.a2 == 40 * 40 - # - BStruct12 = new_struct_type("struct test12") - complete_struct_or_union(BStruct12, [('a1', BDouble, -1), - ]) - BFunc12 = new_function_type((BInt,), BStruct12) - f = cast(BFunc12, _testfunc(12)) - s = f(40) - assert repr(s) == "<cdata 'struct test12' owning 8 bytes>" - assert s.a1 == 40.0 - # - BStruct13 = new_struct_type("struct test13") - complete_struct_or_union(BStruct13, [('a1', BInt, -1), - ('a2', BInt, -1), - ('a3', BInt, -1)]) - BFunc13 = new_function_type((BInt,), BStruct13) - f = cast(BFunc13, _testfunc(13)) - s = f(40) - assert repr(s) == "<cdata 'struct test13' owning 12 bytes>" - assert s.a1 == 40 - assert s.a2 == 40 * 40 - assert s.a3 == 40 * 40 * 40 - # - BStruct14 = new_struct_type("struct test14") - complete_struct_or_union(BStruct14, [('a1', BFloat, -1), - ]) - BFunc14 = new_function_type((BInt,), BStruct14) - f = cast(BFunc14, _testfunc(14)) - s = f(40) - assert repr(s) == "<cdata 'struct test14' owning 4 bytes>" - assert s.a1 == 40.0 - # - BStruct15 = new_struct_type("struct test15") - complete_struct_or_union(BStruct15, [('a1', BFloat, -1), - ('a2', BInt, -1)]) - BFunc15 = new_function_type((BInt,), BStruct15) - f = cast(BFunc15, _testfunc(15)) - s = f(40) - assert repr(s) == "<cdata 'struct test15' owning 8 bytes>" - assert s.a1 == 40.0 - assert s.a2 == 40 * 40 - # - BStruct16 = new_struct_type("struct test16") - complete_struct_or_union(BStruct16, [('a1', BFloat, -1), - ('a2', BFloat, -1)]) - BFunc16 = new_function_type((BInt,), BStruct16) - f = cast(BFunc16, _testfunc(16)) - s = f(40) - assert repr(s) == "<cdata 'struct test16' owning 8 bytes>" - assert s.a1 == 40.0 - assert s.a2 == -40.0 - # - BStruct17 = new_struct_type("struct test17") - complete_struct_or_union(BStruct17, [('a1', BInt, -1), - ('a2', BFloat, -1)]) - BFunc17 = new_function_type((BInt,), BStruct17) - f = cast(BFunc17, _testfunc(17)) - s = f(40) - assert repr(s) == "<cdata 'struct test17' owning 8 bytes>" - assert s.a1 == 40 - assert s.a2 == 40.0 * 40.0 - # - BStruct17Ptr = new_pointer_type(BStruct17) - BFunc18 = new_function_type((BStruct17Ptr,), BInt) - f = cast(BFunc18, _testfunc(18)) - x = f([[40, 2.5]]) - assert x == 42 - x = f([{'a2': 43.1}]) - assert x == 43 - -def test_cast_with_functionptr(): - BFunc = new_function_type((), new_void_type()) - BFunc2 = new_function_type((), new_primitive_type("short")) - BCharP = new_pointer_type(new_primitive_type("char")) - BIntP = new_pointer_type(new_primitive_type("int")) - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BFunc, -1)]) - newp(BStructPtr, [cast(BFunc, 0)]) - newp(BStructPtr, [cast(BCharP, 0)]) - py.test.raises(TypeError, newp, BStructPtr, [cast(BIntP, 0)]) - py.test.raises(TypeError, newp, BStructPtr, [cast(BFunc2, 0)]) - -def test_wchar(): - _test_wchar_variant("wchar_t") - if sys.platform.startswith("linux"): - BWChar = new_primitive_type("wchar_t") - assert sizeof(BWChar) == 4 - # wchar_t is often signed on Linux, but not always (e.g. on ARM) - assert int(cast(BWChar, -1)) in (-1, 4294967295) - -def test_char16(): - BChar16 = new_primitive_type("char16_t") - assert sizeof(BChar16) == 2 - _test_wchar_variant("char16_t") - assert int(cast(BChar16, -1)) == 0xffff # always unsigned - -def test_char32(): - BChar32 = new_primitive_type("char32_t") - assert sizeof(BChar32) == 4 - _test_wchar_variant("char32_t") - assert int(cast(BChar32, -1)) == 0xffffffff # always unsigned - -def _test_wchar_variant(typename): - BWChar = new_primitive_type(typename) - BInt = new_primitive_type("int") - pyuni4 = {1: True, 2: False}[len(u+'\U00012345')] - wchar4 = {2: False, 4: True}[sizeof(BWChar)] - assert str(cast(BWChar, 0x45)) == "<cdata '%s' %s'E'>" % ( - typename, mandatory_u_prefix) - assert str(cast(BWChar, 0x1234)) == "<cdata '%s' %s'\u1234'>" % ( - typename, mandatory_u_prefix) - if not _hacked_pypy_uni4(): - if wchar4: - x = cast(BWChar, 0x12345) - assert str(x) == "<cdata '%s' %s'\U00012345'>" % ( - typename, mandatory_u_prefix) - assert int(x) == 0x12345 - else: - x = cast(BWChar, 0x18345) - assert str(x) == "<cdata '%s' %s'\u8345'>" % ( - typename, mandatory_u_prefix) - assert int(x) == 0x8345 - # - BWCharP = new_pointer_type(BWChar) - BStruct = new_struct_type("struct foo_s") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BWChar, -1), - ('a2', BWCharP, -1)]) - s = newp(BStructPtr) - s.a1 = u+'\x00' - assert s.a1 == u+'\x00' - with pytest.raises(TypeError): - s.a1 = b'a' - with pytest.raises(TypeError): - s.a1 = bytechr(0xFF) - s.a1 = u+'\u1234' - assert s.a1 == u+'\u1234' - if pyuni4: - if wchar4: - s.a1 = u+'\U00012345' - assert s.a1 == u+'\U00012345' - elif wchar4: - if not _hacked_pypy_uni4(): - s.a1 = cast(BWChar, 0x12345) - assert s.a1 == u+'\ud808\udf45' - s.a1 = u+'\ud807\udf44' - assert s.a1 == u+'\U00011f44' - else: - with pytest.raises(TypeError): - s.a1 = u+'\U00012345' - # - BWCharArray = new_array_type(BWCharP, None) - a = newp(BWCharArray, u+'hello \u1234 world') - assert len(a) == 14 # including the final null - assert string(a) == u+'hello \u1234 world' - a[13] = u+'!' - assert string(a) == u+'hello \u1234 world!' - assert str(a) == repr(a) - assert a[6] == u+'\u1234' - a[6] = u+'-' - assert string(a) == u+'hello - world!' - assert str(a) == repr(a) - # - if wchar4 and not _hacked_pypy_uni4(): - u1 = u+'\U00012345\U00012346\U00012347' - a = newp(BWCharArray, u1) - assert len(a) == 4 - assert string(a) == u1 - assert len(list(a)) == 4 - expected = [u+'\U00012345', u+'\U00012346', u+'\U00012347', unichr(0)] - assert list(a) == expected - got = [a[i] for i in range(4)] - assert got == expected - with pytest.raises(IndexError): - a[4] - # - w = cast(BWChar, 'a') - assert repr(w) == "<cdata '%s' %s'a'>" % (typename, mandatory_u_prefix) - assert str(w) == repr(w) - assert string(w) == u+'a' - assert int(w) == ord('a') - w = cast(BWChar, 0x1234) - assert repr(w) == "<cdata '%s' %s'\u1234'>" % (typename, mandatory_u_prefix) - assert str(w) == repr(w) - assert string(w) == u+'\u1234' - assert int(w) == 0x1234 - w = cast(BWChar, u+'\u8234') - assert repr(w) == "<cdata '%s' %s'\u8234'>" % (typename, mandatory_u_prefix) - assert str(w) == repr(w) - assert string(w) == u+'\u8234' - assert int(w) == 0x8234 - w = cast(BInt, u+'\u1234') - assert repr(w) == "<cdata 'int' 4660>" - if wchar4 and not _hacked_pypy_uni4(): - w = cast(BWChar, u+'\U00012345') - assert repr(w) == "<cdata '%s' %s'\U00012345'>" % ( - typename, mandatory_u_prefix) - assert str(w) == repr(w) - assert string(w) == u+'\U00012345' - assert int(w) == 0x12345 - w = cast(BInt, u+'\U00012345') - assert repr(w) == "<cdata 'int' 74565>" - py.test.raises(TypeError, cast, BInt, u+'') - py.test.raises(TypeError, cast, BInt, u+'XX') - assert int(cast(BInt, u+'a')) == ord('a') - # - a = newp(BWCharArray, u+'hello - world') - p = cast(BWCharP, a) - assert string(p) == u+'hello - world' - p[6] = u+'\u2345' - assert string(p) == u+'hello \u2345 world' - # - s = newp(BStructPtr, [u+'\u1234', p]) - assert s.a1 == u+'\u1234' - assert s.a2 == p - assert str(s.a2) == repr(s.a2) - assert string(s.a2) == u+'hello \u2345 world' - # - q = cast(BWCharP, 0) - assert str(q) == repr(q) - py.test.raises(RuntimeError, string, q) - # - def cb(p): - assert repr(p).startswith("<cdata '%s *' 0x" % typename) - return len(string(p)) - BFunc = new_function_type((BWCharP,), BInt, False) - f = callback(BFunc, cb, -42) - assert f(u+'a\u1234b') == 3 - # - if wchar4 and not pyuni4 and not _hacked_pypy_uni4(): - # try out-of-range wchar_t values - x = cast(BWChar, 1114112) - py.test.raises(ValueError, string, x) - x = cast(BWChar, -1) - py.test.raises(ValueError, string, x) - -def test_wchar_variants_mix(): - BWChar = new_primitive_type("wchar_t") - BChar16 = new_primitive_type("char16_t") - BChar32 = new_primitive_type("char32_t") - assert int(cast(BChar32, cast(BChar16, -2))) == 0xfffe - assert int(cast(BWChar, cast(BChar16, -2))) == 0xfffe - assert int(cast(BChar16, cast(BChar32, 0x0001f345))) == 0xf345 - assert int(cast(BChar16, cast(BWChar, 0x0001f345))) == 0xf345 - # - BChar16A = new_array_type(new_pointer_type(BChar16), None) - BChar32A = new_array_type(new_pointer_type(BChar32), None) - x = cast(BChar32, 'A') - py.test.raises(TypeError, newp, BChar16A, [x]) - x = cast(BChar16, 'A') - py.test.raises(TypeError, newp, BChar32A, [x]) - # - a = newp(BChar16A, u+'\U00012345') - assert len(a) == 3 - a = newp(BChar32A, u+'\U00012345') - assert len(a) == 2 # even if the Python unicode string above is 2 chars - -def test_keepalive_struct(): - # exception to the no-keepalive rule: p=newp(BStructPtr) returns a - # pointer owning the memory, and p[0] returns a pointer to the - # struct that *also* owns the memory - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', new_primitive_type("int"), -1), - ('a2', new_primitive_type("int"), -1), - ('a3', new_primitive_type("int"), -1)]) - p = newp(BStructPtr) - assert repr(p) == "<cdata 'struct foo *' owning 12 bytes>" - q = p[0] - assert repr(q) == "<cdata 'struct foo' owning 12 bytes>" - q.a1 = 123456 - assert p.a1 == 123456 - r = cast(BStructPtr, p) - assert repr(r[0]).startswith("<cdata 'struct foo &' 0x") - del p - import gc; gc.collect() - assert q.a1 == 123456 - assert repr(q) == "<cdata 'struct foo' owning 12 bytes>" - assert q.a1 == 123456 - -def test_nokeepalive_struct(): - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - BStructPtrPtr = new_pointer_type(BStructPtr) - complete_struct_or_union(BStruct, [('a1', new_primitive_type("int"), -1)]) - p = newp(BStructPtr) - pp = newp(BStructPtrPtr) - pp[0] = p - s = pp[0][0] - assert repr(s).startswith("<cdata 'struct foo &' 0x") - -def test_owning_repr(): - BInt = new_primitive_type("int") - BArray = new_array_type(new_pointer_type(BInt), None) # int[] - p = newp(BArray, 7) - assert repr(p) == "<cdata 'int[]' owning 28 bytes>" - assert sizeof(p) == 28 - # - BArray = new_array_type(new_pointer_type(BInt), 7) # int[7] - p = newp(BArray, None) - assert repr(p) == "<cdata 'int[7]' owning 28 bytes>" - assert sizeof(p) == 28 - -def test_cannot_dereference_void(): - BVoidP = new_pointer_type(new_void_type()) - p = cast(BVoidP, 123456) - with pytest.raises(TypeError): - p[0] - p = cast(BVoidP, 0) - with pytest.raises((TypeError, RuntimeError)): - p[0] - -def test_iter(): - BInt = new_primitive_type("int") - BIntP = new_pointer_type(BInt) - BArray = new_array_type(BIntP, None) # int[] - p = newp(BArray, 7) - assert list(p) == list(iter(p)) == [0] * 7 - # - py.test.raises(TypeError, iter, cast(BInt, 5)) - py.test.raises(TypeError, iter, cast(BIntP, 123456)) - -def test_cmp(): - BInt = new_primitive_type("int") - BIntP = new_pointer_type(BInt) - BVoidP = new_pointer_type(new_void_type()) - p = newp(BIntP, 123) - q = cast(BInt, 124) - assert (p == q) is False - assert (p != q) is True - assert (q == p) is False - assert (q != p) is True - if strict_compare: - with pytest.raises(TypeError): p < q - with pytest.raises(TypeError): p <= q - with pytest.raises(TypeError): q < p - with pytest.raises(TypeError): q <= p - with pytest.raises(TypeError): p > q - with pytest.raises(TypeError): p >= q - r = cast(BVoidP, p) - assert (p < r) is False - assert (p <= r) is True - assert (p == r) is True - assert (p != r) is False - assert (p > r) is False - assert (p >= r) is True - s = newp(BIntP, 125) - assert (p == s) is False - assert (p != s) is True - assert (p < s) is (p <= s) is (s > p) is (s >= p) - assert (p > s) is (p >= s) is (s < p) is (s <= p) - assert (p < s) ^ (p > s) - -def test_buffer(): - try: - import __builtin__ - except ImportError: - import builtins as __builtin__ - BShort = new_primitive_type("short") - s = newp(new_pointer_type(BShort), 100) - assert sizeof(s) == size_of_ptr() - assert sizeof(BShort) == 2 - assert len(buffer(s)) == 2 - # - BChar = new_primitive_type("char") - BCharArray = new_array_type(new_pointer_type(BChar), None) - c = newp(BCharArray, b"hi there") - # - buf = buffer(c) - assert repr(buf).startswith('<_cffi_backend.buffer object at 0x') - assert bytes(buf) == b"hi there\x00" - assert type(buf) is buffer - if sys.version_info < (3,): - assert str(buf) == "hi there\x00" - assert unicode(buf) == u+"hi there\x00" - else: - assert str(buf) == repr(buf) - # --mb_length-- - assert len(buf) == len(b"hi there\x00") - # --mb_item-- - for i in range(-12, 12): - try: - expected = b"hi there\x00"[i] - except IndexError: - with pytest.raises(IndexError): - buf[i] - else: - assert buf[i] == bitem2bchr(expected) - # --mb_slice-- - assert buf[:] == b"hi there\x00" - for i in range(-12, 12): - assert buf[i:] == b"hi there\x00"[i:] - assert buf[:i] == b"hi there\x00"[:i] - for j in range(-12, 12): - assert buf[i:j] == b"hi there\x00"[i:j] - # --misc-- - assert list(buf) == list(map(bitem2bchr, b"hi there\x00")) - # --mb_as_buffer-- - if hasattr(__builtin__, 'buffer'): # Python <= 2.7 - py.test.raises(TypeError, __builtin__.buffer, c) - bf1 = __builtin__.buffer(buf) - assert len(bf1) == len(buf) and bf1[3] == "t" - if hasattr(__builtin__, 'memoryview'): # Python >= 2.7 - py.test.raises(TypeError, memoryview, c) - mv1 = memoryview(buf) - assert len(mv1) == len(buf) and mv1[3] in (b"t", ord(b"t")) - # --mb_ass_item-- - expected = list(map(bitem2bchr, b"hi there\x00")) - for i in range(-12, 12): - try: - expected[i] = bytechr(i & 0xff) - except IndexError: - with pytest.raises(IndexError): - buf[i] = bytechr(i & 0xff) - else: - buf[i] = bytechr(i & 0xff) - assert list(buf) == expected - # --mb_ass_slice-- - buf[:] = b"hi there\x00" - assert list(buf) == list(c) == list(map(bitem2bchr, b"hi there\x00")) - with pytest.raises(ValueError): - buf[:] = b"shorter" - with pytest.raises(ValueError): - buf[:] = b"this is much too long!" - buf[4:2] = b"" # no effect, but should work - assert buf[:] == b"hi there\x00" - buf[:2] = b"HI" - assert buf[:] == b"HI there\x00" - buf[:2] = b"hi" - expected = list(map(bitem2bchr, b"hi there\x00")) - x = 0 - for i in range(-12, 12): - for j in range(-12, 12): - start = i if i >= 0 else i + len(buf) - stop = j if j >= 0 else j + len(buf) - start = max(0, min(len(buf), start)) - stop = max(0, min(len(buf), stop)) - sample = bytechr(x & 0xff) * (stop - start) - x += 1 - buf[i:j] = sample - expected[i:j] = map(bitem2bchr, sample) - assert list(buf) == expected - -def test_getcname(): - BUChar = new_primitive_type("unsigned char") - BArray = new_array_type(new_pointer_type(BUChar), 123) - assert getcname(BArray, "<-->") == "unsigned char<-->[123]" - -def test_errno(): - BVoid = new_void_type() - BFunc5 = new_function_type((), BVoid) - f = cast(BFunc5, _testfunc(5)) - set_errno(50) - f() - assert get_errno() == 65 - f(); f() - assert get_errno() == 95 - -def test_errno_callback(): - if globals().get('PY_DOT_PY'): - py.test.skip("cannot run this test on py.py (e.g. fails on Windows)") - set_errno(95) - def cb(): - e = get_errno() - set_errno(e - 6) - BVoid = new_void_type() - BFunc5 = new_function_type((), BVoid) - f = callback(BFunc5, cb) - f() - assert get_errno() == 89 - f(); f() - assert get_errno() == 77 - -def test_cast_to_array(): - # not valid in C! extension to get a non-owning <cdata 'int[3]'> - BInt = new_primitive_type("int") - BIntP = new_pointer_type(BInt) - BArray = new_array_type(BIntP, 3) - x = cast(BArray, 0) - assert repr(x) == "<cdata 'int[3]' NULL>" - -def test_cast_invalid(): - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, []) - p = cast(new_pointer_type(BStruct), 123456) - s = p[0] - py.test.raises(TypeError, cast, BStruct, s) - -def test_bug_float_convertion(): - BDouble = new_primitive_type("double") - BDoubleP = new_pointer_type(BDouble) - py.test.raises(TypeError, newp, BDoubleP, "foobar") - -def test_bug_delitem(): - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - x = newp(BCharP) - with pytest.raises(TypeError): - del x[0] - -def test_bug_delattr(): - BLong = new_primitive_type("long") - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('a1', BLong, -1)]) - x = newp(new_pointer_type(BStruct)) - with pytest.raises(AttributeError): - del x.a1 - -def test_variable_length_struct(): - py.test.skip("later") - BLong = new_primitive_type("long") - BArray = new_array_type(new_pointer_type(BLong), None) - BStruct = new_struct_type("struct foo") - BStructP = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BLong, -1), - ('a2', BArray, -1)]) - assert sizeof(BStruct) == size_of_long() - assert alignof(BStruct) == alignof(BLong) - # - py.test.raises(TypeError, newp, BStructP, None) - x = newp(BStructP, 5) - assert sizeof(x) == 6 * size_of_long() - x[4] = 123 - assert x[4] == 123 - with pytest.raises(IndexError): - x[5] - assert len(x.a2) == 5 - # - py.test.raises(TypeError, newp, BStructP, [123]) - x = newp(BStructP, [123, 5]) - assert x.a1 == 123 - assert len(x.a2) == 5 - assert list(x.a2) == [0] * 5 - # - x = newp(BStructP, {'a2': 5}) - assert x.a1 == 0 - assert len(x.a2) == 5 - assert list(x.a2) == [0] * 5 - # - x = newp(BStructP, [123, (4, 5)]) - assert x.a1 == 123 - assert len(x.a2) == 2 - assert list(x.a2) == [4, 5] - # - x = newp(BStructP, {'a2': (4, 5)}) - assert x.a1 == 0 - assert len(x.a2) == 2 - assert list(x.a2) == [4, 5] - -def test_autocast_int(): - BInt = new_primitive_type("int") - BIntPtr = new_pointer_type(BInt) - BLongLong = new_primitive_type("long long") - BULongLong = new_primitive_type("unsigned long long") - BULongLongPtr = new_pointer_type(BULongLong) - x = newp(BIntPtr, cast(BInt, 42)) - assert x[0] == 42 - x = newp(BIntPtr, cast(BLongLong, 42)) - assert x[0] == 42 - x = newp(BIntPtr, cast(BULongLong, 42)) - assert x[0] == 42 - x = newp(BULongLongPtr, cast(BInt, 42)) - assert x[0] == 42 - py.test.raises(OverflowError, newp, BULongLongPtr, cast(BInt, -42)) - x = cast(BInt, cast(BInt, 42)) - assert int(x) == 42 - x = cast(BInt, cast(BLongLong, 42)) - assert int(x) == 42 - x = cast(BInt, cast(BULongLong, 42)) - assert int(x) == 42 - x = cast(BULongLong, cast(BInt, 42)) - assert int(x) == 42 - x = cast(BULongLong, cast(BInt, -42)) - assert int(x) == 2 ** 64 - 42 - x = cast(BIntPtr, cast(BInt, 42)) - assert int(cast(BInt, x)) == 42 - -def test_autocast_float(): - BFloat = new_primitive_type("float") - BDouble = new_primitive_type("float") - BFloatPtr = new_pointer_type(BFloat) - x = newp(BFloatPtr, cast(BDouble, 12.5)) - assert x[0] == 12.5 - x = cast(BFloat, cast(BDouble, 12.5)) - assert float(x) == 12.5 - -def test_longdouble(): - py_py = 'PY_DOT_PY' in globals() - BInt = new_primitive_type("int") - BLongDouble = new_primitive_type("long double") - BLongDoublePtr = new_pointer_type(BLongDouble) - BLongDoubleArray = new_array_type(BLongDoublePtr, None) - a = newp(BLongDoubleArray, 1) - x = a[0] - if not py_py: - assert repr(x).startswith("<cdata 'long double' 0.0") - assert float(x) == 0.0 - assert int(x) == 0 - # - b = newp(BLongDoubleArray, [1.23]) - x = b[0] - if not py_py: - assert repr(x).startswith("<cdata 'long double' 1.23") - assert float(x) == 1.23 - assert int(x) == 1 - # - BFunc19 = new_function_type((BLongDouble, BInt), BLongDouble) - f = cast(BFunc19, _testfunc(19)) - start = lstart = 1.5 - for i in range(107): - start = 4 * start - start * start - lstart = f(lstart, 1) - lother = f(1.5, 107) - if not py_py: - assert float(lstart) == float(lother) - assert repr(lstart) == repr(lother) - if sizeof(BLongDouble) > sizeof(new_primitive_type("double")): - assert float(lstart) != start - assert repr(lstart).startswith("<cdata 'long double' ") - # - c = newp(BLongDoubleArray, [lstart]) - x = c[0] - assert float(f(lstart, 107)) == float(f(x, 107)) - -def test_get_array_of_length_zero(): - for length in [0, 5, 10]: - BLong = new_primitive_type("long") - BLongP = new_pointer_type(BLong) - BArray0 = new_array_type(BLongP, length) - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BArray0, -1)]) - p = newp(BStructPtr, None) - if length == 0: - assert repr(p.a1).startswith("<cdata 'long *' 0x") - else: - assert repr(p.a1).startswith("<cdata 'long[%d]' 0x" % length) - -def test_nested_anonymous_struct(): - BInt = new_primitive_type("int") - BChar = new_primitive_type("char") - BStruct = new_struct_type("struct foo") - BInnerStruct = new_struct_type("struct foo") - complete_struct_or_union(BInnerStruct, [('a1', BInt, -1), - ('a2', BChar, -1)]) - complete_struct_or_union(BStruct, [('', BInnerStruct, -1), - ('a3', BChar, -1)]) - assert sizeof(BInnerStruct) == sizeof(BInt) * 2 # with alignment - assert sizeof(BStruct) == sizeof(BInt) * 3 # 'a3' is placed after - d = BStruct.fields - assert len(d) == 3 - assert d[0][0] == 'a1' - assert d[0][1].type is BInt - assert d[0][1].offset == 0 - assert d[0][1].bitshift == -1 - assert d[0][1].bitsize == -1 - assert d[1][0] == 'a2' - assert d[1][1].type is BChar - assert d[1][1].offset == sizeof(BInt) - assert d[1][1].bitshift == -1 - assert d[1][1].bitsize == -1 - assert d[2][0] == 'a3' - assert d[2][1].type is BChar - assert d[2][1].offset == sizeof(BInt) * 2 - assert d[2][1].bitshift == -1 - assert d[2][1].bitsize == -1 - -def test_nested_anonymous_struct_2(): - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - BInnerUnion = new_union_type("union bar") - complete_struct_or_union(BInnerUnion, [('a1', BInt, -1), - ('a2', BInt, -1)]) - complete_struct_or_union(BStruct, [('b1', BInt, -1), - ('', BInnerUnion, -1), - ('b2', BInt, -1)]) - assert sizeof(BInnerUnion) == sizeof(BInt) - assert sizeof(BStruct) == sizeof(BInt) * 3 - fields = [(name, fld.offset, fld.flags) for (name, fld) in BStruct.fields] - assert fields == [ - ('b1', 0 * sizeof(BInt), 0), - ('a1', 1 * sizeof(BInt), 0), - ('a2', 1 * sizeof(BInt), 1), - ('b2', 2 * sizeof(BInt), 0), - ] - -def test_sizeof_union(): - # a union has the largest alignment of its members, and a total size - # that is the largest of its items *possibly further aligned* if - # another smaller item has a larger alignment... - BChar = new_primitive_type("char") - BShort = new_primitive_type("short") - assert sizeof(BShort) == alignof(BShort) == 2 - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('a1', BChar), - ('a2', BChar), - ('a3', BChar)]) - assert sizeof(BStruct) == 3 and alignof(BStruct) == 1 - BUnion = new_union_type("union u") - complete_struct_or_union(BUnion, [('s', BStruct), - ('i', BShort)]) - assert sizeof(BUnion) == 4 - assert alignof(BUnion) == 2 - -def test_unaligned_struct(): - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('b', BInt, -1, 1)], - None, 5, 1) - -def test_CData_CType(): - CData, CType = _get_types() - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - nullchr = cast(BChar, 0) - chrref = newp(BCharP, None) - assert isinstance(nullchr, CData) - assert isinstance(chrref, CData) - assert not isinstance(BChar, CData) - assert not isinstance(nullchr, CType) - assert not isinstance(chrref, CType) - assert isinstance(BChar, CType) - -def test_no_cdata_float(): - BInt = new_primitive_type("int") - BIntP = new_pointer_type(BInt) - BUInt = new_primitive_type("unsigned int") - BUIntP = new_pointer_type(BUInt) - BFloat = new_primitive_type("float") - py.test.raises(TypeError, newp, BIntP, cast(BFloat, 0.0)) - py.test.raises(TypeError, newp, BUIntP, cast(BFloat, 0.0)) - -def test_bool(): - BBool = new_primitive_type("_Bool") - BBoolP = new_pointer_type(BBool) - assert int(cast(BBool, False)) == 0 - assert int(cast(BBool, True)) == 1 - assert bool(cast(BBool, False)) is False # since 1.7 - assert bool(cast(BBool, True)) is True - assert int(cast(BBool, 3)) == 1 - assert int(cast(BBool, long(3))) == 1 - assert int(cast(BBool, long(10)**4000)) == 1 - assert int(cast(BBool, -0.1)) == 1 - assert int(cast(BBool, -0.0)) == 0 - assert int(cast(BBool, '\x00')) == 0 - assert int(cast(BBool, '\xff')) == 1 - assert newp(BBoolP, False)[0] == 0 - assert newp(BBoolP, True)[0] == 1 - assert newp(BBoolP, 0)[0] == 0 - assert newp(BBoolP, 1)[0] == 1 - py.test.raises(TypeError, newp, BBoolP, 1.0) - py.test.raises(TypeError, newp, BBoolP, '\x00') - py.test.raises(OverflowError, newp, BBoolP, 2) - py.test.raises(OverflowError, newp, BBoolP, -1) - BCharP = new_pointer_type(new_primitive_type("char")) - p = newp(BCharP, b'\x01') - q = cast(BBoolP, p) - assert q[0] is True - p = newp(BCharP, b'\x00') - q = cast(BBoolP, p) - assert q[0] is False - py.test.raises(TypeError, string, cast(BBool, False)) - BDouble = new_primitive_type("double") - assert int(cast(BBool, cast(BDouble, 0.1))) == 1 - assert int(cast(BBool, cast(BDouble, 0.0))) == 0 - BBoolA = new_array_type(BBoolP, None) - p = newp(BBoolA, b'\x01\x00') - assert p[0] is True - assert p[1] is False - -def test_bool_forbidden_cases(): - BBool = new_primitive_type("_Bool") - BBoolP = new_pointer_type(BBool) - BBoolA = new_array_type(BBoolP, None) - BCharP = new_pointer_type(new_primitive_type("char")) - p = newp(BCharP, b'X') - q = cast(BBoolP, p) - with pytest.raises(ValueError): - q[0] - py.test.raises(TypeError, newp, BBoolP, b'\x00') - assert newp(BBoolP, 0)[0] is False - assert newp(BBoolP, 1)[0] is True - py.test.raises(OverflowError, newp, BBoolP, 2) - py.test.raises(OverflowError, newp, BBoolP, -1) - py.test.raises(ValueError, newp, BBoolA, b'\x00\x01\x02') - py.test.raises(OverflowError, newp, BBoolA, [0, 1, 2]) - py.test.raises(TypeError, string, newp(BBoolP, 1)) - py.test.raises(TypeError, string, newp(BBoolA, [1])) - -def test_typeoffsetof(): - BChar = new_primitive_type("char") - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BChar, -1), - ('a2', BChar, -1), - ('a3', BChar, -1)]) - py.test.raises(TypeError, typeoffsetof, BStructPtr, None) - py.test.raises(TypeError, typeoffsetof, BStruct, None) - assert typeoffsetof(BStructPtr, 'a1') == (BChar, 0) - assert typeoffsetof(BStruct, 'a1') == (BChar, 0) - assert typeoffsetof(BStructPtr, 'a2') == (BChar, 1) - assert typeoffsetof(BStruct, 'a3') == (BChar, 2) - assert typeoffsetof(BStructPtr, 'a2', 0) == (BChar, 1) - assert typeoffsetof(BStruct, u+'a3') == (BChar, 2) - py.test.raises(TypeError, typeoffsetof, BStructPtr, 'a2', 1) - py.test.raises(KeyError, typeoffsetof, BStructPtr, 'a4') - py.test.raises(KeyError, typeoffsetof, BStruct, 'a5') - py.test.raises(TypeError, typeoffsetof, BStruct, 42) - py.test.raises(TypeError, typeoffsetof, BChar, 'a1') - -def test_typeoffsetof_array(): - BInt = new_primitive_type("int") - BIntP = new_pointer_type(BInt) - BArray = new_array_type(BIntP, None) - py.test.raises(TypeError, typeoffsetof, BArray, None) - py.test.raises(TypeError, typeoffsetof, BArray, 'a1') - assert typeoffsetof(BArray, 51) == (BInt, 51 * size_of_int()) - assert typeoffsetof(BIntP, 51) == (BInt, 51 * size_of_int()) - assert typeoffsetof(BArray, -51) == (BInt, -51 * size_of_int()) - MAX = sys.maxsize // size_of_int() - assert typeoffsetof(BArray, MAX) == (BInt, MAX * size_of_int()) - assert typeoffsetof(BIntP, MAX) == (BInt, MAX * size_of_int()) - py.test.raises(OverflowError, typeoffsetof, BArray, MAX + 1) - -def test_typeoffsetof_no_bitfield(): - BInt = new_primitive_type("int") - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('a1', BInt, 4)]) - py.test.raises(TypeError, typeoffsetof, BStruct, 'a1') - -def test_rawaddressof(): - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BStruct = new_struct_type("struct foo") - BStructPtr = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('a1', BChar, -1), - ('a2', BChar, -1), - ('a3', BChar, -1)]) - p = newp(BStructPtr) - assert repr(p) == "<cdata 'struct foo *' owning 3 bytes>" - s = p[0] - assert repr(s) == "<cdata 'struct foo' owning 3 bytes>" - a = rawaddressof(BStructPtr, s, 0) - assert repr(a).startswith("<cdata 'struct foo *' 0x") - py.test.raises(TypeError, rawaddressof, BStruct, s, 0) - b = rawaddressof(BCharP, s, 0) - assert b == cast(BCharP, p) - c = rawaddressof(BStructPtr, a, 0) - assert c == a - py.test.raises(TypeError, rawaddressof, BStructPtr, cast(BChar, '?'), 0) - # - d = rawaddressof(BCharP, s, 1) - assert d == cast(BCharP, p) + 1 - # - e = cast(BCharP, 109238) - f = rawaddressof(BCharP, e, 42) - assert f == e + 42 - # - BCharA = new_array_type(BCharP, None) - e = newp(BCharA, 50) - f = rawaddressof(BCharP, e, 42) - assert f == e + 42 - -def test_newp_signed_unsigned_char(): - BCharArray = new_array_type( - new_pointer_type(new_primitive_type("char")), None) - p = newp(BCharArray, b"foo") - assert len(p) == 4 - assert list(p) == [b"f", b"o", b"o", b"\x00"] - # - BUCharArray = new_array_type( - new_pointer_type(new_primitive_type("unsigned char")), None) - p = newp(BUCharArray, b"fo\xff") - assert len(p) == 4 - assert list(p) == [ord("f"), ord("o"), 0xff, 0] - # - BSCharArray = new_array_type( - new_pointer_type(new_primitive_type("signed char")), None) - p = newp(BSCharArray, b"fo\xff") - assert len(p) == 4 - assert list(p) == [ord("f"), ord("o"), -1, 0] - -def test_newp_from_bytearray_doesnt_work(): - BCharArray = new_array_type( - new_pointer_type(new_primitive_type("char")), None) - py.test.raises(TypeError, newp, BCharArray, bytearray(b"foo")) - p = newp(BCharArray, 5) - buffer(p)[:] = bytearray(b"foo.\x00") - assert len(p) == 5 - assert list(p) == [b"f", b"o", b"o", b".", b"\x00"] - p[1:3] = bytearray(b"XY") - assert list(p) == [b"f", b"X", b"Y", b".", b"\x00"] - -def test_string_assignment_to_byte_array(): - BByteArray = new_array_type( - new_pointer_type(new_primitive_type("unsigned char")), None) - p = newp(BByteArray, 5) - p[0:3] = bytearray(b"XYZ") - assert list(p) == [ord("X"), ord("Y"), ord("Z"), 0, 0] - -# XXX hack -if sys.version_info >= (3,): - try: - import posix, io - posix.fdopen = io.open - except ImportError: - pass # win32 - -def test_FILE(): - if sys.platform == "win32": - py.test.skip("testing FILE not implemented") - # - BFILE = new_struct_type("struct _IO_FILE") - BFILEP = new_pointer_type(BFILE) - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BInt = new_primitive_type("int") - BFunc = new_function_type((BCharP, BFILEP), BInt, False) - BFunc2 = new_function_type((BFILEP, BCharP), BInt, True) - ll = find_and_load_library('c') - fputs = ll.load_function(BFunc, "fputs") - fscanf = ll.load_function(BFunc2, "fscanf") - # - import posix - fdr, fdw = posix.pipe() - fr1 = posix.fdopen(fdr, 'rb', 256) - fw1 = posix.fdopen(fdw, 'wb', 256) - # - fw1.write(b"X") - res = fputs(b"hello world\n", fw1) - assert res >= 0 - fw1.flush() # should not be needed - # - p = newp(new_array_type(BCharP, 100), None) - res = fscanf(fr1, b"%s\n", p) - assert res == 1 - assert string(p) == b"Xhello" - fr1.close() - fw1.close() - -def test_FILE_only_for_FILE_arg(): - if sys.platform == "win32": - py.test.skip("testing FILE not implemented") - # - B_NOT_FILE = new_struct_type("struct NOT_FILE") - B_NOT_FILEP = new_pointer_type(B_NOT_FILE) - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BInt = new_primitive_type("int") - BFunc = new_function_type((BCharP, B_NOT_FILEP), BInt, False) - ll = find_and_load_library('c') - fputs = ll.load_function(BFunc, "fputs") - # - import posix - fdr, fdw = posix.pipe() - fr1 = posix.fdopen(fdr, 'r') - fw1 = posix.fdopen(fdw, 'w') - # - e = py.test.raises(TypeError, fputs, b"hello world\n", fw1) - assert str(e.value).startswith( - "initializer for ctype 'struct NOT_FILE *' must " - "be a cdata pointer, not ") - -def test_FILE_object(): - if sys.platform == "win32": - py.test.skip("testing FILE not implemented") - # - BFILE = new_struct_type("FILE") - BFILEP = new_pointer_type(BFILE) - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BInt = new_primitive_type("int") - BFunc = new_function_type((BCharP, BFILEP), BInt, False) - BFunc2 = new_function_type((BFILEP,), BInt, False) - ll = find_and_load_library('c') - fputs = ll.load_function(BFunc, "fputs") - fileno = ll.load_function(BFunc2, "fileno") - # - import posix - fdr, fdw = posix.pipe() - fw1 = posix.fdopen(fdw, 'wb', 256) - # - fw1p = cast(BFILEP, fw1) - fw1.write(b"X") - fw1.flush() - res = fputs(b"hello\n", fw1p) - assert res >= 0 - res = fileno(fw1p) - assert (res == fdw) == (sys.version_info < (3,)) - fw1.close() - # - data = posix.read(fdr, 256) - assert data == b"Xhello\n" - posix.close(fdr) - -def test_errno_saved(): - set_errno(42) - # a random function that will reset errno to 0 (at least on non-windows) - import os; os.stat('.') - # - res = get_errno() - assert res == 42 - -def test_GetLastError(): - if sys.platform != "win32": - py.test.skip("GetLastError(): only for Windows") - # - lib = find_and_load_library('KERNEL32.DLL') - BInt = new_primitive_type("int") - BVoid = new_void_type() - BFunc1 = new_function_type((BInt,), BVoid, False) - BFunc2 = new_function_type((), BInt, False) - SetLastError = lib.load_function(BFunc1, "SetLastError") - GetLastError = lib.load_function(BFunc2, "GetLastError") - # - SetLastError(42) - # a random function that will reset the real GetLastError() to 0 - import nt; nt.stat('.') - # - res = GetLastError() - assert res == 42 - # - SetLastError(2) - code, message = getwinerror() - assert code == 2 - assert message == "The system cannot find the file specified" - # - code, message = getwinerror(1155) - assert code == 1155 - assert message == ("No application is associated with the " - "specified file for this operation") - -def test_nonstandard_integer_types(): - for typename in ['int8_t', 'uint8_t', 'int16_t', 'uint16_t', 'int32_t', - 'uint32_t', 'int64_t', 'uint64_t', 'intptr_t', - 'uintptr_t', 'ptrdiff_t', 'size_t', 'ssize_t', - 'int_least8_t', 'uint_least8_t', - 'int_least16_t', 'uint_least16_t', - 'int_least32_t', 'uint_least32_t', - 'int_least64_t', 'uint_least64_t', - 'int_fast8_t', 'uint_fast8_t', - 'int_fast16_t', 'uint_fast16_t', - 'int_fast32_t', 'uint_fast32_t', - 'int_fast64_t', 'uint_fast64_t', - 'intmax_t', 'uintmax_t']: - new_primitive_type(typename) # works - -def test_cannot_convert_unicode_to_charp(): - BCharP = new_pointer_type(new_primitive_type("char")) - BCharArray = new_array_type(BCharP, None) - py.test.raises(TypeError, newp, BCharArray, u+'foobar') - -def test_buffer_keepalive(): - BCharP = new_pointer_type(new_primitive_type("char")) - BCharArray = new_array_type(BCharP, None) - buflist = [] - for i in range(20): - c = newp(BCharArray, str2bytes("hi there %d" % i)) - buflist.append(buffer(c)) - import gc; gc.collect() - for i in range(20): - buf = buflist[i] - assert buf[:] == str2bytes("hi there %d\x00" % i) - -def test_slice(): - BIntP = new_pointer_type(new_primitive_type("int")) - BIntArray = new_array_type(BIntP, None) - c = newp(BIntArray, 5) - assert len(c) == 5 - assert repr(c) == "<cdata 'int[]' owning 20 bytes>" - d = c[1:4] - assert len(d) == 3 - assert repr(d) == "<cdata 'int[]' sliced length 3>" - d[0] = 123 - d[2] = 456 - assert c[1] == 123 - assert c[3] == 456 - assert d[2] == 456 - with pytest.raises(IndexError): - d[3] - with pytest.raises(IndexError): - d[-1] - -def test_slice_ptr(): - BIntP = new_pointer_type(new_primitive_type("int")) - BIntArray = new_array_type(BIntP, None) - c = newp(BIntArray, 5) - d = (c+1)[0:2] - assert len(d) == 2 - assert repr(d) == "<cdata 'int[]' sliced length 2>" - d[1] += 50 - assert c[2] == 50 - -def test_slice_array_checkbounds(): - BIntP = new_pointer_type(new_primitive_type("int")) - BIntArray = new_array_type(BIntP, None) - c = newp(BIntArray, 5) - c[0:5] - assert len(c[5:5]) == 0 - with pytest.raises(IndexError): - c[-1:1] - cp = c + 0 - cp[-1:1] - -def test_nonstandard_slice(): - BIntP = new_pointer_type(new_primitive_type("int")) - BIntArray = new_array_type(BIntP, None) - c = newp(BIntArray, 5) - with pytest.raises(IndexError) as e: - c[:5] - assert str(e.value) == "slice start must be specified" - with pytest.raises(IndexError) as e: - c[4:] - assert str(e.value) == "slice stop must be specified" - with pytest.raises(IndexError) as e: - c[1:2:3] - assert str(e.value) == "slice with step not supported" - with pytest.raises(IndexError) as e: - c[1:2:1] - assert str(e.value) == "slice with step not supported" - with pytest.raises(IndexError) as e: - c[4:2] - assert str(e.value) == "slice start > stop" - with pytest.raises(IndexError) as e: - c[6:6] - assert str(e.value) == "index too large (expected 6 <= 5)" - -def test_setslice(): - BIntP = new_pointer_type(new_primitive_type("int")) - BIntArray = new_array_type(BIntP, None) - c = newp(BIntArray, 5) - c[1:3] = [100, 200] - assert list(c) == [0, 100, 200, 0, 0] - cp = c + 3 - cp[-1:1] = [300, 400] - assert list(c) == [0, 100, 300, 400, 0] - cp[-1:1] = iter([500, 600]) - assert list(c) == [0, 100, 500, 600, 0] - with pytest.raises(ValueError): - cp[-1:1] = [1000] - assert list(c) == [0, 100, 1000, 600, 0] - with pytest.raises(ValueError): - cp[-1:1] = (700, 800, 900) - assert list(c) == [0, 100, 700, 800, 0] - -def test_setslice_array(): - BIntP = new_pointer_type(new_primitive_type("int")) - BIntArray = new_array_type(BIntP, None) - c = newp(BIntArray, 5) - d = newp(BIntArray, [10, 20, 30]) - c[1:4] = d - assert list(c) == [0, 10, 20, 30, 0] - # - BShortP = new_pointer_type(new_primitive_type("short")) - BShortArray = new_array_type(BShortP, None) - d = newp(BShortArray, [40, 50]) - c[1:3] = d - assert list(c) == [0, 40, 50, 30, 0] - -def test_cdata_name_module_doc(): - p = new_primitive_type("signed char") - x = cast(p, 17) - assert x.__module__ == '_cffi_backend' - assert x.__name__ == '<cdata>' - assert hasattr(x, '__doc__') - -def test_different_types_of_ptr_equality(): - BVoidP = new_pointer_type(new_void_type()) - BIntP = new_pointer_type(new_primitive_type("int")) - x = cast(BVoidP, 12345) - assert x == cast(BIntP, 12345) - assert x != cast(BIntP, 12344) - assert hash(x) == hash(cast(BIntP, 12345)) - -def test_new_handle(): - import _weakref - BVoidP = new_pointer_type(new_void_type()) - BCharP = new_pointer_type(new_primitive_type("char")) - class mylist(list): - pass - o = mylist([2, 3, 4]) - x = newp_handle(BVoidP, o) - assert repr(x) == "<cdata 'void *' handle to [2, 3, 4]>" - assert x - assert from_handle(x) is o - assert from_handle(cast(BCharP, x)) is o - wr = _weakref.ref(o) - del o - import gc; gc.collect() - assert wr() is not None - assert from_handle(x) == list((2, 3, 4)) - assert from_handle(cast(BCharP, x)) == list((2, 3, 4)) - del x - for i in range(3): - if wr() is not None: - import gc; gc.collect() - assert wr() is None - py.test.raises(RuntimeError, from_handle, cast(BCharP, 0)) - -def test_new_handle_cycle(): - import _weakref - BVoidP = new_pointer_type(new_void_type()) - class A(object): - pass - o = A() - o.cycle = newp_handle(BVoidP, o) - wr = _weakref.ref(o) - del o - for i in range(3): - if wr() is not None: - import gc; gc.collect() - assert wr() is None - -def _test_bitfield_details(flag): - BChar = new_primitive_type("char") - BShort = new_primitive_type("short") - BInt = new_primitive_type("int") - BUInt = new_primitive_type("unsigned int") - BStruct = new_struct_type("struct foo1") - complete_struct_or_union(BStruct, [('a', BChar, -1), - ('b1', BInt, 9), - ('b2', BUInt, 7), - ('c', BChar, -1)], -1, -1, -1, flag) - if not (flag & SF_MSVC_BITFIELDS): # gcc, any variant - assert typeoffsetof(BStruct, 'c') == (BChar, 3) - assert sizeof(BStruct) == 4 - else: # msvc - assert typeoffsetof(BStruct, 'c') == (BChar, 8) - assert sizeof(BStruct) == 12 - assert alignof(BStruct) == 4 - # - p = newp(new_pointer_type(BStruct), None) - p.a = b'A' - p.b1 = -201 - p.b2 = 99 - p.c = b'\x9D' - raw = buffer(p)[:] - if sys.byteorder == 'little': - if flag & SF_MSVC_BITFIELDS: - assert raw == b'A\x00\x00\x007\xC7\x00\x00\x9D\x00\x00\x00' - elif flag & SF_GCC_LITTLE_ENDIAN: - assert raw == b'A7\xC7\x9D' - elif flag & SF_GCC_BIG_ENDIAN: - assert raw == b'A\xE3\x9B\x9D' - else: - raise AssertionError("bad flag") - else: - if flag & SF_MSVC_BITFIELDS: - assert raw == b'A\x00\x00\x00\x00\x00\xC77\x9D\x00\x00\x00' - elif flag & SF_GCC_LITTLE_ENDIAN: - assert raw == b'A\xC77\x9D' - elif flag & SF_GCC_BIG_ENDIAN: - assert raw == b'A\x9B\xE3\x9D' - else: - raise AssertionError("bad flag") - # - BStruct = new_struct_type("struct foo2") - complete_struct_or_union(BStruct, [('a', BChar, -1), - ('', BShort, 9), - ('c', BChar, -1)], -1, -1, -1, flag) - assert typeoffsetof(BStruct, 'c') == (BChar, 4) - if flag & SF_MSVC_BITFIELDS: - assert sizeof(BStruct) == 6 - assert alignof(BStruct) == 2 - elif flag & SF_GCC_X86_BITFIELDS: - assert sizeof(BStruct) == 5 - assert alignof(BStruct) == 1 - elif flag & SF_GCC_ARM_BITFIELDS: - assert sizeof(BStruct) == 6 - assert alignof(BStruct) == 2 - else: - raise AssertionError("bad flag") - # - BStruct = new_struct_type("struct foo2") - complete_struct_or_union(BStruct, [('a', BChar, -1), - ('', BInt, 0), - ('', BInt, 0), - ('c', BChar, -1)], -1, -1, -1, flag) - if flag & SF_MSVC_BITFIELDS: - assert typeoffsetof(BStruct, 'c') == (BChar, 1) - assert sizeof(BStruct) == 2 - assert alignof(BStruct) == 1 - elif flag & SF_GCC_X86_BITFIELDS: - assert typeoffsetof(BStruct, 'c') == (BChar, 4) - assert sizeof(BStruct) == 5 - assert alignof(BStruct) == 1 - elif flag & SF_GCC_ARM_BITFIELDS: - assert typeoffsetof(BStruct, 'c') == (BChar, 4) - assert sizeof(BStruct) == 8 - assert alignof(BStruct) == 4 - else: - raise AssertionError("bad flag") - - -SF_MSVC_BITFIELDS = 0x01 -SF_GCC_ARM_BITFIELDS = 0x02 -SF_GCC_X86_BITFIELDS = 0x10 - -SF_GCC_BIG_ENDIAN = 0x04 -SF_GCC_LITTLE_ENDIAN = 0x40 - -SF_PACKED = 0x08 - -def test_bitfield_as_x86_gcc(): - _test_bitfield_details(flag=SF_GCC_X86_BITFIELDS|SF_GCC_LITTLE_ENDIAN) - -def test_bitfield_as_msvc(): - _test_bitfield_details(flag=SF_MSVC_BITFIELDS|SF_GCC_LITTLE_ENDIAN) - -def test_bitfield_as_arm_gcc(): - _test_bitfield_details(flag=SF_GCC_ARM_BITFIELDS|SF_GCC_LITTLE_ENDIAN) - -def test_bitfield_as_ppc_gcc(): - # PowerPC uses the same format as X86, but is big-endian - _test_bitfield_details(flag=SF_GCC_X86_BITFIELDS|SF_GCC_BIG_ENDIAN) - - -def test_struct_array_no_length(): - BInt = new_primitive_type("int") - BIntP = new_pointer_type(BInt) - BArray = new_array_type(BIntP, None) - BStruct = new_struct_type("foo") - py.test.raises(TypeError, complete_struct_or_union, - BStruct, [('x', BArray), - ('y', BInt)]) - # - BStruct = new_struct_type("foo") - complete_struct_or_union(BStruct, [('x', BInt), - ('y', BArray)]) - assert sizeof(BStruct) == size_of_int() - d = BStruct.fields - assert len(d) == 2 - assert d[0][0] == 'x' - assert d[0][1].type is BInt - assert d[0][1].offset == 0 - assert d[0][1].bitshift == -1 - assert d[0][1].bitsize == -1 - assert d[1][0] == 'y' - assert d[1][1].type is BArray - assert d[1][1].offset == size_of_int() - assert d[1][1].bitshift == -2 - assert d[1][1].bitsize == -1 - # - p = newp(new_pointer_type(BStruct)) - p.x = 42 - assert p.x == 42 - assert typeof(p.y) is BArray - assert len(p.y) == 0 - assert p.y == cast(BIntP, p) + 1 - # - p = newp(new_pointer_type(BStruct), [100]) - assert p.x == 100 - assert len(p.y) == 0 - # - # Tests for - # ffi.new("struct_with_var_array *", [field.., [the_array_items..]]) - # ffi.new("struct_with_var_array *", [field.., array_size]) - plist = [] - for i in range(20): - if i % 2 == 0: - p = newp(new_pointer_type(BStruct), [100, [200, i, 400]]) - else: - p = newp(new_pointer_type(BStruct), [100, 3]) - p.y[1] = i - p.y[0] = 200 - assert p.y[2] == 0 - p.y[2] = 400 - assert len(p.y) == 3 - assert len(p[0].y) == 3 - assert len(buffer(p)) == sizeof(BInt) * 4 - assert sizeof(p[0]) == sizeof(BInt) * 4 - plist.append(p) - for i in range(20): - p = plist[i] - assert p.x == 100 - assert p.y[0] == 200 - assert p.y[1] == i - assert p.y[2] == 400 - assert list(p.y) == [200, i, 400] - # - # the following assignment works, as it normally would, for any array field - p.y = [501, 601] - assert list(p.y) == [501, 601, 400] - p[0].y = [500, 600] - assert list(p[0].y) == [500, 600, 400] - assert repr(p) == "<cdata 'foo *' owning %d bytes>" % ( - sizeof(BStruct) + 3 * sizeof(BInt),) - assert repr(p[0]) == "<cdata 'foo' owning %d bytes>" % ( - sizeof(BStruct) + 3 * sizeof(BInt),) - assert sizeof(p[0]) == sizeof(BStruct) + 3 * sizeof(BInt) - # - # from a non-owning pointer, we can't get the length - q = cast(new_pointer_type(BStruct), p) - assert q.y[0] == 500 - assert q[0].y[0] == 500 - py.test.raises(TypeError, len, q.y) - py.test.raises(TypeError, len, q[0].y) - assert typeof(q.y) is BIntP - assert typeof(q[0].y) is BIntP - assert sizeof(q[0]) == sizeof(BStruct) - # - # error cases - with pytest.raises(IndexError): - p.y[4] - with pytest.raises(TypeError): - p.y = cast(BIntP, 0) - with pytest.raises(TypeError): - p.y = 15 - with pytest.raises(TypeError): - p.y = None - # - # accepting this may be specified by the C99 standard, - # or a GCC strangeness... - BStruct2 = new_struct_type("bar") - complete_struct_or_union(BStruct2, [('f', BStruct), - ('n', BInt)]) - p = newp(new_pointer_type(BStruct2), {'n': 42}) - assert p.n == 42 - # - # more error cases - py.test.raises(TypeError, newp, new_pointer_type(BStruct), [100, None]) - BArray4 = new_array_type(BIntP, 4) - BStruct4 = new_struct_type("test4") - complete_struct_or_union(BStruct4, [('a', BArray4)]) # not varsized - py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [None]) - py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [4]) - p = newp(new_pointer_type(BStruct4), [[10, 20, 30]]) - assert p.a[0] == 10 - assert p.a[1] == 20 - assert p.a[2] == 30 - assert p.a[3] == 0 - # - # struct of struct of varsized array - BStruct2 = new_struct_type("bar") - complete_struct_or_union(BStruct2, [('head', BInt), - ('tail', BStruct)]) - for i in range(2): # try to detect heap overwrites - p = newp(new_pointer_type(BStruct2), [100, [200, list(range(50))]]) - assert p.tail.y[49] == 49 - - -def test_struct_array_no_length_explicit_position(): - BInt = new_primitive_type("int") - BIntP = new_pointer_type(BInt) - BArray = new_array_type(BIntP, None) - BStruct = new_struct_type("foo") - complete_struct_or_union(BStruct, [('x', BArray, -1, 0), # actually 3 items - ('y', BInt, -1, 12)]) - p = newp(new_pointer_type(BStruct), [[10, 20], 30]) - assert p.x[0] == 10 - assert p.x[1] == 20 - assert p.x[2] == 0 - assert p.y == 30 - p = newp(new_pointer_type(BStruct), {'x': [40], 'y': 50}) - assert p.x[0] == 40 - assert p.x[1] == 0 - assert p.x[2] == 0 - assert p.y == 50 - p = newp(new_pointer_type(BStruct), {'y': 60}) - assert p.x[0] == 0 - assert p.x[1] == 0 - assert p.x[2] == 0 - assert p.y == 60 - # - # This "should" work too, allocating a larger structure - # (a bit strange in this case, but useful in general) - plist = [] - for i in range(20): - p = newp(new_pointer_type(BStruct), [[10, 20, 30, 40, 50, 60, 70]]) - plist.append(p) - for i in range(20): - p = plist[i] - assert p.x[0] == 10 - assert p.x[1] == 20 - assert p.x[2] == 30 - assert p.x[3] == 40 == p.y - assert p.x[4] == 50 - assert p.x[5] == 60 - assert p.x[6] == 70 - -def test_struct_array_not_aligned(): - # struct a { int x; char y; char z[]; }; - # ends up of size 8, but 'z' is at offset 5 - BChar = new_primitive_type("char") - BInt = new_primitive_type("int") - BCharP = new_pointer_type(BChar) - BArray = new_array_type(BCharP, None) - BStruct = new_struct_type("foo") - complete_struct_or_union(BStruct, [('x', BInt), - ('y', BChar), - ('z', BArray)]) - assert sizeof(BStruct) == 2 * size_of_int() - def offsetof(BType, fieldname): - return typeoffsetof(BType, fieldname)[1] - base = offsetof(BStruct, 'z') - assert base == size_of_int() + 1 - # - p = newp(new_pointer_type(BStruct), {'z': 3}) - assert sizeof(p[0]) == base + 3 - q = newp(new_pointer_type(BStruct), {'z': size_of_int()}) - assert sizeof(q) == size_of_ptr() - assert sizeof(q[0]) == base + size_of_int() - assert len(p.z) == 3 - assert len(p[0].z) == 3 - assert len(q.z) == size_of_int() - assert len(q[0].z) == size_of_int() - -def test_ass_slice(): - BChar = new_primitive_type("char") - BArray = new_array_type(new_pointer_type(BChar), None) - p = newp(BArray, b"foobar") - p[2:5] = [b"*", b"Z", b"T"] - p[1:3] = b"XY" - assert list(p) == [b"f", b"X", b"Y", b"Z", b"T", b"r", b"\x00"] - with pytest.raises(TypeError): - p[1:5] = u+'XYZT' - with pytest.raises(TypeError): - p[1:5] = [1, 2, 3, 4] - # - for typename in ["wchar_t", "char16_t", "char32_t"]: - BUniChar = new_primitive_type(typename) - BArray = new_array_type(new_pointer_type(BUniChar), None) - p = newp(BArray, u+"foobar") - p[2:5] = [u+"*", u+"Z", u+"T"] - p[1:3] = u+"XY" - assert list(p) == [u+"f", u+"X", u+"Y", u+"Z", u+"T", u+"r", u+"\x00"] - with pytest.raises(TypeError): - p[1:5] = b'XYZT' - with pytest.raises(TypeError): - p[1:5] = [1, 2, 3, 4] - -def test_void_p_arithmetic(): - BVoid = new_void_type() - BInt = new_primitive_type("intptr_t") - p = cast(new_pointer_type(BVoid), 100000) - assert int(cast(BInt, p)) == 100000 - assert int(cast(BInt, p + 42)) == 100042 - assert int(cast(BInt, p - (-42))) == 100042 - assert (p + 42) - p == 42 - q = cast(new_pointer_type(new_primitive_type("char")), 100000) - with pytest.raises(TypeError): - p - q - with pytest.raises(TypeError): - q - p - with pytest.raises(TypeError): - p + cast(new_primitive_type('int'), 42) - with pytest.raises(TypeError): - p - cast(new_primitive_type('int'), 42) - -def test_sizeof_sliced_array(): - BInt = new_primitive_type("int") - BArray = new_array_type(new_pointer_type(BInt), 10) - p = newp(BArray, None) - assert sizeof(p[2:9]) == 7 * sizeof(BInt) - -def test_packed(): - BLong = new_primitive_type("long") - BChar = new_primitive_type("char") - BShort = new_primitive_type("short") - for extra_args in [(SF_PACKED,), (0, 1)]: - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('a1', BLong, -1), - ('a2', BChar, -1), - ('a3', BShort, -1)], - None, -1, -1, *extra_args) - d = BStruct.fields - assert len(d) == 3 - assert d[0][0] == 'a1' - assert d[0][1].type is BLong - assert d[0][1].offset == 0 - assert d[0][1].bitshift == -1 - assert d[0][1].bitsize == -1 - assert d[1][0] == 'a2' - assert d[1][1].type is BChar - assert d[1][1].offset == sizeof(BLong) - assert d[1][1].bitshift == -1 - assert d[1][1].bitsize == -1 - assert d[2][0] == 'a3' - assert d[2][1].type is BShort - assert d[2][1].offset == sizeof(BLong) + sizeof(BChar) - assert d[2][1].bitshift == -1 - assert d[2][1].bitsize == -1 - assert sizeof(BStruct) == sizeof(BLong) + sizeof(BChar) + sizeof(BShort) - assert alignof(BStruct) == 1 - # - BStruct2 = new_struct_type("struct foo") - complete_struct_or_union(BStruct2, [('b1', BChar, -1), - ('b2', BLong, -1)], - None, -1, -1, 0, 2) - d = BStruct2.fields - assert len(d) == 2 - assert d[0][0] == 'b1' - assert d[0][1].type is BChar - assert d[0][1].offset == 0 - assert d[0][1].bitshift == -1 - assert d[0][1].bitsize == -1 - assert d[1][0] == 'b2' - assert d[1][1].type is BLong - assert d[1][1].offset == 2 - assert d[1][1].bitshift == -1 - assert d[1][1].bitsize == -1 - assert sizeof(BStruct2) == 2 + sizeof(BLong) - assert alignof(BStruct2) == 2 - -def test_packed_with_bitfields(): - if sys.platform == "win32": - py.test.skip("testing gcc behavior") - BLong = new_primitive_type("long") - BChar = new_primitive_type("char") - BStruct = new_struct_type("struct foo") - py.test.raises(NotImplementedError, - complete_struct_or_union, - BStruct, [('a1', BLong, 30), - ('a2', BChar, 5)], - None, -1, -1, SF_PACKED) - -def test_from_buffer(): - import array - a = array.array('H', [10000, 20000, 30000]) - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - c = from_buffer(BCharA, a) - assert typeof(c) is BCharA - assert len(c) == 6 - assert repr(c) == "<cdata 'char[]' buffer len 6 from 'array.array' object>" - p = new_pointer_type(new_primitive_type("unsigned short")) - cast(p, c)[1] += 500 - assert list(a) == [10000, 20500, 30000] - -def test_from_buffer_not_str_unicode(): - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - p1 = from_buffer(BCharA, b"foo") - assert p1 == from_buffer(BCharA, b"foo") - import gc; gc.collect() - assert p1 == from_buffer(BCharA, b"foo") - py.test.raises(TypeError, from_buffer, BCharA, u+"foo") - try: - from __builtin__ import buffer - except ImportError: - pass - else: - # Python 2 only - contents = from_buffer(BCharA, buffer(b"foo")) - assert len(contents) == len(p1) - for i in range(len(contents)): - assert contents[i] == p1[i] - p4 = buffer(u+"foo") - contents = from_buffer(BCharA, buffer(u+"foo")) - assert len(contents) == len(p4) - for i in range(len(contents)): - assert contents[i] == p4[i] - try: - from __builtin__ import memoryview - except ImportError: - pass - else: - contents = from_buffer(BCharA, memoryview(b"foo")) - assert len(contents) == len(p1) - for i in range(len(contents)): - assert contents[i] == p1[i] - - -def test_from_buffer_bytearray(): - a = bytearray(b"xyz") - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - p = from_buffer(BCharA, a) - assert typeof(p) is BCharA - assert len(p) == 3 - assert repr(p) == "<cdata 'char[]' buffer len 3 from 'bytearray' object>" - assert p[2] == b"z" - p[2] = b"." - assert a[2] == ord(".") - a[2] = ord("?") - assert p[2] == b"?" - -def test_from_buffer_more_cases(): - try: - from _cffi_backend import _testbuff - except ImportError: - py.test.skip("not for pypy") - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - # - def check1(bufobj, expected): - c = from_buffer(BCharA, bufobj) - assert typeof(c) is BCharA - if sys.version_info >= (3,): - expected = [bytes(c, "ascii") for c in expected] - assert list(c) == list(expected) - # - def check(methods, expected, expected_for_memoryview=None): - if sys.version_info >= (3,): - if methods <= 7: - return - if expected_for_memoryview is not None: - expected = expected_for_memoryview - class X(object): - pass - _testbuff(X, methods) - bufobj = X() - check1(bufobj, expected) - try: - from __builtin__ import buffer - bufobjb = buffer(bufobj) - except (TypeError, ImportError): - pass - else: - check1(bufobjb, expected) - try: - bufobjm = memoryview(bufobj) - except (TypeError, NameError): - pass - else: - check1(bufobjm, expected_for_memoryview or expected) - # - check(1, "RDB") - check(2, "WRB") - check(4, "CHB") - check(8, "GTB") - check(16, "ROB") - # - check(1 | 2, "RDB") - check(1 | 4, "RDB") - check(2 | 4, "CHB") - check(1 | 8, "RDB", "GTB") - check(1 | 16, "RDB", "ROB") - check(2 | 8, "WRB", "GTB") - check(2 | 16, "WRB", "ROB") - check(4 | 8, "CHB", "GTB") - check(4 | 16, "CHB", "ROB") - -def test_from_buffer_require_writable(): - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - p1 = from_buffer(BCharA, b"foo", False) - assert p1 == from_buffer(BCharA, b"foo", False) - py.test.raises((TypeError, BufferError), from_buffer, BCharA, b"foo", True) - ba = bytearray(b"foo") - p1 = from_buffer(BCharA, ba, True) - p1[0] = b"g" - assert ba == b"goo" - -def test_from_buffer_types(): - BInt = new_primitive_type("int") - BIntP = new_pointer_type(BInt) - BIntA = new_array_type(BIntP, None) - lst = [-12345678, 87654321, 489148] - bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ') - lst2 = lst + [42, -999999999] - bytestring2 = bytearray(buffer(newp(BIntA, lst2))[:] + b'XYZ') - # - p1 = from_buffer(BIntA, bytestring) # int[] - assert typeof(p1) is BIntA - assert len(p1) == 3 - assert p1[0] == lst[0] - assert p1[1] == lst[1] - assert p1[2] == lst[2] - with pytest.raises(IndexError): - p1[3] - with pytest.raises(IndexError): - p1[-1] - # - py.test.raises(TypeError, from_buffer, BInt, bytestring) - # - p2 = from_buffer(BIntP, bytestring) # int * - assert p2 == p1 or 'PY_DOT_PY' in globals() - # note: on py.py ^^^, bytearray buffers are not emulated well enough - assert typeof(p2) is BIntP - assert p2[0] == lst[0] - assert p2[1] == lst[1] - assert p2[2] == lst[2] - # hopefully does not crash, but doesn't raise an exception: - p2[3] - p2[-1] - # not enough data even for one, but this is not enforced: - from_buffer(BIntP, b"") - # - BIntA2 = new_array_type(BIntP, 2) - p2 = from_buffer(BIntA2, bytestring) # int[2] - assert typeof(p2) is BIntA2 - assert len(p2) == 2 - assert p2[0] == lst[0] - assert p2[1] == lst[1] - with pytest.raises(IndexError): - p2[2] - with pytest.raises(IndexError): - p2[-1] - assert p2 == p1 or 'PY_DOT_PY' in globals() - # - BIntA4 = new_array_type(BIntP, 4) # int[4]: too big - py.test.raises(ValueError, from_buffer, BIntA4, bytestring) - # - BStruct = new_struct_type("foo") - complete_struct_or_union(BStruct, [('a1', BInt, -1), - ('a2', BInt, -1)]) - BStructP = new_pointer_type(BStruct) - BStructA = new_array_type(BStructP, None) - p1 = from_buffer(BStructA, bytestring2) # struct[] - assert len(p1) == 2 - assert typeof(p1) is BStructA - assert p1[0].a1 == lst2[0] - assert p1[0].a2 == lst2[1] - assert p1[1].a1 == lst2[2] - assert p1[1].a2 == lst2[3] - with pytest.raises(IndexError): - p1[2] - with pytest.raises(IndexError): - p1[-1] - assert repr(p1) == "<cdata 'foo[]' buffer len 2 from 'bytearray' object>" - # - p2 = from_buffer(BStructP, bytestring2) # 'struct *' - assert p2 == p1 or 'PY_DOT_PY' in globals() - assert typeof(p2) is BStructP - assert p2.a1 == lst2[0] - assert p2.a2 == lst2[1] - assert p2[0].a1 == lst2[0] - assert p2[0].a2 == lst2[1] - assert p2[1].a1 == lst2[2] - assert p2[1].a2 == lst2[3] - # does not crash: - p2[2] - p2[-1] - # not enough data even for one, but this is not enforced: - from_buffer(BStructP, b"") - from_buffer(BStructP, b"1234567") - # - release(p1) - assert repr(p1) == "<cdata 'foo[]' buffer RELEASED>" - # - BEmptyStruct = new_struct_type("empty") - complete_struct_or_union(BEmptyStruct, [], Ellipsis, 0) - assert sizeof(BEmptyStruct) == 0 - BEmptyStructP = new_pointer_type(BEmptyStruct) - BEmptyStructA = new_array_type(BEmptyStructP, None) - py.test.raises(ZeroDivisionError, from_buffer, # empty[] - BEmptyStructA, bytestring) - # - BEmptyStructA5 = new_array_type(BEmptyStructP, 5) - p1 = from_buffer(BEmptyStructA5, bytestring) # struct empty[5] - assert typeof(p1) is BEmptyStructA5 - assert len(p1) == 5 - assert (cast(BIntP, p1) == from_buffer(BIntA, bytestring) - or 'PY_DOT_PY' in globals()) - # - BVarStruct = new_struct_type("varfoo") - BVarStructP = new_pointer_type(BVarStruct) - complete_struct_or_union(BVarStruct, [('a1', BInt, -1), - ('va', BIntA, -1)]) - with pytest.raises(TypeError): - from_buffer(BVarStruct, bytestring) - pv = from_buffer(BVarStructP, bytestring) # varfoo * - assert pv.a1 == lst[0] - assert pv.va[0] == lst[1] - assert pv.va[1] == lst[2] - assert sizeof(pv[0]) == 1 * size_of_int() - with pytest.raises(TypeError): - len(pv.va) - # hopefully does not crash, but doesn't raise an exception: - pv.va[2] - pv.va[-1] - # not enough data even for one, but this is not enforced: - from_buffer(BVarStructP, b"") - assert repr(pv) == "<cdata 'varfoo *' buffer from 'bytearray' object>" - assert repr(pv[0]).startswith("<cdata 'varfoo &' ") - # - release(pv) - assert repr(pv) == "<cdata 'varfoo *' buffer RELEASED>" - assert repr(pv[0]).startswith("<cdata 'varfoo &' ") - # - pv = from_buffer(BVarStructP, bytestring) # make a fresh one - with pytest.raises(ValueError): - release(pv[0]) - -def test_issue483(): - BInt = new_primitive_type("int") - BIntP = new_pointer_type(BInt) - BIntA = new_array_type(BIntP, None) - lst = list(range(25)) - bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ') - p1 = from_buffer(BIntA, bytestring) # int[] - assert len(buffer(p1)) == 25 * size_of_int() - assert sizeof(p1) == 25 * size_of_int() - # - p2 = from_buffer(BIntP, bytestring) - assert sizeof(p2) == size_of_ptr() - assert len(buffer(p2)) == size_of_int() # first element only, by default - -def test_memmove(): - Short = new_primitive_type("short") - ShortA = new_array_type(new_pointer_type(Short), None) - Char = new_primitive_type("char") - CharA = new_array_type(new_pointer_type(Char), None) - p = newp(ShortA, [-1234, -2345, -3456, -4567, -5678]) - memmove(p, p + 1, 4) - assert list(p) == [-2345, -3456, -3456, -4567, -5678] - p[2] = 999 - memmove(p + 2, p, 6) - assert list(p) == [-2345, -3456, -2345, -3456, 999] - memmove(p + 4, newp(CharA, b"\x71\x72"), 2) - if sys.byteorder == 'little': - assert list(p) == [-2345, -3456, -2345, -3456, 0x7271] - else: - assert list(p) == [-2345, -3456, -2345, -3456, 0x7172] - -def test_memmove_buffer(): - import array - Short = new_primitive_type("short") - ShortA = new_array_type(new_pointer_type(Short), None) - a = array.array('H', [10000, 20000, 30000]) - p = newp(ShortA, 5) - memmove(p, a, 6) - assert list(p) == [10000, 20000, 30000, 0, 0] - memmove(p + 1, a, 6) - assert list(p) == [10000, 10000, 20000, 30000, 0] - b = array.array('h', [-1000, -2000, -3000]) - memmove(b, a, 4) - assert b.tolist() == [10000, 20000, -3000] - assert a.tolist() == [10000, 20000, 30000] - p[0] = 999 - p[1] = 998 - p[2] = 997 - p[3] = 996 - p[4] = 995 - memmove(b, p, 2) - assert b.tolist() == [999, 20000, -3000] - memmove(b, p + 2, 4) - assert b.tolist() == [997, 996, -3000] - p[2] = -p[2] - p[3] = -p[3] - memmove(b, p + 2, 6) - assert b.tolist() == [-997, -996, 995] - -def test_memmove_readonly_readwrite(): - SignedChar = new_primitive_type("signed char") - SignedCharA = new_array_type(new_pointer_type(SignedChar), None) - p = newp(SignedCharA, 5) - memmove(p, b"abcde", 3) - assert list(p) == [ord("a"), ord("b"), ord("c"), 0, 0] - memmove(p, bytearray(b"ABCDE"), 2) - assert list(p) == [ord("A"), ord("B"), ord("c"), 0, 0] - py.test.raises((TypeError, BufferError), memmove, b"abcde", p, 3) - ba = bytearray(b"xxxxx") - memmove(dest=ba, src=p, n=3) - assert ba == bytearray(b"ABcxx") - memmove(ba, b"EFGH", 4) - assert ba == bytearray(b"EFGHx") - -def test_memmove_sign_check(): - SignedChar = new_primitive_type("signed char") - SignedCharA = new_array_type(new_pointer_type(SignedChar), None) - p = newp(SignedCharA, 5) - py.test.raises(ValueError, memmove, p, p + 1, -1) # not segfault - -def test_memmove_bad_cdata(): - BInt = new_primitive_type("int") - p = cast(BInt, 42) - py.test.raises(TypeError, memmove, p, bytearray(b'a'), 1) - py.test.raises(TypeError, memmove, bytearray(b'a'), p, 1) - -def test_dereference_null_ptr(): - BInt = new_primitive_type("int") - BIntPtr = new_pointer_type(BInt) - p = cast(BIntPtr, 0) - with pytest.raises(RuntimeError): - p[0] - with pytest.raises(RuntimeError): - p[0] = 42 - with pytest.raises(RuntimeError): - p[42] - with pytest.raises(RuntimeError): - p[42] = -1 - -def test_mixup(): - BStruct1 = new_struct_type("foo") - BStruct2 = new_struct_type("foo") # <= same name as BStruct1 - BStruct3 = new_struct_type("bar") - BStruct1Ptr = new_pointer_type(BStruct1) - BStruct2Ptr = new_pointer_type(BStruct2) - BStruct3Ptr = new_pointer_type(BStruct3) - BStruct1PtrPtr = new_pointer_type(BStruct1Ptr) - BStruct2PtrPtr = new_pointer_type(BStruct2Ptr) - BStruct3PtrPtr = new_pointer_type(BStruct3Ptr) - pp1 = newp(BStruct1PtrPtr) - pp2 = newp(BStruct2PtrPtr) - pp3 = newp(BStruct3PtrPtr) - pp1[0] = pp1[0] - with pytest.raises(TypeError) as e: - pp3[0] = pp1[0] - assert str(e.value).startswith("initializer for ctype 'bar *' must be a ") - assert str(e.value).endswith(", not cdata 'foo *'") - with pytest.raises(TypeError) as e: - pp2[0] = pp1[0] - assert str(e.value) == ("initializer for ctype 'foo *' appears indeed to " - "be 'foo *', but the types are different (check " - "that you are not e.g. mixing up different ffi " - "instances)") - -def test_stdcall_function_type(): - assert FFI_CDECL == FFI_DEFAULT_ABI - try: - stdcall = FFI_STDCALL - except NameError: - stdcall = FFI_DEFAULT_ABI - BInt = new_primitive_type("int") - BFunc = new_function_type((BInt, BInt), BInt, False, stdcall) - if stdcall != FFI_DEFAULT_ABI: - assert repr(BFunc) == "<ctype 'int(__stdcall *)(int, int)'>" - else: - assert repr(BFunc) == "<ctype 'int(*)(int, int)'>" - -def test_get_common_types(): - d = {} - _get_common_types(d) - assert d['bool'] == '_Bool' - -def test_unpack(): - BChar = new_primitive_type("char") - BArray = new_array_type(new_pointer_type(BChar), 10) # char[10] - p = newp(BArray, b"abc\x00def") - p0 = p - assert unpack(p, 10) == b"abc\x00def\x00\x00\x00" - assert unpack(p+1, 5) == b"bc\x00de" - - for typename in ["wchar_t", "char16_t", "char32_t"]: - BWChar = new_primitive_type(typename) - BArray = new_array_type(new_pointer_type(BWChar), 10) # wchar_t[10] - p = newp(BArray, u"abc\x00def") - assert unpack(p, 10) == u"abc\x00def\x00\x00\x00" - - for typename, samples in [ - ("uint8_t", [0, 2**8-1]), - ("uint16_t", [0, 2**16-1]), - ("uint32_t", [0, 2**32-1]), - ("uint64_t", [0, 2**64-1]), - ("int8_t", [-2**7, 2**7-1]), - ("int16_t", [-2**15, 2**15-1]), - ("int32_t", [-2**31, 2**31-1]), - ("int64_t", [-2**63, 2**63-1]), - ("_Bool", [False, True]), - ("float", [0.0, 10.5]), - ("double", [12.34, 56.78]), - ]: - BItem = new_primitive_type(typename) - BArray = new_array_type(new_pointer_type(BItem), 10) - p = newp(BArray, samples) - result = unpack(p, len(samples)) - assert result == samples - for i in range(len(samples)): - assert result[i] == p[i] and type(result[i]) is type(p[i]) - assert (type(result[i]) is bool) == (type(samples[i]) is bool) - # - BInt = new_primitive_type("int") - py.test.raises(TypeError, unpack, p) - py.test.raises(TypeError, unpack, b"foobar", 6) - py.test.raises(TypeError, unpack, cast(BInt, 42), 1) - # - BPtr = new_pointer_type(BInt) - random_ptr = cast(BPtr, -424344) - other_ptr = cast(BPtr, 54321) - BArray = new_array_type(new_pointer_type(BPtr), None) - lst = unpack(newp(BArray, [random_ptr, other_ptr]), 2) - assert lst == [random_ptr, other_ptr] - # - BFunc = new_function_type((BInt, BInt), BInt, False) - BFuncPtr = new_pointer_type(BFunc) - lst = unpack(newp(new_array_type(BFuncPtr, None), 2), 2) - assert len(lst) == 2 - assert not lst[0] and not lst[1] - assert typeof(lst[0]) is BFunc - # - BStruct = new_struct_type("foo") - BStructPtr = new_pointer_type(BStruct) - e = py.test.raises(ValueError, unpack, cast(BStructPtr, 42), 5) - assert str(e.value) == "'foo *' points to items of unknown size" - complete_struct_or_union(BStruct, [('a1', BInt, -1), - ('a2', BInt, -1)]) - array_of_structs = newp(new_array_type(BStructPtr, None), [[4,5], [6,7]]) - lst = unpack(array_of_structs, 2) - assert typeof(lst[0]) is BStruct - assert lst[0].a1 == 4 and lst[1].a2 == 7 - # - py.test.raises(RuntimeError, unpack, cast(new_pointer_type(BChar), 0), 0) - py.test.raises(RuntimeError, unpack, cast(new_pointer_type(BChar), 0), 10) - # - py.test.raises(ValueError, unpack, p0, -1) - py.test.raises(ValueError, unpack, p, -1) - -def test_cdata_dir(): - BInt = new_primitive_type("int") - p = cast(BInt, 42) - check_dir(p, []) - p = newp(new_array_type(new_pointer_type(BInt), None), 5) - check_dir(p, []) - BStruct = new_struct_type("foo") - p = cast(new_pointer_type(BStruct), 0) - check_dir(p, []) # opaque - complete_struct_or_union(BStruct, [('a2', BInt, -1), - ('a1', BInt, -1)]) - check_dir(p, ['a1', 'a2']) # always sorted - p = newp(new_pointer_type(BStruct), None) - check_dir(p, ['a1', 'a2']) - check_dir(p[0], ['a1', 'a2']) - pp = newp(new_pointer_type(new_pointer_type(BStruct)), p) - check_dir(pp, []) - check_dir(pp[0], ['a1', 'a2']) - check_dir(pp[0][0], ['a1', 'a2']) - -def test_char_pointer_conversion(): - import warnings - assert __version__.startswith("1."), ( - "the warning will be an error if we ever release cffi 2.x") - BCharP = new_pointer_type(new_primitive_type("char")) - BIntP = new_pointer_type(new_primitive_type("int")) - BVoidP = new_pointer_type(new_void_type()) - BUCharP = new_pointer_type(new_primitive_type("unsigned char")) - z1 = cast(BCharP, 0) - z2 = cast(BIntP, 0) - z3 = cast(BVoidP, 0) - z4 = cast(BUCharP, 0) - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - newp(new_pointer_type(BIntP), z1) # warn - assert len(w) == 1 - newp(new_pointer_type(BVoidP), z1) # fine - assert len(w) == 1 - newp(new_pointer_type(BCharP), z2) # warn - assert len(w) == 2 - newp(new_pointer_type(BVoidP), z2) # fine - assert len(w) == 2 - newp(new_pointer_type(BCharP), z3) # fine - assert len(w) == 2 - newp(new_pointer_type(BIntP), z3) # fine - assert len(w) == 2 - newp(new_pointer_type(BCharP), z4) # fine (ignore signedness here) - assert len(w) == 2 - newp(new_pointer_type(BUCharP), z1) # fine (ignore signedness here) - assert len(w) == 2 - newp(new_pointer_type(BUCharP), z3) # fine - assert len(w) == 2 - # check that the warnings are associated with lines in this file - assert w[1].lineno == w[0].lineno + 4 - -def test_primitive_comparison(): - def assert_eq(a, b): - assert (a == b) is True - assert (b == a) is True - assert (a != b) is False - assert (b != a) is False - assert (a < b) is False - assert (a <= b) is True - assert (a > b) is False - assert (a >= b) is True - assert (b < a) is False - assert (b <= a) is True - assert (b > a) is False - assert (b >= a) is True - assert hash(a) == hash(b) - def assert_lt(a, b, check_hash=True): - assert (a == b) is False - assert (b == a) is False - assert (a != b) is True - assert (b != a) is True - assert (a < b) is True - assert (a <= b) is True - assert (a > b) is False - assert (a >= b) is False - assert (b < a) is False - assert (b <= a) is False - assert (b > a) is True - assert (b >= a) is True - if check_hash: - assert hash(a) != hash(b) # (or at least, it is unlikely) - def assert_gt(a, b, check_hash=True): - assert_lt(b, a, check_hash) - def assert_ne(a, b): - assert (a == b) is False - assert (b == a) is False - assert (a != b) is True - assert (b != a) is True - if strict_compare: - with pytest.raises(TypeError): a < b - with pytest.raises(TypeError): a <= b - with pytest.raises(TypeError): a > b - with pytest.raises(TypeError): a >= b - with pytest.raises(TypeError): b < a - with pytest.raises(TypeError): b <= a - with pytest.raises(TypeError): b > a - with pytest.raises(TypeError): b >= a - elif a < b: - assert_lt(a, b) - else: - assert_lt(b, a) - assert_eq(5, 5) - assert_lt(3, 5) - assert_ne('5', 5) - # - t1 = new_primitive_type("char") - t2 = new_primitive_type("int") - t3 = new_primitive_type("unsigned char") - t4 = new_primitive_type("unsigned int") - t5 = new_primitive_type("float") - t6 = new_primitive_type("double") - assert_eq(cast(t1, 65), b'A') - assert_lt(cast(t1, 64), b'\x99') - assert_gt(cast(t1, 200), b'A') - assert_ne(cast(t1, 65), 65) - assert_eq(cast(t2, -25), -25) - assert_lt(cast(t2, -25), -24) - assert_gt(cast(t2, -25), -26) - assert_eq(cast(t3, 65), 65) - assert_ne(cast(t3, 65), b'A') - assert_ne(cast(t3, 65), cast(t1, 65)) - assert_gt(cast(t4, -1), -1, check_hash=False) - assert_gt(cast(t4, -1), cast(t2, -1), check_hash=False) - assert_gt(cast(t4, -1), 99999) - assert_eq(cast(t4, -1), 256 ** size_of_int() - 1) - assert_eq(cast(t5, 3.0), 3) - assert_eq(cast(t5, 3.5), 3.5) - assert_lt(cast(t5, 3.3), 3.3) # imperfect rounding - assert_eq(cast(t6, 3.3), 3.3) - assert_eq(cast(t5, 3.5), cast(t6, 3.5)) - assert_lt(cast(t5, 3.1), cast(t6, 3.1)) # imperfect rounding - assert_eq(cast(t5, 7.0), cast(t3, 7)) - assert_lt(cast(t5, 3.1), 3.101) - assert_gt(cast(t5, 3.1), 3) - -def test_explicit_release_new(): - # release() on a ffi.new() object has no effect on CPython, but - # really releases memory on PyPy. We can't test that effect - # though, because a released cdata is not marked. - BIntP = new_pointer_type(new_primitive_type("int")) - p = newp(BIntP) - p[0] = 42 - with pytest.raises(IndexError): - p[1] - release(p) - # here, reading p[0] might give garbage or segfault... - release(p) # no effect - # - BStruct = new_struct_type("struct foo") - BStructP = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('p', BIntP, -1)]) - pstruct = newp(BStructP) - assert pstruct.p == cast(BIntP, 0) - release(pstruct) - # here, reading pstruct.p might give garbage or segfault... - release(pstruct) # no effect - -def test_explicit_release_new_contextmgr(): - BIntP = new_pointer_type(new_primitive_type("int")) - with newp(BIntP) as p: - p[0] = 42 - assert p[0] == 42 - # here, reading p[0] might give garbage or segfault... - release(p) # no effect - -def test_explicit_release_badtype(): - BIntP = new_pointer_type(new_primitive_type("int")) - p = cast(BIntP, 12345) - py.test.raises(ValueError, release, p) - py.test.raises(ValueError, release, p) - BStruct = new_struct_type("struct foo") - BStructP = new_pointer_type(BStruct) - complete_struct_or_union(BStruct, [('p', BIntP, -1)]) - pstruct = newp(BStructP) - py.test.raises(ValueError, release, pstruct[0]) - -def test_explicit_release_badtype_contextmgr(): - BIntP = new_pointer_type(new_primitive_type("int")) - p = cast(BIntP, 12345) - with pytest.raises(ValueError): - with p: - pass - with pytest.raises(ValueError): - with p: - pass - -def test_explicit_release_gc(): - BIntP = new_pointer_type(new_primitive_type("int")) - seen = [] - intp1 = newp(BIntP, 12345) - p1 = cast(BIntP, intp1) - p = gcp(p1, seen.append) - assert seen == [] - release(p) - assert seen == [p1] - assert p1[0] == 12345 - assert p[0] == 12345 # true so far, but might change to raise RuntimeError - release(p) # no effect - -def test_explicit_release_gc_contextmgr(): - BIntP = new_pointer_type(new_primitive_type("int")) - seen = [] - intp1 = newp(BIntP, 12345) - p1 = cast(BIntP, intp1) - p = gcp(p1, seen.append) - with p: - assert p[0] == 12345 - assert seen == [] - assert seen == [p1] - assert p1[0] == 12345 - assert p[0] == 12345 # true so far, but might change to raise RuntimeError - release(p) # no effect - -def test_explicit_release_from_buffer(): - a = bytearray(b"xyz") - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - p = from_buffer(BCharA, a) - assert p[2] == b"z" - assert repr(p) == "<cdata 'char[]' buffer len 3 from 'bytearray' object>" - release(p) - assert p[2] == b"z" # true so far, but might change to raise RuntimeError - assert repr(p) == "<cdata 'char[]' buffer RELEASED>" - release(p) # no effect - -def test_explicit_release_from_buffer_contextmgr(): - a = bytearray(b"xyz") - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - p = from_buffer(BCharA, a) - with p: - assert p[2] == b"z" - assert p[2] == b"z" # true so far, but might change to raise RuntimeError - assert repr(p) == "<cdata 'char[]' buffer RELEASED>" - release(p) # no effect - -def test_explicit_release_bytearray_on_cpython(): - if '__pypy__' in sys.builtin_module_names: - py.test.skip("pypy's bytearray are never locked") - a = bytearray(b"xyz") - BChar = new_primitive_type("char") - BCharP = new_pointer_type(BChar) - BCharA = new_array_type(BCharP, None) - a += b't' * 10 - p = from_buffer(BCharA, a) - with pytest.raises(BufferError): - a += b'u' * 100 - release(p) - a += b'v' * 100 - release(p) # no effect - a += b'w' * 1000 - assert a == bytearray(b"xyz" + b't' * 10 + b'v' * 100 + b'w' * 1000) - -def test_int_doesnt_give_bool(): - BBool = new_primitive_type("_Bool") - x = int(cast(BBool, 42)) - assert type(x) is int and x == 1 - x = long(cast(BBool, 42)) - assert type(x) is long and x == 1 - with pytest.raises(TypeError): - float(cast(BBool, 42)) - with pytest.raises(TypeError): - complex(cast(BBool, 42)) - -def test_cannot_call_null_function_pointer(): - BInt = new_primitive_type("int") - BFunc = new_function_type((BInt, BInt), BInt, False) - f = cast(BFunc, 0) - with pytest.raises(RuntimeError): - f(40, 2) - -def test_huge_structure(): - BChar = new_primitive_type("char") - BArray = new_array_type(new_pointer_type(BChar), sys.maxsize) - assert sizeof(BArray) == sys.maxsize - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('a1', BArray, -1)]) - assert sizeof(BStruct) == sys.maxsize - -def test_get_types(): - import _cffi_backend - CData, CType = _get_types() - assert CData is _cffi_backend._CDataBase - assert CType is _cffi_backend.CType - -def test_type_available_with_correct_names(): - import _cffi_backend - check_names = [ - 'CType', - 'CField', - 'CLibrary', - '_CDataBase', - 'FFI', - 'Lib', - 'buffer', - ] - if '__pypy__' in sys.builtin_module_names: - check_names += [ - '__CData_iterator', - '__FFIGlobSupport', - '__FFIAllocator', - '__FFIFunctionWrapper', - ] - else: - check_names += [ - '__CDataOwn', - '__CDataOwnGC', - '__CDataFromBuf', - '__CDataGCP', - '__CData_iterator', - '__FFIGlobSupport', - ] - for name in check_names: - tp = getattr(_cffi_backend, name) - assert isinstance(tp, type) - assert (tp.__module__, tp.__name__) == ('_cffi_backend', name) - -def test_unaligned_types(): - BByteArray = new_array_type( - new_pointer_type(new_primitive_type("unsigned char")), None) - pbuf = newp(BByteArray, 40) - buf = buffer(pbuf) - # - for name in ['short', 'int', 'long', 'long long', 'float', 'double', - 'float _Complex', 'double _Complex']: - p = new_primitive_type(name) - if name.endswith(' _Complex'): - num = cast(p, 1.23 - 4.56j) - else: - num = cast(p, 0x0123456789abcdef) - size = sizeof(p) - buf[0:40] = b"\x00" * 40 - pbuf1 = cast(new_pointer_type(p), pbuf + 1) - pbuf1[0] = num - assert pbuf1[0] == num - assert buf[0] == b'\x00' - assert buf[1 + size] == b'\x00' |