• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import py
2def _setup_path():
3    import os, sys
4    if '__pypy__' in sys.builtin_module_names:
5        py.test.skip("_cffi_backend.c: not tested on top of pypy, "
6                     "use pypy/module/_cffi_backend/test/ instead.")
7    sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
8_setup_path()
9from _cffi_backend import *
10from _cffi_backend import _testfunc, _get_types, _get_common_types, __version__
11
12# ____________________________________________________________
13
14import sys
15assert __version__ == "1.12.2", ("This test_c.py file is for testing a version"
16                                 " of cffi that differs from the one that we"
17                                 " get from 'import _cffi_backend'")
18if sys.version_info < (3,):
19    type_or_class = "type"
20    mandatory_b_prefix = ''
21    mandatory_u_prefix = 'u'
22    bytechr = chr
23    bitem2bchr = lambda x: x
24    class U(object):
25        def __add__(self, other):
26            return eval('u'+repr(other).replace(r'\\u', r'\u')
27                                       .replace(r'\\U', r'\U'))
28    u = U()
29    str2bytes = str
30    strict_compare = False
31else:
32    type_or_class = "class"
33    long = int
34    unicode = str
35    unichr = chr
36    mandatory_b_prefix = 'b'
37    mandatory_u_prefix = ''
38    bytechr = lambda n: bytes([n])
39    bitem2bchr = bytechr
40    u = ""
41    str2bytes = lambda s: bytes(s, "ascii")
42    strict_compare = True
43
44def size_of_int():
45    BInt = new_primitive_type("int")
46    return sizeof(BInt)
47
48def size_of_long():
49    BLong = new_primitive_type("long")
50    return sizeof(BLong)
51
52def size_of_ptr():
53    BInt = new_primitive_type("int")
54    BPtr = new_pointer_type(BInt)
55    return sizeof(BPtr)
56
57
58def find_and_load_library(name, flags=RTLD_NOW):
59    import ctypes.util
60    if name is None:
61        path = None
62    else:
63        path = ctypes.util.find_library(name)
64        if path is None and name == 'c':
65            assert sys.platform == 'win32'
66            assert sys.version_info >= (3,)
67            py.test.skip("dlopen(None) cannot work on Windows with Python 3")
68    return load_library(path, flags)
69
70def test_load_library():
71    x = find_and_load_library('c')
72    assert repr(x).startswith("<clibrary '")
73    x = find_and_load_library('c', RTLD_NOW | RTLD_GLOBAL)
74    assert repr(x).startswith("<clibrary '")
75    x = find_and_load_library('c', RTLD_LAZY)
76    assert repr(x).startswith("<clibrary '")
77
78def test_all_rtld_symbols():
79    import sys
80    FFI_DEFAULT_ABI        # these symbols must be defined
81    FFI_CDECL
82    RTLD_LAZY
83    RTLD_NOW
84    RTLD_GLOBAL
85    RTLD_LOCAL
86    if sys.platform.startswith("linux"):
87        RTLD_NODELETE
88        RTLD_NOLOAD
89        RTLD_DEEPBIND
90
91def test_new_primitive_type():
92    py.test.raises(KeyError, new_primitive_type, "foo")
93    p = new_primitive_type("signed char")
94    assert repr(p) == "<ctype 'signed char'>"
95
96def check_dir(p, expected):
97    got = [name for name in dir(p) if not name.startswith('_')]
98    assert got == sorted(expected)
99
100def test_inspect_primitive_type():
101    p = new_primitive_type("signed char")
102    assert p.kind == "primitive"
103    assert p.cname == "signed char"
104    check_dir(p, ['cname', 'kind'])
105
106def test_cast_to_signed_char():
107    p = new_primitive_type("signed char")
108    x = cast(p, -65 + 17*256)
109    assert repr(x) == "<cdata 'signed char' -65>"
110    assert repr(type(x)) == "<%s '_cffi_backend.CData'>" % type_or_class
111    assert int(x) == -65
112    x = cast(p, -66 + (1<<199)*256)
113    assert repr(x) == "<cdata 'signed char' -66>"
114    assert int(x) == -66
115    assert (x == cast(p, -66)) is True
116    assert (x != cast(p, -66)) is False
117    q = new_primitive_type("short")
118    assert (x == cast(q, -66)) is True
119    assert (x != cast(q, -66)) is False
120
121def test_sizeof_type():
122    py.test.raises(TypeError, sizeof, 42.5)
123    p = new_primitive_type("short")
124    assert sizeof(p) == 2
125
126def test_integer_types():
127    for name in ['signed char', 'short', 'int', 'long', 'long long']:
128        p = new_primitive_type(name)
129        size = sizeof(p)
130        min = -(1 << (8*size-1))
131        max = (1 << (8*size-1)) - 1
132        assert int(cast(p, min)) == min
133        assert int(cast(p, max)) == max
134        assert int(cast(p, min - 1)) == max
135        assert int(cast(p, max + 1)) == min
136        py.test.raises(TypeError, cast, p, None)
137        assert long(cast(p, min - 1)) == max
138        assert int(cast(p, b'\x08')) == 8
139        assert int(cast(p, u+'\x08')) == 8
140    for name in ['char', 'short', 'int', 'long', 'long long']:
141        p = new_primitive_type('unsigned ' + name)
142        size = sizeof(p)
143        max = (1 << (8*size)) - 1
144        assert int(cast(p, 0)) == 0
145        assert int(cast(p, max)) == max
146        assert int(cast(p, -1)) == max
147        assert int(cast(p, max + 1)) == 0
148        assert long(cast(p, -1)) == max
149        assert int(cast(p, b'\xFE')) == 254
150        assert int(cast(p, u+'\xFE')) == 254
151
152def test_no_float_on_int_types():
153    p = new_primitive_type('long')
154    py.test.raises(TypeError, float, cast(p, 42))
155    py.test.raises(TypeError, complex, cast(p, 42))
156
157def test_float_types():
158    INF = 1E200 * 1E200
159    for name in ["float", "double"]:
160        p = new_primitive_type(name)
161        assert bool(cast(p, 0)) is False      # since 1.7
162        assert bool(cast(p, -0.0)) is False   # since 1.7
163        assert bool(cast(p, 1e-42)) is True
164        assert bool(cast(p, -1e-42)) is True
165        assert bool(cast(p, INF))
166        assert bool(cast(p, -INF))
167        assert bool(cast(p, float("nan")))
168        assert int(cast(p, -150)) == -150
169        assert int(cast(p, 61.91)) == 61
170        assert long(cast(p, 61.91)) == 61
171        assert type(int(cast(p, 61.91))) is int
172        assert type(int(cast(p, 1E22))) is long
173        assert type(long(cast(p, 61.91))) is long
174        assert type(long(cast(p, 1E22))) is long
175        py.test.raises(OverflowError, int, cast(p, INF))
176        py.test.raises(OverflowError, int, cast(p, -INF))
177        assert float(cast(p, 1.25)) == 1.25
178        assert float(cast(p, INF)) == INF
179        assert float(cast(p, -INF)) == -INF
180        if name == "float":
181            assert float(cast(p, 1.1)) != 1.1     # rounding error
182            assert float(cast(p, 1E200)) == INF   # limited range
183
184        assert cast(p, -1.1) == cast(p, -1.1)
185        assert repr(float(cast(p, -0.0))) == '-0.0'
186        assert float(cast(p, b'\x09')) == 9.0
187        assert float(cast(p, u+'\x09')) == 9.0
188        assert float(cast(p, True)) == 1.0
189        py.test.raises(TypeError, cast, p, None)
190
191def test_complex_types():
192    INF = 1E200 * 1E200
193    for name in ["float", "double"]:
194        p = new_primitive_type(name + " _Complex")
195        assert bool(cast(p, 0)) is False
196        assert bool(cast(p, INF))
197        assert bool(cast(p, -INF))
198        assert bool(cast(p, 0j)) is False
199        assert bool(cast(p, INF*1j))
200        assert bool(cast(p, -INF*1j))
201        # "can't convert complex to float", like CPython's "float(0j)"
202        py.test.raises(TypeError, int, cast(p, -150))
203        py.test.raises(TypeError, long, cast(p, -150))
204        py.test.raises(TypeError, float, cast(p, -150))
205        assert complex(cast(p, 1.25)) == 1.25
206        assert complex(cast(p, 1.25j)) == 1.25j
207        assert complex(cast(p, complex(0,INF))) == complex(0,INF)
208        assert complex(cast(p, -INF)) == -INF
209        if name == "float":
210            assert complex(cast(p, 1.1j)) != 1.1j         # rounding error
211            assert complex(cast(p, 1E200+3j)) == INF+3j   # limited range
212            assert complex(cast(p, complex(3,1E200))) == complex(3,INF) # limited range
213
214        assert cast(p, -1.1j) == cast(p, -1.1j)
215        assert repr(complex(cast(p, -0.0)).real) == '-0.0'
216        #assert repr(complex(cast(p, -0j))) == '-0j'   # http://bugs.python.org/issue29602
217        assert complex(cast(p, b'\x09')) == 9.0 + 0j
218        assert complex(cast(p, u+'\x09')) == 9.0 + 0j
219        assert complex(cast(p, True)) == 1.0 + 0j
220        py.test.raises(TypeError, cast, p, None)
221        #
222        py.test.raises(TypeError, cast, new_primitive_type(name), 1+0j)
223        #
224        for basetype in ["char", "int", "uint64_t", "float",
225                         "double", "long double"]:
226            baseobj = cast(new_primitive_type(basetype), 65)
227            py.test.raises(TypeError, complex, baseobj)
228        #
229        BArray = new_array_type(new_pointer_type(p), 10)
230        x = newp(BArray, None)
231        x[5] = 12.34 + 56.78j
232        assert type(x[5]) is complex
233        assert abs(x[5] - (12.34 + 56.78j)) < 1e-5
234        assert (x[5] == 12.34 + 56.78j) == (name == "double")  # rounding error
235        #
236        class Foo:
237            def __complex__(self):
238                return 2 + 3j
239        assert complex(Foo()) == 2 + 3j
240        assert complex(cast(p, Foo())) == 2 + 3j
241    py.test.raises(TypeError, cast, new_primitive_type("int"), 1+0j)
242
243def test_character_type():
244    p = new_primitive_type("char")
245    assert bool(cast(p, 'A')) is True
246    assert bool(cast(p, '\x00')) is False    # since 1.7
247    assert cast(p, '\x00') == cast(p, -17*256)
248    assert int(cast(p, 'A')) == 65
249    assert long(cast(p, 'A')) == 65
250    assert type(int(cast(p, 'A'))) is int
251    assert type(long(cast(p, 'A'))) is long
252    assert str(cast(p, 'A')) == repr(cast(p, 'A'))
253    assert repr(cast(p, 'A')) == "<cdata 'char' %s'A'>" % mandatory_b_prefix
254    assert repr(cast(p, 255)) == r"<cdata 'char' %s'\xff'>" % mandatory_b_prefix
255    assert repr(cast(p, 0)) == r"<cdata 'char' %s'\x00'>" % mandatory_b_prefix
256
257def test_pointer_type():
258    p = new_primitive_type("int")
259    assert repr(p) == "<ctype 'int'>"
260    p = new_pointer_type(p)
261    assert repr(p) == "<ctype 'int *'>"
262    p = new_pointer_type(p)
263    assert repr(p) == "<ctype 'int * *'>"
264    p = new_pointer_type(p)
265    assert repr(p) == "<ctype 'int * * *'>"
266
267def test_inspect_pointer_type():
268    p1 = new_primitive_type("int")
269    p2 = new_pointer_type(p1)
270    assert p2.kind == "pointer"
271    assert p2.cname == "int *"
272    assert p2.item is p1
273    check_dir(p2, ['cname', 'kind', 'item'])
274    p3 = new_pointer_type(p2)
275    assert p3.item is p2
276
277def test_pointer_to_int():
278    BInt = new_primitive_type("int")
279    py.test.raises(TypeError, newp, BInt)
280    py.test.raises(TypeError, newp, BInt, None)
281    BPtr = new_pointer_type(BInt)
282    p = newp(BPtr)
283    assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int()
284    p = newp(BPtr, None)
285    assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int()
286    p = newp(BPtr, 5000)
287    assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int()
288    q = cast(BPtr, p)
289    assert repr(q).startswith("<cdata 'int *' 0x")
290    assert p == q
291    assert hash(p) == hash(q)
292    e = py.test.raises(TypeError, newp, new_array_type(BPtr, None), None)
293    assert str(e.value) == (
294        "expected new array length or list/tuple/str, not NoneType")
295
296def test_pointer_bool():
297    BInt = new_primitive_type("int")
298    BPtr = new_pointer_type(BInt)
299    p = cast(BPtr, 0)
300    assert bool(p) is False
301    p = cast(BPtr, 42)
302    assert bool(p) is True
303
304def test_pointer_to_pointer():
305    BInt = new_primitive_type("int")
306    BPtr = new_pointer_type(BInt)
307    BPtrPtr = new_pointer_type(BPtr)
308    p = newp(BPtrPtr, None)
309    assert repr(p) == "<cdata 'int * *' owning %d bytes>" % size_of_ptr()
310
311def test_reading_pointer_to_int():
312    BInt = new_primitive_type("int")
313    BPtr = new_pointer_type(BInt)
314    p = newp(BPtr, None)
315    assert p[0] == 0
316    p = newp(BPtr, 5000)
317    assert p[0] == 5000
318    py.test.raises(IndexError, "p[1]")
319    py.test.raises(IndexError, "p[-1]")
320
321def test_reading_pointer_to_float():
322    BFloat = new_primitive_type("float")
323    py.test.raises(TypeError, newp, BFloat, None)
324    BPtr = new_pointer_type(BFloat)
325    p = newp(BPtr, None)
326    assert p[0] == 0.0 and type(p[0]) is float
327    p = newp(BPtr, 1.25)
328    assert p[0] == 1.25 and type(p[0]) is float
329    p = newp(BPtr, 1.1)
330    assert p[0] != 1.1 and abs(p[0] - 1.1) < 1E-5   # rounding errors
331
332def test_cast_float_to_int():
333    for type in ["int", "unsigned int", "long", "unsigned long",
334                 "long long", "unsigned long long"]:
335        p = new_primitive_type(type)
336        assert int(cast(p, 4.2)) == 4
337        py.test.raises(TypeError, newp, new_pointer_type(p), 4.2)
338
339def test_newp_integer_types():
340    for name in ['signed char', 'short', 'int', 'long', 'long long']:
341        p = new_primitive_type(name)
342        pp = new_pointer_type(p)
343        size = sizeof(p)
344        min = -(1 << (8*size-1))
345        max = (1 << (8*size-1)) - 1
346        assert newp(pp, min)[0] == min
347        assert newp(pp, max)[0] == max
348        py.test.raises(OverflowError, newp, pp, min - 2 ** 32)
349        py.test.raises(OverflowError, newp, pp, min - 2 ** 64)
350        py.test.raises(OverflowError, newp, pp, max + 2 ** 32)
351        py.test.raises(OverflowError, newp, pp, max + 2 ** 64)
352        py.test.raises(OverflowError, newp, pp, min - 1)
353        py.test.raises(OverflowError, newp, pp, max + 1)
354        py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 32)
355        py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 64)
356        py.test.raises(OverflowError, newp, pp, max + 1)
357        py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 32)
358        py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 64)
359        py.test.raises(TypeError, newp, pp, 1.0)
360    for name in ['char', 'short', 'int', 'long', 'long long']:
361        p = new_primitive_type('unsigned ' + name)
362        pp = new_pointer_type(p)
363        size = sizeof(p)
364        max = (1 << (8*size)) - 1
365        assert newp(pp, 0)[0] == 0
366        assert newp(pp, max)[0] == max
367        py.test.raises(OverflowError, newp, pp, -1)
368        py.test.raises(OverflowError, newp, pp, max + 1)
369
370def test_reading_pointer_to_char():
371    BChar = new_primitive_type("char")
372    py.test.raises(TypeError, newp, BChar, None)
373    BPtr = new_pointer_type(BChar)
374    p = newp(BPtr, None)
375    assert p[0] == b'\x00'
376    p = newp(BPtr, b'A')
377    assert p[0] == b'A'
378    py.test.raises(TypeError, newp, BPtr, 65)
379    py.test.raises(TypeError, newp, BPtr, b"foo")
380    py.test.raises(TypeError, newp, BPtr, u+"foo")
381    c = cast(BChar, b'A')
382    assert str(c) == repr(c)
383    assert int(c) == ord(b'A')
384    py.test.raises(TypeError, cast, BChar, b'foo')
385    py.test.raises(TypeError, cast, BChar, u+'foo')
386    e = py.test.raises(TypeError, newp, new_array_type(BPtr, None), 12.3)
387    assert str(e.value) == (
388        "expected new array length or list/tuple/str, not float")
389
390def test_reading_pointer_to_pointer():
391    BVoidP = new_pointer_type(new_void_type())
392    BCharP = new_pointer_type(new_primitive_type("char"))
393    BInt = new_primitive_type("int")
394    BIntPtr = new_pointer_type(BInt)
395    BIntPtrPtr = new_pointer_type(BIntPtr)
396    q = newp(BIntPtr, 42)
397    assert q[0] == 42
398    p = newp(BIntPtrPtr, None)
399    assert p[0] is not None
400    assert p[0] == cast(BVoidP, 0)
401    assert p[0] == cast(BCharP, 0)
402    assert p[0] != None
403    assert repr(p[0]) == "<cdata 'int *' NULL>"
404    p[0] = q
405    assert p[0] != cast(BVoidP, 0)
406    assert p[0] != cast(BCharP, 0)
407    assert p[0][0] == 42
408    q[0] += 1
409    assert p[0][0] == 43
410    p = newp(BIntPtrPtr, q)
411    assert p[0][0] == 43
412
413def test_load_standard_library():
414    if sys.platform == "win32":
415        py.test.raises(OSError, find_and_load_library, None)
416        return
417    x = find_and_load_library(None)
418    BVoidP = new_pointer_type(new_void_type())
419    assert x.load_function(BVoidP, 'strcpy')
420    py.test.raises(AttributeError, x.load_function,
421                   BVoidP, 'xxx_this_function_does_not_exist')
422    # the next one is from 'libm', not 'libc', but we assume
423    # that it is already loaded too, so it should work
424    assert x.load_function(BVoidP, 'sqrt')
425    #
426    x.close_lib()
427    py.test.raises(ValueError, x.load_function, BVoidP, 'sqrt')
428    x.close_lib()
429
430def test_no_len_on_nonarray():
431    p = new_primitive_type("int")
432    py.test.raises(TypeError, len, cast(p, 42))
433
434def test_cmp_none():
435    p = new_primitive_type("int")
436    x = cast(p, 42)
437    assert (x == None) is False
438    assert (x != None) is True
439    assert (x == ["hello"]) is False
440    assert (x != ["hello"]) is True
441    y = cast(p, 0)
442    assert (y == None) is False
443
444def test_invalid_indexing():
445    p = new_primitive_type("int")
446    x = cast(p, 42)
447    py.test.raises(TypeError, "x[0]")
448
449def test_default_str():
450    BChar = new_primitive_type("char")
451    x = cast(BChar, 42)
452    assert str(x) == repr(x)
453    BInt = new_primitive_type("int")
454    x = cast(BInt, 42)
455    assert str(x) == repr(x)
456    BArray = new_array_type(new_pointer_type(BInt), 10)
457    x = newp(BArray, None)
458    assert str(x) == repr(x)
459
460def test_default_unicode():
461    BInt = new_primitive_type("int")
462    x = cast(BInt, 42)
463    assert unicode(x) == unicode(repr(x))
464    BArray = new_array_type(new_pointer_type(BInt), 10)
465    x = newp(BArray, None)
466    assert unicode(x) == unicode(repr(x))
467
468def test_cast_from_cdataint():
469    BInt = new_primitive_type("int")
470    x = cast(BInt, 0)
471    y = cast(new_pointer_type(BInt), x)
472    assert bool(y) is False
473    #
474    x = cast(BInt, 42)
475    y = cast(BInt, x)
476    assert int(y) == 42
477    y = cast(new_primitive_type("char"), x)
478    assert int(y) == 42
479    y = cast(new_primitive_type("float"), x)
480    assert float(y) == 42.0
481    #
482    z = cast(BInt, 42.5)
483    assert int(z) == 42
484    z = cast(BInt, y)
485    assert int(z) == 42
486
487def test_void_type():
488    p = new_void_type()
489    assert p.kind == "void"
490    assert p.cname == "void"
491    check_dir(p, ['kind', 'cname'])
492
493def test_array_type():
494    p = new_primitive_type("int")
495    assert repr(p) == "<ctype 'int'>"
496    #
497    py.test.raises(TypeError, new_array_type, new_pointer_type(p), "foo")
498    py.test.raises(ValueError, new_array_type, new_pointer_type(p), -42)
499    #
500    p1 = new_array_type(new_pointer_type(p), None)
501    assert repr(p1) == "<ctype 'int[]'>"
502    py.test.raises(ValueError, new_array_type, new_pointer_type(p1), 42)
503    #
504    p1 = new_array_type(new_pointer_type(p), 42)
505    p2 = new_array_type(new_pointer_type(p1), 25)
506    assert repr(p2) == "<ctype 'int[25][42]'>"
507    p2 = new_array_type(new_pointer_type(p1), None)
508    assert repr(p2) == "<ctype 'int[][42]'>"
509    #
510    py.test.raises(OverflowError,
511                   new_array_type, new_pointer_type(p), sys.maxsize+1)
512    py.test.raises(OverflowError,
513                   new_array_type, new_pointer_type(p), sys.maxsize // 3)
514
515def test_inspect_array_type():
516    p = new_primitive_type("int")
517    p1 = new_array_type(new_pointer_type(p), None)
518    assert p1.kind == "array"
519    assert p1.cname == "int[]"
520    assert p1.item is p
521    assert p1.length is None
522    check_dir(p1, ['cname', 'kind', 'item', 'length'])
523    p1 = new_array_type(new_pointer_type(p), 42)
524    assert p1.kind == "array"
525    assert p1.cname == "int[42]"
526    assert p1.item is p
527    assert p1.length == 42
528    check_dir(p1, ['cname', 'kind', 'item', 'length'])
529
530def test_array_instance():
531    LENGTH = 1423
532    p = new_primitive_type("int")
533    p1 = new_array_type(new_pointer_type(p), LENGTH)
534    a = newp(p1, None)
535    assert repr(a) == "<cdata 'int[%d]' owning %d bytes>" % (
536        LENGTH, LENGTH * size_of_int())
537    assert len(a) == LENGTH
538    for i in range(LENGTH):
539        assert a[i] == 0
540    py.test.raises(IndexError, "a[LENGTH]")
541    py.test.raises(IndexError, "a[-1]")
542    for i in range(LENGTH):
543        a[i] = i * i + 1
544    for i in range(LENGTH):
545        assert a[i] == i * i + 1
546    e = py.test.raises(IndexError, "a[LENGTH+100] = 500")
547    assert ('(expected %d < %d)' % (LENGTH+100, LENGTH)) in str(e.value)
548    py.test.raises(TypeError, int, a)
549
550def test_array_of_unknown_length_instance():
551    p = new_primitive_type("int")
552    p1 = new_array_type(new_pointer_type(p), None)
553    py.test.raises(TypeError, newp, p1, None)
554    py.test.raises(ValueError, newp, p1, -42)
555    a = newp(p1, 42)
556    assert len(a) == 42
557    for i in range(42):
558        a[i] -= i
559    for i in range(42):
560        assert a[i] == -i
561    py.test.raises(IndexError, "a[42]")
562    py.test.raises(IndexError, "a[-1]")
563    py.test.raises(IndexError, "a[42] = 123")
564    py.test.raises(IndexError, "a[-1] = 456")
565
566def test_array_of_unknown_length_instance_with_initializer():
567    p = new_primitive_type("int")
568    p1 = new_array_type(new_pointer_type(p), None)
569    a = newp(p1, list(range(42)))
570    assert len(a) == 42
571    a = newp(p1, tuple(range(142)))
572    assert len(a) == 142
573
574def test_array_initializer():
575    p = new_primitive_type("int")
576    p1 = new_array_type(new_pointer_type(p), None)
577    a = newp(p1, list(range(100, 142)))
578    for i in range(42):
579        assert a[i] == 100 + i
580    #
581    p2 = new_array_type(new_pointer_type(p), 43)
582    a = newp(p2, tuple(range(100, 142)))
583    for i in range(42):
584        assert a[i] == 100 + i
585    assert a[42] == 0      # extra uninitialized item
586
587def test_array_add():
588    p = new_primitive_type("int")
589    p1 = new_array_type(new_pointer_type(p), 5)    # int[5]
590    p2 = new_array_type(new_pointer_type(p1), 3)   # int[3][5]
591    a = newp(p2, [list(range(n, n+5)) for n in [100, 200, 300]])
592    assert repr(a) == "<cdata 'int[3][5]' owning %d bytes>" % (
593        3*5*size_of_int(),)
594    assert repr(a + 0).startswith("<cdata 'int(*)[5]' 0x")
595    assert 0 + a == a + 0 != 1 + a == a + 1
596    assert repr(a[0]).startswith("<cdata 'int[5]' 0x")
597    assert repr((a + 0)[0]).startswith("<cdata 'int[5]' 0x")
598    assert repr(a[0] + 0).startswith("<cdata 'int *' 0x")
599    assert type(a[0][0]) is int
600    assert type((a[0] + 0)[0]) is int
601
602def test_array_sub():
603    BInt = new_primitive_type("int")
604    BArray = new_array_type(new_pointer_type(BInt), 5)   # int[5]
605    a = newp(BArray, None)
606    p = a + 1
607    assert p - a == 1
608    assert p - (a+0) == 1
609    assert a == (p - 1)
610    BPtr = new_pointer_type(new_primitive_type("short"))
611    q = newp(BPtr, None)
612    py.test.raises(TypeError, "p - q")
613    py.test.raises(TypeError, "q - p")
614    py.test.raises(TypeError, "a - q")
615    e = py.test.raises(TypeError, "q - a")
616    assert str(e.value) == "cannot subtract cdata 'short *' and cdata 'int *'"
617
618def test_ptr_sub_unaligned():
619    BInt = new_primitive_type("int")
620    BIntPtr = new_pointer_type(BInt)
621    a = cast(BIntPtr, 1240)
622    for bi in range(1430, 1438):
623        b = cast(BIntPtr, bi)
624        if ((bi - 1240) % size_of_int()) == 0:
625            assert b - a == (bi - 1240) // size_of_int()
626            assert a - b == (1240 - bi) // size_of_int()
627        else:
628            py.test.raises(ValueError, "b - a")
629            py.test.raises(ValueError, "a - b")
630
631def test_cast_primitive_from_cdata():
632    p = new_primitive_type("int")
633    n = cast(p, cast(p, -42))
634    assert int(n) == -42
635    #
636    p = new_primitive_type("unsigned int")
637    n = cast(p, cast(p, 42))
638    assert int(n) == 42
639    #
640    p = new_primitive_type("long long")
641    n = cast(p, cast(p, -(1<<60)))
642    assert int(n) == -(1<<60)
643    #
644    p = new_primitive_type("unsigned long long")
645    n = cast(p, cast(p, 1<<63))
646    assert int(n) == 1<<63
647    #
648    p = new_primitive_type("float")
649    n = cast(p, cast(p, 42.5))
650    assert float(n) == 42.5
651    #
652    p = new_primitive_type("char")
653    n = cast(p, cast(p, "A"))
654    assert int(n) == ord("A")
655
656def test_new_primitive_from_cdata():
657    p = new_primitive_type("int")
658    p1 = new_pointer_type(p)
659    n = newp(p1, cast(p, -42))
660    assert n[0] == -42
661    #
662    p = new_primitive_type("unsigned int")
663    p1 = new_pointer_type(p)
664    n = newp(p1, cast(p, 42))
665    assert n[0] == 42
666    #
667    p = new_primitive_type("float")
668    p1 = new_pointer_type(p)
669    n = newp(p1, cast(p, 42.5))
670    assert n[0] == 42.5
671    #
672    p = new_primitive_type("char")
673    p1 = new_pointer_type(p)
674    n = newp(p1, cast(p, "A"))
675    assert n[0] == b"A"
676
677def test_cast_between_pointers():
678    BIntP = new_pointer_type(new_primitive_type("int"))
679    BIntA = new_array_type(BIntP, None)
680    a = newp(BIntA, [40, 41, 42, 43, 44])
681    BShortP = new_pointer_type(new_primitive_type("short"))
682    b = cast(BShortP, a)
683    c = cast(BIntP, b)
684    assert c[3] == 43
685    BLongLong = new_primitive_type("long long")
686    d = cast(BLongLong, c)
687    e = cast(BIntP, d)
688    assert e[3] == 43
689    f = cast(BIntP, int(d))
690    assert f[3] == 43
691    #
692    b = cast(BShortP, 0)
693    assert not b
694    c = cast(BIntP, b)
695    assert not c
696    assert int(cast(BLongLong, c)) == 0
697
698def test_alignof():
699    BInt = new_primitive_type("int")
700    assert alignof(BInt) == sizeof(BInt)
701    BPtr = new_pointer_type(BInt)
702    assert alignof(BPtr) == sizeof(BPtr)
703    BArray = new_array_type(BPtr, None)
704    assert alignof(BArray) == alignof(BInt)
705
706def test_new_struct_type():
707    BStruct = new_struct_type("foo")
708    assert repr(BStruct) == "<ctype 'foo'>"
709    BStruct = new_struct_type("struct foo")
710    assert repr(BStruct) == "<ctype 'struct foo'>"
711    BPtr = new_pointer_type(BStruct)
712    assert repr(BPtr) == "<ctype 'struct foo *'>"
713    py.test.raises(ValueError, sizeof, BStruct)
714    py.test.raises(ValueError, alignof, BStruct)
715
716def test_new_union_type():
717    BUnion = new_union_type("union foo")
718    assert repr(BUnion) == "<ctype 'union foo'>"
719    BPtr = new_pointer_type(BUnion)
720    assert repr(BPtr) == "<ctype 'union foo *'>"
721
722def test_complete_struct():
723    BLong = new_primitive_type("long")
724    BChar = new_primitive_type("char")
725    BShort = new_primitive_type("short")
726    BStruct = new_struct_type("struct foo")
727    assert BStruct.kind == "struct"
728    assert BStruct.cname == "struct foo"
729    assert BStruct.fields is None
730    check_dir(BStruct, ['cname', 'kind', 'fields'])
731    #
732    complete_struct_or_union(BStruct, [('a1', BLong, -1),
733                                       ('a2', BChar, -1),
734                                       ('a3', BShort, -1)])
735    d = BStruct.fields
736    assert len(d) == 3
737    assert d[0][0] == 'a1'
738    assert d[0][1].type is BLong
739    assert d[0][1].offset == 0
740    assert d[0][1].bitshift == -1
741    assert d[0][1].bitsize == -1
742    assert d[1][0] == 'a2'
743    assert d[1][1].type is BChar
744    assert d[1][1].offset == sizeof(BLong)
745    assert d[1][1].bitshift == -1
746    assert d[1][1].bitsize == -1
747    assert d[2][0] == 'a3'
748    assert d[2][1].type is BShort
749    assert d[2][1].offset == sizeof(BLong) + sizeof(BShort)
750    assert d[2][1].bitshift == -1
751    assert d[2][1].bitsize == -1
752    assert sizeof(BStruct) == 2 * sizeof(BLong)
753    assert alignof(BStruct) == alignof(BLong)
754
755def test_complete_union():
756    BLong = new_primitive_type("long")
757    BChar = new_primitive_type("char")
758    BUnion = new_union_type("union foo")
759    assert BUnion.kind == "union"
760    assert BUnion.cname == "union foo"
761    assert BUnion.fields is None
762    complete_struct_or_union(BUnion, [('a1', BLong, -1),
763                                      ('a2', BChar, -1)])
764    d = BUnion.fields
765    assert len(d) == 2
766    assert d[0][0] == 'a1'
767    assert d[0][1].type is BLong
768    assert d[0][1].offset == 0
769    assert d[1][0] == 'a2'
770    assert d[1][1].type is BChar
771    assert d[1][1].offset == 0
772    assert sizeof(BUnion) == sizeof(BLong)
773    assert alignof(BUnion) == alignof(BLong)
774
775def test_struct_instance():
776    BInt = new_primitive_type("int")
777    BStruct = new_struct_type("struct foo")
778    BStructPtr = new_pointer_type(BStruct)
779    p = cast(BStructPtr, 42)
780    e = py.test.raises(AttributeError, "p.a1")    # opaque
781    assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: "
782                            "cannot read fields")
783    e = py.test.raises(AttributeError, "p.a1 = 10")    # opaque
784    assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: "
785                            "cannot write fields")
786
787    complete_struct_or_union(BStruct, [('a1', BInt, -1),
788                                       ('a2', BInt, -1)])
789    p = newp(BStructPtr, None)
790    s = p[0]
791    assert s.a1 == 0
792    s.a2 = 123
793    assert s.a1 == 0
794    assert s.a2 == 123
795    py.test.raises(OverflowError, "s.a1 = sys.maxsize+1")
796    assert s.a1 == 0
797    e = py.test.raises(AttributeError, "p.foobar")
798    assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'"
799    e = py.test.raises(AttributeError, "p.foobar = 42")
800    assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'"
801    e = py.test.raises(AttributeError, "s.foobar")
802    assert str(e.value) == "cdata 'struct foo' has no field 'foobar'"
803    e = py.test.raises(AttributeError, "s.foobar = 42")
804    assert str(e.value) == "cdata 'struct foo' has no field 'foobar'"
805    j = cast(BInt, 42)
806    e = py.test.raises(AttributeError, "j.foobar")
807    assert str(e.value) == "cdata 'int' has no attribute 'foobar'"
808    e = py.test.raises(AttributeError, "j.foobar = 42")
809    assert str(e.value) == "cdata 'int' has no attribute 'foobar'"
810    j = cast(new_pointer_type(BInt), 42)
811    e = py.test.raises(AttributeError, "j.foobar")
812    assert str(e.value) == "cdata 'int *' has no attribute 'foobar'"
813    e = py.test.raises(AttributeError, "j.foobar = 42")
814    assert str(e.value) == "cdata 'int *' has no attribute 'foobar'"
815    pp = newp(new_pointer_type(BStructPtr), p)
816    e = py.test.raises(AttributeError, "pp.a1")
817    assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'"
818    e = py.test.raises(AttributeError, "pp.a1 = 42")
819    assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'"
820
821def test_union_instance():
822    BInt = new_primitive_type("int")
823    BUInt = new_primitive_type("unsigned int")
824    BUnion = new_union_type("union bar")
825    complete_struct_or_union(BUnion, [('a1', BInt, -1), ('a2', BUInt, -1)])
826    p = newp(new_pointer_type(BUnion), [-42])
827    bigval = -42 + (1 << (8*size_of_int()))
828    assert p.a1 == -42
829    assert p.a2 == bigval
830    p = newp(new_pointer_type(BUnion), {'a2': bigval})
831    assert p.a1 == -42
832    assert p.a2 == bigval
833    py.test.raises(OverflowError, newp, new_pointer_type(BUnion),
834                   {'a1': bigval})
835    p = newp(new_pointer_type(BUnion), [])
836    assert p.a1 == p.a2 == 0
837
838def test_struct_pointer():
839    BInt = new_primitive_type("int")
840    BStruct = new_struct_type("struct foo")
841    BStructPtr = new_pointer_type(BStruct)
842    complete_struct_or_union(BStruct, [('a1', BInt, -1),
843                                       ('a2', BInt, -1)])
844    p = newp(BStructPtr, None)
845    assert p.a1 == 0      # read/write via the pointer (C equivalent: '->')
846    p.a2 = 123
847    assert p.a1 == 0
848    assert p.a2 == 123
849
850def test_struct_init_list():
851    BVoidP = new_pointer_type(new_void_type())
852    BInt = new_primitive_type("int")
853    BIntPtr = new_pointer_type(BInt)
854    BStruct = new_struct_type("struct foo")
855    BStructPtr = new_pointer_type(BStruct)
856    complete_struct_or_union(BStruct, [('a1', BInt, -1),
857                                       ('a2', BInt, -1),
858                                       ('a3', BInt, -1),
859                                       ('p4', BIntPtr, -1)])
860    s = newp(BStructPtr, [123, 456])
861    assert s.a1 == 123
862    assert s.a2 == 456
863    assert s.a3 == 0
864    assert s.p4 == cast(BVoidP, 0)
865    assert s.p4 != 0
866    #
867    s = newp(BStructPtr, {'a2': 41122, 'a3': -123})
868    assert s.a1 == 0
869    assert s.a2 == 41122
870    assert s.a3 == -123
871    assert s.p4 == cast(BVoidP, 0)
872    #
873    py.test.raises(KeyError, newp, BStructPtr, {'foobar': 0})
874    #
875    p = newp(BIntPtr, 14141)
876    s = newp(BStructPtr, [12, 34, 56, p])
877    assert s.p4 == p
878    assert s.p4
879    #
880    s = newp(BStructPtr, [12, 34, 56, cast(BVoidP, 0)])
881    assert s.p4 == cast(BVoidP, 0)
882    assert not s.p4
883    #
884    py.test.raises(TypeError, newp, BStructPtr, [12, 34, 56, None])
885
886def test_array_in_struct():
887    BInt = new_primitive_type("int")
888    BStruct = new_struct_type("struct foo")
889    BArrayInt5 = new_array_type(new_pointer_type(BInt), 5)
890    complete_struct_or_union(BStruct, [('a1', BArrayInt5, -1)])
891    s = newp(new_pointer_type(BStruct), [[20, 24, 27, 29, 30]])
892    assert s.a1[2] == 27
893    assert repr(s.a1).startswith("<cdata 'int[5]' 0x")
894
895def test_offsetof():
896    def offsetof(BType, fieldname):
897        return typeoffsetof(BType, fieldname)[1]
898    BInt = new_primitive_type("int")
899    BStruct = new_struct_type("struct foo")
900    py.test.raises(TypeError, offsetof, BInt, "abc")
901    py.test.raises(TypeError, offsetof, BStruct, "abc")
902    complete_struct_or_union(BStruct, [('abc', BInt, -1), ('def', BInt, -1)])
903    assert offsetof(BStruct, 'abc') == 0
904    assert offsetof(BStruct, 'def') == size_of_int()
905    py.test.raises(KeyError, offsetof, BStruct, "ghi")
906    assert offsetof(new_pointer_type(BStruct), "def") == size_of_int()
907
908def test_function_type():
909    BInt = new_primitive_type("int")
910    BFunc = new_function_type((BInt, BInt), BInt, False)
911    assert repr(BFunc) == "<ctype 'int(*)(int, int)'>"
912    BFunc2 = new_function_type((), BFunc, False)
913    assert repr(BFunc2) == "<ctype 'int(*(*)())(int, int)'>"
914
915def test_inspect_function_type():
916    BInt = new_primitive_type("int")
917    BFunc = new_function_type((BInt, BInt), BInt, False)
918    assert BFunc.kind == "function"
919    assert BFunc.cname == "int(*)(int, int)"
920    assert BFunc.args == (BInt, BInt)
921    assert BFunc.result is BInt
922    assert BFunc.ellipsis is False
923    assert BFunc.abi == FFI_DEFAULT_ABI
924
925def test_function_type_taking_struct():
926    BChar = new_primitive_type("char")
927    BShort = new_primitive_type("short")
928    BStruct = new_struct_type("struct foo")
929    complete_struct_or_union(BStruct, [('a1', BChar, -1),
930                                       ('a2', BShort, -1)])
931    BFunc = new_function_type((BStruct,), BShort, False)
932    assert repr(BFunc) == "<ctype 'short(*)(struct foo)'>"
933
934def test_function_void_result():
935    BVoid = new_void_type()
936    BInt = new_primitive_type("int")
937    BFunc = new_function_type((BInt, BInt), BVoid, False)
938    assert repr(BFunc) == "<ctype 'void(*)(int, int)'>"
939
940def test_function_void_arg():
941    BVoid = new_void_type()
942    BInt = new_primitive_type("int")
943    py.test.raises(TypeError, new_function_type, (BVoid,), BInt, False)
944
945def test_call_function_0():
946    BSignedChar = new_primitive_type("signed char")
947    BFunc0 = new_function_type((BSignedChar, BSignedChar), BSignedChar, False)
948    f = cast(BFunc0, _testfunc(0))
949    assert f(40, 2) == 42
950    assert f(-100, -100) == -200 + 256
951    py.test.raises(OverflowError, f, 128, 0)
952    py.test.raises(OverflowError, f, 0, 128)
953
954def test_call_function_0_pretend_bool_result():
955    BSignedChar = new_primitive_type("signed char")
956    BBool = new_primitive_type("_Bool")
957    BFunc0 = new_function_type((BSignedChar, BSignedChar), BBool, False)
958    f = cast(BFunc0, _testfunc(0))
959    assert f(40, -39) is True
960    assert f(40, -40) is False
961    py.test.raises(ValueError, f, 40, 2)
962
963def test_call_function_1():
964    BInt = new_primitive_type("int")
965    BLong = new_primitive_type("long")
966    BFunc1 = new_function_type((BInt, BLong), BLong, False)
967    f = cast(BFunc1, _testfunc(1))
968    assert f(40, 2) == 42
969    assert f(-100, -100) == -200
970    int_max = (1 << (8*size_of_int()-1)) - 1
971    long_max = (1 << (8*size_of_long()-1)) - 1
972    if int_max == long_max:
973        assert f(int_max, 1) == - int_max - 1
974    else:
975        assert f(int_max, 1) == int_max + 1
976
977def test_call_function_2():
978    BLongLong = new_primitive_type("long long")
979    BFunc2 = new_function_type((BLongLong, BLongLong), BLongLong, False)
980    f = cast(BFunc2, _testfunc(2))
981    longlong_max = (1 << (8*sizeof(BLongLong)-1)) - 1
982    assert f(longlong_max - 42, 42) == longlong_max
983    assert f(43, longlong_max - 42) == - longlong_max - 1
984
985def test_call_function_3():
986    BFloat = new_primitive_type("float")
987    BDouble = new_primitive_type("double")
988    BFunc3 = new_function_type((BFloat, BDouble), BDouble, False)
989    f = cast(BFunc3, _testfunc(3))
990    assert f(1.25, 5.1) == 1.25 + 5.1     # exact
991    res = f(1.3, 5.1)
992    assert res != 6.4 and abs(res - 6.4) < 1E-5    # inexact
993
994def test_call_function_4():
995    BFloat = new_primitive_type("float")
996    BDouble = new_primitive_type("double")
997    BFunc4 = new_function_type((BFloat, BDouble), BFloat, False)
998    f = cast(BFunc4, _testfunc(4))
999    res = f(1.25, 5.1)
1000    assert res != 6.35 and abs(res - 6.35) < 1E-5    # inexact
1001
1002def test_call_function_5():
1003    BVoid = new_void_type()
1004    BFunc5 = new_function_type((), BVoid, False)
1005    f = cast(BFunc5, _testfunc(5))
1006    f()   # did not crash
1007
1008def test_call_function_6():
1009    BInt = new_primitive_type("int")
1010    BIntPtr = new_pointer_type(BInt)
1011    BFunc6 = new_function_type((BIntPtr,), BIntPtr, False)
1012    f = cast(BFunc6, _testfunc(6))
1013    x = newp(BIntPtr, 42)
1014    res = f(x)
1015    assert typeof(res) is BIntPtr
1016    assert res[0] == 42 - 1000
1017    #
1018    BIntArray = new_array_type(BIntPtr, None)
1019    BFunc6bis = new_function_type((BIntArray,), BIntPtr, False)
1020    f = cast(BFunc6bis, _testfunc(6))
1021    #
1022    res = f([142])
1023    assert typeof(res) is BIntPtr
1024    assert res[0] == 142 - 1000
1025    #
1026    res = f((143,))
1027    assert typeof(res) is BIntPtr
1028    assert res[0] == 143 - 1000
1029    #
1030    x = newp(BIntArray, [242])
1031    res = f(x)
1032    assert typeof(res) is BIntPtr
1033    assert res[0] == 242 - 1000
1034    #
1035    py.test.raises(TypeError, f, 123456)
1036    py.test.raises(TypeError, f, "foo")
1037    py.test.raises(TypeError, f, u+"bar")
1038
1039def test_call_function_7():
1040    BChar = new_primitive_type("char")
1041    BShort = new_primitive_type("short")
1042    BStruct = new_struct_type("struct foo")
1043    BStructPtr = new_pointer_type(BStruct)
1044    complete_struct_or_union(BStruct, [('a1', BChar, -1),
1045                                       ('a2', BShort, -1)])
1046    BFunc7 = new_function_type((BStruct,), BShort, False)
1047    f = cast(BFunc7, _testfunc(7))
1048    res = f({'a1': b'A', 'a2': -4042})
1049    assert res == -4042 + ord(b'A')
1050    #
1051    x = newp(BStructPtr, {'a1': b'A', 'a2': -4042})
1052    res = f(x[0])
1053    assert res == -4042 + ord(b'A')
1054
1055def test_call_function_20():
1056    BChar = new_primitive_type("char")
1057    BShort = new_primitive_type("short")
1058    BStruct = new_struct_type("struct foo")
1059    BStructPtr = new_pointer_type(BStruct)
1060    complete_struct_or_union(BStruct, [('a1', BChar, -1),
1061                                       ('a2', BShort, -1)])
1062    BFunc20 = new_function_type((BStructPtr,), BShort, False)
1063    f = cast(BFunc20, _testfunc(20))
1064    x = newp(BStructPtr, {'a1': b'A', 'a2': -4042})
1065    # can't pass a 'struct foo'
1066    py.test.raises(TypeError, f, x[0])
1067
1068def test_call_function_21():
1069    BInt = new_primitive_type("int")
1070    BStruct = new_struct_type("struct foo")
1071    complete_struct_or_union(BStruct, [('a', BInt, -1),
1072                                       ('b', BInt, -1),
1073                                       ('c', BInt, -1),
1074                                       ('d', BInt, -1),
1075                                       ('e', BInt, -1),
1076                                       ('f', BInt, -1),
1077                                       ('g', BInt, -1),
1078                                       ('h', BInt, -1),
1079                                       ('i', BInt, -1),
1080                                       ('j', BInt, -1)])
1081    BFunc21 = new_function_type((BStruct,), BInt, False)
1082    f = cast(BFunc21, _testfunc(21))
1083    res = f(list(range(13, 3, -1)))
1084    lst = [(n << i) for (i, n) in enumerate(range(13, 3, -1))]
1085    assert res == sum(lst)
1086
1087def test_call_function_22():
1088    BInt = new_primitive_type("int")
1089    BArray10 = new_array_type(new_pointer_type(BInt), 10)
1090    BStruct = new_struct_type("struct foo")
1091    BStructP = new_pointer_type(BStruct)
1092    complete_struct_or_union(BStruct, [('a', BArray10, -1)])
1093    BFunc22 = new_function_type((BStruct, BStruct), BStruct, False)
1094    f = cast(BFunc22, _testfunc(22))
1095    p1 = newp(BStructP, {'a': list(range(100, 110))})
1096    p2 = newp(BStructP, {'a': list(range(1000, 1100, 10))})
1097    res = f(p1[0], p2[0])
1098    for i in range(10):
1099        assert res.a[i] == p1.a[i] - p2.a[i]
1100
1101def test_call_function_23():
1102    BVoid = new_void_type()          # declaring the function as int(void*)
1103    BVoidP = new_pointer_type(BVoid)
1104    BInt = new_primitive_type("int")
1105    BFunc23 = new_function_type((BVoidP,), BInt, False)
1106    f = cast(BFunc23, _testfunc(23))
1107    res = f(b"foo")
1108    assert res == 1000 * ord(b'f')
1109    res = f(cast(BVoidP, 0))        # NULL
1110    assert res == -42
1111    py.test.raises(TypeError, f, None)
1112    py.test.raises(TypeError, f, 0)
1113    py.test.raises(TypeError, f, 0.0)
1114
1115def test_call_function_23_bis():
1116    # declaring the function as int(unsigned char*)
1117    BUChar = new_primitive_type("unsigned char")
1118    BUCharP = new_pointer_type(BUChar)
1119    BInt = new_primitive_type("int")
1120    BFunc23 = new_function_type((BUCharP,), BInt, False)
1121    f = cast(BFunc23, _testfunc(23))
1122    res = f(b"foo")
1123    assert res == 1000 * ord(b'f')
1124
1125def test_call_function_23_bool_array():
1126    # declaring the function as int(_Bool*)
1127    BBool = new_primitive_type("_Bool")
1128    BBoolP = new_pointer_type(BBool)
1129    BInt = new_primitive_type("int")
1130    BFunc23 = new_function_type((BBoolP,), BInt, False)
1131    f = cast(BFunc23, _testfunc(23))
1132    res = f(b"\x01\x01")
1133    assert res == 1000
1134    py.test.raises(ValueError, f, b"\x02\x02")
1135
1136def test_cannot_pass_struct_with_array_of_length_0():
1137    BInt = new_primitive_type("int")
1138    BArray0 = new_array_type(new_pointer_type(BInt), 0)
1139    BStruct = new_struct_type("struct foo")
1140    BStructP = new_pointer_type(BStruct)
1141    complete_struct_or_union(BStruct, [('a', BArray0)])
1142    BFunc = new_function_type((BStruct,), BInt, False)
1143    py.test.raises(NotImplementedError, cast(BFunc, 123), cast(BStructP, 123))
1144    BFunc2 = new_function_type((BInt,), BStruct, False)
1145    py.test.raises(NotImplementedError, cast(BFunc2, 123), 123)
1146
1147def test_call_function_9():
1148    BInt = new_primitive_type("int")
1149    BFunc9 = new_function_type((BInt,), BInt, True)    # vararg
1150    f = cast(BFunc9, _testfunc(9))
1151    assert f(0) == 0
1152    assert f(1, cast(BInt, 42)) == 42
1153    assert f(2, cast(BInt, 40), cast(BInt, 2)) == 42
1154    py.test.raises(TypeError, f, 1, 42)
1155    py.test.raises(TypeError, f, 2, None)
1156    # promotion of chars and shorts to ints
1157    BSChar = new_primitive_type("signed char")
1158    BUChar = new_primitive_type("unsigned char")
1159    BSShort = new_primitive_type("short")
1160    assert f(3, cast(BSChar, -3), cast(BUChar, 200), cast(BSShort, -5)) == 192
1161
1162def test_call_function_24():
1163    BFloat = new_primitive_type("float")
1164    BFloatComplex = new_primitive_type("float _Complex")
1165    BFunc3 = new_function_type((BFloat, BFloat), BFloatComplex, False)
1166    if 0:   # libffi returning nonsense silently, so logic disabled for now
1167        f = cast(BFunc3, _testfunc(24))
1168        result = f(1.25, 5.1)
1169        assert type(result) == complex
1170        assert result.real == 1.25   # exact
1171        assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-5) # inexact
1172    else:
1173        f = cast(BFunc3, _testfunc(9))
1174        py.test.raises(NotImplementedError, f, 12.3, 34.5)
1175
1176def test_call_function_25():
1177    BDouble = new_primitive_type("double")
1178    BDoubleComplex = new_primitive_type("double _Complex")
1179    BFunc3 = new_function_type((BDouble, BDouble), BDoubleComplex, False)
1180    if 0:   # libffi returning nonsense silently, so logic disabled for now
1181        f = cast(BFunc3, _testfunc(25))
1182        result = f(1.25, 5.1)
1183        assert type(result) == complex
1184        assert result.real == 1.25   # exact
1185        assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-10) # inexact
1186    else:
1187        f = cast(BFunc3, _testfunc(9))
1188        py.test.raises(NotImplementedError, f, 12.3, 34.5)
1189
1190def test_cannot_call_with_a_autocompleted_struct():
1191    BSChar = new_primitive_type("signed char")
1192    BDouble = new_primitive_type("double")
1193    BStruct = new_struct_type("struct foo")
1194    BStructPtr = new_pointer_type(BStruct)
1195    complete_struct_or_union(BStruct, [('c', BDouble, -1, 8),
1196                                       ('a', BSChar, -1, 2),
1197                                       ('b', BSChar, -1, 0)])
1198    BFunc = new_function_type((BStruct,), BDouble)   # internally not callable
1199    dummy_func = cast(BFunc, 42)
1200    e = py.test.raises(NotImplementedError, dummy_func, "?")
1201    msg = ("ctype 'struct foo' not supported as argument.  It is a struct "
1202           'declared with "...;", but the C calling convention may depend '
1203           "on the missing fields; or, it contains anonymous struct/unions.  "
1204           "Such structs are only supported as argument if the function is "
1205           "'API mode' and non-variadic (i.e. declared inside ffibuilder."
1206           "cdef()+ffibuilder.set_source() and not taking a final '...' "
1207           "argument)")
1208    assert str(e.value) == msg
1209
1210def test_new_charp():
1211    BChar = new_primitive_type("char")
1212    BCharP = new_pointer_type(BChar)
1213    BCharA = new_array_type(BCharP, None)
1214    x = newp(BCharA, 42)
1215    assert len(x) == 42
1216    x = newp(BCharA, b"foobar")
1217    assert len(x) == 7
1218
1219def test_load_and_call_function():
1220    BChar = new_primitive_type("char")
1221    BCharP = new_pointer_type(BChar)
1222    BLong = new_primitive_type("long")
1223    BFunc = new_function_type((BCharP,), BLong, False)
1224    ll = find_and_load_library('c')
1225    strlen = ll.load_function(BFunc, "strlen")
1226    input = newp(new_array_type(BCharP, None), b"foobar")
1227    assert strlen(input) == 6
1228    #
1229    assert strlen(b"foobarbaz") == 9
1230    #
1231    BVoidP = new_pointer_type(new_void_type())
1232    strlenaddr = ll.load_function(BVoidP, "strlen")
1233    assert strlenaddr == cast(BVoidP, strlen)
1234
1235def test_read_variable():
1236    ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard
1237    ## https://bugs.pypy.org/issue1643
1238    if not sys.platform.startswith("linux"):
1239        py.test.skip("untested")
1240    BVoidP = new_pointer_type(new_void_type())
1241    ll = find_and_load_library('c')
1242    stderr = ll.read_variable(BVoidP, "stderr")
1243    assert stderr == cast(BVoidP, _testfunc(8))
1244    #
1245    ll.close_lib()
1246    py.test.raises(ValueError, ll.read_variable, BVoidP, "stderr")
1247
1248def test_read_variable_as_unknown_length_array():
1249    ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard
1250    ## https://bugs.pypy.org/issue1643
1251    if not sys.platform.startswith("linux"):
1252        py.test.skip("untested")
1253    BCharP = new_pointer_type(new_primitive_type("char"))
1254    BArray = new_array_type(BCharP, None)
1255    ll = find_and_load_library('c')
1256    stderr = ll.read_variable(BArray, "stderr")
1257    assert repr(stderr).startswith("<cdata 'char *' 0x")
1258    # ^^ and not 'char[]', which is basically not allowed and would crash
1259
1260def test_write_variable():
1261    ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard
1262    ## https://bugs.pypy.org/issue1643
1263    if not sys.platform.startswith("linux"):
1264        py.test.skip("untested")
1265    BVoidP = new_pointer_type(new_void_type())
1266    ll = find_and_load_library('c')
1267    stderr = ll.read_variable(BVoidP, "stderr")
1268    ll.write_variable(BVoidP, "stderr", cast(BVoidP, 0))
1269    assert ll.read_variable(BVoidP, "stderr") is not None
1270    assert not ll.read_variable(BVoidP, "stderr")
1271    ll.write_variable(BVoidP, "stderr", stderr)
1272    assert ll.read_variable(BVoidP, "stderr") == stderr
1273    #
1274    ll.close_lib()
1275    py.test.raises(ValueError, ll.write_variable, BVoidP, "stderr", stderr)
1276
1277def test_callback():
1278    BInt = new_primitive_type("int")
1279    def make_callback():
1280        def cb(n):
1281            return n + 1
1282        BFunc = new_function_type((BInt,), BInt, False)
1283        return callback(BFunc, cb, 42)    # 'cb' and 'BFunc' go out of scope
1284    f = make_callback()
1285    assert f(-142) == -141
1286    assert repr(f).startswith(
1287        "<cdata 'int(*)(int)' calling <function ")
1288    assert "cb at 0x" in repr(f)
1289    e = py.test.raises(TypeError, f)
1290    assert str(e.value) == "'int(*)(int)' expects 1 arguments, got 0"
1291
1292def test_callback_exception():
1293    try:
1294        import cStringIO
1295    except ImportError:
1296        import io as cStringIO    # Python 3
1297    import linecache
1298    def matches(istr, ipattern):
1299        str, pattern = istr, ipattern
1300        while '$' in pattern:
1301            i = pattern.index('$')
1302            assert str[:i] == pattern[:i]
1303            j = str.find(pattern[i+1], i)
1304            assert i + 1 <= j <= str.find('\n', i)
1305            str = str[j:]
1306            pattern = pattern[i+1:]
1307        assert str == pattern
1308        return True
1309    def check_value(x):
1310        if x == 10000:
1311            raise ValueError(42)
1312    def Zcb1(x):
1313        check_value(x)
1314        return x * 3
1315    BShort = new_primitive_type("short")
1316    BFunc = new_function_type((BShort,), BShort, False)
1317    f = callback(BFunc, Zcb1, -42)
1318    #
1319    seen = []
1320    oops_result = None
1321    def oops(*args):
1322        seen.append(args)
1323        return oops_result
1324    ff = callback(BFunc, Zcb1, -42, oops)
1325    #
1326    orig_stderr = sys.stderr
1327    orig_getline = linecache.getline
1328    try:
1329        linecache.getline = lambda *args: 'LINE'    # hack: speed up PyPy tests
1330        sys.stderr = cStringIO.StringIO()
1331        assert f(100) == 300
1332        assert sys.stderr.getvalue() == ''
1333        assert f(10000) == -42
1334        assert matches(sys.stderr.getvalue(), """\
1335From cffi callback <function$Zcb1 at 0x$>:
1336Traceback (most recent call last):
1337  File "$", line $, in Zcb1
1338    $
1339  File "$", line $, in check_value
1340    $
1341ValueError: 42
1342""")
1343        sys.stderr = cStringIO.StringIO()
1344        bigvalue = 20000
1345        assert f(bigvalue) == -42
1346        assert matches(sys.stderr.getvalue(), """\
1347From cffi callback <function$Zcb1 at 0x$>:
1348Trying to convert the result back to C:
1349OverflowError: integer 60000 does not fit 'short'
1350""")
1351        sys.stderr = cStringIO.StringIO()
1352        bigvalue = 20000
1353        assert len(seen) == 0
1354        assert ff(bigvalue) == -42
1355        assert sys.stderr.getvalue() == ""
1356        assert len(seen) == 1
1357        exc, val, tb = seen[0]
1358        assert exc is OverflowError
1359        assert str(val) == "integer 60000 does not fit 'short'"
1360        #
1361        sys.stderr = cStringIO.StringIO()
1362        bigvalue = 20000
1363        del seen[:]
1364        oops_result = 81
1365        assert ff(bigvalue) == 81
1366        oops_result = None
1367        assert sys.stderr.getvalue() == ""
1368        assert len(seen) == 1
1369        exc, val, tb = seen[0]
1370        assert exc is OverflowError
1371        assert str(val) == "integer 60000 does not fit 'short'"
1372        #
1373        sys.stderr = cStringIO.StringIO()
1374        bigvalue = 20000
1375        del seen[:]
1376        oops_result = "xy"     # not None and not an int!
1377        assert ff(bigvalue) == -42
1378        oops_result = None
1379        assert matches(sys.stderr.getvalue(), """\
1380From cffi callback <function$Zcb1 at 0x$>:
1381Trying to convert the result back to C:
1382OverflowError: integer 60000 does not fit 'short'
1383
1384During the call to 'onerror', another exception occurred:
1385
1386TypeError: $integer$
1387""")
1388        #
1389        sys.stderr = cStringIO.StringIO()
1390        seen = "not a list"    # this makes the oops() function crash
1391        assert ff(bigvalue) == -42
1392        assert matches(sys.stderr.getvalue(), """\
1393From cffi callback <function$Zcb1 at 0x$>:
1394Trying to convert the result back to C:
1395OverflowError: integer 60000 does not fit 'short'
1396
1397During the call to 'onerror', another exception occurred:
1398
1399Traceback (most recent call last):
1400  File "$", line $, in oops
1401    $
1402AttributeError: 'str' object has no attribute 'append'
1403""")
1404    finally:
1405        sys.stderr = orig_stderr
1406        linecache.getline = orig_getline
1407
1408def test_callback_return_type():
1409    for rettype in ["signed char", "short", "int", "long", "long long",
1410                    "unsigned char", "unsigned short", "unsigned int",
1411                    "unsigned long", "unsigned long long"]:
1412        BRet = new_primitive_type(rettype)
1413        def cb(n):
1414            return n + 1
1415        BFunc = new_function_type((BRet,), BRet)
1416        f = callback(BFunc, cb, 42)
1417        assert f(41) == 42
1418        if rettype.startswith("unsigned "):
1419            min = 0
1420            max = (1 << (8*sizeof(BRet))) - 1
1421        else:
1422            min = -(1 << (8*sizeof(BRet)-1))
1423            max = (1 << (8*sizeof(BRet)-1)) - 1
1424        assert f(min) == min + 1
1425        assert f(max - 1) == max
1426        assert f(max) == 42
1427
1428def test_a_lot_of_callbacks():
1429    BIGNUM = 10000
1430    if 'PY_DOT_PY' in globals(): BIGNUM = 100   # tests on py.py
1431    #
1432    BInt = new_primitive_type("int")
1433    BFunc = new_function_type((BInt,), BInt, False)
1434    def make_callback(m):
1435        def cb(n):
1436            return n + m
1437        return callback(BFunc, cb, 42)    # 'cb' and 'BFunc' go out of scope
1438    #
1439    flist = [make_callback(i) for i in range(BIGNUM)]
1440    for i, f in enumerate(flist):
1441        assert f(-142) == -142 + i
1442
1443def test_callback_receiving_tiny_struct():
1444    BSChar = new_primitive_type("signed char")
1445    BInt = new_primitive_type("int")
1446    BStruct = new_struct_type("struct foo")
1447    BStructPtr = new_pointer_type(BStruct)
1448    complete_struct_or_union(BStruct, [('a', BSChar, -1),
1449                                       ('b', BSChar, -1)])
1450    def cb(s):
1451        return s.a + 10 * s.b
1452    BFunc = new_function_type((BStruct,), BInt)
1453    f = callback(BFunc, cb)
1454    p = newp(BStructPtr, [-2, -4])
1455    n = f(p[0])
1456    assert n == -42
1457
1458def test_callback_returning_tiny_struct():
1459    BSChar = new_primitive_type("signed char")
1460    BInt = new_primitive_type("int")
1461    BStruct = new_struct_type("struct foo")
1462    BStructPtr = new_pointer_type(BStruct)
1463    complete_struct_or_union(BStruct, [('a', BSChar, -1),
1464                                       ('b', BSChar, -1)])
1465    def cb(n):
1466        return newp(BStructPtr, [-n, -3*n])[0]
1467    BFunc = new_function_type((BInt,), BStruct)
1468    f = callback(BFunc, cb)
1469    s = f(10)
1470    assert typeof(s) is BStruct
1471    assert repr(s) == "<cdata 'struct foo' owning 2 bytes>"
1472    assert s.a == -10
1473    assert s.b == -30
1474
1475def test_callback_receiving_struct():
1476    BSChar = new_primitive_type("signed char")
1477    BInt = new_primitive_type("int")
1478    BDouble = new_primitive_type("double")
1479    BStruct = new_struct_type("struct foo")
1480    BStructPtr = new_pointer_type(BStruct)
1481    complete_struct_or_union(BStruct, [('a', BSChar, -1),
1482                                       ('b', BDouble, -1)])
1483    def cb(s):
1484        return s.a + int(s.b)
1485    BFunc = new_function_type((BStruct,), BInt)
1486    f = callback(BFunc, cb)
1487    p = newp(BStructPtr, [-2, 44.444])
1488    n = f(p[0])
1489    assert n == 42
1490
1491def test_callback_returning_struct():
1492    BSChar = new_primitive_type("signed char")
1493    BInt = new_primitive_type("int")
1494    BDouble = new_primitive_type("double")
1495    BStruct = new_struct_type("struct foo")
1496    BStructPtr = new_pointer_type(BStruct)
1497    complete_struct_or_union(BStruct, [('a', BSChar, -1),
1498                                       ('b', BDouble, -1)])
1499    def cb(n):
1500        return newp(BStructPtr, [-n, 1E-42])[0]
1501    BFunc = new_function_type((BInt,), BStruct)
1502    f = callback(BFunc, cb)
1503    s = f(10)
1504    assert typeof(s) is BStruct
1505    assert repr(s) in ["<cdata 'struct foo' owning 12 bytes>",
1506                       "<cdata 'struct foo' owning 16 bytes>"]
1507    assert s.a == -10
1508    assert s.b == 1E-42
1509
1510def test_callback_receiving_big_struct():
1511    BInt = new_primitive_type("int")
1512    BStruct = new_struct_type("struct foo")
1513    BStructPtr = new_pointer_type(BStruct)
1514    complete_struct_or_union(BStruct, [('a', BInt, -1),
1515                                       ('b', BInt, -1),
1516                                       ('c', BInt, -1),
1517                                       ('d', BInt, -1),
1518                                       ('e', BInt, -1),
1519                                       ('f', BInt, -1),
1520                                       ('g', BInt, -1),
1521                                       ('h', BInt, -1),
1522                                       ('i', BInt, -1),
1523                                       ('j', BInt, -1)])
1524    def cb(s):
1525        for i, name in enumerate("abcdefghij"):
1526            assert getattr(s, name) == 13 - i
1527        return 42
1528    BFunc = new_function_type((BStruct,), BInt)
1529    f = callback(BFunc, cb)
1530    p = newp(BStructPtr, list(range(13, 3, -1)))
1531    n = f(p[0])
1532    assert n == 42
1533
1534def test_callback_returning_big_struct():
1535    BInt = new_primitive_type("int")
1536    BStruct = new_struct_type("struct foo")
1537    BStructPtr = new_pointer_type(BStruct)
1538    complete_struct_or_union(BStruct, [('a', BInt, -1),
1539                                       ('b', BInt, -1),
1540                                       ('c', BInt, -1),
1541                                       ('d', BInt, -1),
1542                                       ('e', BInt, -1),
1543                                       ('f', BInt, -1),
1544                                       ('g', BInt, -1),
1545                                       ('h', BInt, -1),
1546                                       ('i', BInt, -1),
1547                                       ('j', BInt, -1)])
1548    def cb():
1549        return newp(BStructPtr, list(range(13, 3, -1)))[0]
1550    BFunc = new_function_type((), BStruct)
1551    f = callback(BFunc, cb)
1552    s = f()
1553    assert typeof(s) is BStruct
1554    assert repr(s) in ["<cdata 'struct foo' owning 40 bytes>",
1555                       "<cdata 'struct foo' owning 80 bytes>"]
1556    for i, name in enumerate("abcdefghij"):
1557        assert getattr(s, name) == 13 - i
1558
1559def test_callback_returning_void():
1560    BVoid = new_void_type()
1561    BFunc = new_function_type((), BVoid, False)
1562    def cb():
1563        seen.append(42)
1564    f = callback(BFunc, cb)
1565    seen = []
1566    f()
1567    assert seen == [42]
1568    py.test.raises(TypeError, callback, BFunc, cb, -42)
1569
1570def test_enum_type():
1571    BUInt = new_primitive_type("unsigned int")
1572    BEnum = new_enum_type("foo", (), (), BUInt)
1573    assert repr(BEnum) == "<ctype 'foo'>"
1574    assert BEnum.kind == "enum"
1575    assert BEnum.cname == "foo"
1576    assert BEnum.elements == {}
1577    #
1578    BInt = new_primitive_type("int")
1579    BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
1580    assert BEnum.kind == "enum"
1581    assert BEnum.cname == "enum foo"
1582    assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'}
1583    # 'elements' is not the real dict, but merely a copy
1584    BEnum.elements[2] = '??'
1585    assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'}
1586    #
1587    BEnum = new_enum_type("enum bar", ('ab', 'cd'), (5, 5), BUInt)
1588    assert BEnum.elements == {5: 'ab'}
1589    assert BEnum.relements == {'ab': 5, 'cd': 5}
1590
1591def test_cast_to_enum():
1592    BInt = new_primitive_type("int")
1593    BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
1594    assert sizeof(BEnum) == sizeof(BInt)
1595    e = cast(BEnum, 0)
1596    assert repr(e) == "<cdata 'enum foo' 0: def>"
1597    assert repr(cast(BEnum, -42)) == "<cdata 'enum foo' -42>"
1598    assert repr(cast(BEnum, -20)) == "<cdata 'enum foo' -20: ab>"
1599    assert string(e) == 'def'
1600    assert string(cast(BEnum, -20)) == 'ab'
1601    assert int(cast(BEnum, 1)) == 1
1602    assert int(cast(BEnum, 0)) == 0
1603    assert int(cast(BEnum, -242 + 2**128)) == -242
1604    assert string(cast(BEnum, -242 + 2**128)) == '-242'
1605    #
1606    BUInt = new_primitive_type("unsigned int")
1607    BEnum = new_enum_type("enum bar", ('def', 'c', 'ab'), (0, 1, 20), BUInt)
1608    e = cast(BEnum, -1)
1609    assert repr(e) == "<cdata 'enum bar' 4294967295>"     # unsigned int
1610    #
1611    BLong = new_primitive_type("long")
1612    BEnum = new_enum_type("enum baz", (), (), BLong)
1613    assert sizeof(BEnum) == sizeof(BLong)
1614    e = cast(BEnum, -1)
1615    assert repr(e) == "<cdata 'enum baz' -1>"
1616
1617def test_enum_with_non_injective_mapping():
1618    BInt = new_primitive_type("int")
1619    BEnum = new_enum_type("enum foo", ('ab', 'cd'), (7, 7), BInt)
1620    e = cast(BEnum, 7)
1621    assert repr(e) == "<cdata 'enum foo' 7: ab>"
1622    assert string(e) == 'ab'
1623
1624def test_enum_in_struct():
1625    BInt = new_primitive_type("int")
1626    BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
1627    BStruct = new_struct_type("struct bar")
1628    BStructPtr = new_pointer_type(BStruct)
1629    complete_struct_or_union(BStruct, [('a1', BEnum, -1)])
1630    p = newp(BStructPtr, [-20])
1631    assert p.a1 == -20
1632    p = newp(BStructPtr, [12])
1633    assert p.a1 == 12
1634    e = py.test.raises(TypeError, newp, BStructPtr, [None])
1635    msg = str(e.value)
1636    assert ("an integer is required" in msg or  # CPython
1637            "unsupported operand type for int(): 'NoneType'" in msg or  # old PyPys
1638            "expected integer, got NoneType object" in msg) # newer PyPys
1639    py.test.raises(TypeError, 'p.a1 = "def"')
1640    if sys.version_info < (3,):
1641        BEnum2 = new_enum_type(unicode("foo"), (unicode('abc'),), (5,), BInt)
1642        assert string(cast(BEnum2, 5)) == 'abc'
1643        assert type(string(cast(BEnum2, 5))) is str
1644
1645def test_enum_overflow():
1646    max_uint = 2 ** (size_of_int()*8) - 1
1647    max_int = max_uint // 2
1648    max_ulong = 2 ** (size_of_long()*8) - 1
1649    max_long = max_ulong // 2
1650    for BPrimitive in [new_primitive_type("int"),
1651                       new_primitive_type("unsigned int"),
1652                       new_primitive_type("long"),
1653                       new_primitive_type("unsigned long")]:
1654        for x in [max_uint, max_int, max_ulong, max_long]:
1655            for testcase in [x, x+1, -x-1, -x-2]:
1656                if int(cast(BPrimitive, testcase)) == testcase:
1657                    # fits
1658                    BEnum = new_enum_type("foo", ("AA",), (testcase,),
1659                                          BPrimitive)
1660                    assert int(cast(BEnum, testcase)) == testcase
1661                else:
1662                    # overflows
1663                    py.test.raises(OverflowError, new_enum_type,
1664                                   "foo", ("AA",), (testcase,), BPrimitive)
1665
1666def test_callback_returning_enum():
1667    BInt = new_primitive_type("int")
1668    BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
1669    def cb(n):
1670        if n & 1:
1671            return cast(BEnum, n)
1672        else:
1673            return n
1674    BFunc = new_function_type((BInt,), BEnum)
1675    f = callback(BFunc, cb)
1676    assert f(0) == 0
1677    assert f(1) == 1
1678    assert f(-20) == -20
1679    assert f(20) == 20
1680    assert f(21) == 21
1681
1682def test_callback_returning_enum_unsigned():
1683    BInt = new_primitive_type("int")
1684    BUInt = new_primitive_type("unsigned int")
1685    BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, 20), BUInt)
1686    def cb(n):
1687        if n & 1:
1688            return cast(BEnum, n)
1689        else:
1690            return n
1691    BFunc = new_function_type((BInt,), BEnum)
1692    f = callback(BFunc, cb)
1693    assert f(0) == 0
1694    assert f(1) == 1
1695    assert f(-21) == 2**32 - 21
1696    assert f(20) == 20
1697    assert f(21) == 21
1698
1699def test_callback_returning_char():
1700    BInt = new_primitive_type("int")
1701    BChar = new_primitive_type("char")
1702    def cb(n):
1703        return bytechr(n)
1704    BFunc = new_function_type((BInt,), BChar)
1705    f = callback(BFunc, cb)
1706    assert f(0) == b'\x00'
1707    assert f(255) == b'\xFF'
1708
1709def _hacked_pypy_uni4():
1710    pyuni4 = {1: True, 2: False}[len(u+'\U00012345')]
1711    return 'PY_DOT_PY' in globals() and not pyuni4
1712
1713def test_callback_returning_wchar_t():
1714    BInt = new_primitive_type("int")
1715    BWChar = new_primitive_type("wchar_t")
1716    def cb(n):
1717        if n == -1:
1718            return u+'\U00012345'
1719        if n == -2:
1720            raise ValueError
1721        return unichr(n)
1722    BFunc = new_function_type((BInt,), BWChar)
1723    f = callback(BFunc, cb)
1724    assert f(0) == unichr(0)
1725    assert f(255) == unichr(255)
1726    assert f(0x1234) == u+'\u1234'
1727    if sizeof(BWChar) == 4 and not _hacked_pypy_uni4():
1728        assert f(-1) == u+'\U00012345'
1729    assert f(-2) == u+'\x00'   # and an exception printed to stderr
1730
1731def test_struct_with_bitfields():
1732    BLong = new_primitive_type("long")
1733    BStruct = new_struct_type("struct foo")
1734    LONGBITS = 8 * sizeof(BLong)
1735    complete_struct_or_union(BStruct, [('a1', BLong, 1),
1736                                       ('a2', BLong, 2),
1737                                       ('a3', BLong, 3),
1738                                       ('a4', BLong, LONGBITS - 5)])
1739    d = BStruct.fields
1740    assert d[0][1].offset == d[1][1].offset == d[2][1].offset == 0
1741    assert d[3][1].offset == sizeof(BLong)
1742    def f(m, r):
1743        if sys.byteorder == 'little':
1744            return r
1745        else:
1746            return LONGBITS - m - r
1747    assert d[0][1].bitshift == f(1, 0)
1748    assert d[0][1].bitsize == 1
1749    assert d[1][1].bitshift == f(2, 1)
1750    assert d[1][1].bitsize == 2
1751    assert d[2][1].bitshift == f(3, 3)
1752    assert d[2][1].bitsize == 3
1753    assert d[3][1].bitshift == f(LONGBITS - 5, 0)
1754    assert d[3][1].bitsize == LONGBITS - 5
1755    assert sizeof(BStruct) == 2 * sizeof(BLong)
1756    assert alignof(BStruct) == alignof(BLong)
1757
1758def test_bitfield_instance():
1759    BInt = new_primitive_type("int")
1760    BUnsignedInt = new_primitive_type("unsigned int")
1761    BStruct = new_struct_type("struct foo")
1762    complete_struct_or_union(BStruct, [('a1', BInt, 1),
1763                                       ('a2', BUnsignedInt, 2),
1764                                       ('a3', BInt, 3)])
1765    p = newp(new_pointer_type(BStruct), None)
1766    p.a1 = -1
1767    assert p.a1 == -1
1768    p.a1 = 0
1769    py.test.raises(OverflowError, "p.a1 = 2")
1770    assert p.a1 == 0
1771    #
1772    p.a1 = -1
1773    p.a2 = 3
1774    p.a3 = -4
1775    py.test.raises(OverflowError, "p.a3 = 4")
1776    e = py.test.raises(OverflowError, "p.a3 = -5")
1777    assert str(e.value) == ("value -5 outside the range allowed by the "
1778                            "bit field width: -4 <= x <= 3")
1779    assert p.a1 == -1 and p.a2 == 3 and p.a3 == -4
1780    #
1781    # special case for convenience: "int x:1", while normally signed,
1782    # allows also setting the value "1" (it still gets read back as -1)
1783    p.a1 = 1
1784    assert p.a1 == -1
1785    e = py.test.raises(OverflowError, "p.a1 = -2")
1786    assert str(e.value) == ("value -2 outside the range allowed by the "
1787                            "bit field width: -1 <= x <= 1")
1788
1789def test_bitfield_instance_init():
1790    BInt = new_primitive_type("int")
1791    BStruct = new_struct_type("struct foo")
1792    complete_struct_or_union(BStruct, [('a1', BInt, 1)])
1793    p = newp(new_pointer_type(BStruct), [-1])
1794    assert p.a1 == -1
1795    p = newp(new_pointer_type(BStruct), {'a1': -1})
1796    assert p.a1 == -1
1797    #
1798    BUnion = new_union_type("union bar")
1799    complete_struct_or_union(BUnion, [('a1', BInt, 1)])
1800    p = newp(new_pointer_type(BUnion), [-1])
1801    assert p.a1 == -1
1802
1803def test_weakref():
1804    import _weakref
1805    BInt = new_primitive_type("int")
1806    BPtr = new_pointer_type(BInt)
1807    rlist = [_weakref.ref(BInt),
1808             _weakref.ref(newp(BPtr, 42)),
1809             _weakref.ref(cast(BPtr, 42)),
1810             _weakref.ref(cast(BInt, 42)),
1811             _weakref.ref(buffer(newp(BPtr, 42))),
1812             ]
1813    for i in range(5):
1814        import gc; gc.collect()
1815        if [r() for r in rlist] == [None for r in rlist]:
1816            break
1817
1818def test_no_inheritance():
1819    BInt = new_primitive_type("int")
1820    try:
1821        class foo(type(BInt)): pass
1822    except TypeError:
1823        pass
1824    else:
1825        raise AssertionError
1826    x = cast(BInt, 42)
1827    try:
1828        class foo(type(x)): pass
1829    except TypeError:
1830        pass
1831    else:
1832        raise AssertionError
1833
1834def test_assign_string():
1835    BChar = new_primitive_type("char")
1836    BArray1 = new_array_type(new_pointer_type(BChar), 5)
1837    BArray2 = new_array_type(new_pointer_type(BArray1), 5)
1838    a = newp(BArray2, [b"abc", b"de", b"ghij"])
1839    assert string(a[1]) == b"de"
1840    assert string(a[2]) == b"ghij"
1841    a[2] = b"."
1842    assert string(a[2]) == b"."
1843    a[2] = b"12345"
1844    assert string(a[2]) == b"12345"
1845    e = py.test.raises(IndexError, 'a[2] = b"123456"')
1846    assert 'char[5]' in str(e.value)
1847    assert 'got 6 characters' in str(e.value)
1848
1849def test_add_error():
1850    x = cast(new_primitive_type("int"), 42)
1851    py.test.raises(TypeError, "x + 1")
1852    py.test.raises(TypeError, "x - 1")
1853
1854def test_void_errors():
1855    py.test.raises(ValueError, alignof, new_void_type())
1856    py.test.raises(TypeError, newp, new_pointer_type(new_void_type()), None)
1857
1858def test_too_many_items():
1859    BChar = new_primitive_type("char")
1860    BArray = new_array_type(new_pointer_type(BChar), 5)
1861    py.test.raises(IndexError, newp, BArray, tuple(b'123456'))
1862    py.test.raises(IndexError, newp, BArray, list(b'123456'))
1863    py.test.raises(IndexError, newp, BArray, b'123456')
1864    BStruct = new_struct_type("struct foo")
1865    complete_struct_or_union(BStruct, [])
1866    py.test.raises(TypeError, newp, new_pointer_type(BStruct), b'')
1867    py.test.raises(ValueError, newp, new_pointer_type(BStruct), [b'1'])
1868
1869def test_more_type_errors():
1870    BInt = new_primitive_type("int")
1871    BChar = new_primitive_type("char")
1872    BArray = new_array_type(new_pointer_type(BChar), 5)
1873    py.test.raises(TypeError, newp, BArray, 12.34)
1874    BArray = new_array_type(new_pointer_type(BInt), 5)
1875    py.test.raises(TypeError, newp, BArray, 12.34)
1876    BFloat = new_primitive_type("float")
1877    py.test.raises(TypeError, cast, BFloat, newp(BArray, None))
1878
1879def test_more_overflow_errors():
1880    BUInt = new_primitive_type("unsigned int")
1881    py.test.raises(OverflowError, newp, new_pointer_type(BUInt), -1)
1882    py.test.raises(OverflowError, newp, new_pointer_type(BUInt), 2**32)
1883
1884def test_newp_copying():
1885    """Test that we can do newp(<type>, <cdata of the given type>) for most
1886    types, including same-type arrays.
1887    """
1888    BInt = new_primitive_type("int")
1889    p = newp(new_pointer_type(BInt), cast(BInt, 42))
1890    assert p[0] == 42
1891    #
1892    BUInt = new_primitive_type("unsigned int")
1893    p = newp(new_pointer_type(BUInt), cast(BUInt, 42))
1894    assert p[0] == 42
1895    #
1896    BChar = new_primitive_type("char")
1897    p = newp(new_pointer_type(BChar), cast(BChar, '!'))
1898    assert p[0] == b'!'
1899    #
1900    BFloat = new_primitive_type("float")
1901    p = newp(new_pointer_type(BFloat), cast(BFloat, 12.25))
1902    assert p[0] == 12.25
1903    #
1904    BStruct = new_struct_type("struct foo_s")
1905    BStructPtr = new_pointer_type(BStruct)
1906    complete_struct_or_union(BStruct, [('a1', BInt, -1)])
1907    s1 = newp(BStructPtr, [42])
1908    p1 = newp(new_pointer_type(BStructPtr), s1)
1909    assert p1[0] == s1
1910    #
1911    BArray = new_array_type(new_pointer_type(BInt), None)
1912    a1 = newp(BArray, [1, 2, 3, 4])
1913    py.test.raises(TypeError, newp, BArray, a1)
1914    BArray6 = new_array_type(new_pointer_type(BInt), 6)
1915    a1 = newp(BArray6, [10, 20, 30])
1916    a2 = newp(BArray6, a1)
1917    assert list(a2) == [10, 20, 30, 0, 0, 0]
1918    #
1919    s1 = newp(BStructPtr, [42])
1920    s2 = newp(BStructPtr, s1[0])
1921    assert s2.a1 == 42
1922    #
1923    BUnion = new_union_type("union foo_u")
1924    BUnionPtr = new_pointer_type(BUnion)
1925    complete_struct_or_union(BUnion, [('a1', BInt, -1)])
1926    u1 = newp(BUnionPtr, [42])
1927    u2 = newp(BUnionPtr, u1[0])
1928    assert u2.a1 == 42
1929    #
1930    BFunc = new_function_type((BInt,), BUInt)
1931    p1 = cast(BFunc, 42)
1932    p2 = newp(new_pointer_type(BFunc), p1)
1933    assert p2[0] == p1
1934
1935def test_string():
1936    BChar = new_primitive_type("char")
1937    assert string(cast(BChar, 42)) == b'*'
1938    assert string(cast(BChar, 0)) == b'\x00'
1939    BCharP = new_pointer_type(BChar)
1940    BArray = new_array_type(BCharP, 10)
1941    a = newp(BArray, b"hello")
1942    assert len(a) == 10
1943    assert string(a) == b"hello"
1944    p = a + 2
1945    assert string(p) == b"llo"
1946    assert string(newp(new_array_type(BCharP, 4), b"abcd")) == b"abcd"
1947    py.test.raises(RuntimeError, string, cast(BCharP, 0))
1948    assert string(a, 4) == b"hell"
1949    assert string(a, 5) == b"hello"
1950    assert string(a, 6) == b"hello"
1951
1952def test_string_byte():
1953    BByte = new_primitive_type("signed char")
1954    assert string(cast(BByte, 42)) == b'*'
1955    assert string(cast(BByte, 0)) == b'\x00'
1956    BArray = new_array_type(new_pointer_type(BByte), None)
1957    a = newp(BArray, [65, 66, 67])
1958    assert type(string(a)) is bytes and string(a) == b'ABC'
1959    #
1960    BByte = new_primitive_type("unsigned char")
1961    assert string(cast(BByte, 42)) == b'*'
1962    assert string(cast(BByte, 0)) == b'\x00'
1963    BArray = new_array_type(new_pointer_type(BByte), None)
1964    a = newp(BArray, [65, 66, 67])
1965    assert type(string(a)) is bytes and string(a) == b'ABC'
1966    if 'PY_DOT_PY' not in globals() and sys.version_info < (3,):
1967        assert string(a, 8).startswith(b'ABC')  # may contain additional garbage
1968
1969def test_string_wchar():
1970    for typename in ["wchar_t", "char16_t", "char32_t"]:
1971        _test_string_wchar_variant(typename)
1972
1973def _test_string_wchar_variant(typename):
1974    BWChar = new_primitive_type(typename)
1975    assert string(cast(BWChar, 42)) == u+'*'
1976    assert string(cast(BWChar, 0x4253)) == u+'\u4253'
1977    assert string(cast(BWChar, 0)) == u+'\x00'
1978    BArray = new_array_type(new_pointer_type(BWChar), None)
1979    a = newp(BArray, [u+'A', u+'B', u+'C'])
1980    assert type(string(a)) is unicode and string(a) == u+'ABC'
1981    if 'PY_DOT_PY' not in globals() and sys.version_info < (3,):
1982        try:
1983            # may contain additional garbage
1984            assert string(a, 8).startswith(u+'ABC')
1985        except ValueError:    # garbage contains values > 0x10FFFF
1986            assert sizeof(BWChar) == 4
1987
1988def test_string_typeerror():
1989    BShort = new_primitive_type("short")
1990    BArray = new_array_type(new_pointer_type(BShort), None)
1991    a = newp(BArray, [65, 66, 67])
1992    py.test.raises(TypeError, string, a)
1993
1994def test_bug_convert_to_ptr():
1995    BChar = new_primitive_type("char")
1996    BCharP = new_pointer_type(BChar)
1997    BDouble = new_primitive_type("double")
1998    x = cast(BDouble, 42)
1999    py.test.raises(TypeError, newp, new_pointer_type(BCharP), x)
2000
2001def test_set_struct_fields():
2002    BChar = new_primitive_type("char")
2003    BCharP = new_pointer_type(BChar)
2004    BCharArray10 = new_array_type(BCharP, 10)
2005    BStruct = new_struct_type("struct foo")
2006    BStructPtr = new_pointer_type(BStruct)
2007    complete_struct_or_union(BStruct, [('a1', BCharArray10, -1)])
2008    p = newp(BStructPtr, None)
2009    assert string(p.a1) == b''
2010    p.a1 = b'foo'
2011    assert string(p.a1) == b'foo'
2012    assert list(p.a1) == [b'f', b'o', b'o'] + [b'\x00'] * 7
2013    p.a1 = [b'x', b'y']
2014    assert string(p.a1) == b'xyo'
2015
2016def test_invalid_function_result_types():
2017    BFunc = new_function_type((), new_void_type())
2018    BArray = new_array_type(new_pointer_type(BFunc), 5)        # works
2019    new_function_type((), BFunc)    # works
2020    new_function_type((), new_primitive_type("int"))
2021    new_function_type((), new_pointer_type(BFunc))
2022    BUnion = new_union_type("union foo_u")
2023    complete_struct_or_union(BUnion, [])
2024    BFunc = new_function_type((), BUnion)
2025    py.test.raises(NotImplementedError, cast(BFunc, 123))
2026    py.test.raises(TypeError, new_function_type, (), BArray)
2027
2028def test_struct_return_in_func():
2029    BChar = new_primitive_type("char")
2030    BShort = new_primitive_type("short")
2031    BFloat = new_primitive_type("float")
2032    BDouble = new_primitive_type("double")
2033    BInt = new_primitive_type("int")
2034    BStruct = new_struct_type("struct foo_s")
2035    complete_struct_or_union(BStruct, [('a1', BChar, -1),
2036                                       ('a2', BShort, -1)])
2037    BFunc10 = new_function_type((BInt,), BStruct)
2038    f = cast(BFunc10, _testfunc(10))
2039    s = f(40)
2040    assert repr(s) == "<cdata 'struct foo_s' owning 4 bytes>"
2041    assert s.a1 == bytechr(40)
2042    assert s.a2 == 40 * 40
2043    #
2044    BStruct11 = new_struct_type("struct test11")
2045    complete_struct_or_union(BStruct11, [('a1', BInt, -1),
2046                                         ('a2', BInt, -1)])
2047    BFunc11 = new_function_type((BInt,), BStruct11)
2048    f = cast(BFunc11, _testfunc(11))
2049    s = f(40)
2050    assert repr(s) == "<cdata 'struct test11' owning 8 bytes>"
2051    assert s.a1 == 40
2052    assert s.a2 == 40 * 40
2053    #
2054    BStruct12 = new_struct_type("struct test12")
2055    complete_struct_or_union(BStruct12, [('a1', BDouble, -1),
2056                                         ])
2057    BFunc12 = new_function_type((BInt,), BStruct12)
2058    f = cast(BFunc12, _testfunc(12))
2059    s = f(40)
2060    assert repr(s) == "<cdata 'struct test12' owning 8 bytes>"
2061    assert s.a1 == 40.0
2062    #
2063    BStruct13 = new_struct_type("struct test13")
2064    complete_struct_or_union(BStruct13, [('a1', BInt, -1),
2065                                         ('a2', BInt, -1),
2066                                         ('a3', BInt, -1)])
2067    BFunc13 = new_function_type((BInt,), BStruct13)
2068    f = cast(BFunc13, _testfunc(13))
2069    s = f(40)
2070    assert repr(s) == "<cdata 'struct test13' owning 12 bytes>"
2071    assert s.a1 == 40
2072    assert s.a2 == 40 * 40
2073    assert s.a3 == 40 * 40 * 40
2074    #
2075    BStruct14 = new_struct_type("struct test14")
2076    complete_struct_or_union(BStruct14, [('a1', BFloat, -1),
2077                                         ])
2078    BFunc14 = new_function_type((BInt,), BStruct14)
2079    f = cast(BFunc14, _testfunc(14))
2080    s = f(40)
2081    assert repr(s) == "<cdata 'struct test14' owning 4 bytes>"
2082    assert s.a1 == 40.0
2083    #
2084    BStruct15 = new_struct_type("struct test15")
2085    complete_struct_or_union(BStruct15, [('a1', BFloat, -1),
2086                                         ('a2', BInt, -1)])
2087    BFunc15 = new_function_type((BInt,), BStruct15)
2088    f = cast(BFunc15, _testfunc(15))
2089    s = f(40)
2090    assert repr(s) == "<cdata 'struct test15' owning 8 bytes>"
2091    assert s.a1 == 40.0
2092    assert s.a2 == 40 * 40
2093    #
2094    BStruct16 = new_struct_type("struct test16")
2095    complete_struct_or_union(BStruct16, [('a1', BFloat, -1),
2096                                         ('a2', BFloat, -1)])
2097    BFunc16 = new_function_type((BInt,), BStruct16)
2098    f = cast(BFunc16, _testfunc(16))
2099    s = f(40)
2100    assert repr(s) == "<cdata 'struct test16' owning 8 bytes>"
2101    assert s.a1 == 40.0
2102    assert s.a2 == -40.0
2103    #
2104    BStruct17 = new_struct_type("struct test17")
2105    complete_struct_or_union(BStruct17, [('a1', BInt, -1),
2106                                         ('a2', BFloat, -1)])
2107    BFunc17 = new_function_type((BInt,), BStruct17)
2108    f = cast(BFunc17, _testfunc(17))
2109    s = f(40)
2110    assert repr(s) == "<cdata 'struct test17' owning 8 bytes>"
2111    assert s.a1 == 40
2112    assert s.a2 == 40.0 * 40.0
2113    #
2114    BStruct17Ptr = new_pointer_type(BStruct17)
2115    BFunc18 = new_function_type((BStruct17Ptr,), BInt)
2116    f = cast(BFunc18, _testfunc(18))
2117    x = f([[40, 2.5]])
2118    assert x == 42
2119    x = f([{'a2': 43.1}])
2120    assert x == 43
2121
2122def test_cast_with_functionptr():
2123    BFunc = new_function_type((), new_void_type())
2124    BFunc2 = new_function_type((), new_primitive_type("short"))
2125    BCharP = new_pointer_type(new_primitive_type("char"))
2126    BIntP = new_pointer_type(new_primitive_type("int"))
2127    BStruct = new_struct_type("struct foo")
2128    BStructPtr = new_pointer_type(BStruct)
2129    complete_struct_or_union(BStruct, [('a1', BFunc, -1)])
2130    newp(BStructPtr, [cast(BFunc, 0)])
2131    newp(BStructPtr, [cast(BCharP, 0)])
2132    py.test.raises(TypeError, newp, BStructPtr, [cast(BIntP, 0)])
2133    py.test.raises(TypeError, newp, BStructPtr, [cast(BFunc2, 0)])
2134
2135def test_wchar():
2136    _test_wchar_variant("wchar_t")
2137    if sys.platform.startswith("linux"):
2138        BWChar = new_primitive_type("wchar_t")
2139        assert sizeof(BWChar) == 4
2140        # wchar_t is often signed on Linux, but not always (e.g. on ARM)
2141        assert int(cast(BWChar, -1)) in (-1, 4294967295)
2142
2143def test_char16():
2144    BChar16 = new_primitive_type("char16_t")
2145    assert sizeof(BChar16) == 2
2146    _test_wchar_variant("char16_t")
2147    assert int(cast(BChar16, -1)) == 0xffff       # always unsigned
2148
2149def test_char32():
2150    BChar32 = new_primitive_type("char32_t")
2151    assert sizeof(BChar32) == 4
2152    _test_wchar_variant("char32_t")
2153    assert int(cast(BChar32, -1)) == 0xffffffff   # always unsigned
2154
2155def _test_wchar_variant(typename):
2156    BWChar = new_primitive_type(typename)
2157    BInt = new_primitive_type("int")
2158    pyuni4 = {1: True, 2: False}[len(u+'\U00012345')]
2159    wchar4 = {2: False, 4: True}[sizeof(BWChar)]
2160    assert str(cast(BWChar, 0x45)) == "<cdata '%s' %s'E'>" % (
2161        typename, mandatory_u_prefix)
2162    assert str(cast(BWChar, 0x1234)) == "<cdata '%s' %s'\u1234'>" % (
2163        typename, mandatory_u_prefix)
2164    if not _hacked_pypy_uni4():
2165        if wchar4:
2166            x = cast(BWChar, 0x12345)
2167            assert str(x) == "<cdata '%s' %s'\U00012345'>" % (
2168                typename, mandatory_u_prefix)
2169            assert int(x) == 0x12345
2170        else:
2171            x = cast(BWChar, 0x18345)
2172            assert str(x) == "<cdata '%s' %s'\u8345'>" % (
2173                typename, mandatory_u_prefix)
2174            assert int(x) == 0x8345
2175    #
2176    BWCharP = new_pointer_type(BWChar)
2177    BStruct = new_struct_type("struct foo_s")
2178    BStructPtr = new_pointer_type(BStruct)
2179    complete_struct_or_union(BStruct, [('a1', BWChar, -1),
2180                                       ('a2', BWCharP, -1)])
2181    s = newp(BStructPtr)
2182    s.a1 = u+'\x00'
2183    assert s.a1 == u+'\x00'
2184    py.test.raises(TypeError, "s.a1 = b'a'")
2185    py.test.raises(TypeError, "s.a1 = bytechr(0xFF)")
2186    s.a1 = u+'\u1234'
2187    assert s.a1 == u+'\u1234'
2188    if pyuni4:
2189        if wchar4:
2190            s.a1 = u+'\U00012345'
2191            assert s.a1 == u+'\U00012345'
2192    elif wchar4:
2193        if not _hacked_pypy_uni4():
2194            s.a1 = cast(BWChar, 0x12345)
2195            assert s.a1 == u+'\ud808\udf45'
2196            s.a1 = u+'\ud807\udf44'
2197            assert s.a1 == u+'\U00011f44'
2198    else:
2199        py.test.raises(TypeError, "s.a1 = u+'\U00012345'")
2200    #
2201    BWCharArray = new_array_type(BWCharP, None)
2202    a = newp(BWCharArray, u+'hello \u1234 world')
2203    assert len(a) == 14   # including the final null
2204    assert string(a) == u+'hello \u1234 world'
2205    a[13] = u+'!'
2206    assert string(a) == u+'hello \u1234 world!'
2207    assert str(a) == repr(a)
2208    assert a[6] == u+'\u1234'
2209    a[6] = u+'-'
2210    assert string(a) == u+'hello - world!'
2211    assert str(a) == repr(a)
2212    #
2213    if wchar4 and not _hacked_pypy_uni4():
2214        u1 = u+'\U00012345\U00012346\U00012347'
2215        a = newp(BWCharArray, u1)
2216        assert len(a) == 4
2217        assert string(a) == u1
2218        assert len(list(a)) == 4
2219        expected = [u+'\U00012345', u+'\U00012346', u+'\U00012347', unichr(0)]
2220        assert list(a) == expected
2221        got = [a[i] for i in range(4)]
2222        assert got == expected
2223        py.test.raises(IndexError, 'a[4]')
2224    #
2225    w = cast(BWChar, 'a')
2226    assert repr(w) == "<cdata '%s' %s'a'>" % (typename, mandatory_u_prefix)
2227    assert str(w) == repr(w)
2228    assert string(w) == u+'a'
2229    assert int(w) == ord('a')
2230    w = cast(BWChar, 0x1234)
2231    assert repr(w) == "<cdata '%s' %s'\u1234'>" % (typename, mandatory_u_prefix)
2232    assert str(w) == repr(w)
2233    assert string(w) == u+'\u1234'
2234    assert int(w) == 0x1234
2235    w = cast(BWChar, u+'\u8234')
2236    assert repr(w) == "<cdata '%s' %s'\u8234'>" % (typename, mandatory_u_prefix)
2237    assert str(w) == repr(w)
2238    assert string(w) == u+'\u8234'
2239    assert int(w) == 0x8234
2240    w = cast(BInt, u+'\u1234')
2241    assert repr(w) == "<cdata 'int' 4660>"
2242    if wchar4 and not _hacked_pypy_uni4():
2243        w = cast(BWChar, u+'\U00012345')
2244        assert repr(w) == "<cdata '%s' %s'\U00012345'>" % (
2245            typename, mandatory_u_prefix)
2246        assert str(w) == repr(w)
2247        assert string(w) == u+'\U00012345'
2248        assert int(w) == 0x12345
2249        w = cast(BInt, u+'\U00012345')
2250        assert repr(w) == "<cdata 'int' 74565>"
2251    py.test.raises(TypeError, cast, BInt, u+'')
2252    py.test.raises(TypeError, cast, BInt, u+'XX')
2253    assert int(cast(BInt, u+'a')) == ord('a')
2254    #
2255    a = newp(BWCharArray, u+'hello - world')
2256    p = cast(BWCharP, a)
2257    assert string(p) == u+'hello - world'
2258    p[6] = u+'\u2345'
2259    assert string(p) == u+'hello \u2345 world'
2260    #
2261    s = newp(BStructPtr, [u+'\u1234', p])
2262    assert s.a1 == u+'\u1234'
2263    assert s.a2 == p
2264    assert str(s.a2) == repr(s.a2)
2265    assert string(s.a2) == u+'hello \u2345 world'
2266    #
2267    q = cast(BWCharP, 0)
2268    assert str(q) == repr(q)
2269    py.test.raises(RuntimeError, string, q)
2270    #
2271    def cb(p):
2272        assert repr(p).startswith("<cdata '%s *' 0x" % typename)
2273        return len(string(p))
2274    BFunc = new_function_type((BWCharP,), BInt, False)
2275    f = callback(BFunc, cb, -42)
2276    assert f(u+'a\u1234b') == 3
2277    #
2278    if wchar4 and not pyuni4 and not _hacked_pypy_uni4():
2279        # try out-of-range wchar_t values
2280        x = cast(BWChar, 1114112)
2281        py.test.raises(ValueError, string, x)
2282        x = cast(BWChar, -1)
2283        py.test.raises(ValueError, string, x)
2284
2285def test_wchar_variants_mix():
2286    BWChar  = new_primitive_type("wchar_t")
2287    BChar16 = new_primitive_type("char16_t")
2288    BChar32 = new_primitive_type("char32_t")
2289    assert int(cast(BChar32, cast(BChar16, -2))) == 0xfffe
2290    assert int(cast(BWChar, cast(BChar16, -2))) == 0xfffe
2291    assert int(cast(BChar16, cast(BChar32, 0x0001f345))) == 0xf345
2292    assert int(cast(BChar16, cast(BWChar, 0x0001f345))) == 0xf345
2293    #
2294    BChar16A = new_array_type(new_pointer_type(BChar16), None)
2295    BChar32A = new_array_type(new_pointer_type(BChar32), None)
2296    x = cast(BChar32, 'A')
2297    py.test.raises(TypeError, newp, BChar16A, [x])
2298    x = cast(BChar16, 'A')
2299    py.test.raises(TypeError, newp, BChar32A, [x])
2300    #
2301    a = newp(BChar16A, u+'\U00012345')
2302    assert len(a) == 3
2303    a = newp(BChar32A, u+'\U00012345')
2304    assert len(a) == 2   # even if the Python unicode string above is 2 chars
2305
2306def test_keepalive_struct():
2307    # exception to the no-keepalive rule: p=newp(BStructPtr) returns a
2308    # pointer owning the memory, and p[0] returns a pointer to the
2309    # struct that *also* owns the memory
2310    BStruct = new_struct_type("struct foo")
2311    BStructPtr = new_pointer_type(BStruct)
2312    complete_struct_or_union(BStruct, [('a1', new_primitive_type("int"), -1),
2313                                       ('a2', new_primitive_type("int"), -1),
2314                                       ('a3', new_primitive_type("int"), -1)])
2315    p = newp(BStructPtr)
2316    assert repr(p) == "<cdata 'struct foo *' owning 12 bytes>"
2317    q = p[0]
2318    assert repr(q) == "<cdata 'struct foo' owning 12 bytes>"
2319    q.a1 = 123456
2320    assert p.a1 == 123456
2321    r = cast(BStructPtr, p)
2322    assert repr(r[0]).startswith("<cdata 'struct foo &' 0x")
2323    del p
2324    import gc; gc.collect()
2325    assert q.a1 == 123456
2326    assert repr(q) == "<cdata 'struct foo' owning 12 bytes>"
2327    assert q.a1 == 123456
2328
2329def test_nokeepalive_struct():
2330    BStruct = new_struct_type("struct foo")
2331    BStructPtr = new_pointer_type(BStruct)
2332    BStructPtrPtr = new_pointer_type(BStructPtr)
2333    complete_struct_or_union(BStruct, [('a1', new_primitive_type("int"), -1)])
2334    p = newp(BStructPtr)
2335    pp = newp(BStructPtrPtr)
2336    pp[0] = p
2337    s = pp[0][0]
2338    assert repr(s).startswith("<cdata 'struct foo &' 0x")
2339
2340def test_owning_repr():
2341    BInt = new_primitive_type("int")
2342    BArray = new_array_type(new_pointer_type(BInt), None)   # int[]
2343    p = newp(BArray, 7)
2344    assert repr(p) == "<cdata 'int[]' owning 28 bytes>"
2345    assert sizeof(p) == 28
2346    #
2347    BArray = new_array_type(new_pointer_type(BInt), 7)   # int[7]
2348    p = newp(BArray, None)
2349    assert repr(p) == "<cdata 'int[7]' owning 28 bytes>"
2350    assert sizeof(p) == 28
2351
2352def test_cannot_dereference_void():
2353    BVoidP = new_pointer_type(new_void_type())
2354    p = cast(BVoidP, 123456)
2355    py.test.raises(TypeError, "p[0]")
2356    p = cast(BVoidP, 0)
2357    py.test.raises((TypeError, RuntimeError), "p[0]")
2358
2359def test_iter():
2360    BInt = new_primitive_type("int")
2361    BIntP = new_pointer_type(BInt)
2362    BArray = new_array_type(BIntP, None)   # int[]
2363    p = newp(BArray, 7)
2364    assert list(p) == list(iter(p)) == [0] * 7
2365    #
2366    py.test.raises(TypeError, iter, cast(BInt, 5))
2367    py.test.raises(TypeError, iter, cast(BIntP, 123456))
2368
2369def test_cmp():
2370    BInt = new_primitive_type("int")
2371    BIntP = new_pointer_type(BInt)
2372    BVoidP = new_pointer_type(new_void_type())
2373    p = newp(BIntP, 123)
2374    q = cast(BInt, 124)
2375    assert (p == q) is False
2376    assert (p != q) is True
2377    assert (q == p) is False
2378    assert (q != p) is True
2379    if strict_compare:
2380        py.test.raises(TypeError, "p < q")
2381        py.test.raises(TypeError, "p <= q")
2382        py.test.raises(TypeError, "q < p")
2383        py.test.raises(TypeError, "q <= p")
2384        py.test.raises(TypeError, "p > q")
2385        py.test.raises(TypeError, "p >= q")
2386    r = cast(BVoidP, p)
2387    assert (p <  r) is False
2388    assert (p <= r) is True
2389    assert (p == r) is True
2390    assert (p != r) is False
2391    assert (p >  r) is False
2392    assert (p >= r) is True
2393    s = newp(BIntP, 125)
2394    assert (p == s) is False
2395    assert (p != s) is True
2396    assert (p < s) is (p <= s) is (s > p) is (s >= p)
2397    assert (p > s) is (p >= s) is (s < p) is (s <= p)
2398    assert (p < s) ^ (p > s)
2399
2400def test_buffer():
2401    try:
2402        import __builtin__
2403    except ImportError:
2404        import builtins as __builtin__
2405    BShort = new_primitive_type("short")
2406    s = newp(new_pointer_type(BShort), 100)
2407    assert sizeof(s) == size_of_ptr()
2408    assert sizeof(BShort) == 2
2409    assert len(buffer(s)) == 2
2410    #
2411    BChar = new_primitive_type("char")
2412    BCharArray = new_array_type(new_pointer_type(BChar), None)
2413    c = newp(BCharArray, b"hi there")
2414    #
2415    buf = buffer(c)
2416    assert repr(buf).startswith('<_cffi_backend.buffer object at 0x')
2417    assert bytes(buf) == b"hi there\x00"
2418    assert type(buf) is buffer
2419    if sys.version_info < (3,):
2420        assert str(buf) == "hi there\x00"
2421        assert unicode(buf) == u+"hi there\x00"
2422    else:
2423        assert str(buf) == repr(buf)
2424    # --mb_length--
2425    assert len(buf) == len(b"hi there\x00")
2426    # --mb_item--
2427    for i in range(-12, 12):
2428        try:
2429            expected = b"hi there\x00"[i]
2430        except IndexError:
2431            py.test.raises(IndexError, "buf[i]")
2432        else:
2433            assert buf[i] == bitem2bchr(expected)
2434    # --mb_slice--
2435    assert buf[:] == b"hi there\x00"
2436    for i in range(-12, 12):
2437        assert buf[i:] == b"hi there\x00"[i:]
2438        assert buf[:i] == b"hi there\x00"[:i]
2439        for j in range(-12, 12):
2440            assert buf[i:j] == b"hi there\x00"[i:j]
2441    # --misc--
2442    assert list(buf) == list(map(bitem2bchr, b"hi there\x00"))
2443    # --mb_as_buffer--
2444    if hasattr(__builtin__, 'buffer'):          # Python <= 2.7
2445        py.test.raises(TypeError, __builtin__.buffer, c)
2446        bf1 = __builtin__.buffer(buf)
2447        assert len(bf1) == len(buf) and bf1[3] == "t"
2448    if hasattr(__builtin__, 'memoryview'):      # Python >= 2.7
2449        py.test.raises(TypeError, memoryview, c)
2450        mv1 = memoryview(buf)
2451        assert len(mv1) == len(buf) and mv1[3] in (b"t", ord(b"t"))
2452    # --mb_ass_item--
2453    expected = list(map(bitem2bchr, b"hi there\x00"))
2454    for i in range(-12, 12):
2455        try:
2456            expected[i] = bytechr(i & 0xff)
2457        except IndexError:
2458            py.test.raises(IndexError, "buf[i] = bytechr(i & 0xff)")
2459        else:
2460            buf[i] = bytechr(i & 0xff)
2461        assert list(buf) == expected
2462    # --mb_ass_slice--
2463    buf[:] = b"hi there\x00"
2464    assert list(buf) == list(c) == list(map(bitem2bchr, b"hi there\x00"))
2465    py.test.raises(ValueError, 'buf[:] = b"shorter"')
2466    py.test.raises(ValueError, 'buf[:] = b"this is much too long!"')
2467    buf[4:2] = b""   # no effect, but should work
2468    assert buf[:] == b"hi there\x00"
2469    buf[:2] = b"HI"
2470    assert buf[:] == b"HI there\x00"
2471    buf[:2] = b"hi"
2472    expected = list(map(bitem2bchr, b"hi there\x00"))
2473    x = 0
2474    for i in range(-12, 12):
2475        for j in range(-12, 12):
2476            start = i if i >= 0 else i + len(buf)
2477            stop  = j if j >= 0 else j + len(buf)
2478            start = max(0, min(len(buf), start))
2479            stop  = max(0, min(len(buf), stop))
2480            sample = bytechr(x & 0xff) * (stop - start)
2481            x += 1
2482            buf[i:j] = sample
2483            expected[i:j] = map(bitem2bchr, sample)
2484            assert list(buf) == expected
2485
2486def test_getcname():
2487    BUChar = new_primitive_type("unsigned char")
2488    BArray = new_array_type(new_pointer_type(BUChar), 123)
2489    assert getcname(BArray, "<-->") == "unsigned char<-->[123]"
2490
2491def test_errno():
2492    BVoid = new_void_type()
2493    BFunc5 = new_function_type((), BVoid)
2494    f = cast(BFunc5, _testfunc(5))
2495    set_errno(50)
2496    f()
2497    assert get_errno() == 65
2498    f(); f()
2499    assert get_errno() == 95
2500
2501def test_errno_callback():
2502    if globals().get('PY_DOT_PY') == '2.5':
2503        py.test.skip("cannot run this test on py.py with Python 2.5")
2504    set_errno(95)
2505    def cb():
2506        e = get_errno()
2507        set_errno(e - 6)
2508    BVoid = new_void_type()
2509    BFunc5 = new_function_type((), BVoid)
2510    f = callback(BFunc5, cb)
2511    f()
2512    assert get_errno() == 89
2513    f(); f()
2514    assert get_errno() == 77
2515
2516def test_cast_to_array():
2517    # not valid in C!  extension to get a non-owning <cdata 'int[3]'>
2518    BInt = new_primitive_type("int")
2519    BIntP = new_pointer_type(BInt)
2520    BArray = new_array_type(BIntP, 3)
2521    x = cast(BArray, 0)
2522    assert repr(x) == "<cdata 'int[3]' NULL>"
2523
2524def test_cast_invalid():
2525    BStruct = new_struct_type("struct foo")
2526    complete_struct_or_union(BStruct, [])
2527    p = cast(new_pointer_type(BStruct), 123456)
2528    s = p[0]
2529    py.test.raises(TypeError, cast, BStruct, s)
2530
2531def test_bug_float_convertion():
2532    BDouble = new_primitive_type("double")
2533    BDoubleP = new_pointer_type(BDouble)
2534    py.test.raises(TypeError, newp, BDoubleP, "foobar")
2535
2536def test_bug_delitem():
2537    BChar = new_primitive_type("char")
2538    BCharP = new_pointer_type(BChar)
2539    x = newp(BCharP)
2540    py.test.raises(TypeError, "del x[0]")
2541
2542def test_bug_delattr():
2543    BLong = new_primitive_type("long")
2544    BStruct = new_struct_type("struct foo")
2545    complete_struct_or_union(BStruct, [('a1', BLong, -1)])
2546    x = newp(new_pointer_type(BStruct))
2547    py.test.raises(AttributeError, "del x.a1")
2548
2549def test_variable_length_struct():
2550    py.test.skip("later")
2551    BLong = new_primitive_type("long")
2552    BArray = new_array_type(new_pointer_type(BLong), None)
2553    BStruct = new_struct_type("struct foo")
2554    BStructP = new_pointer_type(BStruct)
2555    complete_struct_or_union(BStruct, [('a1', BLong, -1),
2556                                       ('a2', BArray, -1)])
2557    assert sizeof(BStruct) == size_of_long()
2558    assert alignof(BStruct) == alignof(BLong)
2559    #
2560    py.test.raises(TypeError, newp, BStructP, None)
2561    x = newp(BStructP, 5)
2562    assert sizeof(x) == 6 * size_of_long()
2563    x[4] = 123
2564    assert x[4] == 123
2565    py.test.raises(IndexError, "x[5]")
2566    assert len(x.a2) == 5
2567    #
2568    py.test.raises(TypeError, newp, BStructP, [123])
2569    x = newp(BStructP, [123, 5])
2570    assert x.a1 == 123
2571    assert len(x.a2) == 5
2572    assert list(x.a2) == [0] * 5
2573    #
2574    x = newp(BStructP, {'a2': 5})
2575    assert x.a1 == 0
2576    assert len(x.a2) == 5
2577    assert list(x.a2) == [0] * 5
2578    #
2579    x = newp(BStructP, [123, (4, 5)])
2580    assert x.a1 == 123
2581    assert len(x.a2) == 2
2582    assert list(x.a2) == [4, 5]
2583    #
2584    x = newp(BStructP, {'a2': (4, 5)})
2585    assert x.a1 == 0
2586    assert len(x.a2) == 2
2587    assert list(x.a2) == [4, 5]
2588
2589def test_autocast_int():
2590    BInt = new_primitive_type("int")
2591    BIntPtr = new_pointer_type(BInt)
2592    BLongLong = new_primitive_type("long long")
2593    BULongLong = new_primitive_type("unsigned long long")
2594    BULongLongPtr = new_pointer_type(BULongLong)
2595    x = newp(BIntPtr, cast(BInt, 42))
2596    assert x[0] == 42
2597    x = newp(BIntPtr, cast(BLongLong, 42))
2598    assert x[0] == 42
2599    x = newp(BIntPtr, cast(BULongLong, 42))
2600    assert x[0] == 42
2601    x = newp(BULongLongPtr, cast(BInt, 42))
2602    assert x[0] == 42
2603    py.test.raises(OverflowError, newp, BULongLongPtr, cast(BInt, -42))
2604    x = cast(BInt, cast(BInt, 42))
2605    assert int(x) == 42
2606    x = cast(BInt, cast(BLongLong, 42))
2607    assert int(x) == 42
2608    x = cast(BInt, cast(BULongLong, 42))
2609    assert int(x) == 42
2610    x = cast(BULongLong, cast(BInt, 42))
2611    assert int(x) == 42
2612    x = cast(BULongLong, cast(BInt, -42))
2613    assert int(x) == 2 ** 64 - 42
2614    x = cast(BIntPtr, cast(BInt, 42))
2615    assert int(cast(BInt, x)) == 42
2616
2617def test_autocast_float():
2618    BFloat = new_primitive_type("float")
2619    BDouble = new_primitive_type("float")
2620    BFloatPtr = new_pointer_type(BFloat)
2621    x = newp(BFloatPtr, cast(BDouble, 12.5))
2622    assert x[0] == 12.5
2623    x = cast(BFloat, cast(BDouble, 12.5))
2624    assert float(x) == 12.5
2625
2626def test_longdouble():
2627    py_py = 'PY_DOT_PY' in globals()
2628    BInt = new_primitive_type("int")
2629    BLongDouble = new_primitive_type("long double")
2630    BLongDoublePtr = new_pointer_type(BLongDouble)
2631    BLongDoubleArray = new_array_type(BLongDoublePtr, None)
2632    a = newp(BLongDoubleArray, 1)
2633    x = a[0]
2634    if not py_py:
2635        assert repr(x).startswith("<cdata 'long double' 0.0")
2636    assert float(x) == 0.0
2637    assert int(x) == 0
2638    #
2639    b = newp(BLongDoubleArray, [1.23])
2640    x = b[0]
2641    if not py_py:
2642        assert repr(x).startswith("<cdata 'long double' 1.23")
2643    assert float(x) == 1.23
2644    assert int(x) == 1
2645    #
2646    BFunc19 = new_function_type((BLongDouble, BInt), BLongDouble)
2647    f = cast(BFunc19, _testfunc(19))
2648    start = lstart = 1.5
2649    for i in range(107):
2650        start = 4 * start - start * start
2651        lstart = f(lstart, 1)
2652    lother = f(1.5, 107)
2653    if not py_py:
2654        assert float(lstart) == float(lother)
2655        assert repr(lstart) == repr(lother)
2656        if sizeof(BLongDouble) > sizeof(new_primitive_type("double")):
2657            assert float(lstart) != start
2658            assert repr(lstart).startswith("<cdata 'long double' ")
2659    #
2660    c = newp(BLongDoubleArray, [lstart])
2661    x = c[0]
2662    assert float(f(lstart, 107)) == float(f(x, 107))
2663
2664def test_get_array_of_length_zero():
2665    for length in [0, 5, 10]:
2666        BLong = new_primitive_type("long")
2667        BLongP = new_pointer_type(BLong)
2668        BArray0 = new_array_type(BLongP, length)
2669        BStruct = new_struct_type("struct foo")
2670        BStructPtr = new_pointer_type(BStruct)
2671        complete_struct_or_union(BStruct, [('a1', BArray0, -1)])
2672        p = newp(BStructPtr, None)
2673        if length == 0:
2674            assert repr(p.a1).startswith("<cdata 'long *' 0x")
2675        else:
2676            assert repr(p.a1).startswith("<cdata 'long[%d]' 0x" % length)
2677
2678def test_nested_anonymous_struct():
2679    BInt = new_primitive_type("int")
2680    BChar = new_primitive_type("char")
2681    BStruct = new_struct_type("struct foo")
2682    BInnerStruct = new_struct_type("struct foo")
2683    complete_struct_or_union(BInnerStruct, [('a1', BInt, -1),
2684                                            ('a2', BChar, -1)])
2685    complete_struct_or_union(BStruct, [('', BInnerStruct, -1),
2686                                       ('a3', BChar, -1)])
2687    assert sizeof(BInnerStruct) == sizeof(BInt) * 2   # with alignment
2688    assert sizeof(BStruct) == sizeof(BInt) * 3        # 'a3' is placed after
2689    d = BStruct.fields
2690    assert len(d) == 3
2691    assert d[0][0] == 'a1'
2692    assert d[0][1].type is BInt
2693    assert d[0][1].offset == 0
2694    assert d[0][1].bitshift == -1
2695    assert d[0][1].bitsize == -1
2696    assert d[1][0] == 'a2'
2697    assert d[1][1].type is BChar
2698    assert d[1][1].offset == sizeof(BInt)
2699    assert d[1][1].bitshift == -1
2700    assert d[1][1].bitsize == -1
2701    assert d[2][0] == 'a3'
2702    assert d[2][1].type is BChar
2703    assert d[2][1].offset == sizeof(BInt) * 2
2704    assert d[2][1].bitshift == -1
2705    assert d[2][1].bitsize == -1
2706
2707def test_nested_anonymous_struct_2():
2708    BInt = new_primitive_type("int")
2709    BStruct = new_struct_type("struct foo")
2710    BInnerUnion = new_union_type("union bar")
2711    complete_struct_or_union(BInnerUnion, [('a1', BInt, -1),
2712                                           ('a2', BInt, -1)])
2713    complete_struct_or_union(BStruct, [('b1', BInt, -1),
2714                                       ('', BInnerUnion, -1),
2715                                       ('b2', BInt, -1)])
2716    assert sizeof(BInnerUnion) == sizeof(BInt)
2717    assert sizeof(BStruct) == sizeof(BInt) * 3
2718    fields = [(name, fld.offset, fld.flags) for (name, fld) in BStruct.fields]
2719    assert fields == [
2720        ('b1', 0 * sizeof(BInt), 0),
2721        ('a1', 1 * sizeof(BInt), 0),
2722        ('a2', 1 * sizeof(BInt), 1),
2723        ('b2', 2 * sizeof(BInt), 0),
2724    ]
2725
2726def test_sizeof_union():
2727    # a union has the largest alignment of its members, and a total size
2728    # that is the largest of its items *possibly further aligned* if
2729    # another smaller item has a larger alignment...
2730    BChar = new_primitive_type("char")
2731    BShort = new_primitive_type("short")
2732    assert sizeof(BShort) == alignof(BShort) == 2
2733    BStruct = new_struct_type("struct foo")
2734    complete_struct_or_union(BStruct, [('a1', BChar),
2735                                       ('a2', BChar),
2736                                       ('a3', BChar)])
2737    assert sizeof(BStruct) == 3 and alignof(BStruct) == 1
2738    BUnion = new_union_type("union u")
2739    complete_struct_or_union(BUnion, [('s', BStruct),
2740                                      ('i', BShort)])
2741    assert sizeof(BUnion) == 4
2742    assert alignof(BUnion) == 2
2743
2744def test_unaligned_struct():
2745    BInt = new_primitive_type("int")
2746    BStruct = new_struct_type("struct foo")
2747    complete_struct_or_union(BStruct, [('b', BInt, -1, 1)],
2748                             None, 5, 1)
2749
2750def test_CData_CType():
2751    CData, CType = _get_types()
2752    BChar = new_primitive_type("char")
2753    BCharP = new_pointer_type(BChar)
2754    nullchr = cast(BChar, 0)
2755    chrref = newp(BCharP, None)
2756    assert isinstance(nullchr, CData)
2757    assert isinstance(chrref, CData)
2758    assert not isinstance(BChar, CData)
2759    assert not isinstance(nullchr, CType)
2760    assert not isinstance(chrref, CType)
2761    assert isinstance(BChar, CType)
2762
2763def test_no_cdata_float():
2764    BInt = new_primitive_type("int")
2765    BIntP = new_pointer_type(BInt)
2766    BUInt = new_primitive_type("unsigned int")
2767    BUIntP = new_pointer_type(BUInt)
2768    BFloat = new_primitive_type("float")
2769    py.test.raises(TypeError, newp, BIntP, cast(BFloat, 0.0))
2770    py.test.raises(TypeError, newp, BUIntP, cast(BFloat, 0.0))
2771
2772def test_bool():
2773    BBool = new_primitive_type("_Bool")
2774    BBoolP = new_pointer_type(BBool)
2775    assert int(cast(BBool, False)) == 0
2776    assert int(cast(BBool, True)) == 1
2777    assert bool(cast(BBool, False)) is False    # since 1.7
2778    assert bool(cast(BBool, True)) is True
2779    assert int(cast(BBool, 3)) == 1
2780    assert int(cast(BBool, long(3))) == 1
2781    assert int(cast(BBool, long(10)**4000)) == 1
2782    assert int(cast(BBool, -0.1)) == 1
2783    assert int(cast(BBool, -0.0)) == 0
2784    assert int(cast(BBool, '\x00')) == 0
2785    assert int(cast(BBool, '\xff')) == 1
2786    assert newp(BBoolP, False)[0] == 0
2787    assert newp(BBoolP, True)[0] == 1
2788    assert newp(BBoolP, 0)[0] == 0
2789    assert newp(BBoolP, 1)[0] == 1
2790    py.test.raises(TypeError, newp, BBoolP, 1.0)
2791    py.test.raises(TypeError, newp, BBoolP, '\x00')
2792    py.test.raises(OverflowError, newp, BBoolP, 2)
2793    py.test.raises(OverflowError, newp, BBoolP, -1)
2794    BCharP = new_pointer_type(new_primitive_type("char"))
2795    p = newp(BCharP, b'\x01')
2796    q = cast(BBoolP, p)
2797    assert q[0] is True
2798    p = newp(BCharP, b'\x00')
2799    q = cast(BBoolP, p)
2800    assert q[0] is False
2801    py.test.raises(TypeError, string, cast(BBool, False))
2802    BDouble = new_primitive_type("double")
2803    assert int(cast(BBool, cast(BDouble, 0.1))) == 1
2804    assert int(cast(BBool, cast(BDouble, 0.0))) == 0
2805    BBoolA = new_array_type(BBoolP, None)
2806    p = newp(BBoolA, b'\x01\x00')
2807    assert p[0] is True
2808    assert p[1] is False
2809
2810def test_bool_forbidden_cases():
2811    BBool = new_primitive_type("_Bool")
2812    BBoolP = new_pointer_type(BBool)
2813    BBoolA = new_array_type(BBoolP, None)
2814    BCharP = new_pointer_type(new_primitive_type("char"))
2815    p = newp(BCharP, b'X')
2816    q = cast(BBoolP, p)
2817    py.test.raises(ValueError, "q[0]")
2818    py.test.raises(TypeError, newp, BBoolP, b'\x00')
2819    assert newp(BBoolP, 0)[0] is False
2820    assert newp(BBoolP, 1)[0] is True
2821    py.test.raises(OverflowError, newp, BBoolP, 2)
2822    py.test.raises(OverflowError, newp, BBoolP, -1)
2823    py.test.raises(ValueError, newp, BBoolA, b'\x00\x01\x02')
2824    py.test.raises(OverflowError, newp, BBoolA, [0, 1, 2])
2825    py.test.raises(TypeError, string, newp(BBoolP, 1))
2826    py.test.raises(TypeError, string, newp(BBoolA, [1]))
2827
2828def test_typeoffsetof():
2829    BChar = new_primitive_type("char")
2830    BStruct = new_struct_type("struct foo")
2831    BStructPtr = new_pointer_type(BStruct)
2832    complete_struct_or_union(BStruct, [('a1', BChar, -1),
2833                                       ('a2', BChar, -1),
2834                                       ('a3', BChar, -1)])
2835    py.test.raises(TypeError, typeoffsetof, BStructPtr, None)
2836    py.test.raises(TypeError, typeoffsetof, BStruct, None)
2837    assert typeoffsetof(BStructPtr, 'a1') == (BChar, 0)
2838    assert typeoffsetof(BStruct, 'a1') == (BChar, 0)
2839    assert typeoffsetof(BStructPtr, 'a2') == (BChar, 1)
2840    assert typeoffsetof(BStruct, 'a3') == (BChar, 2)
2841    assert typeoffsetof(BStructPtr, 'a2', 0) == (BChar, 1)
2842    assert typeoffsetof(BStruct, u+'a3') == (BChar, 2)
2843    py.test.raises(TypeError, typeoffsetof, BStructPtr, 'a2', 1)
2844    py.test.raises(KeyError, typeoffsetof, BStructPtr, 'a4')
2845    py.test.raises(KeyError, typeoffsetof, BStruct, 'a5')
2846    py.test.raises(TypeError, typeoffsetof, BStruct, 42)
2847    py.test.raises(TypeError, typeoffsetof, BChar, 'a1')
2848
2849def test_typeoffsetof_array():
2850    BInt = new_primitive_type("int")
2851    BIntP = new_pointer_type(BInt)
2852    BArray = new_array_type(BIntP, None)
2853    py.test.raises(TypeError, typeoffsetof, BArray, None)
2854    py.test.raises(TypeError, typeoffsetof, BArray, 'a1')
2855    assert typeoffsetof(BArray, 51) == (BInt, 51 * size_of_int())
2856    assert typeoffsetof(BIntP, 51) == (BInt, 51 * size_of_int())
2857    assert typeoffsetof(BArray, -51) == (BInt, -51 * size_of_int())
2858    MAX = sys.maxsize // size_of_int()
2859    assert typeoffsetof(BArray, MAX) == (BInt, MAX * size_of_int())
2860    assert typeoffsetof(BIntP, MAX) == (BInt, MAX * size_of_int())
2861    py.test.raises(OverflowError, typeoffsetof, BArray, MAX + 1)
2862
2863def test_typeoffsetof_no_bitfield():
2864    BInt = new_primitive_type("int")
2865    BStruct = new_struct_type("struct foo")
2866    complete_struct_or_union(BStruct, [('a1', BInt, 4)])
2867    py.test.raises(TypeError, typeoffsetof, BStruct, 'a1')
2868
2869def test_rawaddressof():
2870    BChar = new_primitive_type("char")
2871    BCharP = new_pointer_type(BChar)
2872    BStruct = new_struct_type("struct foo")
2873    BStructPtr = new_pointer_type(BStruct)
2874    complete_struct_or_union(BStruct, [('a1', BChar, -1),
2875                                       ('a2', BChar, -1),
2876                                       ('a3', BChar, -1)])
2877    p = newp(BStructPtr)
2878    assert repr(p) == "<cdata 'struct foo *' owning 3 bytes>"
2879    s = p[0]
2880    assert repr(s) == "<cdata 'struct foo' owning 3 bytes>"
2881    a = rawaddressof(BStructPtr, s, 0)
2882    assert repr(a).startswith("<cdata 'struct foo *' 0x")
2883    py.test.raises(TypeError, rawaddressof, BStruct, s, 0)
2884    b = rawaddressof(BCharP, s, 0)
2885    assert b == cast(BCharP, p)
2886    c = rawaddressof(BStructPtr, a, 0)
2887    assert c == a
2888    py.test.raises(TypeError, rawaddressof, BStructPtr, cast(BChar, '?'), 0)
2889    #
2890    d = rawaddressof(BCharP, s, 1)
2891    assert d == cast(BCharP, p) + 1
2892    #
2893    e = cast(BCharP, 109238)
2894    f = rawaddressof(BCharP, e, 42)
2895    assert f == e + 42
2896    #
2897    BCharA = new_array_type(BCharP, None)
2898    e = newp(BCharA, 50)
2899    f = rawaddressof(BCharP, e, 42)
2900    assert f == e + 42
2901
2902def test_newp_signed_unsigned_char():
2903    BCharArray = new_array_type(
2904        new_pointer_type(new_primitive_type("char")), None)
2905    p = newp(BCharArray, b"foo")
2906    assert len(p) == 4
2907    assert list(p) == [b"f", b"o", b"o", b"\x00"]
2908    #
2909    BUCharArray = new_array_type(
2910        new_pointer_type(new_primitive_type("unsigned char")), None)
2911    p = newp(BUCharArray, b"fo\xff")
2912    assert len(p) == 4
2913    assert list(p) == [ord("f"), ord("o"), 0xff, 0]
2914    #
2915    BSCharArray = new_array_type(
2916        new_pointer_type(new_primitive_type("signed char")), None)
2917    p = newp(BSCharArray, b"fo\xff")
2918    assert len(p) == 4
2919    assert list(p) == [ord("f"), ord("o"), -1, 0]
2920
2921def test_newp_from_bytearray_doesnt_work():
2922    BCharArray = new_array_type(
2923        new_pointer_type(new_primitive_type("char")), None)
2924    py.test.raises(TypeError, newp, BCharArray, bytearray(b"foo"))
2925    p = newp(BCharArray, 5)
2926    buffer(p)[:] = bytearray(b"foo.\x00")
2927    assert len(p) == 5
2928    assert list(p) == [b"f", b"o", b"o", b".", b"\x00"]
2929    p[1:3] = bytearray(b"XY")
2930    assert list(p) == [b"f", b"X", b"Y", b".", b"\x00"]
2931
2932def test_string_assignment_to_byte_array():
2933    BByteArray = new_array_type(
2934        new_pointer_type(new_primitive_type("unsigned char")), None)
2935    p = newp(BByteArray, 5)
2936    p[0:3] = bytearray(b"XYZ")
2937    assert list(p) == [ord("X"), ord("Y"), ord("Z"), 0, 0]
2938
2939# XXX hack
2940if sys.version_info >= (3,):
2941    try:
2942        import posix, io
2943        posix.fdopen = io.open
2944    except ImportError:
2945        pass   # win32
2946
2947def test_FILE():
2948    if sys.platform == "win32":
2949        py.test.skip("testing FILE not implemented")
2950    #
2951    BFILE = new_struct_type("struct _IO_FILE")
2952    BFILEP = new_pointer_type(BFILE)
2953    BChar = new_primitive_type("char")
2954    BCharP = new_pointer_type(BChar)
2955    BInt = new_primitive_type("int")
2956    BFunc = new_function_type((BCharP, BFILEP), BInt, False)
2957    BFunc2 = new_function_type((BFILEP, BCharP), BInt, True)
2958    ll = find_and_load_library('c')
2959    fputs = ll.load_function(BFunc, "fputs")
2960    fscanf = ll.load_function(BFunc2, "fscanf")
2961    #
2962    import posix
2963    fdr, fdw = posix.pipe()
2964    fr1 = posix.fdopen(fdr, 'rb', 256)
2965    fw1 = posix.fdopen(fdw, 'wb', 256)
2966    #
2967    fw1.write(b"X")
2968    res = fputs(b"hello world\n", fw1)
2969    assert res >= 0
2970    fw1.flush()     # should not be needed
2971    #
2972    p = newp(new_array_type(BCharP, 100), None)
2973    res = fscanf(fr1, b"%s\n", p)
2974    assert res == 1
2975    assert string(p) == b"Xhello"
2976    fr1.close()
2977    fw1.close()
2978
2979def test_FILE_only_for_FILE_arg():
2980    if sys.platform == "win32":
2981        py.test.skip("testing FILE not implemented")
2982    #
2983    B_NOT_FILE = new_struct_type("struct NOT_FILE")
2984    B_NOT_FILEP = new_pointer_type(B_NOT_FILE)
2985    BChar = new_primitive_type("char")
2986    BCharP = new_pointer_type(BChar)
2987    BInt = new_primitive_type("int")
2988    BFunc = new_function_type((BCharP, B_NOT_FILEP), BInt, False)
2989    ll = find_and_load_library('c')
2990    fputs = ll.load_function(BFunc, "fputs")
2991    #
2992    import posix
2993    fdr, fdw = posix.pipe()
2994    fr1 = posix.fdopen(fdr, 'r')
2995    fw1 = posix.fdopen(fdw, 'w')
2996    #
2997    e = py.test.raises(TypeError, fputs, b"hello world\n", fw1)
2998    assert str(e.value).startswith(
2999        "initializer for ctype 'struct NOT_FILE *' must "
3000        "be a cdata pointer, not ")
3001
3002def test_FILE_object():
3003    if sys.platform == "win32":
3004        py.test.skip("testing FILE not implemented")
3005    #
3006    BFILE = new_struct_type("FILE")
3007    BFILEP = new_pointer_type(BFILE)
3008    BChar = new_primitive_type("char")
3009    BCharP = new_pointer_type(BChar)
3010    BInt = new_primitive_type("int")
3011    BFunc = new_function_type((BCharP, BFILEP), BInt, False)
3012    BFunc2 = new_function_type((BFILEP,), BInt, False)
3013    ll = find_and_load_library('c')
3014    fputs = ll.load_function(BFunc, "fputs")
3015    fileno = ll.load_function(BFunc2, "fileno")
3016    #
3017    import posix
3018    fdr, fdw = posix.pipe()
3019    fw1 = posix.fdopen(fdw, 'wb', 256)
3020    #
3021    fw1p = cast(BFILEP, fw1)
3022    fw1.write(b"X")
3023    fw1.flush()
3024    res = fputs(b"hello\n", fw1p)
3025    assert res >= 0
3026    res = fileno(fw1p)
3027    assert (res == fdw) == (sys.version_info < (3,))
3028    fw1.close()
3029    #
3030    data = posix.read(fdr, 256)
3031    assert data == b"Xhello\n"
3032    posix.close(fdr)
3033
3034def test_errno_saved():
3035    set_errno(42)
3036    # a random function that will reset errno to 0 (at least on non-windows)
3037    import os; os.stat('.')
3038    #
3039    res = get_errno()
3040    assert res == 42
3041
3042def test_GetLastError():
3043    if sys.platform != "win32":
3044        py.test.skip("GetLastError(): only for Windows")
3045    #
3046    lib = find_and_load_library('KERNEL32.DLL')
3047    BInt = new_primitive_type("int")
3048    BVoid = new_void_type()
3049    BFunc1 = new_function_type((BInt,), BVoid, False)
3050    BFunc2 = new_function_type((), BInt, False)
3051    SetLastError = lib.load_function(BFunc1, "SetLastError")
3052    GetLastError = lib.load_function(BFunc2, "GetLastError")
3053    #
3054    SetLastError(42)
3055    # a random function that will reset the real GetLastError() to 0
3056    import nt; nt.stat('.')
3057    #
3058    res = GetLastError()
3059    assert res == 42
3060    #
3061    SetLastError(2)
3062    code, message = getwinerror()
3063    assert code == 2
3064    assert message == "The system cannot find the file specified"
3065    #
3066    code, message = getwinerror(1155)
3067    assert code == 1155
3068    assert message == ("No application is associated with the "
3069                       "specified file for this operation")
3070
3071def test_nonstandard_integer_types():
3072    for typename in ['int8_t', 'uint8_t', 'int16_t', 'uint16_t', 'int32_t',
3073                     'uint32_t', 'int64_t', 'uint64_t', 'intptr_t',
3074                     'uintptr_t', 'ptrdiff_t', 'size_t', 'ssize_t',
3075                     'int_least8_t',  'uint_least8_t',
3076                     'int_least16_t', 'uint_least16_t',
3077                     'int_least32_t', 'uint_least32_t',
3078                     'int_least64_t', 'uint_least64_t',
3079                     'int_fast8_t',  'uint_fast8_t',
3080                     'int_fast16_t', 'uint_fast16_t',
3081                     'int_fast32_t', 'uint_fast32_t',
3082                     'int_fast64_t', 'uint_fast64_t',
3083                     'intmax_t', 'uintmax_t']:
3084        new_primitive_type(typename)    # works
3085
3086def test_cannot_convert_unicode_to_charp():
3087    BCharP = new_pointer_type(new_primitive_type("char"))
3088    BCharArray = new_array_type(BCharP, None)
3089    py.test.raises(TypeError, newp, BCharArray, u+'foobar')
3090
3091def test_buffer_keepalive():
3092    BCharP = new_pointer_type(new_primitive_type("char"))
3093    BCharArray = new_array_type(BCharP, None)
3094    buflist = []
3095    for i in range(20):
3096        c = newp(BCharArray, str2bytes("hi there %d" % i))
3097        buflist.append(buffer(c))
3098    import gc; gc.collect()
3099    for i in range(20):
3100        buf = buflist[i]
3101        assert buf[:] == str2bytes("hi there %d\x00" % i)
3102
3103def test_slice():
3104    BIntP = new_pointer_type(new_primitive_type("int"))
3105    BIntArray = new_array_type(BIntP, None)
3106    c = newp(BIntArray, 5)
3107    assert len(c) == 5
3108    assert repr(c) == "<cdata 'int[]' owning 20 bytes>"
3109    d = c[1:4]
3110    assert len(d) == 3
3111    assert repr(d) == "<cdata 'int[]' sliced length 3>"
3112    d[0] = 123
3113    d[2] = 456
3114    assert c[1] == 123
3115    assert c[3] == 456
3116    assert d[2] == 456
3117    py.test.raises(IndexError, "d[3]")
3118    py.test.raises(IndexError, "d[-1]")
3119
3120def test_slice_ptr():
3121    BIntP = new_pointer_type(new_primitive_type("int"))
3122    BIntArray = new_array_type(BIntP, None)
3123    c = newp(BIntArray, 5)
3124    d = (c+1)[0:2]
3125    assert len(d) == 2
3126    assert repr(d) == "<cdata 'int[]' sliced length 2>"
3127    d[1] += 50
3128    assert c[2] == 50
3129
3130def test_slice_array_checkbounds():
3131    BIntP = new_pointer_type(new_primitive_type("int"))
3132    BIntArray = new_array_type(BIntP, None)
3133    c = newp(BIntArray, 5)
3134    c[0:5]
3135    assert len(c[5:5]) == 0
3136    py.test.raises(IndexError, "c[-1:1]")
3137    cp = c + 0
3138    cp[-1:1]
3139
3140def test_nonstandard_slice():
3141    BIntP = new_pointer_type(new_primitive_type("int"))
3142    BIntArray = new_array_type(BIntP, None)
3143    c = newp(BIntArray, 5)
3144    e = py.test.raises(IndexError, "c[:5]")
3145    assert str(e.value) == "slice start must be specified"
3146    e = py.test.raises(IndexError, "c[4:]")
3147    assert str(e.value) == "slice stop must be specified"
3148    e = py.test.raises(IndexError, "c[1:2:3]")
3149    assert str(e.value) == "slice with step not supported"
3150    e = py.test.raises(IndexError, "c[1:2:1]")
3151    assert str(e.value) == "slice with step not supported"
3152    e = py.test.raises(IndexError, "c[4:2]")
3153    assert str(e.value) == "slice start > stop"
3154    e = py.test.raises(IndexError, "c[6:6]")
3155    assert str(e.value) == "index too large (expected 6 <= 5)"
3156
3157def test_setslice():
3158    BIntP = new_pointer_type(new_primitive_type("int"))
3159    BIntArray = new_array_type(BIntP, None)
3160    c = newp(BIntArray, 5)
3161    c[1:3] = [100, 200]
3162    assert list(c) == [0, 100, 200, 0, 0]
3163    cp = c + 3
3164    cp[-1:1] = [300, 400]
3165    assert list(c) == [0, 100, 300, 400, 0]
3166    cp[-1:1] = iter([500, 600])
3167    assert list(c) == [0, 100, 500, 600, 0]
3168    py.test.raises(ValueError, "cp[-1:1] = [1000]")
3169    assert list(c) == [0, 100, 1000, 600, 0]
3170    py.test.raises(ValueError, "cp[-1:1] = (700, 800, 900)")
3171    assert list(c) == [0, 100, 700, 800, 0]
3172
3173def test_setslice_array():
3174    BIntP = new_pointer_type(new_primitive_type("int"))
3175    BIntArray = new_array_type(BIntP, None)
3176    c = newp(BIntArray, 5)
3177    d = newp(BIntArray, [10, 20, 30])
3178    c[1:4] = d
3179    assert list(c) == [0, 10, 20, 30, 0]
3180    #
3181    BShortP = new_pointer_type(new_primitive_type("short"))
3182    BShortArray = new_array_type(BShortP, None)
3183    d = newp(BShortArray, [40, 50])
3184    c[1:3] = d
3185    assert list(c) == [0, 40, 50, 30, 0]
3186
3187def test_cdata_name_module_doc():
3188    p = new_primitive_type("signed char")
3189    x = cast(p, 17)
3190    assert x.__module__ == '_cffi_backend'
3191    assert x.__name__ == '<cdata>'
3192    assert hasattr(x, '__doc__')
3193
3194def test_different_types_of_ptr_equality():
3195    BVoidP = new_pointer_type(new_void_type())
3196    BIntP = new_pointer_type(new_primitive_type("int"))
3197    x = cast(BVoidP, 12345)
3198    assert x == cast(BIntP, 12345)
3199    assert x != cast(BIntP, 12344)
3200    assert hash(x) == hash(cast(BIntP, 12345))
3201
3202def test_new_handle():
3203    import _weakref
3204    BVoidP = new_pointer_type(new_void_type())
3205    BCharP = new_pointer_type(new_primitive_type("char"))
3206    class mylist(list):
3207        pass
3208    o = mylist([2, 3, 4])
3209    x = newp_handle(BVoidP, o)
3210    assert repr(x) == "<cdata 'void *' handle to [2, 3, 4]>"
3211    assert x
3212    assert from_handle(x) is o
3213    assert from_handle(cast(BCharP, x)) is o
3214    wr = _weakref.ref(o)
3215    del o
3216    import gc; gc.collect()
3217    assert wr() is not None
3218    assert from_handle(x) == list((2, 3, 4))
3219    assert from_handle(cast(BCharP, x)) == list((2, 3, 4))
3220    del x
3221    for i in range(3):
3222        if wr() is not None:
3223            import gc; gc.collect()
3224    assert wr() is None
3225    py.test.raises(RuntimeError, from_handle, cast(BCharP, 0))
3226
3227def test_new_handle_cycle():
3228    import _weakref
3229    BVoidP = new_pointer_type(new_void_type())
3230    class A(object):
3231        pass
3232    o = A()
3233    o.cycle = newp_handle(BVoidP, o)
3234    wr = _weakref.ref(o)
3235    del o
3236    for i in range(3):
3237        if wr() is not None:
3238            import gc; gc.collect()
3239    assert wr() is None
3240
3241def _test_bitfield_details(flag):
3242    BChar = new_primitive_type("char")
3243    BShort = new_primitive_type("short")
3244    BInt = new_primitive_type("int")
3245    BUInt = new_primitive_type("unsigned int")
3246    BStruct = new_struct_type("struct foo1")
3247    complete_struct_or_union(BStruct, [('a', BChar, -1),
3248                                       ('b1', BInt, 9),
3249                                       ('b2', BUInt, 7),
3250                                       ('c', BChar, -1)], -1, -1, -1, flag)
3251    if not (flag & SF_MSVC_BITFIELDS):   # gcc, any variant
3252        assert typeoffsetof(BStruct, 'c') == (BChar, 3)
3253        assert sizeof(BStruct) == 4
3254    else:               # msvc
3255        assert typeoffsetof(BStruct, 'c') == (BChar, 8)
3256        assert sizeof(BStruct) == 12
3257    assert alignof(BStruct) == 4
3258    #
3259    p = newp(new_pointer_type(BStruct), None)
3260    p.a = b'A'
3261    p.b1 = -201
3262    p.b2 = 99
3263    p.c = b'\x9D'
3264    raw = buffer(p)[:]
3265    if sys.byteorder == 'little':
3266        if flag & SF_MSVC_BITFIELDS:
3267            assert raw == b'A\x00\x00\x007\xC7\x00\x00\x9D\x00\x00\x00'
3268        elif flag & SF_GCC_LITTLE_ENDIAN:
3269            assert raw == b'A7\xC7\x9D'
3270        elif flag & SF_GCC_BIG_ENDIAN:
3271            assert raw == b'A\xE3\x9B\x9D'
3272        else:
3273            raise AssertionError("bad flag")
3274    else:
3275        if flag & SF_MSVC_BITFIELDS:
3276            assert raw == b'A\x00\x00\x00\x00\x00\xC77\x9D\x00\x00\x00'
3277        elif flag & SF_GCC_LITTLE_ENDIAN:
3278            assert raw == b'A\xC77\x9D'
3279        elif flag & SF_GCC_BIG_ENDIAN:
3280            assert raw == b'A\x9B\xE3\x9D'
3281        else:
3282            raise AssertionError("bad flag")
3283    #
3284    BStruct = new_struct_type("struct foo2")
3285    complete_struct_or_union(BStruct, [('a', BChar, -1),
3286                                       ('',  BShort, 9),
3287                                       ('c', BChar, -1)], -1, -1, -1, flag)
3288    assert typeoffsetof(BStruct, 'c') == (BChar, 4)
3289    if flag & SF_MSVC_BITFIELDS:
3290        assert sizeof(BStruct) == 6
3291        assert alignof(BStruct) == 2
3292    elif flag & SF_GCC_X86_BITFIELDS:
3293        assert sizeof(BStruct) == 5
3294        assert alignof(BStruct) == 1
3295    elif flag & SF_GCC_ARM_BITFIELDS:
3296        assert sizeof(BStruct) == 6
3297        assert alignof(BStruct) == 2
3298    else:
3299        raise AssertionError("bad flag")
3300    #
3301    BStruct = new_struct_type("struct foo2")
3302    complete_struct_or_union(BStruct, [('a', BChar, -1),
3303                                       ('',  BInt, 0),
3304                                       ('',  BInt, 0),
3305                                       ('c', BChar, -1)], -1, -1, -1, flag)
3306    if flag & SF_MSVC_BITFIELDS:
3307        assert typeoffsetof(BStruct, 'c') == (BChar, 1)
3308        assert sizeof(BStruct) == 2
3309        assert alignof(BStruct) == 1
3310    elif flag & SF_GCC_X86_BITFIELDS:
3311        assert typeoffsetof(BStruct, 'c') == (BChar, 4)
3312        assert sizeof(BStruct) == 5
3313        assert alignof(BStruct) == 1
3314    elif flag & SF_GCC_ARM_BITFIELDS:
3315        assert typeoffsetof(BStruct, 'c') == (BChar, 4)
3316        assert sizeof(BStruct) == 8
3317        assert alignof(BStruct) == 4
3318    else:
3319        raise AssertionError("bad flag")
3320
3321
3322SF_MSVC_BITFIELDS     = 0x01
3323SF_GCC_ARM_BITFIELDS  = 0x02
3324SF_GCC_X86_BITFIELDS  = 0x10
3325
3326SF_GCC_BIG_ENDIAN     = 0x04
3327SF_GCC_LITTLE_ENDIAN  = 0x40
3328
3329SF_PACKED             = 0x08
3330
3331def test_bitfield_as_x86_gcc():
3332    _test_bitfield_details(flag=SF_GCC_X86_BITFIELDS|SF_GCC_LITTLE_ENDIAN)
3333
3334def test_bitfield_as_msvc():
3335    _test_bitfield_details(flag=SF_MSVC_BITFIELDS|SF_GCC_LITTLE_ENDIAN)
3336
3337def test_bitfield_as_arm_gcc():
3338    _test_bitfield_details(flag=SF_GCC_ARM_BITFIELDS|SF_GCC_LITTLE_ENDIAN)
3339
3340def test_bitfield_as_ppc_gcc():
3341    # PowerPC uses the same format as X86, but is big-endian
3342    _test_bitfield_details(flag=SF_GCC_X86_BITFIELDS|SF_GCC_BIG_ENDIAN)
3343
3344
3345def test_struct_array_no_length():
3346    BInt = new_primitive_type("int")
3347    BIntP = new_pointer_type(BInt)
3348    BArray = new_array_type(BIntP, None)
3349    BStruct = new_struct_type("foo")
3350    py.test.raises(TypeError, complete_struct_or_union,
3351                   BStruct, [('x', BArray),
3352                             ('y', BInt)])
3353    #
3354    BStruct = new_struct_type("foo")
3355    complete_struct_or_union(BStruct, [('x', BInt),
3356                                       ('y', BArray)])
3357    assert sizeof(BStruct) == size_of_int()
3358    d = BStruct.fields
3359    assert len(d) == 2
3360    assert d[0][0] == 'x'
3361    assert d[0][1].type is BInt
3362    assert d[0][1].offset == 0
3363    assert d[0][1].bitshift == -1
3364    assert d[0][1].bitsize == -1
3365    assert d[1][0] == 'y'
3366    assert d[1][1].type is BArray
3367    assert d[1][1].offset == size_of_int()
3368    assert d[1][1].bitshift == -2
3369    assert d[1][1].bitsize == -1
3370    #
3371    p = newp(new_pointer_type(BStruct))
3372    p.x = 42
3373    assert p.x == 42
3374    assert typeof(p.y) is BArray
3375    assert len(p.y) == 0
3376    assert p.y == cast(BIntP, p) + 1
3377    #
3378    p = newp(new_pointer_type(BStruct), [100])
3379    assert p.x == 100
3380    assert len(p.y) == 0
3381    #
3382    # Tests for
3383    #    ffi.new("struct_with_var_array *", [field.., [the_array_items..]])
3384    #    ffi.new("struct_with_var_array *", [field.., array_size])
3385    plist = []
3386    for i in range(20):
3387        if i % 2 == 0:
3388            p = newp(new_pointer_type(BStruct), [100, [200, i, 400]])
3389        else:
3390            p = newp(new_pointer_type(BStruct), [100, 3])
3391            p.y[1] = i
3392            p.y[0] = 200
3393            assert p.y[2] == 0
3394            p.y[2] = 400
3395        assert len(p.y) == 3
3396        assert len(p[0].y) == 3
3397        assert len(buffer(p)) == sizeof(BInt) * 4
3398        assert sizeof(p[0]) == sizeof(BInt) * 4
3399        plist.append(p)
3400    for i in range(20):
3401        p = plist[i]
3402        assert p.x == 100
3403        assert p.y[0] == 200
3404        assert p.y[1] == i
3405        assert p.y[2] == 400
3406        assert list(p.y) == [200, i, 400]
3407    #
3408    # the following assignment works, as it normally would, for any array field
3409    p.y = [501, 601]
3410    assert list(p.y) == [501, 601, 400]
3411    p[0].y = [500, 600]
3412    assert list(p[0].y) == [500, 600, 400]
3413    assert repr(p) == "<cdata 'foo *' owning %d bytes>" % (
3414        sizeof(BStruct) + 3 * sizeof(BInt),)
3415    assert repr(p[0]) == "<cdata 'foo' owning %d bytes>" % (
3416        sizeof(BStruct) + 3 * sizeof(BInt),)
3417    assert sizeof(p[0]) == sizeof(BStruct) + 3 * sizeof(BInt)
3418    #
3419    # from a non-owning pointer, we can't get the length
3420    q = cast(new_pointer_type(BStruct), p)
3421    assert q.y[0] == 500
3422    assert q[0].y[0] == 500
3423    py.test.raises(TypeError, len, q.y)
3424    py.test.raises(TypeError, len, q[0].y)
3425    assert typeof(q.y) is BIntP
3426    assert typeof(q[0].y) is BIntP
3427    assert sizeof(q[0]) == sizeof(BStruct)
3428    #
3429    # error cases
3430    py.test.raises(IndexError, "p.y[4]")
3431    py.test.raises(TypeError, "p.y = cast(BIntP, 0)")
3432    py.test.raises(TypeError, "p.y = 15")
3433    py.test.raises(TypeError, "p.y = None")
3434    #
3435    # accepting this may be specified by the C99 standard,
3436    # or a GCC strangeness...
3437    BStruct2 = new_struct_type("bar")
3438    complete_struct_or_union(BStruct2, [('f', BStruct),
3439                                        ('n', BInt)])
3440    p = newp(new_pointer_type(BStruct2), {'n': 42})
3441    assert p.n == 42
3442    #
3443    # more error cases
3444    py.test.raises(TypeError, newp, new_pointer_type(BStruct), [100, None])
3445    BArray4 = new_array_type(BIntP, 4)
3446    BStruct4 = new_struct_type("test4")
3447    complete_struct_or_union(BStruct4, [('a', BArray4)])   # not varsized
3448    py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [None])
3449    py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [4])
3450    p = newp(new_pointer_type(BStruct4), [[10, 20, 30]])
3451    assert p.a[0] == 10
3452    assert p.a[1] == 20
3453    assert p.a[2] == 30
3454    assert p.a[3] == 0
3455
3456def test_struct_array_no_length_explicit_position():
3457    BInt = new_primitive_type("int")
3458    BIntP = new_pointer_type(BInt)
3459    BArray = new_array_type(BIntP, None)
3460    BStruct = new_struct_type("foo")
3461    complete_struct_or_union(BStruct, [('x', BArray, -1, 0), # actually 3 items
3462                                       ('y', BInt, -1, 12)])
3463    p = newp(new_pointer_type(BStruct), [[10, 20], 30])
3464    assert p.x[0] == 10
3465    assert p.x[1] == 20
3466    assert p.x[2] == 0
3467    assert p.y == 30
3468    p = newp(new_pointer_type(BStruct), {'x': [40], 'y': 50})
3469    assert p.x[0] == 40
3470    assert p.x[1] == 0
3471    assert p.x[2] == 0
3472    assert p.y == 50
3473    p = newp(new_pointer_type(BStruct), {'y': 60})
3474    assert p.x[0] == 0
3475    assert p.x[1] == 0
3476    assert p.x[2] == 0
3477    assert p.y == 60
3478    #
3479    # This "should" work too, allocating a larger structure
3480    # (a bit strange in this case, but useful in general)
3481    plist = []
3482    for i in range(20):
3483        p = newp(new_pointer_type(BStruct), [[10, 20, 30, 40, 50, 60, 70]])
3484        plist.append(p)
3485    for i in range(20):
3486        p = plist[i]
3487        assert p.x[0] == 10
3488        assert p.x[1] == 20
3489        assert p.x[2] == 30
3490        assert p.x[3] == 40 == p.y
3491        assert p.x[4] == 50
3492        assert p.x[5] == 60
3493        assert p.x[6] == 70
3494
3495def test_struct_array_not_aligned():
3496    # struct a { int x; char y; char z[]; };
3497    # ends up of size 8, but 'z' is at offset 5
3498    BChar = new_primitive_type("char")
3499    BInt = new_primitive_type("int")
3500    BCharP = new_pointer_type(BChar)
3501    BArray = new_array_type(BCharP, None)
3502    BStruct = new_struct_type("foo")
3503    complete_struct_or_union(BStruct, [('x', BInt),
3504                                       ('y', BChar),
3505                                       ('z', BArray)])
3506    assert sizeof(BStruct) == 2 * size_of_int()
3507    def offsetof(BType, fieldname):
3508        return typeoffsetof(BType, fieldname)[1]
3509    base = offsetof(BStruct, 'z')
3510    assert base == size_of_int() + 1
3511    #
3512    p = newp(new_pointer_type(BStruct), {'z': 3})
3513    assert sizeof(p[0]) == base + 3
3514    q = newp(new_pointer_type(BStruct), {'z': size_of_int()})
3515    assert sizeof(q) == size_of_ptr()
3516    assert sizeof(q[0]) == base + size_of_int()
3517    assert len(p.z) == 3
3518    assert len(p[0].z) == 3
3519    assert len(q.z) == size_of_int()
3520    assert len(q[0].z) == size_of_int()
3521
3522def test_ass_slice():
3523    BChar = new_primitive_type("char")
3524    BArray = new_array_type(new_pointer_type(BChar), None)
3525    p = newp(BArray, b"foobar")
3526    p[2:5] = [b"*", b"Z", b"T"]
3527    p[1:3] = b"XY"
3528    assert list(p) == [b"f", b"X", b"Y", b"Z", b"T", b"r", b"\x00"]
3529    py.test.raises(TypeError, "p[1:5] = u+'XYZT'")
3530    py.test.raises(TypeError, "p[1:5] = [1, 2, 3, 4]")
3531    #
3532    for typename in ["wchar_t", "char16_t", "char32_t"]:
3533        BUniChar = new_primitive_type(typename)
3534        BArray = new_array_type(new_pointer_type(BUniChar), None)
3535        p = newp(BArray, u+"foobar")
3536        p[2:5] = [u+"*", u+"Z", u+"T"]
3537        p[1:3] = u+"XY"
3538        assert list(p) == [u+"f", u+"X", u+"Y", u+"Z", u+"T", u+"r", u+"\x00"]
3539        py.test.raises(TypeError, "p[1:5] = b'XYZT'")
3540        py.test.raises(TypeError, "p[1:5] = [1, 2, 3, 4]")
3541
3542def test_void_p_arithmetic():
3543    BVoid = new_void_type()
3544    BInt = new_primitive_type("intptr_t")
3545    p = cast(new_pointer_type(BVoid), 100000)
3546    assert int(cast(BInt, p)) == 100000
3547    assert int(cast(BInt, p + 42)) == 100042
3548    assert int(cast(BInt, p - (-42))) == 100042
3549    assert (p + 42) - p == 42
3550    q = cast(new_pointer_type(new_primitive_type("char")), 100000)
3551    py.test.raises(TypeError, "p - q")
3552    py.test.raises(TypeError, "q - p")
3553    py.test.raises(TypeError, "p + cast(new_primitive_type('int'), 42)")
3554    py.test.raises(TypeError, "p - cast(new_primitive_type('int'), 42)")
3555
3556def test_sizeof_sliced_array():
3557    BInt = new_primitive_type("int")
3558    BArray = new_array_type(new_pointer_type(BInt), 10)
3559    p = newp(BArray, None)
3560    assert sizeof(p[2:9]) == 7 * sizeof(BInt)
3561
3562def test_packed():
3563    BLong = new_primitive_type("long")
3564    BChar = new_primitive_type("char")
3565    BShort = new_primitive_type("short")
3566    for extra_args in [(SF_PACKED,), (0, 1)]:
3567        BStruct = new_struct_type("struct foo")
3568        complete_struct_or_union(BStruct, [('a1', BLong, -1),
3569                                           ('a2', BChar, -1),
3570                                           ('a3', BShort, -1)],
3571                                 None, -1, -1, *extra_args)
3572        d = BStruct.fields
3573        assert len(d) == 3
3574        assert d[0][0] == 'a1'
3575        assert d[0][1].type is BLong
3576        assert d[0][1].offset == 0
3577        assert d[0][1].bitshift == -1
3578        assert d[0][1].bitsize == -1
3579        assert d[1][0] == 'a2'
3580        assert d[1][1].type is BChar
3581        assert d[1][1].offset == sizeof(BLong)
3582        assert d[1][1].bitshift == -1
3583        assert d[1][1].bitsize == -1
3584        assert d[2][0] == 'a3'
3585        assert d[2][1].type is BShort
3586        assert d[2][1].offset == sizeof(BLong) + sizeof(BChar)
3587        assert d[2][1].bitshift == -1
3588        assert d[2][1].bitsize == -1
3589        assert sizeof(BStruct) == sizeof(BLong) + sizeof(BChar) + sizeof(BShort)
3590        assert alignof(BStruct) == 1
3591    #
3592    BStruct2 = new_struct_type("struct foo")
3593    complete_struct_or_union(BStruct2, [('b1', BChar, -1),
3594                                        ('b2', BLong, -1)],
3595                             None, -1, -1, 0, 2)
3596    d = BStruct2.fields
3597    assert len(d) == 2
3598    assert d[0][0] == 'b1'
3599    assert d[0][1].type is BChar
3600    assert d[0][1].offset == 0
3601    assert d[0][1].bitshift == -1
3602    assert d[0][1].bitsize == -1
3603    assert d[1][0] == 'b2'
3604    assert d[1][1].type is BLong
3605    assert d[1][1].offset == 2
3606    assert d[1][1].bitshift == -1
3607    assert d[1][1].bitsize == -1
3608    assert sizeof(BStruct2) == 2 + sizeof(BLong)
3609    assert alignof(BStruct2) == 2
3610
3611def test_packed_with_bitfields():
3612    if sys.platform == "win32":
3613        py.test.skip("testing gcc behavior")
3614    BLong = new_primitive_type("long")
3615    BChar = new_primitive_type("char")
3616    BStruct = new_struct_type("struct foo")
3617    py.test.raises(NotImplementedError,
3618                   complete_struct_or_union,
3619                   BStruct, [('a1', BLong, 30),
3620                             ('a2', BChar, 5)],
3621                   None, -1, -1, SF_PACKED)
3622
3623def test_from_buffer():
3624    import array
3625    a = array.array('H', [10000, 20000, 30000])
3626    BChar = new_primitive_type("char")
3627    BCharP = new_pointer_type(BChar)
3628    BCharA = new_array_type(BCharP, None)
3629    c = from_buffer(BCharA, a)
3630    assert typeof(c) is BCharA
3631    assert len(c) == 6
3632    assert repr(c) == "<cdata 'char[]' buffer len 6 from 'array.array' object>"
3633    p = new_pointer_type(new_primitive_type("unsigned short"))
3634    cast(p, c)[1] += 500
3635    assert list(a) == [10000, 20500, 30000]
3636
3637def test_from_buffer_not_str_unicode():
3638    BChar = new_primitive_type("char")
3639    BCharP = new_pointer_type(BChar)
3640    BCharA = new_array_type(BCharP, None)
3641    p1 = from_buffer(BCharA, b"foo")
3642    assert p1 == from_buffer(BCharA, b"foo")
3643    import gc; gc.collect()
3644    assert p1 == from_buffer(BCharA, b"foo")
3645    py.test.raises(TypeError, from_buffer, BCharA, u+"foo")
3646    try:
3647        from __builtin__ import buffer
3648    except ImportError:
3649        pass
3650    else:
3651        # Python 2 only
3652        contents = from_buffer(BCharA, buffer(b"foo"))
3653        assert len(contents) == len(p1)
3654        for i in range(len(contents)):
3655            assert contents[i] == p1[i]
3656        p4 = buffer(u+"foo")
3657        contents = from_buffer(BCharA, buffer(u+"foo"))
3658        assert len(contents) == len(p4)
3659        for i in range(len(contents)):
3660            assert contents[i] == p4[i]
3661    try:
3662        from __builtin__ import memoryview
3663    except ImportError:
3664        pass
3665    else:
3666        contents = from_buffer(BCharA, memoryview(b"foo"))
3667        assert len(contents) == len(p1)
3668        for i in range(len(contents)):
3669            assert contents[i] == p1[i]
3670
3671
3672def test_from_buffer_bytearray():
3673    a = bytearray(b"xyz")
3674    BChar = new_primitive_type("char")
3675    BCharP = new_pointer_type(BChar)
3676    BCharA = new_array_type(BCharP, None)
3677    p = from_buffer(BCharA, a)
3678    assert typeof(p) is BCharA
3679    assert len(p) == 3
3680    assert repr(p) == "<cdata 'char[]' buffer len 3 from 'bytearray' object>"
3681    assert p[2] == b"z"
3682    p[2] = b"."
3683    assert a[2] == ord(".")
3684    a[2] = ord("?")
3685    assert p[2] == b"?"
3686
3687def test_from_buffer_more_cases():
3688    try:
3689        from _cffi_backend import _testbuff
3690    except ImportError:
3691        py.test.skip("not for pypy")
3692    BChar = new_primitive_type("char")
3693    BCharP = new_pointer_type(BChar)
3694    BCharA = new_array_type(BCharP, None)
3695    #
3696    def check1(bufobj, expected):
3697        c = from_buffer(BCharA, bufobj)
3698        assert typeof(c) is BCharA
3699        if sys.version_info >= (3,):
3700            expected = [bytes(c, "ascii") for c in expected]
3701        assert list(c) == list(expected)
3702    #
3703    def check(methods, expected, expected_for_memoryview=None):
3704        if sys.version_info >= (3,):
3705            if methods <= 7:
3706                return
3707            if expected_for_memoryview is not None:
3708                expected = expected_for_memoryview
3709        class X(object):
3710            pass
3711        _testbuff(X, methods)
3712        bufobj = X()
3713        check1(bufobj, expected)
3714        try:
3715            from __builtin__ import buffer
3716            bufobjb = buffer(bufobj)
3717        except (TypeError, ImportError):
3718            pass
3719        else:
3720            check1(bufobjb, expected)
3721        try:
3722            bufobjm = memoryview(bufobj)
3723        except (TypeError, NameError):
3724            pass
3725        else:
3726            check1(bufobjm, expected_for_memoryview or expected)
3727    #
3728    check(1, "RDB")
3729    check(2, "WRB")
3730    check(4, "CHB")
3731    check(8, "GTB")
3732    check(16, "ROB")
3733    #
3734    check(1 | 2,  "RDB")
3735    check(1 | 4,  "RDB")
3736    check(2 | 4,  "CHB")
3737    check(1 | 8,  "RDB", "GTB")
3738    check(1 | 16, "RDB", "ROB")
3739    check(2 | 8,  "WRB", "GTB")
3740    check(2 | 16, "WRB", "ROB")
3741    check(4 | 8,  "CHB", "GTB")
3742    check(4 | 16, "CHB", "ROB")
3743
3744def test_from_buffer_require_writable():
3745    BChar = new_primitive_type("char")
3746    BCharP = new_pointer_type(BChar)
3747    BCharA = new_array_type(BCharP, None)
3748    p1 = from_buffer(BCharA, b"foo", False)
3749    assert p1 == from_buffer(BCharA, b"foo", False)
3750    py.test.raises((TypeError, BufferError), from_buffer, BCharA, b"foo", True)
3751    ba = bytearray(b"foo")
3752    p1 = from_buffer(BCharA, ba, True)
3753    p1[0] = b"g"
3754    assert ba == b"goo"
3755
3756def test_from_buffer_types():
3757    BInt = new_primitive_type("int")
3758    BIntP = new_pointer_type(BInt)
3759    BIntA = new_array_type(BIntP, None)
3760    lst = [-12345678, 87654321, 489148]
3761    bytestring = buffer(newp(BIntA, lst))[:] + b'XYZ'
3762    #
3763    p1 = from_buffer(BIntA, bytestring)      # int[]
3764    assert typeof(p1) is BIntA
3765    assert len(p1) == 3
3766    assert p1[0] == lst[0]
3767    assert p1[1] == lst[1]
3768    assert p1[2] == lst[2]
3769    py.test.raises(IndexError, "p1[3]")
3770    py.test.raises(IndexError, "p1[-1]")
3771    #
3772    py.test.raises(TypeError, from_buffer, BInt, bytestring)
3773    py.test.raises(TypeError, from_buffer, BIntP, bytestring)
3774    #
3775    BIntA2 = new_array_type(BIntP, 2)
3776    p2 = from_buffer(BIntA2, bytestring)     # int[2]
3777    assert typeof(p2) is BIntA2
3778    assert len(p2) == 2
3779    assert p2[0] == lst[0]
3780    assert p2[1] == lst[1]
3781    py.test.raises(IndexError, "p2[2]")
3782    py.test.raises(IndexError, "p2[-1]")
3783    assert p2 == p1
3784    #
3785    BIntA4 = new_array_type(BIntP, 4)        # int[4]: too big
3786    py.test.raises(ValueError, from_buffer, BIntA4, bytestring)
3787    #
3788    BStruct = new_struct_type("foo")
3789    complete_struct_or_union(BStruct, [('a1', BInt, -1),
3790                                       ('a2', BInt, -1)])
3791    BStructP = new_pointer_type(BStruct)
3792    BStructA = new_array_type(BStructP, None)
3793    p1 = from_buffer(BStructA, bytestring)   # struct[]
3794    assert len(p1) == 1
3795    assert typeof(p1) is BStructA
3796    assert p1[0].a1 == lst[0]
3797    assert p1[0].a2 == lst[1]
3798    py.test.raises(IndexError, "p1[1]")
3799    #
3800    BEmptyStruct = new_struct_type("empty")
3801    complete_struct_or_union(BEmptyStruct, [], Ellipsis, 0)
3802    assert sizeof(BEmptyStruct) == 0
3803    BEmptyStructP = new_pointer_type(BEmptyStruct)
3804    BEmptyStructA = new_array_type(BEmptyStructP, None)
3805    py.test.raises(ZeroDivisionError, from_buffer,      # empty[]
3806                                      BEmptyStructA, bytestring)
3807    #
3808    BEmptyStructA5 = new_array_type(BEmptyStructP, 5)
3809    p1 = from_buffer(BEmptyStructA5, bytestring)   # struct empty[5]
3810    assert typeof(p1) is BEmptyStructA5
3811    assert len(p1) == 5
3812    assert cast(BIntP, p1) == from_buffer(BIntA, bytestring)
3813
3814def test_memmove():
3815    Short = new_primitive_type("short")
3816    ShortA = new_array_type(new_pointer_type(Short), None)
3817    Char = new_primitive_type("char")
3818    CharA = new_array_type(new_pointer_type(Char), None)
3819    p = newp(ShortA, [-1234, -2345, -3456, -4567, -5678])
3820    memmove(p, p + 1, 4)
3821    assert list(p) == [-2345, -3456, -3456, -4567, -5678]
3822    p[2] = 999
3823    memmove(p + 2, p, 6)
3824    assert list(p) == [-2345, -3456, -2345, -3456, 999]
3825    memmove(p + 4, newp(CharA, b"\x71\x72"), 2)
3826    if sys.byteorder == 'little':
3827        assert list(p) == [-2345, -3456, -2345, -3456, 0x7271]
3828    else:
3829        assert list(p) == [-2345, -3456, -2345, -3456, 0x7172]
3830
3831def test_memmove_buffer():
3832    import array
3833    Short = new_primitive_type("short")
3834    ShortA = new_array_type(new_pointer_type(Short), None)
3835    a = array.array('H', [10000, 20000, 30000])
3836    p = newp(ShortA, 5)
3837    memmove(p, a, 6)
3838    assert list(p) == [10000, 20000, 30000, 0, 0]
3839    memmove(p + 1, a, 6)
3840    assert list(p) == [10000, 10000, 20000, 30000, 0]
3841    b = array.array('h', [-1000, -2000, -3000])
3842    memmove(b, a, 4)
3843    assert b.tolist() == [10000, 20000, -3000]
3844    assert a.tolist() == [10000, 20000, 30000]
3845    p[0] = 999
3846    p[1] = 998
3847    p[2] = 997
3848    p[3] = 996
3849    p[4] = 995
3850    memmove(b, p, 2)
3851    assert b.tolist() == [999, 20000, -3000]
3852    memmove(b, p + 2, 4)
3853    assert b.tolist() == [997, 996, -3000]
3854    p[2] = -p[2]
3855    p[3] = -p[3]
3856    memmove(b, p + 2, 6)
3857    assert b.tolist() == [-997, -996, 995]
3858
3859def test_memmove_readonly_readwrite():
3860    SignedChar = new_primitive_type("signed char")
3861    SignedCharA = new_array_type(new_pointer_type(SignedChar), None)
3862    p = newp(SignedCharA, 5)
3863    memmove(p, b"abcde", 3)
3864    assert list(p) == [ord("a"), ord("b"), ord("c"), 0, 0]
3865    memmove(p, bytearray(b"ABCDE"), 2)
3866    assert list(p) == [ord("A"), ord("B"), ord("c"), 0, 0]
3867    py.test.raises((TypeError, BufferError), memmove, b"abcde", p, 3)
3868    ba = bytearray(b"xxxxx")
3869    memmove(dest=ba, src=p, n=3)
3870    assert ba == bytearray(b"ABcxx")
3871    memmove(ba, b"EFGH", 4)
3872    assert ba == bytearray(b"EFGHx")
3873
3874def test_memmove_sign_check():
3875    SignedChar = new_primitive_type("signed char")
3876    SignedCharA = new_array_type(new_pointer_type(SignedChar), None)
3877    p = newp(SignedCharA, 5)
3878    py.test.raises(ValueError, memmove, p, p + 1, -1)   # not segfault
3879
3880def test_memmove_bad_cdata():
3881    BInt = new_primitive_type("int")
3882    p = cast(BInt, 42)
3883    py.test.raises(TypeError, memmove, p, bytearray(b'a'), 1)
3884    py.test.raises(TypeError, memmove, bytearray(b'a'), p, 1)
3885
3886def test_dereference_null_ptr():
3887    BInt = new_primitive_type("int")
3888    BIntPtr = new_pointer_type(BInt)
3889    p = cast(BIntPtr, 0)
3890    py.test.raises(RuntimeError, "p[0]")
3891    py.test.raises(RuntimeError, "p[0] = 42")
3892    py.test.raises(RuntimeError, "p[42]")
3893    py.test.raises(RuntimeError, "p[42] = -1")
3894
3895def test_mixup():
3896    BStruct1 = new_struct_type("foo")
3897    BStruct2 = new_struct_type("foo")   # <= same name as BStruct1
3898    BStruct3 = new_struct_type("bar")
3899    BStruct1Ptr = new_pointer_type(BStruct1)
3900    BStruct2Ptr = new_pointer_type(BStruct2)
3901    BStruct3Ptr = new_pointer_type(BStruct3)
3902    BStruct1PtrPtr = new_pointer_type(BStruct1Ptr)
3903    BStruct2PtrPtr = new_pointer_type(BStruct2Ptr)
3904    BStruct3PtrPtr = new_pointer_type(BStruct3Ptr)
3905    pp1 = newp(BStruct1PtrPtr)
3906    pp2 = newp(BStruct2PtrPtr)
3907    pp3 = newp(BStruct3PtrPtr)
3908    pp1[0] = pp1[0]
3909    e = py.test.raises(TypeError, "pp3[0] = pp1[0]")
3910    assert str(e.value).startswith("initializer for ctype 'bar *' must be a ")
3911    assert str(e.value).endswith(", not cdata 'foo *'")
3912    e = py.test.raises(TypeError, "pp2[0] = pp1[0]")
3913    assert str(e.value) == ("initializer for ctype 'foo *' appears indeed to "
3914                            "be 'foo *', but the types are different (check "
3915                            "that you are not e.g. mixing up different ffi "
3916                            "instances)")
3917
3918def test_stdcall_function_type():
3919    assert FFI_CDECL == FFI_DEFAULT_ABI
3920    try:
3921        stdcall = FFI_STDCALL
3922    except NameError:
3923        stdcall = FFI_DEFAULT_ABI
3924    BInt = new_primitive_type("int")
3925    BFunc = new_function_type((BInt, BInt), BInt, False, stdcall)
3926    if stdcall != FFI_DEFAULT_ABI:
3927        assert repr(BFunc) == "<ctype 'int(__stdcall *)(int, int)'>"
3928    else:
3929        assert repr(BFunc) == "<ctype 'int(*)(int, int)'>"
3930
3931def test_get_common_types():
3932    d = {}
3933    _get_common_types(d)
3934    assert d['bool'] == '_Bool'
3935
3936def test_unpack():
3937    BChar = new_primitive_type("char")
3938    BArray = new_array_type(new_pointer_type(BChar), 10)   # char[10]
3939    p = newp(BArray, b"abc\x00def")
3940    p0 = p
3941    assert unpack(p, 10) == b"abc\x00def\x00\x00\x00"
3942    assert unpack(p+1, 5) == b"bc\x00de"
3943
3944    for typename in ["wchar_t", "char16_t", "char32_t"]:
3945        BWChar = new_primitive_type(typename)
3946        BArray = new_array_type(new_pointer_type(BWChar), 10)   # wchar_t[10]
3947        p = newp(BArray, u"abc\x00def")
3948        assert unpack(p, 10) == u"abc\x00def\x00\x00\x00"
3949
3950    for typename, samples in [
3951            ("uint8_t",  [0, 2**8-1]),
3952            ("uint16_t", [0, 2**16-1]),
3953            ("uint32_t", [0, 2**32-1]),
3954            ("uint64_t", [0, 2**64-1]),
3955            ("int8_t",  [-2**7, 2**7-1]),
3956            ("int16_t", [-2**15, 2**15-1]),
3957            ("int32_t", [-2**31, 2**31-1]),
3958            ("int64_t", [-2**63, 2**63-1]),
3959            ("_Bool", [False, True]),
3960            ("float", [0.0, 10.5]),
3961            ("double", [12.34, 56.78]),
3962            ]:
3963        BItem = new_primitive_type(typename)
3964        BArray = new_array_type(new_pointer_type(BItem), 10)
3965        p = newp(BArray, samples)
3966        result = unpack(p, len(samples))
3967        assert result == samples
3968        for i in range(len(samples)):
3969            assert result[i] == p[i] and type(result[i]) is type(p[i])
3970            assert (type(result[i]) is bool) == (type(samples[i]) is bool)
3971    #
3972    BInt = new_primitive_type("int")
3973    py.test.raises(TypeError, unpack, p)
3974    py.test.raises(TypeError, unpack, b"foobar", 6)
3975    py.test.raises(TypeError, unpack, cast(BInt, 42), 1)
3976    #
3977    BPtr = new_pointer_type(BInt)
3978    random_ptr = cast(BPtr, -424344)
3979    other_ptr = cast(BPtr, 54321)
3980    BArray = new_array_type(new_pointer_type(BPtr), None)
3981    lst = unpack(newp(BArray, [random_ptr, other_ptr]), 2)
3982    assert lst == [random_ptr, other_ptr]
3983    #
3984    BFunc = new_function_type((BInt, BInt), BInt, False)
3985    BFuncPtr = new_pointer_type(BFunc)
3986    lst = unpack(newp(new_array_type(BFuncPtr, None), 2), 2)
3987    assert len(lst) == 2
3988    assert not lst[0] and not lst[1]
3989    assert typeof(lst[0]) is BFunc
3990    #
3991    BStruct = new_struct_type("foo")
3992    BStructPtr = new_pointer_type(BStruct)
3993    e = py.test.raises(ValueError, unpack, cast(BStructPtr, 42), 5)
3994    assert str(e.value) == "'foo *' points to items of unknown size"
3995    complete_struct_or_union(BStruct, [('a1', BInt, -1),
3996                                       ('a2', BInt, -1)])
3997    array_of_structs = newp(new_array_type(BStructPtr, None), [[4,5], [6,7]])
3998    lst = unpack(array_of_structs, 2)
3999    assert typeof(lst[0]) is BStruct
4000    assert lst[0].a1 == 4 and lst[1].a2 == 7
4001    #
4002    py.test.raises(RuntimeError, unpack, cast(new_pointer_type(BChar), 0), 0)
4003    py.test.raises(RuntimeError, unpack, cast(new_pointer_type(BChar), 0), 10)
4004    #
4005    py.test.raises(ValueError, unpack, p0, -1)
4006    py.test.raises(ValueError, unpack, p, -1)
4007
4008def test_cdata_dir():
4009    BInt = new_primitive_type("int")
4010    p = cast(BInt, 42)
4011    check_dir(p, [])
4012    p = newp(new_array_type(new_pointer_type(BInt), None), 5)
4013    check_dir(p, [])
4014    BStruct = new_struct_type("foo")
4015    p = cast(new_pointer_type(BStruct), 0)
4016    check_dir(p, [])    # opaque
4017    complete_struct_or_union(BStruct, [('a2', BInt, -1),
4018                                       ('a1', BInt, -1)])
4019    check_dir(p, ['a1', 'a2'])   # always sorted
4020    p = newp(new_pointer_type(BStruct), None)
4021    check_dir(p, ['a1', 'a2'])
4022    check_dir(p[0], ['a1', 'a2'])
4023    pp = newp(new_pointer_type(new_pointer_type(BStruct)), p)
4024    check_dir(pp, [])
4025    check_dir(pp[0], ['a1', 'a2'])
4026    check_dir(pp[0][0], ['a1', 'a2'])
4027
4028def test_char_pointer_conversion():
4029    import warnings
4030    assert __version__.startswith("1."), (
4031        "the warning will be an error if we ever release cffi 2.x")
4032    BCharP = new_pointer_type(new_primitive_type("char"))
4033    BIntP = new_pointer_type(new_primitive_type("int"))
4034    BVoidP = new_pointer_type(new_void_type())
4035    BUCharP = new_pointer_type(new_primitive_type("unsigned char"))
4036    z1 = cast(BCharP, 0)
4037    z2 = cast(BIntP, 0)
4038    z3 = cast(BVoidP, 0)
4039    z4 = cast(BUCharP, 0)
4040    with warnings.catch_warnings(record=True) as w:
4041        warnings.simplefilter("always")
4042        newp(new_pointer_type(BIntP), z1)    # warn
4043        assert len(w) == 1
4044        newp(new_pointer_type(BVoidP), z1)   # fine
4045        assert len(w) == 1
4046        newp(new_pointer_type(BCharP), z2)   # warn
4047        assert len(w) == 2
4048        newp(new_pointer_type(BVoidP), z2)   # fine
4049        assert len(w) == 2
4050        newp(new_pointer_type(BCharP), z3)   # fine
4051        assert len(w) == 2
4052        newp(new_pointer_type(BIntP), z3)    # fine
4053        assert len(w) == 2
4054        newp(new_pointer_type(BCharP), z4)   # fine (ignore signedness here)
4055        assert len(w) == 2
4056        newp(new_pointer_type(BUCharP), z1)  # fine (ignore signedness here)
4057        assert len(w) == 2
4058        newp(new_pointer_type(BUCharP), z3)  # fine
4059        assert len(w) == 2
4060    # check that the warnings are associated with lines in this file
4061    assert w[1].lineno == w[0].lineno + 4
4062
4063def test_primitive_comparison():
4064    def assert_eq(a, b):
4065        assert (a == b) is True
4066        assert (b == a) is True
4067        assert (a != b) is False
4068        assert (b != a) is False
4069        assert (a < b) is False
4070        assert (a <= b) is True
4071        assert (a > b) is False
4072        assert (a >= b) is True
4073        assert (b < a) is False
4074        assert (b <= a) is True
4075        assert (b > a) is False
4076        assert (b >= a) is True
4077        assert hash(a) == hash(b)
4078    def assert_lt(a, b, check_hash=True):
4079        assert (a == b) is False
4080        assert (b == a) is False
4081        assert (a != b) is True
4082        assert (b != a) is True
4083        assert (a < b) is True
4084        assert (a <= b) is True
4085        assert (a > b) is False
4086        assert (a >= b) is False
4087        assert (b < a) is False
4088        assert (b <= a) is False
4089        assert (b > a) is True
4090        assert (b >= a) is True
4091        if check_hash:
4092            assert hash(a) != hash(b)    # (or at least, it is unlikely)
4093    def assert_gt(a, b, check_hash=True):
4094        assert_lt(b, a, check_hash)
4095    def assert_ne(a, b):
4096        assert (a == b) is False
4097        assert (b == a) is False
4098        assert (a != b) is True
4099        assert (b != a) is True
4100        if strict_compare:
4101            py.test.raises(TypeError, "a < b")
4102            py.test.raises(TypeError, "a <= b")
4103            py.test.raises(TypeError, "a > b")
4104            py.test.raises(TypeError, "a >= b")
4105            py.test.raises(TypeError, "b < a")
4106            py.test.raises(TypeError, "b <= a")
4107            py.test.raises(TypeError, "b > a")
4108            py.test.raises(TypeError, "b >= a")
4109        elif a < b:
4110            assert_lt(a, b)
4111        else:
4112            assert_lt(b, a)
4113    assert_eq(5, 5)
4114    assert_lt(3, 5)
4115    assert_ne('5', 5)
4116    #
4117    t1 = new_primitive_type("char")
4118    t2 = new_primitive_type("int")
4119    t3 = new_primitive_type("unsigned char")
4120    t4 = new_primitive_type("unsigned int")
4121    t5 = new_primitive_type("float")
4122    t6 = new_primitive_type("double")
4123    assert_eq(cast(t1, 65), b'A')
4124    assert_lt(cast(t1, 64), b'\x99')
4125    assert_gt(cast(t1, 200), b'A')
4126    assert_ne(cast(t1, 65), 65)
4127    assert_eq(cast(t2, -25), -25)
4128    assert_lt(cast(t2, -25), -24)
4129    assert_gt(cast(t2, -25), -26)
4130    assert_eq(cast(t3, 65), 65)
4131    assert_ne(cast(t3, 65), b'A')
4132    assert_ne(cast(t3, 65), cast(t1, 65))
4133    assert_gt(cast(t4, -1), -1, check_hash=False)
4134    assert_gt(cast(t4, -1), cast(t2, -1), check_hash=False)
4135    assert_gt(cast(t4, -1), 99999)
4136    assert_eq(cast(t4, -1), 256 ** size_of_int() - 1)
4137    assert_eq(cast(t5, 3.0), 3)
4138    assert_eq(cast(t5, 3.5), 3.5)
4139    assert_lt(cast(t5, 3.3), 3.3)   # imperfect rounding
4140    assert_eq(cast(t6, 3.3), 3.3)
4141    assert_eq(cast(t5, 3.5), cast(t6, 3.5))
4142    assert_lt(cast(t5, 3.1), cast(t6, 3.1))   # imperfect rounding
4143    assert_eq(cast(t5, 7.0), cast(t3, 7))
4144    assert_lt(cast(t5, 3.1), 3.101)
4145    assert_gt(cast(t5, 3.1), 3)
4146
4147def test_explicit_release_new():
4148    # release() on a ffi.new() object has no effect on CPython, but
4149    # really releases memory on PyPy.  We can't test that effect
4150    # though, because a released cdata is not marked.
4151    BIntP = new_pointer_type(new_primitive_type("int"))
4152    p = newp(BIntP)
4153    p[0] = 42
4154    py.test.raises(IndexError, "p[1]")
4155    release(p)
4156    # here, reading p[0] might give garbage or segfault...
4157    release(p)   # no effect
4158    #
4159    BStruct = new_struct_type("struct foo")
4160    BStructP = new_pointer_type(BStruct)
4161    complete_struct_or_union(BStruct, [('p', BIntP, -1)])
4162    pstruct = newp(BStructP)
4163    assert pstruct.p == cast(BIntP, 0)
4164    release(pstruct)
4165    # here, reading pstruct.p might give garbage or segfault...
4166    release(pstruct)   # no effect
4167
4168def test_explicit_release_new_contextmgr():
4169    BIntP = new_pointer_type(new_primitive_type("int"))
4170    with newp(BIntP) as p:
4171        p[0] = 42
4172        assert p[0] == 42
4173    # here, reading p[0] might give garbage or segfault...
4174    release(p)   # no effect
4175
4176def test_explicit_release_badtype():
4177    BIntP = new_pointer_type(new_primitive_type("int"))
4178    p = cast(BIntP, 12345)
4179    py.test.raises(ValueError, release, p)
4180    py.test.raises(ValueError, release, p)
4181    BStruct = new_struct_type("struct foo")
4182    BStructP = new_pointer_type(BStruct)
4183    complete_struct_or_union(BStruct, [('p', BIntP, -1)])
4184    pstruct = newp(BStructP)
4185    py.test.raises(ValueError, release, pstruct[0])
4186
4187def test_explicit_release_badtype_contextmgr():
4188    BIntP = new_pointer_type(new_primitive_type("int"))
4189    p = cast(BIntP, 12345)
4190    py.test.raises(ValueError, "with p: pass")
4191    py.test.raises(ValueError, "with p: pass")
4192
4193def test_explicit_release_gc():
4194    BIntP = new_pointer_type(new_primitive_type("int"))
4195    seen = []
4196    intp1 = newp(BIntP, 12345)
4197    p1 = cast(BIntP, intp1)
4198    p = gcp(p1, seen.append)
4199    assert seen == []
4200    release(p)
4201    assert seen == [p1]
4202    assert p1[0] == 12345
4203    assert p[0] == 12345  # true so far, but might change to raise RuntimeError
4204    release(p)   # no effect
4205
4206def test_explicit_release_gc_contextmgr():
4207    BIntP = new_pointer_type(new_primitive_type("int"))
4208    seen = []
4209    intp1 = newp(BIntP, 12345)
4210    p1 = cast(BIntP, intp1)
4211    p = gcp(p1, seen.append)
4212    with p:
4213        assert p[0] == 12345
4214        assert seen == []
4215    assert seen == [p1]
4216    assert p1[0] == 12345
4217    assert p[0] == 12345  # true so far, but might change to raise RuntimeError
4218    release(p)   # no effect
4219
4220def test_explicit_release_from_buffer():
4221    a = bytearray(b"xyz")
4222    BChar = new_primitive_type("char")
4223    BCharP = new_pointer_type(BChar)
4224    BCharA = new_array_type(BCharP, None)
4225    p = from_buffer(BCharA, a)
4226    assert p[2] == b"z"
4227    release(p)
4228    assert p[2] == b"z"  # true so far, but might change to raise RuntimeError
4229    release(p)   # no effect
4230
4231def test_explicit_release_from_buffer_contextmgr():
4232    a = bytearray(b"xyz")
4233    BChar = new_primitive_type("char")
4234    BCharP = new_pointer_type(BChar)
4235    BCharA = new_array_type(BCharP, None)
4236    p = from_buffer(BCharA, a)
4237    with p:
4238        assert p[2] == b"z"
4239    assert p[2] == b"z"  # true so far, but might change to raise RuntimeError
4240    release(p)   # no effect
4241
4242def test_explicit_release_bytearray_on_cpython():
4243    if '__pypy__' in sys.builtin_module_names:
4244        py.test.skip("pypy's bytearray are never locked")
4245    a = bytearray(b"xyz")
4246    BChar = new_primitive_type("char")
4247    BCharP = new_pointer_type(BChar)
4248    BCharA = new_array_type(BCharP, None)
4249    a += b't' * 10
4250    p = from_buffer(BCharA, a)
4251    py.test.raises(BufferError, "a += b'u' * 100")
4252    release(p)
4253    a += b'v' * 100
4254    release(p)   # no effect
4255    a += b'w' * 1000
4256    assert a == bytearray(b"xyz" + b't' * 10 + b'v' * 100 + b'w' * 1000)
4257