1import py
2from cffi import FFI, VerificationError, CDefError
3from cffi.recompiler import make_py_source
4from testing.udir import udir
5
6
7def test_simple():
8    ffi = FFI()
9    ffi.cdef("int close(int); static const int BB = 42; int somevar;")
10    target = udir.join('test_simple.py')
11    make_py_source(ffi, 'test_simple', str(target))
12    assert target.read() == r"""# auto-generated file
13import _cffi_backend
14
15ffi = _cffi_backend.FFI('test_simple',
16    _version = 0x2601,
17    _types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F',
18    _globals = (b'\xFF\xFF\xFF\x1FBB',42,b'\x00\x00\x00\x23close',0,b'\x00\x00\x01\x21somevar',0),
19)
20"""
21
22def test_global_constant():
23    ffi = FFI()
24    ffi.cdef("static const long BB; static const float BF = 12;")
25    target = udir.join('test_valid_global_constant.py')
26    make_py_source(ffi, 'test_valid_global_constant', str(target))
27    assert target.read() == r"""# auto-generated file
28import _cffi_backend
29
30ffi = _cffi_backend.FFI('test_valid_global_constant',
31    _version = 0x2601,
32    _types = b'\x00\x00\x0D\x01\x00\x00\x09\x01',
33    _globals = (b'\x00\x00\x01\x25BB',0,b'\x00\x00\x00\x25BF',0),
34)
35"""
36
37def test_invalid_global_constant_3():
38    ffi = FFI()
39    e = py.test.raises(CDefError, ffi.cdef, "#define BB 12.34")
40    assert str(e.value).startswith(
41        "only supports one of the following syntax:")
42
43def test_invalid_dotdotdot_in_macro():
44    ffi = FFI()
45    ffi.cdef("#define FOO ...")
46    target = udir.join('test_invalid_dotdotdot_in_macro.py')
47    e = py.test.raises(VerificationError, make_py_source, ffi,
48                       'test_invalid_dotdotdot_in_macro', str(target))
49    assert str(e.value) == ("macro FOO: cannot use the syntax '...' in "
50                            "'#define FOO ...' when using the ABI mode")
51
52def test_typename():
53    ffi = FFI()
54    ffi.cdef("typedef int foobar_t;")
55    target = udir.join('test_typename.py')
56    make_py_source(ffi, 'test_typename', str(target))
57    assert target.read() == r"""# auto-generated file
58import _cffi_backend
59
60ffi = _cffi_backend.FFI('test_typename',
61    _version = 0x2601,
62    _types = b'\x00\x00\x07\x01',
63    _typenames = (b'\x00\x00\x00\x00foobar_t',),
64)
65"""
66
67def test_enum():
68    ffi = FFI()
69    ffi.cdef("enum myenum_e { AA, BB, CC=-42 };")
70    target = udir.join('test_enum.py')
71    make_py_source(ffi, 'test_enum', str(target))
72    assert target.read() == r"""# auto-generated file
73import _cffi_backend
74
75ffi = _cffi_backend.FFI('test_enum',
76    _version = 0x2601,
77    _types = b'\x00\x00\x00\x0B',
78    _globals = (b'\xFF\xFF\xFF\x0BAA',0,b'\xFF\xFF\xFF\x0BBB',1,b'\xFF\xFF\xFF\x0BCC',-42),
79    _enums = (b'\x00\x00\x00\x00\x00\x00\x00\x15myenum_e\x00AA,BB,CC',),
80)
81"""
82
83def test_struct():
84    ffi = FFI()
85    ffi.cdef("struct foo_s { int a; signed char b[]; }; struct bar_s;")
86    target = udir.join('test_struct.py')
87    make_py_source(ffi, 'test_struct', str(target))
88    assert target.read() == r"""# auto-generated file
89import _cffi_backend
90
91ffi = _cffi_backend.FFI('test_struct',
92    _version = 0x2601,
93    _types = b'\x00\x00\x07\x01\x00\x00\x03\x01\x00\x00\x01\x07\x00\x00\x00\x09\x00\x00\x01\x09',
94    _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')),
95)
96"""
97
98def test_include():
99    ffi = FFI()
100    ffi.cdef("#define ABC 123")
101    ffi.set_source('test_include', None)
102    target = udir.join('test_include.py')
103    make_py_source(ffi, 'test_include', str(target))
104    assert target.read() == r"""# auto-generated file
105import _cffi_backend
106
107ffi = _cffi_backend.FFI('test_include',
108    _version = 0x2601,
109    _types = b'',
110    _globals = (b'\xFF\xFF\xFF\x1FABC',123,),
111)
112"""
113    #
114    ffi2 = FFI()
115    ffi2.include(ffi)
116    target2 = udir.join('test2_include.py')
117    make_py_source(ffi2, 'test2_include', str(target2))
118    assert target2.read() == r"""# auto-generated file
119import _cffi_backend
120from test_include import ffi as _ffi0
121
122ffi = _cffi_backend.FFI('test2_include',
123    _version = 0x2601,
124    _types = b'',
125    _includes = (_ffi0,),
126)
127"""
128
129def test_negative_constant():
130    ffi = FFI()
131    ffi.cdef("static const int BB = -42;")
132    target = udir.join('test_negative_constant.py')
133    make_py_source(ffi, 'test_negative_constant', str(target))
134    assert target.read() == r"""# auto-generated file
135import _cffi_backend
136
137ffi = _cffi_backend.FFI('test_negative_constant',
138    _version = 0x2601,
139    _types = b'',
140    _globals = (b'\xFF\xFF\xFF\x1FBB',-42,),
141)
142"""
143
144def test_struct_included():
145    baseffi = FFI()
146    baseffi.cdef("struct foo_s { int x; };")
147    baseffi.set_source('test_struct_included_base', None)
148    #
149    ffi = FFI()
150    ffi.include(baseffi)
151    target = udir.join('test_struct_included.py')
152    make_py_source(ffi, 'test_struct_included', str(target))
153    assert target.read() == r"""# auto-generated file
154import _cffi_backend
155from test_struct_included_base import ffi as _ffi0
156
157ffi = _cffi_backend.FFI('test_struct_included',
158    _version = 0x2601,
159    _types = b'\x00\x00\x00\x09',
160    _struct_unions = ((b'\x00\x00\x00\x00\x00\x00\x00\x08foo_s',),),
161    _includes = (_ffi0,),
162)
163"""
164
165def test_no_cross_include():
166    baseffi = FFI()
167    baseffi.set_source('test_no_cross_include_base', "..source..")
168    #
169    ffi = FFI()
170    ffi.include(baseffi)
171    target = udir.join('test_no_cross_include.py')
172    py.test.raises(VerificationError, make_py_source,
173                   ffi, 'test_no_cross_include', str(target))
174
175def test_array():
176    ffi = FFI()
177    ffi.cdef("typedef int32_t my_array_t[42];")
178    target = udir.join('test_array.py')
179    make_py_source(ffi, 'test_array', str(target))
180    assert target.read() == r"""# auto-generated file
181import _cffi_backend
182
183ffi = _cffi_backend.FFI('test_array',
184    _version = 0x2601,
185    _types = b'\x00\x00\x15\x01\x00\x00\x00\x05\x00\x00\x00\x2A',
186    _typenames = (b'\x00\x00\x00\x01my_array_t',),
187)
188"""
189
190def test_array_overflow():
191    ffi = FFI()
192    ffi.cdef("typedef int32_t my_array_t[3000000000];")
193    target = udir.join('test_array_overflow.py')
194    py.test.raises(OverflowError, make_py_source,
195                   ffi, 'test_array_overflow', str(target))
196
197def test_global_var():
198    ffi = FFI()
199    ffi.cdef("int myglob;")
200    target = udir.join('test_global_var.py')
201    make_py_source(ffi, 'test_global_var', str(target))
202    assert target.read() == r"""# auto-generated file
203import _cffi_backend
204
205ffi = _cffi_backend.FFI('test_global_var',
206    _version = 0x2601,
207    _types = b'\x00\x00\x07\x01',
208    _globals = (b'\x00\x00\x00\x21myglob',0,),
209)
210"""
211
212def test_bitfield():
213    ffi = FFI()
214    ffi.cdef("struct foo_s { int y:10; short x:5; };")
215    target = udir.join('test_bitfield.py')
216    make_py_source(ffi, 'test_bitfield', str(target))
217    assert target.read() == r"""# auto-generated file
218import _cffi_backend
219
220ffi = _cffi_backend.FFI('test_bitfield',
221    _version = 0x2601,
222    _types = b'\x00\x00\x07\x01\x00\x00\x05\x01\x00\x00\x00\x09',
223    _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'),),
224)
225"""
226