summaryrefslogtreecommitdiff
path: root/testing/cffi1
diff options
context:
space:
mode:
Diffstat (limited to 'testing/cffi1')
-rw-r--r--testing/cffi1/__init__.py0
-rw-r--r--testing/cffi1/test_cffi_binary.py22
-rw-r--r--testing/cffi1/test_commontypes.py34
-rw-r--r--testing/cffi1/test_dlopen.py225
-rw-r--r--testing/cffi1/test_dlopen_unicode_literals.py9
-rw-r--r--testing/cffi1/test_ffi_obj.py536
-rw-r--r--testing/cffi1/test_function_args.py208
-rw-r--r--testing/cffi1/test_new_ffi_1.py1831
-rw-r--r--testing/cffi1/test_parse_c_type.py372
-rw-r--r--testing/cffi1/test_pkgconfig.py94
-rw-r--r--testing/cffi1/test_re_python.py288
-rw-r--r--testing/cffi1/test_realize_c_type.py73
-rw-r--r--testing/cffi1/test_recompiler.py2495
-rw-r--r--testing/cffi1/test_unicode_literals.py43
-rw-r--r--testing/cffi1/test_verify1.py2359
-rw-r--r--testing/cffi1/test_zdist.py426
16 files changed, 0 insertions, 9015 deletions
diff --git a/testing/cffi1/__init__.py b/testing/cffi1/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/testing/cffi1/__init__.py
+++ /dev/null
diff --git a/testing/cffi1/test_cffi_binary.py b/testing/cffi1/test_cffi_binary.py
deleted file mode 100644
index 7cfbace..0000000
--- a/testing/cffi1/test_cffi_binary.py
+++ /dev/null
@@ -1,22 +0,0 @@
-import py, sys, os
-import _cffi_backend
-
-def test_no_unknown_exported_symbols():
- if not hasattr(_cffi_backend, '__file__'):
- py.test.skip("_cffi_backend module is built-in")
- if not sys.platform.startswith('linux'):
- py.test.skip("linux-only")
- g = os.popen("objdump -T '%s'" % _cffi_backend.__file__, 'r')
- for line in g:
- if not line.startswith('0'):
- continue
- if line[line.find(' ') + 1] == 'l':
- continue
- if '*UND*' in line:
- continue
- name = line.split()[-1]
- if name.startswith('_') or name.startswith('.'):
- continue
- if name not in ('init_cffi_backend', 'PyInit__cffi_backend'):
- raise Exception("Unexpected exported name %r" % (name,))
- g.close()
diff --git a/testing/cffi1/test_commontypes.py b/testing/cffi1/test_commontypes.py
deleted file mode 100644
index ea7ffde..0000000
--- a/testing/cffi1/test_commontypes.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import py, os, cffi, re
-import _cffi_backend
-
-
-def getlines():
- try:
- f = open(os.path.join(os.path.dirname(cffi.__file__),
- '..', 'c', 'commontypes.c'))
- except IOError:
- py.test.skip("cannot find ../c/commontypes.c")
- lines = [line for line in f.readlines() if line.strip().startswith('EQ(')]
- f.close()
- return lines
-
-def test_alphabetical_order():
- lines = getlines()
- assert lines == sorted(lines)
-
-def test_dependencies():
- r = re.compile(r'EQ[(]"([^"]+)",(?:\s*"([A-Z0-9_]+)\s*[*]*"[)])?')
- lines = getlines()
- d = {}
- for line in lines:
- match = r.search(line)
- if match is not None:
- d[match.group(1)] = match.group(2)
- for value in d.values():
- if value:
- assert value in d
-
-def test_get_common_types():
- d = {}
- _cffi_backend._get_common_types(d)
- assert d["bool"] == "_Bool"
diff --git a/testing/cffi1/test_dlopen.py b/testing/cffi1/test_dlopen.py
deleted file mode 100644
index 26a2717..0000000
--- a/testing/cffi1/test_dlopen.py
+++ /dev/null
@@ -1,225 +0,0 @@
-import py
-from cffi import FFI, VerificationError, CDefError
-from cffi.recompiler import make_py_source
-from testing.udir import udir
-
-
-def test_simple():
- ffi = FFI()
- ffi.cdef("int close(int); static const int BB = 42; extern int somevar;")
- target = udir.join('test_simple.py')
- make_py_source(ffi, 'test_simple', str(target))
- assert target.read() == r"""# auto-generated file
-import _cffi_backend
-
-ffi = _cffi_backend.FFI('test_simple',
- _version = 0x2601,
- _types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F',
- _globals = (b'\xFF\xFF\xFF\x1FBB',42,b'\x00\x00\x00\x23close',0,b'\x00\x00\x01\x21somevar',0),
-)
-"""
-
-def test_global_constant():
- ffi = FFI()
- ffi.cdef("static const long BB; static const float BF = 12;")
- target = udir.join('test_valid_global_constant.py')
- make_py_source(ffi, 'test_valid_global_constant', str(target))
- assert target.read() == r"""# auto-generated file
-import _cffi_backend
-
-ffi = _cffi_backend.FFI('test_valid_global_constant',
- _version = 0x2601,
- _types = b'\x00\x00\x0D\x01\x00\x00\x09\x01',
- _globals = (b'\x00\x00\x01\x25BB',0,b'\x00\x00\x00\x25BF',0),
-)
-"""
-
-def test_invalid_global_constant_3():
- ffi = FFI()
- e = py.test.raises(CDefError, ffi.cdef, "#define BB 12.34")
- assert str(e.value).startswith(
- "only supports one of the following syntax:")
-
-def test_invalid_dotdotdot_in_macro():
- ffi = FFI()
- ffi.cdef("#define FOO ...")
- target = udir.join('test_invalid_dotdotdot_in_macro.py')
- e = py.test.raises(VerificationError, make_py_source, ffi,
- 'test_invalid_dotdotdot_in_macro', str(target))
- assert str(e.value) == ("macro FOO: cannot use the syntax '...' in "
- "'#define FOO ...' when using the ABI mode")
-
-def test_typename():
- ffi = FFI()
- ffi.cdef("typedef int foobar_t;")
- target = udir.join('test_typename.py')
- make_py_source(ffi, 'test_typename', str(target))
- assert target.read() == r"""# auto-generated file
-import _cffi_backend
-
-ffi = _cffi_backend.FFI('test_typename',
- _version = 0x2601,
- _types = b'\x00\x00\x07\x01',
- _typenames = (b'\x00\x00\x00\x00foobar_t',),
-)
-"""
-
-def test_enum():
- ffi = FFI()
- ffi.cdef("enum myenum_e { AA, BB, CC=-42 };")
- target = udir.join('test_enum.py')
- make_py_source(ffi, 'test_enum', str(target))
- assert target.read() == r"""# auto-generated file
-import _cffi_backend
-
-ffi = _cffi_backend.FFI('test_enum',
- _version = 0x2601,
- _types = b'\x00\x00\x00\x0B',
- _globals = (b'\xFF\xFF\xFF\x0BAA',0,b'\xFF\xFF\xFF\x0BBB',1,b'\xFF\xFF\xFF\x0BCC',-42),
- _enums = (b'\x00\x00\x00\x00\x00\x00\x00\x15myenum_e\x00AA,BB,CC',),
-)
-"""
-
-def test_struct():
- ffi = FFI()
- ffi.cdef("struct foo_s { int a; signed char b[]; }; struct bar_s;")
- target = udir.join('test_struct.py')
- make_py_source(ffi, 'test_struct', str(target))
- assert target.read() == r"""# auto-generated file
-import _cffi_backend
-
-ffi = _cffi_backend.FFI('test_struct',
- _version = 0x2601,
- _types = b'\x00\x00\x07\x01\x00\x00\x03\x01\x00\x00\x01\x07\x00\x00\x00\x09\x00\x00\x01\x09',
- _struct_unions = ((b'\x00\x00\x00\x03\x00\x00\x00\x10bar_s',),(b'\x00\x00\x00\x04\x00\x00\x00\x02foo_s',b'\x00\x00\x00\x11a',b'\x00\x00\x02\x11b')),
-)
-"""
-
-def test_include():
- ffi = FFI()
- ffi.cdef("#define ABC 123")
- ffi.set_source('test_include', None)
- target = udir.join('test_include.py')
- make_py_source(ffi, 'test_include', str(target))
- assert target.read() == r"""# auto-generated file
-import _cffi_backend
-
-ffi = _cffi_backend.FFI('test_include',
- _version = 0x2601,
- _types = b'',
- _globals = (b'\xFF\xFF\xFF\x1FABC',123,),
-)
-"""
- #
- ffi2 = FFI()
- ffi2.include(ffi)
- target2 = udir.join('test2_include.py')
- make_py_source(ffi2, 'test2_include', str(target2))
- assert target2.read() == r"""# auto-generated file
-import _cffi_backend
-from test_include import ffi as _ffi0
-
-ffi = _cffi_backend.FFI('test2_include',
- _version = 0x2601,
- _types = b'',
- _includes = (_ffi0,),
-)
-"""
-
-def test_negative_constant():
- ffi = FFI()
- ffi.cdef("static const int BB = -42;")
- target = udir.join('test_negative_constant.py')
- make_py_source(ffi, 'test_negative_constant', str(target))
- assert target.read() == r"""# auto-generated file
-import _cffi_backend
-
-ffi = _cffi_backend.FFI('test_negative_constant',
- _version = 0x2601,
- _types = b'',
- _globals = (b'\xFF\xFF\xFF\x1FBB',-42,),
-)
-"""
-
-def test_struct_included():
- baseffi = FFI()
- baseffi.cdef("struct foo_s { int x; };")
- baseffi.set_source('test_struct_included_base', None)
- #
- ffi = FFI()
- ffi.include(baseffi)
- target = udir.join('test_struct_included.py')
- make_py_source(ffi, 'test_struct_included', str(target))
- assert target.read() == r"""# auto-generated file
-import _cffi_backend
-from test_struct_included_base import ffi as _ffi0
-
-ffi = _cffi_backend.FFI('test_struct_included',
- _version = 0x2601,
- _types = b'\x00\x00\x00\x09',
- _struct_unions = ((b'\x00\x00\x00\x00\x00\x00\x00\x08foo_s',),),
- _includes = (_ffi0,),
-)
-"""
-
-def test_no_cross_include():
- baseffi = FFI()
- baseffi.set_source('test_no_cross_include_base', "..source..")
- #
- ffi = FFI()
- ffi.include(baseffi)
- target = udir.join('test_no_cross_include.py')
- py.test.raises(VerificationError, make_py_source,
- ffi, 'test_no_cross_include', str(target))
-
-def test_array():
- ffi = FFI()
- ffi.cdef("typedef int32_t my_array_t[42];")
- target = udir.join('test_array.py')
- make_py_source(ffi, 'test_array', str(target))
- assert target.read() == r"""# auto-generated file
-import _cffi_backend
-
-ffi = _cffi_backend.FFI('test_array',
- _version = 0x2601,
- _types = b'\x00\x00\x15\x01\x00\x00\x00\x05\x00\x00\x00\x2A',
- _typenames = (b'\x00\x00\x00\x01my_array_t',),
-)
-"""
-
-def test_array_overflow():
- ffi = FFI()
- ffi.cdef("typedef int32_t my_array_t[3000000000];")
- target = udir.join('test_array_overflow.py')
- py.test.raises(OverflowError, make_py_source,
- ffi, 'test_array_overflow', str(target))
-
-def test_global_var():
- ffi = FFI()
- ffi.cdef("extern int myglob;")
- target = udir.join('test_global_var.py')
- make_py_source(ffi, 'test_global_var', str(target))
- assert target.read() == r"""# auto-generated file
-import _cffi_backend
-
-ffi = _cffi_backend.FFI('test_global_var',
- _version = 0x2601,
- _types = b'\x00\x00\x07\x01',
- _globals = (b'\x00\x00\x00\x21myglob',0,),
-)
-"""
-
-def test_bitfield():
- ffi = FFI()
- ffi.cdef("struct foo_s { int y:10; short x:5; };")
- target = udir.join('test_bitfield.py')
- make_py_source(ffi, 'test_bitfield', str(target))
- assert target.read() == r"""# auto-generated file
-import _cffi_backend
-
-ffi = _cffi_backend.FFI('test_bitfield',
- _version = 0x2601,
- _types = b'\x00\x00\x07\x01\x00\x00\x05\x01\x00\x00\x00\x09',
- _struct_unions = ((b'\x00\x00\x00\x02\x00\x00\x00\x02foo_s',b'\x00\x00\x00\x13\x00\x00\x00\x0Ay',b'\x00\x00\x01\x13\x00\x00\x00\x05x'),),
-)
-"""
diff --git a/testing/cffi1/test_dlopen_unicode_literals.py b/testing/cffi1/test_dlopen_unicode_literals.py
deleted file mode 100644
index e792866..0000000
--- a/testing/cffi1/test_dlopen_unicode_literals.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import py, os
-
-s = """from __future__ import unicode_literals
-"""
-
-with open(os.path.join(os.path.dirname(__file__), 'test_dlopen.py')) as f:
- s += f.read()
-
-exec(py.code.compile(s))
diff --git a/testing/cffi1/test_ffi_obj.py b/testing/cffi1/test_ffi_obj.py
deleted file mode 100644
index 0d29290..0000000
--- a/testing/cffi1/test_ffi_obj.py
+++ /dev/null
@@ -1,536 +0,0 @@
-import py, sys
-import pytest
-import _cffi_backend as _cffi1_backend
-
-
-def test_ffi_new():
- ffi = _cffi1_backend.FFI()
- p = ffi.new("int *")
- p[0] = -42
- assert p[0] == -42
- assert type(ffi) is ffi.__class__ is _cffi1_backend.FFI
-
-def test_ffi_subclass():
- class FOO(_cffi1_backend.FFI):
- def __init__(self, x):
- self.x = x
- foo = FOO(42)
- assert foo.x == 42
- p = foo.new("int *")
- assert p[0] == 0
- assert type(foo) is foo.__class__ is FOO
-
-def test_ffi_no_argument():
- py.test.raises(TypeError, _cffi1_backend.FFI, 42)
-
-def test_ffi_cache_type():
- ffi = _cffi1_backend.FFI()
- t1 = ffi.typeof("int **")
- t2 = ffi.typeof("int *")
- assert t2.item is t1.item.item
- assert t2 is t1.item
- assert ffi.typeof("int[][10]") is ffi.typeof("int[][10]")
- assert ffi.typeof("int(*)()") is ffi.typeof("int(*)()")
-
-def test_ffi_type_not_immortal():
- import weakref, gc
- ffi = _cffi1_backend.FFI()
- t1 = ffi.typeof("int **")
- t2 = ffi.typeof("int *")
- w1 = weakref.ref(t1)
- w2 = weakref.ref(t2)
- del t1, ffi
- gc.collect()
- assert w1() is None
- assert w2() is t2
- ffi = _cffi1_backend.FFI()
- assert ffi.typeof(ffi.new("int **")[0]) is t2
- #
- ffi = _cffi1_backend.FFI()
- t1 = ffi.typeof("int ***")
- t2 = ffi.typeof("int **")
- w1 = weakref.ref(t1)
- w2 = weakref.ref(t2)
- del t2, ffi
- gc.collect()
- assert w1() is t1
- assert w2() is not None # kept alive by t1
- ffi = _cffi1_backend.FFI()
- assert ffi.typeof("int * *") is t1.item
-
-def test_ffi_cache_type_globally():
- ffi1 = _cffi1_backend.FFI()
- ffi2 = _cffi1_backend.FFI()
- t1 = ffi1.typeof("int *")
- t2 = ffi2.typeof("int *")
- assert t1 is t2
-
-def test_ffi_invalid():
- ffi = _cffi1_backend.FFI()
- # array of 10 times an "int[]" is invalid
- py.test.raises(ValueError, ffi.typeof, "int[10][]")
-
-def test_ffi_docstrings():
- # check that all methods of the FFI class have a docstring.
- check_type = type(_cffi1_backend.FFI.new)
- for methname in dir(_cffi1_backend.FFI):
- if not methname.startswith('_'):
- method = getattr(_cffi1_backend.FFI, methname)
- if isinstance(method, check_type):
- assert method.__doc__, "method FFI.%s() has no docstring" % (
- methname,)
-
-def test_ffi_NULL():
- NULL = _cffi1_backend.FFI.NULL
- assert _cffi1_backend.FFI().typeof(NULL).cname == "void *"
-
-def test_ffi_no_attr():
- ffi = _cffi1_backend.FFI()
- with pytest.raises(AttributeError):
- ffi.no_such_name
- with pytest.raises(AttributeError):
- ffi.no_such_name = 42
- with pytest.raises(AttributeError):
- del ffi.no_such_name
-
-def test_ffi_string():
- ffi = _cffi1_backend.FFI()
- p = ffi.new("char[]", init=b"foobar\x00baz")
- assert ffi.string(p) == b"foobar"
- assert ffi.string(cdata=p, maxlen=3) == b"foo"
-
-def test_ffi_errno():
- # xxx not really checking errno, just checking that we can read/write it
- ffi = _cffi1_backend.FFI()
- ffi.errno = 42
- assert ffi.errno == 42
-
-def test_ffi_alignof():
- ffi = _cffi1_backend.FFI()
- assert ffi.alignof("int") == 4
- assert ffi.alignof("int[]") == 4
- assert ffi.alignof("int[41]") == 4
- assert ffi.alignof("short[41]") == 2
- assert ffi.alignof(ffi.new("int[41]")) == 4
- assert ffi.alignof(ffi.new("int[]", 41)) == 4
-
-def test_ffi_sizeof():
- ffi = _cffi1_backend.FFI()
- assert ffi.sizeof("int") == 4
- py.test.raises(ffi.error, ffi.sizeof, "int[]")
- assert ffi.sizeof("int[41]") == 41 * 4
- assert ffi.sizeof(ffi.new("int[41]")) == 41 * 4
- assert ffi.sizeof(ffi.new("int[]", 41)) == 41 * 4
-
-def test_ffi_callback():
- ffi = _cffi1_backend.FFI()
- assert ffi.callback("int(int)", lambda x: x + 42)(10) == 52
- assert ffi.callback("int(*)(int)", lambda x: x + 42)(10) == 52
- assert ffi.callback("int(int)", lambda x: x + "", -66)(10) == -66
- assert ffi.callback("int(int)", lambda x: x + "", error=-66)(10) == -66
-
-def test_ffi_callback_decorator():
- ffi = _cffi1_backend.FFI()
- assert ffi.callback(ffi.typeof("int(*)(int)"))(lambda x: x + 42)(10) == 52
- deco = ffi.callback("int(int)", error=-66)
- assert deco(lambda x: x + "")(10) == -66
- assert deco(lambda x: x + 42)(10) == 52
-
-def test_ffi_callback_onerror():
- ffi = _cffi1_backend.FFI()
- seen = []
- def oops(*args):
- seen.append(args)
-
- @ffi.callback("int(int)", onerror=oops)
- def fn1(x):
- return x + ""
- assert fn1(10) == 0
-
- @ffi.callback("int(int)", onerror=oops, error=-66)
- def fn2(x):
- return x + ""
- assert fn2(10) == -66
-
- assert len(seen) == 2
- exc, val, tb = seen[0]
- assert exc is TypeError
- assert isinstance(val, TypeError)
- assert tb.tb_frame.f_code.co_name == "fn1"
- exc, val, tb = seen[1]
- assert exc is TypeError
- assert isinstance(val, TypeError)
- assert tb.tb_frame.f_code.co_name == "fn2"
- #
- py.test.raises(TypeError, ffi.callback, "int(int)",
- lambda x: x, onerror=42) # <- not callable
-
-def test_ffi_getctype():
- ffi = _cffi1_backend.FFI()
- assert ffi.getctype("int") == "int"
- assert ffi.getctype("int", 'x') == "int x"
- assert ffi.getctype("int*") == "int *"
- assert ffi.getctype("int*", '') == "int *"
- assert ffi.getctype("int*", 'x') == "int * x"
- assert ffi.getctype("int", '*') == "int *"
- assert ffi.getctype("int", replace_with=' * x ') == "int * x"
- assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *"
- assert ffi.getctype("int", '[5]') == "int[5]"
- assert ffi.getctype("int[5]", '[6]') == "int[6][5]"
- assert ffi.getctype("int[5]", '(*)') == "int(*)[5]"
- # special-case for convenience: automatically put '()' around '*'
- assert ffi.getctype("int[5]", '*') == "int(*)[5]"
- assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]"
- assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]"
-
-def test_addressof():
- ffi = _cffi1_backend.FFI()
- a = ffi.new("int[10]")
- b = ffi.addressof(a, 5)
- b[2] = -123
- assert a[7] == -123
-
-def test_handle():
- ffi = _cffi1_backend.FFI()
- x = [2, 4, 6]
- xp = ffi.new_handle(x)
- assert ffi.typeof(xp) == ffi.typeof("void *")
- assert ffi.from_handle(xp) is x
- yp = ffi.new_handle([6, 4, 2])
- assert ffi.from_handle(yp) == [6, 4, 2]
-
-def test_handle_unique():
- ffi = _cffi1_backend.FFI()
- assert ffi.new_handle(None) is not ffi.new_handle(None)
- assert ffi.new_handle(None) != ffi.new_handle(None)
-
-def test_ffi_cast():
- ffi = _cffi1_backend.FFI()
- assert ffi.cast("int(*)(int)", 0) == ffi.NULL
- ffi.callback("int(int)") # side-effect of registering this string
- py.test.raises(ffi.error, ffi.cast, "int(int)", 0)
-
-def test_ffi_invalid_type():
- ffi = _cffi1_backend.FFI()
- e = py.test.raises(ffi.error, ffi.cast, "", 0)
- assert str(e.value) == ("identifier expected\n"
- "\n"
- "^")
- e = py.test.raises(ffi.error, ffi.cast, "struct struct", 0)
- assert str(e.value) == ("struct or union name expected\n"
- "struct struct\n"
- " ^")
- e = py.test.raises(ffi.error, ffi.cast, "struct never_heard_of_s", 0)
- assert str(e.value) == ("undefined struct/union name\n"
- "struct never_heard_of_s\n"
- " ^")
- e = py.test.raises(ffi.error, ffi.cast, "\t\n\x01\x1f~\x7f\x80\xff", 0)
- marks = "?" if sys.version_info < (3,) else "??"
- assert str(e.value) == ("identifier expected\n"
- " ??~?%s%s\n"
- " ^" % (marks, marks))
- e = py.test.raises(ffi.error, ffi.cast, "X" * 600, 0)
- assert str(e.value) == ("undefined type name")
-
-def test_ffi_buffer():
- ffi = _cffi1_backend.FFI()
- a = ffi.new("signed char[]", [5, 6, 7])
- assert ffi.buffer(a)[:] == b'\x05\x06\x07'
- assert ffi.buffer(cdata=a, size=2)[:] == b'\x05\x06'
- assert type(ffi.buffer(a)) is ffi.buffer
-
-def test_ffi_from_buffer():
- import array
- ffi = _cffi1_backend.FFI()
- a = array.array('H', [10000, 20000, 30000, 40000])
- c = ffi.from_buffer(a)
- assert ffi.typeof(c) is ffi.typeof("char[]")
- assert len(c) == 8
- ffi.cast("unsigned short *", c)[1] += 500
- assert list(a) == [10000, 20500, 30000, 40000]
- py.test.raises(TypeError, ffi.from_buffer, a, True)
- assert c == ffi.from_buffer("char[]", a, True)
- assert c == ffi.from_buffer(a, require_writable=True)
- #
- c = ffi.from_buffer("unsigned short[]", a)
- assert len(c) == 4
- assert c[1] == 20500
- #
- c = ffi.from_buffer("unsigned short[2][2]", a)
- assert len(c) == 2
- assert len(c[0]) == 2
- assert c[0][1] == 20500
- #
- p = ffi.from_buffer(b"abcd")
- assert p[2] == b"c"
- #
- assert p == ffi.from_buffer(b"abcd", require_writable=False)
- py.test.raises((TypeError, BufferError), ffi.from_buffer,
- "char[]", b"abcd", True)
- py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd",
- require_writable=True)
-
-def test_memmove():
- ffi = _cffi1_backend.FFI()
- p = ffi.new("short[]", [-1234, -2345, -3456, -4567, -5678])
- ffi.memmove(p, p + 1, 4)
- assert list(p) == [-2345, -3456, -3456, -4567, -5678]
- p[2] = 999
- ffi.memmove(p + 2, p, 6)
- assert list(p) == [-2345, -3456, -2345, -3456, 999]
- ffi.memmove(p + 4, ffi.new("char[]", 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
- ffi = _cffi1_backend.FFI()
- a = array.array('H', [10000, 20000, 30000])
- p = ffi.new("short[]", 5)
- ffi.memmove(p, a, 6)
- assert list(p) == [10000, 20000, 30000, 0, 0]
- ffi.memmove(p + 1, a, 6)
- assert list(p) == [10000, 10000, 20000, 30000, 0]
- b = array.array('h', [-1000, -2000, -3000])
- ffi.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
- ffi.memmove(b, p, 2)
- assert b.tolist() == [999, 20000, -3000]
- ffi.memmove(b, p + 2, 4)
- assert b.tolist() == [997, 996, -3000]
- p[2] = -p[2]
- p[3] = -p[3]
- ffi.memmove(b, p + 2, 6)
- assert b.tolist() == [-997, -996, 995]
-
-def test_memmove_readonly_readwrite():
- ffi = _cffi1_backend.FFI()
- p = ffi.new("signed char[]", 5)
- ffi.memmove(p, b"abcde", 3)
- assert list(p) == [ord("a"), ord("b"), ord("c"), 0, 0]
- ffi.memmove(p, bytearray(b"ABCDE"), 2)
- assert list(p) == [ord("A"), ord("B"), ord("c"), 0, 0]
- py.test.raises((TypeError, BufferError), ffi.memmove, b"abcde", p, 3)
- ba = bytearray(b"xxxxx")
- ffi.memmove(dest=ba, src=p, n=3)
- assert ba == bytearray(b"ABcxx")
-
-def test_ffi_types():
- CData = _cffi1_backend.FFI.CData
- CType = _cffi1_backend.FFI.CType
- ffi = _cffi1_backend.FFI()
- assert isinstance(ffi.cast("int", 42), CData)
- assert isinstance(ffi.typeof("int"), CType)
-
-def test_ffi_getwinerror():
- if sys.platform != "win32":
- py.test.skip("for windows")
- ffi = _cffi1_backend.FFI()
- n = (1 << 29) + 42
- code, message = ffi.getwinerror(code=n)
- assert code == n
-
-def test_ffi_new_allocator_1():
- ffi = _cffi1_backend.FFI()
- alloc1 = ffi.new_allocator()
- alloc2 = ffi.new_allocator(should_clear_after_alloc=False)
- for retry in range(100):
- p1 = alloc1("int[10]")
- p2 = alloc2("int[10]")
- combination = 0
- for i in range(10):
- assert p1[i] == 0
- combination |= p2[i]
- p1[i] = -42
- p2[i] = -43
- if combination != 0:
- break
- del p1, p2
- import gc; gc.collect()
- else:
- raise AssertionError("cannot seem to get an int[10] not "
- "completely cleared")
-
-def test_ffi_new_allocator_2():
- ffi = _cffi1_backend.FFI()
- seen = []
- def myalloc(size):
- seen.append(size)
- return ffi.new("char[]", b"X" * size)
- def myfree(raw):
- seen.append(raw)
- alloc1 = ffi.new_allocator(myalloc, myfree)
- alloc2 = ffi.new_allocator(alloc=myalloc, free=myfree,
- should_clear_after_alloc=False)
- p1 = alloc1("int[10]")
- p2 = alloc2("int[]", 10)
- assert seen == [40, 40]
- assert ffi.typeof(p1) == ffi.typeof("int[10]")
- assert ffi.sizeof(p1) == 40
- assert ffi.typeof(p2) == ffi.typeof("int[]")
- assert ffi.sizeof(p2) == 40
- assert p1[5] == 0
- assert p2[6] == ord('X') * 0x01010101
- raw1 = ffi.cast("char *", p1)
- raw2 = ffi.cast("char *", p2)
- del p1, p2
- retries = 0
- while len(seen) != 4:
- retries += 1
- assert retries <= 5
- import gc; gc.collect()
- assert (seen == [40, 40, raw1, raw2] or
- seen == [40, 40, raw2, raw1])
- assert repr(seen[2]) == "<cdata 'char[]' owning 41 bytes>"
- assert repr(seen[3]) == "<cdata 'char[]' owning 41 bytes>"
-
-def test_ffi_new_allocator_3():
- ffi = _cffi1_backend.FFI()
- seen = []
- def myalloc(size):
- seen.append(size)
- return ffi.new("char[]", b"X" * size)
- alloc1 = ffi.new_allocator(myalloc) # no 'free'
- p1 = alloc1("int[10]")
- assert seen == [40]
- assert ffi.typeof(p1) == ffi.typeof("int[10]")
- assert ffi.sizeof(p1) == 40
- assert p1[5] == 0
-
-def test_ffi_new_allocator_4():
- ffi = _cffi1_backend.FFI()
- py.test.raises(TypeError, ffi.new_allocator, free=lambda x: None)
- #
- def myalloc2(size):
- raise LookupError
- alloc2 = ffi.new_allocator(myalloc2)
- py.test.raises(LookupError, alloc2, "int[5]")
- #
- def myalloc3(size):
- return 42
- alloc3 = ffi.new_allocator(myalloc3)
- e = py.test.raises(TypeError, alloc3, "int[5]")
- assert str(e.value) == "alloc() must return a cdata object (got int)"
- #
- def myalloc4(size):
- return ffi.cast("int", 42)
- alloc4 = ffi.new_allocator(myalloc4)
- e = py.test.raises(TypeError, alloc4, "int[5]")
- assert str(e.value) == "alloc() must return a cdata pointer, not 'int'"
- #
- def myalloc5(size):
- return ffi.NULL
- alloc5 = ffi.new_allocator(myalloc5)
- py.test.raises(MemoryError, alloc5, "int[5]")
-
-def test_bool_issue228():
- ffi = _cffi1_backend.FFI()
- fntype = ffi.typeof("int(*callback)(bool is_valid)")
- assert repr(fntype.args[0]) == "<ctype '_Bool'>"
-
-def test_FILE_issue228():
- fntype1 = _cffi1_backend.FFI().typeof("FILE *")
- fntype2 = _cffi1_backend.FFI().typeof("FILE *")
- assert repr(fntype1) == "<ctype 'FILE *'>"
- assert fntype1 is fntype2
-
-def test_cast_from_int_type_to_bool():
- ffi = _cffi1_backend.FFI()
- for basetype in ['char', 'short', 'int', 'long', 'long long']:
- for sign in ['signed', 'unsigned']:
- type = '%s %s' % (sign, basetype)
- assert int(ffi.cast("_Bool", ffi.cast(type, 42))) == 1
- assert int(ffi.cast("bool", ffi.cast(type, 42))) == 1
- assert int(ffi.cast("_Bool", ffi.cast(type, 0))) == 0
-
-def test_init_once():
- def do_init():
- seen.append(1)
- return 42
- ffi = _cffi1_backend.FFI()
- seen = []
- for i in range(3):
- res = ffi.init_once(do_init, "tag1")
- assert res == 42
- assert seen == [1]
- for i in range(3):
- res = ffi.init_once(do_init, "tag2")
- assert res == 42
- assert seen == [1, 1]
-
-def test_init_once_multithread():
- if sys.version_info < (3,):
- import thread
- else:
- import _thread as thread
- import time
- #
- def do_init():
- print('init!')
- seen.append('init!')
- time.sleep(1)
- seen.append('init done')
- print('init done')
- return 7
- ffi = _cffi1_backend.FFI()
- seen = []
- for i in range(6):
- def f():
- res = ffi.init_once(do_init, "tag")
- seen.append(res)
- thread.start_new_thread(f, ())
- time.sleep(1.5)
- assert seen == ['init!', 'init done'] + 6 * [7]
-
-def test_init_once_failure():
- def do_init():
- seen.append(1)
- raise ValueError
- ffi = _cffi1_backend.FFI()
- seen = []
- for i in range(5):
- py.test.raises(ValueError, ffi.init_once, do_init, "tag")
- assert seen == [1] * (i + 1)
-
-def test_init_once_multithread_failure():
- if sys.version_info < (3,):
- import thread
- else:
- import _thread as thread
- import time
- def do_init():
- seen.append('init!')
- time.sleep(1)
- seen.append('oops')
- raise ValueError
- ffi = _cffi1_backend.FFI()
- seen = []
- for i in range(3):
- def f():
- py.test.raises(ValueError, ffi.init_once, do_init, "tag")
- thread.start_new_thread(f, ())
- i = 0
- while len(seen) < 6:
- i += 1
- assert i < 20
- time.sleep(0.51)
- assert seen == ['init!', 'oops'] * 3
-
-def test_unpack():
- ffi = _cffi1_backend.FFI()
- p = ffi.new("char[]", b"abc\x00def")
- assert ffi.unpack(p+1, 7) == b"bc\x00def\x00"
- p = ffi.new("int[]", [-123456789])
- assert ffi.unpack(p, 1) == [-123456789]
-
-def test_negative_array_size():
- ffi = _cffi1_backend.FFI()
- py.test.raises(ffi.error, ffi.cast, "int[-5]", 0)
diff --git a/testing/cffi1/test_function_args.py b/testing/cffi1/test_function_args.py
deleted file mode 100644
index 30c6fed..0000000
--- a/testing/cffi1/test_function_args.py
+++ /dev/null
@@ -1,208 +0,0 @@
-import pytest, sys
-try:
- # comment out the following line to run this test.
- # the latest on x86-64 linux: https://github.com/libffi/libffi/issues/574
- if sys.platform != 'win32':
- raise ImportError("this test is skipped because it keeps finding "
- "failures in libffi, instead of cffi")
-
- from hypothesis import given, settings, example
- from hypothesis import strategies as st
-except ImportError as e:
- e1 = e
- def test_types():
- pytest.skip(str(e1))
-else:
-
- from cffi import FFI
- import sys, random
- from .test_recompiler import verify
-
- ALL_PRIMITIVES = [
- 'unsigned char',
- 'short',
- 'int',
- 'long',
- 'long long',
- 'float',
- 'double',
- #'long double', --- on x86 it can give libffi crashes
- ]
- def _make_struct(s):
- return st.lists(s, min_size=1)
- types = st.one_of(st.sampled_from(ALL_PRIMITIVES),
- st.lists(st.sampled_from(ALL_PRIMITIVES), min_size=1))
- # NB. 'types' could be st.recursive instead, but it doesn't
- # really seem useful
-
- def draw_primitive(ffi, typename):
- value = random.random() * 2**40
- if typename != 'long double':
- return ffi.cast(typename, value)
- else:
- return value
-
- TEST_RUN_COUNTER = 0
-
-
- @given(st.lists(types), types)
- @settings(max_examples=100, deadline=5000) # 5000ms
- def test_types(tp_args, tp_result):
- global TEST_RUN_COUNTER
- print(tp_args, tp_result)
- cdefs = []
- structs = {}
-
- def build_type(tp):
- if type(tp) is list:
- field_types = [build_type(tp1) for tp1 in tp]
- fields = ['%s f%d;' % (ftp, j)
- for (j, ftp) in enumerate(field_types)]
- fields = '\n '.join(fields)
- name = 's%d' % len(cdefs)
- cdefs.append("typedef struct {\n %s\n} %s;" % (fields, name))
- structs[name] = field_types
- return name
- else:
- return tp
-
- args = [build_type(tp) for tp in tp_args]
- result = build_type(tp_result)
-
- TEST_RUN_COUNTER += 1
- signature = "%s testfargs(%s)" % (result,
- ', '.join(['%s a%d' % (arg, i) for (i, arg) in enumerate(args)])
- or 'void')
-
- source = list(cdefs)
-
- cdefs.append("%s;" % signature)
- cdefs.append("extern %s testfargs_result;" % result)
- for i, arg in enumerate(args):
- cdefs.append("extern %s testfargs_arg%d;" % (arg, i))
- source.append("%s testfargs_result;" % result)
- for i, arg in enumerate(args):
- source.append("%s testfargs_arg%d;" % (arg, i))
- source.append(signature)
- source.append("{")
- for i, arg in enumerate(args):
- source.append(" testfargs_arg%d = a%d;" % (i, i))
- source.append(" return testfargs_result;")
- source.append("}")
-
- typedef_line = "typedef %s;" % (signature.replace('testfargs',
- '(*mycallback_t)'),)
- assert signature.endswith(')')
- sig_callback = "%s testfcallback(mycallback_t callback)" % result
- cdefs.append(typedef_line)
- cdefs.append("%s;" % sig_callback)
- source.append(typedef_line)
- source.append(sig_callback)
- source.append("{")
- source.append(" return callback(%s);" %
- ', '.join(["testfargs_arg%d" % i for i in range(len(args))]))
- source.append("}")
-
- ffi = FFI()
- ffi.cdef("\n".join(cdefs))
- lib = verify(ffi, 'test_function_args_%d' % TEST_RUN_COUNTER,
- "\n".join(source), no_cpp=True)
-
- # when getting segfaults, enable this:
- if False:
- from testing.udir import udir
- import subprocess
- f = open(str(udir.join('run1.py')), 'w')
- f.write('import sys; sys.path = %r\n' % (sys.path,))
- f.write('from _CFFI_test_function_args_%d import ffi, lib\n' %
- TEST_RUN_COUNTER)
- for i in range(len(args)):
- f.write('a%d = ffi.new("%s *")\n' % (i, args[i]))
- aliststr = ', '.join(['a%d[0]' % i for i in range(len(args))])
- f.write('lib.testfargs(%s)\n' % aliststr)
- f.write('ffi.addressof(lib, "testfargs")(%s)\n' % aliststr)
- f.close()
- print("checking for segfault for direct call...")
- rc = subprocess.call([sys.executable, 'run1.py'], cwd=str(udir))
- assert rc == 0, rc
-
- def make_arg(tp):
- if tp in structs:
- return [make_arg(tp1) for tp1 in structs[tp]]
- else:
- return draw_primitive(ffi, tp)
-
- passed_args = [make_arg(arg) for arg in args]
- returned_value = make_arg(result)
-
- def write(p, v):
- if type(v) is list:
- for i, v1 in enumerate(v):
- write(ffi.addressof(p, 'f%d' % i), v1)
- else:
- p[0] = v
-
- write(ffi.addressof(lib, 'testfargs_result'), returned_value)
-
- ## CALL forcing libffi
- print("CALL forcing libffi")
- received_return = ffi.addressof(lib, 'testfargs')(*passed_args)
- ##
-
- _tp_long_double = ffi.typeof("long double")
- def check(p, v):
- if type(v) is list:
- for i, v1 in enumerate(v):
- check(ffi.addressof(p, 'f%d' % i), v1)
- else:
- if ffi.typeof(p).item is _tp_long_double:
- assert ffi.cast("double", p[0]) == v
- else:
- assert p[0] == v
-
- for i, arg in enumerate(passed_args):
- check(ffi.addressof(lib, 'testfargs_arg%d' % i), arg)
- ret = ffi.new(result + "*", received_return)
- check(ret, returned_value)
-
- ## CALLBACK
- def expand(value):
- if isinstance(value, ffi.CData):
- t = ffi.typeof(value)
- if t is _tp_long_double:
- return float(ffi.cast("double", value))
- return [expand(getattr(value, 'f%d' % i))
- for i in range(len(t.fields))]
- else:
- return value
-
- # when getting segfaults, enable this:
- if False:
- from testing.udir import udir
- import subprocess
- f = open(str(udir.join('run1.py')), 'w')
- f.write('import sys; sys.path = %r\n' % (sys.path,))
- f.write('from _CFFI_test_function_args_%d import ffi, lib\n' %
- TEST_RUN_COUNTER)
- f.write('def callback(*args): return ffi.new("%s *")[0]\n' % result)
- f.write('fptr = ffi.callback("%s(%s)", callback)\n' % (result,
- ','.join(args)))
- f.write('print(lib.testfcallback(fptr))\n')
- f.close()
- print("checking for segfault for callback...")
- rc = subprocess.call([sys.executable, 'run1.py'], cwd=str(udir))
- assert rc == 0, rc
-
- seen_args = []
- def callback(*args):
- seen_args.append([expand(arg) for arg in args])
- return returned_value
-
- fptr = ffi.callback("%s(%s)" % (result, ','.join(args)), callback)
- print("CALL with callback")
- received_return = lib.testfcallback(fptr)
-
- assert len(seen_args) == 1
- assert passed_args == seen_args[0]
- ret = ffi.new(result + "*", received_return)
- check(ret, returned_value)
diff --git a/testing/cffi1/test_new_ffi_1.py b/testing/cffi1/test_new_ffi_1.py
deleted file mode 100644
index 640830b..0000000
--- a/testing/cffi1/test_new_ffi_1.py
+++ /dev/null
@@ -1,1831 +0,0 @@
-import py
-import pytest
-import platform, imp
-import sys, os, ctypes
-import cffi
-from testing.udir import udir
-from testing.support import *
-from cffi.recompiler import recompile
-from cffi.cffi_opcode import PRIMITIVE_TO_INDEX
-
-SIZE_OF_INT = ctypes.sizeof(ctypes.c_int)
-SIZE_OF_LONG = ctypes.sizeof(ctypes.c_long)
-SIZE_OF_SHORT = ctypes.sizeof(ctypes.c_short)
-SIZE_OF_PTR = ctypes.sizeof(ctypes.c_void_p)
-SIZE_OF_WCHAR = ctypes.sizeof(ctypes.c_wchar)
-
-
-def setup_module():
- global ffi, construction_params
- ffi1 = cffi.FFI()
- DEFS = r"""
- struct repr { short a, b, c; };
- struct simple { int a; short b, c; };
- struct array { int a[2]; char b[3]; };
- struct recursive { int value; struct recursive *next; };
- union simple_u { int a; short b, c; };
- union init_u { char a; int b; };
- struct four_s { int a; short b, c, d; };
- union four_u { int a; short b, c, d; };
- struct string { const char *name; };
- struct ustring { const wchar_t *name; };
- struct voidp { void *p; int *q; short *r; };
- struct ab { int a, b; };
- struct abc { int a, b, c; };
-
- /* don't use A0, B0, CC0, D0 because termios.h might be included
- and it has its own #defines for these names */
- enum foq { cffiA0, cffiB0, cffiCC0, cffiD0 };
- enum bar { A1, B1=-2, CC1, D1, E1 };
- enum baz { A2=0x1000, B2=0x2000 };
- enum foo2 { A3, B3, C3, D3 };
- struct bar_with_e { enum foo2 e; };
- enum noncont { A4, B4=42, C4 };
- enum etypes {A5='!', B5='\'', C5=0x10, D5=010, E5=- 0x10, F5=-010};
- typedef enum { Value0 = 0 } e_t, *pe_t;
- enum e_noninj { AA3=0, BB3=0, CC3=0, DD3=0 };
- enum e_prev { AA4, BB4=2, CC4=4, DD4=BB4, EE4, FF4=CC4, GG4=FF4 };
-
- struct nesting { struct abc d, e; };
- struct array2 { int a, b; int c[99]; };
- struct align { char a; short b; char c; };
- struct bitfield { int a:10, b:20, c:3; };
- typedef enum { AA2, BB2, CC2 } foo_e_t;
- typedef struct { foo_e_t f:2; } bfenum_t;
- typedef struct { int a; } anon_foo_t;
- typedef struct { char b, c; } anon_bar_t;
- typedef struct named_foo_s { int a; } named_foo_t, *named_foo_p;
- typedef struct { int a; } unnamed_foo_t, *unnamed_foo_p;
- struct nonpacked { char a; int b; };
- struct array0 { int len; short data[0]; };
- struct array_no_length { int x; int a[]; };
-
- struct nested_anon {
- struct { int a, b; };
- union { int c, d; };
- };
- struct nested_field_ofs_s {
- struct { int a; char b; };
- union { char c; };
- };
- union nested_anon_u {
- struct { int a, b; };
- union { int c, d; };
- };
- struct abc50 { int a, b; int c[50]; };
- struct ints_and_bitfield { int a,b,c,d,e; int x:1; };
- """
- DEFS_PACKED = """
- struct is_packed { char a; int b; } /*here*/;
- """
- if sys.platform == "win32":
- DEFS = DEFS.replace('data[0]', 'data[1]') # not supported
- CCODE = (DEFS + "\n#pragma pack(push,1)\n" + DEFS_PACKED +
- "\n#pragma pack(pop)\n")
- else:
- CCODE = (DEFS +
- DEFS_PACKED.replace('/*here*/', '__attribute__((packed))'))
-
- ffi1.cdef(DEFS)
- ffi1.cdef(DEFS_PACKED, packed=True)
- ffi1.set_source("test_new_ffi_1", CCODE)
-
- outputfilename = recompile(ffi1, "test_new_ffi_1", CCODE,
- tmpdir=str(udir))
- module = imp.load_dynamic("test_new_ffi_1", outputfilename)
- ffi = module.ffi
- construction_params = (ffi1, CCODE)
-
-
-class TestNewFFI1:
-
- def test_integer_ranges(self):
- for (c_type, size) in [('char', 1),
- ('short', 2),
- ('short int', 2),
- ('', 4),
- ('int', 4),
- ('long', SIZE_OF_LONG),
- ('long int', SIZE_OF_LONG),
- ('long long', 8),
- ('long long int', 8),
- ]:
- for unsigned in [None, False, True]:
- c_decl = {None: '',
- False: 'signed ',
- True: 'unsigned '}[unsigned] + c_type
- if c_decl == 'char' or c_decl == '':
- continue
- self._test_int_type(ffi, c_decl, size, unsigned)
-
- def test_fixedsize_int(self):
- for size in [1, 2, 4, 8]:
- self._test_int_type(ffi, 'int%d_t' % (8*size), size, False)
- self._test_int_type(ffi, 'uint%d_t' % (8*size), size, True)
- self._test_int_type(ffi, 'intptr_t', SIZE_OF_PTR, False)
- self._test_int_type(ffi, 'uintptr_t', SIZE_OF_PTR, True)
- self._test_int_type(ffi, 'ptrdiff_t', SIZE_OF_PTR, False)
- self._test_int_type(ffi, 'size_t', SIZE_OF_PTR, True)
- self._test_int_type(ffi, 'ssize_t', SIZE_OF_PTR, False)
-
- def _test_int_type(self, ffi, c_decl, size, unsigned):
- if unsigned:
- min = 0
- max = (1 << (8*size)) - 1
- else:
- min = -(1 << (8*size-1))
- max = (1 << (8*size-1)) - 1
- min = int(min)
- max = int(max)
- p = ffi.cast(c_decl, min)
- assert p == min
- assert bool(p) is bool(min)
- assert int(p) == min
- p = ffi.cast(c_decl, max)
- assert int(p) == max
- p = ffi.cast(c_decl, long(max))
- assert int(p) == max
- q = ffi.cast(c_decl, min - 1)
- assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
- q = ffi.cast(c_decl, long(min - 1))
- assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
- assert q == p
- assert int(q) == int(p)
- assert hash(q) == hash(p)
- c_decl_ptr = '%s *' % c_decl
- py.test.raises(OverflowError, ffi.new, c_decl_ptr, min - 1)
- py.test.raises(OverflowError, ffi.new, c_decl_ptr, max + 1)
- py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(min - 1))
- py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(max + 1))
- assert ffi.new(c_decl_ptr, min)[0] == min
- assert ffi.new(c_decl_ptr, max)[0] == max
- assert ffi.new(c_decl_ptr, long(min))[0] == min
- assert ffi.new(c_decl_ptr, long(max))[0] == max
-
- def test_new_unsupported_type(self):
- e = py.test.raises(TypeError, ffi.new, "int")
- assert str(e.value) == "expected a pointer or array ctype, got 'int'"
-
- def test_new_single_integer(self):
- p = ffi.new("int *") # similar to ffi.new("int[1]")
- assert p[0] == 0
- p[0] = -123
- assert p[0] == -123
- p = ffi.new("int *", -42)
- assert p[0] == -42
- assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
-
- def test_new_array_no_arg(self):
- p = ffi.new("int[10]")
- # the object was zero-initialized:
- for i in range(10):
- assert p[i] == 0
-
- def test_array_indexing(self):
- p = ffi.new("int[10]")
- p[0] = 42
- p[9] = 43
- assert p[0] == 42
- assert p[9] == 43
- with pytest.raises(IndexError):
- p[10]
- with pytest.raises(IndexError):
- p[10] = 44
- with pytest.raises(IndexError):
- p[-1]
- with pytest.raises(IndexError):
- p[-1] = 44
-
- def test_new_array_args(self):
- # this tries to be closer to C: where we say "int x[5] = {10, 20, ..}"
- # then here we must enclose the items in a list
- p = ffi.new("int[5]", [10, 20, 30, 40, 50])
- assert p[0] == 10
- assert p[1] == 20
- assert p[2] == 30
- assert p[3] == 40
- assert p[4] == 50
- p = ffi.new("int[4]", [25])
- assert p[0] == 25
- assert p[1] == 0 # follow C convention rather than LuaJIT's
- assert p[2] == 0
- assert p[3] == 0
- p = ffi.new("int[4]", [ffi.cast("int", -5)])
- assert p[0] == -5
- assert repr(p) == "<cdata 'int[4]' owning %d bytes>" % (4*SIZE_OF_INT)
-
- def test_new_array_varsize(self):
- p = ffi.new("int[]", 10) # a single integer is the length
- assert p[9] == 0
- with pytest.raises(IndexError):
- p[10]
- #
- py.test.raises(TypeError, ffi.new, "int[]")
- #
- p = ffi.new("int[]", [-6, -7]) # a list is all the items, like C
- assert p[0] == -6
- assert p[1] == -7
- with pytest.raises(IndexError):
- p[2]
- assert repr(p) == "<cdata 'int[]' owning %d bytes>" % (2*SIZE_OF_INT)
- #
- p = ffi.new("int[]", 0)
- with pytest.raises(IndexError):
- p[0]
- py.test.raises(ValueError, ffi.new, "int[]", -1)
- assert repr(p) == "<cdata 'int[]' owning 0 bytes>"
-
- def test_pointer_init(self):
- n = ffi.new("int *", 24)
- a = ffi.new("int *[10]", [ffi.NULL, ffi.NULL, n, n, ffi.NULL])
- for i in range(10):
- if i not in (2, 3):
- assert a[i] == ffi.NULL
- assert a[2] == a[3] == n
-
- def test_cannot_cast(self):
- a = ffi.new("short int[10]")
- e = py.test.raises(TypeError, ffi.new, "long int **", a)
- msg = str(e.value)
- assert "'short[10]'" in msg and "'long *'" in msg
-
- def test_new_pointer_to_array(self):
- a = ffi.new("int[4]", [100, 102, 104, 106])
- p = ffi.new("int **", a)
- assert p[0] == ffi.cast("int *", a)
- assert p[0][2] == 104
- p = ffi.cast("int *", a)
- assert p[0] == 100
- assert p[1] == 102
- assert p[2] == 104
- assert p[3] == 106
- # keepalive: a
-
- def test_pointer_direct(self):
- p = ffi.cast("int*", 0)
- assert p is not None
- assert bool(p) is False
- assert p == ffi.cast("int*", 0)
- assert p != None
- assert repr(p) == "<cdata 'int *' NULL>"
- a = ffi.new("int[]", [123, 456])
- p = ffi.cast("int*", a)
- assert bool(p) is True
- assert p == ffi.cast("int*", a)
- assert p != ffi.cast("int*", 0)
- assert p[0] == 123
- assert p[1] == 456
-
- def test_repr(self):
- typerepr = "<ctype '%s'>"
- p = ffi.cast("short unsigned int", 0)
- assert repr(p) == "<cdata 'unsigned short' 0>"
- assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
- p = ffi.cast("unsigned short int", 0)
- assert repr(p) == "<cdata 'unsigned short' 0>"
- assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
- p = ffi.cast("int*", 0)
- assert repr(p) == "<cdata 'int *' NULL>"
- assert repr(ffi.typeof(p)) == typerepr % "int *"
- #
- p = ffi.new("int*")
- assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
- assert repr(ffi.typeof(p)) == typerepr % "int *"
- p = ffi.new("int**")
- assert repr(p) == "<cdata 'int * *' owning %d bytes>" % SIZE_OF_PTR
- assert repr(ffi.typeof(p)) == typerepr % "int * *"
- p = ffi.new("int [2]")
- assert repr(p) == "<cdata 'int[2]' owning %d bytes>" % (2*SIZE_OF_INT)
- assert repr(ffi.typeof(p)) == typerepr % "int[2]"
- p = ffi.new("int*[2][3]")
- assert repr(p) == "<cdata 'int *[2][3]' owning %d bytes>" % (
- 6*SIZE_OF_PTR)
- assert repr(ffi.typeof(p)) == typerepr % "int *[2][3]"
- p = ffi.new("struct repr *")
- assert repr(p) == "<cdata 'struct repr *' owning %d bytes>" % (
- 3*SIZE_OF_SHORT)
- assert repr(ffi.typeof(p)) == typerepr % "struct repr *"
- #
- q = ffi.cast("short", -123)
- assert repr(q) == "<cdata 'short' -123>"
- assert repr(ffi.typeof(q)) == typerepr % "short"
- p = ffi.new("int*")
- q = ffi.cast("short*", p)
- assert repr(q).startswith("<cdata 'short *' 0x")
- assert repr(ffi.typeof(q)) == typerepr % "short *"
- p = ffi.new("int [2]")
- q = ffi.cast("int*", p)
- assert repr(q).startswith("<cdata 'int *' 0x")
- assert repr(ffi.typeof(q)) == typerepr % "int *"
- p = ffi.new("struct repr*")
- q = ffi.cast("struct repr *", p)
- assert repr(q).startswith("<cdata 'struct repr *' 0x")
- assert repr(ffi.typeof(q)) == typerepr % "struct repr *"
- prevrepr = repr(q)
- q = q[0]
- assert repr(q) == prevrepr.replace(' *', ' &')
- assert repr(ffi.typeof(q)) == typerepr % "struct repr"
-
- def test_new_array_of_array(self):
- p = ffi.new("int[3][4]")
- p[0][0] = 10
- p[2][3] = 33
- assert p[0][0] == 10
- assert p[2][3] == 33
- with pytest.raises(IndexError):
- p[1][-1]
-
- def test_constructor_array_of_array(self):
- p = ffi.new("int[3][2]", [[10, 11], [12, 13], [14, 15]])
- assert p[2][1] == 15
-
- def test_new_array_of_pointer_1(self):
- n = ffi.new("int*", 99)
- p = ffi.new("int*[4]")
- p[3] = n
- a = p[3]
- assert repr(a).startswith("<cdata 'int *' 0x")
- assert a[0] == 99
-
- def test_new_array_of_pointer_2(self):
- n = ffi.new("int[1]", [99])
- p = ffi.new("int*[4]")
- p[3] = n
- a = p[3]
- assert repr(a).startswith("<cdata 'int *' 0x")
- assert a[0] == 99
-
- def test_char(self):
- assert ffi.new("char*", b"\xff")[0] == b'\xff'
- assert ffi.new("char*")[0] == b'\x00'
- assert int(ffi.cast("char", 300)) == 300 - 256
- assert not bool(ffi.cast("char", 0))
- assert bool(ffi.cast("char", 1))
- assert bool(ffi.cast("char", 255))
- py.test.raises(TypeError, ffi.new, "char*", 32)
- py.test.raises(TypeError, ffi.new, "char*", u+"x")
- py.test.raises(TypeError, ffi.new, "char*", b"foo")
- #
- p = ffi.new("char[]", [b'a', b'b', b'\x9c'])
- assert len(p) == 3
- assert p[0] == b'a'
- assert p[1] == b'b'
- assert p[2] == b'\x9c'
- p[0] = b'\xff'
- assert p[0] == b'\xff'
- p = ffi.new("char[]", b"abcd")
- assert len(p) == 5
- assert p[4] == b'\x00' # like in C, with: char[] p = "abcd";
- #
- p = ffi.new("char[4]", b"ab")
- assert len(p) == 4
- assert [p[i] for i in range(4)] == [b'a', b'b', b'\x00', b'\x00']
- p = ffi.new("char[2]", b"ab")
- assert len(p) == 2
- assert [p[i] for i in range(2)] == [b'a', b'b']
- py.test.raises(IndexError, ffi.new, "char[2]", b"abc")
-
- def check_wchar_t(self, ffi):
- try:
- ffi.cast("wchar_t", 0)
- except NotImplementedError:
- py.test.skip("NotImplementedError: wchar_t")
-
- def test_wchar_t(self):
- self.check_wchar_t(ffi)
- assert ffi.new("wchar_t*", u+'x')[0] == u+'x'
- assert ffi.new("wchar_t*", u+'\u1234')[0] == u+'\u1234'
- if SIZE_OF_WCHAR > 2:
- assert ffi.new("wchar_t*", u+'\U00012345')[0] == u+'\U00012345'
- else:
- py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345')
- assert ffi.new("wchar_t*")[0] == u+'\x00'
- assert int(ffi.cast("wchar_t", 300)) == 300
- assert not bool(ffi.cast("wchar_t", 0))
- assert bool(ffi.cast("wchar_t", 1))
- assert bool(ffi.cast("wchar_t", 65535))
- if SIZE_OF_WCHAR > 2:
- assert bool(ffi.cast("wchar_t", 65536))
- py.test.raises(TypeError, ffi.new, "wchar_t*", 32)
- py.test.raises(TypeError, ffi.new, "wchar_t*", "foo")
- #
- p = ffi.new("wchar_t[]", [u+'a', u+'b', u+'\u1234'])
- assert len(p) == 3
- assert p[0] == u+'a'
- assert p[1] == u+'b' and type(p[1]) is unicode
- assert p[2] == u+'\u1234'
- p[0] = u+'x'
- assert p[0] == u+'x' and type(p[0]) is unicode
- p[1] = u+'\u1357'
- assert p[1] == u+'\u1357'
- p = ffi.new("wchar_t[]", u+"abcd")
- assert len(p) == 5
- assert p[4] == u+'\x00'
- p = ffi.new("wchar_t[]", u+"a\u1234b")
- assert len(p) == 4
- assert p[1] == u+'\u1234'
- #
- p = ffi.new("wchar_t[]", u+'\U00023456')
- if SIZE_OF_WCHAR == 2:
- assert len(p) == 3
- assert p[0] == u+'\ud84d'
- assert p[1] == u+'\udc56'
- assert p[2] == u+'\x00'
- else:
- assert len(p) == 2
- assert p[0] == u+'\U00023456'
- assert p[1] == u+'\x00'
- #
- p = ffi.new("wchar_t[4]", u+"ab")
- assert len(p) == 4
- assert [p[i] for i in range(4)] == [u+'a', u+'b', u+'\x00', u+'\x00']
- p = ffi.new("wchar_t[2]", u+"ab")
- assert len(p) == 2
- assert [p[i] for i in range(2)] == [u+'a', u+'b']
- py.test.raises(IndexError, ffi.new, "wchar_t[2]", u+"abc")
-
- def test_none_as_null_doesnt_work(self):
- p = ffi.new("int*[1]")
- assert p[0] is not None
- assert p[0] != None
- assert p[0] == ffi.NULL
- assert repr(p[0]) == "<cdata 'int *' NULL>"
- #
- n = ffi.new("int*", 99)
- p = ffi.new("int*[]", [n])
- assert p[0][0] == 99
- with pytest.raises(TypeError):
- p[0] = None
- p[0] = ffi.NULL
- assert p[0] == ffi.NULL
-
- def test_float(self):
- p = ffi.new("float[]", [-2, -2.5])
- assert p[0] == -2.0
- assert p[1] == -2.5
- p[1] += 17.75
- assert p[1] == 15.25
- #
- p = ffi.new("float*", 15.75)
- assert p[0] == 15.75
- py.test.raises(TypeError, int, p)
- py.test.raises(TypeError, float, p)
- p[0] = 0.0
- assert bool(p) is True
- #
- p = ffi.new("float*", 1.1)
- f = p[0]
- assert f != 1.1 # because of rounding effect
- assert abs(f - 1.1) < 1E-7
- #
- INF = 1E200 * 1E200
- assert 1E200 != INF
- p[0] = 1E200
- assert p[0] == INF # infinite, not enough precision
-
- def test_struct_simple(self):
- s = ffi.new("struct simple*")
- assert s.a == s.b == s.c == 0
- s.b = -23
- assert s.b == -23
- with pytest.raises(OverflowError):
- s.b = 32768
- #
- s = ffi.new("struct simple*", [-2, -3])
- assert s.a == -2
- assert s.b == -3
- assert s.c == 0
- with pytest.raises((AttributeError, TypeError)):
- del s.a
- assert repr(s) == "<cdata 'struct simple *' owning %d bytes>" % (
- SIZE_OF_INT + 2 * SIZE_OF_SHORT)
- #
- py.test.raises(ValueError, ffi.new, "struct simple*", [1, 2, 3, 4])
-
- def test_constructor_struct_from_dict(self):
- s = ffi.new("struct simple*", {'b': 123, 'c': 456})
- assert s.a == 0
- assert s.b == 123
- assert s.c == 456
- py.test.raises(KeyError, ffi.new, "struct simple*", {'d': 456})
-
- def test_struct_pointer(self):
- s = ffi.new("struct simple*")
- assert s[0].a == s[0].b == s[0].c == 0
- s[0].b = -23
- assert s[0].b == s.b == -23
- with pytest.raises(OverflowError):
- s[0].b = -32769
- with pytest.raises(IndexError):
- s[1]
-
- def test_struct_opaque(self):
- py.test.raises(ffi.error, ffi.new, "struct baz*")
- # should 'ffi.new("struct baz **") work? it used to, but it was
- # not particularly useful...
- py.test.raises(ffi.error, ffi.new, "struct baz**")
-
- def test_pointer_to_struct(self):
- s = ffi.new("struct simple *")
- s.a = -42
- assert s[0].a == -42
- p = ffi.new("struct simple **", s)
- assert p[0].a == -42
- assert p[0][0].a == -42
- p[0].a = -43
- assert s.a == -43
- assert s[0].a == -43
- p[0][0].a = -44
- assert s.a == -44
- assert s[0].a == -44
- s.a = -45
- assert p[0].a == -45
- assert p[0][0].a == -45
- s[0].a = -46
- assert p[0].a == -46
- assert p[0][0].a == -46
-
- def test_constructor_struct_of_array(self):
- s = ffi.new("struct array *", [[10, 11], [b'a', b'b', b'c']])
- assert s.a[1] == 11
- assert s.b[2] == b'c'
- s.b[1] = b'X'
- assert s.b[0] == b'a'
- assert s.b[1] == b'X'
- assert s.b[2] == b'c'
-
- def test_recursive_struct(self):
- s = ffi.new("struct recursive*")
- t = ffi.new("struct recursive*")
- s.value = 123
- s.next = t
- t.value = 456
- assert s.value == 123
- assert s.next.value == 456
-
- def test_union_simple(self):
- u = ffi.new("union simple_u*")
- assert u.a == u.b == u.c == 0
- u.b = -23
- assert u.b == -23
- assert u.a != 0
- with pytest.raises(OverflowError):
- u.b = 32768
- #
- u = ffi.new("union simple_u*", [-2])
- assert u.a == -2
- with pytest.raises((AttributeError, TypeError)):
- del u.a
- assert repr(u) == "<cdata 'union simple_u *' owning %d bytes>" % (
- SIZE_OF_INT,)
-
- def test_union_opaque(self):
- py.test.raises(ffi.error, ffi.new, "union baz*")
- # should 'ffi.new("union baz **") work? it used to, but it was
- # not particularly useful...
- py.test.raises(ffi.error, ffi.new, "union baz**")
-
- def test_union_initializer(self):
- py.test.raises(TypeError, ffi.new, "union init_u*", b'A')
- py.test.raises(TypeError, ffi.new, "union init_u*", 5)
- py.test.raises(ValueError, ffi.new, "union init_u*", [b'A', 5])
- u = ffi.new("union init_u*", [b'A'])
- assert u.a == b'A'
- py.test.raises(TypeError, ffi.new, "union init_u*", [1005])
- u = ffi.new("union init_u*", {'b': 12345})
- assert u.b == 12345
- u = ffi.new("union init_u*", [])
- assert u.a == b'\x00'
- assert u.b == 0
-
- def test_sizeof_type(self):
- for c_type, expected_size in [
- ('char', 1),
- ('unsigned int', 4),
- ('char *', SIZE_OF_PTR),
- ('int[5]', 20),
- ('struct four_s', 12),
- ('union four_u', 4),
- ]:
- size = ffi.sizeof(c_type)
- assert size == expected_size, (size, expected_size, ctype)
-
- def test_sizeof_cdata(self):
- assert ffi.sizeof(ffi.new("short*")) == SIZE_OF_PTR
- assert ffi.sizeof(ffi.cast("short", 123)) == SIZE_OF_SHORT
- #
- a = ffi.new("int[]", [10, 11, 12, 13, 14])
- assert len(a) == 5
- assert ffi.sizeof(a) == 5 * SIZE_OF_INT
-
- def test_string_from_char_pointer(self):
- x = ffi.new("char*", b"x")
- assert str(x) == repr(x)
- assert ffi.string(x) == b"x"
- assert ffi.string(ffi.new("char*", b"\x00")) == b""
- py.test.raises(TypeError, ffi.new, "char*", unicode("foo"))
-
- def test_unicode_from_wchar_pointer(self):
- self.check_wchar_t(ffi)
- x = ffi.new("wchar_t*", u+"x")
- assert unicode(x) == unicode(repr(x))
- assert ffi.string(x) == u+"x"
- assert ffi.string(ffi.new("wchar_t*", u+"\x00")) == u+""
-
- def test_string_from_char_array(self):
- p = ffi.new("char[]", b"hello.")
- p[5] = b'!'
- assert ffi.string(p) == b"hello!"
- p[6] = b'?'
- assert ffi.string(p) == b"hello!?"
- p[3] = b'\x00'
- assert ffi.string(p) == b"hel"
- assert ffi.string(p, 2) == b"he"
- with pytest.raises(IndexError):
- p[7] = b'X'
- #
- a = ffi.new("char[]", b"hello\x00world")
- assert len(a) == 12
- p = ffi.cast("char *", a)
- assert ffi.string(p) == b'hello'
-
- def test_string_from_wchar_array(self):
- self.check_wchar_t(ffi)
- assert ffi.string(ffi.cast("wchar_t", "x")) == u+"x"
- assert ffi.string(ffi.cast("wchar_t", u+"x")) == u+"x"
- x = ffi.cast("wchar_t", "x")
- assert str(x) == repr(x)
- assert ffi.string(x) == u+"x"
- #
- p = ffi.new("wchar_t[]", u+"hello.")
- p[5] = u+'!'
- assert ffi.string(p) == u+"hello!"
- p[6] = u+'\u04d2'
- assert ffi.string(p) == u+"hello!\u04d2"
- p[3] = u+'\x00'
- assert ffi.string(p) == u+"hel"
- assert ffi.string(p, 123) == u+"hel"
- with pytest.raises(IndexError):
- p[7] = u+'X'
- #
- a = ffi.new("wchar_t[]", u+"hello\x00world")
- assert len(a) == 12
- p = ffi.cast("wchar_t *", a)
- assert ffi.string(p) == u+'hello'
- assert ffi.string(p, 123) == u+'hello'
- assert ffi.string(p, 5) == u+'hello'
- assert ffi.string(p, 2) == u+'he'
-
- def test_fetch_const_char_p_field(self):
- # 'const' is ignored so far, in the declaration of 'struct string'
- t = ffi.new("const char[]", b"testing")
- s = ffi.new("struct string*", [t])
- assert type(s.name) not in (bytes, str, unicode)
- assert ffi.string(s.name) == b"testing"
- with pytest.raises(TypeError):
- s.name = None
- s.name = ffi.NULL
- assert s.name == ffi.NULL
-
- def test_fetch_const_wchar_p_field(self):
- # 'const' is ignored so far
- self.check_wchar_t(ffi)
- t = ffi.new("const wchar_t[]", u+"testing")
- s = ffi.new("struct ustring*", [t])
- assert type(s.name) not in (bytes, str, unicode)
- assert ffi.string(s.name) == u+"testing"
- s.name = ffi.NULL
- assert s.name == ffi.NULL
-
- def test_voidp(self):
- py.test.raises(TypeError, ffi.new, "void*")
- p = ffi.new("void **")
- assert p[0] == ffi.NULL
- a = ffi.new("int[]", [10, 11, 12])
- p = ffi.new("void **", a)
- vp = p[0]
- with pytest.raises(TypeError):
- vp[0]
- py.test.raises(TypeError, ffi.new, "short **", a)
- #
- s = ffi.new("struct voidp *")
- s.p = a # works
- s.q = a # works
- with pytest.raises(TypeError):
- s.r = a # fails
- b = ffi.cast("int *", a)
- s.p = b # works
- s.q = b # works
- with pytest.raises(TypeError):
- s.r = b # fails
-
- def test_functionptr_simple(self):
- py.test.raises(TypeError, ffi.callback, "int(*)(int)", 0)
- def cb(n):
- return n + 1
- cb.__qualname__ = 'cb'
- p = ffi.callback("int(*)(int)", cb)
- res = p(41) # calling an 'int(*)(int)', i.e. a function pointer
- assert res == 42 and type(res) is int
- res = p(ffi.cast("int", -41))
- assert res == -40 and type(res) is int
- assert repr(p).startswith(
- "<cdata 'int(*)(int)' calling <function cb at 0x")
- assert ffi.typeof(p) is ffi.typeof("int(*)(int)")
- q = ffi.new("int(**)(int)", p)
- assert repr(q) == "<cdata 'int(* *)(int)' owning %d bytes>" % (
- SIZE_OF_PTR)
- with pytest.raises(TypeError):
- q(43)
- res = q[0](43)
- assert res == 44
- q = ffi.cast("int(*)(int)", p)
- assert repr(q).startswith("<cdata 'int(*)(int)' 0x")
- res = q(45)
- assert res == 46
-
- def test_functionptr_advanced(self):
- t = ffi.typeof("int(*(*)(int))(int)")
- assert repr(t) == "<ctype '%s'>" % "int(*(*)(int))(int)"
-
- def test_functionptr_voidptr_return(self):
- def cb():
- return ffi.NULL
- p = ffi.callback("void*(*)()", cb)
- res = p()
- assert res is not None
- assert res == ffi.NULL
- int_ptr = ffi.new('int*')
- void_ptr = ffi.cast('void*', int_ptr)
- def cb():
- return void_ptr
- p = ffi.callback("void*(*)()", cb)
- res = p()
- assert res == void_ptr
-
- def test_functionptr_intptr_return(self):
- def cb():
- return ffi.NULL
- p = ffi.callback("int*(*)()", cb)
- res = p()
- assert res == ffi.NULL
- int_ptr = ffi.new('int*')
- def cb():
- return int_ptr
- p = ffi.callback("int*(*)()", cb)
- res = p()
- assert repr(res).startswith("<cdata 'int *' 0x")
- assert res == int_ptr
- int_array_ptr = ffi.new('int[1]')
- def cb():
- return int_array_ptr
- p = ffi.callback("int*(*)()", cb)
- res = p()
- assert repr(res).startswith("<cdata 'int *' 0x")
- assert res == int_array_ptr
-
- def test_functionptr_void_return(self):
- def foo():
- pass
- foo_cb = ffi.callback("void foo()", foo)
- result = foo_cb()
- assert result is None
-
- def test_char_cast(self):
- p = ffi.cast("int", b'\x01')
- assert ffi.typeof(p) is ffi.typeof("int")
- assert int(p) == 1
- p = ffi.cast("int", ffi.cast("char", b"a"))
- assert int(p) == ord("a")
- p = ffi.cast("int", ffi.cast("char", b"\x80"))
- assert int(p) == 0x80 # "char" is considered unsigned in this case
- p = ffi.cast("int", b"\x81")
- assert int(p) == 0x81
-
- def test_wchar_cast(self):
- self.check_wchar_t(ffi)
- p = ffi.cast("int", ffi.cast("wchar_t", u+'\u1234'))
- assert int(p) == 0x1234
- p = ffi.cast("long long", ffi.cast("wchar_t", -1))
- if SIZE_OF_WCHAR == 2: # 2 bytes, unsigned
- assert int(p) == 0xffff
- elif (sys.platform.startswith('linux') and
- platform.machine().startswith('x86')): # known to be signed
- assert int(p) == -1
- else: # in general, it can be either signed or not
- assert int(p) in [-1, 0xffffffff] # e.g. on arm, both cases occur
- p = ffi.cast("int", u+'\u1234')
- assert int(p) == 0x1234
-
- def test_cast_array_to_charp(self):
- a = ffi.new("short int[]", [0x1234, 0x5678])
- p = ffi.cast("char*", a)
- data = b''.join([p[i] for i in range(4)])
- if sys.byteorder == 'little':
- assert data == b'\x34\x12\x78\x56'
- else:
- assert data == b'\x12\x34\x56\x78'
-
- def test_cast_between_pointers(self):
- a = ffi.new("short int[]", [0x1234, 0x5678])
- p = ffi.cast("short*", a)
- p2 = ffi.cast("int*", p)
- q = ffi.cast("char*", p2)
- data = b''.join([q[i] for i in range(4)])
- if sys.byteorder == 'little':
- assert data == b'\x34\x12\x78\x56'
- else:
- assert data == b'\x12\x34\x56\x78'
-
- def test_cast_pointer_and_int(self):
- a = ffi.new("short int[]", [0x1234, 0x5678])
- l1 = ffi.cast("intptr_t", a)
- p = ffi.cast("short*", a)
- l2 = ffi.cast("intptr_t", p)
- assert int(l1) == int(l2) != 0
- q = ffi.cast("short*", l1)
- assert q == ffi.cast("short*", int(l1))
- assert q[0] == 0x1234
- assert int(ffi.cast("intptr_t", ffi.NULL)) == 0
-
- def test_cast_functionptr_and_int(self):
- def cb(n):
- return n + 1
- a = ffi.callback("int(*)(int)", cb)
- p = ffi.cast("void *", a)
- assert p
- b = ffi.cast("int(*)(int)", p)
- assert b(41) == 42
- assert a == b
- assert hash(a) == hash(b)
-
- def test_callback_crash(self):
- def cb(n):
- raise Exception
- a = ffi.callback("int(*)(int)", cb, error=42)
- res = a(1) # and the error reported to stderr
- assert res == 42
-
- def test_structptr_argument(self):
- def cb(p):
- return p[0].a * 1000 + p[0].b * 100 + p[1].a * 10 + p[1].b
- a = ffi.callback("int(*)(struct ab[])", cb)
- res = a([[5, 6], {'a': 7, 'b': 8}])
- assert res == 5678
- res = a([[5], {'b': 8}])
- assert res == 5008
-
- def test_array_argument_as_list(self):
- seen = []
- def cb(argv):
- seen.append(ffi.string(argv[0]))
- seen.append(ffi.string(argv[1]))
- a = ffi.callback("void(*)(char *[])", cb)
- a([ffi.new("char[]", b"foobar"), ffi.new("char[]", b"baz")])
- assert seen == [b"foobar", b"baz"]
-
- def test_cast_float(self):
- a = ffi.cast("float", 12)
- assert float(a) == 12.0
- a = ffi.cast("float", 12.5)
- assert float(a) == 12.5
- a = ffi.cast("float", b"A")
- assert float(a) == ord("A")
- a = ffi.cast("int", 12.9)
- assert int(a) == 12
- a = ffi.cast("char", 66.9 + 256)
- assert ffi.string(a) == b"B"
- #
- a = ffi.cast("float", ffi.cast("int", 12))
- assert float(a) == 12.0
- a = ffi.cast("float", ffi.cast("double", 12.5))
- assert float(a) == 12.5
- a = ffi.cast("float", ffi.cast("char", b"A"))
- assert float(a) == ord("A")
- a = ffi.cast("int", ffi.cast("double", 12.9))
- assert int(a) == 12
- a = ffi.cast("char", ffi.cast("double", 66.9 + 256))
- assert ffi.string(a) == b"B"
-
- def test_enum(self):
- # enum foq { A0, B0, CC0, D0 };
- assert ffi.string(ffi.cast("enum foq", 0)) == "cffiA0"
- assert ffi.string(ffi.cast("enum foq", 2)) == "cffiCC0"
- assert ffi.string(ffi.cast("enum foq", 3)) == "cffiD0"
- assert ffi.string(ffi.cast("enum foq", 4)) == "4"
- # enum bar { A1, B1=-2, CC1, D1, E1 };
- assert ffi.string(ffi.cast("enum bar", 0)) == "A1"
- assert ffi.string(ffi.cast("enum bar", -2)) == "B1"
- assert ffi.string(ffi.cast("enum bar", -1)) == "CC1"
- assert ffi.string(ffi.cast("enum bar", 1)) == "E1"
- assert ffi.cast("enum bar", -2) == ffi.cast("enum bar", -2)
- assert ffi.cast("enum foq", 0) == ffi.cast("enum bar", 0)
- assert ffi.cast("enum bar", 0) == ffi.cast("int", 0)
- assert repr(ffi.cast("enum bar", -1)) == "<cdata 'enum bar' -1: CC1>"
- assert repr(ffi.cast("enum foq", -1)) == ( # enums are unsigned, if
- "<cdata 'enum foq' 4294967295>") or ( # they contain no neg value
- sys.platform == "win32") # (but not on msvc)
- # enum baz { A2=0x1000, B2=0x2000 };
- assert ffi.string(ffi.cast("enum baz", 0x1000)) == "A2"
- assert ffi.string(ffi.cast("enum baz", 0x2000)) == "B2"
-
- def test_enum_in_struct(self):
- # enum foo2 { A3, B3, C3, D3 };
- # struct bar_with_e { enum foo2 e; };
- s = ffi.new("struct bar_with_e *")
- s.e = 0
- assert s.e == 0
- s.e = 3
- assert s.e == 3
- assert s[0].e == 3
- s[0].e = 2
- assert s.e == 2
- assert s[0].e == 2
- s.e = ffi.cast("enum foo2", -1)
- assert s.e in (4294967295, -1) # two choices
- assert s[0].e in (4294967295, -1)
- s.e = s.e
- with pytest.raises(TypeError):
- s.e = 'B3'
- with pytest.raises(TypeError):
- s.e = '2'
- with pytest.raises(TypeError):
- s.e = '#2'
- with pytest.raises(TypeError):
- s.e = '#7'
-
- def test_enum_non_contiguous(self):
- # enum noncont { A4, B4=42, C4 };
- assert ffi.string(ffi.cast("enum noncont", 0)) == "A4"
- assert ffi.string(ffi.cast("enum noncont", 42)) == "B4"
- assert ffi.string(ffi.cast("enum noncont", 43)) == "C4"
- invalid_value = ffi.cast("enum noncont", 2)
- assert int(invalid_value) == 2
- assert ffi.string(invalid_value) == "2"
-
- def test_enum_char_hex_oct(self):
- # enum etypes {A5='!', B5='\'', C5=0x10, D5=010, E5=- 0x10, F5=-010};
- assert ffi.string(ffi.cast("enum etypes", ord('!'))) == "A5"
- assert ffi.string(ffi.cast("enum etypes", ord("'"))) == "B5"
- assert ffi.string(ffi.cast("enum etypes", 16)) == "C5"
- assert ffi.string(ffi.cast("enum etypes", 8)) == "D5"
- assert ffi.string(ffi.cast("enum etypes", -16)) == "E5"
- assert ffi.string(ffi.cast("enum etypes", -8)) == "F5"
-
- def test_array_of_struct(self):
- s = ffi.new("struct ab[1]")
- with pytest.raises(AttributeError):
- s.b
- with pytest.raises(AttributeError):
- s.b = 412
- s[0].b = 412
- assert s[0].b == 412
- with pytest.raises(IndexError):
- s[1]
-
- def test_pointer_to_array(self):
- p = ffi.new("int(**)[5]")
- assert repr(p) == "<cdata 'int(* *)[5]' owning %d bytes>" % SIZE_OF_PTR
-
- def test_iterate_array(self):
- a = ffi.new("char[]", b"hello")
- assert list(a) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
- assert list(iter(a)) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
- #
- py.test.raises(TypeError, iter, ffi.cast("char *", a))
- py.test.raises(TypeError, list, ffi.cast("char *", a))
- py.test.raises(TypeError, iter, ffi.new("int *"))
- py.test.raises(TypeError, list, ffi.new("int *"))
-
- def test_offsetof(self):
- # struct abc { int a, b, c; };
- assert ffi.offsetof("struct abc", "a") == 0
- assert ffi.offsetof("struct abc", "b") == 4
- assert ffi.offsetof("struct abc", "c") == 8
-
- def test_offsetof_nested(self):
- # struct nesting { struct abc d, e; };
- assert ffi.offsetof("struct nesting", "e") == 12
- py.test.raises(KeyError, ffi.offsetof, "struct nesting", "e.a")
- assert ffi.offsetof("struct nesting", "e", "a") == 12
- assert ffi.offsetof("struct nesting", "e", "b") == 16
- assert ffi.offsetof("struct nesting", "e", "c") == 20
-
- def test_offsetof_array(self):
- assert ffi.offsetof("int[]", 51) == 51 * ffi.sizeof("int")
- assert ffi.offsetof("int *", 51) == 51 * ffi.sizeof("int")
- # struct array2 { int a, b; int c[99]; };
- assert ffi.offsetof("struct array2", "c") == 2 * ffi.sizeof("int")
- assert ffi.offsetof("struct array2", "c", 0) == 2 * ffi.sizeof("int")
- assert ffi.offsetof("struct array2", "c", 51) == 53 * ffi.sizeof("int")
-
- def test_alignof(self):
- # struct align { char a; short b; char c; };
- assert ffi.alignof("int") == 4
- assert ffi.alignof("double") in (4, 8)
- assert ffi.alignof("struct align") == 2
-
- def test_bitfield(self):
- # struct bitfield { int a:10, b:20, c:3; };
- assert ffi.sizeof("struct bitfield") == 8
- s = ffi.new("struct bitfield *")
- s.a = 511
- with pytest.raises(OverflowError):
- s.a = 512
- with pytest.raises(OverflowError):
- s[0].a = 512
- assert s.a == 511
- s.a = -512
- with pytest.raises(OverflowError):
- s.a = -513
- with pytest.raises(OverflowError):
- s[0].a = -513
- assert s.a == -512
- s.c = 3
- assert s.c == 3
- with pytest.raises(OverflowError):
- s.c = 4
- with pytest.raises(OverflowError):
- s[0].c = 4
- s.c = -4
- assert s.c == -4
-
- def test_bitfield_enum(self):
- # typedef enum { AA1, BB1, CC1 } foo_e_t;
- # typedef struct { foo_e_t f:2; } bfenum_t;
- if sys.platform == "win32":
- py.test.skip("enums are not unsigned")
- s = ffi.new("bfenum_t *")
- s.f = 2
- assert s.f == 2
-
- def test_anonymous_struct(self):
- # typedef struct { int a; } anon_foo_t;
- # typedef struct { char b, c; } anon_bar_t;
- f = ffi.new("anon_foo_t *", [12345])
- b = ffi.new("anon_bar_t *", [b"B", b"C"])
- assert f.a == 12345
- assert b.b == b"B"
- assert b.c == b"C"
- assert repr(b).startswith("<cdata 'anon_bar_t *'")
-
- def test_struct_with_two_usages(self):
- # typedef struct named_foo_s { int a; } named_foo_t, *named_foo_p;
- # typedef struct { int a; } unnamed_foo_t, *unnamed_foo_p;
- f = ffi.new("named_foo_t *", [12345])
- ps = ffi.new("named_foo_p[]", [f])
- f = ffi.new("unnamed_foo_t *", [12345])
- ps = ffi.new("unnamed_foo_p[]", [f])
-
- def test_pointer_arithmetic(self):
- s = ffi.new("short[]", list(range(100, 110)))
- p = ffi.cast("short *", s)
- assert p[2] == 102
- assert p+1 == p+1
- assert p+1 != p+0
- assert p == p+0 == p-0
- assert (p+1)[0] == 101
- assert (p+19)[-10] == 109
- assert (p+5) - (p+1) == 4
- assert p == s+0
- assert p+1 == s+1
-
- def test_pointer_comparison(self):
- s = ffi.new("short[]", list(range(100)))
- p = ffi.cast("short *", s)
- assert (p < s) is False
- assert (p <= s) is True
- assert (p == s) is True
- assert (p != s) is False
- assert (p > s) is False
- assert (p >= s) is True
- assert (s < p) is False
- assert (s <= p) is True
- assert (s == p) is True
- assert (s != p) is False
- assert (s > p) is False
- assert (s >= p) is True
- q = p + 1
- assert (q < s) is False
- assert (q <= s) is False
- assert (q == s) is False
- assert (q != s) is True
- assert (q > s) is True
- assert (q >= s) is True
- assert (s < q) is True
- assert (s <= q) is True
- assert (s == q) is False
- assert (s != q) is True
- assert (s > q) is False
- assert (s >= q) is False
- assert (q < p) is False
- assert (q <= p) is False
- assert (q == p) is False
- assert (q != p) is True
- assert (q > p) is True
- assert (q >= p) is True
- assert (p < q) is True
- assert (p <= q) is True
- assert (p == q) is False
- assert (p != q) is True
- assert (p > q) is False
- assert (p >= q) is False
- #
- assert (None == s) is False
- assert (None != s) is True
- assert (s == None) is False
- assert (s != None) is True
- assert (None == q) is False
- assert (None != q) is True
- assert (q == None) is False
- assert (q != None) is True
-
- def test_integer_comparison(self):
- x = ffi.cast("int", 123)
- y = ffi.cast("int", 456)
- assert x < y
- #
- z = ffi.cast("double", 78.9)
- assert x > z
- assert y > z
-
- def test_ffi_buffer_ptr(self):
- a = ffi.new("short *", 100)
- try:
- b = ffi.buffer(a)
- except NotImplementedError as e:
- py.test.skip(str(e))
- content = b[:]
- assert len(content) == len(b) == 2
- if sys.byteorder == 'little':
- assert content == b'\x64\x00'
- assert b[0] == b'\x64'
- b[0] = b'\x65'
- else:
- assert content == b'\x00\x64'
- assert b[1] == b'\x64'
- b[1] = b'\x65'
- assert a[0] == 101
-
- def test_ffi_buffer_array(self):
- a = ffi.new("int[]", list(range(100, 110)))
- try:
- b = ffi.buffer(a)
- except NotImplementedError as e:
- py.test.skip(str(e))
- content = b[:]
- if sys.byteorder == 'little':
- assert content.startswith(b'\x64\x00\x00\x00\x65\x00\x00\x00')
- b[4] = b'\x45'
- else:
- assert content.startswith(b'\x00\x00\x00\x64\x00\x00\x00\x65')
- b[7] = b'\x45'
- assert len(content) == 4 * 10
- assert a[1] == 0x45
-
- def test_ffi_buffer_ptr_size(self):
- a = ffi.new("short *", 0x4243)
- try:
- b = ffi.buffer(a, 1)
- except NotImplementedError as e:
- py.test.skip(str(e))
- content = b[:]
- assert len(content) == 1
- if sys.byteorder == 'little':
- assert content == b'\x43'
- b[0] = b'\x62'
- assert a[0] == 0x4262
- else:
- assert content == b'\x42'
- b[0] = b'\x63'
- assert a[0] == 0x6343
-
- def test_ffi_buffer_array_size(self):
- a1 = ffi.new("int[]", list(range(100, 110)))
- a2 = ffi.new("int[]", list(range(100, 115)))
- try:
- ffi.buffer(a1)
- except NotImplementedError as e:
- py.test.skip(str(e))
- assert ffi.buffer(a1)[:] == ffi.buffer(a2, 4*10)[:]
-
- def test_ffi_buffer_with_file(self):
- import tempfile, os, array
- fd, filename = tempfile.mkstemp()
- f = os.fdopen(fd, 'r+b')
- a = ffi.new("int[]", list(range(1005)))
- try:
- ffi.buffer(a, 512)
- except NotImplementedError as e:
- py.test.skip(str(e))
- f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
- f.seek(0)
- assert f.read() == arraytostring(array.array('i', range(1000)))
- f.seek(0)
- b = ffi.new("int[]", 1005)
- f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
- assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
- f.close()
- os.unlink(filename)
-
- def test_ffi_buffer_with_io(self):
- import io, array
- f = io.BytesIO()
- a = ffi.new("int[]", list(range(1005)))
- try:
- ffi.buffer(a, 512)
- except NotImplementedError as e:
- py.test.skip(str(e))
- f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
- f.seek(0)
- assert f.read() == arraytostring(array.array('i', range(1000)))
- f.seek(0)
- b = ffi.new("int[]", 1005)
- f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
- assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
- f.close()
-
- def test_array_in_struct(self):
- # struct array { int a[2]; char b[3]; };
- p = ffi.new("struct array *")
- p.a[1] = 5
- assert p.a[1] == 5
- assert repr(p.a).startswith("<cdata 'int[2]' 0x")
-
- def test_struct_containing_array_varsize_workaround(self):
- if sys.platform == "win32":
- py.test.skip("array of length 0 not supported")
- # struct array0 { int len; short data[0]; };
- p = ffi.new("char[]", ffi.sizeof("struct array0") + 7 * SIZE_OF_SHORT)
- q = ffi.cast("struct array0 *", p)
- assert q.len == 0
- # 'q.data' gets not a 'short[0]', but just a 'short *' instead
- assert repr(q.data).startswith("<cdata 'short *' 0x")
- assert q.data[6] == 0
- q.data[6] = 15
- assert q.data[6] == 15
-
- def test_new_struct_containing_array_varsize(self):
- py.test.skip("later?")
- ffi.cdef("struct foo_s { int len; short data[]; };")
- p = ffi.new("struct foo_s *", 10) # a single integer is the length
- assert p.len == 0
- assert p.data[9] == 0
- with pytest.raises(IndexError):
- p.data[10]
-
- def test_ffi_typeof_getcname(self):
- assert ffi.getctype("int") == "int"
- assert ffi.getctype("int", 'x') == "int x"
- assert ffi.getctype("int*") == "int *"
- assert ffi.getctype("int*", '') == "int *"
- assert ffi.getctype("int*", 'x') == "int * x"
- assert ffi.getctype("int", '*') == "int *"
- assert ffi.getctype("int", ' * x ') == "int * x"
- assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *"
- assert ffi.getctype("int", '[5]') == "int[5]"
- assert ffi.getctype("int[5]", '[6]') == "int[6][5]"
- assert ffi.getctype("int[5]", '(*)') == "int(*)[5]"
- # special-case for convenience: automatically put '()' around '*'
- assert ffi.getctype("int[5]", '*') == "int(*)[5]"
- assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]"
- assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]"
-
- def test_array_of_func_ptr(self):
- f = ffi.cast("int(*)(int)", 42)
- assert f != ffi.NULL
- py.test.raises(ffi.error, ffi.cast, "int(int)", 42)
- py.test.raises(ffi.error, ffi.new, "int([5])(int)")
- a = ffi.new("int(*[5])(int)", [f])
- assert ffi.getctype(ffi.typeof(a)) == "int(*[5])(int)"
- assert len(a) == 5
- assert a[0] == f
- assert a[1] == ffi.NULL
- py.test.raises(TypeError, ffi.cast, "int(*)(int)[5]", 0)
- #
- def cb(n):
- return n + 1
- f = ffi.callback("int(*)(int)", cb)
- a = ffi.new("int(*[5])(int)", [f, f])
- assert a[1](42) == 43
-
- def test_callback_as_function_argument(self):
- # In C, function arguments can be declared with a function type,
- # which is automatically replaced with the ptr-to-function type.
- def cb(a, b):
- return chr(ord(a) + ord(b)).encode()
- f = ffi.callback("char cb(char, char)", cb)
- assert f(b'A', b'\x01') == b'B'
- def g(callback):
- return callback(b'A', b'\x01')
- g = ffi.callback("char g(char cb(char, char))", g)
- assert g(f) == b'B'
-
- def test_vararg_callback(self):
- py.test.skip("callback with '...'")
- def cb(i, va_list):
- j = ffi.va_arg(va_list, "int")
- k = ffi.va_arg(va_list, "long long")
- return i * 2 + j * 3 + k * 5
- f = ffi.callback("long long cb(long i, ...)", cb)
- res = f(10, ffi.cast("int", 100), ffi.cast("long long", 1000))
- assert res == 20 + 300 + 5000
-
- def test_callback_decorator(self):
- #
- @ffi.callback("long(long, long)", error=42)
- def cb(a, b):
- return a - b
- #
- assert cb(-100, -10) == -90
- sz = ffi.sizeof("long")
- assert cb((1 << (sz*8-1)) - 1, -10) == 42
-
- def test_anonymous_enum(self):
- # typedef enum { Value0 = 0 } e_t, *pe_t;
- assert ffi.getctype("e_t*") == 'e_t *'
- assert ffi.getctype("pe_t") == 'e_t *'
- assert ffi.getctype("foo_e_t*") == 'foo_e_t *'
-
- def test_new_ctype(self):
- p = ffi.new("int *")
- py.test.raises(TypeError, ffi.new, p)
- p = ffi.new(ffi.typeof("int *"), 42)
- assert p[0] == 42
-
- def test_enum_with_non_injective_mapping(self):
- # enum e_noninj { AA3=0, BB3=0, CC3=0, DD3=0 };
- e = ffi.cast("enum e_noninj", 0)
- assert ffi.string(e) == "AA3" # pick the first one arbitrarily
-
- def test_enum_refer_previous_enum_value(self):
- # enum e_prev { AA4, BB4=2, CC4=4, DD4=BB4, EE4, FF4=CC4, GG4=FF4 };
- assert ffi.string(ffi.cast("enum e_prev", 2)) == "BB4"
- assert ffi.string(ffi.cast("enum e_prev", 3)) == "EE4"
- assert ffi.sizeof("char[DD4]") == 2
- assert ffi.sizeof("char[EE4]") == 3
- assert ffi.sizeof("char[FF4]") == 4
- assert ffi.sizeof("char[GG4]") == 4
-
- def test_nested_anonymous_struct(self):
- # struct nested_anon {
- # struct { int a, b; };
- # union { int c, d; };
- # };
- assert ffi.sizeof("struct nested_anon") == 3 * SIZE_OF_INT
- p = ffi.new("struct nested_anon *", [1, 2, 3])
- assert p.a == 1
- assert p.b == 2
- assert p.c == 3
- assert p.d == 3
- p.d = 17
- assert p.c == 17
- p.b = 19
- assert p.a == 1
- assert p.b == 19
- assert p.c == 17
- assert p.d == 17
- p = ffi.new("struct nested_anon *", {'b': 12, 'd': 14})
- assert p.a == 0
- assert p.b == 12
- assert p.c == 14
- assert p.d == 14
-
- def test_nested_field_offset_align(self):
- # struct nested_field_ofs_s {
- # struct { int a; char b; };
- # union { char c; };
- # };
- assert ffi.offsetof("struct nested_field_ofs_s", "c") == 2 * SIZE_OF_INT
- assert ffi.sizeof("struct nested_field_ofs_s") == 3 * SIZE_OF_INT
-
- def test_nested_anonymous_union(self):
- # union nested_anon_u {
- # struct { int a, b; };
- # union { int c, d; };
- # };
- assert ffi.sizeof("union nested_anon_u") == 2 * SIZE_OF_INT
- p = ffi.new("union nested_anon_u *", [5])
- assert p.a == 5
- assert p.b == 0
- assert p.c == 5
- assert p.d == 5
- p.d = 17
- assert p.c == 17
- assert p.a == 17
- p.b = 19
- assert p.a == 17
- assert p.b == 19
- assert p.c == 17
- assert p.d == 17
- p = ffi.new("union nested_anon_u *", {'d': 14})
- assert p.a == 14
- assert p.b == 0
- assert p.c == 14
- assert p.d == 14
- p = ffi.new("union nested_anon_u *", {'b': 12})
- assert p.a == 0
- assert p.b == 12
- assert p.c == 0
- assert p.d == 0
- # we cannot specify several items in the dict, even though
- # in theory in this particular case it would make sense
- # to give both 'a' and 'b'
-
- def test_cast_to_array_type(self):
- p = ffi.new("int[4]", [-5])
- q = ffi.cast("int[3]", p)
- assert q[0] == -5
- assert repr(q).startswith("<cdata 'int[3]' 0x")
-
- def test_gc(self):
- p = ffi.new("int *", 123)
- seen = []
- def destructor(p1):
- assert p1 is p
- assert p1[0] == 123
- seen.append(1)
- q = ffi.gc(p, destructor=destructor)
- import gc; gc.collect()
- assert seen == []
- del q
- import gc; gc.collect(); gc.collect(); gc.collect()
- assert seen == [1]
-
- def test_gc_2(self):
- p = ffi.new("int *", 123)
- seen = []
- q1 = ffi.gc(p, lambda p: seen.append(1))
- q2 = ffi.gc(q1, lambda p: seen.append(2))
- import gc; gc.collect()
- assert seen == []
- del q1, q2
- import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
- assert seen == [2, 1]
-
- def test_gc_3(self):
- p = ffi.new("int *", 123)
- r = ffi.new("int *", 123)
- seen = []
- seen_r = []
- q1 = ffi.gc(p, lambda p: seen.append(1))
- s1 = ffi.gc(r, lambda r: seen_r.append(4))
- q2 = ffi.gc(q1, lambda p: seen.append(2))
- s2 = ffi.gc(s1, lambda r: seen_r.append(5))
- q3 = ffi.gc(q2, lambda p: seen.append(3))
- import gc; gc.collect()
- assert seen == []
- assert seen_r == []
- del q1, q2, q3, s2, s1
- import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
- assert seen == [3, 2, 1]
- assert seen_r == [5, 4]
-
- def test_gc_4(self):
- p = ffi.new("int *", 123)
- seen = []
- q1 = ffi.gc(p, lambda p: seen.append(1))
- q2 = ffi.gc(q1, lambda p: seen.append(2))
- q3 = ffi.gc(q2, lambda p: seen.append(3))
- import gc; gc.collect()
- assert seen == []
- del q1, q3 # q2 remains, and has a hard ref to q1
- import gc; gc.collect(); gc.collect(); gc.collect()
- assert seen == [3]
-
- def test_release(self):
- p = ffi.new("int[]", 123)
- ffi.release(p)
- # here, reading p[0] might give garbage or segfault...
- ffi.release(p) # no effect
-
- def test_release_new_allocator(self):
- seen = []
- def myalloc(size):
- seen.append(size)
- return ffi.new("char[]", b"X" * size)
- def myfree(raw):
- seen.append(raw)
- alloc2 = ffi.new_allocator(alloc=myalloc, free=myfree)
- p = alloc2("int[]", 15)
- assert seen == [15 * 4]
- ffi.release(p)
- assert seen == [15 * 4, p]
- ffi.release(p) # no effect
- assert seen == [15 * 4, p]
- #
- del seen[:]
- p = alloc2("struct ab *")
- assert seen == [2 * 4]
- ffi.release(p)
- assert seen == [2 * 4, p]
- ffi.release(p) # no effect
- assert seen == [2 * 4, p]
-
- def test_CData_CType(self):
- assert isinstance(ffi.cast("int", 0), ffi.CData)
- assert isinstance(ffi.new("int *"), ffi.CData)
- assert not isinstance(ffi.typeof("int"), ffi.CData)
- assert not isinstance(ffi.cast("int", 0), ffi.CType)
- assert not isinstance(ffi.new("int *"), ffi.CType)
-
- def test_CData_CType_2(self):
- assert isinstance(ffi.typeof("int"), ffi.CType)
-
- def test_bool(self):
- assert int(ffi.cast("_Bool", 0.1)) == 1
- assert int(ffi.cast("_Bool", -0.0)) == 0
- assert int(ffi.cast("_Bool", b'\x02')) == 1
- assert int(ffi.cast("_Bool", b'\x00')) == 0
- assert int(ffi.cast("_Bool", b'\x80')) == 1
- assert ffi.new("_Bool *", False)[0] == 0
- assert ffi.new("_Bool *", 1)[0] == 1
- py.test.raises(OverflowError, ffi.new, "_Bool *", 2)
- py.test.raises(TypeError, ffi.string, ffi.cast("_Bool", 2))
-
- def test_addressof(self):
- p = ffi.new("struct ab *")
- a = ffi.addressof(p[0])
- assert repr(a).startswith("<cdata 'struct ab *' 0x")
- assert a == p
- py.test.raises(TypeError, ffi.addressof, p)
- py.test.raises((AttributeError, TypeError), ffi.addressof, 5)
- py.test.raises(TypeError, ffi.addressof, ffi.cast("int", 5))
-
- def test_addressof_field(self):
- p = ffi.new("struct ab *")
- b = ffi.addressof(p[0], 'b')
- assert repr(b).startswith("<cdata 'int *' 0x")
- assert int(ffi.cast("uintptr_t", b)) == (
- int(ffi.cast("uintptr_t", p)) + ffi.sizeof("int"))
- assert b == ffi.addressof(p, 'b')
- assert b != ffi.addressof(p, 'a')
-
- def test_addressof_field_nested(self):
- # struct nesting { struct abc d, e; };
- p = ffi.new("struct nesting *")
- py.test.raises(KeyError, ffi.addressof, p[0], 'e.b')
- a = ffi.addressof(p[0], 'e', 'b')
- assert int(ffi.cast("uintptr_t", a)) == (
- int(ffi.cast("uintptr_t", p)) +
- ffi.sizeof("struct abc") + ffi.sizeof("int"))
-
- def test_addressof_anonymous_struct(self):
- # typedef struct { int a; } anon_foo_t;
- p = ffi.new("anon_foo_t *")
- a = ffi.addressof(p[0])
- assert a == p
-
- def test_addressof_array(self):
- p = ffi.new("int[52]")
- p0 = ffi.addressof(p)
- assert p0 == p
- assert ffi.typeof(p0) is ffi.typeof("int(*)[52]")
- py.test.raises(TypeError, ffi.addressof, p0)
- #
- p1 = ffi.addressof(p, 25)
- assert ffi.typeof(p1) is ffi.typeof("int *")
- assert (p1 - p) == 25
- assert ffi.addressof(p, 0) == p
-
- def test_addressof_pointer(self):
- array = ffi.new("int[50]")
- p = ffi.cast("int *", array)
- py.test.raises(TypeError, ffi.addressof, p)
- assert ffi.addressof(p, 0) == p
- assert ffi.addressof(p, 25) == p + 25
- assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p)
- #
- array = ffi.new("struct ab[50]")
- p = ffi.cast("int *", array)
- py.test.raises(TypeError, ffi.addressof, p)
- assert ffi.addressof(p, 0) == p
- assert ffi.addressof(p, 25) == p + 25
- assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p)
-
- def test_addressof_array_in_struct(self):
- # struct abc50 { int a, b; int c[50]; };
- p = ffi.new("struct abc50 *")
- p1 = ffi.addressof(p, "c", 25)
- assert ffi.typeof(p1) is ffi.typeof("int *")
- assert p1 == ffi.cast("int *", p) + 27
- assert ffi.addressof(p, "c") == ffi.cast("int *", p) + 2
- assert ffi.addressof(p, "c", 0) == ffi.cast("int *", p) + 2
- p2 = ffi.addressof(p, 1)
- assert ffi.typeof(p2) is ffi.typeof("struct abc50 *")
- assert p2 == p + 1
-
- def test_multiple_independent_structs(self):
- CDEF2 = "struct ab { int x; };"
- ffi2 = cffi.FFI(); ffi2.cdef(CDEF2)
- outputfilename = recompile(ffi2, "test_multiple_independent_structs",
- CDEF2, tmpdir=str(udir))
- module = imp.load_dynamic("test_multiple_independent_structs",
- outputfilename)
- ffi1 = module.ffi
- foo1 = ffi1.new("struct ab *", [10])
- foo2 = ffi .new("struct ab *", [20, 30])
- assert foo1.x == 10
- assert foo2.a == 20
- assert foo2.b == 30
-
- def test_include_struct_union_enum_typedef(self):
- ffi1, CCODE = construction_params
- ffi2 = cffi.FFI()
- ffi2.include(ffi1)
- outputfilename = recompile(ffi2,
- "test_include_struct_union_enum_typedef",
- CCODE, tmpdir=str(udir))
- module = imp.load_dynamic("test_include_struct_union_enum_typedef",
- outputfilename)
- ffi2 = module.ffi
- #
- p = ffi2.new("struct nonpacked *", [b'A', -43141])
- assert p.a == b'A'
- assert p.b == -43141
- #
- p = ffi.new("union simple_u *", [-52525])
- assert p.a == -52525
- #
- p = ffi.cast("enum foq", 2)
- assert ffi.string(p) == "cffiCC0"
- assert ffi2.sizeof("char[cffiCC0]") == 2
- #
- p = ffi.new("anon_foo_t *", [-52526])
- assert p.a == -52526
- p = ffi.new("named_foo_p", [-52527])
- assert p.a == -52527
-
- def test_struct_packed(self):
- # struct nonpacked { char a; int b; };
- # struct is_packed { char a; int b; } __attribute__((packed));
- assert ffi.sizeof("struct nonpacked") == 8
- assert ffi.sizeof("struct is_packed") == 5
- assert ffi.alignof("struct nonpacked") == 4
- assert ffi.alignof("struct is_packed") == 1
- s = ffi.new("struct is_packed[2]")
- s[0].b = 42623381
- s[0].a = b'X'
- s[1].b = -4892220
- s[1].a = b'Y'
- assert s[0].b == 42623381
- assert s[0].a == b'X'
- assert s[1].b == -4892220
- assert s[1].a == b'Y'
-
- def test_not_supported_bitfield_in_result(self):
- # struct ints_and_bitfield { int a,b,c,d,e; int x:1; };
- e = py.test.raises(NotImplementedError, ffi.callback,
- "struct ints_and_bitfield foo(void)", lambda: 42)
- assert str(e.value) == ("struct ints_and_bitfield(*)(): "
- "callback with unsupported argument or return type or with '...'")
-
- def test_inspecttype(self):
- assert ffi.typeof("long").kind == "primitive"
- assert ffi.typeof("long(*)(long, long**, ...)").cname == (
- "long(*)(long, long * *, ...)")
- assert ffi.typeof("long(*)(long, long**, ...)").ellipsis is True
-
- def test_new_handle(self):
- o = [2, 3, 4]
- p = ffi.new_handle(o)
- assert ffi.typeof(p) == ffi.typeof("void *")
- assert ffi.from_handle(p) is o
- assert ffi.from_handle(ffi.cast("char *", p)) is o
- py.test.raises(RuntimeError, ffi.from_handle, ffi.NULL)
-
- def test_struct_array_no_length(self):
- # struct array_no_length { int x; int a[]; };
- p = ffi.new("struct array_no_length *", [100, [200, 300, 400]])
- assert p.x == 100
- assert ffi.typeof(p.a) is ffi.typeof("int[]") # length available
- assert p.a[0] == 200
- assert p.a[1] == 300
- assert p.a[2] == 400
- assert len(p.a) == 3
- assert list(p.a) == [200, 300, 400]
- q = ffi.cast("struct array_no_length *", p)
- assert ffi.typeof(q.a) is ffi.typeof("int *") # no length available
- assert q.a[0] == 200
- assert q.a[1] == 300
- assert q.a[2] == 400
- py.test.raises(TypeError, len, q.a)
- py.test.raises(TypeError, list, q.a)
-
- def test_all_primitives(self):
- assert set(PRIMITIVE_TO_INDEX) == set([
- "char",
- "short",
- "int",
- "long",
- "long long",
- "signed char",
- "unsigned char",
- "unsigned short",
- "unsigned int",
- "unsigned long",
- "unsigned long long",
- "float",
- "double",
- "long double",
- "wchar_t",
- "char16_t",
- "char32_t",
- "_Bool",
- "int8_t",
- "uint8_t",
- "int16_t",
- "uint16_t",
- "int32_t",
- "uint32_t",
- "int64_t",
- "uint64_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",
- "intptr_t",
- "uintptr_t",
- "intmax_t",
- "uintmax_t",
- "ptrdiff_t",
- "size_t",
- "ssize_t",
- 'float _Complex',
- 'double _Complex',
- ])
- for name in PRIMITIVE_TO_INDEX:
- x = ffi.sizeof(name)
- assert 1 <= x <= 16
-
- def test_emit_c_code(self):
- ffi = cffi.FFI()
- ffi.set_source("foobar", "??")
- c_file = str(udir.join('test_emit_c_code'))
- ffi.emit_c_code(c_file)
- assert os.path.isfile(c_file)
-
- def test_import_from_lib(self):
- ffi2 = cffi.FFI()
- ffi2.cdef("int myfunc(int); extern int myvar;\n#define MYFOO ...\n")
- outputfilename = recompile(ffi2, "_test_import_from_lib",
- "int myfunc(int x) { return x + 1; }\n"
- "int myvar = -5;\n"
- "#define MYFOO 42", tmpdir=str(udir))
- imp.load_dynamic("_test_import_from_lib", outputfilename)
- from _test_import_from_lib.lib import myfunc, myvar, MYFOO
- assert MYFOO == 42
- assert myfunc(43) == 44
- assert myvar == -5 # but can't be changed, so not very useful
- with pytest.raises(ImportError):
- from _test_import_from_lib.lib import bar
- d = {}
- exec("from _test_import_from_lib.lib import *", d)
- assert (set(key for key in d if not key.startswith('_')) ==
- set(['myfunc', 'MYFOO']))
- #
- # also test "import *" on the module itself, which should be
- # equivalent to "import ffi, lib"
- d = {}
- exec("from _test_import_from_lib import *", d)
- assert (sorted([x for x in d.keys() if not x.startswith('__')]) ==
- ['ffi', 'lib'])
-
- def test_char16_t(self):
- x = ffi.new("char16_t[]", 5)
- assert len(x) == 5 and ffi.sizeof(x) == 10
- x[2] = u+'\u1324'
- assert x[2] == u+'\u1324'
- y = ffi.new("char16_t[]", u+'\u1234\u5678')
- assert len(y) == 3
- assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
- assert ffi.string(y) == u+'\u1234\u5678'
- z = ffi.new("char16_t[]", u+'\U00012345')
- assert len(z) == 3
- assert list(z) == [u+'\ud808', u+'\udf45', u+'\x00']
- assert ffi.string(z) == u+'\U00012345'
-
- def test_char32_t(self):
- x = ffi.new("char32_t[]", 5)
- assert len(x) == 5 and ffi.sizeof(x) == 20
- x[3] = u+'\U00013245'
- assert x[3] == u+'\U00013245'
- y = ffi.new("char32_t[]", u+'\u1234\u5678')
- assert len(y) == 3
- assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
- z = ffi.new("char32_t[]", u+'\U00012345')
- assert len(z) == 2
- assert list(z) == [u+'\U00012345', u+'\x00'] # maybe a 2-unichars strin
- assert ffi.string(z) == u+'\U00012345'
diff --git a/testing/cffi1/test_parse_c_type.py b/testing/cffi1/test_parse_c_type.py
deleted file mode 100644
index a9f5fcb..0000000
--- a/testing/cffi1/test_parse_c_type.py
+++ /dev/null
@@ -1,372 +0,0 @@
-import sys, re, os, py
-import cffi
-from cffi import cffi_opcode
-
-if '__pypy__' in sys.builtin_module_names:
- try:
- # pytest >= 4.0
- py.test.skip("not available on pypy", allow_module_level=True)
- except TypeError:
- # older pytest
- py.test.skip("not available on pypy")
-
-cffi_dir = os.path.dirname(cffi_opcode.__file__)
-
-r_macro = re.compile(r"#define \w+[(][^\n]*|#include [^\n]*")
-r_define = re.compile(r"(#define \w+) [^\n]*")
-r_ifdefs = re.compile(r"(#ifdef |#endif)[^\n]*")
-header = open(os.path.join(cffi_dir, 'parse_c_type.h')).read()
-header = r_macro.sub(r"", header)
-header = r_define.sub(r"\1 ...", header)
-header = r_ifdefs.sub(r"", header)
-
-ffi = cffi.FFI()
-ffi.cdef(header)
-
-lib = ffi.verify(
- open(os.path.join(cffi_dir, '..', 'c', 'parse_c_type.c')).read() + """
-static const char *get_common_type(const char *search, size_t search_len) {
- return NULL;
-}
-""", include_dirs=[cffi_dir])
-
-class ParseError(Exception):
- pass
-
-struct_names = ["bar_s", "foo", "foo_", "foo_s", "foo_s1", "foo_s12"]
-assert struct_names == sorted(struct_names)
-
-enum_names = ["ebar_s", "efoo", "efoo_", "efoo_s", "efoo_s1", "efoo_s12"]
-assert enum_names == sorted(enum_names)
-
-identifier_names = ["id", "id0", "id05", "id05b", "tail"]
-assert identifier_names == sorted(identifier_names)
-
-global_names = ["FIVE", "NEG", "ZERO"]
-assert global_names == sorted(global_names)
-
-ctx = ffi.new("struct _cffi_type_context_s *")
-c_struct_names = [ffi.new("char[]", _n.encode('ascii')) for _n in struct_names]
-ctx_structs = ffi.new("struct _cffi_struct_union_s[]", len(struct_names))
-for _i in range(len(struct_names)):
- ctx_structs[_i].name = c_struct_names[_i]
-ctx_structs[3].flags = lib._CFFI_F_UNION
-ctx.struct_unions = ctx_structs
-ctx.num_struct_unions = len(struct_names)
-
-c_enum_names = [ffi.new("char[]", _n.encode('ascii')) for _n in enum_names]
-ctx_enums = ffi.new("struct _cffi_enum_s[]", len(enum_names))
-for _i in range(len(enum_names)):
- ctx_enums[_i].name = c_enum_names[_i]
-ctx.enums = ctx_enums
-ctx.num_enums = len(enum_names)
-
-c_identifier_names = [ffi.new("char[]", _n.encode('ascii'))
- for _n in identifier_names]
-ctx_identifiers = ffi.new("struct _cffi_typename_s[]", len(identifier_names))
-for _i in range(len(identifier_names)):
- ctx_identifiers[_i].name = c_identifier_names[_i]
- ctx_identifiers[_i].type_index = 100 + _i
-ctx.typenames = ctx_identifiers
-ctx.num_typenames = len(identifier_names)
-
-@ffi.callback("int(unsigned long long *)")
-def fetch_constant_five(p):
- p[0] = 5
- return 0
-@ffi.callback("int(unsigned long long *)")
-def fetch_constant_zero(p):
- p[0] = 0
- return 1
-@ffi.callback("int(unsigned long long *)")
-def fetch_constant_neg(p):
- p[0] = 123321
- return 1
-
-ctx_globals = ffi.new("struct _cffi_global_s[]", len(global_names))
-c_glob_names = [ffi.new("char[]", _n.encode('ascii')) for _n in global_names]
-for _i, _fn in enumerate([fetch_constant_five,
- fetch_constant_neg,
- fetch_constant_zero]):
- ctx_globals[_i].name = c_glob_names[_i]
- ctx_globals[_i].address = _fn
- ctx_globals[_i].type_op = ffi.cast("_cffi_opcode_t",
- cffi_opcode.OP_CONSTANT_INT if _i != 1
- else cffi_opcode.OP_ENUM)
-ctx.globals = ctx_globals
-ctx.num_globals = len(global_names)
-
-
-def parse(input):
- out = ffi.new("_cffi_opcode_t[]", 100)
- info = ffi.new("struct _cffi_parse_info_s *")
- info.ctx = ctx
- info.output = out
- info.output_size = len(out)
- for j in range(len(out)):
- out[j] = ffi.cast("void *", -424242)
- res = lib.parse_c_type(info, input.encode('ascii'))
- if res < 0:
- raise ParseError(ffi.string(info.error_message).decode('ascii'),
- info.error_location)
- assert 0 <= res < len(out)
- result = []
- for j in range(len(out)):
- if out[j] == ffi.cast("void *", -424242):
- assert res < j
- break
- i = int(ffi.cast("intptr_t", out[j]))
- if j == res:
- result.append('->')
- result.append(i)
- return result
-
-def parsex(input):
- result = parse(input)
- def str_if_int(x):
- if isinstance(x, str):
- return x
- return '%d,%d' % (x & 255, x >> 8)
- return ' '.join(map(str_if_int, result))
-
-def parse_error(input, expected_msg, expected_location):
- e = py.test.raises(ParseError, parse, input)
- assert e.value.args[0] == expected_msg
- assert e.value.args[1] == expected_location
-
-def make_getter(name):
- opcode = getattr(lib, '_CFFI_OP_' + name)
- def getter(value):
- return opcode | (value << 8)
- return getter
-
-Prim = make_getter('PRIMITIVE')
-Pointer = make_getter('POINTER')
-Array = make_getter('ARRAY')
-OpenArray = make_getter('OPEN_ARRAY')
-NoOp = make_getter('NOOP')
-Func = make_getter('FUNCTION')
-FuncEnd = make_getter('FUNCTION_END')
-Struct = make_getter('STRUCT_UNION')
-Enum = make_getter('ENUM')
-Typename = make_getter('TYPENAME')
-
-
-def test_simple():
- for simple_type, expected in [
- ("int", lib._CFFI_PRIM_INT),
- ("signed int", lib._CFFI_PRIM_INT),
- (" long ", lib._CFFI_PRIM_LONG),
- ("long int", lib._CFFI_PRIM_LONG),
- ("unsigned short", lib._CFFI_PRIM_USHORT),
- ("long double", lib._CFFI_PRIM_LONGDOUBLE),
- (" float _Complex", lib._CFFI_PRIM_FLOATCOMPLEX),
- ("double _Complex ", lib._CFFI_PRIM_DOUBLECOMPLEX),
- ]:
- assert parse(simple_type) == ['->', Prim(expected)]
-
-def test_array():
- assert parse("int[5]") == [Prim(lib._CFFI_PRIM_INT), '->', Array(0), 5]
- assert parse("int[]") == [Prim(lib._CFFI_PRIM_INT), '->', OpenArray(0)]
- assert parse("int[5][8]") == [Prim(lib._CFFI_PRIM_INT),
- '->', Array(3),
- 5,
- Array(0),
- 8]
- assert parse("int[][8]") == [Prim(lib._CFFI_PRIM_INT),
- '->', OpenArray(2),
- Array(0),
- 8]
-
-def test_pointer():
- assert parse("int*") == [Prim(lib._CFFI_PRIM_INT), '->', Pointer(0)]
- assert parse("int***") == [Prim(lib._CFFI_PRIM_INT),
- Pointer(0), Pointer(1), '->', Pointer(2)]
-
-def test_grouping():
- assert parse("int*[]") == [Prim(lib._CFFI_PRIM_INT),
- Pointer(0), '->', OpenArray(1)]
- assert parse("int**[][8]") == [Prim(lib._CFFI_PRIM_INT),
- Pointer(0), Pointer(1),
- '->', OpenArray(4), Array(2), 8]
- assert parse("int(*)[]") == [Prim(lib._CFFI_PRIM_INT),
- NoOp(3), '->', Pointer(1), OpenArray(0)]
- assert parse("int(*)[][8]") == [Prim(lib._CFFI_PRIM_INT),
- NoOp(3), '->', Pointer(1),
- OpenArray(4), Array(0), 8]
- assert parse("int**(**)") == [Prim(lib._CFFI_PRIM_INT),
- Pointer(0), Pointer(1),
- NoOp(2), Pointer(3), '->', Pointer(4)]
- assert parse("int**(**)[]") == [Prim(lib._CFFI_PRIM_INT),
- Pointer(0), Pointer(1),
- NoOp(6), Pointer(3), '->', Pointer(4),
- OpenArray(2)]
-
-def test_simple_function():
- assert parse("int()") == [Prim(lib._CFFI_PRIM_INT),
- '->', Func(0), FuncEnd(0), 0]
- assert parse("int(int)") == [Prim(lib._CFFI_PRIM_INT),
- '->', Func(0), NoOp(4), FuncEnd(0),
- Prim(lib._CFFI_PRIM_INT)]
- assert parse("int(long, char)") == [
- Prim(lib._CFFI_PRIM_INT),
- '->', Func(0), NoOp(5), NoOp(6), FuncEnd(0),
- Prim(lib._CFFI_PRIM_LONG),
- Prim(lib._CFFI_PRIM_CHAR)]
- assert parse("int(int*)") == [Prim(lib._CFFI_PRIM_INT),
- '->', Func(0), NoOp(5), FuncEnd(0),
- Prim(lib._CFFI_PRIM_INT),
- Pointer(4)]
- assert parse("int*(void)") == [Prim(lib._CFFI_PRIM_INT),
- Pointer(0),
- '->', Func(1), FuncEnd(0), 0]
- assert parse("int(int, ...)") == [Prim(lib._CFFI_PRIM_INT),
- '->', Func(0), NoOp(5), FuncEnd(1), 0,
- Prim(lib._CFFI_PRIM_INT)]
-
-def test_internal_function():
- assert parse("int(*)()") == [Prim(lib._CFFI_PRIM_INT),
- NoOp(3), '->', Pointer(1),
- Func(0), FuncEnd(0), 0]
- assert parse("int(*())[]") == [Prim(lib._CFFI_PRIM_INT),
- NoOp(6), Pointer(1),
- '->', Func(2), FuncEnd(0), 0,
- OpenArray(0)]
- assert parse("int(char(*)(long, short))") == [
- Prim(lib._CFFI_PRIM_INT),
- '->', Func(0), NoOp(6), FuncEnd(0),
- Prim(lib._CFFI_PRIM_CHAR),
- NoOp(7), Pointer(5),
- Func(4), NoOp(11), NoOp(12), FuncEnd(0),
- Prim(lib._CFFI_PRIM_LONG),
- Prim(lib._CFFI_PRIM_SHORT)]
-
-def test_fix_arg_types():
- assert parse("int(char(long, short))") == [
- Prim(lib._CFFI_PRIM_INT),
- '->', Func(0), Pointer(5), FuncEnd(0),
- Prim(lib._CFFI_PRIM_CHAR),
- Func(4), NoOp(9), NoOp(10), FuncEnd(0),
- Prim(lib._CFFI_PRIM_LONG),
- Prim(lib._CFFI_PRIM_SHORT)]
- assert parse("int(char[])") == [
- Prim(lib._CFFI_PRIM_INT),
- '->', Func(0), Pointer(4), FuncEnd(0),
- Prim(lib._CFFI_PRIM_CHAR),
- OpenArray(4)]
-
-def test_enum():
- for i in range(len(enum_names)):
- assert parse("enum %s" % (enum_names[i],)) == ['->', Enum(i)]
- assert parse("enum %s*" % (enum_names[i],)) == [Enum(i),
- '->', Pointer(0)]
-
-def test_error():
- parse_error("short short int", "'short' after another 'short' or 'long'", 6)
- parse_error("long long long", "'long long long' is too long", 10)
- parse_error("short long", "'long' after 'short'", 6)
- parse_error("signed unsigned int", "multiple 'signed' or 'unsigned'", 7)
- parse_error("unsigned signed int", "multiple 'signed' or 'unsigned'", 9)
- parse_error("long char", "invalid combination of types", 5)
- parse_error("short char", "invalid combination of types", 6)
- parse_error("signed void", "invalid combination of types", 7)
- parse_error("unsigned struct", "invalid combination of types", 9)
- #
- parse_error("", "identifier expected", 0)
- parse_error("]", "identifier expected", 0)
- parse_error("*", "identifier expected", 0)
- parse_error("int ]**", "unexpected symbol", 4)
- parse_error("char char", "unexpected symbol", 5)
- parse_error("int(int]", "expected ')'", 7)
- parse_error("int(*]", "expected ')'", 5)
- parse_error("int(]", "identifier expected", 4)
- parse_error("int[?]", "expected a positive integer constant", 4)
- parse_error("int[24)", "expected ']'", 6)
- parse_error("struct", "struct or union name expected", 6)
- parse_error("struct 24", "struct or union name expected", 7)
- parse_error("int[5](*)", "unexpected symbol", 6)
- parse_error("int a(*)", "identifier expected", 6)
- parse_error("int[123456789012345678901234567890]", "number too large", 4)
- #
- parse_error("_Complex", "identifier expected", 0)
- parse_error("int _Complex", "_Complex type combination unsupported", 4)
- parse_error("long double _Complex", "_Complex type combination unsupported",
- 12)
-
-def test_number_too_large():
- num_max = sys.maxsize
- assert parse("char[%d]" % num_max) == [Prim(lib._CFFI_PRIM_CHAR),
- '->', Array(0), num_max]
- parse_error("char[%d]" % (num_max + 1), "number too large", 5)
-
-def test_complexity_limit():
- parse_error("int" + "[]" * 2500, "internal type complexity limit reached",
- 202)
-
-def test_struct():
- for i in range(len(struct_names)):
- if i == 3:
- tag = "union"
- else:
- tag = "struct"
- assert parse("%s %s" % (tag, struct_names[i])) == ['->', Struct(i)]
- assert parse("%s %s*" % (tag, struct_names[i])) == [Struct(i),
- '->', Pointer(0)]
-
-def test_exchanging_struct_union():
- parse_error("union %s" % (struct_names[0],),
- "wrong kind of tag: struct vs union", 6)
- parse_error("struct %s" % (struct_names[3],),
- "wrong kind of tag: struct vs union", 7)
-
-def test_identifier():
- for i in range(len(identifier_names)):
- assert parse("%s" % (identifier_names[i])) == ['->', Typename(i)]
- assert parse("%s*" % (identifier_names[i])) == [Typename(i),
- '->', Pointer(0)]
-
-def test_cffi_opcode_sync():
- import cffi.model
- for name in dir(lib):
- if name.startswith('_CFFI_'):
- assert getattr(cffi_opcode, name[6:]) == getattr(lib, name)
- assert sorted(cffi_opcode.PRIMITIVE_TO_INDEX.keys()) == (
- sorted(cffi.model.PrimitiveType.ALL_PRIMITIVE_TYPES.keys()))
-
-def test_array_length_from_constant():
- parse_error("int[UNKNOWN]", "expected a positive integer constant", 4)
- assert parse("int[FIVE]") == [Prim(lib._CFFI_PRIM_INT), '->', Array(0), 5]
- assert parse("int[ZERO]") == [Prim(lib._CFFI_PRIM_INT), '->', Array(0), 0]
- parse_error("int[NEG]", "expected a positive integer constant", 4)
-
-def test_various_constant_exprs():
- def array(n):
- return [Prim(lib._CFFI_PRIM_CHAR), '->', Array(0), n]
- assert parse("char[21]") == array(21)
- assert parse("char[0x10]") == array(16)
- assert parse("char[0X21]") == array(33)
- assert parse("char[0Xb]") == array(11)
- assert parse("char[0x1C]") == array(0x1C)
- assert parse("char[0xc6]") == array(0xC6)
- assert parse("char[010]") == array(8)
- assert parse("char[021]") == array(17)
- parse_error("char[08]", "invalid number", 5)
- parse_error("char[1C]", "invalid number", 5)
- parse_error("char[0C]", "invalid number", 5)
- # not supported (really obscure):
- # "char[+5]"
- # "char['A']"
-
-def test_stdcall_cdecl():
- assert parse("int __stdcall(int)") == [Prim(lib._CFFI_PRIM_INT),
- '->', Func(0), NoOp(4), FuncEnd(2),
- Prim(lib._CFFI_PRIM_INT)]
- assert parse("int __stdcall func(int)") == parse("int __stdcall(int)")
- assert parse("int (__stdcall *)()") == [Prim(lib._CFFI_PRIM_INT),
- NoOp(3), '->', Pointer(1),
- Func(0), FuncEnd(2), 0]
- assert parse("int (__stdcall *p)()") == parse("int (__stdcall*)()")
- parse_error("__stdcall int", "identifier expected", 0)
- parse_error("__cdecl int", "identifier expected", 0)
- parse_error("int __stdcall", "expected '('", 13)
- parse_error("int __cdecl", "expected '('", 11)
diff --git a/testing/cffi1/test_pkgconfig.py b/testing/cffi1/test_pkgconfig.py
deleted file mode 100644
index c725cca..0000000
--- a/testing/cffi1/test_pkgconfig.py
+++ /dev/null
@@ -1,94 +0,0 @@
-import sys
-import subprocess
-import py
-import cffi.pkgconfig as pkgconfig
-from cffi import PkgConfigError
-
-
-def mock_call(libname, flag):
- assert libname=="foobarbaz"
- flags = {
- "--cflags": "-I/usr/include/python3.6m -DABCD -DCFFI_TEST=1 -O42\n",
- "--libs": "-L/usr/lib64 -lpython3.6 -shared\n",
- }
- return flags[flag]
-
-
-def test_merge_flags():
- d1 = {"ham": [1, 2, 3], "spam" : ["a", "b", "c"], "foo" : []}
- d2 = {"spam" : ["spam", "spam", "spam"], "bar" : ["b", "a", "z"]}
-
- pkgconfig.merge_flags(d1, d2)
- assert d1 == {
- "ham": [1, 2, 3],
- "spam" : ["a", "b", "c", "spam", "spam", "spam"],
- "bar" : ["b", "a", "z"],
- "foo" : []}
-
-
-def test_pkgconfig():
- assert pkgconfig.flags_from_pkgconfig([]) == {}
-
- saved = pkgconfig.call
- try:
- pkgconfig.call = mock_call
- flags = pkgconfig.flags_from_pkgconfig(["foobarbaz"])
- finally:
- pkgconfig.call = saved
- assert flags == {
- 'include_dirs': ['/usr/include/python3.6m'],
- 'library_dirs': ['/usr/lib64'],
- 'libraries': ['python3.6'],
- 'define_macros': [('ABCD', None), ('CFFI_TEST', '1')],
- 'extra_compile_args': ['-O42'],
- 'extra_link_args': ['-shared']
- }
-
-class mock_subprocess:
- PIPE = Ellipsis
- class Popen:
- def __init__(self, cmd, stdout, stderr):
- if mock_subprocess.RESULT is None:
- raise OSError("oops can't run")
- assert cmd == ['pkg-config', '--print-errors', '--cflags', 'libfoo']
- def communicate(self):
- bout, berr, rc = mock_subprocess.RESULT
- self.returncode = rc
- return bout, berr
-
-def test_call():
- saved = pkgconfig.subprocess
- try:
- pkgconfig.subprocess = mock_subprocess
-
- mock_subprocess.RESULT = None
- e = py.test.raises(PkgConfigError, pkgconfig.call, "libfoo", "--cflags")
- assert str(e.value) == "cannot run pkg-config: oops can't run"
-
- mock_subprocess.RESULT = b"", "Foo error!\n", 1
- e = py.test.raises(PkgConfigError, pkgconfig.call, "libfoo", "--cflags")
- assert str(e.value) == "Foo error!"
-
- mock_subprocess.RESULT = b"abc\\def\n", "", 0
- e = py.test.raises(PkgConfigError, pkgconfig.call, "libfoo", "--cflags")
- assert str(e.value).startswith("pkg-config --cflags libfoo returned an "
- "unsupported backslash-escaped output:")
-
- mock_subprocess.RESULT = b"abc def\n", "", 0
- result = pkgconfig.call("libfoo", "--cflags")
- assert result == "abc def\n"
-
- mock_subprocess.RESULT = b"abc def\n", "", 0
- result = pkgconfig.call("libfoo", "--cflags")
- assert result == "abc def\n"
-
- if sys.version_info >= (3,):
- mock_subprocess.RESULT = b"\xff\n", "", 0
- e = py.test.raises(PkgConfigError, pkgconfig.call,
- "libfoo", "--cflags", encoding="utf-8")
- assert str(e.value) == (
- "pkg-config --cflags libfoo returned bytes that cannot be "
- "decoded with encoding 'utf-8':\nb'\\xff\\n'")
-
- finally:
- pkgconfig.subprocess = saved
diff --git a/testing/cffi1/test_re_python.py b/testing/cffi1/test_re_python.py
deleted file mode 100644
index 2ae0dd1..0000000
--- a/testing/cffi1/test_re_python.py
+++ /dev/null
@@ -1,288 +0,0 @@
-import sys, os
-import py
-from cffi import FFI
-from cffi import recompiler, ffiplatform, VerificationMissing
-from testing.udir import udir
-from testing.support import u
-
-
-def setup_module(mod):
- SRC = """
- #include <string.h>
- #define FOOBAR (-42)
- static const int FOOBAZ = -43;
- #define BIGPOS 420000000000L
- #define BIGNEG -420000000000L
- int add42(int x) { return x + 42; }
- int add43(int x, ...) { return x; }
- int globalvar42 = 1234;
- const int globalconst42 = 4321;
- const char *const globalconsthello = "hello";
- struct foo_s;
- typedef struct bar_s { int x; signed char a[]; } bar_t;
- enum foo_e { AA, BB, CC };
-
- void init_test_re_python(void) { } /* windows hack */
- void PyInit__test_re_python(void) { } /* windows hack */
- """
- tmpdir = udir.join('test_re_python')
- tmpdir.ensure(dir=1)
- c_file = tmpdir.join('_test_re_python.c')
- c_file.write(SRC)
- ext = ffiplatform.get_extension(
- str(c_file),
- '_test_re_python',
- export_symbols=['add42', 'add43', 'globalvar42',
- 'globalconst42', 'globalconsthello']
- )
- outputfilename = ffiplatform.compile(str(tmpdir), ext)
-
- # test with a non-ascii char
- ofn, oext = os.path.splitext(outputfilename)
- if sys.platform == "win32":
- unicode_name = ofn + (u+'\u03be') + oext
- else:
- unicode_name = ofn + (u+'\xe9') + oext
- try:
- unicode_name.encode(sys.getfilesystemencoding())
- except UnicodeEncodeError:
- unicode_name = None
- if unicode_name is not None:
- print(repr(outputfilename) + ' ==> ' + repr(unicode_name))
- os.rename(outputfilename, unicode_name)
- outputfilename = unicode_name
-
- mod.extmod = outputfilename
- mod.tmpdir = tmpdir
- #
- ffi = FFI()
- ffi.cdef("""
- #define FOOBAR -42
- static const int FOOBAZ = -43;
- #define BIGPOS 420000000000L
- #define BIGNEG -420000000000L
- int add42(int);
- int add43(int, ...);
- extern int globalvar42;
- const int globalconst42;
- const char *const globalconsthello;
- int no_such_function(int);
- extern int no_such_globalvar;
- struct foo_s;
- typedef struct bar_s { int x; signed char a[]; } bar_t;
- enum foo_e { AA, BB, CC };
- int strlen(const char *);
- struct with_union { union { int a; char b; }; };
- union with_struct { struct { int a; char b; }; };
- struct with_struct_with_union { struct { union { int x; }; } cp; };
- struct NVGcolor { union { float rgba[4]; struct { float r,g,b,a; }; }; };
- typedef struct selfref { struct selfref *next; } *selfref_ptr_t;
- """)
- ffi.set_source('re_python_pysrc', None)
- ffi.emit_python_code(str(tmpdir.join('re_python_pysrc.py')))
- mod.original_ffi = ffi
- #
- sys.path.insert(0, str(tmpdir))
-
-
-def test_constant():
- from re_python_pysrc import ffi
- assert ffi.integer_const('FOOBAR') == -42
- assert ffi.integer_const('FOOBAZ') == -43
-
-def test_large_constant():
- from re_python_pysrc import ffi
- assert ffi.integer_const('BIGPOS') == 420000000000
- assert ffi.integer_const('BIGNEG') == -420000000000
-
-def test_function():
- import _cffi_backend
- from re_python_pysrc import ffi
- lib = ffi.dlopen(extmod)
- assert lib.add42(-10) == 32
- assert type(lib.add42) is _cffi_backend.FFI.CData
-
-def test_function_with_varargs():
- import _cffi_backend
- from re_python_pysrc import ffi
- lib = ffi.dlopen(extmod, 0)
- assert lib.add43(45, ffi.cast("int", -5)) == 45
- assert type(lib.add43) is _cffi_backend.FFI.CData
-
-def test_dlopen_none():
- import _cffi_backend
- from re_python_pysrc import ffi
- name = None
- if sys.platform == 'win32':
- import ctypes.util
- name = ctypes.util.find_msvcrt()
- if name is None:
- py.test.skip("dlopen(None) cannot work on Windows with Python 3")
- lib = ffi.dlopen(name)
- assert lib.strlen(b"hello") == 5
-
-def test_dlclose():
- import _cffi_backend
- from re_python_pysrc import ffi
- lib = ffi.dlopen(extmod)
- ffi.dlclose(lib)
- if type(extmod) is not str: # unicode, on python 2
- str_extmod = extmod.encode('utf-8')
- else:
- str_extmod = extmod
- e = py.test.raises(ffi.error, getattr, lib, 'add42')
- assert str(e.value) == (
- "library '%s' has been closed" % (str_extmod,))
- ffi.dlclose(lib) # does not raise
-
-def test_constant_via_lib():
- from re_python_pysrc import ffi
- lib = ffi.dlopen(extmod)
- assert lib.FOOBAR == -42
- assert lib.FOOBAZ == -43
-
-def test_opaque_struct():
- from re_python_pysrc import ffi
- ffi.cast("struct foo_s *", 0)
- py.test.raises(TypeError, ffi.new, "struct foo_s *")
-
-def test_nonopaque_struct():
- from re_python_pysrc import ffi
- for p in [ffi.new("struct bar_s *", [5, b"foobar"]),
- ffi.new("bar_t *", [5, b"foobar"])]:
- assert p.x == 5
- assert p.a[0] == ord('f')
- assert p.a[5] == ord('r')
-
-def test_enum():
- from re_python_pysrc import ffi
- assert ffi.integer_const("BB") == 1
- e = ffi.cast("enum foo_e", 2)
- assert ffi.string(e) == "CC"
-
-def test_include_1():
- sub_ffi = FFI()
- sub_ffi.cdef("static const int k2 = 121212;")
- sub_ffi.include(original_ffi)
- assert 'macro FOOBAR' in original_ffi._parser._declarations
- assert 'macro FOOBAZ' in original_ffi._parser._declarations
- sub_ffi.set_source('re_python_pysrc', None)
- sub_ffi.emit_python_code(str(tmpdir.join('_re_include_1.py')))
- #
- if sys.version_info[:2] >= (3, 3):
- import importlib
- importlib.invalidate_caches() # issue 197 (but can't reproduce myself)
- #
- from _re_include_1 import ffi
- assert ffi.integer_const('FOOBAR') == -42
- assert ffi.integer_const('FOOBAZ') == -43
- assert ffi.integer_const('k2') == 121212
- lib = ffi.dlopen(extmod) # <- a random unrelated library would be fine
- assert lib.FOOBAR == -42
- assert lib.FOOBAZ == -43
- assert lib.k2 == 121212
- #
- p = ffi.new("bar_t *", [5, b"foobar"])
- assert p.a[4] == ord('a')
-
-def test_global_var():
- from re_python_pysrc import ffi
- lib = ffi.dlopen(extmod)
- assert lib.globalvar42 == 1234
- p = ffi.addressof(lib, 'globalvar42')
- lib.globalvar42 += 5
- assert p[0] == 1239
- p[0] -= 1
- assert lib.globalvar42 == 1238
-
-def test_global_const_int():
- from re_python_pysrc import ffi
- lib = ffi.dlopen(extmod)
- assert lib.globalconst42 == 4321
- py.test.raises(AttributeError, ffi.addressof, lib, 'globalconst42')
-
-def test_global_const_nonint():
- from re_python_pysrc import ffi
- lib = ffi.dlopen(extmod)
- assert ffi.string(lib.globalconsthello, 8) == b"hello"
- py.test.raises(AttributeError, ffi.addressof, lib, 'globalconsthello')
-
-def test_rtld_constants():
- from re_python_pysrc import ffi
- ffi.RTLD_NOW # check that we have the attributes
- ffi.RTLD_LAZY
- ffi.RTLD_GLOBAL
-
-def test_no_such_function_or_global_var():
- from re_python_pysrc import ffi
- lib = ffi.dlopen(extmod)
- e = py.test.raises(ffi.error, getattr, lib, 'no_such_function')
- assert str(e.value).startswith(
- "symbol 'no_such_function' not found in library '")
- e = py.test.raises(ffi.error, getattr, lib, 'no_such_globalvar')
- assert str(e.value).startswith(
- "symbol 'no_such_globalvar' not found in library '")
-
-def test_check_version():
- import _cffi_backend
- e = py.test.raises(ImportError, _cffi_backend.FFI,
- "foobar", _version=0x2594)
- assert str(e.value).startswith(
- "cffi out-of-line Python module 'foobar' has unknown version")
-
-def test_partial_enum():
- ffi = FFI()
- ffi.cdef("enum foo { A, B, ... };")
- ffi.set_source('test_partial_enum', None)
- py.test.raises(VerificationMissing, ffi.emit_python_code,
- str(tmpdir.join('test_partial_enum.py')))
-
-def test_anonymous_union_inside_struct():
- # based on issue #357
- from re_python_pysrc import ffi
- INT = ffi.sizeof("int")
- assert ffi.offsetof("struct with_union", "a") == 0
- assert ffi.offsetof("struct with_union", "b") == 0
- assert ffi.sizeof("struct with_union") == INT
- #
- assert ffi.offsetof("union with_struct", "a") == 0
- assert ffi.offsetof("union with_struct", "b") == INT
- assert ffi.sizeof("union with_struct") >= INT + 1
- #
- assert ffi.sizeof("struct with_struct_with_union") == INT
- p = ffi.new("struct with_struct_with_union *")
- assert p.cp.x == 0
- #
- FLOAT = ffi.sizeof("float")
- assert ffi.sizeof("struct NVGcolor") == FLOAT * 4
- assert ffi.offsetof("struct NVGcolor", "rgba") == 0
- assert ffi.offsetof("struct NVGcolor", "r") == 0
- assert ffi.offsetof("struct NVGcolor", "g") == FLOAT
- assert ffi.offsetof("struct NVGcolor", "b") == FLOAT * 2
- assert ffi.offsetof("struct NVGcolor", "a") == FLOAT * 3
-
-def test_selfref():
- # based on issue #429
- from re_python_pysrc import ffi
- ffi.new("selfref_ptr_t")
-
-def test_dlopen_handle():
- import _cffi_backend
- from re_python_pysrc import ffi
- if sys.platform == 'win32':
- py.test.skip("uses 'dl' explicitly")
- ffi1 = FFI()
- ffi1.cdef("""void *dlopen(const char *filename, int flags);
- int dlclose(void *handle);""")
- lib1 = ffi1.dlopen('dl')
- handle = lib1.dlopen(extmod.encode(sys.getfilesystemencoding()),
- _cffi_backend.RTLD_LAZY)
- assert ffi1.typeof(handle) == ffi1.typeof("void *")
- assert handle
-
- lib = ffi.dlopen(handle)
- assert lib.add42(-10) == 32
- assert type(lib.add42) is _cffi_backend.FFI.CData
-
- err = lib1.dlclose(handle)
- assert err == 0
diff --git a/testing/cffi1/test_realize_c_type.py b/testing/cffi1/test_realize_c_type.py
deleted file mode 100644
index a1f31e6..0000000
--- a/testing/cffi1/test_realize_c_type.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import py, sys
-from cffi import cffi_opcode
-
-
-def check(input, expected_output=None, expected_ffi_error=False):
- import _cffi_backend
- ffi = _cffi_backend.FFI()
- if not expected_ffi_error:
- ct = ffi.typeof(input)
- assert isinstance(ct, ffi.CType)
- assert ct.cname == (expected_output or input)
- else:
- e = py.test.raises(ffi.error, ffi.typeof, input)
- if isinstance(expected_ffi_error, str):
- assert str(e.value) == expected_ffi_error
-
-def test_void():
- check("void", "void")
- check(" void ", "void")
-
-def test_int_star():
- check("int")
- check("int *")
- check("int*", "int *")
- check("long int", "long")
- check("long")
-
-def test_noop():
- check("int(*)", "int *")
-
-def test_array():
- check("int[6]")
-
-def test_funcptr():
- check("int(*)(long)")
- check("int(long)", expected_ffi_error="the type 'int(long)' is a"
- " function type, not a pointer-to-function type")
- check("int(void)", expected_ffi_error="the type 'int()' is a"
- " function type, not a pointer-to-function type")
-
-def test_funcptr_rewrite_args():
- check("int(*)(int(int))", "int(*)(int(*)(int))")
- check("int(*)(long[])", "int(*)(long *)")
- check("int(*)(long[5])", "int(*)(long *)")
-
-def test_all_primitives():
- for name in cffi_opcode.PRIMITIVE_TO_INDEX:
- check(name, name)
-
-def check_func(input, expected_output=None):
- import _cffi_backend
- ffi = _cffi_backend.FFI()
- ct = ffi.typeof(ffi.callback(input, lambda: None))
- assert isinstance(ct, ffi.CType)
- if sys.platform != 'win32' or sys.maxsize > 2**32:
- expected_output = expected_output.replace('__stdcall *', '*')
- assert ct.cname == expected_output
-
-def test_funcptr_stdcall():
- check_func("int(int)", "int(*)(int)")
- check_func("int foobar(int)", "int(*)(int)")
- check_func("int __stdcall(int)", "int(__stdcall *)(int)")
- check_func("int __stdcall foobar(int)", "int(__stdcall *)(int)")
- check_func("void __cdecl(void)", "void(*)()")
- check_func("void __cdecl foobar(void)", "void(*)()")
- check_func("void __stdcall(void)", "void(__stdcall *)()")
- check_func("void __stdcall foobar(long, short)",
- "void(__stdcall *)(long, short)")
- check_func("void(void __cdecl(void), void __stdcall(void))",
- "void(*)(void(*)(), void(__stdcall *)())")
-
-def test_variadic_overrides_stdcall():
- check("void (__stdcall*)(int, ...)", "void(*)(int, ...)")
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
deleted file mode 100644
index fdb4d5a..0000000
--- a/testing/cffi1/test_recompiler.py
+++ /dev/null
@@ -1,2495 +0,0 @@
-
-import sys, os, py
-import pytest
-from cffi import FFI, VerificationError, FFIError, CDefError
-from cffi import recompiler
-from testing.udir import udir
-from testing.support import u, long
-from testing.support import FdWriteCapture, StdErrCapture, _verify
-
-try:
- import importlib
-except ImportError:
- importlib = None
-
-
-def check_type_table(input, expected_output, included=None):
- ffi = FFI()
- if included:
- ffi1 = FFI()
- ffi1.cdef(included)
- ffi.include(ffi1)
- ffi.cdef(input)
- recomp = recompiler.Recompiler(ffi, 'testmod')
- recomp.collect_type_table()
- assert ''.join(map(str, recomp.cffi_types)) == expected_output
-
-def verify(ffi, module_name, source, *args, **kwds):
- no_cpp = kwds.pop('no_cpp', False)
- ignore_warnings = kwds.pop('ignore_warnings', False)
- kwds.setdefault('undef_macros', ['NDEBUG'])
- module_name = '_CFFI_' + module_name
- ffi.set_source(module_name, source)
- if not os.environ.get('NO_CPP') and not no_cpp: # test the .cpp mode too
- kwds.setdefault('source_extension', '.cpp')
- source = 'extern "C" {\n%s\n}' % (source,)
- elif sys.platform != 'win32' and not ignore_warnings:
- # add '-Werror' to the existing 'extra_compile_args' flags
- from testing.support import extra_compile_args
- kwds['extra_compile_args'] = (kwds.get('extra_compile_args', []) +
- extra_compile_args)
- if sys.platform == 'darwin':
- kwds['extra_link_args'] = (kwds.get('extra_link_args', []) +
- ['-stdlib=libc++'])
- return _verify(ffi, module_name, source, *args, **kwds)
-
-def test_set_source_no_slashes():
- ffi = FFI()
- py.test.raises(ValueError, ffi.set_source, "abc/def", None)
- py.test.raises(ValueError, ffi.set_source, "abc/def", "C code")
-
-
-def test_type_table_func():
- check_type_table("double sin(double);",
- "(FUNCTION 1)(PRIMITIVE 14)(FUNCTION_END 0)")
- check_type_table("float sin(double);",
- "(FUNCTION 3)(PRIMITIVE 14)(FUNCTION_END 0)(PRIMITIVE 13)")
- check_type_table("float sin(void);",
- "(FUNCTION 2)(FUNCTION_END 0)(PRIMITIVE 13)")
- check_type_table("double sin(float); double cos(float);",
- "(FUNCTION 3)(PRIMITIVE 13)(FUNCTION_END 0)(PRIMITIVE 14)")
- check_type_table("double sin(float); double cos(double);",
- "(FUNCTION 1)(PRIMITIVE 14)(FUNCTION_END 0)" # cos
- "(FUNCTION 1)(PRIMITIVE 13)(FUNCTION_END 0)") # sin
- check_type_table("float sin(double); float cos(float);",
- "(FUNCTION 4)(PRIMITIVE 14)(FUNCTION_END 0)" # sin
- "(FUNCTION 4)(PRIMITIVE 13)(FUNCTION_END 0)") # cos
-
-def test_type_table_use_noop_for_repeated_args():
- check_type_table("double sin(double *, double *);",
- "(FUNCTION 4)(POINTER 4)(NOOP 1)(FUNCTION_END 0)"
- "(PRIMITIVE 14)")
- check_type_table("double sin(double *, double *, double);",
- "(FUNCTION 3)(POINTER 3)(NOOP 1)(PRIMITIVE 14)"
- "(FUNCTION_END 0)")
-
-def test_type_table_dont_use_noop_for_primitives():
- check_type_table("double sin(double, double);",
- "(FUNCTION 1)(PRIMITIVE 14)(PRIMITIVE 14)(FUNCTION_END 0)")
-
-def test_type_table_funcptr_as_argument():
- check_type_table("int sin(double(float));",
- "(FUNCTION 6)(PRIMITIVE 13)(FUNCTION_END 0)"
- "(FUNCTION 7)(POINTER 0)(FUNCTION_END 0)"
- "(PRIMITIVE 14)(PRIMITIVE 7)")
-
-def test_type_table_variadic_function():
- check_type_table("int sin(int, ...);",
- "(FUNCTION 1)(PRIMITIVE 7)(FUNCTION_END 1)(POINTER 0)")
-
-def test_type_table_array():
- check_type_table("extern int a[100];",
- "(PRIMITIVE 7)(ARRAY 0)(None 100)")
-
-def test_type_table_typedef():
- check_type_table("typedef int foo_t;",
- "(PRIMITIVE 7)")
-
-def test_type_table_prebuilt_type():
- check_type_table("int32_t f(void);",
- "(FUNCTION 2)(FUNCTION_END 0)(PRIMITIVE 21)")
-
-def test_type_table_struct_opaque():
- check_type_table("struct foo_s;",
- "(STRUCT_UNION 0)")
-
-def test_type_table_struct():
- check_type_table("struct foo_s { int a; long b; };",
- "(PRIMITIVE 7)(PRIMITIVE 9)(STRUCT_UNION 0)")
-
-def test_type_table_union():
- check_type_table("union foo_u { int a; long b; };",
- "(PRIMITIVE 7)(PRIMITIVE 9)(STRUCT_UNION 0)")
-
-def test_type_table_struct_used():
- check_type_table("struct foo_s { int a; long b; }; int f(struct foo_s*);",
- "(FUNCTION 3)(POINTER 5)(FUNCTION_END 0)"
- "(PRIMITIVE 7)(PRIMITIVE 9)"
- "(STRUCT_UNION 0)")
-
-def test_type_table_anonymous_struct_with_typedef():
- check_type_table("typedef struct { int a; long b; } foo_t;",
- "(STRUCT_UNION 0)(PRIMITIVE 7)(PRIMITIVE 9)")
-
-def test_type_table_enum():
- check_type_table("enum foo_e { AA, BB, ... };",
- "(ENUM 0)")
-
-def test_type_table_include_1():
- check_type_table("foo_t sin(foo_t);",
- "(FUNCTION 1)(PRIMITIVE 14)(FUNCTION_END 0)",
- included="typedef double foo_t;")
-
-def test_type_table_include_2():
- check_type_table("struct foo_s *sin(struct foo_s *);",
- "(FUNCTION 1)(POINTER 3)(FUNCTION_END 0)(STRUCT_UNION 0)",
- included="struct foo_s { int x, y; };")
-
-
-def test_math_sin():
- import math
- ffi = FFI()
- ffi.cdef("float sin(double); double cos(double);")
- lib = verify(ffi, 'test_math_sin', '#include <math.h>',
- ignore_warnings=True)
- assert lib.cos(1.43) == math.cos(1.43)
-
-def test_repr_lib():
- ffi = FFI()
- lib = verify(ffi, 'test_repr_lib', '')
- assert repr(lib) == "<Lib object for '_CFFI_test_repr_lib'>"
-
-def test_funcarg_ptr():
- ffi = FFI()
- ffi.cdef("int foo(int *);")
- lib = verify(ffi, 'test_funcarg_ptr', 'int foo(int *p) { return *p; }')
- assert lib.foo([-12345]) == -12345
-
-def test_funcres_ptr():
- ffi = FFI()
- ffi.cdef("int *foo(void);")
- lib = verify(ffi, 'test_funcres_ptr',
- 'int *foo(void) { static int x=-12345; return &x; }')
- assert lib.foo()[0] == -12345
-
-def test_global_var_array():
- ffi = FFI()
- ffi.cdef("extern int a[100];")
- lib = verify(ffi, 'test_global_var_array', 'int a[100] = { 9999 };')
- lib.a[42] = 123456
- assert lib.a[42] == 123456
- assert lib.a[0] == 9999
-
-def test_verify_typedef():
- ffi = FFI()
- ffi.cdef("typedef int **foo_t;")
- lib = verify(ffi, 'test_verify_typedef', 'typedef int **foo_t;')
- assert ffi.sizeof("foo_t") == ffi.sizeof("void *")
-
-def test_verify_typedef_dotdotdot():
- ffi = FFI()
- ffi.cdef("typedef ... foo_t;")
- verify(ffi, 'test_verify_typedef_dotdotdot', 'typedef int **foo_t;')
-
-def test_verify_typedef_star_dotdotdot():
- ffi = FFI()
- ffi.cdef("typedef ... *foo_t;")
- verify(ffi, 'test_verify_typedef_star_dotdotdot', 'typedef int **foo_t;')
-
-def test_global_var_int():
- ffi = FFI()
- ffi.cdef("extern int a, b, c;")
- lib = verify(ffi, 'test_global_var_int', 'int a = 999, b, c;')
- assert lib.a == 999
- lib.a -= 1001
- assert lib.a == -2
- lib.a = -2147483648
- assert lib.a == -2147483648
- with pytest.raises(OverflowError):
- lib.a = 2147483648
- with pytest.raises(OverflowError):
- lib.a = -2147483649
- lib.b = 525 # try with the first access being in setattr, too
- assert lib.b == 525
- with pytest.raises(AttributeError):
- del lib.a
- with pytest.raises(AttributeError):
- del lib.c
- with pytest.raises(AttributeError):
- del lib.foobarbaz
-
-def test_macro():
- ffi = FFI()
- ffi.cdef("#define FOOBAR ...")
- lib = verify(ffi, 'test_macro', "#define FOOBAR (-6912)")
- assert lib.FOOBAR == -6912
- with pytest.raises(AttributeError):
- lib.FOOBAR = 2
-
-def test_macro_check_value():
- # the value '-0x80000000' in C sources does not have a clear meaning
- # to me; it appears to have a different effect than '-2147483648'...
- # Moreover, on 32-bits, -2147483648 is actually equal to
- # -2147483648U, which in turn is equal to 2147483648U and so positive.
- vals = ['42', '-42', '0x80000000', '-2147483648',
- '0', '9223372036854775809ULL',
- '-9223372036854775807LL']
- if sys.maxsize <= 2**32 or sys.platform == 'win32':
- vals.remove('-2147483648')
- ffi = FFI()
- cdef_lines = ['#define FOO_%d_%d %s' % (i, j, vals[i])
- for i in range(len(vals))
- for j in range(len(vals))]
- ffi.cdef('\n'.join(cdef_lines))
-
- verify_lines = ['#define FOO_%d_%d %s' % (i, j, vals[j]) # [j], not [i]
- for i in range(len(vals))
- for j in range(len(vals))]
- lib = verify(ffi, 'test_macro_check_value_ok',
- '\n'.join(verify_lines))
- #
- for j in range(len(vals)):
- c_got = int(vals[j].replace('U', '').replace('L', ''), 0)
- c_compiler_msg = str(c_got)
- if c_got > 0:
- c_compiler_msg += ' (0x%x)' % (c_got,)
- #
- for i in range(len(vals)):
- attrname = 'FOO_%d_%d' % (i, j)
- if i == j:
- x = getattr(lib, attrname)
- assert x == c_got
- else:
- e = py.test.raises(ffi.error, getattr, lib, attrname)
- assert str(e.value) == (
- "the C compiler says '%s' is equal to "
- "%s, but the cdef disagrees" % (attrname, c_compiler_msg))
-
-def test_constant():
- ffi = FFI()
- ffi.cdef("static const int FOOBAR;")
- lib = verify(ffi, 'test_constant', "#define FOOBAR (-6912)")
- assert lib.FOOBAR == -6912
- with pytest.raises(AttributeError):
- lib.FOOBAR = 2
-
-def test_check_value_of_static_const():
- ffi = FFI()
- ffi.cdef("static const int FOOBAR = 042;")
- lib = verify(ffi, 'test_check_value_of_static_const',
- "#define FOOBAR (-6912)")
- e = py.test.raises(ffi.error, getattr, lib, 'FOOBAR')
- assert str(e.value) == (
- "the C compiler says 'FOOBAR' is equal to -6912, but the cdef disagrees")
-
-def test_constant_nonint():
- ffi = FFI()
- ffi.cdef("static const double FOOBAR;")
- lib = verify(ffi, 'test_constant_nonint', "#define FOOBAR (-6912.5)")
- assert lib.FOOBAR == -6912.5
- with pytest.raises(AttributeError):
- lib.FOOBAR = 2
-
-def test_constant_ptr():
- ffi = FFI()
- ffi.cdef("static double *const FOOBAR;")
- lib = verify(ffi, 'test_constant_ptr', "#define FOOBAR NULL")
- assert lib.FOOBAR == ffi.NULL
- assert ffi.typeof(lib.FOOBAR) == ffi.typeof("double *")
-
-def test_dir():
- ffi = FFI()
- ffi.cdef("int ff(int); extern int aa; static const int my_constant;")
- lib = verify(ffi, 'test_dir', """
- #define my_constant (-45)
- int aa;
- int ff(int x) { return x+aa; }
- """)
- lib.aa = 5
- assert dir(lib) == ['aa', 'ff', 'my_constant']
- #
- aaobj = lib.__dict__['aa']
- assert not isinstance(aaobj, int) # some internal object instead
- assert lib.__dict__ == {
- 'ff': lib.ff,
- 'aa': aaobj,
- 'my_constant': -45}
- lib.__dict__['ff'] = "??"
- assert lib.ff(10) == 15
-
-def test_verify_opaque_struct():
- ffi = FFI()
- ffi.cdef("struct foo_s;")
- lib = verify(ffi, 'test_verify_opaque_struct', "struct foo_s;")
- assert ffi.typeof("struct foo_s").cname == "struct foo_s"
-
-def test_verify_opaque_union():
- ffi = FFI()
- ffi.cdef("union foo_s;")
- lib = verify(ffi, 'test_verify_opaque_union', "union foo_s;")
- assert ffi.typeof("union foo_s").cname == "union foo_s"
-
-def test_verify_struct():
- ffi = FFI()
- ffi.cdef("""struct foo_s { int b; short a; ...; };
- struct bar_s { struct foo_s *f; };""")
- lib = verify(ffi, 'test_verify_struct',
- """struct foo_s { short a; int b; };
- struct bar_s { struct foo_s *f; };""")
- ffi.typeof("struct bar_s *")
- p = ffi.new("struct foo_s *", {'a': -32768, 'b': -2147483648})
- assert p.a == -32768
- assert p.b == -2147483648
- with pytest.raises(OverflowError):
- p.a -= 1
- with pytest.raises(OverflowError):
- p.b -= 1
- q = ffi.new("struct bar_s *", {'f': p})
- assert q.f == p
- #
- assert ffi.offsetof("struct foo_s", "a") == 0
- assert ffi.offsetof("struct foo_s", "b") == 4
- assert ffi.offsetof(u+"struct foo_s", u+"b") == 4
- #
- py.test.raises(TypeError, ffi.addressof, p)
- assert ffi.addressof(p[0]) == p
- assert ffi.typeof(ffi.addressof(p[0])) is ffi.typeof("struct foo_s *")
- assert ffi.typeof(ffi.addressof(p, "b")) is ffi.typeof("int *")
- assert ffi.addressof(p, "b")[0] == p.b
-
-def test_verify_exact_field_offset():
- ffi = FFI()
- ffi.cdef("""struct foo_s { int b; short a; };""")
- lib = verify(ffi, 'test_verify_exact_field_offset',
- """struct foo_s { short a; int b; };""")
- e = py.test.raises(ffi.error, ffi.new, "struct foo_s *", []) # lazily
- assert str(e.value).startswith(
- "struct foo_s: wrong offset for field 'b' (cdef "
- 'says 0, but C compiler says 4). fix it or use "...;" ')
-
-def test_type_caching():
- ffi1 = FFI(); ffi1.cdef("struct foo_s;")
- ffi2 = FFI(); ffi2.cdef("struct foo_s;") # different one!
- lib1 = verify(ffi1, 'test_type_caching_1', 'struct foo_s;')
- lib2 = verify(ffi2, 'test_type_caching_2', 'struct foo_s;')
- # shared types
- assert ffi1.typeof("long") is ffi2.typeof("long")
- assert ffi1.typeof("long**") is ffi2.typeof("long * *")
- assert ffi1.typeof("long(*)(int, ...)") is ffi2.typeof("long(*)(int, ...)")
- # non-shared types
- assert ffi1.typeof("struct foo_s") is not ffi2.typeof("struct foo_s")
- assert ffi1.typeof("struct foo_s *") is not ffi2.typeof("struct foo_s *")
- assert ffi1.typeof("struct foo_s*(*)()") is not (
- ffi2.typeof("struct foo_s*(*)()"))
- assert ffi1.typeof("void(*)(struct foo_s*)") is not (
- ffi2.typeof("void(*)(struct foo_s*)"))
-
-def test_verify_enum():
- ffi = FFI()
- ffi.cdef("""enum e1 { B1, A1, ... }; enum e2 { B2, A2, ... };""")
- lib = verify(ffi, 'test_verify_enum',
- "enum e1 { A1, B1, C1=%d };" % sys.maxsize +
- "enum e2 { A2, B2, C2 };")
- ffi.typeof("enum e1")
- ffi.typeof("enum e2")
- assert lib.A1 == 0
- assert lib.B1 == 1
- assert lib.A2 == 0
- assert lib.B2 == 1
- assert ffi.sizeof("enum e1") == ffi.sizeof("long")
- assert ffi.sizeof("enum e2") == ffi.sizeof("int")
- assert repr(ffi.cast("enum e1", 0)) == "<cdata 'enum e1' 0: A1>"
-
-def test_duplicate_enum():
- ffi = FFI()
- ffi.cdef("enum e1 { A1, ... }; enum e2 { A1, ... };")
- py.test.raises(VerificationError, verify, ffi, 'test_duplicate_enum',
- "enum e1 { A1 }; enum e2 { B1 };")
-
-def test_dotdotdot_length_of_array_field():
- ffi = FFI()
- ffi.cdef("struct foo_s { int a[...]; int b[...]; };")
- verify(ffi, 'test_dotdotdot_length_of_array_field',
- "struct foo_s { int a[42]; int b[11]; };")
- assert ffi.sizeof("struct foo_s") == (42 + 11) * 4
- p = ffi.new("struct foo_s *")
- assert p.a[41] == p.b[10] == 0
- with pytest.raises(IndexError):
- p.a[42]
- with pytest.raises(IndexError):
- p.b[11]
-
-def test_dotdotdot_global_array():
- ffi = FFI()
- ffi.cdef("extern int aa[...]; extern int bb[...];")
- lib = verify(ffi, 'test_dotdotdot_global_array',
- "int aa[41]; int bb[12];")
- assert ffi.sizeof(lib.aa) == 41 * 4
- assert ffi.sizeof(lib.bb) == 12 * 4
- assert lib.aa[40] == lib.bb[11] == 0
- with pytest.raises(IndexError):
- lib.aa[41]
- with pytest.raises(IndexError):
- lib.bb[12]
-
-def test_misdeclared_field_1():
- ffi = FFI()
- ffi.cdef("struct foo_s { int a[5]; };")
- try:
- verify(ffi, 'test_misdeclared_field_1',
- "struct foo_s { int a[6]; };")
- except VerificationError:
- pass # ok, fail during compilation already (e.g. C++)
- else:
- assert ffi.sizeof("struct foo_s") == 24 # found by the actual C code
- try:
- # lazily build the fields and boom:
- p = ffi.new("struct foo_s *")
- p.a
- assert False, "should have raised"
- except ffi.error as e:
- assert str(e).startswith("struct foo_s: wrong size for field 'a' "
- "(cdef says 20, but C compiler says 24)")
-
-def test_open_array_in_struct():
- ffi = FFI()
- ffi.cdef("struct foo_s { int b; int a[]; };")
- verify(ffi, 'test_open_array_in_struct',
- "struct foo_s { int b; int a[]; };")
- assert ffi.sizeof("struct foo_s") == 4
- p = ffi.new("struct foo_s *", [5, [10, 20, 30, 40]])
- assert p.a[2] == 30
- assert ffi.sizeof(p) == ffi.sizeof("void *")
- assert ffi.sizeof(p[0]) == 5 * ffi.sizeof("int")
-
-def test_math_sin_type():
- ffi = FFI()
- ffi.cdef("double sin(double); void *xxtestfunc();")
- lib = verify(ffi, 'test_math_sin_type', """
- #include <math.h>
- void *xxtestfunc(void) { return 0; }
- """)
- # 'lib.sin' is typed as a <built-in method> object on lib
- assert ffi.typeof(lib.sin).cname == "double(*)(double)"
- # 'x' is another <built-in method> object on lib, made very indirectly
- x = type(lib).__dir__.__get__(lib)
- py.test.raises(TypeError, ffi.typeof, x)
- #
- # present on built-in functions on CPython; must be emulated on PyPy:
- assert lib.sin.__name__ == 'sin'
- assert lib.sin.__module__ == '_CFFI_test_math_sin_type'
- assert lib.sin.__doc__ == (
- "double sin(double);\n"
- "\n"
- "CFFI C function from _CFFI_test_math_sin_type.lib")
-
- assert ffi.typeof(lib.xxtestfunc).cname == "void *(*)()"
- assert lib.xxtestfunc.__doc__ == (
- "void *xxtestfunc();\n"
- "\n"
- "CFFI C function from _CFFI_test_math_sin_type.lib")
-
-def test_verify_anonymous_struct_with_typedef():
- ffi = FFI()
- ffi.cdef("typedef struct { int a; long b; ...; } foo_t;")
- verify(ffi, 'test_verify_anonymous_struct_with_typedef',
- "typedef struct { long b; int hidden, a; } foo_t;")
- p = ffi.new("foo_t *", {'b': 42})
- assert p.b == 42
- assert repr(p).startswith("<cdata 'foo_t *' ")
-
-def test_verify_anonymous_struct_with_star_typedef():
- ffi = FFI()
- ffi.cdef("typedef struct { int a; long b; } *foo_t;")
- verify(ffi, 'test_verify_anonymous_struct_with_star_typedef',
- "typedef struct { int a; long b; } *foo_t;")
- p = ffi.new("foo_t", {'b': 42})
- assert p.b == 42
-
-def test_verify_anonymous_enum_with_typedef():
- ffi = FFI()
- ffi.cdef("typedef enum { AA, ... } e1;")
- lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef1',
- "typedef enum { BB, CC, AA } e1;")
- assert lib.AA == 2
- assert ffi.sizeof("e1") == ffi.sizeof("int")
- assert repr(ffi.cast("e1", 2)) == "<cdata 'e1' 2: AA>"
- #
- ffi = FFI()
- ffi.cdef("typedef enum { AA=%d } e1;" % sys.maxsize)
- lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef2',
- "typedef enum { AA=%d } e1;" % sys.maxsize)
- assert lib.AA == int(ffi.cast("long", sys.maxsize))
- assert ffi.sizeof("e1") == ffi.sizeof("long")
-
-def test_unique_types():
- CDEF = "struct foo_s; union foo_u; enum foo_e { AA };"
- ffi1 = FFI(); ffi1.cdef(CDEF); verify(ffi1, "test_unique_types_1", CDEF)
- ffi2 = FFI(); ffi2.cdef(CDEF); verify(ffi2, "test_unique_types_2", CDEF)
- #
- assert ffi1.typeof("char") is ffi2.typeof("char ")
- assert ffi1.typeof("long") is ffi2.typeof("signed long int")
- assert ffi1.typeof("double *") is ffi2.typeof("double*")
- assert ffi1.typeof("int ***") is ffi2.typeof(" int * * *")
- assert ffi1.typeof("int[]") is ffi2.typeof("signed int[]")
- assert ffi1.typeof("signed int*[17]") is ffi2.typeof("int *[17]")
- assert ffi1.typeof("void") is ffi2.typeof("void")
- assert ffi1.typeof("int(*)(int,int)") is ffi2.typeof("int(*)(int,int)")
- #
- # these depend on user-defined data, so should not be shared
- for name in ["struct foo_s",
- "union foo_u *",
- "enum foo_e",
- "struct foo_s *(*)()",
- "void(*)(struct foo_s *)",
- "struct foo_s *(*[5])[8]",
- ]:
- assert ffi1.typeof(name) is not ffi2.typeof(name)
- # sanity check: twice 'ffi1'
- assert ffi1.typeof("struct foo_s*") is ffi1.typeof("struct foo_s *")
-
-def test_module_name_in_package():
- ffi = FFI()
- ffi.cdef("int foo(int);")
- recompiler.recompile(ffi, "test_module_name_in_package.mymod",
- "int foo(int x) { return x + 32; }",
- tmpdir=str(udir))
- old_sys_path = sys.path[:]
- try:
- package_dir = udir.join('test_module_name_in_package')
- for name in os.listdir(str(udir)):
- assert not name.startswith('test_module_name_in_package.')
- assert os.path.isdir(str(package_dir))
- assert len(os.listdir(str(package_dir))) > 0
- assert os.path.exists(str(package_dir.join('mymod.c')))
- package_dir.join('__init__.py').write('')
- #
- getattr(importlib, 'invalidate_caches', object)()
- #
- sys.path.insert(0, str(udir))
- import test_module_name_in_package.mymod
- assert test_module_name_in_package.mymod.lib.foo(10) == 42
- assert test_module_name_in_package.mymod.__name__ == (
- 'test_module_name_in_package.mymod')
- finally:
- sys.path[:] = old_sys_path
-
-def test_bad_size_of_global_1():
- ffi = FFI()
- ffi.cdef("extern short glob;")
- py.test.raises(VerificationError, verify, ffi,
- "test_bad_size_of_global_1", "long glob;")
-
-def test_bad_size_of_global_2():
- ffi = FFI()
- ffi.cdef("extern int glob[10];")
- py.test.raises(VerificationError, verify, ffi,
- "test_bad_size_of_global_2", "int glob[9];")
-
-def test_unspecified_size_of_global_1():
- ffi = FFI()
- ffi.cdef("extern int glob[];")
- lib = verify(ffi, "test_unspecified_size_of_global_1", "int glob[10];")
- assert ffi.typeof(lib.glob) == ffi.typeof("int *")
-
-def test_unspecified_size_of_global_2():
- ffi = FFI()
- ffi.cdef("extern int glob[][5];")
- lib = verify(ffi, "test_unspecified_size_of_global_2", "int glob[10][5];")
- assert ffi.typeof(lib.glob) == ffi.typeof("int(*)[5]")
-
-def test_unspecified_size_of_global_3():
- ffi = FFI()
- ffi.cdef("extern int glob[][...];")
- lib = verify(ffi, "test_unspecified_size_of_global_3", "int glob[10][5];")
- assert ffi.typeof(lib.glob) == ffi.typeof("int(*)[5]")
-
-def test_unspecified_size_of_global_4():
- ffi = FFI()
- ffi.cdef("extern int glob[...][...];")
- lib = verify(ffi, "test_unspecified_size_of_global_4", "int glob[10][5];")
- assert ffi.typeof(lib.glob) == ffi.typeof("int[10][5]")
-
-def test_include_1():
- ffi1 = FFI()
- ffi1.cdef("typedef double foo_t;")
- verify(ffi1, "test_include_1_parent", "typedef double foo_t;")
- ffi = FFI()
- ffi.include(ffi1)
- ffi.cdef("foo_t ff1(foo_t);")
- lib = verify(ffi, "test_include_1", "double ff1(double x) { return 42.5; }")
- assert lib.ff1(0) == 42.5
- assert ffi1.typeof("foo_t") is ffi.typeof("foo_t") is ffi.typeof("double")
-
-def test_include_1b():
- ffi1 = FFI()
- ffi1.cdef("int foo1(int);")
- lib1 = verify(ffi1, "test_include_1b_parent",
- "int foo1(int x) { return x + 10; }")
- ffi = FFI()
- ffi.include(ffi1)
- ffi.cdef("int foo2(int);")
- lib = verify(ffi, "test_include_1b", "int foo2(int x) { return x - 5; }")
- assert lib.foo2(42) == 37
- assert lib.foo1(42) == 52
- assert lib.foo1 is lib1.foo1
-
-def test_include_2():
- ffi1 = FFI()
- ffi1.cdef("struct foo_s { int x, y; };")
- verify(ffi1, "test_include_2_parent", "struct foo_s { int x, y; };")
- ffi = FFI()
- ffi.include(ffi1)
- ffi.cdef("struct foo_s *ff2(struct foo_s *);")
- lib = verify(ffi, "test_include_2",
- "struct foo_s { int x, y; }; //usually from a #include\n"
- "struct foo_s *ff2(struct foo_s *p) { p->y++; return p; }")
- p = ffi.new("struct foo_s *")
- p.y = 41
- q = lib.ff2(p)
- assert q == p
- assert p.y == 42
- assert ffi1.typeof("struct foo_s") is ffi.typeof("struct foo_s")
-
-def test_include_3():
- ffi1 = FFI()
- ffi1.cdef("typedef short sshort_t;")
- verify(ffi1, "test_include_3_parent", "typedef short sshort_t;")
- ffi = FFI()
- ffi.include(ffi1)
- ffi.cdef("sshort_t ff3(sshort_t);")
- lib = verify(ffi, "test_include_3",
- "typedef short sshort_t; //usually from a #include\n"
- "sshort_t ff3(sshort_t x) { return (sshort_t)(x + 42); }")
- assert lib.ff3(10) == 52
- assert ffi.typeof(ffi.cast("sshort_t", 42)) is ffi.typeof("short")
- assert ffi1.typeof("sshort_t") is ffi.typeof("sshort_t")
-
-def test_include_4():
- ffi1 = FFI()
- ffi1.cdef("typedef struct { int x; } mystruct_t;")
- verify(ffi1, "test_include_4_parent",
- "typedef struct { int x; } mystruct_t;")
- ffi = FFI()
- ffi.include(ffi1)
- ffi.cdef("mystruct_t *ff4(mystruct_t *);")
- lib = verify(ffi, "test_include_4",
- "typedef struct {int x; } mystruct_t; //usually from a #include\n"
- "mystruct_t *ff4(mystruct_t *p) { p->x += 42; return p; }")
- p = ffi.new("mystruct_t *", [10])
- q = lib.ff4(p)
- assert q == p
- assert p.x == 52
- assert ffi1.typeof("mystruct_t") is ffi.typeof("mystruct_t")
-
-def test_include_5():
- ffi1 = FFI()
- ffi1.cdef("typedef struct { int x[2]; int y; } *mystruct_p;")
- verify(ffi1, "test_include_5_parent",
- "typedef struct { int x[2]; int y; } *mystruct_p;")
- ffi = FFI()
- ffi.include(ffi1)
- ffi.cdef("mystruct_p ff5(mystruct_p);")
- lib = verify(ffi, "test_include_5",
- "typedef struct {int x[2]; int y; } *mystruct_p; //usually #include\n"
- "mystruct_p ff5(mystruct_p p) { p->x[1] += 42; return p; }")
- assert ffi.alignof(ffi.typeof("mystruct_p").item) == 4
- assert ffi1.typeof("mystruct_p") is ffi.typeof("mystruct_p")
- p = ffi.new("mystruct_p", [[5, 10], -17])
- q = lib.ff5(p)
- assert q == p
- assert p.x[0] == 5
- assert p.x[1] == 52
- assert p.y == -17
- assert ffi.alignof(ffi.typeof(p[0])) == 4
-
-def test_include_6():
- ffi1 = FFI()
- ffi1.cdef("typedef ... mystruct_t;")
- verify(ffi1, "test_include_6_parent",
- "typedef struct _mystruct_s mystruct_t;")
- ffi = FFI()
- ffi.include(ffi1)
- ffi.cdef("mystruct_t *ff6(void); int ff6b(mystruct_t *);")
- lib = verify(ffi, "test_include_6",
- "typedef struct _mystruct_s mystruct_t; //usually from a #include\n"
- "struct _mystruct_s { int x; };\n"
- "static mystruct_t result_struct = { 42 };\n"
- "mystruct_t *ff6(void) { return &result_struct; }\n"
- "int ff6b(mystruct_t *p) { return p->x; }")
- p = lib.ff6()
- assert ffi.cast("int *", p)[0] == 42
- assert lib.ff6b(p) == 42
-
-def test_include_7():
- ffi1 = FFI()
- ffi1.cdef("typedef ... mystruct_t;\n"
- "int ff7b(mystruct_t *);")
- verify(ffi1, "test_include_7_parent",
- "typedef struct { int x; } mystruct_t;\n"
- "int ff7b(mystruct_t *p) { return p->x; }")
- ffi = FFI()
- ffi.include(ffi1)
- ffi.cdef("mystruct_t *ff7(void);")
- lib = verify(ffi, "test_include_7",
- "typedef struct { int x; } mystruct_t; //usually from a #include\n"
- "static mystruct_t result_struct = { 42 };"
- "mystruct_t *ff7(void) { return &result_struct; }")
- p = lib.ff7()
- assert ffi.cast("int *", p)[0] == 42
- assert lib.ff7b(p) == 42
-
-def test_include_8():
- ffi1 = FFI()
- ffi1.cdef("struct foo_s;")
- verify(ffi1, "test_include_8_parent", "struct foo_s;")
- ffi = FFI()
- ffi.include(ffi1)
- ffi.cdef("struct foo_s { int x, y; };")
- verify(ffi, "test_include_8", "struct foo_s { int x, y; };")
- e = py.test.raises(NotImplementedError, ffi.new, "struct foo_s *")
- assert str(e.value) == (
- "'struct foo_s' is opaque in the ffi.include(), but no longer in "
- "the ffi doing the include (workaround: don't use ffi.include() but"
- " duplicate the declarations of everything using struct foo_s)")
-
-def test_unicode_libraries():
- try:
- unicode
- except NameError:
- py.test.skip("for python 2.x")
- #
- import math
- lib_m = "m"
- if sys.platform == 'win32':
- #there is a small chance this fails on Mingw via environ $CC
- import distutils.ccompiler
- if distutils.ccompiler.get_default_compiler() == 'msvc':
- lib_m = 'msvcrt'
- ffi = FFI()
- ffi.cdef(unicode("float sin(double); double cos(double);"))
- lib = verify(ffi, 'test_math_sin_unicode', unicode('#include <math.h>'),
- libraries=[unicode(lib_m)], ignore_warnings=True)
- assert lib.cos(1.43) == math.cos(1.43)
-
-def test_incomplete_struct_as_arg():
- ffi = FFI()
- ffi.cdef("struct foo_s { int x; ...; }; int f(int, struct foo_s);")
- lib = verify(ffi, "test_incomplete_struct_as_arg",
- "struct foo_s { int a, x, z; };\n"
- "int f(int b, struct foo_s s) { return s.x * b; }")
- s = ffi.new("struct foo_s *", [21])
- assert s.x == 21
- assert ffi.sizeof(s[0]) == 12
- assert ffi.offsetof(ffi.typeof(s), 'x') == 4
- assert lib.f(2, s[0]) == 42
- assert ffi.typeof(lib.f) == ffi.typeof("int(*)(int, struct foo_s)")
-
-def test_incomplete_struct_as_result():
- ffi = FFI()
- ffi.cdef("struct foo_s { int x; ...; }; struct foo_s f(int);")
- lib = verify(ffi, "test_incomplete_struct_as_result",
- "struct foo_s { int a, x, z; };\n"
- "struct foo_s f(int x) { struct foo_s r; r.x = x * 2; return r; }")
- s = lib.f(21)
- assert s.x == 42
- assert ffi.typeof(lib.f) == ffi.typeof("struct foo_s(*)(int)")
-
-def test_incomplete_struct_as_both():
- ffi = FFI()
- ffi.cdef("struct foo_s { int x; ...; }; struct bar_s { int y; ...; };\n"
- "struct foo_s f(int, struct bar_s);")
- lib = verify(ffi, "test_incomplete_struct_as_both",
- "struct foo_s { int a, x, z; };\n"
- "struct bar_s { int b, c, y, d; };\n"
- "struct foo_s f(int x, struct bar_s b) {\n"
- " struct foo_s r; r.x = x * b.y; return r;\n"
- "}")
- b = ffi.new("struct bar_s *", [7])
- s = lib.f(6, b[0])
- assert s.x == 42
- assert ffi.typeof(lib.f) == ffi.typeof(
- "struct foo_s(*)(int, struct bar_s)")
- s = lib.f(14, {'y': -3})
- assert s.x == -42
-
-def test_name_of_unnamed_struct():
- ffi = FFI()
- ffi.cdef("typedef struct { int x; } foo_t;\n"
- "typedef struct { int y; } *bar_p;\n"
- "typedef struct { int y; } **baz_pp;\n")
- verify(ffi, "test_name_of_unnamed_struct",
- "typedef struct { int x; } foo_t;\n"
- "typedef struct { int y; } *bar_p;\n"
- "typedef struct { int y; } **baz_pp;\n")
- assert repr(ffi.typeof("foo_t")) == "<ctype 'foo_t'>"
- assert repr(ffi.typeof("bar_p")) == "<ctype 'struct $1 *'>"
- assert repr(ffi.typeof("baz_pp")) == "<ctype 'struct $2 * *'>"
-
-def test_address_of_global_var():
- ffi = FFI()
- ffi.cdef("""
- extern long bottom, bottoms[2];
- long FetchRectBottom(void);
- long FetchRectBottoms1(void);
- #define FOOBAR 42
- """)
- lib = verify(ffi, "test_address_of_global_var", """
- long bottom, bottoms[2];
- long FetchRectBottom(void) { return bottom; }
- long FetchRectBottoms1(void) { return bottoms[1]; }
- #define FOOBAR 42
- """)
- lib.bottom = 300
- assert lib.FetchRectBottom() == 300
- lib.bottom += 1
- assert lib.FetchRectBottom() == 301
- lib.bottoms[1] = 500
- assert lib.FetchRectBottoms1() == 500
- lib.bottoms[1] += 2
- assert lib.FetchRectBottoms1() == 502
- #
- p = ffi.addressof(lib, 'bottom')
- assert ffi.typeof(p) == ffi.typeof("long *")
- assert p[0] == 301
- p[0] += 1
- assert lib.FetchRectBottom() == 302
- p = ffi.addressof(lib, 'bottoms')
- assert ffi.typeof(p) == ffi.typeof("long(*)[2]")
- assert p[0] == lib.bottoms
- #
- py.test.raises(AttributeError, ffi.addressof, lib, 'unknown_var')
- py.test.raises(AttributeError, ffi.addressof, lib, "FOOBAR")
-
-def test_defines__CFFI_():
- # Check that we define the macro _CFFI_ automatically.
- # It should be done before including Python.h, so that PyPy's Python.h
- # can check for it.
- ffi = FFI()
- ffi.cdef("""
- #define CORRECT 1
- """)
- lib = verify(ffi, "test_defines__CFFI_", """
- #ifdef _CFFI_
- # define CORRECT 1
- #endif
- """)
- assert lib.CORRECT == 1
-
-def test_unpack_args():
- ffi = FFI()
- ffi.cdef("void foo0(void); void foo1(int); void foo2(int, int);")
- lib = verify(ffi, "test_unpack_args", """
- void foo0(void) { }
- void foo1(int x) { }
- void foo2(int x, int y) { }
- """)
- assert 'foo0' in repr(lib.foo0)
- assert 'foo1' in repr(lib.foo1)
- assert 'foo2' in repr(lib.foo2)
- lib.foo0()
- lib.foo1(42)
- lib.foo2(43, 44)
- e1 = py.test.raises(TypeError, lib.foo0, 42)
- e2 = py.test.raises(TypeError, lib.foo0, 43, 44)
- e3 = py.test.raises(TypeError, lib.foo1)
- e4 = py.test.raises(TypeError, lib.foo1, 43, 44)
- e5 = py.test.raises(TypeError, lib.foo2)
- e6 = py.test.raises(TypeError, lib.foo2, 42)
- e7 = py.test.raises(TypeError, lib.foo2, 45, 46, 47)
- def st1(s):
- s = str(s)
- if s.startswith("_CFFI_test_unpack_args.Lib."):
- s = s[len("_CFFI_test_unpack_args.Lib."):]
- return s
- assert st1(e1.value) == "foo0() takes no arguments (1 given)"
- assert st1(e2.value) == "foo0() takes no arguments (2 given)"
- assert st1(e3.value) == "foo1() takes exactly one argument (0 given)"
- assert st1(e4.value) == "foo1() takes exactly one argument (2 given)"
- assert st1(e5.value) in ["foo2 expected 2 arguments, got 0",
- "foo2() takes exactly 2 arguments (0 given)"]
- assert st1(e6.value) in ["foo2 expected 2 arguments, got 1",
- "foo2() takes exactly 2 arguments (1 given)"]
- assert st1(e7.value) in ["foo2 expected 2 arguments, got 3",
- "foo2() takes exactly 2 arguments (3 given)"]
-
-def test_address_of_function():
- ffi = FFI()
- ffi.cdef("long myfunc(long x);")
- lib = verify(ffi, "test_addressof_function", """
- char myfunc(char x) { return (char)(x + 42); }
- """, ignore_warnings=True)
- assert lib.myfunc(5) == 47
- assert lib.myfunc(0xABC05) == 47
- assert not isinstance(lib.myfunc, ffi.CData)
- assert ffi.typeof(lib.myfunc) == ffi.typeof("long(*)(long)")
- addr = ffi.addressof(lib, 'myfunc')
- assert addr(5) == 47
- assert addr(0xABC05) == 47
- assert isinstance(addr, ffi.CData)
- assert ffi.typeof(addr) == ffi.typeof("long(*)(long)")
-
-def test_address_of_function_with_struct():
- ffi = FFI()
- ffi.cdef("struct foo_s { int x; }; long myfunc(struct foo_s);")
- lib = verify(ffi, "test_addressof_function_with_struct", """
- struct foo_s { int x; };
- char myfunc(struct foo_s input) { return (char)(input.x + 42); }
- """)
- s = ffi.new("struct foo_s *", [5])[0]
- assert lib.myfunc(s) == 47
- assert not isinstance(lib.myfunc, ffi.CData)
- assert ffi.typeof(lib.myfunc) == ffi.typeof("long(*)(struct foo_s)")
- addr = ffi.addressof(lib, 'myfunc')
- assert addr(s) == 47
- assert isinstance(addr, ffi.CData)
- assert ffi.typeof(addr) == ffi.typeof("long(*)(struct foo_s)")
-
-def test_issue198():
- ffi = FFI()
- ffi.cdef("""
- typedef struct{...;} opaque_t;
- const opaque_t CONSTANT;
- int toint(opaque_t);
- """)
- lib = verify(ffi, 'test_issue198', """
- typedef int opaque_t;
- #define CONSTANT ((opaque_t)42)
- static int toint(opaque_t o) { return o; }
- """)
- def random_stuff():
- pass
- assert lib.toint(lib.CONSTANT) == 42
- random_stuff()
- assert lib.toint(lib.CONSTANT) == 42
-
-def test_constant_is_not_a_compiler_constant():
- ffi = FFI()
- ffi.cdef("static const float almost_forty_two;")
- lib = verify(ffi, 'test_constant_is_not_a_compiler_constant', """
- static float f(void) { return 42.25; }
- #define almost_forty_two (f())
- """)
- assert lib.almost_forty_two == 42.25
-
-def test_constant_of_unknown_size():
- ffi = FFI()
- ffi.cdef("""
- typedef ... opaque_t;
- const opaque_t CONSTANT;
- """)
- lib = verify(ffi, 'test_constant_of_unknown_size',
- "typedef int opaque_t;"
- "const int CONSTANT = 42;")
- e = py.test.raises(ffi.error, getattr, lib, 'CONSTANT')
- assert str(e.value) == ("constant 'CONSTANT' is of "
- "type 'opaque_t', whose size is not known")
-
-def test_variable_of_unknown_size():
- ffi = FFI()
- ffi.cdef("""
- typedef ... opaque_t;
- extern opaque_t globvar;
- """)
- lib = verify(ffi, 'test_variable_of_unknown_size', """
- typedef char opaque_t[6];
- opaque_t globvar = "hello";
- """)
- # can't read or write it at all
- e = py.test.raises(TypeError, getattr, lib, 'globvar')
- assert str(e.value) in ["cdata 'opaque_t' is opaque",
- "'opaque_t' is opaque or not completed yet"] #pypy
- e = py.test.raises(TypeError, setattr, lib, 'globvar', [])
- assert str(e.value) in ["'opaque_t' is opaque",
- "'opaque_t' is opaque or not completed yet"] #pypy
- # but we can get its address
- p = ffi.addressof(lib, 'globvar')
- assert ffi.typeof(p) == ffi.typeof('opaque_t *')
- assert ffi.string(ffi.cast("char *", p), 8) == b"hello"
-
-def test_constant_of_value_unknown_to_the_compiler():
- extra_c_source = udir.join(
- 'extra_test_constant_of_value_unknown_to_the_compiler.c')
- extra_c_source.write('const int external_foo = 42;\n')
- ffi = FFI()
- ffi.cdef("const int external_foo;")
- lib = verify(ffi, 'test_constant_of_value_unknown_to_the_compiler', """
- extern const int external_foo;
- """, sources=[str(extra_c_source)])
- assert lib.external_foo == 42
-
-def test_dotdot_in_source_file_names():
- extra_c_source = udir.join(
- 'extra_test_dotdot_in_source_file_names.c')
- extra_c_source.write('const int external_foo = 42;\n')
- ffi = FFI()
- ffi.cdef("const int external_foo;")
- lib = verify(ffi, 'test_dotdot_in_source_file_names', """
- extern const int external_foo;
- """, sources=[os.path.join(os.path.dirname(str(extra_c_source)),
- 'foobar', '..',
- os.path.basename(str(extra_c_source)))])
- assert lib.external_foo == 42
-
-def test_call_with_incomplete_structs():
- ffi = FFI()
- ffi.cdef("typedef struct {...;} foo_t; "
- "extern foo_t myglob; "
- "foo_t increment(foo_t s); "
- "double getx(foo_t s);")
- lib = verify(ffi, 'test_call_with_incomplete_structs', """
- typedef double foo_t;
- double myglob = 42.5;
- double getx(double x) { return x; }
- double increment(double x) { return x + 1; }
- """)
- assert lib.getx(lib.myglob) == 42.5
- assert lib.getx(lib.increment(lib.myglob)) == 43.5
-
-def test_struct_array_guess_length_2():
- ffi = FFI()
- ffi.cdef("struct foo_s { int a[...][...]; };")
- lib = verify(ffi, 'test_struct_array_guess_length_2',
- "struct foo_s { int x; int a[5][8]; int y; };")
- assert ffi.sizeof('struct foo_s') == 42 * ffi.sizeof('int')
- s = ffi.new("struct foo_s *")
- assert ffi.typeof(s.a) == ffi.typeof("int[5][8]")
- assert ffi.sizeof(s.a) == 40 * ffi.sizeof('int')
- assert s.a[4][7] == 0
- with pytest.raises(IndexError):
- s.a[4][8]
- with pytest.raises(IndexError):
- s.a[5][0]
- assert ffi.typeof(s.a) == ffi.typeof("int[5][8]")
- assert ffi.typeof(s.a[0]) == ffi.typeof("int[8]")
-
-def test_struct_array_guess_length_3():
- ffi = FFI()
- ffi.cdef("struct foo_s { int a[][...]; };")
- lib = verify(ffi, 'test_struct_array_guess_length_3',
- "struct foo_s { int x; int a[5][7]; int y; };")
- assert ffi.sizeof('struct foo_s') == 37 * ffi.sizeof('int')
- s = ffi.new("struct foo_s *")
- assert ffi.typeof(s.a) == ffi.typeof("int[][7]")
- assert s.a[4][6] == 0
- with pytest.raises(IndexError):
- s.a[4][7]
- assert ffi.typeof(s.a[0]) == ffi.typeof("int[7]")
-
-def test_global_var_array_2():
- ffi = FFI()
- ffi.cdef("extern int a[...][...];")
- lib = verify(ffi, 'test_global_var_array_2', 'int a[10][8];')
- lib.a[9][7] = 123456
- assert lib.a[9][7] == 123456
- with pytest.raises(IndexError):
- lib.a[0][8]
- with pytest.raises(IndexError):
- lib.a[10][0]
- assert ffi.typeof(lib.a) == ffi.typeof("int[10][8]")
- assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
-
-def test_global_var_array_3():
- ffi = FFI()
- ffi.cdef("extern int a[][...];")
- lib = verify(ffi, 'test_global_var_array_3', 'int a[10][8];')
- lib.a[9][7] = 123456
- assert lib.a[9][7] == 123456
- with pytest.raises(IndexError):
- lib.a[0][8]
- assert ffi.typeof(lib.a) == ffi.typeof("int(*)[8]")
- assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
-
-def test_global_var_array_4():
- ffi = FFI()
- ffi.cdef("extern int a[10][...];")
- lib = verify(ffi, 'test_global_var_array_4', 'int a[10][8];')
- lib.a[9][7] = 123456
- assert lib.a[9][7] == 123456
- with pytest.raises(IndexError):
- lib.a[0][8]
- with pytest.raises(IndexError):
- lib.a[10][8]
- assert ffi.typeof(lib.a) == ffi.typeof("int[10][8]")
- assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
-
-def test_some_integer_type():
- ffi = FFI()
- ffi.cdef("""
- typedef int... foo_t;
- typedef unsigned long... bar_t;
- typedef struct { foo_t a, b; } mystruct_t;
- foo_t foobar(bar_t, mystruct_t);
- static const bar_t mu = -20;
- static const foo_t nu = 20;
- """)
- lib = verify(ffi, 'test_some_integer_type', """
- typedef unsigned long long foo_t;
- typedef short bar_t;
- typedef struct { foo_t a, b; } mystruct_t;
- static foo_t foobar(bar_t x, mystruct_t s) {
- return (foo_t)x + s.a + s.b;
- }
- static const bar_t mu = -20;
- static const foo_t nu = 20;
- """)
- assert ffi.sizeof("foo_t") == ffi.sizeof("unsigned long long")
- assert ffi.sizeof("bar_t") == ffi.sizeof("short")
- maxulonglong = 2 ** 64 - 1
- assert int(ffi.cast("foo_t", -1)) == maxulonglong
- assert int(ffi.cast("bar_t", -1)) == -1
- assert lib.foobar(-1, [0, 0]) == maxulonglong
- assert lib.foobar(2 ** 15 - 1, [0, 0]) == 2 ** 15 - 1
- assert lib.foobar(10, [20, 31]) == 61
- assert lib.foobar(0, [0, maxulonglong]) == maxulonglong
- py.test.raises(OverflowError, lib.foobar, 2 ** 15, [0, 0])
- py.test.raises(OverflowError, lib.foobar, -(2 ** 15) - 1, [0, 0])
- py.test.raises(OverflowError, ffi.new, "mystruct_t *", [0, -1])
- assert lib.mu == -20
- assert lib.nu == 20
-
-def test_some_float_type():
- ffi = FFI()
- ffi.cdef("""
- typedef double... foo_t;
- typedef float... bar_t;
- foo_t sum(foo_t[]);
- bar_t neg(bar_t);
- """)
- lib = verify(ffi, 'test_some_float_type', """
- typedef float foo_t;
- static foo_t sum(foo_t x[]) { return x[0] + x[1]; }
- typedef double bar_t;
- static double neg(double x) { return -x; }
- """)
- assert lib.sum([40.0, 2.25]) == 42.25
- assert lib.sum([12.3, 45.6]) != 12.3 + 45.6 # precision loss
- assert lib.neg(12.3) == -12.3 # no precision loss
- assert ffi.sizeof("foo_t") == ffi.sizeof("float")
- assert ffi.sizeof("bar_t") == ffi.sizeof("double")
-
-def test_some_float_invalid_1():
- ffi = FFI()
- py.test.raises((FFIError, # with pycparser <= 2.17
- CDefError), # with pycparser >= 2.18
- ffi.cdef, "typedef long double... foo_t;")
-
-def test_some_float_invalid_2():
- ffi = FFI()
- ffi.cdef("typedef double... foo_t; foo_t neg(foo_t);")
- lib = verify(ffi, 'test_some_float_invalid_2', """
- typedef unsigned long foo_t;
- foo_t neg(foo_t x) { return -x; }
- """)
- e = py.test.raises(ffi.error, getattr, lib, 'neg')
- assert str(e.value) == ("primitive floating-point type with an unexpected "
- "size (or not a float type at all)")
-
-def test_some_float_invalid_3():
- ffi = FFI()
- ffi.cdef("typedef double... foo_t; foo_t neg(foo_t);")
- lib = verify(ffi, 'test_some_float_invalid_3', """
- typedef long double foo_t;
- foo_t neg(foo_t x) { return -x; }
- """, ignore_warnings=True)
- if ffi.sizeof("long double") == ffi.sizeof("double"):
- assert lib.neg(12.3) == -12.3
- else:
- e = py.test.raises(ffi.error, getattr, lib, 'neg')
- assert str(e.value) == ("primitive floating-point type is "
- "'long double', not supported for now with "
- "the syntax 'typedef double... xxx;'")
-
-def test_issue200():
- ffi = FFI()
- ffi.cdef("""
- typedef void (function_t)(void*);
- void function(void *);
- """)
- lib = verify(ffi, 'test_issue200', """
- static void function(void *p) { (void)p; }
- """)
- ffi.typeof('function_t*')
- lib.function(ffi.NULL)
- # assert did not crash
-
-def test_alignment_of_longlong():
- ffi = FFI()
- x1 = ffi.alignof('unsigned long long')
- assert x1 in [4, 8]
- ffi.cdef("struct foo_s { unsigned long long x; };")
- lib = verify(ffi, 'test_alignment_of_longlong',
- "struct foo_s { unsigned long long x; };")
- assert ffi.alignof('unsigned long long') == x1
- assert ffi.alignof('struct foo_s') == x1
-
-def test_import_from_lib():
- ffi = FFI()
- ffi.cdef("int mybar(int); static int myvar;\n#define MYFOO ...")
- lib = verify(ffi, 'test_import_from_lib',
- "#define MYFOO 42\n"
- "static int mybar(int x) { return x + 1; }\n"
- "static int myvar = -5;")
- assert sys.modules['_CFFI_test_import_from_lib'].lib is lib
- assert sys.modules['_CFFI_test_import_from_lib.lib'] is lib
- from _CFFI_test_import_from_lib.lib import MYFOO
- assert MYFOO == 42
- assert hasattr(lib, '__dict__')
- assert lib.__all__ == ['MYFOO', 'mybar'] # but not 'myvar'
- assert lib.__name__ == '_CFFI_test_import_from_lib.lib'
- assert lib.__class__ is type(sys) # !! hack for help()
-
-def test_macro_var_callback():
- ffi = FFI()
- ffi.cdef("extern int my_value; extern int *(*get_my_value)(void);")
- lib = verify(ffi, 'test_macro_var_callback',
- "int *(*get_my_value)(void);\n"
- "#define my_value (*get_my_value())")
- #
- values = ffi.new("int[50]")
- def it():
- for i in range(50):
- yield i
- it = it()
- #
- @ffi.callback("int *(*)(void)")
- def get_my_value():
- for nextvalue in it:
- return values + nextvalue
- lib.get_my_value = get_my_value
- #
- values[0] = 41
- assert lib.my_value == 41 # [0]
- p = ffi.addressof(lib, 'my_value') # [1]
- assert p == values + 1
- assert p[-1] == 41
- assert p[+1] == 0
- lib.my_value = 42 # [2]
- assert values[2] == 42
- assert p[-1] == 41
- assert p[+1] == 42
- #
- # if get_my_value raises or returns nonsense, the exception is printed
- # to stderr like with any callback, but then the C expression 'my_value'
- # expand to '*NULL'. We assume here that '&my_value' will return NULL
- # without segfaulting, and check for NULL when accessing the variable.
- @ffi.callback("int *(*)(void)")
- def get_my_value():
- raise LookupError
- lib.get_my_value = get_my_value
- py.test.raises(ffi.error, getattr, lib, 'my_value')
- py.test.raises(ffi.error, setattr, lib, 'my_value', 50)
- py.test.raises(ffi.error, ffi.addressof, lib, 'my_value')
- @ffi.callback("int *(*)(void)")
- def get_my_value():
- return "hello"
- lib.get_my_value = get_my_value
- py.test.raises(ffi.error, getattr, lib, 'my_value')
- e = py.test.raises(ffi.error, setattr, lib, 'my_value', 50)
- assert str(e.value) == "global variable 'my_value' is at address NULL"
-
-def test_const_fields():
- ffi = FFI()
- ffi.cdef("""struct foo_s { const int a; void *const b; };""")
- lib = verify(ffi, 'test_const_fields', """
- struct foo_s { const int a; void *const b; };""")
- foo_s = ffi.typeof("struct foo_s")
- assert foo_s.fields[0][0] == 'a'
- assert foo_s.fields[0][1].type is ffi.typeof("int")
- assert foo_s.fields[1][0] == 'b'
- assert foo_s.fields[1][1].type is ffi.typeof("void *")
-
-def test_restrict_fields():
- ffi = FFI()
- ffi.cdef("""struct foo_s { void * restrict b; };""")
- lib = verify(ffi, 'test_restrict_fields', """
- struct foo_s { void * __restrict b; };""")
- foo_s = ffi.typeof("struct foo_s")
- assert foo_s.fields[0][0] == 'b'
- assert foo_s.fields[0][1].type is ffi.typeof("void *")
-
-def test_volatile_fields():
- ffi = FFI()
- ffi.cdef("""struct foo_s { void * volatile b; };""")
- lib = verify(ffi, 'test_volatile_fields', """
- struct foo_s { void * volatile b; };""")
- foo_s = ffi.typeof("struct foo_s")
- assert foo_s.fields[0][0] == 'b'
- assert foo_s.fields[0][1].type is ffi.typeof("void *")
-
-def test_const_array_fields():
- ffi = FFI()
- ffi.cdef("""struct foo_s { const int a[4]; };""")
- lib = verify(ffi, 'test_const_array_fields', """
- struct foo_s { const int a[4]; };""")
- foo_s = ffi.typeof("struct foo_s")
- assert foo_s.fields[0][0] == 'a'
- assert foo_s.fields[0][1].type is ffi.typeof("int[4]")
-
-def test_const_array_fields_varlength():
- ffi = FFI()
- ffi.cdef("""struct foo_s { const int a[]; ...; };""")
- lib = verify(ffi, 'test_const_array_fields_varlength', """
- struct foo_s { const int a[4]; };""")
- foo_s = ffi.typeof("struct foo_s")
- assert foo_s.fields[0][0] == 'a'
- assert foo_s.fields[0][1].type is ffi.typeof("int[]")
-
-def test_const_array_fields_unknownlength():
- ffi = FFI()
- ffi.cdef("""struct foo_s { const int a[...]; ...; };""")
- lib = verify(ffi, 'test_const_array_fields_unknownlength', """
- struct foo_s { const int a[4]; };""")
- foo_s = ffi.typeof("struct foo_s")
- assert foo_s.fields[0][0] == 'a'
- assert foo_s.fields[0][1].type is ffi.typeof("int[4]")
-
-def test_const_function_args():
- ffi = FFI()
- ffi.cdef("""int foobar(const int a, const int *b, const int c[]);""")
- lib = verify(ffi, 'test_const_function_args', """
- int foobar(const int a, const int *b, const int c[]) {
- return a + *b + *c;
- }
- """)
- assert lib.foobar(100, ffi.new("int *", 40), ffi.new("int *", 2)) == 142
-
-def test_const_function_type_args():
- ffi = FFI()
- ffi.cdef("""extern int(*foobar)(const int a,const int*b,const int c[]);""")
- lib = verify(ffi, 'test_const_function_type_args', """
- int (*foobar)(const int a, const int *b, const int c[]);
- """)
- t = ffi.typeof(lib.foobar)
- assert t.args[0] is ffi.typeof("int")
- assert t.args[1] is ffi.typeof("int *")
- assert t.args[2] is ffi.typeof("int *")
-
-def test_const_constant():
- ffi = FFI()
- ffi.cdef("""struct foo_s { int x,y; }; const struct foo_s myfoo;""")
- lib = verify(ffi, 'test_const_constant', """
- struct foo_s { int x,y; }; const struct foo_s myfoo = { 40, 2 };
- """)
- assert lib.myfoo.x == 40
- assert lib.myfoo.y == 2
-
-def test_const_via_typedef():
- ffi = FFI()
- ffi.cdef("""typedef const int const_t; const_t aaa;""")
- lib = verify(ffi, 'test_const_via_typedef', """
- typedef const int const_t;
- #define aaa 42
- """)
- assert lib.aaa == 42
- with pytest.raises(AttributeError):
- lib.aaa = 43
-
-def test_win32_calling_convention_0():
- ffi = FFI()
- ffi.cdef("""
- int call1(int(__cdecl *cb)(int));
- int (*const call2)(int(__stdcall *cb)(int));
- """)
- lib = verify(ffi, 'test_win32_calling_convention_0', r"""
- #ifndef _MSC_VER
- # define __stdcall /* nothing */
- #endif
- int call1(int(*cb)(int)) {
- int i, result = 0;
- //printf("call1: cb = %p\n", cb);
- for (i = 0; i < 1000; i++)
- result += cb(i);
- //printf("result = %d\n", result);
- return result;
- }
- int call2(int(__stdcall *cb)(int)) {
- int i, result = 0;
- //printf("call2: cb = %p\n", cb);
- for (i = 0; i < 1000; i++)
- result += cb(-i);
- //printf("result = %d\n", result);
- return result;
- }
- """)
- @ffi.callback("int(int)")
- def cb1(x):
- return x * 2
- @ffi.callback("int __stdcall(int)")
- def cb2(x):
- return x * 3
- res = lib.call1(cb1)
- assert res == 500*999*2
- assert res == ffi.addressof(lib, 'call1')(cb1)
- res = lib.call2(cb2)
- assert res == -500*999*3
- assert res == ffi.addressof(lib, 'call2')(cb2)
- if sys.platform == 'win32' and not sys.maxsize > 2**32:
- assert '__stdcall' in str(ffi.typeof(cb2))
- assert '__stdcall' not in str(ffi.typeof(cb1))
- py.test.raises(TypeError, lib.call1, cb2)
- py.test.raises(TypeError, lib.call2, cb1)
- else:
- assert '__stdcall' not in str(ffi.typeof(cb2))
- assert ffi.typeof(cb2) is ffi.typeof(cb1)
-
-def test_win32_calling_convention_1():
- ffi = FFI()
- ffi.cdef("""
- int __cdecl call1(int(__cdecl *cb)(int));
- int __stdcall call2(int(__stdcall *cb)(int));
- int (__cdecl *const cb1)(int);
- int (__stdcall *const cb2)(int);
- """)
- lib = verify(ffi, 'test_win32_calling_convention_1', r"""
- #ifndef _MSC_VER
- # define __cdecl
- # define __stdcall
- #endif
- int __cdecl cb1(int x) { return x * 2; }
- int __stdcall cb2(int x) { return x * 3; }
-
- int __cdecl call1(int(__cdecl *cb)(int)) {
- int i, result = 0;
- //printf("here1\n");
- //printf("cb = %p, cb1 = %p\n", cb, (void *)cb1);
- for (i = 0; i < 1000; i++)
- result += cb(i);
- //printf("result = %d\n", result);
- return result;
- }
- int __stdcall call2(int(__stdcall *cb)(int)) {
- int i, result = 0;
- //printf("here1\n");
- //printf("cb = %p, cb2 = %p\n", cb, (void *)cb2);
- for (i = 0; i < 1000; i++)
- result += cb(-i);
- //printf("result = %d\n", result);
- return result;
- }
- """)
- #print '<<< cb1 =', ffi.addressof(lib, 'cb1')
- ptr_call1 = ffi.addressof(lib, 'call1')
- assert lib.call1(ffi.addressof(lib, 'cb1')) == 500*999*2
- assert ptr_call1(ffi.addressof(lib, 'cb1')) == 500*999*2
- #print '<<< cb2 =', ffi.addressof(lib, 'cb2')
- ptr_call2 = ffi.addressof(lib, 'call2')
- assert lib.call2(ffi.addressof(lib, 'cb2')) == -500*999*3
- assert ptr_call2(ffi.addressof(lib, 'cb2')) == -500*999*3
- #print '<<< done'
-
-def test_win32_calling_convention_2():
- # any mistake in the declaration of plain function (including the
- # precise argument types and, here, the calling convention) are
- # automatically corrected. But this does not apply to the 'cb'
- # function pointer argument.
- ffi = FFI()
- ffi.cdef("""
- int __stdcall call1(int(__cdecl *cb)(int));
- int __cdecl call2(int(__stdcall *cb)(int));
- int (__cdecl *const cb1)(int);
- int (__stdcall *const cb2)(int);
- """)
- lib = verify(ffi, 'test_win32_calling_convention_2', """
- #ifndef _MSC_VER
- # define __cdecl
- # define __stdcall
- #endif
- int __cdecl call1(int(__cdecl *cb)(int)) {
- int i, result = 0;
- for (i = 0; i < 1000; i++)
- result += cb(i);
- return result;
- }
- int __stdcall call2(int(__stdcall *cb)(int)) {
- int i, result = 0;
- for (i = 0; i < 1000; i++)
- result += cb(-i);
- return result;
- }
- int __cdecl cb1(int x) { return x * 2; }
- int __stdcall cb2(int x) { return x * 3; }
- """)
- ptr_call1 = ffi.addressof(lib, 'call1')
- ptr_call2 = ffi.addressof(lib, 'call2')
- if sys.platform == 'win32' and not sys.maxsize > 2**32:
- py.test.raises(TypeError, lib.call1, ffi.addressof(lib, 'cb2'))
- py.test.raises(TypeError, ptr_call1, ffi.addressof(lib, 'cb2'))
- py.test.raises(TypeError, lib.call2, ffi.addressof(lib, 'cb1'))
- py.test.raises(TypeError, ptr_call2, ffi.addressof(lib, 'cb1'))
- assert lib.call1(ffi.addressof(lib, 'cb1')) == 500*999*2
- assert ptr_call1(ffi.addressof(lib, 'cb1')) == 500*999*2
- assert lib.call2(ffi.addressof(lib, 'cb2')) == -500*999*3
- assert ptr_call2(ffi.addressof(lib, 'cb2')) == -500*999*3
-
-def test_win32_calling_convention_3():
- ffi = FFI()
- ffi.cdef("""
- struct point { int x, y; };
-
- int (*const cb1)(struct point);
- int (__stdcall *const cb2)(struct point);
-
- struct point __stdcall call1(int(*cb)(struct point));
- struct point call2(int(__stdcall *cb)(struct point));
- """)
- lib = verify(ffi, 'test_win32_calling_convention_3', r"""
- #ifndef _MSC_VER
- # define __cdecl
- # define __stdcall
- #endif
- struct point { int x, y; };
- int cb1(struct point pt) { return pt.x + 10 * pt.y; }
- int __stdcall cb2(struct point pt) { return pt.x + 100 * pt.y; }
- struct point __stdcall call1(int(__cdecl *cb)(struct point)) {
- int i;
- struct point result = { 0, 0 };
- //printf("here1\n");
- //printf("cb = %p, cb1 = %p\n", cb, (void *)cb1);
- for (i = 0; i < 1000; i++) {
- struct point p = { i, -i };
- int r = cb(p);
- result.x += r;
- result.y -= r;
- }
- return result;
- }
- struct point __cdecl call2(int(__stdcall *cb)(struct point)) {
- int i;
- struct point result = { 0, 0 };
- for (i = 0; i < 1000; i++) {
- struct point p = { -i, i };
- int r = cb(p);
- result.x += r;
- result.y -= r;
- }
- return result;
- }
- """)
- ptr_call1 = ffi.addressof(lib, 'call1')
- ptr_call2 = ffi.addressof(lib, 'call2')
- if sys.platform == 'win32' and not sys.maxsize > 2**32:
- py.test.raises(TypeError, lib.call1, ffi.addressof(lib, 'cb2'))
- py.test.raises(TypeError, ptr_call1, ffi.addressof(lib, 'cb2'))
- py.test.raises(TypeError, lib.call2, ffi.addressof(lib, 'cb1'))
- py.test.raises(TypeError, ptr_call2, ffi.addressof(lib, 'cb1'))
- pt = lib.call1(ffi.addressof(lib, 'cb1'))
- assert (pt.x, pt.y) == (-9*500*999, 9*500*999)
- pt = ptr_call1(ffi.addressof(lib, 'cb1'))
- assert (pt.x, pt.y) == (-9*500*999, 9*500*999)
- pt = lib.call2(ffi.addressof(lib, 'cb2'))
- assert (pt.x, pt.y) == (99*500*999, -99*500*999)
- pt = ptr_call2(ffi.addressof(lib, 'cb2'))
- assert (pt.x, pt.y) == (99*500*999, -99*500*999)
-
-def test_extern_python_1():
- import warnings
- ffi = FFI()
- with warnings.catch_warnings(record=True) as log:
- ffi.cdef("""
- extern "Python" {
- int bar(int, int);
- void baz(int, int);
- int bok(void);
- void boz(void);
- }
- """)
- assert len(log) == 0, "got a warning: %r" % (log,)
- lib = verify(ffi, 'test_extern_python_1', """
- static void baz(int, int); /* forward */
- """)
- assert ffi.typeof(lib.bar) == ffi.typeof("int(*)(int, int)")
- with FdWriteCapture() as f:
- res = lib.bar(4, 5)
- assert res == 0
- assert f.getvalue() == (
- b"extern \"Python\": function _CFFI_test_extern_python_1.bar() called, "
- b"but no code was attached "
- b"to it yet with @ffi.def_extern(). Returning 0.\n")
-
- @ffi.def_extern("bar")
- def my_bar(x, y):
- seen.append(("Bar", x, y))
- return x * y
- assert my_bar != lib.bar
- seen = []
- res = lib.bar(6, 7)
- assert seen == [("Bar", 6, 7)]
- assert res == 42
-
- def baz(x, y):
- seen.append(("Baz", x, y))
- baz1 = ffi.def_extern()(baz)
- assert baz1 is baz
- seen = []
- baz(long(40), long(4))
- res = lib.baz(long(50), long(8))
- assert res is None
- assert seen == [("Baz", 40, 4), ("Baz", 50, 8)]
- assert type(seen[0][1]) is type(seen[0][2]) is long
- assert type(seen[1][1]) is type(seen[1][2]) is int
-
- @ffi.def_extern(name="bok")
- def bokk():
- seen.append("Bok")
- return 42
- seen = []
- assert lib.bok() == 42
- assert seen == ["Bok"]
-
- @ffi.def_extern()
- def boz():
- seen.append("Boz")
- seen = []
- assert lib.boz() is None
- assert seen == ["Boz"]
-
-def test_extern_python_bogus_name():
- ffi = FFI()
- ffi.cdef("extern int abc;")
- lib = verify(ffi, 'test_extern_python_bogus_name', "int abc;")
- def fn():
- pass
- py.test.raises(ffi.error, ffi.def_extern("unknown_name"), fn)
- py.test.raises(ffi.error, ffi.def_extern("abc"), fn)
- assert lib.abc == 0
- e = py.test.raises(ffi.error, ffi.def_extern("abc"), fn)
- assert str(e.value) == ("ffi.def_extern('abc'): no 'extern \"Python\"' "
- "function with this name")
- e = py.test.raises(ffi.error, ffi.def_extern(), fn)
- assert str(e.value) == ("ffi.def_extern('fn'): no 'extern \"Python\"' "
- "function with this name")
- #
- py.test.raises(TypeError, ffi.def_extern(42), fn)
- py.test.raises((TypeError, AttributeError), ffi.def_extern(), "foo")
- class X:
- pass
- x = X()
- x.__name__ = x
- py.test.raises(TypeError, ffi.def_extern(), x)
-
-def test_extern_python_bogus_result_type():
- ffi = FFI()
- ffi.cdef("""extern "Python" void bar(int);""")
- lib = verify(ffi, 'test_extern_python_bogus_result_type', "")
- #
- @ffi.def_extern()
- def bar(n):
- return n * 10
- with StdErrCapture() as f:
- res = lib.bar(321)
- assert res is None
- msg = f.getvalue()
- assert "rom cffi callback %r" % (bar,) in msg
- assert "rying to convert the result back to C:\n" in msg
- assert msg.endswith(
- "TypeError: callback with the return type 'void' must return None\n")
-
-def test_extern_python_redefine():
- ffi = FFI()
- ffi.cdef("""extern "Python" int bar(int);""")
- lib = verify(ffi, 'test_extern_python_redefine', "")
- #
- @ffi.def_extern()
- def bar(n):
- return n * 10
- assert lib.bar(42) == 420
- #
- @ffi.def_extern()
- def bar(n):
- return -n
- assert lib.bar(42) == -42
-
-def test_extern_python_struct():
- ffi = FFI()
- ffi.cdef("""
- struct foo_s { int a, b, c; };
- extern "Python" int bar(int, struct foo_s, int);
- extern "Python" { struct foo_s baz(int, int);
- struct foo_s bok(void); }
- """)
- lib = verify(ffi, 'test_extern_python_struct',
- "struct foo_s { int a, b, c; };")
- #
- @ffi.def_extern()
- def bar(x, s, z):
- return x + s.a + s.b + s.c + z
- res = lib.bar(1000, [1001, 1002, 1004], 1008)
- assert res == 5015
- #
- @ffi.def_extern()
- def baz(x, y):
- return [x + y, x - y, x * y]
- res = lib.baz(1000, 42)
- assert res.a == 1042
- assert res.b == 958
- assert res.c == 42000
- #
- @ffi.def_extern()
- def bok():
- return [10, 20, 30]
- res = lib.bok()
- assert [res.a, res.b, res.c] == [10, 20, 30]
-
-def test_extern_python_long_double():
- ffi = FFI()
- ffi.cdef("""
- extern "Python" int bar(int, long double, int);
- extern "Python" long double baz(int, int);
- extern "Python" long double bok(void);
- """)
- lib = verify(ffi, 'test_extern_python_long_double', "")
- #
- @ffi.def_extern()
- def bar(x, l, z):
- seen.append((x, l, z))
- return 6
- seen = []
- lib.bar(10, 3.5, 20)
- expected = ffi.cast("long double", 3.5)
- assert repr(seen) == repr([(10, expected, 20)])
- #
- @ffi.def_extern()
- def baz(x, z):
- assert x == 10 and z == 20
- return expected
- res = lib.baz(10, 20)
- assert repr(res) == repr(expected)
- #
- @ffi.def_extern()
- def bok():
- return expected
- res = lib.bok()
- assert repr(res) == repr(expected)
-
-def test_extern_python_signature():
- ffi = FFI()
- lib = verify(ffi, 'test_extern_python_signature', "")
- py.test.raises(TypeError, ffi.def_extern(425), None)
- py.test.raises(TypeError, ffi.def_extern, 'a', 'b', 'c', 'd')
-
-def test_extern_python_errors():
- ffi = FFI()
- ffi.cdef("""
- extern "Python" int bar(int);
- """)
- lib = verify(ffi, 'test_extern_python_errors', "")
-
- seen = []
- def oops(*args):
- seen.append(args)
-
- @ffi.def_extern(onerror=oops)
- def bar(x):
- return x + ""
- assert lib.bar(10) == 0
-
- @ffi.def_extern(name="bar", onerror=oops, error=-66)
- def bar2(x):
- return x + ""
- assert lib.bar(10) == -66
-
- assert len(seen) == 2
- exc, val, tb = seen[0]
- assert exc is TypeError
- assert isinstance(val, TypeError)
- assert tb.tb_frame.f_code.co_name == "bar"
- exc, val, tb = seen[1]
- assert exc is TypeError
- assert isinstance(val, TypeError)
- assert tb.tb_frame.f_code.co_name == "bar2"
- #
- # a case where 'onerror' is not callable
- py.test.raises(TypeError, ffi.def_extern(name='bar', onerror=42),
- lambda x: x)
-
-def test_extern_python_stdcall():
- ffi = FFI()
- ffi.cdef("""
- extern "Python" int __stdcall foo(int);
- extern "Python" int WINAPI bar(int);
- static int (__stdcall * mycb1)(int);
- static int indirect_call(int);
- """)
- lib = verify(ffi, 'test_extern_python_stdcall', """
- #ifndef _MSC_VER
- # define __stdcall
- #endif
- static int (__stdcall * mycb1)(int);
- static int indirect_call(int x) {
- return mycb1(x);
- }
- """)
- #
- @ffi.def_extern()
- def foo(x):
- return x + 42
- @ffi.def_extern()
- def bar(x):
- return x + 43
- assert lib.foo(100) == 142
- assert lib.bar(100) == 143
- lib.mycb1 = lib.foo
- assert lib.mycb1(200) == 242
- assert lib.indirect_call(300) == 342
-
-def test_extern_python_plus_c():
- ffi = FFI()
- ffi.cdef("""
- extern "Python+C" int foo(int);
- extern "C +\tPython" int bar(int);
- int call_me(int);
- """)
- lib = verify(ffi, 'test_extern_python_plus_c', """
- int foo(int);
- #ifdef __GNUC__
- __attribute__((visibility("hidden")))
- #endif
- int bar(int);
-
- static int call_me(int x) {
- return foo(x) - bar(x);
- }
- """)
- #
- @ffi.def_extern()
- def foo(x):
- return x * 42
- @ffi.def_extern()
- def bar(x):
- return x * 63
- assert lib.foo(100) == 4200
- assert lib.bar(100) == 6300
- assert lib.call_me(100) == -2100
-
-def test_introspect_function():
- ffi = FFI()
- ffi.cdef("float f1(double);")
- lib = verify(ffi, 'test_introspect_function', """
- float f1(double x) { return (float)x; }
- """)
- assert dir(lib) == ['f1']
- FUNC = ffi.typeof(lib.f1)
- assert FUNC.kind == 'function'
- assert FUNC.args[0].cname == 'double'
- assert FUNC.result.cname == 'float'
- assert ffi.typeof(ffi.addressof(lib, 'f1')) is FUNC
-
-def test_introspect_global_var():
- ffi = FFI()
- ffi.cdef("extern float g1;")
- lib = verify(ffi, 'test_introspect_global_var', """
- float g1;
- """)
- assert dir(lib) == ['g1']
- FLOATPTR = ffi.typeof(ffi.addressof(lib, 'g1'))
- assert FLOATPTR.kind == 'pointer'
- assert FLOATPTR.item.cname == 'float'
-
-def test_introspect_global_var_array():
- ffi = FFI()
- ffi.cdef("extern float g1[100];")
- lib = verify(ffi, 'test_introspect_global_var_array', """
- float g1[100];
- """)
- assert dir(lib) == ['g1']
- FLOATARRAYPTR = ffi.typeof(ffi.addressof(lib, 'g1'))
- assert FLOATARRAYPTR.kind == 'pointer'
- assert FLOATARRAYPTR.item.kind == 'array'
- assert FLOATARRAYPTR.item.length == 100
- assert ffi.typeof(lib.g1) is FLOATARRAYPTR.item
-
-def test_introspect_integer_const():
- ffi = FFI()
- ffi.cdef("#define FOO 42")
- lib = verify(ffi, 'test_introspect_integer_const', """
- #define FOO 42
- """)
- assert dir(lib) == ['FOO']
- assert lib.FOO == ffi.integer_const('FOO') == 42
-
-def test_introspect_typedef():
- ffi = FFI()
- ffi.cdef("typedef int foo_t;")
- lib = verify(ffi, 'test_introspect_typedef', """
- typedef int foo_t;
- """)
- assert ffi.list_types() == (['foo_t'], [], [])
- assert ffi.typeof('foo_t').kind == 'primitive'
- assert ffi.typeof('foo_t').cname == 'int'
-
-def test_introspect_typedef_multiple():
- ffi = FFI()
- ffi.cdef("typedef signed char a_t, c_t, g_t, b_t;")
- lib = verify(ffi, 'test_introspect_typedef_multiple', """
- typedef signed char a_t, c_t, g_t, b_t;
- """)
- assert ffi.list_types() == (['a_t', 'b_t', 'c_t', 'g_t'], [], [])
-
-def test_introspect_struct():
- ffi = FFI()
- ffi.cdef("struct foo_s { int a; };")
- lib = verify(ffi, 'test_introspect_struct', """
- struct foo_s { int a; };
- """)
- assert ffi.list_types() == ([], ['foo_s'], [])
- assert ffi.typeof('struct foo_s').kind == 'struct'
- assert ffi.typeof('struct foo_s').cname == 'struct foo_s'
-
-def test_introspect_union():
- ffi = FFI()
- ffi.cdef("union foo_s { int a; };")
- lib = verify(ffi, 'test_introspect_union', """
- union foo_s { int a; };
- """)
- assert ffi.list_types() == ([], [], ['foo_s'])
- assert ffi.typeof('union foo_s').kind == 'union'
- assert ffi.typeof('union foo_s').cname == 'union foo_s'
-
-def test_introspect_struct_and_typedef():
- ffi = FFI()
- ffi.cdef("typedef struct { int a; } foo_t;")
- lib = verify(ffi, 'test_introspect_struct_and_typedef', """
- typedef struct { int a; } foo_t;
- """)
- assert ffi.list_types() == (['foo_t'], [], [])
- assert ffi.typeof('foo_t').kind == 'struct'
- assert ffi.typeof('foo_t').cname == 'foo_t'
-
-def test_introspect_included_type():
- SOURCE = """
- typedef signed char schar_t;
- struct sint_t { int x; };
- """
- ffi1 = FFI()
- ffi1.cdef(SOURCE)
- ffi2 = FFI()
- ffi2.include(ffi1)
- verify(ffi1, "test_introspect_included_type_parent", SOURCE)
- verify(ffi2, "test_introspect_included_type", SOURCE)
- assert ffi1.list_types() == ffi2.list_types() == (
- ['schar_t'], ['sint_t'], [])
-
-def test_introspect_order():
- ffi = FFI()
- ffi.cdef("union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb;")
- ffi.cdef("union CFFIg { int a; }; typedef struct CFFIcc { int a; } CFFIbbb;")
- ffi.cdef("union CFFIaa { int a; }; typedef struct CFFIa { int a; } CFFIbb;")
- verify(ffi, "test_introspect_order", """
- union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb;
- union CFFIg { int a; }; typedef struct CFFIcc { int a; } CFFIbbb;
- union CFFIaa { int a; }; typedef struct CFFIa { int a; } CFFIbb;
- """)
- assert ffi.list_types() == (['CFFIb', 'CFFIbb', 'CFFIbbb'],
- ['CFFIa', 'CFFIcc', 'CFFIccc'],
- ['CFFIaa', 'CFFIaaa', 'CFFIg'])
-
-def test_bool_in_cpp():
- # this works when compiled as C, but in cffi < 1.7 it fails as C++
- ffi = FFI()
- ffi.cdef("bool f(void);")
- lib = verify(ffi, "test_bool_in_cpp", "char f(void) { return 2; }")
- assert lib.f() is True
-
-def test_bool_in_cpp_2():
- ffi = FFI()
- ffi.cdef('int add(int a, int b);')
- lib = verify(ffi, "test_bool_bug_cpp", '''
- typedef bool _Bool; /* there is a Windows header with this line */
- int add(int a, int b)
- {
- return a + b;
- }''', source_extension='.cpp')
- c = lib.add(2, 3)
- assert c == 5
-
-def test_struct_field_opaque():
- ffi = FFI()
- ffi.cdef("struct a { struct b b; };")
- e = py.test.raises(TypeError, verify,
- ffi, "test_struct_field_opaque", "?")
- assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
- " type (not declared in cdef())")
- ffi = FFI()
- ffi.cdef("struct a { struct b b[2]; };")
- e = py.test.raises(TypeError, verify,
- ffi, "test_struct_field_opaque", "?")
- assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
- " type (not declared in cdef())")
- ffi = FFI()
- ffi.cdef("struct a { struct b b[]; };")
- e = py.test.raises(TypeError, verify,
- ffi, "test_struct_field_opaque", "?")
- assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
- " type (not declared in cdef())")
-
-def test_function_arg_opaque():
- py.test.skip("can currently declare a function with an opaque struct "
- "as argument, but AFAICT it's impossible to call it later")
-
-def test_function_returns_opaque():
- ffi = FFI()
- ffi.cdef("struct a foo(int);")
- e = py.test.raises(TypeError, verify,
- ffi, "test_function_returns_opaque", "?")
- assert str(e.value) == ("function foo: 'struct a' is used as result type,"
- " but is opaque")
-
-def test_function_returns_union():
- ffi = FFI()
- ffi.cdef("union u1 { int a, b; }; union u1 f1(int);")
- lib = verify(ffi, "test_function_returns_union", """
- union u1 { int a, b; };
- static union u1 f1(int x) { union u1 u; u.b = x; return u; }
- """)
- assert lib.f1(51).a == 51
-
-def test_function_returns_partial_struct():
- ffi = FFI()
- ffi.cdef("struct aaa { int a; ...; }; struct aaa f1(int);")
- lib = verify(ffi, "test_function_returns_partial_struct", """
- struct aaa { int b, a, c; };
- static struct aaa f1(int x) { struct aaa s = {0}; s.a = x; return s; }
- """)
- assert lib.f1(52).a == 52
-
-def test_function_returns_float_complex():
- if sys.platform == 'win32':
- py.test.skip("MSVC may not support _Complex")
- ffi = FFI()
- ffi.cdef("float _Complex f1(float a, float b);");
- lib = verify(ffi, "test_function_returns_float_complex", """
- #include <complex.h>
- static float _Complex f1(float a, float b) { return a + I*2.0f*b; }
- """, no_cpp=True) # <complex.h> fails on some systems with C++
- result = lib.f1(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
-
-def test_function_returns_double_complex():
- if sys.platform == 'win32':
- py.test.skip("MSVC may not support _Complex")
- ffi = FFI()
- ffi.cdef("double _Complex f1(double a, double b);");
- lib = verify(ffi, "test_function_returns_double_complex", """
- #include <complex.h>
- static double _Complex f1(double a, double b) { return a + I*2.0*b; }
- """, no_cpp=True) # <complex.h> fails on some systems with C++
- result = lib.f1(1.25, 5.1)
- assert type(result) == complex
- assert result.real == 1.25 # exact
- assert result.imag == 2*5.1 # exact
-
-def test_function_argument_float_complex():
- if sys.platform == 'win32':
- py.test.skip("MSVC may not support _Complex")
- ffi = FFI()
- ffi.cdef("float f1(float _Complex x);");
- lib = verify(ffi, "test_function_argument_float_complex", """
- #include <complex.h>
- static float f1(float _Complex x) { return cabsf(x); }
- """, no_cpp=True) # <complex.h> fails on some systems with C++
- x = complex(12.34, 56.78)
- result = lib.f1(x)
- assert abs(result - abs(x)) < 1e-5
-
-def test_function_argument_double_complex():
- if sys.platform == 'win32':
- py.test.skip("MSVC may not support _Complex")
- ffi = FFI()
- ffi.cdef("double f1(double _Complex);");
- lib = verify(ffi, "test_function_argument_double_complex", """
- #include <complex.h>
- static double f1(double _Complex x) { return cabs(x); }
- """, no_cpp=True) # <complex.h> fails on some systems with C++
- x = complex(12.34, 56.78)
- result = lib.f1(x)
- assert abs(result - abs(x)) < 1e-11
-
-def test_typedef_array_dotdotdot():
- ffi = FFI()
- ffi.cdef("""
- typedef int foo_t[...], bar_t[...];
- extern int gv[...];
- typedef int mat_t[...][...];
- typedef int vmat_t[][...];
- """)
- lib = verify(ffi, "test_typedef_array_dotdotdot", """
- typedef int foo_t[50], bar_t[50];
- int gv[23];
- typedef int mat_t[6][7];
- typedef int vmat_t[][8];
- """)
- assert ffi.sizeof("foo_t") == 50 * ffi.sizeof("int")
- assert ffi.sizeof("bar_t") == 50 * ffi.sizeof("int")
- assert len(ffi.new("foo_t")) == 50
- assert len(ffi.new("bar_t")) == 50
- assert ffi.sizeof(lib.gv) == 23 * ffi.sizeof("int")
- assert ffi.sizeof("mat_t") == 6 * 7 * ffi.sizeof("int")
- assert len(ffi.new("mat_t")) == 6
- assert len(ffi.new("mat_t")[3]) == 7
- py.test.raises(ffi.error, ffi.sizeof, "vmat_t")
- p = ffi.new("vmat_t", 4)
- assert ffi.sizeof(p[3]) == 8 * ffi.sizeof("int")
-
-def test_typedef_array_dotdotdot_usage():
- ffi = FFI()
- ffi.cdef("""
- typedef int foo_t[...];
- typedef int mat_t[...][...];
- struct s { foo_t a; foo_t *b; foo_t **c; };
- int myfunc(foo_t a, foo_t *b, foo_t **c);
- struct sm { mat_t a; mat_t *b; mat_t **c; };
- int myfuncm(mat_t a, mat_t *b, mat_t **c);
- """)
- lib = verify(ffi, "test_typedef_array_dotdotdot_usage", """
- typedef int foo_t[50];
- typedef int mat_t[6][7];
- struct s { foo_t a; foo_t *b; foo_t **c; };
- static int myfunc(foo_t a, foo_t *b, foo_t **c) { return (**c)[49]; }
- struct sm { mat_t a; mat_t *b; mat_t **c; };
- static int myfuncm(mat_t a, mat_t *b, mat_t **c) { return (**c)[5][6]; }
- """)
- assert ffi.sizeof("foo_t") == 50 * ffi.sizeof("int")
- p = ffi.new("struct s *")
- assert ffi.sizeof(p[0]) == 50 * ffi.sizeof("int") + 2 * ffi.sizeof("void *")
- p.a[49] = 321
- p.b = ffi.addressof(p, 'a')
- p.c = ffi.addressof(p, 'b')
- assert lib.myfunc(ffi.NULL, ffi.NULL, p.c) == 321
- #
- assert ffi.sizeof("mat_t") == 42 * ffi.sizeof("int")
- p = ffi.new("struct sm *")
- assert ffi.sizeof(p[0]) == 42 * ffi.sizeof("int") + 2 * ffi.sizeof("void *")
- p.a[5][6] = -321
- p.b = ffi.addressof(p, 'a')
- p.c = ffi.addressof(p, 'b')
- assert lib.myfuncm(ffi.NULL, ffi.NULL, p.c) == -321
-
-def test_call_with_custom_field_pos():
- ffi = FFI()
- ffi.cdef("""
- struct foo { int x; ...; };
- struct foo f(void);
- struct foo g(int, ...);
- """)
- lib = verify(ffi, "test_call_with_custom_field_pos", """
- struct foo { int y, x; };
- struct foo f(void) {
- struct foo s = { 40, 200 };
- return s;
- }
- struct foo g(int a, ...) { return f(); }
- """)
- assert lib.f().x == 200
- e = py.test.raises(NotImplementedError, lib.g, 0)
- assert str(e.value) == (
- 'ctype \'struct foo\' not supported as return value. 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 return value if the function is \'API mode\' and non-variadic '
- '(i.e. declared inside ffibuilder.cdef()+ffibuilder.set_source() '
- 'and not taking a final \'...\' argument)')
-
-def test_call_with_nested_anonymous_struct():
- if sys.platform == 'win32':
- py.test.skip("needs a GCC extension")
- ffi = FFI()
- ffi.cdef("""
- struct foo { int a; union { int b, c; }; };
- struct foo f(void);
- struct foo g(int, ...);
- """)
- lib = verify(ffi, "test_call_with_nested_anonymous_struct", """
- struct foo { int a; union { int b, c; }; };
- struct foo f(void) {
- struct foo s;
- s.a = 40;
- s.b = 200;
- return s;
- }
- struct foo g(int a, ...) { return f(); }
- """)
- assert lib.f().b == 200
- e = py.test.raises(NotImplementedError, lib.g, 0)
- assert str(e.value) == (
- 'ctype \'struct foo\' not supported as return value. 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 return value if the function is \'API mode\' and non-variadic '
- '(i.e. declared inside ffibuilder.cdef()+ffibuilder.set_source() '
- 'and not taking a final \'...\' argument)')
-
-def test_call_with_bitfield():
- ffi = FFI()
- ffi.cdef("""
- struct foo { int x:5; };
- struct foo f(void);
- struct foo g(int, ...);
- """)
- lib = verify(ffi, "test_call_with_bitfield", """
- struct foo { int x:5; };
- struct foo f(void) {
- struct foo s = { 11 };
- return s;
- }
- struct foo g(int a, ...) { return f(); }
- """)
- assert lib.f().x == 11
- e = py.test.raises(NotImplementedError, lib.g, 0)
- assert str(e.value) == (
- "ctype 'struct foo' not supported as return value. It is a struct "
- "with bit fields, which libffi does not support. Such structs are "
- "only supported as return value if the function is 'API mode' and "
- "non-variadic (i.e. declared inside ffibuilder.cdef()+ffibuilder."
- "set_source() and not taking a final '...' argument)")
-
-def test_call_with_zero_length_field():
- if sys.platform == 'win32':
- py.test.skip("zero-length field not supported by MSVC")
- ffi = FFI()
- ffi.cdef("""
- struct foo { int a; int x[0]; };
- struct foo f(void);
- struct foo g(int, ...);
- """)
- lib = verify(ffi, "test_call_with_zero_length_field", """
- struct foo { int a; int x[0]; };
- struct foo f(void) {
- struct foo s = { 42 };
- return s;
- }
- struct foo g(int a, ...) { return f(); }
- """)
- assert lib.f().a == 42
- e = py.test.raises(NotImplementedError, lib.g, 0)
- assert str(e.value) == (
- "ctype 'struct foo' not supported as return value. It is a "
- "struct with a zero-length array, which libffi does not support."
- " Such structs are only supported as return value if the function is "
- "'API mode' and non-variadic (i.e. declared inside ffibuilder.cdef()"
- "+ffibuilder.set_source() and not taking a final '...' argument)")
-
-def test_call_with_union():
- ffi = FFI()
- ffi.cdef("""
- union foo { int a; char b; };
- union foo f(void);
- union foo g(int, ...);
- """)
- lib = verify(ffi, "test_call_with_union", """
- union foo { int a; char b; };
- union foo f(void) {
- union foo s = { 42 };
- return s;
- }
- union foo g(int a, ...) { return f(); }
- """)
- assert lib.f().a == 42
- e = py.test.raises(NotImplementedError, lib.g, 0)
- assert str(e.value) == (
- "ctype 'union foo' not supported as return value by libffi. "
- "Unions are only supported as return value if the function is "
- "'API mode' and non-variadic (i.e. declared inside ffibuilder.cdef()"
- "+ffibuilder.set_source() and not taking a final '...' argument)")
-
-def test_call_with_packed_struct():
- if sys.platform == 'win32':
- py.test.skip("needs a GCC extension")
- ffi = FFI()
- ffi.cdef("""
- struct foo { char y; int x; };
- struct foo f(void);
- struct foo g(int, ...);
- """, packed=True)
- lib = verify(ffi, "test_call_with_packed_struct", """
- struct foo { char y; int x; } __attribute__((packed));
- struct foo f(void) {
- struct foo s = { 40, 200 };
- return s;
- }
- struct foo g(int a, ...) {
- struct foo s = { 41, 201 };
- return s;
- }
- """)
- assert ord(lib.f().y) == 40
- assert lib.f().x == 200
- e = py.test.raises(NotImplementedError, lib.g, 0)
- assert str(e.value) == (
- "ctype 'struct foo' not supported as return value. It is a "
- "'packed' structure, with a different layout than expected by libffi."
- " Such structs are only supported as return value if the function is "
- "'API mode' and non-variadic (i.e. declared inside ffibuilder.cdef()"
- "+ffibuilder.set_source() and not taking a final '...' argument)")
-
-def test_pack_not_supported():
- ffi = FFI()
- ffi.cdef("""struct foo { char y; int x; };""", pack=2)
- py.test.raises(NotImplementedError, verify,
- ffi, "test_pack_not_supported", "")
-
-def test_gcc_visibility_hidden():
- if sys.platform == 'win32':
- py.test.skip("test for gcc/clang")
- ffi = FFI()
- ffi.cdef("""
- int f(int);
- """)
- lib = verify(ffi, "test_gcc_visibility_hidden", """
- int f(int a) { return a + 40; }
- """, extra_compile_args=['-fvisibility=hidden'])
- assert lib.f(2) == 42
-
-def test_override_default_definition():
- ffi = FFI()
- ffi.cdef("typedef long int16_t, char16_t;")
- lib = verify(ffi, "test_override_default_definition", "")
- assert ffi.typeof("int16_t") is ffi.typeof("char16_t") is ffi.typeof("long")
-
-def test_char16_char32_type(no_cpp=False):
- if no_cpp is False and sys.platform == "win32":
- py.test.skip("aaaaaaa why do modern MSVC compilers still define "
- "a very old __cplusplus value")
- ffi = FFI()
- ffi.cdef("""
- char16_t foo_2bytes(char16_t);
- char32_t foo_4bytes(char32_t);
- """)
- lib = verify(ffi, "test_char16_char32_type" + no_cpp * "_nocpp", """
- #if !defined(__cplusplus) || (!defined(_LIBCPP_VERSION) && __cplusplus < 201103L)
- typedef uint_least16_t char16_t;
- typedef uint_least32_t char32_t;
- #endif
-
- char16_t foo_2bytes(char16_t a) { return (char16_t)(a + 42); }
- char32_t foo_4bytes(char32_t a) { return (char32_t)(a + 42); }
- """, no_cpp=no_cpp)
- assert lib.foo_2bytes(u+'\u1234') == u+'\u125e'
- assert lib.foo_4bytes(u+'\u1234') == u+'\u125e'
- assert lib.foo_4bytes(u+'\U00012345') == u+'\U0001236f'
- py.test.raises(TypeError, lib.foo_2bytes, u+'\U00012345')
- py.test.raises(TypeError, lib.foo_2bytes, 1234)
- py.test.raises(TypeError, lib.foo_4bytes, 1234)
-
-def test_char16_char32_plain_c():
- test_char16_char32_type(no_cpp=True)
-
-def test_loader_spec():
- ffi = FFI()
- lib = verify(ffi, "test_loader_spec", "")
- if sys.version_info < (3,):
- assert not hasattr(lib, '__loader__')
- assert not hasattr(lib, '__spec__')
- else:
- assert lib.__loader__ is None
- assert lib.__spec__ is None
-
-def test_realize_struct_error():
- ffi = FFI()
- ffi.cdef("""typedef ... foo_t; struct foo_s { void (*x)(foo_t); };""")
- lib = verify(ffi, "test_realize_struct_error", """
- typedef int foo_t; struct foo_s { void (*x)(foo_t); };
- """)
- py.test.raises(TypeError, ffi.new, "struct foo_s *")
-
-def test_from_buffer_struct():
- ffi = FFI()
- ffi.cdef("""struct foo_s { int a, b; };""")
- lib = verify(ffi, "test_from_buffer_struct_p", """
- struct foo_s { int a, b; };
- """)
- p = ffi.new("struct foo_s *", [-219239, 58974983])
- q = ffi.from_buffer("struct foo_s[]", ffi.buffer(p))
- assert ffi.typeof(q) == ffi.typeof("struct foo_s[]")
- assert len(q) == 1
- assert q[0].a == p.a
- assert q[0].b == p.b
- assert q == p
- q = ffi.from_buffer("struct foo_s *", ffi.buffer(p))
- assert ffi.typeof(q) == ffi.typeof("struct foo_s *")
- assert q.a == p.a
- assert q.b == p.b
- assert q[0].a == p.a
- assert q[0].b == p.b
- assert q == p
-
-def test_unnamed_bitfield_1():
- ffi = FFI()
- ffi.cdef("""struct A { char : 1; };""")
- lib = verify(ffi, "test_unnamed_bitfield_1", """
- struct A { char : 1; };
- """)
- p = ffi.new("struct A *")
- assert ffi.sizeof(p[0]) == 1
- # Note: on gcc, the type name is ignored for anonymous bitfields
- # and that's why the result is 1. On MSVC, the result is
- # sizeof("char") which is also 1.
-
-def test_unnamed_bitfield_2():
- ffi = FFI()
- ffi.cdef("""struct A {
- short c : 1; short : 1; short d : 1; short : 1; };""")
- lib = verify(ffi, "test_unnamed_bitfield_2", """
- struct A {
- short c : 1; short : 1; short d : 1; short : 1;
- };
- """)
- p = ffi.new("struct A *")
- assert ffi.sizeof(p[0]) == ffi.sizeof("short")
-
-def test_unnamed_bitfield_3():
- ffi = FFI()
- ffi.cdef("""struct A { struct { char : 1; char : 1; } b; };""")
- lib = verify(ffi, "test_unnamed_bitfield_3", """
- struct A { struct { char : 1; char : 1; } b; };
- """)
- p = ffi.new("struct A *")
- assert ffi.sizeof(p[0]) == 1
- # Note: on gcc, the type name is ignored for anonymous bitfields
- # and that's why the result is 1. On MSVC, the result is
- # sizeof("char") which is also 1.
-
-def test_unnamed_bitfield_4():
- ffi = FFI()
- ffi.cdef("""struct A { struct {
- unsigned c : 1; unsigned : 1; unsigned d : 1; unsigned : 1; } a;
- };
- struct B { struct A a; };""")
- lib = verify(ffi, "test_unnamed_bitfield_4", """
- struct A { struct {
- unsigned c : 1; unsigned : 1; unsigned d : 1; unsigned : 1; } a;
- };
- struct B { struct A a; };
- """)
- b = ffi.new("struct B *")
- a = ffi.new("struct A *")
- assert ffi.sizeof(a[0]) == ffi.sizeof("unsigned")
- assert ffi.sizeof(b[0]) == ffi.sizeof(a[0])
-
-def test_struct_with_func_with_struct_pointer_arg():
- ffi = FFI()
- ffi.cdef("""struct BinaryTree {
- int (* CompareKey)(struct BinaryTree *tree);
- };""")
- lib = verify(ffi, "test_struct_with_func_with_struct_pointer_arg", """
- struct BinaryTree {
- int (* CompareKey)(struct BinaryTree *tree);
- };
- """)
- ffi.new("struct BinaryTree *")
-
-def test_struct_with_func_with_struct_arg():
- ffi = FFI()
- ffi.cdef("""struct BinaryTree {
- int (* CompareKey)(struct BinaryTree tree);
- };""")
- lib = verify(ffi, "test_struct_with_func_with_struct_arg", """
- struct BinaryTree {
- int (* CompareKey)(struct BinaryTree tree);
- };
- """)
- py.test.raises(RuntimeError, ffi.new, "struct BinaryTree *")
-
-def test_passing_large_list():
- ffi = FFI()
- ffi.cdef("""void passing_large_list(long[]);""")
- lib = verify(ffi, "test_passing_large_list", """
- static void passing_large_list(long a[]) { }
- """)
- arg = list(range(20000000))
- lib.passing_large_list(arg)
- # assert did not segfault
diff --git a/testing/cffi1/test_unicode_literals.py b/testing/cffi1/test_unicode_literals.py
deleted file mode 100644
index e9825db..0000000
--- a/testing/cffi1/test_unicode_literals.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# ----------------------------------------------
-# WARNING, ALL LITERALS IN THIS FILE ARE UNICODE
-# ----------------------------------------------
-#
-from __future__ import unicode_literals
-#
-#
-#
-from _cffi_backend import FFI
-
-
-def test_cast():
- ffi = FFI()
- assert int(ffi.cast("int", 3.14)) == 3 # unicode literal
-
-def test_new():
- ffi = FFI()
- assert ffi.new("int[]", [3, 4, 5])[2] == 5 # unicode literal
-
-def test_typeof():
- ffi = FFI()
- tp = ffi.typeof("int[51]") # unicode literal
- assert tp.length == 51
-
-def test_sizeof():
- ffi = FFI()
- assert ffi.sizeof("int[51]") == 51 * 4 # unicode literal
-
-def test_alignof():
- ffi = FFI()
- assert ffi.alignof("int[51]") == 4 # unicode literal
-
-def test_getctype():
- ffi = FFI()
- assert ffi.getctype("int**") == "int * *" # unicode literal
- assert type(ffi.getctype("int**")) is str
-
-def test_callback():
- ffi = FFI()
- cb = ffi.callback("int(int)", # unicode literal
- lambda x: x + 42)
- assert cb(5) == 47
diff --git a/testing/cffi1/test_verify1.py b/testing/cffi1/test_verify1.py
deleted file mode 100644
index 33244cc..0000000
--- a/testing/cffi1/test_verify1.py
+++ /dev/null
@@ -1,2359 +0,0 @@
-import os, sys, math, py
-import pytest
-from cffi import FFI, FFIError, VerificationError, VerificationMissing, model
-from cffi import CDefError
-from cffi import recompiler
-from testing.support import *
-from testing.support import _verify, extra_compile_args
-import _cffi_backend
-
-lib_m = ['m']
-if sys.platform == 'win32':
- #there is a small chance this fails on Mingw via environ $CC
- import distutils.ccompiler
- if distutils.ccompiler.get_default_compiler() == 'msvc':
- lib_m = ['msvcrt']
-
-class FFI(FFI):
- error = _cffi_backend.FFI.error
- _extra_compile_args = extra_compile_args
- _verify_counter = 0
-
- def verify(self, preamble='', *args, **kwds):
- # HACK to reuse the tests from ../cffi0/test_verify.py
- FFI._verify_counter += 1
- module_name = 'verify%d' % FFI._verify_counter
- try:
- del self._assigned_source
- except AttributeError:
- pass
- self.set_source(module_name, preamble)
- return _verify(self, module_name, preamble, *args,
- extra_compile_args=self._extra_compile_args, **kwds)
-
-class FFI_warnings_not_error(FFI):
- _extra_compile_args = []
-
-
-def test_missing_function(ffi=None):
- # uses the FFI hacked above with '-Werror'
- if ffi is None:
- ffi = FFI()
- ffi.cdef("void some_completely_unknown_function();")
- try:
- lib = ffi.verify()
- except (VerificationError, OSError, ImportError):
- pass # expected case: we get a VerificationError
- else:
- # but depending on compiler and loader details, maybe
- # 'lib' could actually be imported but will fail if we
- # actually try to call the unknown function... Hard
- # to test anything more.
- pass
-
-def test_missing_function_import_error():
- # uses the original FFI that just gives a warning during compilation
- test_missing_function(ffi=FFI_warnings_not_error())
-
-def test_simple_case():
- ffi = FFI()
- ffi.cdef("double sin(double x);")
- lib = ffi.verify('#include <math.h>', libraries=lib_m)
- assert lib.sin(1.23) == math.sin(1.23)
-
-def _Wconversion(cdef, source, **kargs):
- if sys.platform in ('win32', 'darwin'):
- py.test.skip("needs GCC")
- ffi = FFI()
- ffi.cdef(cdef)
- py.test.raises(VerificationError, ffi.verify, source, **kargs)
- extra_compile_args_orig = extra_compile_args[:]
- extra_compile_args.remove('-Wconversion')
- try:
- lib = ffi.verify(source, **kargs)
- finally:
- extra_compile_args[:] = extra_compile_args_orig
- return lib
-
-def test_Wconversion_unsigned():
- _Wconversion("unsigned foo(void);",
- "int foo(void) { return -1;}")
-
-def test_Wconversion_integer():
- _Wconversion("short foo(void);",
- "long long foo(void) { return 1<<sizeof(short);}")
-
-def test_Wconversion_floating():
- lib = _Wconversion("float sin(double);",
- "#include <math.h>", libraries=lib_m)
- res = lib.sin(1.23)
- assert res != math.sin(1.23) # not exact, because of double->float
- assert abs(res - math.sin(1.23)) < 1E-5
-
-def test_Wconversion_float2int():
- _Wconversion("int sinf(float);",
- "#include <math.h>", libraries=lib_m)
-
-def test_Wconversion_double2int():
- _Wconversion("int sin(double);",
- "#include <math.h>", libraries=lib_m)
-
-def test_rounding_1():
- ffi = FFI()
- ffi.cdef("double sinf(float x);")
- lib = ffi.verify('#include <math.h>', libraries=lib_m)
- res = lib.sinf(1.23)
- assert res != math.sin(1.23) # not exact, because of double->float
- assert abs(res - math.sin(1.23)) < 1E-5
-
-def test_rounding_2():
- ffi = FFI()
- ffi.cdef("double sin(float x);")
- lib = ffi.verify('#include <math.h>', libraries=lib_m)
- res = lib.sin(1.23)
- assert res != math.sin(1.23) # not exact, because of double->float
- assert abs(res - math.sin(1.23)) < 1E-5
-
-def test_strlen_exact():
- ffi = FFI()
- ffi.cdef("size_t strlen(const char *s);")
- lib = ffi.verify("#include <string.h>")
- assert lib.strlen(b"hi there!") == 9
-
-def test_strlen_approximate():
- lib = _Wconversion("int strlen(char *s);",
- "#include <string.h>")
- assert lib.strlen(b"hi there!") == 9
-
-def test_return_approximate():
- for typename in ['short', 'int', 'long', 'long long']:
- ffi = FFI()
- ffi.cdef("%s foo(signed char x);" % typename)
- lib = ffi.verify("signed char foo(signed char x) { return x;}")
- assert lib.foo(-128) == -128
- assert lib.foo(+127) == +127
-
-def test_strlen_array_of_char():
- ffi = FFI()
- ffi.cdef("size_t strlen(char[]);")
- lib = ffi.verify("#include <string.h>")
- assert lib.strlen(b"hello") == 5
-
-def test_longdouble():
- ffi = FFI()
- ffi.cdef("long double sinl(long double x);")
- lib = ffi.verify('#include <math.h>', libraries=lib_m)
- for input in [1.23,
- ffi.cast("double", 1.23),
- ffi.cast("long double", 1.23)]:
- x = lib.sinl(input)
- assert repr(x).startswith("<cdata 'long double'")
- assert (float(x) - math.sin(1.23)) < 1E-10
-
-def test_longdouble_precision():
- # Test that we don't loose any precision of 'long double' when
- # passing through Python and CFFI.
- ffi = FFI()
- ffi.cdef("long double step1(long double x);")
- SAME_SIZE = ffi.sizeof("long double") == ffi.sizeof("double")
- lib = ffi.verify("""
- long double step1(long double x)
- {
- return 4*x-x*x;
- }
- """)
- def do(cast_to_double):
- x = 0.9789
- for i in range(10000):
- x = lib.step1(x)
- if cast_to_double:
- x = float(x)
- return float(x)
-
- more_precise = do(False)
- less_precise = do(True)
- if SAME_SIZE:
- assert more_precise == less_precise
- else:
- assert abs(more_precise - less_precise) > 0.1
- # Check the particular results on Intel
- import platform
- if (platform.machine().startswith('i386') or
- platform.machine().startswith('i486') or
- platform.machine().startswith('i586') or
- platform.machine().startswith('i686') or
- platform.machine().startswith('x86')):
- assert abs(more_precise - 0.656769) < 0.001
- assert abs(less_precise - 3.99091) < 0.001
- else:
- py.test.skip("don't know the very exact precision of 'long double'")
-
-
-all_primitive_types = model.PrimitiveType.ALL_PRIMITIVE_TYPES
-if sys.platform == 'win32':
- all_primitive_types = all_primitive_types.copy()
- del all_primitive_types['ssize_t']
-all_integer_types = sorted(tp for tp in all_primitive_types
- if all_primitive_types[tp] == 'i')
-all_float_types = sorted(tp for tp in all_primitive_types
- if all_primitive_types[tp] == 'f')
-
-def all_signed_integer_types(ffi):
- return [x for x in all_integer_types if int(ffi.cast(x, -1)) < 0]
-
-def all_unsigned_integer_types(ffi):
- return [x for x in all_integer_types if int(ffi.cast(x, -1)) > 0]
-
-
-def test_primitive_category():
- for typename in all_primitive_types:
- tp = model.PrimitiveType(typename)
- C = tp.is_char_type()
- F = tp.is_float_type()
- X = tp.is_complex_type()
- I = tp.is_integer_type()
- assert C == (typename in ('char', 'wchar_t', 'char16_t', 'char32_t'))
- assert F == (typename in ('float', 'double', 'long double'))
- assert X == (typename in ('float _Complex', 'double _Complex'))
- assert I + F + C + X == 1 # one and only one of them is true
-
-def test_all_integer_and_float_types():
- typenames = []
- for typename in all_primitive_types:
- if (all_primitive_types[typename] == 'c' or
- all_primitive_types[typename] == 'j' or # complex
- typename == '_Bool' or typename == 'long double'):
- pass
- else:
- typenames.append(typename)
- #
- ffi = FFI()
- ffi.cdef('\n'.join(["%s foo_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
- for tp in typenames]))
- lib = ffi.verify('\n'.join(["%s foo_%s(%s x) { return (%s)(x+1); }" %
- (tp, tp.replace(' ', '_'), tp, tp)
- for tp in typenames]))
- for typename in typenames:
- foo = getattr(lib, 'foo_%s' % typename.replace(' ', '_'))
- assert foo(42) == 43
- if sys.version < '3':
- assert foo(long(44)) == 45
- assert foo(ffi.cast(typename, 46)) == 47
- py.test.raises(TypeError, foo, ffi.NULL)
- #
- # check for overflow cases
- if all_primitive_types[typename] == 'f':
- continue
- for value in [-2**80, -2**40, -2**20, -2**10, -2**5, -1,
- 2**5, 2**10, 2**20, 2**40, 2**80]:
- overflows = int(ffi.cast(typename, value)) != value
- if overflows:
- py.test.raises(OverflowError, foo, value)
- else:
- assert foo(value) == value + 1
-
-def test_var_signed_integer_types():
- ffi = FFI()
- lst = all_signed_integer_types(ffi)
- csource = "\n".join(["static %s somevar_%s;" % (tp, tp.replace(' ', '_'))
- for tp in lst])
- ffi.cdef(csource)
- lib = ffi.verify(csource)
- for tp in lst:
- varname = 'somevar_%s' % tp.replace(' ', '_')
- sz = ffi.sizeof(tp)
- max = (1 << (8*sz-1)) - 1
- min = -(1 << (8*sz-1))
- setattr(lib, varname, max)
- assert getattr(lib, varname) == max
- setattr(lib, varname, min)
- assert getattr(lib, varname) == min
- py.test.raises(OverflowError, setattr, lib, varname, max+1)
- py.test.raises(OverflowError, setattr, lib, varname, min-1)
-
-def test_var_unsigned_integer_types():
- ffi = FFI()
- lst = all_unsigned_integer_types(ffi)
- csource = "\n".join(["static %s somevar_%s;" % (tp, tp.replace(' ', '_'))
- for tp in lst])
- ffi.cdef(csource)
- lib = ffi.verify(csource)
- for tp in lst:
- varname = 'somevar_%s' % tp.replace(' ', '_')
- sz = ffi.sizeof(tp)
- if tp != '_Bool':
- max = (1 << (8*sz)) - 1
- else:
- max = 1
- setattr(lib, varname, max)
- assert getattr(lib, varname) == max
- setattr(lib, varname, 0)
- assert getattr(lib, varname) == 0
- py.test.raises(OverflowError, setattr, lib, varname, max+1)
- py.test.raises(OverflowError, setattr, lib, varname, -1)
-
-def test_fn_signed_integer_types():
- ffi = FFI()
- lst = all_signed_integer_types(ffi)
- cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
- for tp in lst])
- ffi.cdef(cdefsrc)
- verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
- (tp, tp.replace(' ', '_'), tp) for tp in lst])
- lib = ffi.verify(verifysrc)
- for tp in lst:
- fnname = 'somefn_%s' % tp.replace(' ', '_')
- sz = ffi.sizeof(tp)
- max = (1 << (8*sz-1)) - 1
- min = -(1 << (8*sz-1))
- fn = getattr(lib, fnname)
- assert fn(max) == max
- assert fn(min) == min
- py.test.raises(OverflowError, fn, max + 1)
- py.test.raises(OverflowError, fn, min - 1)
-
-def test_fn_unsigned_integer_types():
- ffi = FFI()
- lst = all_unsigned_integer_types(ffi)
- cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
- for tp in lst])
- ffi.cdef(cdefsrc)
- verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
- (tp, tp.replace(' ', '_'), tp) for tp in lst])
- lib = ffi.verify(verifysrc)
- for tp in lst:
- fnname = 'somefn_%s' % tp.replace(' ', '_')
- sz = ffi.sizeof(tp)
- if tp != '_Bool':
- max = (1 << (8*sz)) - 1
- else:
- max = 1
- fn = getattr(lib, fnname)
- assert fn(max) == max
- assert fn(0) == 0
- py.test.raises(OverflowError, fn, max + 1)
- py.test.raises(OverflowError, fn, -1)
-
-def test_char_type():
- ffi = FFI()
- ffi.cdef("char foo(char);")
- lib = ffi.verify("char foo(char x) { return ++x; }")
- assert lib.foo(b"A") == b"B"
- py.test.raises(TypeError, lib.foo, b"bar")
- py.test.raises(TypeError, lib.foo, "bar")
-
-def test_wchar_type():
- ffi = FFI()
- if ffi.sizeof('wchar_t') == 2:
- uniexample1 = u+'\u1234'
- uniexample2 = u+'\u1235'
- else:
- uniexample1 = u+'\U00012345'
- uniexample2 = u+'\U00012346'
- #
- ffi.cdef("wchar_t foo(wchar_t);")
- lib = ffi.verify("wchar_t foo(wchar_t x) { return x+1; }")
- assert lib.foo(uniexample1) == uniexample2
-
-def test_no_argument():
- ffi = FFI()
- ffi.cdef("int foo(void);")
- lib = ffi.verify("int foo(void) { return 42; }")
- assert lib.foo() == 42
-
-def test_two_arguments():
- ffi = FFI()
- ffi.cdef("int foo(int, int);")
- lib = ffi.verify("int foo(int a, int b) { return a - b; }")
- assert lib.foo(40, -2) == 42
-
-def test_macro():
- ffi = FFI()
- ffi.cdef("int foo(int, int);")
- lib = ffi.verify("#define foo(a, b) ((a) * (b))")
- assert lib.foo(-6, -7) == 42
-
-def test_ptr():
- ffi = FFI()
- ffi.cdef("int *foo(int *);")
- lib = ffi.verify("int *foo(int *a) { return a; }")
- assert lib.foo(ffi.NULL) == ffi.NULL
- p = ffi.new("int *", 42)
- q = ffi.new("int *", 42)
- assert lib.foo(p) == p
- assert lib.foo(q) != p
-
-def test_bogus_ptr():
- ffi = FFI()
- ffi.cdef("int *foo(int *);")
- lib = ffi.verify("int *foo(int *a) { return a; }")
- py.test.raises(TypeError, lib.foo, ffi.new("short *", 42))
-
-
-def test_verify_typedefs():
- py.test.skip("ignored so far")
- types = ['signed char', 'unsigned char', 'int', 'long']
- for cdefed in types:
- for real in types:
- ffi = FFI()
- ffi.cdef("typedef %s foo_t;" % cdefed)
- if cdefed == real:
- ffi.verify("typedef %s foo_t;" % real)
- else:
- py.test.raises(VerificationError, ffi.verify,
- "typedef %s foo_t;" % real)
-
-def test_nondecl_struct():
- ffi = FFI()
- ffi.cdef("typedef struct foo_s foo_t; int bar(foo_t *);")
- lib = ffi.verify("typedef struct foo_s foo_t;\n"
- "int bar(foo_t *f) { (void)f; return 42; }\n")
- assert lib.bar(ffi.NULL) == 42
-
-def test_ffi_full_struct():
- def check(verified_code):
- ffi = FFI()
- ffi.cdef("struct foo_s { char x; int y; long *z; };")
- ffi.verify(verified_code)
- ffi.new("struct foo_s *", {})
-
- check("struct foo_s { char x; int y; long *z; };")
- #
- if sys.platform != 'win32': # XXX fixme: only gives warnings
- py.test.raises(VerificationError, check,
- "struct foo_s { char x; int y; int *z; };")
- #
- py.test.raises(VerificationError, check,
- "struct foo_s { int y; long *z; };") # cdef'ed field x is missing
- #
- e = py.test.raises(FFI.error, check,
- "struct foo_s { int y; char x; long *z; };")
- assert str(e.value).startswith(
- "struct foo_s: wrong offset for field 'x'"
- " (cdef says 0, but C compiler says 4)")
- #
- e = py.test.raises(FFI.error, check,
- "struct foo_s { char x; int y; long *z; char extra; };")
- assert str(e.value).startswith(
- "struct foo_s: wrong total size"
- " (cdef says %d, but C compiler says %d)" % (
- 8 + FFI().sizeof('long *'),
- 8 + FFI().sizeof('long *') * 2))
- #
- # a corner case that we cannot really detect, but where it has no
- # bad consequences: the size is the same, but there is an extra field
- # that replaces what is just padding in our declaration above
- check("struct foo_s { char x, extra; int y; long *z; };")
- #
- e = py.test.raises(FFI.error, check,
- "struct foo_s { char x; short pad; short y; long *z; };")
- assert str(e.value).startswith(
- "struct foo_s: wrong size for field 'y'"
- " (cdef says 4, but C compiler says 2)")
-
-def test_ffi_nonfull_struct():
- ffi = FFI()
- ffi.cdef("""
- struct foo_s {
- int x;
- ...;
- };
- """)
- py.test.raises(VerificationMissing, ffi.sizeof, 'struct foo_s')
- py.test.raises(VerificationMissing, ffi.offsetof, 'struct foo_s', 'x')
- py.test.raises(VerificationMissing, ffi.new, 'struct foo_s *')
- ffi.verify("""
- struct foo_s {
- int a, b, x, c, d, e;
- };
- """)
- assert ffi.sizeof('struct foo_s') == 6 * ffi.sizeof('int')
- assert ffi.offsetof('struct foo_s', 'x') == 2 * ffi.sizeof('int')
-
-def test_ffi_nonfull_alignment():
- ffi = FFI()
- ffi.cdef("struct foo_s { char x; ...; };")
- ffi.verify("struct foo_s { int a, b; char x; };")
- assert ffi.sizeof('struct foo_s') == 3 * ffi.sizeof('int')
- assert ffi.alignof('struct foo_s') == ffi.sizeof('int')
-
-def _check_field_match(typename, real, expect_mismatch):
- ffi = FFI()
- testing_by_size = (expect_mismatch == 'by_size')
- if testing_by_size:
- expect_mismatch = ffi.sizeof(typename) != ffi.sizeof(real)
- ffi.cdef("struct foo_s { %s x; ...; };" % typename)
- try:
- ffi.verify("struct foo_s { %s x; };" % real)
- ffi.new("struct foo_s *", []) # because some mismatches show up lazily
- except (VerificationError, ffi.error):
- if not expect_mismatch:
- if testing_by_size and typename != real:
- print("ignoring mismatch between %s* and %s* even though "
- "they have the same size" % (typename, real))
- return
- raise AssertionError("unexpected mismatch: %s should be accepted "
- "as equal to %s" % (typename, real))
- else:
- if expect_mismatch:
- raise AssertionError("mismatch not detected: "
- "%s != %s" % (typename, real))
-
-def test_struct_bad_sized_integer():
- for typename in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
- for real in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
- _check_field_match(typename, real, "by_size")
-
-def test_struct_bad_sized_float():
- for typename in all_float_types:
- for real in all_float_types:
- _check_field_match(typename, real, "by_size")
-
-def test_struct_signedness_ignored():
- _check_field_match("int", "unsigned int", expect_mismatch=False)
- _check_field_match("unsigned short", "signed short", expect_mismatch=False)
-
-def test_struct_float_vs_int():
- if sys.platform == 'win32':
- py.test.skip("XXX fixme: only gives warnings")
- ffi = FFI()
- for typename in all_signed_integer_types(ffi):
- for real in all_float_types:
- _check_field_match(typename, real, expect_mismatch=True)
- for typename in all_float_types:
- for real in all_signed_integer_types(ffi):
- _check_field_match(typename, real, expect_mismatch=True)
-
-def test_struct_array_field():
- ffi = FFI()
- ffi.cdef("struct foo_s { int a[17]; ...; };")
- ffi.verify("struct foo_s { int x; int a[17]; int y; };")
- assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
- s = ffi.new("struct foo_s *")
- assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
-
-def test_struct_array_no_length():
- ffi = FFI()
- ffi.cdef("struct foo_s { int a[]; int y; ...; };\n"
- "int bar(struct foo_s *);\n")
- lib = ffi.verify("struct foo_s { int x; int a[17]; int y; };\n"
- "int bar(struct foo_s *f) { return f->a[14]; }\n")
- assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
- s = ffi.new("struct foo_s *")
- assert ffi.typeof(s.a) is ffi.typeof('int[]') # implicit max length
- assert len(s.a) == 18 # max length, computed from the size and start offset
- s.a[14] = 4242
- assert lib.bar(s) == 4242
- # with no declared length, out-of-bound accesses are not detected
- s.a[17] = -521
- assert s.y == s.a[17] == -521
- #
- s = ffi.new("struct foo_s *", {'a': list(range(17))})
- assert s.a[16] == 16
- # overflows at construction time not detected either
- s = ffi.new("struct foo_s *", {'a': list(range(18))})
- assert s.y == s.a[17] == 17
-
-def test_struct_array_guess_length():
- ffi = FFI()
- ffi.cdef("struct foo_s { int a[...]; };")
- ffi.verify("struct foo_s { int x; int a[17]; int y; };")
- assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
- s = ffi.new("struct foo_s *")
- assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
- with pytest.raises(IndexError):
- s.a[17]
-
-def test_struct_array_c99_1():
- if sys.platform == 'win32':
- py.test.skip("requires C99")
- ffi = FFI()
- ffi.cdef("struct foo_s { int x; int a[]; };")
- ffi.verify("struct foo_s { int x; int a[]; };")
- assert ffi.sizeof('struct foo_s') == 1 * ffi.sizeof('int')
- s = ffi.new("struct foo_s *", [424242, 4])
- assert ffi.sizeof(ffi.typeof(s[0])) == 1 * ffi.sizeof('int')
- assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int')
- # ^^^ explanation: if you write in C: "char x[5];", then
- # "sizeof(x)" will evaluate to 5. The behavior above is
- # a generalization of that to "struct foo_s[len(a)=5] x;"
- # if you could do that in C.
- assert s.a[3] == 0
- s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]])
- assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int')
- assert s.a[3] == -10
- s = ffi.new("struct foo_s *")
- assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int')
- s = ffi.new("struct foo_s *", [424242])
- assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int')
-
-def test_struct_array_c99_2():
- if sys.platform == 'win32':
- py.test.skip("requires C99")
- ffi = FFI()
- ffi.cdef("struct foo_s { int x; int a[]; ...; };")
- ffi.verify("struct foo_s { int x, y; int a[]; };")
- assert ffi.sizeof('struct foo_s') == 2 * ffi.sizeof('int')
- s = ffi.new("struct foo_s *", [424242, 4])
- assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int')
- assert s.a[3] == 0
- s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]])
- assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int')
- assert s.a[3] == -10
- s = ffi.new("struct foo_s *")
- assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int')
- s = ffi.new("struct foo_s *", [424242])
- assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int')
-
-def test_struct_ptr_to_array_field():
- ffi = FFI()
- ffi.cdef("struct foo_s { int (*a)[17]; ...; }; struct bar_s { ...; };")
- ffi.verify("struct foo_s { int x; int (*a)[17]; int y; };\n"
- "struct bar_s { int x; int *a; int y; };")
- assert ffi.sizeof('struct foo_s') == ffi.sizeof("struct bar_s")
- s = ffi.new("struct foo_s *")
- assert ffi.sizeof(s.a) == ffi.sizeof('int(*)[17]') == ffi.sizeof("int *")
-
-def test_struct_with_bitfield_exact():
- ffi = FFI()
- ffi.cdef("struct foo_s { int a:2, b:3; };")
- ffi.verify("struct foo_s { int a:2, b:3; };")
- s = ffi.new("struct foo_s *")
- s.b = 3
- with pytest.raises(OverflowError):
- s.b = 4
- assert s.b == 3
-
-def test_struct_with_bitfield_enum():
- ffi = FFI()
- code = """
- typedef enum { AA, BB, CC } foo_e;
- typedef struct { foo_e f:2; } foo_s;
- """
- ffi.cdef(code)
- ffi.verify(code)
- s = ffi.new("foo_s *")
- s.f = 1
- assert s.f == 1
- if int(ffi.cast("foo_e", -1)) < 0:
- two = -2
- else:
- two = 2
- s.f = two
- assert s.f == two
-
-def test_unsupported_struct_with_bitfield_ellipsis():
- ffi = FFI()
- py.test.raises(NotImplementedError, ffi.cdef,
- "struct foo_s { int a:2, b:3; ...; };")
-
-def test_global_constants():
- ffi = FFI()
- # use 'static const int', as generally documented, although in this
- # case the 'static' is completely ignored.
- ffi.cdef("static const int AA, BB, CC, DD;")
- lib = ffi.verify("#define AA 42\n"
- "#define BB (-43) // blah\n"
- "#define CC (22*2) /* foobar */\n"
- "#define DD ((unsigned int)142) /* foo\nbar */\n")
- assert lib.AA == 42
- assert lib.BB == -43
- assert lib.CC == 44
- assert lib.DD == 142
-
-def test_global_const_int_size():
- # integer constants: ignore the declared type, always just use the value
- for value in [-2**63, -2**31, -2**15,
- 2**15-1, 2**15, 2**31-1, 2**31, 2**32-1, 2**32,
- 2**63-1, 2**63, 2**64-1]:
- ffi = FFI()
- if value == int(ffi.cast("long long", value)):
- if value < 0:
- vstr = '(-%dLL-1)' % (~value,)
- else:
- vstr = '%dLL' % value
- elif value == int(ffi.cast("unsigned long long", value)):
- vstr = '%dULL' % value
- else:
- raise AssertionError(value)
- ffi.cdef("static const unsigned short AA;")
- lib = ffi.verify("#define AA %s\n" % vstr)
- assert lib.AA == value
- assert type(lib.AA) is type(int(lib.AA))
-
-def test_global_constants_non_int():
- ffi = FFI()
- ffi.cdef("static char *const PP;")
- lib = ffi.verify('static char *const PP = "testing!";\n')
- assert ffi.typeof(lib.PP) == ffi.typeof("char *")
- assert ffi.string(lib.PP) == b"testing!"
-
-def test_nonfull_enum():
- ffi = FFI()
- ffi.cdef("enum ee { EE1, EE2, EE3, ... \n \t };")
- py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE2')
- ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
- assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
- assert ffi.string(ffi.cast('enum ee', -10)) == "EE3"
- #
- assert ffi.typeof("enum ee").relements == {'EE1': 10, 'EE2': 11, 'EE3': -10}
- assert ffi.typeof("enum ee").elements == {10: 'EE1', 11: 'EE2', -10: 'EE3'}
-
-def test_full_enum():
- ffi = FFI()
- ffi.cdef("enum ee { EE1, EE2, EE3 };")
- lib = ffi.verify("enum ee { EE1, EE2, EE3 };")
- assert [lib.EE1, lib.EE2, lib.EE3] == [0, 1, 2]
-
-def test_enum_usage():
- ffi = FFI()
- ffi.cdef("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;")
- lib = ffi.verify("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;")
- assert lib.EE2 == 1
- s = ffi.new("sp", [lib.EE2])
- assert s.x == 1
- s.x = 17
- assert s.x == 17
-
-def test_anonymous_enum():
- ffi = FFI()
- ffi.cdef("enum { EE1 }; enum { EE2, EE3 };")
- lib = ffi.verify("enum { EE1 }; enum { EE2, EE3 };")
- assert lib.EE1 == 0
- assert lib.EE2 == 0
- assert lib.EE3 == 1
-
-def test_nonfull_anonymous_enum():
- ffi = FFI()
- ffi.cdef("enum { EE1, ... }; enum { EE3, ... };")
- lib = ffi.verify("enum { EE2, EE1 }; enum { EE3 };")
- assert lib.EE1 == 1
- assert lib.EE3 == 0
-
-def test_nonfull_enum_syntax2():
- ffi = FFI()
- ffi.cdef("enum ee { EE1, EE2=\t..., EE3 };")
- py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1')
- ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
- assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2'
- assert ffi.string(ffi.cast('enum ee', -10)) == 'EE3'
- #
- ffi = FFI()
- ffi.cdef("enum ee { EE1, EE2=\t... };")
- py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1')
- ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
- assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2'
- #
- ffi = FFI()
- ffi.cdef("enum ee2 { EE4=..., EE5=..., ... };")
- ffi.verify("enum ee2 { EE4=-1234-5, EE5 }; ")
- assert ffi.string(ffi.cast('enum ee2', -1239)) == 'EE4'
- assert ffi.string(ffi.cast('enum ee2', -1238)) == 'EE5'
-
-def test_get_set_errno():
- ffi = FFI()
- ffi.cdef("int foo(int);")
- lib = ffi.verify("""
- static int foo(int x)
- {
- errno += 1;
- return x * 7;
- }
- """)
- ffi.errno = 15
- assert lib.foo(6) == 42
- assert ffi.errno == 16
-
-def test_define_int():
- ffi = FFI()
- ffi.cdef("#define FOO ...\n"
- "\t#\tdefine\tBAR\t...\t\n"
- "#define BAZ ...\n")
- lib = ffi.verify("#define FOO 42\n"
- "#define BAR (-44)\n"
- "#define BAZ 0xffffffffffffffffULL\n")
- assert lib.FOO == 42
- assert lib.BAR == -44
- assert lib.BAZ == 0xffffffffffffffff
-
-def test_access_variable():
- ffi = FFI()
- ffi.cdef("static int foo(void);\n"
- "static int somenumber;")
- lib = ffi.verify("""
- static int somenumber = 2;
- static int foo(void) {
- return somenumber * 7;
- }
- """)
- assert lib.somenumber == 2
- assert lib.foo() == 14
- lib.somenumber = -6
- assert lib.foo() == -42
- assert lib.somenumber == -6
- lib.somenumber = 2 # reset for the next run, if any
-
-def test_access_address_of_variable():
- # access the address of 'somenumber': need a trick
- ffi = FFI()
- ffi.cdef("static int somenumber; static int *const somenumberptr;")
- lib = ffi.verify("""
- static int somenumber = 2;
- #define somenumberptr (&somenumber)
- """)
- assert lib.somenumber == 2
- lib.somenumberptr[0] = 42
- assert lib.somenumber == 42
- lib.somenumber = 2 # reset for the next run, if any
-
-def test_access_array_variable(length=5):
- ffi = FFI()
- ffi.cdef("static int foo(int);\n"
- "static int somenumber[%s];" % (length,))
- lib = ffi.verify("""
- static int somenumber[] = {2, 2, 3, 4, 5};
- static int foo(int i) {
- return somenumber[i] * 7;
- }
- """)
- if length == '':
- # a global variable of an unknown array length is implicitly
- # transformed into a global pointer variable, because we can only
- # work with array instances whose length we know. using a pointer
- # instead of an array gives the correct effects.
- assert repr(lib.somenumber).startswith("<cdata 'int *' 0x")
- py.test.raises(TypeError, len, lib.somenumber)
- else:
- assert repr(lib.somenumber).startswith("<cdata 'int[%s]' 0x" % length)
- assert len(lib.somenumber) == 5
- assert lib.somenumber[3] == 4
- assert lib.foo(3) == 28
- lib.somenumber[3] = -6
- assert lib.foo(3) == -42
- assert lib.somenumber[3] == -6
- assert lib.somenumber[4] == 5
- lib.somenumber[3] = 4 # reset for the next run, if any
-
-def test_access_array_variable_length_hidden():
- test_access_array_variable(length='')
-
-def test_access_struct_variable():
- ffi = FFI()
- ffi.cdef("struct foo { int x; ...; };\n"
- "static int foo(int);\n"
- "static struct foo stuff;")
- lib = ffi.verify("""
- struct foo { int x, y, z; };
- static struct foo stuff = {2, 5, 8};
- static int foo(int i) {
- switch (i) {
- case 0: return stuff.x * 7;
- case 1: return stuff.y * 7;
- case 2: return stuff.z * 7;
- }
- return -1;
- }
- """)
- assert lib.stuff.x == 2
- assert lib.foo(0) == 14
- assert lib.foo(1) == 35
- assert lib.foo(2) == 56
- lib.stuff.x = -6
- assert lib.foo(0) == -42
- assert lib.foo(1) == 35
- lib.stuff.x = 2 # reset for the next run, if any
-
-def test_access_callback():
- ffi = FFI()
- ffi.cdef("static int (*cb)(int);\n"
- "static int foo(int);\n"
- "static void reset_cb(void);")
- lib = ffi.verify("""
- static int g(int x) { return x * 7; }
- static int (*cb)(int);
- static int foo(int i) { return cb(i) - 1; }
- static void reset_cb(void) { cb = g; }
- """)
- lib.reset_cb()
- assert lib.foo(6) == 41
- my_callback = ffi.callback("int(*)(int)", lambda n: n * 222)
- lib.cb = my_callback
- assert lib.foo(4) == 887
-
-def test_access_callback_function_typedef():
- ffi = FFI()
- ffi.cdef("typedef int mycallback_t(int);\n"
- "static mycallback_t *cb;\n"
- "static int foo(int);\n"
- "static void reset_cb(void);")
- lib = ffi.verify("""
- static int g(int x) { return x * 7; }
- static int (*cb)(int);
- static int foo(int i) { return cb(i) - 1; }
- static void reset_cb(void) { cb = g; }
- """)
- lib.reset_cb()
- assert lib.foo(6) == 41
- my_callback = ffi.callback("int(*)(int)", lambda n: n * 222)
- lib.cb = my_callback
- assert lib.foo(4) == 887
-
-def test_call_with_struct_ptr():
- ffi = FFI()
- ffi.cdef("typedef struct { int x; ...; } foo_t; int foo(foo_t *);")
- lib = ffi.verify("""
- typedef struct { int y, x; } foo_t;
- static int foo(foo_t *f) { return f->x * 7; }
- """)
- f = ffi.new("foo_t *")
- f.x = 6
- assert lib.foo(f) == 42
-
-def test_unknown_type():
- ffi = FFI()
- ffi.cdef("""
- typedef ... token_t;
- int foo(token_t *);
- #define TOKEN_SIZE ...
- """)
- lib = ffi.verify("""
- typedef float token_t;
- static int foo(token_t *tk) {
- if (!tk)
- return -42;
- *tk += 1.601f;
- return (int)*tk;
- }
- #define TOKEN_SIZE sizeof(token_t)
- """)
- # we cannot let ffi.new("token_t *") work, because we don't know ahead of
- # time if it's ok to ask 'sizeof(token_t)' in the C code or not.
- # See test_unknown_type_2. Workaround.
- tkmem = ffi.new("char[]", lib.TOKEN_SIZE) # zero-initialized
- tk = ffi.cast("token_t *", tkmem)
- results = [lib.foo(tk) for i in range(6)]
- assert results == [1, 3, 4, 6, 8, 9]
- assert lib.foo(ffi.NULL) == -42
-
-def test_unknown_type_2():
- ffi = FFI()
- ffi.cdef("typedef ... token_t;")
- lib = ffi.verify("typedef struct token_s token_t;")
- # assert did not crash, even though 'sizeof(token_t)' is not valid in C.
-
-def test_unknown_type_3():
- ffi = FFI()
- ffi.cdef("""
- typedef ... *token_p;
- token_p foo(token_p);
- """)
- lib = ffi.verify("""
- typedef struct _token_s *token_p;
- token_p foo(token_p arg) {
- if (arg)
- return (token_p)0x12347;
- else
- return (token_p)0x12345;
- }
- """)
- p = lib.foo(ffi.NULL)
- assert int(ffi.cast("intptr_t", p)) == 0x12345
- q = lib.foo(p)
- assert int(ffi.cast("intptr_t", q)) == 0x12347
-
-def test_varargs():
- ffi = FFI()
- ffi.cdef("int foo(int x, ...);")
- lib = ffi.verify("""
- int foo(int x, ...) {
- va_list vargs;
- va_start(vargs, x);
- x -= va_arg(vargs, int);
- x -= va_arg(vargs, int);
- va_end(vargs);
- return x;
- }
- """)
- assert lib.foo(50, ffi.cast("int", 5), ffi.cast("int", 3)) == 42
-
-def test_varargs_exact():
- if sys.platform == 'win32':
- py.test.skip("XXX fixme: only gives warnings")
- ffi = FFI()
- ffi.cdef("int foo(int x, ...);")
- py.test.raises(VerificationError, ffi.verify, """
- int foo(long long x, ...) {
- return x;
- }
- """)
-
-def test_varargs_struct():
- ffi = FFI()
- ffi.cdef("struct foo_s { char a; int b; }; int foo(int x, ...);")
- lib = ffi.verify("""
- struct foo_s {
- char a; int b;
- };
- int foo(int x, ...) {
- va_list vargs;
- struct foo_s s;
- va_start(vargs, x);
- s = va_arg(vargs, struct foo_s);
- va_end(vargs);
- return s.a - s.b;
- }
- """)
- s = ffi.new("struct foo_s *", [b'B', 1])
- assert lib.foo(50, s[0]) == ord('A')
-
-def test_autofilled_struct_as_argument():
- ffi = FFI()
- ffi.cdef("struct foo_s { long a; double b; ...; };\n"
- "int foo(struct foo_s);")
- lib = ffi.verify("""
- struct foo_s {
- double b;
- long a;
- };
- int foo(struct foo_s s) {
- return (int)s.a - (int)s.b;
- }
- """)
- s = ffi.new("struct foo_s *", [100, 1])
- assert lib.foo(s[0]) == 99
- assert lib.foo([100, 1]) == 99
-
-def test_autofilled_struct_as_argument_dynamic():
- ffi = FFI()
- ffi.cdef("struct foo_s { long a; ...; };\n"
- "static int (*foo)(struct foo_s);")
- lib = ffi.verify("""
- struct foo_s {
- double b;
- long a;
- };
- int foo1(struct foo_s s) {
- return (int)s.a - (int)s.b;
- }
- static int (*foo)(struct foo_s s) = &foo1;
- """)
- e = py.test.raises(NotImplementedError, lib.foo, "?")
- msg = ("ctype 'struct foo_s' 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_func_returns_struct():
- ffi = FFI()
- ffi.cdef("""
- struct foo_s { int aa, bb; };
- struct foo_s foo(int a, int b);
- """)
- lib = ffi.verify("""
- struct foo_s { int aa, bb; };
- struct foo_s foo(int a, int b) {
- struct foo_s r;
- r.aa = a*a;
- r.bb = b*b;
- return r;
- }
- """)
- s = lib.foo(6, 7)
- assert repr(s) == "<cdata 'struct foo_s' owning 8 bytes>"
- assert s.aa == 36
- assert s.bb == 49
-
-def test_func_as_funcptr():
- ffi = FFI()
- ffi.cdef("int *(*const fooptr)(void);")
- lib = ffi.verify("""
- int *foo(void) {
- return (int*)"foobar";
- }
- int *(*fooptr)(void) = foo;
- """)
- foochar = ffi.cast("char *(*)(void)", lib.fooptr)
- s = foochar()
- assert ffi.string(s) == b"foobar"
-
-def test_funcptr_as_argument():
- ffi = FFI()
- ffi.cdef("""
- void qsort(void *base, size_t nel, size_t width,
- int (*compar)(const void *, const void *));
- """)
- ffi.verify("#include <stdlib.h>")
-
-def test_func_as_argument():
- ffi = FFI()
- ffi.cdef("""
- void qsort(void *base, size_t nel, size_t width,
- int compar(const void *, const void *));
- """)
- ffi.verify("#include <stdlib.h>")
-
-def test_array_as_argument():
- ffi = FFI()
- ffi.cdef("""
- size_t strlen(char string[]);
- """)
- ffi.verify("#include <string.h>")
-
-def test_enum_as_argument():
- ffi = FFI()
- ffi.cdef("""
- enum foo_e { AA, BB, ... };
- int foo_func(enum foo_e);
- """)
- lib = ffi.verify("""
- enum foo_e { AA, CC, BB };
- int foo_func(enum foo_e e) { return (int)e; }
- """)
- assert lib.foo_func(lib.BB) == 2
- py.test.raises(TypeError, lib.foo_func, "BB")
-
-def test_enum_as_function_result():
- ffi = FFI()
- ffi.cdef("""
- enum foo_e { AA, BB, ... };
- enum foo_e foo_func(int x);
- """)
- lib = ffi.verify("""
- enum foo_e { AA, CC, BB };
- enum foo_e foo_func(int x) { return (enum foo_e)x; }
- """)
- assert lib.foo_func(lib.BB) == lib.BB == 2
-
-def test_enum_values():
- ffi = FFI()
- ffi.cdef("enum enum1_e { AA, BB };")
- lib = ffi.verify("enum enum1_e { AA, BB };")
- assert lib.AA == 0
- assert lib.BB == 1
- assert ffi.string(ffi.cast("enum enum1_e", 1)) == 'BB'
-
-def test_typedef_complete_enum():
- ffi = FFI()
- ffi.cdef("typedef enum { AA, BB } enum1_t;")
- lib = ffi.verify("typedef enum { AA, BB } enum1_t;")
- assert ffi.string(ffi.cast("enum1_t", 1)) == 'BB'
- assert lib.AA == 0
- assert lib.BB == 1
-
-def test_typedef_broken_complete_enum():
- # xxx this is broken in old cffis, but works with recompiler.py
- ffi = FFI()
- ffi.cdef("typedef enum { AA, BB } enum1_t;")
- lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;")
- assert lib.AA == 0
- assert lib.BB == 2
-
-def test_typedef_incomplete_enum():
- ffi = FFI()
- ffi.cdef("typedef enum { AA, BB, ... } enum1_t;")
- lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;")
- assert ffi.string(ffi.cast("enum1_t", 1)) == '1'
- assert ffi.string(ffi.cast("enum1_t", 2)) == 'BB'
- assert lib.AA == 0
- assert lib.BB == 2
-
-def test_typedef_enum_as_argument():
- ffi = FFI()
- ffi.cdef("""
- typedef enum { AA, BB, ... } foo_t;
- int foo_func(foo_t);
- """)
- lib = ffi.verify("""
- typedef enum { AA, CC, BB } foo_t;
- int foo_func(foo_t e) { return (int)e; }
- """)
- assert lib.foo_func(lib.BB) == lib.BB == 2
- py.test.raises(TypeError, lib.foo_func, "BB")
-
-def test_typedef_enum_as_function_result():
- ffi = FFI()
- ffi.cdef("""
- typedef enum { AA, BB, ... } foo_t;
- foo_t foo_func(int x);
- """)
- lib = ffi.verify("""
- typedef enum { AA, CC, BB } foo_t;
- foo_t foo_func(int x) { return (foo_t)x; }
- """)
- assert lib.foo_func(lib.BB) == lib.BB == 2
-
-def test_function_typedef():
- ffi = FFI()
- ffi.cdef("""
- typedef double func_t(double);
- func_t sin;
- """)
- lib = ffi.verify('#include <math.h>', libraries=lib_m)
- assert lib.sin(1.23) == math.sin(1.23)
-
-def test_opaque_integer_as_function_result():
- #import platform
- #if platform.machine().startswith('sparc'):
- # py.test.skip('Breaks horribly on sparc (SIGILL + corrupted stack)')
- #elif platform.machine() == 'mips64' and sys.maxsize > 2**32:
- # py.test.skip('Segfaults on mips64el')
- # XXX bad abuse of "struct { ...; }". It only works a bit by chance
- # anyway. XXX think about something better :-(
- ffi = FFI()
- ffi.cdef("""
- typedef struct { ...; } myhandle_t;
- myhandle_t foo(void);
- """)
- lib = ffi.verify("""
- typedef short myhandle_t;
- myhandle_t foo(void) { return 42; }
- """)
- h = lib.foo()
- assert ffi.sizeof(h) == ffi.sizeof("short")
-
-def test_return_partial_struct():
- ffi = FFI()
- ffi.cdef("""
- typedef struct { int x; ...; } foo_t;
- foo_t foo(void);
- """)
- lib = ffi.verify("""
- typedef struct { int y, x; } foo_t;
- foo_t foo(void) { foo_t r = { 45, 81 }; return r; }
- """)
- h = lib.foo()
- assert ffi.sizeof(h) == 2 * ffi.sizeof("int")
- assert h.x == 81
-
-def test_take_and_return_partial_structs():
- ffi = FFI()
- ffi.cdef("""
- typedef struct { int x; ...; } foo_t;
- foo_t foo(foo_t, foo_t);
- """)
- lib = ffi.verify("""
- typedef struct { int y, x; } foo_t;
- foo_t foo(foo_t a, foo_t b) {
- foo_t r = { 100, a.x * 5 + b.x * 7 };
- return r;
- }
- """)
- args = ffi.new("foo_t[3]")
- args[0].x = 1000
- args[2].x = -498
- h = lib.foo(args[0], args[2])
- assert ffi.sizeof(h) == 2 * ffi.sizeof("int")
- assert h.x == 1000 * 5 - 498 * 7
-
-def test_cannot_name_struct_type():
- ffi = FFI()
- ffi.cdef("typedef struct { int x; } **sp; void foo(sp);")
- e = py.test.raises(VerificationError, ffi.verify,
- "typedef struct { int x; } **sp; void foo(sp x) { }")
- assert 'in argument of foo: unknown type name' in str(e.value)
-
-def test_dont_check_unnamable_fields():
- ffi = FFI()
- ffi.cdef("struct foo_s { struct { int x; } someone; };")
- ffi.verify("struct foo_s { struct { int x; } someone; };")
- # assert did not crash
-
-def test_nested_anonymous_struct_exact():
- if sys.platform == 'win32':
- py.test.skip("nested anonymous struct/union")
- ffi = FFI()
- ffi.cdef("""
- struct foo_s { struct { int a; char b; }; union { char c, d; }; };
- """)
- assert ffi.offsetof("struct foo_s", "c") == 2 * ffi.sizeof("int")
- assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
- ffi.verify("""
- struct foo_s { struct { int a; char b; }; union { char c, d; }; };
- """)
- p = ffi.new("struct foo_s *")
- assert ffi.sizeof(p[0]) == 3 * ffi.sizeof("int") # with alignment
- p.a = 1234567
- p.b = b'X'
- p.c = b'Y'
- assert p.a == 1234567
- assert p.b == b'X'
- assert p.c == b'Y'
- assert p.d == b'Y'
-
-def test_nested_anonymous_struct_exact_error():
- if sys.platform == 'win32':
- py.test.skip("nested anonymous struct/union")
- ffi = FFI()
- ffi.cdef("""
- struct foo_s { struct { int a; char b; }; union { char c, d; }; };
- """)
- py.test.raises(VerificationError, ffi.verify, """
- struct foo_s { struct { int a; short b; }; union { char c, d; }; };
- """)
- # works fine now
- #py.test.raises(VerificationError, ffi.verify, """
- # struct foo_s { struct { int a; char e, b; }; union { char c, d; }; };
- #""")
-
-def test_nested_anonymous_struct_inexact_1():
- ffi = FFI()
- ffi.cdef("""
- struct foo_s { struct { char b; ...; }; union { char c, d; }; };
- """)
- ffi.verify("""
- struct foo_s { int a, padding; char c, d, b; };
- """)
- assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
-
-def test_nested_anonymous_struct_inexact_2():
- ffi = FFI()
- ffi.cdef("""
- struct foo_s { union { char c, d; }; struct { int a; char b; }; ...; };
- """)
- ffi.verify("""
- struct foo_s { int a, padding; char c, d, b; };
- """)
- assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
-
-def test_ffi_union():
- ffi = FFI()
- ffi.cdef("union foo_u { char x; long *z; };")
- ffi.verify("union foo_u { char x; int y; long *z; };")
-
-def test_ffi_union_partial():
- ffi = FFI()
- ffi.cdef("union foo_u { char x; ...; };")
- ffi.verify("union foo_u { char x; int y; };")
- assert ffi.sizeof("union foo_u") == 4
-
-def test_ffi_union_with_partial_struct():
- ffi = FFI()
- ffi.cdef("struct foo_s { int x; ...; }; union foo_u { struct foo_s s; };")
- ffi.verify("struct foo_s { int a; int x; }; "
- "union foo_u { char b[32]; struct foo_s s; };")
- assert ffi.sizeof("struct foo_s") == 8
- assert ffi.sizeof("union foo_u") == 32
-
-def test_ffi_union_partial_2():
- ffi = FFI()
- ffi.cdef("typedef union { char x; ...; } u1;")
- ffi.verify("typedef union { char x; int y; } u1;")
- assert ffi.sizeof("u1") == 4
-
-def test_ffi_union_with_partial_struct_2():
- ffi = FFI()
- ffi.cdef("typedef struct { int x; ...; } s1;"
- "typedef union { s1 s; } u1;")
- ffi.verify("typedef struct { int a; int x; } s1; "
- "typedef union { char b[32]; s1 s; } u1;")
- assert ffi.sizeof("s1") == 8
- assert ffi.sizeof("u1") == 32
- assert ffi.offsetof("u1", "s") == 0
-
-def test_ffi_struct_packed():
- if sys.platform == 'win32':
- py.test.skip("needs a GCC extension")
- ffi = FFI()
- ffi.cdef("struct foo_s { int b; ...; };")
- ffi.verify("""
- struct foo_s {
- char a;
- int b;
- } __attribute__((packed));
- """)
-
-def test_tmpdir():
- import tempfile, os
- from testing.udir import udir
- tmpdir = tempfile.mkdtemp(dir=str(udir))
- ffi = FFI()
- ffi.cdef("int foo(int);")
- lib = ffi.verify("int foo(int a) { return a + 42; }", tmpdir=tmpdir)
- assert os.listdir(tmpdir)
- assert lib.foo(100) == 142
-
-def test_relative_to():
- py.test.skip("not available")
- import tempfile, os
- from testing.udir import udir
- tmpdir = tempfile.mkdtemp(dir=str(udir))
- ffi = FFI()
- ffi.cdef("int foo(int);")
- f = open(os.path.join(tmpdir, 'foo.h'), 'w')
- f.write("int foo(int a) { return a + 42; }\n")
- f.close()
- lib = ffi.verify('#include "foo.h"',
- include_dirs=['.'],
- relative_to=os.path.join(tmpdir, 'x'))
- assert lib.foo(100) == 142
-
-def test_bug1():
- ffi = FFI()
- ffi.cdef("""
- typedef struct tdlhandle_s { ...; } *tdl_handle_t;
- typedef struct my_error_code_ {
- tdl_handle_t *rh;
- } my_error_code_t;
- """)
- ffi.verify("""
- typedef struct tdlhandle_s { int foo; } *tdl_handle_t;
- typedef struct my_error_code_ {
- tdl_handle_t *rh;
- } my_error_code_t;
- """)
-
-def test_bool():
- if sys.platform == 'win32':
- py.test.skip("_Bool not in MSVC")
- ffi = FFI()
- ffi.cdef("struct foo_s { _Bool x; };"
- "_Bool foo(_Bool); static _Bool (*foop)(_Bool);")
- lib = ffi.verify("""
- struct foo_s { _Bool x; };
- int foo(int arg) {
- return !arg;
- }
- _Bool _foofunc(_Bool x) {
- return !x;
- }
- static _Bool (*foop)(_Bool) = _foofunc;
- """)
- p = ffi.new("struct foo_s *")
- p.x = 1
- assert p.x is True
- with pytest.raises(OverflowError):
- p.x = -1
- with pytest.raises(TypeError):
- p.x = 0.0
- assert lib.foop(1) is False
- assert lib.foop(True) is False
- assert lib.foop(0) is True
- py.test.raises(OverflowError, lib.foop, 42)
- py.test.raises(TypeError, lib.foop, 0.0)
- assert lib.foo(1) is False
- assert lib.foo(True) is False
- assert lib.foo(0) is True
- py.test.raises(OverflowError, lib.foo, 42)
- py.test.raises(TypeError, lib.foo, 0.0)
- assert int(ffi.cast("_Bool", long(1))) == 1
- assert int(ffi.cast("_Bool", long(0))) == 0
- assert int(ffi.cast("_Bool", long(-1))) == 1
- assert int(ffi.cast("_Bool", 10**200)) == 1
- assert int(ffi.cast("_Bool", 10**40000)) == 1
- #
- class Foo(object):
- def __int__(self):
- self.seen = 1
- return result
- f = Foo()
- f.seen = 0
- result = 42
- assert int(ffi.cast("_Bool", f)) == 1
- assert f.seen
- f.seen = 0
- result = 0
- assert int(ffi.cast("_Bool", f)) == 0
- assert f.seen
- #
- py.test.raises(TypeError, ffi.cast, "_Bool", [])
-
-def test_bool_on_long_double():
- if sys.platform == 'win32':
- py.test.skip("_Bool not in MSVC")
- f = 1E-250
- if f == 0.0 or f*f != 0.0:
- py.test.skip("unexpected precision")
- ffi = FFI()
- ffi.cdef("long double square(long double f); _Bool opposite(_Bool);")
- lib = ffi.verify("long double square(long double f) { return f*f; }\n"
- "_Bool opposite(_Bool x) { return !x; }")
- f0 = lib.square(0.0)
- f2 = lib.square(f)
- f3 = lib.square(f * 2.0)
- if repr(f2) == repr(f3):
- py.test.skip("long double doesn't have enough precision")
- assert float(f0) == float(f2) == float(f3) == 0.0 # too tiny for 'double'
- assert int(ffi.cast("_Bool", f2)) == 1
- assert int(ffi.cast("_Bool", f3)) == 1
- assert int(ffi.cast("_Bool", f0)) == 0
- py.test.raises(TypeError, lib.opposite, f2)
-
-def test_cannot_pass_float():
- for basetype in ['char', 'short', 'int', 'long', 'long long']:
- for sign in ['signed', 'unsigned']:
- type = '%s %s' % (sign, basetype)
- ffi = FFI()
- ffi.cdef("struct foo_s { %s x; };\n"
- "int foo(%s);" % (type, type))
- lib = ffi.verify("""
- struct foo_s { %s x; };
- int foo(%s arg) {
- return !arg;
- }
- """ % (type, type))
- p = ffi.new("struct foo_s *")
- with pytest.raises(TypeError):
- p.x = 0.0
- assert lib.foo(42) == 0
- assert lib.foo(0) == 1
- py.test.raises(TypeError, lib.foo, 0.0)
-
-def test_addressof():
- ffi = FFI()
- ffi.cdef("""
- struct point_s { int x, y; };
- struct foo_s { int z; struct point_s point; };
- struct point_s sum_coord(struct point_s *);
- """)
- lib = ffi.verify("""
- struct point_s { int x, y; };
- struct foo_s { int z; struct point_s point; };
- struct point_s sum_coord(struct point_s *point) {
- struct point_s r;
- r.x = point->x + point->y;
- r.y = point->x - point->y;
- return r;
- }
- """)
- p = ffi.new("struct foo_s *")
- p.point.x = 16
- p.point.y = 9
- py.test.raises(TypeError, lib.sum_coord, p.point)
- res = lib.sum_coord(ffi.addressof(p.point))
- assert res.x == 25
- assert res.y == 7
- res2 = lib.sum_coord(ffi.addressof(res))
- assert res2.x == 32
- assert res2.y == 18
- py.test.raises(TypeError, lib.sum_coord, res2)
-
-def test_callback_in_thread():
- py.test.xfail("adapt or remove")
- if sys.platform == 'win32':
- py.test.skip("pthread only")
- import os, subprocess, imp
- arg = os.path.join(os.path.dirname(__file__), 'callback_in_thread.py')
- g = subprocess.Popen([sys.executable, arg,
- os.path.dirname(imp.find_module('cffi')[1])])
- result = g.wait()
- assert result == 0
-
-def test_keepalive_lib():
- py.test.xfail("adapt or remove")
- ffi = FFI()
- ffi.cdef("int foobar(void);")
- lib = ffi.verify("int foobar(void) { return 42; }")
- func = lib.foobar
- ffi_r = weakref.ref(ffi)
- lib_r = weakref.ref(lib)
- del ffi
- import gc; gc.collect() # lib stays alive
- assert lib_r() is not None
- assert ffi_r() is not None
- assert func() == 42
-
-def test_keepalive_ffi():
- py.test.xfail("adapt or remove")
- ffi = FFI()
- ffi.cdef("int foobar(void);")
- lib = ffi.verify("int foobar(void) { return 42; }")
- func = lib.foobar
- ffi_r = weakref.ref(ffi)
- lib_r = weakref.ref(lib)
- del lib
- import gc; gc.collect() # ffi stays alive
- assert ffi_r() is not None
- assert lib_r() is not None
- assert func() == 42
-
-def test_FILE_stored_in_stdout():
- if not sys.platform.startswith('linux'):
- py.test.skip("likely, we cannot assign to stdout")
- ffi = FFI()
- ffi.cdef("int printf(const char *, ...); FILE *setstdout(FILE *);")
- lib = ffi.verify("""
- #include <stdio.h>
- FILE *setstdout(FILE *f) {
- FILE *result = stdout;
- stdout = f;
- return result;
- }
- """)
- import os
- fdr, fdw = os.pipe()
- fw1 = os.fdopen(fdw, 'wb', 256)
- old_stdout = lib.setstdout(fw1)
- try:
- #
- fw1.write(b"X")
- r = lib.printf(b"hello, %d!\n", ffi.cast("int", 42))
- fw1.close()
- assert r == len("hello, 42!\n")
- #
- finally:
- lib.setstdout(old_stdout)
- #
- result = os.read(fdr, 256)
- os.close(fdr)
- # the 'X' might remain in the user-level buffer of 'fw1' and
- # end up showing up after the 'hello, 42!\n'
- assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
-
-def test_FILE_stored_explicitly():
- ffi = FFI()
- ffi.cdef("int myprintf11(const char *, int); extern FILE *myfile;")
- lib = ffi.verify("""
- #include <stdio.h>
- FILE *myfile;
- int myprintf11(const char *out, int value) {
- return fprintf(myfile, out, value);
- }
- """)
- import os
- fdr, fdw = os.pipe()
- fw1 = os.fdopen(fdw, 'wb', 256)
- lib.myfile = ffi.cast("FILE *", fw1)
- #
- fw1.write(b"X")
- r = lib.myprintf11(b"hello, %d!\n", ffi.cast("int", 42))
- fw1.close()
- assert r == len("hello, 42!\n")
- #
- result = os.read(fdr, 256)
- os.close(fdr)
- # the 'X' might remain in the user-level buffer of 'fw1' and
- # end up showing up after the 'hello, 42!\n'
- assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
-
-def test_global_array_with_missing_length():
- ffi = FFI()
- ffi.cdef("extern int fooarray[];")
- lib = ffi.verify("int fooarray[50];")
- assert repr(lib.fooarray).startswith("<cdata 'int *'")
-
-def test_global_array_with_dotdotdot_length():
- ffi = FFI()
- ffi.cdef("extern int fooarray[...];")
- lib = ffi.verify("int fooarray[50];")
- assert repr(lib.fooarray).startswith("<cdata 'int[50]'")
-
-def test_bad_global_array_with_dotdotdot_length():
- py.test.xfail("was detected only because 23 bytes cannot be divided by 4; "
- "redo more generally")
- ffi = FFI()
- ffi.cdef("extern int fooarray[...];")
- py.test.raises(VerificationError, ffi.verify, "char fooarray[23];")
-
-def test_struct_containing_struct():
- ffi = FFI()
- ffi.cdef("struct foo_s { ...; }; struct bar_s { struct foo_s f; ...; };")
- ffi.verify("struct foo_s { int x; }; struct bar_s { struct foo_s f; };")
- #
- ffi = FFI()
- ffi.cdef("struct foo_s { struct bar_s f; ...; }; struct bar_s { ...; };")
- ffi.verify("struct bar_s { int x; }; struct foo_s { struct bar_s f; };")
-
-def test_struct_returned_by_func():
- ffi = FFI()
- ffi.cdef("typedef ... foo_t; foo_t myfunc(void);")
- e = py.test.raises(TypeError, ffi.verify,
- "typedef struct { int x; } foo_t; "
- "foo_t myfunc(void) { foo_t x = { 42 }; return x; }")
- assert str(e.value) == (
- "function myfunc: 'foo_t' is used as result type, but is opaque")
-
-def test_include():
- ffi1 = FFI()
- ffi1.cdef("typedef struct { int x; ...; } foo_t;")
- ffi1.verify("typedef struct { int y, x; } foo_t;")
- ffi2 = FFI()
- ffi2.include(ffi1)
- ffi2.cdef("int myfunc(foo_t *);")
- lib = ffi2.verify("typedef struct { int y, x; } foo_t;"
- "int myfunc(foo_t *p) { return 42 * p->x; }")
- res = lib.myfunc(ffi2.new("foo_t *", {'x': 10}))
- assert res == 420
- res = lib.myfunc(ffi1.new("foo_t *", {'x': -10}))
- assert res == -420
-
-def test_include_enum():
- ffi1 = FFI()
- ffi1.cdef("enum foo_e { AA, ... };")
- lib1 = ffi1.verify("enum foo_e { CC, BB, AA };")
- ffi2 = FFI()
- ffi2.include(ffi1)
- ffi2.cdef("int myfunc(enum foo_e);")
- lib2 = ffi2.verify("enum foo_e { CC, BB, AA };"
- "int myfunc(enum foo_e x) { return (int)x; }")
- res = lib2.myfunc(lib2.AA)
- assert res == 2
-
-def test_named_pointer_as_argument():
- ffi = FFI()
- ffi.cdef("typedef struct { int x; } *mystruct_p;\n"
- "mystruct_p ff5a(mystruct_p);")
- lib = ffi.verify("typedef struct { int x; } *mystruct_p;\n"
- "mystruct_p ff5a(mystruct_p p) { p->x += 40; return p; }")
- p = ffi.new("mystruct_p", [-2])
- q = lib.ff5a(p)
- assert q == p
- assert p.x == 38
-
-def test_enum_size():
- cases = [('123', 4, 4294967295),
- ('4294967295U', 4, 4294967295),
- ('-123', 4, -1),
- ('-2147483647-1', 4, -1),
- ]
- if FFI().sizeof("long") == 8:
- cases += [('4294967296L', 8, 2**64-1),
- ('%dUL' % (2**64-1), 8, 2**64-1),
- ('-2147483649L', 8, -1),
- ('%dL-1L' % (1-2**63), 8, -1)]
- for hidden_value, expected_size, expected_minus1 in cases:
- if sys.platform == 'win32' and 'U' in hidden_value:
- continue # skipped on Windows
- ffi = FFI()
- ffi.cdef("enum foo_e { AA, BB, ... };")
- lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value)
- assert lib.AA == 0
- assert lib.BB == eval(hidden_value.replace('U', '').replace('L', ''))
- assert ffi.sizeof("enum foo_e") == expected_size
- if sys.platform != 'win32':
- assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
- # test with the large value hidden:
- # disabled so far, doesn't work
-## for hidden_value, expected_size, expected_minus1 in cases:
-## ffi = FFI()
-## ffi.cdef("enum foo_e { AA, BB, ... };")
-## lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value)
-## assert lib.AA == 0
-## assert ffi.sizeof("enum foo_e") == expected_size
-## assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
-
-def test_enum_bug118():
- maxulong = 256 ** FFI().sizeof("unsigned long") - 1
- for c2, c2c in [(-1, ''),
- (-1, ''),
- (0xffffffff, 'U'),
- (maxulong, 'UL'),
- (-int(maxulong / 3), 'L')]:
- if c2c and sys.platform == 'win32':
- continue # enums may always be signed with MSVC
- ffi = FFI()
- ffi.cdef("enum foo_e { AA };")
- lib = ffi.verify("enum foo_e { AA=%s%s };" % (c2, c2c))
- assert lib.AA == c2
-
-def test_string_to_voidp_arg():
- ffi = FFI()
- ffi.cdef("int myfunc(void *);")
- lib = ffi.verify("int myfunc(void *p) { return ((signed char *)p)[0]; }")
- res = lib.myfunc(b"hi!")
- assert res == ord(b"h")
- p = ffi.new("char[]", b"gah")
- res = lib.myfunc(p)
- assert res == ord(b"g")
- res = lib.myfunc(ffi.cast("void *", p))
- assert res == ord(b"g")
- res = lib.myfunc(ffi.cast("int *", p))
- assert res == ord(b"g")
-
-def test_callback_indirection():
- ffi = FFI()
- ffi.cdef("""
- static int (*python_callback)(int how_many, int *values);
- int (*const c_callback)(int,...); /* pass this ptr to C routines */
- int some_c_function(int(*cb)(int,...));
- """)
- lib = ffi.verify("""
- #include <stdarg.h>
- #ifdef _WIN32
- #include <malloc.h>
- #define alloca _alloca
- #else
- # ifdef __FreeBSD__
- # include <stdlib.h>
- # else
- # include <alloca.h>
- # endif
- #endif
- static int (*python_callback)(int how_many, int *values);
- static int c_callback(int how_many, ...) {
- va_list ap;
- /* collect the "..." arguments into the values[] array */
- int i, *values = alloca((size_t)how_many * sizeof(int));
- va_start(ap, how_many);
- for (i=0; i<how_many; i++)
- values[i] = va_arg(ap, int);
- va_end(ap);
- return python_callback(how_many, values);
- }
- int some_c_function(int(*cb)(int,...)) {
- int result = cb(2, 10, 20);
- result += cb(3, 30, 40, 50);
- return result;
- }
- """)
- seen = []
- @ffi.callback("int(int, int*)")
- def python_callback(how_many, values):
- seen.append([values[i] for i in range(how_many)])
- return 42
- lib.python_callback = python_callback
-
- res = lib.some_c_function(lib.c_callback)
- assert res == 84
- assert seen == [[10, 20], [30, 40, 50]]
-
-def test_floatstar_argument():
- ffi = FFI()
- ffi.cdef("float sum3floats(float *);")
- lib = ffi.verify("""
- float sum3floats(float *f) {
- return f[0] + f[1] + f[2];
- }
- """)
- assert lib.sum3floats((1.5, 2.5, 3.5)) == 7.5
- p = ffi.new("float[]", (1.5, 2.5, 3.5))
- assert lib.sum3floats(p) == 7.5
-
-def test_charstar_argument():
- ffi = FFI()
- ffi.cdef("char sum3chars(char *);")
- lib = ffi.verify("""
- char sum3chars(char *f) {
- return (char)(f[0] + f[1] + f[2]);
- }
- """)
- assert lib.sum3chars((b'\x10', b'\x20', b'\x30')) == b'\x60'
- p = ffi.new("char[]", b'\x10\x20\x30')
- assert lib.sum3chars(p) == b'\x60'
-
-def test_passing_string_or_NULL():
- ffi = FFI()
- ffi.cdef("int seeme1(char *); int seeme2(int *);")
- lib = ffi.verify("""
- int seeme1(char *x) {
- return (x == NULL);
- }
- int seeme2(int *x) {
- return (x == NULL);
- }
- """)
- assert lib.seeme1(b"foo") == 0
- assert lib.seeme1(ffi.NULL) == 1
- assert lib.seeme2([42, 43]) == 0
- assert lib.seeme2(ffi.NULL) == 1
- py.test.raises(TypeError, lib.seeme1, None)
- py.test.raises(TypeError, lib.seeme2, None)
- py.test.raises(TypeError, lib.seeme1, 0.0)
- py.test.raises(TypeError, lib.seeme2, 0.0)
- py.test.raises(TypeError, lib.seeme1, 0)
- py.test.raises(TypeError, lib.seeme2, 0)
- zeroL = 99999999999999999999
- zeroL -= 99999999999999999999
- py.test.raises(TypeError, lib.seeme2, zeroL)
-
-def test_typeof_function():
- ffi = FFI()
- ffi.cdef("int foo(int, char);")
- lib = ffi.verify("int foo(int x, char y) { (void)x; (void)y; return 42; }")
- ctype = ffi.typeof(lib.foo)
- assert len(ctype.args) == 2
- assert ctype.result == ffi.typeof("int")
-
-def test_call_with_voidstar_arg():
- ffi = FFI()
- ffi.cdef("int f(void *);")
- lib = ffi.verify("int f(void *x) { return ((char*)x)[0]; }")
- assert lib.f(b"foobar") == ord(b"f")
-
-def test_dir():
- ffi = FFI()
- ffi.cdef("""void somefunc(void);
- extern int somevar, somearray[2];
- static char *const sv2;
- enum my_e { AA, BB, ... };
- #define FOO ...""")
- lib = ffi.verify("""void somefunc(void) { }
- int somevar, somearray[2];
- #define sv2 "text"
- enum my_e { AA, BB };
- #define FOO 42""")
- assert dir(lib) == ['AA', 'BB', 'FOO', 'somearray',
- 'somefunc', 'somevar', 'sv2']
-
-def test_typeof_func_with_struct_argument():
- ffi = FFI()
- ffi.cdef("""struct s { int a; }; int foo(struct s);""")
- lib = ffi.verify("""struct s { int a; };
- int foo(struct s x) { return x.a; }""")
- s = ffi.new("struct s *", [-1234])
- m = lib.foo(s[0])
- assert m == -1234
- assert repr(ffi.typeof(lib.foo)) == "<ctype 'int(*)(struct s)'>"
-
-def test_bug_const_char_ptr_array_1():
- ffi = FFI()
- ffi.cdef("""extern const char *a[...];""")
- lib = ffi.verify("""const char *a[5];""")
- assert repr(ffi.typeof(lib.a)) == "<ctype 'char *[5]'>"
-
-def test_bug_const_char_ptr_array_2():
- ffi = FFI()
- ffi.cdef("""extern const int a[];""")
- lib = ffi.verify("""const int a[5];""")
- assert repr(ffi.typeof(lib.a)) == "<ctype 'int *'>"
-
-def _test_various_calls(force_libffi):
- cdef_source = """
- extern int xvalue;
- extern long long ivalue, rvalue;
- extern float fvalue;
- extern double dvalue;
- extern long double Dvalue;
- signed char tf_bb(signed char x, signed char c);
- unsigned char tf_bB(signed char x, unsigned char c);
- short tf_bh(signed char x, short c);
- unsigned short tf_bH(signed char x, unsigned short c);
- int tf_bi(signed char x, int c);
- unsigned int tf_bI(signed char x, unsigned int c);
- long tf_bl(signed char x, long c);
- unsigned long tf_bL(signed char x, unsigned long c);
- long long tf_bq(signed char x, long long c);
- unsigned long long tf_bQ(signed char x, unsigned long long c);
- float tf_bf(signed char x, float c);
- double tf_bd(signed char x, double c);
- long double tf_bD(signed char x, long double c);
- """
- if force_libffi:
- cdef_source = (cdef_source
- .replace('tf_', '(*const tf_')
- .replace('(signed char x', ')(signed char x'))
- ffi = FFI()
- ffi.cdef(cdef_source)
- lib = ffi.verify("""
- int xvalue;
- long long ivalue, rvalue;
- float fvalue;
- double dvalue;
- long double Dvalue;
-
- typedef signed char b_t;
- typedef unsigned char B_t;
- typedef short h_t;
- typedef unsigned short H_t;
- typedef int i_t;
- typedef unsigned int I_t;
- typedef long l_t;
- typedef unsigned long L_t;
- typedef long long q_t;
- typedef unsigned long long Q_t;
- typedef float f_t;
- typedef double d_t;
- typedef long double D_t;
- #define S(letter) xvalue = (int)x; letter##value = (letter##_t)c;
- #define R(letter) return (letter##_t)rvalue;
-
- signed char tf_bb(signed char x, signed char c) { S(i) R(b) }
- unsigned char tf_bB(signed char x, unsigned char c) { S(i) R(B) }
- short tf_bh(signed char x, short c) { S(i) R(h) }
- unsigned short tf_bH(signed char x, unsigned short c) { S(i) R(H) }
- int tf_bi(signed char x, int c) { S(i) R(i) }
- unsigned int tf_bI(signed char x, unsigned int c) { S(i) R(I) }
- long tf_bl(signed char x, long c) { S(i) R(l) }
- unsigned long tf_bL(signed char x, unsigned long c) { S(i) R(L) }
- long long tf_bq(signed char x, long long c) { S(i) R(q) }
- unsigned long long tf_bQ(signed char x, unsigned long long c) { S(i) R(Q) }
- float tf_bf(signed char x, float c) { S(f) R(f) }
- double tf_bd(signed char x, double c) { S(d) R(d) }
- long double tf_bD(signed char x, long double c) { S(D) R(D) }
- """)
- lib.rvalue = 0x7182838485868788
- for kind, cname in [('b', 'signed char'),
- ('B', 'unsigned char'),
- ('h', 'short'),
- ('H', 'unsigned short'),
- ('i', 'int'),
- ('I', 'unsigned int'),
- ('l', 'long'),
- ('L', 'unsigned long'),
- ('q', 'long long'),
- ('Q', 'unsigned long long'),
- ('f', 'float'),
- ('d', 'double'),
- ('D', 'long double')]:
- sign = +1 if 'unsigned' in cname else -1
- lib.xvalue = 0
- lib.ivalue = 0
- lib.fvalue = 0
- lib.dvalue = 0
- lib.Dvalue = 0
- fun = getattr(lib, 'tf_b' + kind)
- res = fun(-42, sign * 99)
- if kind == 'D':
- res = float(res)
- assert res == int(ffi.cast(cname, 0x7182838485868788))
- assert lib.xvalue == -42
- if kind in 'fdD':
- assert float(getattr(lib, kind + 'value')) == -99.0
- else:
- assert lib.ivalue == sign * 99
-
-def test_various_calls_direct():
- _test_various_calls(force_libffi=False)
-
-def test_various_calls_libffi():
- _test_various_calls(force_libffi=True)
-
-def test_ptr_to_opaque():
- ffi = FFI()
- ffi.cdef("typedef ... foo_t; int f1(foo_t*); foo_t *f2(int);")
- lib = ffi.verify("""
- #include <stdlib.h>
- typedef struct { int x; } foo_t;
- int f1(foo_t* p) {
- int x = p->x;
- free(p);
- return x;
- }
- foo_t *f2(int x) {
- foo_t *p = malloc(sizeof(foo_t));
- p->x = x;
- return p;
- }
- """)
- p = lib.f2(42)
- x = lib.f1(p)
- assert x == 42
-
-def _run_in_multiple_threads(test1):
- test1()
- import sys
- try:
- import thread
- except ImportError:
- import _thread as thread
- errors = []
- def wrapper(lock):
- try:
- test1()
- except:
- errors.append(sys.exc_info())
- lock.release()
- locks = []
- for i in range(10):
- _lock = thread.allocate_lock()
- _lock.acquire()
- thread.start_new_thread(wrapper, (_lock,))
- locks.append(_lock)
- for _lock in locks:
- _lock.acquire()
- if errors:
- raise errors[0][1]
-
-def test_errno_working_even_with_pypys_jit():
- ffi = FFI()
- ffi.cdef("int f(int);")
- lib = ffi.verify("""
- #include <errno.h>
- int f(int x) { return (errno = errno + x); }
- """)
- @_run_in_multiple_threads
- def test1():
- ffi.errno = 0
- for i in range(10000):
- e = lib.f(1)
- assert e == i + 1
- assert ffi.errno == e
- for i in range(10000):
- ffi.errno = i
- e = lib.f(42)
- assert e == i + 42
-
-def test_getlasterror_working_even_with_pypys_jit():
- if sys.platform != 'win32':
- py.test.skip("win32-only test")
- ffi = FFI()
- ffi.cdef("void SetLastError(DWORD);")
- lib = ffi.dlopen("Kernel32.dll")
- @_run_in_multiple_threads
- def test1():
- for i in range(10000):
- n = (1 << 29) + i
- lib.SetLastError(n)
- assert ffi.getwinerror()[0] == n
-
-def test_verify_dlopen_flags():
- if not hasattr(sys, 'setdlopenflags'):
- py.test.skip("requires sys.setdlopenflags()")
- # Careful with RTLD_GLOBAL. If by chance the FFI is not deleted
- # promptly, like on PyPy, then other tests may see the same
- # exported symbols as well. So we must not export a simple name
- # like 'foo'!
- old = sys.getdlopenflags()
- try:
- ffi1 = FFI()
- ffi1.cdef("extern int foo_verify_dlopen_flags_1;")
- sys.setdlopenflags(ffi1.RTLD_GLOBAL | ffi1.RTLD_NOW)
- lib1 = ffi1.verify("int foo_verify_dlopen_flags_1;")
- finally:
- sys.setdlopenflags(old)
-
- ffi2 = FFI()
- ffi2.cdef("int *getptr(void);")
- lib2 = ffi2.verify("""
- extern int foo_verify_dlopen_flags_1;
- static int *getptr(void) { return &foo_verify_dlopen_flags_1; }
- """)
- p = lib2.getptr()
- assert ffi1.addressof(lib1, 'foo_verify_dlopen_flags_1') == p
-
-def test_consider_not_implemented_function_type():
- ffi = FFI()
- ffi.cdef("typedef union { int a; float b; } Data;"
- "typedef struct { int a:2; } MyStr;"
- "typedef void (*foofunc_t)(Data);"
- "typedef Data (*bazfunc_t)(void);"
- "typedef MyStr (*barfunc_t)(void);")
- fooptr = ffi.cast("foofunc_t", 123)
- bazptr = ffi.cast("bazfunc_t", 123)
- barptr = ffi.cast("barfunc_t", 123)
- # assert did not crash so far
- e = py.test.raises(NotImplementedError, fooptr, ffi.new("Data *"))
- assert str(e.value) == (
- "ctype 'Data' not supported as argument by libffi. Unions 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)")
- e = py.test.raises(NotImplementedError, bazptr)
- assert str(e.value) == (
- "ctype 'Data' not supported as return value by libffi. Unions are "
- "only supported as return value if the function is 'API mode' and "
- "non-variadic (i.e. declared inside ffibuilder.cdef()+"
- "ffibuilder.set_source() and not taking a final '...' argument)")
- e = py.test.raises(NotImplementedError, barptr)
- assert str(e.value) == (
- "ctype 'MyStr' not supported as return value. It is a struct with "
- "bit fields, which libffi does not support. Such structs are only "
- "supported as return value if the function is 'API mode' and non-"
- "variadic (i.e. declared inside ffibuilder.cdef()+ffibuilder."
- "set_source() and not taking a final '...' argument)")
-
-def test_verify_extra_arguments():
- ffi = FFI()
- ffi.cdef("#define ABA ...")
- lib = ffi.verify("", define_macros=[('ABA', '42')])
- assert lib.ABA == 42
-
-def test_implicit_unicode_on_windows():
- from cffi import FFIError
- if sys.platform != 'win32':
- py.test.skip("win32-only test")
- ffi = FFI()
- e = py.test.raises(FFIError, ffi.cdef, "int foo(LPTSTR);")
- assert str(e.value) == ("The Windows type 'LPTSTR' is only available after"
- " you call ffi.set_unicode()")
- for with_unicode in [True, False]:
- ffi = FFI()
- ffi.set_unicode(with_unicode)
- ffi.cdef("""
- DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename,
- DWORD nSize);
- """)
- lib = ffi.verify("""
- #include <windows.h>
- """, libraries=['Kernel32'])
- outbuf = ffi.new("TCHAR[]", 200)
- n = lib.GetModuleFileName(ffi.NULL, outbuf, 500)
- assert 0 < n < 500
- for i in range(n):
- #print repr(outbuf[i])
- assert ord(outbuf[i]) != 0
- assert ord(outbuf[n]) == 0
- assert ord(outbuf[0]) < 128 # should be a letter, or '\'
-
-def test_define_known_value():
- ffi = FFI()
- ffi.cdef("#define FOO 0x123")
- lib = ffi.verify("#define FOO 0x123")
- assert lib.FOO == 0x123
-
-def test_define_wrong_value():
- ffi = FFI()
- ffi.cdef("#define FOO 123")
- lib = ffi.verify("#define FOO 124") # used to complain
- with pytest.raises(ffi.error) as e:
- lib.FOO
- assert str(e.value) == ("the C compiler says 'FOO' is equal to 124 (0x7c),"
- " but the cdef disagrees")
-
-def test_some_integer_type_for_issue73():
- ffi = FFI()
- ffi.cdef("""
- typedef int... AnIntegerWith32Bits;
- typedef AnIntegerWith32Bits (*AFunctionReturningInteger) (void);
- AnIntegerWith32Bits InvokeFunction(AFunctionReturningInteger);
- """)
- lib = ffi.verify("""
- #ifdef __LP64__
- typedef int AnIntegerWith32Bits;
- #else
- typedef long AnIntegerWith32Bits;
- #endif
- typedef AnIntegerWith32Bits (*AFunctionReturningInteger) (void);
- AnIntegerWith32Bits InvokeFunction(AFunctionReturningInteger f) {
- return f();
- }
- """)
- @ffi.callback("AFunctionReturningInteger")
- def add():
- return 3 + 4
- x = lib.InvokeFunction(add)
- assert x == 7
-
-def test_unsupported_some_primitive_types():
- ffi = FFI()
- py.test.raises((FFIError, # with pycparser <= 2.17
- CDefError), # with pycparser >= 2.18
- ffi.cdef, """typedef void... foo_t;""")
- #
- ffi.cdef("typedef int... foo_t;")
- py.test.raises(VerificationError, ffi.verify, "typedef float foo_t;")
-
-def test_windows_dllimport_data():
- if sys.platform != 'win32':
- py.test.skip("Windows only")
- from testing.udir import udir
- tmpfile = udir.join('dllimport_data.c')
- tmpfile.write('int my_value = 42;\n')
- ffi = FFI()
- ffi.cdef("int my_value;")
- lib = ffi.verify("extern __declspec(dllimport) int my_value;",
- sources = [str(tmpfile)])
- assert lib.my_value == 42
-
-def test_macro_var():
- ffi = FFI()
- ffi.cdef("extern int myarray[50], my_value;")
- lib = ffi.verify("""
- int myarray[50];
- int *get_my_value(void) {
- static int index = 0;
- return &myarray[index++];
- }
- #define my_value (*get_my_value())
- """)
- assert lib.my_value == 0 # [0]
- lib.my_value = 42 # [1]
- assert lib.myarray[1] == 42
- assert lib.my_value == 0 # [2]
- lib.myarray[3] = 63
- assert lib.my_value == 63 # [3]
- p = ffi.addressof(lib, 'my_value') # [4]
- assert p[-1] == 63
- assert p[0] == 0
- assert p == lib.myarray + 4
- p[1] = 82
- assert lib.my_value == 82 # [5]
-
-def test_const_pointer_to_pointer():
- ffi = FFI()
- ffi.cdef("struct s { char *const *a; };")
- ffi.verify("struct s { char *const *a; };")
-
-def test_share_FILE():
- ffi1 = FFI()
- ffi1.cdef("void do_stuff(FILE *);")
- lib1 = ffi1.verify("void do_stuff(FILE *f) { (void)f; }")
- ffi2 = FFI()
- ffi2.cdef("FILE *barize(void);")
- lib2 = ffi2.verify("FILE *barize(void) { return NULL; }")
- lib1.do_stuff(lib2.barize())
-
-def test_win_common_types():
- if sys.platform != 'win32':
- py.test.skip("Windows only")
- ffi = FFI()
- ffi.set_unicode(True)
- ffi.verify("")
- assert ffi.typeof("PBYTE") is ffi.typeof("unsigned char *")
- if sys.maxsize > 2**32:
- expected = "unsigned long long"
- else:
- expected = "unsigned int"
- assert ffi.typeof("UINT_PTR") is ffi.typeof(expected)
- assert ffi.typeof("PTSTR") is ffi.typeof("wchar_t *")
-
-def _only_test_on_linux_intel():
- if not sys.platform.startswith('linux'):
- py.test.skip('only running the memory-intensive test on Linux')
- import platform
- machine = platform.machine()
- if 'x86' not in machine and 'x64' not in machine:
- py.test.skip('only running the memory-intensive test on x86/x64')
-
-def test_ffi_gc_size_arg():
- _only_test_on_linux_intel()
- ffi = FFI()
- ffi.cdef("void *malloc(size_t); void free(void *);")
- lib = ffi.verify(r"""
- #include <stdlib.h>
- """)
- for i in range(2000):
- p = lib.malloc(20*1024*1024) # 20 MB
- p1 = ffi.cast("char *", p)
- for j in range(0, 20*1024*1024, 4096):
- p1[j] = b'!'
- p = ffi.gc(p, lib.free, 20*1024*1024)
- del p
- # with PyPy's GC, the above would rapidly consume 40 GB of RAM
- # without the third argument to ffi.gc()
-
-def test_ffi_gc_size_arg_2():
- # a variant of the above: this "attack" works on cpython's cyclic gc too
- # and I found no obvious way to prevent that. So for now, this test
- # is skipped on CPython, where it eats all the memory.
- if '__pypy__' not in sys.builtin_module_names:
- py.test.skip("find a way to tweak the cyclic GC of CPython")
- _only_test_on_linux_intel()
- ffi = FFI()
- ffi.cdef("void *malloc(size_t); void free(void *);")
- lib = ffi.verify(r"""
- #include <stdlib.h>
- """)
- class X(object):
- pass
- for i in range(2000):
- p = lib.malloc(50*1024*1024) # 50 MB
- p1 = ffi.cast("char *", p)
- for j in range(0, 50*1024*1024, 4096):
- p1[j] = b'!'
- p = ffi.gc(p, lib.free, 50*1024*1024)
- x = X()
- x.p = p
- x.cyclic = x
- del p, x
-
-def test_ffi_new_with_cycles():
- # still another variant, with ffi.new()
- if '__pypy__' not in sys.builtin_module_names:
- py.test.skip("find a way to tweak the cyclic GC of CPython")
- ffi = FFI()
- ffi.cdef("")
- lib = ffi.verify("")
- class X(object):
- pass
- for i in range(2000):
- p = ffi.new("char[]", 50*1024*1024) # 50 MB
- for j in range(0, 50*1024*1024, 4096):
- p[j] = b'!'
- x = X()
- x.p = p
- x.cyclic = x
- del p, x
diff --git a/testing/cffi1/test_zdist.py b/testing/cffi1/test_zdist.py
deleted file mode 100644
index efc1d86..0000000
--- a/testing/cffi1/test_zdist.py
+++ /dev/null
@@ -1,426 +0,0 @@
-import sys, os, py
-import subprocess
-import cffi
-from testing.udir import udir
-from shutil import rmtree
-from tempfile import mkdtemp
-
-
-def chdir_to_tmp(f):
- f.chdir_to_tmp = True
- return f
-
-def from_outside(f):
- f.chdir_to_tmp = False
- return f
-
-
-class TestDist(object):
-
- def setup_method(self, meth):
- self.executable = os.path.abspath(sys.executable)
- self.rootdir = os.path.abspath(os.path.dirname(os.path.dirname(
- cffi.__file__)))
- self.udir = udir.join(meth.__name__)
- os.mkdir(str(self.udir))
- if meth.chdir_to_tmp:
- self.saved_cwd = os.getcwd()
- os.chdir(str(self.udir))
-
- def teardown_method(self, meth):
- if hasattr(self, 'saved_cwd'):
- os.chdir(self.saved_cwd)
-
- def run(self, args, cwd=None):
- env = os.environ.copy()
- # a horrible hack to prevent distutils from finding ~/.pydistutils.cfg
- # (there is the --no-user-cfg option, but not in Python 2.6...)
- # NOTE: pointing $HOME to a nonexistent directory can break certain things
- # that look there for configuration (like ccache).
- tmp_home = mkdtemp()
- assert tmp_home != None, "cannot create temporary homedir"
- env['HOME'] = tmp_home
- if cwd is None:
- newpath = self.rootdir
- if 'PYTHONPATH' in env:
- newpath += os.pathsep + env['PYTHONPATH']
- env['PYTHONPATH'] = newpath
- try:
- subprocess.check_call([self.executable] + args, cwd=cwd, env=env)
- finally:
- rmtree(tmp_home)
-
- def _prepare_setuptools(self):
- if hasattr(TestDist, '_setuptools_ready'):
- return
- try:
- import setuptools
- except ImportError:
- py.test.skip("setuptools not found")
- if os.path.exists(os.path.join(self.rootdir, 'setup.py')):
- self.run(['setup.py', 'egg_info'], cwd=self.rootdir)
- TestDist._setuptools_ready = True
-
- def check_produced_files(self, content, curdir=None):
- if curdir is None:
- curdir = str(self.udir)
- found_so = None
- for name in os.listdir(curdir):
- if (name.endswith('.so') or name.endswith('.pyd') or
- name.endswith('.dylib') or name.endswith('.dll')):
- found_so = os.path.join(curdir, name)
- # foo.so => foo
- parts = name.split('.')
- del parts[-1]
- if len(parts) > 1 and parts[-1] != 'bar':
- # foo.cpython-34m.so => foo, but foo.bar.so => foo.bar
- del parts[-1]
- name = '.'.join(parts)
- # foo_d => foo (Python 2 debug builds)
- if name.endswith('_d') and hasattr(sys, 'gettotalrefcount'):
- name = name[:-2]
- name += '.SO'
- if name.startswith('pycparser') and name.endswith('.egg'):
- continue # no clue why this shows up sometimes and not others
- if name == '.eggs':
- continue # seems new in 3.5, ignore it
- assert name in content, "found unexpected file %r" % (
- os.path.join(curdir, name),)
- value = content.pop(name)
- if value is None:
- assert name.endswith('.SO') or (
- os.path.isfile(os.path.join(curdir, name)))
- else:
- subdir = os.path.join(curdir, name)
- assert os.path.isdir(subdir)
- if value == '?':
- continue
- found_so = self.check_produced_files(value, subdir) or found_so
- assert content == {}, "files or dirs not produced in %r: %r" % (
- curdir, content.keys())
- return found_so
-
- @chdir_to_tmp
- def test_empty(self):
- self.check_produced_files({})
-
- @chdir_to_tmp
- def test_abi_emit_python_code_1(self):
- ffi = cffi.FFI()
- ffi.set_source("package_name_1.mymod", None)
- ffi.emit_python_code('xyz.py')
- self.check_produced_files({'xyz.py': None})
-
- @chdir_to_tmp
- def test_abi_emit_python_code_2(self):
- ffi = cffi.FFI()
- ffi.set_source("package_name_1.mymod", None)
- py.test.raises(IOError, ffi.emit_python_code, 'unexisting/xyz.py')
-
- @from_outside
- def test_abi_emit_python_code_3(self):
- ffi = cffi.FFI()
- ffi.set_source("package_name_1.mymod", None)
- ffi.emit_python_code(str(self.udir.join('xyt.py')))
- self.check_produced_files({'xyt.py': None})
-
- @chdir_to_tmp
- def test_abi_compile_1(self):
- ffi = cffi.FFI()
- ffi.set_source("mod_name_in_package.mymod", None)
- x = ffi.compile()
- self.check_produced_files({'mod_name_in_package': {'mymod.py': None}})
- assert x == os.path.join('.', 'mod_name_in_package', 'mymod.py')
-
- @chdir_to_tmp
- def test_abi_compile_2(self):
- ffi = cffi.FFI()
- ffi.set_source("mod_name_in_package.mymod", None)
- x = ffi.compile('build2')
- self.check_produced_files({'build2': {
- 'mod_name_in_package': {'mymod.py': None}}})
- assert x == os.path.join('build2', 'mod_name_in_package', 'mymod.py')
-
- @from_outside
- def test_abi_compile_3(self):
- ffi = cffi.FFI()
- ffi.set_source("mod_name_in_package.mymod", None)
- tmpdir = str(self.udir.join('build3'))
- x = ffi.compile(tmpdir)
- self.check_produced_files({'build3': {
- 'mod_name_in_package': {'mymod.py': None}}})
- assert x == os.path.join(tmpdir, 'mod_name_in_package', 'mymod.py')
-
- @chdir_to_tmp
- def test_api_emit_c_code_1(self):
- ffi = cffi.FFI()
- ffi.set_source("package_name_1.mymod", "/*code would be here*/")
- ffi.emit_c_code('xyz.c')
- self.check_produced_files({'xyz.c': None})
-
- @chdir_to_tmp
- def test_api_emit_c_code_2(self):
- ffi = cffi.FFI()
- ffi.set_source("package_name_1.mymod", "/*code would be here*/")
- py.test.raises(IOError, ffi.emit_c_code, 'unexisting/xyz.c')
-
- @from_outside
- def test_api_emit_c_code_3(self):
- ffi = cffi.FFI()
- ffi.set_source("package_name_1.mymod", "/*code would be here*/")
- ffi.emit_c_code(str(self.udir.join('xyu.c')))
- self.check_produced_files({'xyu.c': None})
-
- @chdir_to_tmp
- def test_api_compile_1(self):
- ffi = cffi.FFI()
- ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
- x = ffi.compile()
- if sys.platform != 'win32':
- sofile = self.check_produced_files({
- 'mod_name_in_package': {'mymod.SO': None,
- 'mymod.c': None,
- 'mymod.o': None}})
- assert os.path.isabs(x) and os.path.samefile(x, sofile)
- else:
- self.check_produced_files({
- 'mod_name_in_package': {'mymod.SO': None,
- 'mymod.c': None},
- 'Release': '?'})
-
- @chdir_to_tmp
- def test_api_compile_2(self):
- ffi = cffi.FFI()
- ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
- x = ffi.compile('output')
- if sys.platform != 'win32':
- sofile = self.check_produced_files({
- 'output': {'mod_name_in_package': {'mymod.SO': None,
- 'mymod.c': None,
- 'mymod.o': None}}})
- assert os.path.isabs(x) and os.path.samefile(x, sofile)
- else:
- self.check_produced_files({
- 'output': {'mod_name_in_package': {'mymod.SO': None,
- 'mymod.c': None},
- 'Release': '?'}})
-
- @from_outside
- def test_api_compile_3(self):
- ffi = cffi.FFI()
- ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
- x = ffi.compile(str(self.udir.join('foo')))
- if sys.platform != 'win32':
- sofile = self.check_produced_files({
- 'foo': {'mod_name_in_package': {'mymod.SO': None,
- 'mymod.c': None,
- 'mymod.o': None}}})
- assert os.path.isabs(x) and os.path.samefile(x, sofile)
- else:
- self.check_produced_files({
- 'foo': {'mod_name_in_package': {'mymod.SO': None,
- 'mymod.c': None},
- 'Release': '?'}})
-
- @chdir_to_tmp
- def test_api_compile_explicit_target_1(self):
- ffi = cffi.FFI()
- ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
- x = ffi.compile(target="foo.bar.*")
- if sys.platform != 'win32':
- sofile = self.check_produced_files({
- 'mod_name_in_package': {'foo.bar.SO': None,
- 'mymod.c': None,
- 'mymod.o': None}})
- assert os.path.isabs(x) and os.path.samefile(x, sofile)
- else:
- self.check_produced_files({
- 'mod_name_in_package': {'foo.bar.SO': None,
- 'mymod.c': None},
- 'Release': '?'})
-
- @chdir_to_tmp
- def test_api_compile_explicit_target_3(self):
- ffi = cffi.FFI()
- ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
- x = ffi.compile(target="foo.bar.baz")
- if sys.platform != 'win32':
- self.check_produced_files({
- 'mod_name_in_package': {'foo.bar.baz': None,
- 'mymod.c': None,
- 'mymod.o': None}})
- sofile = os.path.join(str(self.udir),
- 'mod_name_in_package', 'foo.bar.baz')
- assert os.path.isabs(x) and os.path.samefile(x, sofile)
- else:
- self.check_produced_files({
- 'mod_name_in_package': {'foo.bar.baz': None,
- 'mymod.c': None},
- 'Release': '?'})
-
- @chdir_to_tmp
- def test_api_distutils_extension_1(self):
- ffi = cffi.FFI()
- ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
- ext = ffi.distutils_extension()
- self.check_produced_files({'build': {
- 'mod_name_in_package': {'mymod.c': None}}})
- if hasattr(os.path, 'samefile'):
- assert os.path.samefile(ext.sources[0],
- 'build/mod_name_in_package/mymod.c')
-
- @from_outside
- def test_api_distutils_extension_2(self):
- ffi = cffi.FFI()
- ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
- ext = ffi.distutils_extension(str(self.udir.join('foo')))
- self.check_produced_files({'foo': {
- 'mod_name_in_package': {'mymod.c': None}}})
- if hasattr(os.path, 'samefile'):
- assert os.path.samefile(ext.sources[0],
- str(self.udir.join('foo/mod_name_in_package/mymod.c')))
-
-
- def _make_distutils_api(self):
- os.mkdir("src")
- os.mkdir(os.path.join("src", "pack1"))
- with open(os.path.join("src", "pack1", "__init__.py"), "w") as f:
- pass
- with open("setup.py", "w") as f:
- f.write("""if 1:
- # https://bugs.python.org/issue23246
- import sys
- if sys.platform == 'win32':
- try:
- import setuptools
- except ImportError:
- pass
-
- import cffi
- ffi = cffi.FFI()
- ffi.set_source("pack1.mymod", "/*code would be here*/")
-
- from distutils.core import setup
- setup(name='example1',
- version='0.1',
- packages=['pack1'],
- package_dir={'': 'src'},
- ext_modules=[ffi.distutils_extension()])
- """)
-
- @chdir_to_tmp
- def test_distutils_api_1(self):
- self._make_distutils_api()
- self.run(["setup.py", "build"])
- self.check_produced_files({'setup.py': None,
- 'build': '?',
- 'src': {'pack1': {'__init__.py': None}}})
-
- @chdir_to_tmp
- def test_distutils_api_2(self):
- self._make_distutils_api()
- self.run(["setup.py", "build_ext", "-i"])
- self.check_produced_files({'setup.py': None,
- 'build': '?',
- 'src': {'pack1': {'__init__.py': None,
- 'mymod.SO': None}}})
-
- def _make_setuptools_abi(self):
- self._prepare_setuptools()
- os.mkdir("src0")
- os.mkdir(os.path.join("src0", "pack2"))
- with open(os.path.join("src0", "pack2", "__init__.py"), "w") as f:
- pass
- with open(os.path.join("src0", "pack2", "_build.py"), "w") as f:
- f.write("""if 1:
- import cffi
- ffi = cffi.FFI()
- ffi.set_source("pack2.mymod", None)
- """)
- with open("setup.py", "w") as f:
- f.write("""if 1:
- from setuptools import setup
- setup(name='example1',
- version='0.1',
- packages=['pack2'],
- package_dir={'': 'src0'},
- cffi_modules=["src0/pack2/_build.py:ffi"])
- """)
-
- @chdir_to_tmp
- def test_setuptools_abi_1(self):
- self._make_setuptools_abi()
- self.run(["setup.py", "build"])
- self.check_produced_files({'setup.py': None,
- 'build': '?',
- 'src0': {'pack2': {'__init__.py': None,
- '_build.py': None}}})
-
- @chdir_to_tmp
- def test_setuptools_abi_2(self):
- self._make_setuptools_abi()
- self.run(["setup.py", "build_ext", "-i"])
- self.check_produced_files({'setup.py': None,
- 'src0': {'pack2': {'__init__.py': None,
- '_build.py': None,
- 'mymod.py': None}}})
-
- def _make_setuptools_api(self):
- self._prepare_setuptools()
- os.mkdir("src1")
- os.mkdir(os.path.join("src1", "pack3"))
- with open(os.path.join("src1", "pack3", "__init__.py"), "w") as f:
- pass
- with open(os.path.join("src1", "pack3", "_build.py"), "w") as f:
- f.write("""if 1:
- import cffi
- ffi = cffi.FFI()
- ffi.set_source("pack3.mymod", "/*code would be here*/")
- ffi._hi_there = 42
- """)
- with open("setup.py", "w") as f:
- f.write("from __future__ import print_function\n"
- """if 1:
- from setuptools import setup
- from distutils.command.build_ext import build_ext
- import os
-
- class TestBuildExt(build_ext):
- def pre_run(self, ext, ffi):
- print('_make_setuptools_api: in pre_run:', end=" ")
- assert ffi._hi_there == 42
- assert ext.name == "pack3.mymod"
- fn = os.path.join(os.path.dirname(self.build_lib),
- '..', 'see_me')
- print('creating %r' % (fn,))
- open(fn, 'w').close()
-
- setup(name='example1',
- version='0.1',
- packages=['pack3'],
- package_dir={'': 'src1'},
- cffi_modules=["src1/pack3/_build.py:ffi"],
- cmdclass={'build_ext': TestBuildExt},
- )
- """)
-
- @chdir_to_tmp
- def test_setuptools_api_1(self):
- self._make_setuptools_api()
- self.run(["setup.py", "build"])
- self.check_produced_files({'setup.py': None,
- 'build': '?',
- 'see_me': None,
- 'src1': {'pack3': {'__init__.py': None,
- '_build.py': None}}})
-
- @chdir_to_tmp
- def test_setuptools_api_2(self):
- self._make_setuptools_api()
- self.run(["setup.py", "build_ext", "-i"])
- self.check_produced_files({'setup.py': None,
- 'build': '?',
- 'see_me': None,
- 'src1': {'pack3': {'__init__.py': None,
- '_build.py': None,
- 'mymod.SO': None}}})