• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import py
2import pytest
3import platform, imp
4import sys, os, ctypes
5import cffi
6from testing.udir import udir
7from testing.support import *
8from cffi.recompiler import recompile
9from cffi.cffi_opcode import PRIMITIVE_TO_INDEX
10
11SIZE_OF_INT   = ctypes.sizeof(ctypes.c_int)
12SIZE_OF_LONG  = ctypes.sizeof(ctypes.c_long)
13SIZE_OF_SHORT = ctypes.sizeof(ctypes.c_short)
14SIZE_OF_PTR   = ctypes.sizeof(ctypes.c_void_p)
15SIZE_OF_WCHAR = ctypes.sizeof(ctypes.c_wchar)
16
17
18def setup_module():
19    global ffi, construction_params
20    ffi1 = cffi.FFI()
21    DEFS = r"""
22        struct repr { short a, b, c; };
23        struct simple { int a; short b, c; };
24        struct array { int a[2]; char b[3]; };
25        struct recursive { int value; struct recursive *next; };
26        union simple_u { int a; short b, c; };
27        union init_u { char a; int b; };
28        struct four_s { int a; short b, c, d; };
29        union four_u { int a; short b, c, d; };
30        struct string { const char *name; };
31        struct ustring { const wchar_t *name; };
32        struct voidp { void *p; int *q; short *r; };
33        struct ab { int a, b; };
34        struct abc { int a, b, c; };
35
36        /* don't use A0, B0, CC0, D0 because termios.h might be included
37           and it has its own #defines for these names */
38        enum foq { cffiA0, cffiB0, cffiCC0, cffiD0 };
39        enum bar { A1, B1=-2, CC1, D1, E1 };
40        enum baz { A2=0x1000, B2=0x2000 };
41        enum foo2 { A3, B3, C3, D3 };
42        struct bar_with_e { enum foo2 e; };
43        enum noncont { A4, B4=42, C4 };
44        enum etypes {A5='!', B5='\'', C5=0x10, D5=010, E5=- 0x10, F5=-010};
45        typedef enum { Value0 = 0 } e_t, *pe_t;
46        enum e_noninj { AA3=0, BB3=0, CC3=0, DD3=0 };
47        enum e_prev { AA4, BB4=2, CC4=4, DD4=BB4, EE4, FF4=CC4, GG4=FF4 };
48
49        struct nesting { struct abc d, e; };
50        struct array2 { int a, b; int c[99]; };
51        struct align { char a; short b; char c; };
52        struct bitfield { int a:10, b:20, c:3; };
53        typedef enum { AA2, BB2, CC2 } foo_e_t;
54        typedef struct { foo_e_t f:2; } bfenum_t;
55        typedef struct { int a; } anon_foo_t;
56        typedef struct { char b, c; } anon_bar_t;
57        typedef struct named_foo_s { int a; } named_foo_t, *named_foo_p;
58        typedef struct { int a; } unnamed_foo_t, *unnamed_foo_p;
59        struct nonpacked { char a; int b; };
60        struct array0 { int len; short data[0]; };
61        struct array_no_length { int x; int a[]; };
62
63        struct nested_anon {
64            struct { int a, b; };
65            union { int c, d; };
66        };
67        struct nested_field_ofs_s {
68            struct { int a; char b; };
69            union { char c; };
70        };
71        union nested_anon_u {
72            struct { int a, b; };
73            union { int c, d; };
74        };
75        struct abc50 { int a, b; int c[50]; };
76        struct ints_and_bitfield { int a,b,c,d,e; int x:1; };
77    """
78    DEFS_PACKED = """
79        struct is_packed { char a; int b; } /*here*/;
80    """
81    if sys.platform == "win32":
82        DEFS = DEFS.replace('data[0]', 'data[1]')   # not supported
83        CCODE = (DEFS + "\n#pragma pack(push,1)\n" + DEFS_PACKED +
84                 "\n#pragma pack(pop)\n")
85    else:
86        CCODE = (DEFS +
87                 DEFS_PACKED.replace('/*here*/', '__attribute__((packed))'))
88
89    ffi1.cdef(DEFS)
90    ffi1.cdef(DEFS_PACKED, packed=True)
91    ffi1.set_source("test_new_ffi_1", CCODE)
92
93    outputfilename = recompile(ffi1, "test_new_ffi_1", CCODE,
94                               tmpdir=str(udir))
95    module = imp.load_dynamic("test_new_ffi_1", outputfilename)
96    ffi = module.ffi
97    construction_params = (ffi1, CCODE)
98
99
100class TestNewFFI1:
101
102    def test_integer_ranges(self):
103        for (c_type, size) in [('char', 1),
104                               ('short', 2),
105                               ('short int', 2),
106                               ('', 4),
107                               ('int', 4),
108                               ('long', SIZE_OF_LONG),
109                               ('long int', SIZE_OF_LONG),
110                               ('long long', 8),
111                               ('long long int', 8),
112                               ]:
113            for unsigned in [None, False, True]:
114                c_decl = {None: '',
115                          False: 'signed ',
116                          True: 'unsigned '}[unsigned] + c_type
117                if c_decl == 'char' or c_decl == '':
118                    continue
119                self._test_int_type(ffi, c_decl, size, unsigned)
120
121    def test_fixedsize_int(self):
122        for size in [1, 2, 4, 8]:
123            self._test_int_type(ffi, 'int%d_t' % (8*size), size, False)
124            self._test_int_type(ffi, 'uint%d_t' % (8*size), size, True)
125        self._test_int_type(ffi, 'intptr_t', SIZE_OF_PTR, False)
126        self._test_int_type(ffi, 'uintptr_t', SIZE_OF_PTR, True)
127        self._test_int_type(ffi, 'ptrdiff_t', SIZE_OF_PTR, False)
128        self._test_int_type(ffi, 'size_t', SIZE_OF_PTR, True)
129        self._test_int_type(ffi, 'ssize_t', SIZE_OF_PTR, False)
130
131    def _test_int_type(self, ffi, c_decl, size, unsigned):
132        if unsigned:
133            min = 0
134            max = (1 << (8*size)) - 1
135        else:
136            min = -(1 << (8*size-1))
137            max = (1 << (8*size-1)) - 1
138        min = int(min)
139        max = int(max)
140        p = ffi.cast(c_decl, min)
141        assert p == min
142        assert bool(p) is bool(min)
143        assert int(p) == min
144        p = ffi.cast(c_decl, max)
145        assert int(p) == max
146        p = ffi.cast(c_decl, long(max))
147        assert int(p) == max
148        q = ffi.cast(c_decl, min - 1)
149        assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
150        q = ffi.cast(c_decl, long(min - 1))
151        assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
152        assert q == p
153        assert int(q) == int(p)
154        assert hash(q) == hash(p)
155        c_decl_ptr = '%s *' % c_decl
156        py.test.raises(OverflowError, ffi.new, c_decl_ptr, min - 1)
157        py.test.raises(OverflowError, ffi.new, c_decl_ptr, max + 1)
158        py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(min - 1))
159        py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(max + 1))
160        assert ffi.new(c_decl_ptr, min)[0] == min
161        assert ffi.new(c_decl_ptr, max)[0] == max
162        assert ffi.new(c_decl_ptr, long(min))[0] == min
163        assert ffi.new(c_decl_ptr, long(max))[0] == max
164
165    def test_new_unsupported_type(self):
166        e = py.test.raises(TypeError, ffi.new, "int")
167        assert str(e.value) == "expected a pointer or array ctype, got 'int'"
168
169    def test_new_single_integer(self):
170        p = ffi.new("int *")     # similar to ffi.new("int[1]")
171        assert p[0] == 0
172        p[0] = -123
173        assert p[0] == -123
174        p = ffi.new("int *", -42)
175        assert p[0] == -42
176        assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
177
178    def test_new_array_no_arg(self):
179        p = ffi.new("int[10]")
180        # the object was zero-initialized:
181        for i in range(10):
182            assert p[i] == 0
183
184    def test_array_indexing(self):
185        p = ffi.new("int[10]")
186        p[0] = 42
187        p[9] = 43
188        assert p[0] == 42
189        assert p[9] == 43
190        with pytest.raises(IndexError):
191            p[10]
192        with pytest.raises(IndexError):
193            p[10] = 44
194        with pytest.raises(IndexError):
195            p[-1]
196        with pytest.raises(IndexError):
197            p[-1] = 44
198
199    def test_new_array_args(self):
200        # this tries to be closer to C: where we say "int x[5] = {10, 20, ..}"
201        # then here we must enclose the items in a list
202        p = ffi.new("int[5]", [10, 20, 30, 40, 50])
203        assert p[0] == 10
204        assert p[1] == 20
205        assert p[2] == 30
206        assert p[3] == 40
207        assert p[4] == 50
208        p = ffi.new("int[4]", [25])
209        assert p[0] == 25
210        assert p[1] == 0     # follow C convention rather than LuaJIT's
211        assert p[2] == 0
212        assert p[3] == 0
213        p = ffi.new("int[4]", [ffi.cast("int", -5)])
214        assert p[0] == -5
215        assert repr(p) == "<cdata 'int[4]' owning %d bytes>" % (4*SIZE_OF_INT)
216
217    def test_new_array_varsize(self):
218        p = ffi.new("int[]", 10)     # a single integer is the length
219        assert p[9] == 0
220        with pytest.raises(IndexError):
221            p[10]
222        #
223        py.test.raises(TypeError, ffi.new, "int[]")
224        #
225        p = ffi.new("int[]", [-6, -7])    # a list is all the items, like C
226        assert p[0] == -6
227        assert p[1] == -7
228        with pytest.raises(IndexError):
229            p[2]
230        assert repr(p) == "<cdata 'int[]' owning %d bytes>" % (2*SIZE_OF_INT)
231        #
232        p = ffi.new("int[]", 0)
233        with pytest.raises(IndexError):
234            p[0]
235        py.test.raises(ValueError, ffi.new, "int[]", -1)
236        assert repr(p) == "<cdata 'int[]' owning 0 bytes>"
237
238    def test_pointer_init(self):
239        n = ffi.new("int *", 24)
240        a = ffi.new("int *[10]", [ffi.NULL, ffi.NULL, n, n, ffi.NULL])
241        for i in range(10):
242            if i not in (2, 3):
243                assert a[i] == ffi.NULL
244        assert a[2] == a[3] == n
245
246    def test_cannot_cast(self):
247        a = ffi.new("short int[10]")
248        e = py.test.raises(TypeError, ffi.new, "long int **", a)
249        msg = str(e.value)
250        assert "'short[10]'" in msg and "'long *'" in msg
251
252    def test_new_pointer_to_array(self):
253        a = ffi.new("int[4]", [100, 102, 104, 106])
254        p = ffi.new("int **", a)
255        assert p[0] == ffi.cast("int *", a)
256        assert p[0][2] == 104
257        p = ffi.cast("int *", a)
258        assert p[0] == 100
259        assert p[1] == 102
260        assert p[2] == 104
261        assert p[3] == 106
262        # keepalive: a
263
264    def test_pointer_direct(self):
265        p = ffi.cast("int*", 0)
266        assert p is not None
267        assert bool(p) is False
268        assert p == ffi.cast("int*", 0)
269        assert p != None
270        assert repr(p) == "<cdata 'int *' NULL>"
271        a = ffi.new("int[]", [123, 456])
272        p = ffi.cast("int*", a)
273        assert bool(p) is True
274        assert p == ffi.cast("int*", a)
275        assert p != ffi.cast("int*", 0)
276        assert p[0] == 123
277        assert p[1] == 456
278
279    def test_repr(self):
280        typerepr = "<ctype '%s'>"
281        p = ffi.cast("short unsigned int", 0)
282        assert repr(p) == "<cdata 'unsigned short' 0>"
283        assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
284        p = ffi.cast("unsigned short int", 0)
285        assert repr(p) == "<cdata 'unsigned short' 0>"
286        assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
287        p = ffi.cast("int*", 0)
288        assert repr(p) == "<cdata 'int *' NULL>"
289        assert repr(ffi.typeof(p)) == typerepr % "int *"
290        #
291        p = ffi.new("int*")
292        assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
293        assert repr(ffi.typeof(p)) == typerepr % "int *"
294        p = ffi.new("int**")
295        assert repr(p) == "<cdata 'int * *' owning %d bytes>" % SIZE_OF_PTR
296        assert repr(ffi.typeof(p)) == typerepr % "int * *"
297        p = ffi.new("int [2]")
298        assert repr(p) == "<cdata 'int[2]' owning %d bytes>" % (2*SIZE_OF_INT)
299        assert repr(ffi.typeof(p)) == typerepr % "int[2]"
300        p = ffi.new("int*[2][3]")
301        assert repr(p) == "<cdata 'int *[2][3]' owning %d bytes>" % (
302            6*SIZE_OF_PTR)
303        assert repr(ffi.typeof(p)) == typerepr % "int *[2][3]"
304        p = ffi.new("struct repr *")
305        assert repr(p) == "<cdata 'struct repr *' owning %d bytes>" % (
306            3*SIZE_OF_SHORT)
307        assert repr(ffi.typeof(p)) == typerepr % "struct repr *"
308        #
309        q = ffi.cast("short", -123)
310        assert repr(q) == "<cdata 'short' -123>"
311        assert repr(ffi.typeof(q)) == typerepr % "short"
312        p = ffi.new("int*")
313        q = ffi.cast("short*", p)
314        assert repr(q).startswith("<cdata 'short *' 0x")
315        assert repr(ffi.typeof(q)) == typerepr % "short *"
316        p = ffi.new("int [2]")
317        q = ffi.cast("int*", p)
318        assert repr(q).startswith("<cdata 'int *' 0x")
319        assert repr(ffi.typeof(q)) == typerepr % "int *"
320        p = ffi.new("struct repr*")
321        q = ffi.cast("struct repr *", p)
322        assert repr(q).startswith("<cdata 'struct repr *' 0x")
323        assert repr(ffi.typeof(q)) == typerepr % "struct repr *"
324        prevrepr = repr(q)
325        q = q[0]
326        assert repr(q) == prevrepr.replace(' *', ' &')
327        assert repr(ffi.typeof(q)) == typerepr % "struct repr"
328
329    def test_new_array_of_array(self):
330        p = ffi.new("int[3][4]")
331        p[0][0] = 10
332        p[2][3] = 33
333        assert p[0][0] == 10
334        assert p[2][3] == 33
335        with pytest.raises(IndexError):
336            p[1][-1]
337
338    def test_constructor_array_of_array(self):
339        p = ffi.new("int[3][2]", [[10, 11], [12, 13], [14, 15]])
340        assert p[2][1] == 15
341
342    def test_new_array_of_pointer_1(self):
343        n = ffi.new("int*", 99)
344        p = ffi.new("int*[4]")
345        p[3] = n
346        a = p[3]
347        assert repr(a).startswith("<cdata 'int *' 0x")
348        assert a[0] == 99
349
350    def test_new_array_of_pointer_2(self):
351        n = ffi.new("int[1]", [99])
352        p = ffi.new("int*[4]")
353        p[3] = n
354        a = p[3]
355        assert repr(a).startswith("<cdata 'int *' 0x")
356        assert a[0] == 99
357
358    def test_char(self):
359        assert ffi.new("char*", b"\xff")[0] == b'\xff'
360        assert ffi.new("char*")[0] == b'\x00'
361        assert int(ffi.cast("char", 300)) == 300 - 256
362        assert not bool(ffi.cast("char", 0))
363        assert bool(ffi.cast("char", 1))
364        assert bool(ffi.cast("char", 255))
365        py.test.raises(TypeError, ffi.new, "char*", 32)
366        py.test.raises(TypeError, ffi.new, "char*", u+"x")
367        py.test.raises(TypeError, ffi.new, "char*", b"foo")
368        #
369        p = ffi.new("char[]", [b'a', b'b', b'\x9c'])
370        assert len(p) == 3
371        assert p[0] == b'a'
372        assert p[1] == b'b'
373        assert p[2] == b'\x9c'
374        p[0] = b'\xff'
375        assert p[0] == b'\xff'
376        p = ffi.new("char[]", b"abcd")
377        assert len(p) == 5
378        assert p[4] == b'\x00'    # like in C, with:  char[] p = "abcd";
379        #
380        p = ffi.new("char[4]", b"ab")
381        assert len(p) == 4
382        assert [p[i] for i in range(4)] == [b'a', b'b', b'\x00', b'\x00']
383        p = ffi.new("char[2]", b"ab")
384        assert len(p) == 2
385        assert [p[i] for i in range(2)] == [b'a', b'b']
386        py.test.raises(IndexError, ffi.new, "char[2]", b"abc")
387
388    def check_wchar_t(self, ffi):
389        try:
390            ffi.cast("wchar_t", 0)
391        except NotImplementedError:
392            py.test.skip("NotImplementedError: wchar_t")
393
394    def test_wchar_t(self):
395        self.check_wchar_t(ffi)
396        assert ffi.new("wchar_t*", u+'x')[0] == u+'x'
397        assert ffi.new("wchar_t*", u+'\u1234')[0] == u+'\u1234'
398        if SIZE_OF_WCHAR > 2:
399            assert ffi.new("wchar_t*", u+'\U00012345')[0] == u+'\U00012345'
400        else:
401            py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345')
402        assert ffi.new("wchar_t*")[0] == u+'\x00'
403        assert int(ffi.cast("wchar_t", 300)) == 300
404        assert not bool(ffi.cast("wchar_t", 0))
405        assert bool(ffi.cast("wchar_t", 1))
406        assert bool(ffi.cast("wchar_t", 65535))
407        if SIZE_OF_WCHAR > 2:
408            assert bool(ffi.cast("wchar_t", 65536))
409        py.test.raises(TypeError, ffi.new, "wchar_t*", 32)
410        py.test.raises(TypeError, ffi.new, "wchar_t*", "foo")
411        #
412        p = ffi.new("wchar_t[]", [u+'a', u+'b', u+'\u1234'])
413        assert len(p) == 3
414        assert p[0] == u+'a'
415        assert p[1] == u+'b' and type(p[1]) is unicode
416        assert p[2] == u+'\u1234'
417        p[0] = u+'x'
418        assert p[0] == u+'x' and type(p[0]) is unicode
419        p[1] = u+'\u1357'
420        assert p[1] == u+'\u1357'
421        p = ffi.new("wchar_t[]", u+"abcd")
422        assert len(p) == 5
423        assert p[4] == u+'\x00'
424        p = ffi.new("wchar_t[]", u+"a\u1234b")
425        assert len(p) == 4
426        assert p[1] == u+'\u1234'
427        #
428        p = ffi.new("wchar_t[]", u+'\U00023456')
429        if SIZE_OF_WCHAR == 2:
430            assert len(p) == 3
431            assert p[0] == u+'\ud84d'
432            assert p[1] == u+'\udc56'
433            assert p[2] == u+'\x00'
434        else:
435            assert len(p) == 2
436            assert p[0] == u+'\U00023456'
437            assert p[1] == u+'\x00'
438        #
439        p = ffi.new("wchar_t[4]", u+"ab")
440        assert len(p) == 4
441        assert [p[i] for i in range(4)] == [u+'a', u+'b', u+'\x00', u+'\x00']
442        p = ffi.new("wchar_t[2]", u+"ab")
443        assert len(p) == 2
444        assert [p[i] for i in range(2)] == [u+'a', u+'b']
445        py.test.raises(IndexError, ffi.new, "wchar_t[2]", u+"abc")
446
447    def test_none_as_null_doesnt_work(self):
448        p = ffi.new("int*[1]")
449        assert p[0] is not None
450        assert p[0] != None
451        assert p[0] == ffi.NULL
452        assert repr(p[0]) == "<cdata 'int *' NULL>"
453        #
454        n = ffi.new("int*", 99)
455        p = ffi.new("int*[]", [n])
456        assert p[0][0] == 99
457        with pytest.raises(TypeError):
458            p[0] = None
459        p[0] = ffi.NULL
460        assert p[0] == ffi.NULL
461
462    def test_float(self):
463        p = ffi.new("float[]", [-2, -2.5])
464        assert p[0] == -2.0
465        assert p[1] == -2.5
466        p[1] += 17.75
467        assert p[1] == 15.25
468        #
469        p = ffi.new("float*", 15.75)
470        assert p[0] == 15.75
471        py.test.raises(TypeError, int, p)
472        py.test.raises(TypeError, float, p)
473        p[0] = 0.0
474        assert bool(p) is True
475        #
476        p = ffi.new("float*", 1.1)
477        f = p[0]
478        assert f != 1.1      # because of rounding effect
479        assert abs(f - 1.1) < 1E-7
480        #
481        INF = 1E200 * 1E200
482        assert 1E200 != INF
483        p[0] = 1E200
484        assert p[0] == INF     # infinite, not enough precision
485
486    def test_struct_simple(self):
487        s = ffi.new("struct simple*")
488        assert s.a == s.b == s.c == 0
489        s.b = -23
490        assert s.b == -23
491        with pytest.raises(OverflowError):
492            s.b = 32768
493        #
494        s = ffi.new("struct simple*", [-2, -3])
495        assert s.a == -2
496        assert s.b == -3
497        assert s.c == 0
498        with pytest.raises((AttributeError, TypeError)):
499            del s.a
500        assert repr(s) == "<cdata 'struct simple *' owning %d bytes>" % (
501            SIZE_OF_INT + 2 * SIZE_OF_SHORT)
502        #
503        py.test.raises(ValueError, ffi.new, "struct simple*", [1, 2, 3, 4])
504
505    def test_constructor_struct_from_dict(self):
506        s = ffi.new("struct simple*", {'b': 123, 'c': 456})
507        assert s.a == 0
508        assert s.b == 123
509        assert s.c == 456
510        py.test.raises(KeyError, ffi.new, "struct simple*", {'d': 456})
511
512    def test_struct_pointer(self):
513        s = ffi.new("struct simple*")
514        assert s[0].a == s[0].b == s[0].c == 0
515        s[0].b = -23
516        assert s[0].b == s.b == -23
517        with pytest.raises(OverflowError):
518            s[0].b = -32769
519        with pytest.raises(IndexError):
520            s[1]
521
522    def test_struct_opaque(self):
523        py.test.raises(ffi.error, ffi.new, "struct baz*")
524        # should 'ffi.new("struct baz **") work?  it used to, but it was
525        # not particularly useful...
526        py.test.raises(ffi.error, ffi.new, "struct baz**")
527
528    def test_pointer_to_struct(self):
529        s = ffi.new("struct simple *")
530        s.a = -42
531        assert s[0].a == -42
532        p = ffi.new("struct simple **", s)
533        assert p[0].a == -42
534        assert p[0][0].a == -42
535        p[0].a = -43
536        assert s.a == -43
537        assert s[0].a == -43
538        p[0][0].a = -44
539        assert s.a == -44
540        assert s[0].a == -44
541        s.a = -45
542        assert p[0].a == -45
543        assert p[0][0].a == -45
544        s[0].a = -46
545        assert p[0].a == -46
546        assert p[0][0].a == -46
547
548    def test_constructor_struct_of_array(self):
549        s = ffi.new("struct array *", [[10, 11], [b'a', b'b', b'c']])
550        assert s.a[1] == 11
551        assert s.b[2] == b'c'
552        s.b[1] = b'X'
553        assert s.b[0] == b'a'
554        assert s.b[1] == b'X'
555        assert s.b[2] == b'c'
556
557    def test_recursive_struct(self):
558        s = ffi.new("struct recursive*")
559        t = ffi.new("struct recursive*")
560        s.value = 123
561        s.next = t
562        t.value = 456
563        assert s.value == 123
564        assert s.next.value == 456
565
566    def test_union_simple(self):
567        u = ffi.new("union simple_u*")
568        assert u.a == u.b == u.c == 0
569        u.b = -23
570        assert u.b == -23
571        assert u.a != 0
572        with pytest.raises(OverflowError):
573            u.b = 32768
574        #
575        u = ffi.new("union simple_u*", [-2])
576        assert u.a == -2
577        with pytest.raises((AttributeError, TypeError)):
578            del u.a
579        assert repr(u) == "<cdata 'union simple_u *' owning %d bytes>" % (
580            SIZE_OF_INT,)
581
582    def test_union_opaque(self):
583        py.test.raises(ffi.error, ffi.new, "union baz*")
584        # should 'ffi.new("union baz **") work?  it used to, but it was
585        # not particularly useful...
586        py.test.raises(ffi.error, ffi.new, "union baz**")
587
588    def test_union_initializer(self):
589        py.test.raises(TypeError, ffi.new, "union init_u*", b'A')
590        py.test.raises(TypeError, ffi.new, "union init_u*", 5)
591        py.test.raises(ValueError, ffi.new, "union init_u*", [b'A', 5])
592        u = ffi.new("union init_u*", [b'A'])
593        assert u.a == b'A'
594        py.test.raises(TypeError, ffi.new, "union init_u*", [1005])
595        u = ffi.new("union init_u*", {'b': 12345})
596        assert u.b == 12345
597        u = ffi.new("union init_u*", [])
598        assert u.a == b'\x00'
599        assert u.b == 0
600
601    def test_sizeof_type(self):
602        for c_type, expected_size in [
603            ('char', 1),
604            ('unsigned int', 4),
605            ('char *', SIZE_OF_PTR),
606            ('int[5]', 20),
607            ('struct four_s', 12),
608            ('union four_u', 4),
609            ]:
610            size = ffi.sizeof(c_type)
611            assert size == expected_size, (size, expected_size, ctype)
612
613    def test_sizeof_cdata(self):
614        assert ffi.sizeof(ffi.new("short*")) == SIZE_OF_PTR
615        assert ffi.sizeof(ffi.cast("short", 123)) == SIZE_OF_SHORT
616        #
617        a = ffi.new("int[]", [10, 11, 12, 13, 14])
618        assert len(a) == 5
619        assert ffi.sizeof(a) == 5 * SIZE_OF_INT
620
621    def test_string_from_char_pointer(self):
622        x = ffi.new("char*", b"x")
623        assert str(x) == repr(x)
624        assert ffi.string(x) == b"x"
625        assert ffi.string(ffi.new("char*", b"\x00")) == b""
626        py.test.raises(TypeError, ffi.new, "char*", unicode("foo"))
627
628    def test_unicode_from_wchar_pointer(self):
629        self.check_wchar_t(ffi)
630        x = ffi.new("wchar_t*", u+"x")
631        assert unicode(x) == unicode(repr(x))
632        assert ffi.string(x) == u+"x"
633        assert ffi.string(ffi.new("wchar_t*", u+"\x00")) == u+""
634
635    def test_string_from_char_array(self):
636        p = ffi.new("char[]", b"hello.")
637        p[5] = b'!'
638        assert ffi.string(p) == b"hello!"
639        p[6] = b'?'
640        assert ffi.string(p) == b"hello!?"
641        p[3] = b'\x00'
642        assert ffi.string(p) == b"hel"
643        assert ffi.string(p, 2) == b"he"
644        with pytest.raises(IndexError):
645            p[7] = b'X'
646        #
647        a = ffi.new("char[]", b"hello\x00world")
648        assert len(a) == 12
649        p = ffi.cast("char *", a)
650        assert ffi.string(p) == b'hello'
651
652    def test_string_from_wchar_array(self):
653        self.check_wchar_t(ffi)
654        assert ffi.string(ffi.cast("wchar_t", "x")) == u+"x"
655        assert ffi.string(ffi.cast("wchar_t", u+"x")) == u+"x"
656        x = ffi.cast("wchar_t", "x")
657        assert str(x) == repr(x)
658        assert ffi.string(x) == u+"x"
659        #
660        p = ffi.new("wchar_t[]", u+"hello.")
661        p[5] = u+'!'
662        assert ffi.string(p) == u+"hello!"
663        p[6] = u+'\u04d2'
664        assert ffi.string(p) == u+"hello!\u04d2"
665        p[3] = u+'\x00'
666        assert ffi.string(p) == u+"hel"
667        assert ffi.string(p, 123) == u+"hel"
668        with pytest.raises(IndexError):
669            p[7] = u+'X'
670        #
671        a = ffi.new("wchar_t[]", u+"hello\x00world")
672        assert len(a) == 12
673        p = ffi.cast("wchar_t *", a)
674        assert ffi.string(p) == u+'hello'
675        assert ffi.string(p, 123) == u+'hello'
676        assert ffi.string(p, 5) == u+'hello'
677        assert ffi.string(p, 2) == u+'he'
678
679    def test_fetch_const_char_p_field(self):
680        # 'const' is ignored so far, in the declaration of 'struct string'
681        t = ffi.new("const char[]", b"testing")
682        s = ffi.new("struct string*", [t])
683        assert type(s.name) not in (bytes, str, unicode)
684        assert ffi.string(s.name) == b"testing"
685        with pytest.raises(TypeError):
686            s.name = None
687        s.name = ffi.NULL
688        assert s.name == ffi.NULL
689
690    def test_fetch_const_wchar_p_field(self):
691        # 'const' is ignored so far
692        self.check_wchar_t(ffi)
693        t = ffi.new("const wchar_t[]", u+"testing")
694        s = ffi.new("struct ustring*", [t])
695        assert type(s.name) not in (bytes, str, unicode)
696        assert ffi.string(s.name) == u+"testing"
697        s.name = ffi.NULL
698        assert s.name == ffi.NULL
699
700    def test_voidp(self):
701        py.test.raises(TypeError, ffi.new, "void*")
702        p = ffi.new("void **")
703        assert p[0] == ffi.NULL
704        a = ffi.new("int[]", [10, 11, 12])
705        p = ffi.new("void **", a)
706        vp = p[0]
707        with pytest.raises(TypeError):
708            vp[0]
709        py.test.raises(TypeError, ffi.new, "short **", a)
710        #
711        s = ffi.new("struct voidp *")
712        s.p = a    # works
713        s.q = a    # works
714        with pytest.raises(TypeError):
715            s.r = a    # fails
716        b = ffi.cast("int *", a)
717        s.p = b    # works
718        s.q = b    # works
719        with pytest.raises(TypeError):
720            s.r = b    # fails
721
722    def test_functionptr_simple(self):
723        py.test.raises(TypeError, ffi.callback, "int(*)(int)", 0)
724        def cb(n):
725            return n + 1
726        cb.__qualname__ = 'cb'
727        p = ffi.callback("int(*)(int)", cb)
728        res = p(41)     # calling an 'int(*)(int)', i.e. a function pointer
729        assert res == 42 and type(res) is int
730        res = p(ffi.cast("int", -41))
731        assert res == -40 and type(res) is int
732        assert repr(p).startswith(
733            "<cdata 'int(*)(int)' calling <function cb at 0x")
734        assert ffi.typeof(p) is ffi.typeof("int(*)(int)")
735        q = ffi.new("int(**)(int)", p)
736        assert repr(q) == "<cdata 'int(* *)(int)' owning %d bytes>" % (
737            SIZE_OF_PTR)
738        with pytest.raises(TypeError):
739            q(43)
740        res = q[0](43)
741        assert res == 44
742        q = ffi.cast("int(*)(int)", p)
743        assert repr(q).startswith("<cdata 'int(*)(int)' 0x")
744        res = q(45)
745        assert res == 46
746
747    def test_functionptr_advanced(self):
748        t = ffi.typeof("int(*(*)(int))(int)")
749        assert repr(t) == "<ctype '%s'>" % "int(*(*)(int))(int)"
750
751    def test_functionptr_voidptr_return(self):
752        def cb():
753            return ffi.NULL
754        p = ffi.callback("void*(*)()", cb)
755        res = p()
756        assert res is not None
757        assert res == ffi.NULL
758        int_ptr = ffi.new('int*')
759        void_ptr = ffi.cast('void*', int_ptr)
760        def cb():
761            return void_ptr
762        p = ffi.callback("void*(*)()", cb)
763        res = p()
764        assert res == void_ptr
765
766    def test_functionptr_intptr_return(self):
767        def cb():
768            return ffi.NULL
769        p = ffi.callback("int*(*)()", cb)
770        res = p()
771        assert res == ffi.NULL
772        int_ptr = ffi.new('int*')
773        def cb():
774            return int_ptr
775        p = ffi.callback("int*(*)()", cb)
776        res = p()
777        assert repr(res).startswith("<cdata 'int *' 0x")
778        assert res == int_ptr
779        int_array_ptr = ffi.new('int[1]')
780        def cb():
781            return int_array_ptr
782        p = ffi.callback("int*(*)()", cb)
783        res = p()
784        assert repr(res).startswith("<cdata 'int *' 0x")
785        assert res == int_array_ptr
786
787    def test_functionptr_void_return(self):
788        def foo():
789            pass
790        foo_cb = ffi.callback("void foo()", foo)
791        result = foo_cb()
792        assert result is None
793
794    def test_char_cast(self):
795        p = ffi.cast("int", b'\x01')
796        assert ffi.typeof(p) is ffi.typeof("int")
797        assert int(p) == 1
798        p = ffi.cast("int", ffi.cast("char", b"a"))
799        assert int(p) == ord("a")
800        p = ffi.cast("int", ffi.cast("char", b"\x80"))
801        assert int(p) == 0x80     # "char" is considered unsigned in this case
802        p = ffi.cast("int", b"\x81")
803        assert int(p) == 0x81
804
805    def test_wchar_cast(self):
806        self.check_wchar_t(ffi)
807        p = ffi.cast("int", ffi.cast("wchar_t", u+'\u1234'))
808        assert int(p) == 0x1234
809        p = ffi.cast("long long", ffi.cast("wchar_t", -1))
810        if SIZE_OF_WCHAR == 2:      # 2 bytes, unsigned
811            assert int(p) == 0xffff
812        elif (sys.platform.startswith('linux') and
813              platform.machine().startswith('x86')):   # known to be signed
814            assert int(p) == -1
815        else:                     # in general, it can be either signed or not
816            assert int(p) in [-1, 0xffffffff]  # e.g. on arm, both cases occur
817        p = ffi.cast("int", u+'\u1234')
818        assert int(p) == 0x1234
819
820    def test_cast_array_to_charp(self):
821        a = ffi.new("short int[]", [0x1234, 0x5678])
822        p = ffi.cast("char*", a)
823        data = b''.join([p[i] for i in range(4)])
824        if sys.byteorder == 'little':
825            assert data == b'\x34\x12\x78\x56'
826        else:
827            assert data == b'\x12\x34\x56\x78'
828
829    def test_cast_between_pointers(self):
830        a = ffi.new("short int[]", [0x1234, 0x5678])
831        p = ffi.cast("short*", a)
832        p2 = ffi.cast("int*", p)
833        q = ffi.cast("char*", p2)
834        data = b''.join([q[i] for i in range(4)])
835        if sys.byteorder == 'little':
836            assert data == b'\x34\x12\x78\x56'
837        else:
838            assert data == b'\x12\x34\x56\x78'
839
840    def test_cast_pointer_and_int(self):
841        a = ffi.new("short int[]", [0x1234, 0x5678])
842        l1 = ffi.cast("intptr_t", a)
843        p = ffi.cast("short*", a)
844        l2 = ffi.cast("intptr_t", p)
845        assert int(l1) == int(l2) != 0
846        q = ffi.cast("short*", l1)
847        assert q == ffi.cast("short*", int(l1))
848        assert q[0] == 0x1234
849        assert int(ffi.cast("intptr_t", ffi.NULL)) == 0
850
851    def test_cast_functionptr_and_int(self):
852        def cb(n):
853            return n + 1
854        a = ffi.callback("int(*)(int)", cb)
855        p = ffi.cast("void *", a)
856        assert p
857        b = ffi.cast("int(*)(int)", p)
858        assert b(41) == 42
859        assert a == b
860        assert hash(a) == hash(b)
861
862    def test_callback_crash(self):
863        def cb(n):
864            raise Exception
865        a = ffi.callback("int(*)(int)", cb, error=42)
866        res = a(1)    # and the error reported to stderr
867        assert res == 42
868
869    def test_structptr_argument(self):
870        def cb(p):
871            return p[0].a * 1000 + p[0].b * 100 + p[1].a * 10 + p[1].b
872        a = ffi.callback("int(*)(struct ab[])", cb)
873        res = a([[5, 6], {'a': 7, 'b': 8}])
874        assert res == 5678
875        res = a([[5], {'b': 8}])
876        assert res == 5008
877
878    def test_array_argument_as_list(self):
879        seen = []
880        def cb(argv):
881            seen.append(ffi.string(argv[0]))
882            seen.append(ffi.string(argv[1]))
883        a = ffi.callback("void(*)(char *[])", cb)
884        a([ffi.new("char[]", b"foobar"), ffi.new("char[]", b"baz")])
885        assert seen == [b"foobar", b"baz"]
886
887    def test_cast_float(self):
888        a = ffi.cast("float", 12)
889        assert float(a) == 12.0
890        a = ffi.cast("float", 12.5)
891        assert float(a) == 12.5
892        a = ffi.cast("float", b"A")
893        assert float(a) == ord("A")
894        a = ffi.cast("int", 12.9)
895        assert int(a) == 12
896        a = ffi.cast("char", 66.9 + 256)
897        assert ffi.string(a) == b"B"
898        #
899        a = ffi.cast("float", ffi.cast("int", 12))
900        assert float(a) == 12.0
901        a = ffi.cast("float", ffi.cast("double", 12.5))
902        assert float(a) == 12.5
903        a = ffi.cast("float", ffi.cast("char", b"A"))
904        assert float(a) == ord("A")
905        a = ffi.cast("int", ffi.cast("double", 12.9))
906        assert int(a) == 12
907        a = ffi.cast("char", ffi.cast("double", 66.9 + 256))
908        assert ffi.string(a) == b"B"
909
910    def test_enum(self):
911        # enum foq { A0, B0, CC0, D0 };
912        assert ffi.string(ffi.cast("enum foq", 0)) == "cffiA0"
913        assert ffi.string(ffi.cast("enum foq", 2)) == "cffiCC0"
914        assert ffi.string(ffi.cast("enum foq", 3)) == "cffiD0"
915        assert ffi.string(ffi.cast("enum foq", 4)) == "4"
916        # enum bar { A1, B1=-2, CC1, D1, E1 };
917        assert ffi.string(ffi.cast("enum bar", 0)) == "A1"
918        assert ffi.string(ffi.cast("enum bar", -2)) == "B1"
919        assert ffi.string(ffi.cast("enum bar", -1)) == "CC1"
920        assert ffi.string(ffi.cast("enum bar", 1)) == "E1"
921        assert ffi.cast("enum bar", -2) == ffi.cast("enum bar", -2)
922        assert ffi.cast("enum foq", 0) == ffi.cast("enum bar", 0)
923        assert ffi.cast("enum bar", 0) == ffi.cast("int", 0)
924        assert repr(ffi.cast("enum bar", -1)) == "<cdata 'enum bar' -1: CC1>"
925        assert repr(ffi.cast("enum foq", -1)) == (  # enums are unsigned, if
926            "<cdata 'enum foq' 4294967295>") or (   # they contain no neg value
927                sys.platform == "win32")            # (but not on msvc)
928        # enum baz { A2=0x1000, B2=0x2000 };
929        assert ffi.string(ffi.cast("enum baz", 0x1000)) == "A2"
930        assert ffi.string(ffi.cast("enum baz", 0x2000)) == "B2"
931
932    def test_enum_in_struct(self):
933        # enum foo2 { A3, B3, C3, D3 };
934        # struct bar_with_e { enum foo2 e; };
935        s = ffi.new("struct bar_with_e *")
936        s.e = 0
937        assert s.e == 0
938        s.e = 3
939        assert s.e == 3
940        assert s[0].e == 3
941        s[0].e = 2
942        assert s.e == 2
943        assert s[0].e == 2
944        s.e = ffi.cast("enum foo2", -1)
945        assert s.e in (4294967295, -1)     # two choices
946        assert s[0].e in (4294967295, -1)
947        s.e = s.e
948        with pytest.raises(TypeError):
949            s.e = 'B3'
950        with pytest.raises(TypeError):
951            s.e = '2'
952        with pytest.raises(TypeError):
953            s.e = '#2'
954        with pytest.raises(TypeError):
955            s.e = '#7'
956
957    def test_enum_non_contiguous(self):
958        # enum noncont { A4, B4=42, C4 };
959        assert ffi.string(ffi.cast("enum noncont", 0)) == "A4"
960        assert ffi.string(ffi.cast("enum noncont", 42)) == "B4"
961        assert ffi.string(ffi.cast("enum noncont", 43)) == "C4"
962        invalid_value = ffi.cast("enum noncont", 2)
963        assert int(invalid_value) == 2
964        assert ffi.string(invalid_value) == "2"
965
966    def test_enum_char_hex_oct(self):
967        # enum etypes {A5='!', B5='\'', C5=0x10, D5=010, E5=- 0x10, F5=-010};
968        assert ffi.string(ffi.cast("enum etypes", ord('!'))) == "A5"
969        assert ffi.string(ffi.cast("enum etypes", ord("'"))) == "B5"
970        assert ffi.string(ffi.cast("enum etypes", 16)) == "C5"
971        assert ffi.string(ffi.cast("enum etypes", 8)) == "D5"
972        assert ffi.string(ffi.cast("enum etypes", -16)) == "E5"
973        assert ffi.string(ffi.cast("enum etypes", -8)) == "F5"
974
975    def test_array_of_struct(self):
976        s = ffi.new("struct ab[1]")
977        with pytest.raises(AttributeError):
978            s.b
979        with pytest.raises(AttributeError):
980            s.b = 412
981        s[0].b = 412
982        assert s[0].b == 412
983        with pytest.raises(IndexError):
984            s[1]
985
986    def test_pointer_to_array(self):
987        p = ffi.new("int(**)[5]")
988        assert repr(p) == "<cdata 'int(* *)[5]' owning %d bytes>" % SIZE_OF_PTR
989
990    def test_iterate_array(self):
991        a = ffi.new("char[]", b"hello")
992        assert list(a) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
993        assert list(iter(a)) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
994        #
995        py.test.raises(TypeError, iter, ffi.cast("char *", a))
996        py.test.raises(TypeError, list, ffi.cast("char *", a))
997        py.test.raises(TypeError, iter, ffi.new("int *"))
998        py.test.raises(TypeError, list, ffi.new("int *"))
999
1000    def test_offsetof(self):
1001        # struct abc { int a, b, c; };
1002        assert ffi.offsetof("struct abc", "a") == 0
1003        assert ffi.offsetof("struct abc", "b") == 4
1004        assert ffi.offsetof("struct abc", "c") == 8
1005
1006    def test_offsetof_nested(self):
1007        # struct nesting { struct abc d, e; };
1008        assert ffi.offsetof("struct nesting", "e") == 12
1009        py.test.raises(KeyError, ffi.offsetof, "struct nesting", "e.a")
1010        assert ffi.offsetof("struct nesting", "e", "a") == 12
1011        assert ffi.offsetof("struct nesting", "e", "b") == 16
1012        assert ffi.offsetof("struct nesting", "e", "c") == 20
1013
1014    def test_offsetof_array(self):
1015        assert ffi.offsetof("int[]", 51) == 51 * ffi.sizeof("int")
1016        assert ffi.offsetof("int *", 51) == 51 * ffi.sizeof("int")
1017        # struct array2 { int a, b; int c[99]; };
1018        assert ffi.offsetof("struct array2", "c") == 2 * ffi.sizeof("int")
1019        assert ffi.offsetof("struct array2", "c", 0) == 2 * ffi.sizeof("int")
1020        assert ffi.offsetof("struct array2", "c", 51) == 53 * ffi.sizeof("int")
1021
1022    def test_alignof(self):
1023        # struct align { char a; short b; char c; };
1024        assert ffi.alignof("int") == 4
1025        assert ffi.alignof("double") in (4, 8)
1026        assert ffi.alignof("struct align") == 2
1027
1028    def test_bitfield(self):
1029        # struct bitfield { int a:10, b:20, c:3; };
1030        assert ffi.sizeof("struct bitfield") == 8
1031        s = ffi.new("struct bitfield *")
1032        s.a = 511
1033        with pytest.raises(OverflowError):
1034            s.a = 512
1035        with pytest.raises(OverflowError):
1036            s[0].a = 512
1037        assert s.a == 511
1038        s.a = -512
1039        with pytest.raises(OverflowError):
1040            s.a = -513
1041        with pytest.raises(OverflowError):
1042            s[0].a = -513
1043        assert s.a == -512
1044        s.c = 3
1045        assert s.c == 3
1046        with pytest.raises(OverflowError):
1047            s.c = 4
1048        with pytest.raises(OverflowError):
1049            s[0].c = 4
1050        s.c = -4
1051        assert s.c == -4
1052
1053    def test_bitfield_enum(self):
1054        # typedef enum { AA1, BB1, CC1 } foo_e_t;
1055        # typedef struct { foo_e_t f:2; } bfenum_t;
1056        if sys.platform == "win32":
1057            py.test.skip("enums are not unsigned")
1058        s = ffi.new("bfenum_t *")
1059        s.f = 2
1060        assert s.f == 2
1061
1062    def test_anonymous_struct(self):
1063        # typedef struct { int a; } anon_foo_t;
1064        # typedef struct { char b, c; } anon_bar_t;
1065        f = ffi.new("anon_foo_t *", [12345])
1066        b = ffi.new("anon_bar_t *", [b"B", b"C"])
1067        assert f.a == 12345
1068        assert b.b == b"B"
1069        assert b.c == b"C"
1070        assert repr(b).startswith("<cdata 'anon_bar_t *'")
1071
1072    def test_struct_with_two_usages(self):
1073        # typedef struct named_foo_s { int a; } named_foo_t, *named_foo_p;
1074        # typedef struct { int a; } unnamed_foo_t, *unnamed_foo_p;
1075        f = ffi.new("named_foo_t *", [12345])
1076        ps = ffi.new("named_foo_p[]", [f])
1077        f = ffi.new("unnamed_foo_t *", [12345])
1078        ps = ffi.new("unnamed_foo_p[]", [f])
1079
1080    def test_pointer_arithmetic(self):
1081        s = ffi.new("short[]", list(range(100, 110)))
1082        p = ffi.cast("short *", s)
1083        assert p[2] == 102
1084        assert p+1 == p+1
1085        assert p+1 != p+0
1086        assert p == p+0 == p-0
1087        assert (p+1)[0] == 101
1088        assert (p+19)[-10] == 109
1089        assert (p+5) - (p+1) == 4
1090        assert p == s+0
1091        assert p+1 == s+1
1092
1093    def test_pointer_comparison(self):
1094        s = ffi.new("short[]", list(range(100)))
1095        p = ffi.cast("short *", s)
1096        assert (p <  s) is False
1097        assert (p <= s) is True
1098        assert (p == s) is True
1099        assert (p != s) is False
1100        assert (p >  s) is False
1101        assert (p >= s) is True
1102        assert (s <  p) is False
1103        assert (s <= p) is True
1104        assert (s == p) is True
1105        assert (s != p) is False
1106        assert (s >  p) is False
1107        assert (s >= p) is True
1108        q = p + 1
1109        assert (q <  s) is False
1110        assert (q <= s) is False
1111        assert (q == s) is False
1112        assert (q != s) is True
1113        assert (q >  s) is True
1114        assert (q >= s) is True
1115        assert (s <  q) is True
1116        assert (s <= q) is True
1117        assert (s == q) is False
1118        assert (s != q) is True
1119        assert (s >  q) is False
1120        assert (s >= q) is False
1121        assert (q <  p) is False
1122        assert (q <= p) is False
1123        assert (q == p) is False
1124        assert (q != p) is True
1125        assert (q >  p) is True
1126        assert (q >= p) is True
1127        assert (p <  q) is True
1128        assert (p <= q) is True
1129        assert (p == q) is False
1130        assert (p != q) is True
1131        assert (p >  q) is False
1132        assert (p >= q) is False
1133        #
1134        assert (None == s) is False
1135        assert (None != s) is True
1136        assert (s == None) is False
1137        assert (s != None) is True
1138        assert (None == q) is False
1139        assert (None != q) is True
1140        assert (q == None) is False
1141        assert (q != None) is True
1142
1143    def test_integer_comparison(self):
1144        x = ffi.cast("int", 123)
1145        y = ffi.cast("int", 456)
1146        assert x < y
1147        #
1148        z = ffi.cast("double", 78.9)
1149        assert x > z
1150        assert y > z
1151
1152    def test_ffi_buffer_ptr(self):
1153        a = ffi.new("short *", 100)
1154        try:
1155            b = ffi.buffer(a)
1156        except NotImplementedError as e:
1157            py.test.skip(str(e))
1158        content = b[:]
1159        assert len(content) == len(b) == 2
1160        if sys.byteorder == 'little':
1161            assert content == b'\x64\x00'
1162            assert b[0] == b'\x64'
1163            b[0] = b'\x65'
1164        else:
1165            assert content == b'\x00\x64'
1166            assert b[1] == b'\x64'
1167            b[1] = b'\x65'
1168        assert a[0] == 101
1169
1170    def test_ffi_buffer_array(self):
1171        a = ffi.new("int[]", list(range(100, 110)))
1172        try:
1173            b = ffi.buffer(a)
1174        except NotImplementedError as e:
1175            py.test.skip(str(e))
1176        content = b[:]
1177        if sys.byteorder == 'little':
1178            assert content.startswith(b'\x64\x00\x00\x00\x65\x00\x00\x00')
1179            b[4] = b'\x45'
1180        else:
1181            assert content.startswith(b'\x00\x00\x00\x64\x00\x00\x00\x65')
1182            b[7] = b'\x45'
1183        assert len(content) == 4 * 10
1184        assert a[1] == 0x45
1185
1186    def test_ffi_buffer_ptr_size(self):
1187        a = ffi.new("short *", 0x4243)
1188        try:
1189            b = ffi.buffer(a, 1)
1190        except NotImplementedError as e:
1191            py.test.skip(str(e))
1192        content = b[:]
1193        assert len(content) == 1
1194        if sys.byteorder == 'little':
1195            assert content == b'\x43'
1196            b[0] = b'\x62'
1197            assert a[0] == 0x4262
1198        else:
1199            assert content == b'\x42'
1200            b[0] = b'\x63'
1201            assert a[0] == 0x6343
1202
1203    def test_ffi_buffer_array_size(self):
1204        a1 = ffi.new("int[]", list(range(100, 110)))
1205        a2 = ffi.new("int[]", list(range(100, 115)))
1206        try:
1207            ffi.buffer(a1)
1208        except NotImplementedError as e:
1209            py.test.skip(str(e))
1210        assert ffi.buffer(a1)[:] == ffi.buffer(a2, 4*10)[:]
1211
1212    def test_ffi_buffer_with_file(self):
1213        import tempfile, os, array
1214        fd, filename = tempfile.mkstemp()
1215        f = os.fdopen(fd, 'r+b')
1216        a = ffi.new("int[]", list(range(1005)))
1217        try:
1218            ffi.buffer(a, 512)
1219        except NotImplementedError as e:
1220            py.test.skip(str(e))
1221        f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
1222        f.seek(0)
1223        assert f.read() == arraytostring(array.array('i', range(1000)))
1224        f.seek(0)
1225        b = ffi.new("int[]", 1005)
1226        f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
1227        assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
1228        f.close()
1229        os.unlink(filename)
1230
1231    def test_ffi_buffer_with_io(self):
1232        import io, array
1233        f = io.BytesIO()
1234        a = ffi.new("int[]", list(range(1005)))
1235        try:
1236            ffi.buffer(a, 512)
1237        except NotImplementedError as e:
1238            py.test.skip(str(e))
1239        f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
1240        f.seek(0)
1241        assert f.read() == arraytostring(array.array('i', range(1000)))
1242        f.seek(0)
1243        b = ffi.new("int[]", 1005)
1244        f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
1245        assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
1246        f.close()
1247
1248    def test_array_in_struct(self):
1249        # struct array { int a[2]; char b[3]; };
1250        p = ffi.new("struct array *")
1251        p.a[1] = 5
1252        assert p.a[1] == 5
1253        assert repr(p.a).startswith("<cdata 'int[2]' 0x")
1254
1255    def test_struct_containing_array_varsize_workaround(self):
1256        if sys.platform == "win32":
1257            py.test.skip("array of length 0 not supported")
1258        # struct array0 { int len; short data[0]; };
1259        p = ffi.new("char[]", ffi.sizeof("struct array0") + 7 * SIZE_OF_SHORT)
1260        q = ffi.cast("struct array0 *", p)
1261        assert q.len == 0
1262        # 'q.data' gets not a 'short[0]', but just a 'short *' instead
1263        assert repr(q.data).startswith("<cdata 'short *' 0x")
1264        assert q.data[6] == 0
1265        q.data[6] = 15
1266        assert q.data[6] == 15
1267
1268    def test_new_struct_containing_array_varsize(self):
1269        py.test.skip("later?")
1270        ffi.cdef("struct foo_s { int len; short data[]; };")
1271        p = ffi.new("struct foo_s *", 10)     # a single integer is the length
1272        assert p.len == 0
1273        assert p.data[9] == 0
1274        with pytest.raises(IndexError):
1275            p.data[10]
1276
1277    def test_ffi_typeof_getcname(self):
1278        assert ffi.getctype("int") == "int"
1279        assert ffi.getctype("int", 'x') == "int x"
1280        assert ffi.getctype("int*") == "int *"
1281        assert ffi.getctype("int*", '') == "int *"
1282        assert ffi.getctype("int*", 'x') == "int * x"
1283        assert ffi.getctype("int", '*') == "int *"
1284        assert ffi.getctype("int", ' * x ') == "int * x"
1285        assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *"
1286        assert ffi.getctype("int", '[5]') == "int[5]"
1287        assert ffi.getctype("int[5]", '[6]') == "int[6][5]"
1288        assert ffi.getctype("int[5]", '(*)') == "int(*)[5]"
1289        # special-case for convenience: automatically put '()' around '*'
1290        assert ffi.getctype("int[5]", '*') == "int(*)[5]"
1291        assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]"
1292        assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]"
1293
1294    def test_array_of_func_ptr(self):
1295        f = ffi.cast("int(*)(int)", 42)
1296        assert f != ffi.NULL
1297        py.test.raises(ffi.error, ffi.cast, "int(int)", 42)
1298        py.test.raises(ffi.error, ffi.new, "int([5])(int)")
1299        a = ffi.new("int(*[5])(int)", [f])
1300        assert ffi.getctype(ffi.typeof(a)) == "int(*[5])(int)"
1301        assert len(a) == 5
1302        assert a[0] == f
1303        assert a[1] == ffi.NULL
1304        py.test.raises(TypeError, ffi.cast, "int(*)(int)[5]", 0)
1305        #
1306        def cb(n):
1307            return n + 1
1308        f = ffi.callback("int(*)(int)", cb)
1309        a = ffi.new("int(*[5])(int)", [f, f])
1310        assert a[1](42) == 43
1311
1312    def test_callback_as_function_argument(self):
1313        # In C, function arguments can be declared with a function type,
1314        # which is automatically replaced with the ptr-to-function type.
1315        def cb(a, b):
1316            return chr(ord(a) + ord(b)).encode()
1317        f = ffi.callback("char cb(char, char)", cb)
1318        assert f(b'A', b'\x01') == b'B'
1319        def g(callback):
1320            return callback(b'A', b'\x01')
1321        g = ffi.callback("char g(char cb(char, char))", g)
1322        assert g(f) == b'B'
1323
1324    def test_vararg_callback(self):
1325        py.test.skip("callback with '...'")
1326        def cb(i, va_list):
1327            j = ffi.va_arg(va_list, "int")
1328            k = ffi.va_arg(va_list, "long long")
1329            return i * 2 + j * 3 + k * 5
1330        f = ffi.callback("long long cb(long i, ...)", cb)
1331        res = f(10, ffi.cast("int", 100), ffi.cast("long long", 1000))
1332        assert res == 20 + 300 + 5000
1333
1334    def test_callback_decorator(self):
1335        #
1336        @ffi.callback("long(long, long)", error=42)
1337        def cb(a, b):
1338            return a - b
1339        #
1340        assert cb(-100, -10) == -90
1341        sz = ffi.sizeof("long")
1342        assert cb((1 << (sz*8-1)) - 1, -10) == 42
1343
1344    def test_anonymous_enum(self):
1345        # typedef enum { Value0 = 0 } e_t, *pe_t;
1346        assert ffi.getctype("e_t*") == 'e_t *'
1347        assert ffi.getctype("pe_t") == 'e_t *'
1348        assert ffi.getctype("foo_e_t*") == 'foo_e_t *'
1349
1350    def test_new_ctype(self):
1351        p = ffi.new("int *")
1352        py.test.raises(TypeError, ffi.new, p)
1353        p = ffi.new(ffi.typeof("int *"), 42)
1354        assert p[0] == 42
1355
1356    def test_enum_with_non_injective_mapping(self):
1357        # enum e_noninj { AA3=0, BB3=0, CC3=0, DD3=0 };
1358        e = ffi.cast("enum e_noninj", 0)
1359        assert ffi.string(e) == "AA3"     # pick the first one arbitrarily
1360
1361    def test_enum_refer_previous_enum_value(self):
1362        # enum e_prev { AA4, BB4=2, CC4=4, DD4=BB4, EE4, FF4=CC4, GG4=FF4 };
1363        assert ffi.string(ffi.cast("enum e_prev", 2)) == "BB4"
1364        assert ffi.string(ffi.cast("enum e_prev", 3)) == "EE4"
1365        assert ffi.sizeof("char[DD4]") == 2
1366        assert ffi.sizeof("char[EE4]") == 3
1367        assert ffi.sizeof("char[FF4]") == 4
1368        assert ffi.sizeof("char[GG4]") == 4
1369
1370    def test_nested_anonymous_struct(self):
1371        # struct nested_anon {
1372        #     struct { int a, b; };
1373        #     union { int c, d; };
1374        # };
1375        assert ffi.sizeof("struct nested_anon") == 3 * SIZE_OF_INT
1376        p = ffi.new("struct nested_anon *", [1, 2, 3])
1377        assert p.a == 1
1378        assert p.b == 2
1379        assert p.c == 3
1380        assert p.d == 3
1381        p.d = 17
1382        assert p.c == 17
1383        p.b = 19
1384        assert p.a == 1
1385        assert p.b == 19
1386        assert p.c == 17
1387        assert p.d == 17
1388        p = ffi.new("struct nested_anon *", {'b': 12, 'd': 14})
1389        assert p.a == 0
1390        assert p.b == 12
1391        assert p.c == 14
1392        assert p.d == 14
1393
1394    def test_nested_field_offset_align(self):
1395        # struct nested_field_ofs_s {
1396        #    struct { int a; char b; };
1397        #    union { char c; };
1398        # };
1399        assert ffi.offsetof("struct nested_field_ofs_s", "c") == 2 * SIZE_OF_INT
1400        assert ffi.sizeof("struct nested_field_ofs_s") == 3 * SIZE_OF_INT
1401
1402    def test_nested_anonymous_union(self):
1403        # union nested_anon_u {
1404        #     struct { int a, b; };
1405        #     union { int c, d; };
1406        # };
1407        assert ffi.sizeof("union nested_anon_u") == 2 * SIZE_OF_INT
1408        p = ffi.new("union nested_anon_u *", [5])
1409        assert p.a == 5
1410        assert p.b == 0
1411        assert p.c == 5
1412        assert p.d == 5
1413        p.d = 17
1414        assert p.c == 17
1415        assert p.a == 17
1416        p.b = 19
1417        assert p.a == 17
1418        assert p.b == 19
1419        assert p.c == 17
1420        assert p.d == 17
1421        p = ffi.new("union nested_anon_u *", {'d': 14})
1422        assert p.a == 14
1423        assert p.b == 0
1424        assert p.c == 14
1425        assert p.d == 14
1426        p = ffi.new("union nested_anon_u *", {'b': 12})
1427        assert p.a == 0
1428        assert p.b == 12
1429        assert p.c == 0
1430        assert p.d == 0
1431        # we cannot specify several items in the dict, even though
1432        # in theory in this particular case it would make sense
1433        # to give both 'a' and 'b'
1434
1435    def test_cast_to_array_type(self):
1436        p = ffi.new("int[4]", [-5])
1437        q = ffi.cast("int[3]", p)
1438        assert q[0] == -5
1439        assert repr(q).startswith("<cdata 'int[3]' 0x")
1440
1441    def test_gc(self):
1442        p = ffi.new("int *", 123)
1443        seen = []
1444        def destructor(p1):
1445            assert p1 is p
1446            assert p1[0] == 123
1447            seen.append(1)
1448        q = ffi.gc(p, destructor=destructor)
1449        import gc; gc.collect()
1450        assert seen == []
1451        del q
1452        import gc; gc.collect(); gc.collect(); gc.collect()
1453        assert seen == [1]
1454
1455    def test_gc_2(self):
1456        p = ffi.new("int *", 123)
1457        seen = []
1458        q1 = ffi.gc(p, lambda p: seen.append(1))
1459        q2 = ffi.gc(q1, lambda p: seen.append(2))
1460        import gc; gc.collect()
1461        assert seen == []
1462        del q1, q2
1463        import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
1464        assert seen == [2, 1]
1465
1466    def test_gc_3(self):
1467        p = ffi.new("int *", 123)
1468        r = ffi.new("int *", 123)
1469        seen = []
1470        seen_r = []
1471        q1 = ffi.gc(p, lambda p: seen.append(1))
1472        s1 = ffi.gc(r, lambda r: seen_r.append(4))
1473        q2 = ffi.gc(q1, lambda p: seen.append(2))
1474        s2 = ffi.gc(s1, lambda r: seen_r.append(5))
1475        q3 = ffi.gc(q2, lambda p: seen.append(3))
1476        import gc; gc.collect()
1477        assert seen == []
1478        assert seen_r == []
1479        del q1, q2, q3, s2, s1
1480        import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
1481        assert seen == [3, 2, 1]
1482        assert seen_r == [5, 4]
1483
1484    def test_gc_4(self):
1485        p = ffi.new("int *", 123)
1486        seen = []
1487        q1 = ffi.gc(p, lambda p: seen.append(1))
1488        q2 = ffi.gc(q1, lambda p: seen.append(2))
1489        q3 = ffi.gc(q2, lambda p: seen.append(3))
1490        import gc; gc.collect()
1491        assert seen == []
1492        del q1, q3     # q2 remains, and has a hard ref to q1
1493        import gc; gc.collect(); gc.collect(); gc.collect()
1494        assert seen == [3]
1495
1496    def test_release(self):
1497        p = ffi.new("int[]", 123)
1498        ffi.release(p)
1499        # here, reading p[0] might give garbage or segfault...
1500        ffi.release(p)   # no effect
1501
1502    def test_release_new_allocator(self):
1503        seen = []
1504        def myalloc(size):
1505            seen.append(size)
1506            return ffi.new("char[]", b"X" * size)
1507        def myfree(raw):
1508            seen.append(raw)
1509        alloc2 = ffi.new_allocator(alloc=myalloc, free=myfree)
1510        p = alloc2("int[]", 15)
1511        assert seen == [15 * 4]
1512        ffi.release(p)
1513        assert seen == [15 * 4, p]
1514        ffi.release(p)    # no effect
1515        assert seen == [15 * 4, p]
1516        #
1517        del seen[:]
1518        p = alloc2("struct ab *")
1519        assert seen == [2 * 4]
1520        ffi.release(p)
1521        assert seen == [2 * 4, p]
1522        ffi.release(p)    # no effect
1523        assert seen == [2 * 4, p]
1524
1525    def test_CData_CType(self):
1526        assert isinstance(ffi.cast("int", 0), ffi.CData)
1527        assert isinstance(ffi.new("int *"), ffi.CData)
1528        assert not isinstance(ffi.typeof("int"), ffi.CData)
1529        assert not isinstance(ffi.cast("int", 0), ffi.CType)
1530        assert not isinstance(ffi.new("int *"), ffi.CType)
1531
1532    def test_CData_CType_2(self):
1533        assert isinstance(ffi.typeof("int"), ffi.CType)
1534
1535    def test_bool(self):
1536        assert int(ffi.cast("_Bool", 0.1)) == 1
1537        assert int(ffi.cast("_Bool", -0.0)) == 0
1538        assert int(ffi.cast("_Bool", b'\x02')) == 1
1539        assert int(ffi.cast("_Bool", b'\x00')) == 0
1540        assert int(ffi.cast("_Bool", b'\x80')) == 1
1541        assert ffi.new("_Bool *", False)[0] == 0
1542        assert ffi.new("_Bool *", 1)[0] == 1
1543        py.test.raises(OverflowError, ffi.new, "_Bool *", 2)
1544        py.test.raises(TypeError, ffi.string, ffi.cast("_Bool", 2))
1545
1546    def test_addressof(self):
1547        p = ffi.new("struct ab *")
1548        a = ffi.addressof(p[0])
1549        assert repr(a).startswith("<cdata 'struct ab *' 0x")
1550        assert a == p
1551        py.test.raises(TypeError, ffi.addressof, p)
1552        py.test.raises((AttributeError, TypeError), ffi.addressof, 5)
1553        py.test.raises(TypeError, ffi.addressof, ffi.cast("int", 5))
1554
1555    def test_addressof_field(self):
1556        p = ffi.new("struct ab *")
1557        b = ffi.addressof(p[0], 'b')
1558        assert repr(b).startswith("<cdata 'int *' 0x")
1559        assert int(ffi.cast("uintptr_t", b)) == (
1560            int(ffi.cast("uintptr_t", p)) + ffi.sizeof("int"))
1561        assert b == ffi.addressof(p, 'b')
1562        assert b != ffi.addressof(p, 'a')
1563
1564    def test_addressof_field_nested(self):
1565        # struct nesting { struct abc d, e; };
1566        p = ffi.new("struct nesting *")
1567        py.test.raises(KeyError, ffi.addressof, p[0], 'e.b')
1568        a = ffi.addressof(p[0], 'e', 'b')
1569        assert int(ffi.cast("uintptr_t", a)) == (
1570            int(ffi.cast("uintptr_t", p)) +
1571            ffi.sizeof("struct abc") + ffi.sizeof("int"))
1572
1573    def test_addressof_anonymous_struct(self):
1574        # typedef struct { int a; } anon_foo_t;
1575        p = ffi.new("anon_foo_t *")
1576        a = ffi.addressof(p[0])
1577        assert a == p
1578
1579    def test_addressof_array(self):
1580        p = ffi.new("int[52]")
1581        p0 = ffi.addressof(p)
1582        assert p0 == p
1583        assert ffi.typeof(p0) is ffi.typeof("int(*)[52]")
1584        py.test.raises(TypeError, ffi.addressof, p0)
1585        #
1586        p1 = ffi.addressof(p, 25)
1587        assert ffi.typeof(p1) is ffi.typeof("int *")
1588        assert (p1 - p) == 25
1589        assert ffi.addressof(p, 0) == p
1590
1591    def test_addressof_pointer(self):
1592        array = ffi.new("int[50]")
1593        p = ffi.cast("int *", array)
1594        py.test.raises(TypeError, ffi.addressof, p)
1595        assert ffi.addressof(p, 0) == p
1596        assert ffi.addressof(p, 25) == p + 25
1597        assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p)
1598        #
1599        array = ffi.new("struct ab[50]")
1600        p = ffi.cast("int *", array)
1601        py.test.raises(TypeError, ffi.addressof, p)
1602        assert ffi.addressof(p, 0) == p
1603        assert ffi.addressof(p, 25) == p + 25
1604        assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p)
1605
1606    def test_addressof_array_in_struct(self):
1607        # struct abc50 { int a, b; int c[50]; };
1608        p = ffi.new("struct abc50 *")
1609        p1 = ffi.addressof(p, "c", 25)
1610        assert ffi.typeof(p1) is ffi.typeof("int *")
1611        assert p1 == ffi.cast("int *", p) + 27
1612        assert ffi.addressof(p, "c") == ffi.cast("int *", p) + 2
1613        assert ffi.addressof(p, "c", 0) == ffi.cast("int *", p) + 2
1614        p2 = ffi.addressof(p, 1)
1615        assert ffi.typeof(p2) is ffi.typeof("struct abc50 *")
1616        assert p2 == p + 1
1617
1618    def test_multiple_independent_structs(self):
1619        CDEF2 = "struct ab { int x; };"
1620        ffi2 = cffi.FFI(); ffi2.cdef(CDEF2)
1621        outputfilename = recompile(ffi2, "test_multiple_independent_structs",
1622                                   CDEF2, tmpdir=str(udir))
1623        module = imp.load_dynamic("test_multiple_independent_structs",
1624                                  outputfilename)
1625        ffi1 = module.ffi
1626        foo1 = ffi1.new("struct ab *", [10])
1627        foo2 = ffi .new("struct ab *", [20, 30])
1628        assert foo1.x == 10
1629        assert foo2.a == 20
1630        assert foo2.b == 30
1631
1632    def test_include_struct_union_enum_typedef(self):
1633        ffi1, CCODE = construction_params
1634        ffi2 = cffi.FFI()
1635        ffi2.include(ffi1)
1636        outputfilename = recompile(ffi2,
1637                                   "test_include_struct_union_enum_typedef",
1638                                   CCODE, tmpdir=str(udir))
1639        module = imp.load_dynamic("test_include_struct_union_enum_typedef",
1640                                  outputfilename)
1641        ffi2 = module.ffi
1642        #
1643        p = ffi2.new("struct nonpacked *", [b'A', -43141])
1644        assert p.a == b'A'
1645        assert p.b == -43141
1646        #
1647        p = ffi.new("union simple_u *", [-52525])
1648        assert p.a == -52525
1649        #
1650        p = ffi.cast("enum foq", 2)
1651        assert ffi.string(p) == "cffiCC0"
1652        assert ffi2.sizeof("char[cffiCC0]") == 2
1653        #
1654        p = ffi.new("anon_foo_t *", [-52526])
1655        assert p.a == -52526
1656        p = ffi.new("named_foo_p", [-52527])
1657        assert p.a == -52527
1658
1659    def test_struct_packed(self):
1660        # struct nonpacked { char a; int b; };
1661        # struct is_packed { char a; int b; } __attribute__((packed));
1662        assert ffi.sizeof("struct nonpacked") == 8
1663        assert ffi.sizeof("struct is_packed") == 5
1664        assert ffi.alignof("struct nonpacked") == 4
1665        assert ffi.alignof("struct is_packed") == 1
1666        s = ffi.new("struct is_packed[2]")
1667        s[0].b = 42623381
1668        s[0].a = b'X'
1669        s[1].b = -4892220
1670        s[1].a = b'Y'
1671        assert s[0].b == 42623381
1672        assert s[0].a == b'X'
1673        assert s[1].b == -4892220
1674        assert s[1].a == b'Y'
1675
1676    def test_not_supported_bitfield_in_result(self):
1677        # struct ints_and_bitfield { int a,b,c,d,e; int x:1; };
1678        e = py.test.raises(NotImplementedError, ffi.callback,
1679                           "struct ints_and_bitfield foo(void)", lambda: 42)
1680        assert str(e.value) == ("struct ints_and_bitfield(*)(): "
1681            "callback with unsupported argument or return type or with '...'")
1682
1683    def test_inspecttype(self):
1684        assert ffi.typeof("long").kind == "primitive"
1685        assert ffi.typeof("long(*)(long, long**, ...)").cname == (
1686            "long(*)(long, long * *, ...)")
1687        assert ffi.typeof("long(*)(long, long**, ...)").ellipsis is True
1688
1689    def test_new_handle(self):
1690        o = [2, 3, 4]
1691        p = ffi.new_handle(o)
1692        assert ffi.typeof(p) == ffi.typeof("void *")
1693        assert ffi.from_handle(p) is o
1694        assert ffi.from_handle(ffi.cast("char *", p)) is o
1695        py.test.raises(RuntimeError, ffi.from_handle, ffi.NULL)
1696
1697    def test_struct_array_no_length(self):
1698        # struct array_no_length { int x; int a[]; };
1699        p = ffi.new("struct array_no_length *", [100, [200, 300, 400]])
1700        assert p.x == 100
1701        assert ffi.typeof(p.a) is ffi.typeof("int[]")   # length available
1702        assert p.a[0] == 200
1703        assert p.a[1] == 300
1704        assert p.a[2] == 400
1705        assert len(p.a) == 3
1706        assert list(p.a) == [200, 300, 400]
1707        q = ffi.cast("struct array_no_length *", p)
1708        assert ffi.typeof(q.a) is ffi.typeof("int *")   # no length available
1709        assert q.a[0] == 200
1710        assert q.a[1] == 300
1711        assert q.a[2] == 400
1712        py.test.raises(TypeError, len, q.a)
1713        py.test.raises(TypeError, list, q.a)
1714
1715    def test_all_primitives(self):
1716        assert set(PRIMITIVE_TO_INDEX) == set([
1717            "char",
1718            "short",
1719            "int",
1720            "long",
1721            "long long",
1722            "signed char",
1723            "unsigned char",
1724            "unsigned short",
1725            "unsigned int",
1726            "unsigned long",
1727            "unsigned long long",
1728            "float",
1729            "double",
1730            "long double",
1731            "wchar_t",
1732            "char16_t",
1733            "char32_t",
1734            "_Bool",
1735            "int8_t",
1736            "uint8_t",
1737            "int16_t",
1738            "uint16_t",
1739            "int32_t",
1740            "uint32_t",
1741            "int64_t",
1742            "uint64_t",
1743            "int_least8_t",
1744            "uint_least8_t",
1745            "int_least16_t",
1746            "uint_least16_t",
1747            "int_least32_t",
1748            "uint_least32_t",
1749            "int_least64_t",
1750            "uint_least64_t",
1751            "int_fast8_t",
1752            "uint_fast8_t",
1753            "int_fast16_t",
1754            "uint_fast16_t",
1755            "int_fast32_t",
1756            "uint_fast32_t",
1757            "int_fast64_t",
1758            "uint_fast64_t",
1759            "intptr_t",
1760            "uintptr_t",
1761            "intmax_t",
1762            "uintmax_t",
1763            "ptrdiff_t",
1764            "size_t",
1765            "ssize_t",
1766            'float _Complex',
1767            'double _Complex',
1768            ])
1769        for name in PRIMITIVE_TO_INDEX:
1770            x = ffi.sizeof(name)
1771            assert 1 <= x <= 16
1772
1773    def test_emit_c_code(self):
1774        ffi = cffi.FFI()
1775        ffi.set_source("foobar", "??")
1776        c_file = str(udir.join('test_emit_c_code'))
1777        ffi.emit_c_code(c_file)
1778        assert os.path.isfile(c_file)
1779
1780    def test_import_from_lib(self):
1781        ffi2 = cffi.FFI()
1782        ffi2.cdef("int myfunc(int); extern int myvar;\n#define MYFOO ...\n")
1783        outputfilename = recompile(ffi2, "_test_import_from_lib",
1784                                   "int myfunc(int x) { return x + 1; }\n"
1785                                   "int myvar = -5;\n"
1786                                   "#define MYFOO 42", tmpdir=str(udir))
1787        imp.load_dynamic("_test_import_from_lib", outputfilename)
1788        from _test_import_from_lib.lib import myfunc, myvar, MYFOO
1789        assert MYFOO == 42
1790        assert myfunc(43) == 44
1791        assert myvar == -5     # but can't be changed, so not very useful
1792        with pytest.raises(ImportError):
1793            from _test_import_from_lib.lib import bar
1794        d = {}
1795        exec("from _test_import_from_lib.lib import *", d)
1796        assert (set(key for key in d if not key.startswith('_')) ==
1797                set(['myfunc', 'MYFOO']))
1798        #
1799        # also test "import *" on the module itself, which should be
1800        # equivalent to "import ffi, lib"
1801        d = {}
1802        exec("from _test_import_from_lib import *", d)
1803        assert (sorted([x for x in d.keys() if not x.startswith('__')]) ==
1804                ['ffi', 'lib'])
1805
1806    def test_char16_t(self):
1807        x = ffi.new("char16_t[]", 5)
1808        assert len(x) == 5 and ffi.sizeof(x) == 10
1809        x[2] = u+'\u1324'
1810        assert x[2] == u+'\u1324'
1811        y = ffi.new("char16_t[]", u+'\u1234\u5678')
1812        assert len(y) == 3
1813        assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
1814        assert ffi.string(y) == u+'\u1234\u5678'
1815        z = ffi.new("char16_t[]", u+'\U00012345')
1816        assert len(z) == 3
1817        assert list(z) == [u+'\ud808', u+'\udf45', u+'\x00']
1818        assert ffi.string(z) == u+'\U00012345'
1819
1820    def test_char32_t(self):
1821        x = ffi.new("char32_t[]", 5)
1822        assert len(x) == 5 and ffi.sizeof(x) == 20
1823        x[3] = u+'\U00013245'
1824        assert x[3] == u+'\U00013245'
1825        y = ffi.new("char32_t[]", u+'\u1234\u5678')
1826        assert len(y) == 3
1827        assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
1828        z = ffi.new("char32_t[]", u+'\U00012345')
1829        assert len(z) == 2
1830        assert list(z) == [u+'\U00012345', u+'\x00'] # maybe a 2-unichars strin
1831        assert ffi.string(z) == u+'\U00012345'
1832