summaryrefslogtreecommitdiff
path: root/c/test_c.py
diff options
context:
space:
mode:
Diffstat (limited to 'c/test_c.py')
-rw-r--r--c/test_c.py4575
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'