from cffi import FFI class FakeBackend(object): def nonstandard_integer_types(self): return {} def sizeof(self, name): return 1 def load_library(self, name): assert "libc" in name or "libm" in name return FakeLibrary() def new_function_type(self, args, result, has_varargs): return '' % (', '.join(args), result, has_varargs) def new_primitive_type(self, name): assert name == name.lower() return '<%s>' % name def new_pointer_type(self, itemtype): return '' % (itemtype,) def new_struct_type(self, name): return FakeStruct(name) def complete_struct_or_union(self, s, fields, tp=None): assert isinstance(s, FakeStruct) s.fields = fields def new_array_type(self, ptrtype, length): return '' % (ptrtype, length) class FakeStruct(object): def __init__(self, name): self.name = name def __str__(self): return ', '.join([y + x for x, y, z in self.fields]) class FakeLibrary(object): def load_function(self, BType, name): return FakeFunction(BType, name) class FakeFunction(object): def __init__(self, BType, name): self.BType = BType self.name = name def test_simple(): ffi = FFI(backend=FakeBackend()) ffi.cdef("double sin(double x);") m = ffi.dlopen("m") func = m.sin # should be a callable on real backends assert func.name == 'sin' assert func.BType == '), , False>' def test_pipe(): ffi = FFI(backend=FakeBackend()) ffi.cdef("int pipe(int pipefd[2]);") C = ffi.dlopen(None) func = C.pipe assert func.name == 'pipe' assert func.BType == '>), , False>' def test_vararg(): ffi = FFI(backend=FakeBackend()) ffi.cdef("short foo(int, ...);") C = ffi.dlopen(None) func = C.foo assert func.name == 'foo' assert func.BType == '), , True>' def test_no_args(): ffi = FFI(backend=FakeBackend()) ffi.cdef(""" int foo(void); """) C = ffi.dlopen(None) assert C.foo.BType == ', False>' def test_typedef(): ffi = FFI(backend=FakeBackend()) ffi.cdef(""" typedef unsigned int UInt; typedef UInt UIntReally; UInt foo(void); """) C = ffi.dlopen(None) assert ffi.typeof("UIntReally") == '' assert C.foo.BType == ', False>' def test_typedef_more_complex(): ffi = FFI(backend=FakeBackend()) ffi.cdef(""" typedef struct { int a, b; } foo_t, *foo_p; int foo(foo_p[]); """) C = ffi.dlopen(None) assert str(ffi.typeof("foo_t")) == 'a, b' assert ffi.typeof("foo_p") == 'a, b>' assert C.foo.BType == ('a, b>>), , False>') def test_typedef_array_force_pointer(): ffi = FFI(backend=FakeBackend()) ffi.cdef(""" typedef int array_t[5]; """) type = ffi._parser.parse_type("array_t", force_pointer=True) BType = ffi._get_cached_btype(type) assert BType == '> x 5>' def test_typedef_array_convert_array_to_pointer(): ffi = FFI(backend=FakeBackend()) ffi.cdef(""" typedef int (*fn_t)(int[5]); """) type = ffi._parser.parse_type("fn_t") BType = ffi._get_cached_btype(type) assert BType == '>), , False>' def test_remove_comments(): ffi = FFI(backend=FakeBackend()) ffi.cdef(""" double /*comment here*/ sin // blah blah /* multi- line- //comment */ ( // foo double // bar /* <- ignored, because it's in a comment itself x, double/*several*//*comment*/y) /*on the same line*/ ; """) m = ffi.dlopen("m") func = m.sin assert func.name == 'sin' assert func.BType == ', ), , False>'