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