summaryrefslogtreecommitdiff
path: root/testing/cffi1/test_re_python.py
diff options
context:
space:
mode:
Diffstat (limited to 'testing/cffi1/test_re_python.py')
-rw-r--r--testing/cffi1/test_re_python.py256
1 files changed, 256 insertions, 0 deletions
diff --git a/testing/cffi1/test_re_python.py b/testing/cffi1/test_re_python.py
new file mode 100644
index 0000000..377c29b
--- /dev/null
+++ b/testing/cffi1/test_re_python.py
@@ -0,0 +1,256 @@
+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, ...);
+ int globalvar42;
+ const int globalconst42;
+ const char *const globalconsthello = "hello";
+ int no_such_function(int);
+ 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 NVGcolor { union { float rgba[4]; struct { float r,g,b,a; }; }; };
+ """)
+ 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
+ #
+ 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