1import py, re
2import sys, os, math, weakref
3from cffi import FFI, VerificationError, VerificationMissing, model, FFIError
4from testing.support import *
5
6
7lib_m = ['m']
8if sys.platform == 'win32':
9    #there is a small chance this fails on Mingw via environ $CC
10    import distutils.ccompiler
11    if distutils.ccompiler.get_default_compiler() == 'msvc':
12        lib_m = ['msvcrt']
13    pass      # no obvious -Werror equivalent on MSVC
14else:
15    if (sys.platform == 'darwin' and
16          [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]):
17        # assume a standard clang or gcc
18        extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
19        # special things for clang
20        extra_compile_args.append('-Qunused-arguments')
21    else:
22        # assume a standard gcc
23        extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
24
25    class FFI(FFI):
26        def verify(self, *args, **kwds):
27            return super(FFI, self).verify(
28                *args, extra_compile_args=extra_compile_args, **kwds)
29
30def setup_module():
31    import cffi.verifier
32    cffi.verifier.cleanup_tmpdir()
33    #
34    # check that no $ sign is produced in the C file; it used to be the
35    # case that anonymous enums would produce '$enum_$1', which was
36    # used as part of a function name.  GCC accepts such names, but it's
37    # apparently non-standard.
38    _r_comment = re.compile(r"/\*.*?\*/|//.*?$", re.DOTALL | re.MULTILINE)
39    _r_string = re.compile(r'\".*?\"')
40    def _write_source_and_check(self, file=None):
41        base_write_source(self, file)
42        if file is None:
43            f = open(self.sourcefilename)
44            data = f.read()
45            f.close()
46            data = _r_comment.sub(' ', data)
47            data = _r_string.sub('"skipped"', data)
48            assert '$' not in data
49    base_write_source = cffi.verifier.Verifier._write_source
50    cffi.verifier.Verifier._write_source = _write_source_and_check
51
52
53def test_module_type():
54    import cffi.verifier
55    ffi = FFI()
56    lib = ffi.verify()
57    if hasattr(lib, '_cffi_python_module'):
58        print('verify got a PYTHON module')
59    if hasattr(lib, '_cffi_generic_module'):
60        print('verify got a GENERIC module')
61    expected_generic = (cffi.verifier._FORCE_GENERIC_ENGINE or
62                        '__pypy__' in sys.builtin_module_names)
63    assert hasattr(lib, '_cffi_python_module') == (not expected_generic)
64    assert hasattr(lib, '_cffi_generic_module') == expected_generic
65
66def test_missing_function(ffi=None):
67    # uses the FFI hacked above with '-Werror'
68    if ffi is None:
69        ffi = FFI()
70    ffi.cdef("void some_completely_unknown_function();")
71    try:
72        lib = ffi.verify()
73    except (VerificationError, OSError):
74        pass     # expected case: we get a VerificationError
75    else:
76        # but depending on compiler and loader details, maybe
77        # 'lib' could actually be imported but will fail if we
78        # actually try to call the unknown function...  Hard
79        # to test anything more.
80        pass
81
82def test_missing_function_import_error():
83    # uses the original FFI that just gives a warning during compilation
84    import cffi
85    test_missing_function(ffi=cffi.FFI())
86
87def test_simple_case():
88    ffi = FFI()
89    ffi.cdef("double sin(double x);")
90    lib = ffi.verify('#include <math.h>', libraries=lib_m)
91    assert lib.sin(1.23) == math.sin(1.23)
92
93def _Wconversion(cdef, source, **kargs):
94    if sys.platform in ('win32', 'darwin'):
95        py.test.skip("needs GCC")
96    ffi = FFI()
97    ffi.cdef(cdef)
98    py.test.raises(VerificationError, ffi.verify, source, **kargs)
99    extra_compile_args_orig = extra_compile_args[:]
100    extra_compile_args.remove('-Wconversion')
101    try:
102        lib = ffi.verify(source, **kargs)
103    finally:
104        extra_compile_args[:] = extra_compile_args_orig
105    return lib
106
107def test_Wconversion_unsigned():
108    _Wconversion("unsigned foo(void);",
109                 "int foo(void) { return -1;}")
110
111def test_Wconversion_integer():
112    _Wconversion("short foo(void);",
113                 "long long foo(void) { return 1<<sizeof(short);}")
114
115def test_Wconversion_floating():
116    lib = _Wconversion("float sin(double);",
117                       "#include <math.h>", libraries=lib_m)
118    res = lib.sin(1.23)
119    assert res != math.sin(1.23)     # not exact, because of double->float
120    assert abs(res - math.sin(1.23)) < 1E-5
121
122def test_Wconversion_float2int():
123    _Wconversion("int sinf(float);",
124                 "#include <math.h>", libraries=lib_m)
125
126def test_Wconversion_double2int():
127    _Wconversion("int sin(double);",
128                 "#include <math.h>", libraries=lib_m)
129
130def test_rounding_1():
131    ffi = FFI()
132    ffi.cdef("double sinf(float x);")
133    lib = ffi.verify('#include <math.h>', libraries=lib_m)
134    res = lib.sinf(1.23)
135    assert res != math.sin(1.23)     # not exact, because of double->float
136    assert abs(res - math.sin(1.23)) < 1E-5
137
138def test_rounding_2():
139    ffi = FFI()
140    ffi.cdef("double sin(float x);")
141    lib = ffi.verify('#include <math.h>', libraries=lib_m)
142    res = lib.sin(1.23)
143    assert res != math.sin(1.23)     # not exact, because of double->float
144    assert abs(res - math.sin(1.23)) < 1E-5
145
146def test_strlen_exact():
147    ffi = FFI()
148    ffi.cdef("size_t strlen(const char *s);")
149    lib = ffi.verify("#include <string.h>")
150    assert lib.strlen(b"hi there!") == 9
151
152def test_strlen_approximate():
153    lib = _Wconversion("int strlen(char *s);",
154                       "#include <string.h>")
155    assert lib.strlen(b"hi there!") == 9
156
157def test_return_approximate():
158    for typename in ['short', 'int', 'long', 'long long']:
159        ffi = FFI()
160        ffi.cdef("%s foo(signed char x);" % typename)
161        lib = ffi.verify("signed char foo(signed char x) { return x;}")
162        assert lib.foo(-128) == -128
163        assert lib.foo(+127) == +127
164
165def test_strlen_array_of_char():
166    ffi = FFI()
167    ffi.cdef("size_t strlen(char[]);")
168    lib = ffi.verify("#include <string.h>")
169    assert lib.strlen(b"hello") == 5
170
171def test_longdouble():
172    ffi = FFI()
173    ffi.cdef("long double sinl(long double x);")
174    lib = ffi.verify('#include <math.h>', libraries=lib_m)
175    for input in [1.23,
176                  ffi.cast("double", 1.23),
177                  ffi.cast("long double", 1.23)]:
178        x = lib.sinl(input)
179        assert repr(x).startswith("<cdata 'long double'")
180        assert (float(x) - math.sin(1.23)) < 1E-10
181
182def test_longdouble_precision():
183    # Test that we don't loose any precision of 'long double' when
184    # passing through Python and CFFI.
185    ffi = FFI()
186    ffi.cdef("long double step1(long double x);")
187    SAME_SIZE = ffi.sizeof("long double") == ffi.sizeof("double")
188    lib = ffi.verify("""
189        long double step1(long double x)
190        {
191            return 4*x-x*x;
192        }
193    """)
194    def do(cast_to_double):
195        x = 0.9789
196        for i in range(10000):
197            x = lib.step1(x)
198            if cast_to_double:
199                x = float(x)
200        return float(x)
201
202    more_precise = do(False)
203    less_precise = do(True)
204    if SAME_SIZE:
205        assert more_precise == less_precise
206    else:
207        assert abs(more_precise - less_precise) > 0.1
208        # Check the particular results on Intel
209        import platform
210        if (platform.machine().startswith('i386') or
211            platform.machine().startswith('i486') or
212            platform.machine().startswith('i586') or
213            platform.machine().startswith('i686') or
214            platform.machine().startswith('x86')):
215            assert abs(more_precise - 0.656769) < 0.001
216            assert abs(less_precise - 3.99091) < 0.001
217        else:
218            py.test.skip("don't know the very exact precision of 'long double'")
219
220
221all_primitive_types = model.PrimitiveType.ALL_PRIMITIVE_TYPES
222if sys.platform == 'win32':
223    all_primitive_types = all_primitive_types.copy()
224    del all_primitive_types['ssize_t']
225all_integer_types = sorted(tp for tp in all_primitive_types
226                           if all_primitive_types[tp] == 'i')
227all_float_types = sorted(tp for tp in all_primitive_types
228                            if all_primitive_types[tp] == 'f')
229
230def all_signed_integer_types(ffi):
231    return [x for x in all_integer_types if int(ffi.cast(x, -1)) < 0]
232
233def all_unsigned_integer_types(ffi):
234    return [x for x in all_integer_types if int(ffi.cast(x, -1)) > 0]
235
236
237def test_primitive_category():
238    for typename in all_primitive_types:
239        tp = model.PrimitiveType(typename)
240        C = tp.is_char_type()
241        F = tp.is_float_type()
242        X = tp.is_complex_type()
243        I = tp.is_integer_type()
244        assert C == (typename in ('char', 'wchar_t', 'char16_t', 'char32_t'))
245        assert F == (typename in ('float', 'double', 'long double'))
246        assert X == (typename in ('float _Complex', 'double _Complex'))
247        assert I + F + C + X == 1      # one and only one of them is true
248
249def test_all_integer_and_float_types():
250    typenames = []
251    for typename in all_primitive_types:
252        if (all_primitive_types[typename] == 'c' or
253            all_primitive_types[typename] == 'j' or    # complex
254            typename == '_Bool' or typename == 'long double'):
255            pass
256        else:
257            typenames.append(typename)
258    #
259    ffi = FFI()
260    ffi.cdef('\n'.join(["%s foo_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
261                       for tp in typenames]))
262    lib = ffi.verify('\n'.join(["%s foo_%s(%s x) { return (%s)(x+1); }" %
263                                (tp, tp.replace(' ', '_'), tp, tp)
264                                for tp in typenames]))
265    for typename in typenames:
266        foo = getattr(lib, 'foo_%s' % typename.replace(' ', '_'))
267        assert foo(42) == 43
268        if sys.version < '3':
269            assert foo(long(44)) == 45
270        assert foo(ffi.cast(typename, 46)) == 47
271        py.test.raises(TypeError, foo, ffi.NULL)
272        #
273        # check for overflow cases
274        if all_primitive_types[typename] == 'f':
275            continue
276        for value in [-2**80, -2**40, -2**20, -2**10, -2**5, -1,
277                      2**5, 2**10, 2**20, 2**40, 2**80]:
278            overflows = int(ffi.cast(typename, value)) != value
279            if overflows:
280                py.test.raises(OverflowError, foo, value)
281            else:
282                assert foo(value) == value + 1
283
284def test_var_signed_integer_types():
285    ffi = FFI()
286    lst = all_signed_integer_types(ffi)
287    csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
288                         for tp in lst])
289    ffi.cdef(csource)
290    lib = ffi.verify(csource)
291    for tp in lst:
292        varname = 'somevar_%s' % tp.replace(' ', '_')
293        sz = ffi.sizeof(tp)
294        max = (1 << (8*sz-1)) - 1
295        min = -(1 << (8*sz-1))
296        setattr(lib, varname, max)
297        assert getattr(lib, varname) == max
298        setattr(lib, varname, min)
299        assert getattr(lib, varname) == min
300        py.test.raises(OverflowError, setattr, lib, varname, max+1)
301        py.test.raises(OverflowError, setattr, lib, varname, min-1)
302
303def test_var_unsigned_integer_types():
304    ffi = FFI()
305    lst = all_unsigned_integer_types(ffi)
306    csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
307                         for tp in lst])
308    ffi.cdef(csource)
309    lib = ffi.verify(csource)
310    for tp in lst:
311        varname = 'somevar_%s' % tp.replace(' ', '_')
312        sz = ffi.sizeof(tp)
313        if tp != '_Bool':
314            max = (1 << (8*sz)) - 1
315        else:
316            max = 1
317        setattr(lib, varname, max)
318        assert getattr(lib, varname) == max
319        setattr(lib, varname, 0)
320        assert getattr(lib, varname) == 0
321        py.test.raises(OverflowError, setattr, lib, varname, max+1)
322        py.test.raises(OverflowError, setattr, lib, varname, -1)
323
324def test_fn_signed_integer_types():
325    ffi = FFI()
326    lst = all_signed_integer_types(ffi)
327    cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
328                         for tp in lst])
329    ffi.cdef(cdefsrc)
330    verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
331                           (tp, tp.replace(' ', '_'), tp) for tp in lst])
332    lib = ffi.verify(verifysrc)
333    for tp in lst:
334        fnname = 'somefn_%s' % tp.replace(' ', '_')
335        sz = ffi.sizeof(tp)
336        max = (1 << (8*sz-1)) - 1
337        min = -(1 << (8*sz-1))
338        fn = getattr(lib, fnname)
339        assert fn(max) == max
340        assert fn(min) == min
341        py.test.raises(OverflowError, fn, max + 1)
342        py.test.raises(OverflowError, fn, min - 1)
343
344def test_fn_unsigned_integer_types():
345    ffi = FFI()
346    lst = all_unsigned_integer_types(ffi)
347    cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
348                         for tp in lst])
349    ffi.cdef(cdefsrc)
350    verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
351                           (tp, tp.replace(' ', '_'), tp) for tp in lst])
352    lib = ffi.verify(verifysrc)
353    for tp in lst:
354        fnname = 'somefn_%s' % tp.replace(' ', '_')
355        sz = ffi.sizeof(tp)
356        if tp != '_Bool':
357            max = (1 << (8*sz)) - 1
358        else:
359            max = 1
360        fn = getattr(lib, fnname)
361        assert fn(max) == max
362        assert fn(0) == 0
363        py.test.raises(OverflowError, fn, max + 1)
364        py.test.raises(OverflowError, fn, -1)
365
366def test_char_type():
367    ffi = FFI()
368    ffi.cdef("char foo(char);")
369    lib = ffi.verify("char foo(char x) { return ++x; }")
370    assert lib.foo(b"A") == b"B"
371    py.test.raises(TypeError, lib.foo, b"bar")
372    py.test.raises(TypeError, lib.foo, "bar")
373
374def test_wchar_type():
375    ffi = FFI()
376    if ffi.sizeof('wchar_t') == 2:
377        uniexample1 = u+'\u1234'
378        uniexample2 = u+'\u1235'
379    else:
380        uniexample1 = u+'\U00012345'
381        uniexample2 = u+'\U00012346'
382    #
383    ffi.cdef("wchar_t foo(wchar_t);")
384    lib = ffi.verify("wchar_t foo(wchar_t x) { return x+1; }")
385    assert lib.foo(uniexample1) == uniexample2
386
387def test_char16_char32_type():
388    py.test.skip("XXX test or fully prevent char16_t and char32_t from "
389                 "working in ffi.verify() mode")
390
391def test_no_argument():
392    ffi = FFI()
393    ffi.cdef("int foo(void);")
394    lib = ffi.verify("int foo(void) { return 42; }")
395    assert lib.foo() == 42
396
397def test_two_arguments():
398    ffi = FFI()
399    ffi.cdef("int foo(int, int);")
400    lib = ffi.verify("int foo(int a, int b) { return a - b; }")
401    assert lib.foo(40, -2) == 42
402
403def test_macro():
404    ffi = FFI()
405    ffi.cdef("int foo(int, int);")
406    lib = ffi.verify("#define foo(a, b) ((a) * (b))")
407    assert lib.foo(-6, -7) == 42
408
409def test_ptr():
410    ffi = FFI()
411    ffi.cdef("int *foo(int *);")
412    lib = ffi.verify("int *foo(int *a) { return a; }")
413    assert lib.foo(ffi.NULL) == ffi.NULL
414    p = ffi.new("int *", 42)
415    q = ffi.new("int *", 42)
416    assert lib.foo(p) == p
417    assert lib.foo(q) != p
418
419def test_bogus_ptr():
420    ffi = FFI()
421    ffi.cdef("int *foo(int *);")
422    lib = ffi.verify("int *foo(int *a) { return a; }")
423    py.test.raises(TypeError, lib.foo, ffi.new("short *", 42))
424
425
426def test_verify_typedefs():
427    py.test.skip("ignored so far")
428    types = ['signed char', 'unsigned char', 'int', 'long']
429    for cdefed in types:
430        for real in types:
431            ffi = FFI()
432            ffi.cdef("typedef %s foo_t;" % cdefed)
433            if cdefed == real:
434                ffi.verify("typedef %s foo_t;" % real)
435            else:
436                py.test.raises(VerificationError, ffi.verify,
437                               "typedef %s foo_t;" % real)
438
439def test_nondecl_struct():
440    ffi = FFI()
441    ffi.cdef("typedef struct foo_s foo_t; int bar(foo_t *);")
442    lib = ffi.verify("typedef struct foo_s foo_t;\n"
443                     "int bar(foo_t *f) { (void)f; return 42; }\n")
444    assert lib.bar(ffi.NULL) == 42
445
446def test_ffi_full_struct():
447    ffi = FFI()
448    ffi.cdef("struct foo_s { char x; int y; long *z; };")
449    ffi.verify("struct foo_s { char x; int y; long *z; };")
450    #
451    if sys.platform != 'win32':  # XXX fixme: only gives warnings
452        py.test.raises(VerificationError, ffi.verify,
453            "struct foo_s { char x; int y; int *z; };")
454    #
455    py.test.raises(VerificationError, ffi.verify,
456        "struct foo_s { int y; long *z; };")
457    #
458    e = py.test.raises(VerificationError, ffi.verify,
459        "struct foo_s { int y; char x; long *z; };")
460    assert str(e.value) == (
461        "struct foo_s: wrong offset for field 'x'"
462        " (we have 0, but C compiler says 4)")
463    #
464    e = py.test.raises(VerificationError, ffi.verify,
465        "struct foo_s { char x; int y; long *z; char extra; };")
466    assert str(e.value) == (
467        "struct foo_s: wrong total size"
468        " (we have %d, but C compiler says %d)" % (
469            ffi.sizeof("struct foo_s"),
470            ffi.sizeof("struct foo_s") + ffi.sizeof("long*")))
471    #
472    # a corner case that we cannot really detect, but where it has no
473    # bad consequences: the size is the same, but there is an extra field
474    # that replaces what is just padding in our declaration above
475    ffi.verify("struct foo_s { char x, extra; int y; long *z; };")
476    #
477    e = py.test.raises(VerificationError, ffi.verify,
478        "struct foo_s { char x; short pad; short y; long *z; };")
479    assert str(e.value) == (
480        "struct foo_s: wrong size for field 'y'"
481        " (we have 4, but C compiler says 2)")
482
483def test_ffi_nonfull_struct():
484    ffi = FFI()
485    ffi.cdef("""
486    struct foo_s {
487       int x;
488       ...;
489    };
490    """)
491    py.test.raises(VerificationMissing, ffi.sizeof, 'struct foo_s')
492    py.test.raises(VerificationMissing, ffi.offsetof, 'struct foo_s', 'x')
493    py.test.raises(VerificationMissing, ffi.new, 'struct foo_s *')
494    ffi.verify("""
495    struct foo_s {
496       int a, b, x, c, d, e;
497    };
498    """)
499    assert ffi.sizeof('struct foo_s') == 6 * ffi.sizeof('int')
500    assert ffi.offsetof('struct foo_s', 'x') == 2 * ffi.sizeof('int')
501
502def test_ffi_nonfull_alignment():
503    ffi = FFI()
504    ffi.cdef("struct foo_s { char x; ...; };")
505    ffi.verify("struct foo_s { int a, b; char x; };")
506    assert ffi.sizeof('struct foo_s') == 3 * ffi.sizeof('int')
507    assert ffi.alignof('struct foo_s') == ffi.sizeof('int')
508
509def _check_field_match(typename, real, expect_mismatch):
510    ffi = FFI()
511    testing_by_size = (expect_mismatch == 'by_size')
512    if testing_by_size:
513        expect_mismatch = ffi.sizeof(typename) != ffi.sizeof(real)
514    ffi.cdef("struct foo_s { %s x; ...; };" % typename)
515    try:
516        ffi.verify("struct foo_s { %s x; };" % real)
517    except VerificationError:
518        if not expect_mismatch:
519            if testing_by_size and typename != real:
520                print("ignoring mismatch between %s* and %s* even though "
521                      "they have the same size" % (typename, real))
522                return
523            raise AssertionError("unexpected mismatch: %s should be accepted "
524                                 "as equal to %s" % (typename, real))
525    else:
526        if expect_mismatch:
527            raise AssertionError("mismatch not detected: "
528                                 "%s != %s" % (typename, real))
529
530def test_struct_bad_sized_integer():
531    for typename in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
532        for real in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
533            _check_field_match(typename, real, "by_size")
534
535def test_struct_bad_sized_float():
536    for typename in all_float_types:
537        for real in all_float_types:
538            _check_field_match(typename, real, "by_size")
539
540def test_struct_signedness_ignored():
541    _check_field_match("int", "unsigned int", expect_mismatch=False)
542    _check_field_match("unsigned short", "signed short", expect_mismatch=False)
543
544def test_struct_float_vs_int():
545    if sys.platform == 'win32':
546        py.test.skip("XXX fixme: only gives warnings")
547    ffi = FFI()
548    for typename in all_signed_integer_types(ffi):
549        for real in all_float_types:
550            _check_field_match(typename, real, expect_mismatch=True)
551    for typename in all_float_types:
552        for real in all_signed_integer_types(ffi):
553            _check_field_match(typename, real, expect_mismatch=True)
554
555def test_struct_array_field():
556    ffi = FFI()
557    ffi.cdef("struct foo_s { int a[17]; ...; };")
558    ffi.verify("struct foo_s { int x; int a[17]; int y; };")
559    assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
560    s = ffi.new("struct foo_s *")
561    assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
562
563def test_struct_array_no_length():
564    ffi = FFI()
565    ffi.cdef("struct foo_s { int a[]; int y; ...; };\n"
566             "int bar(struct foo_s *);\n")
567    lib = ffi.verify("struct foo_s { int x; int a[17]; int y; };\n"
568                     "int bar(struct foo_s *f) { return f->a[14]; }\n")
569    assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
570    s = ffi.new("struct foo_s *")
571    assert ffi.typeof(s.a) is ffi.typeof('int[]')   # implicit max length
572    assert len(s.a) == 18  # max length, computed from the size and start offset
573    s.a[14] = 4242
574    assert lib.bar(s) == 4242
575    # with no declared length, out-of-bound accesses are not detected
576    s.a[17] = -521
577    assert s.y == s.a[17] == -521
578    #
579    s = ffi.new("struct foo_s *", {'a': list(range(17))})
580    assert s.a[16] == 16
581    # overflows at construction time not detected either
582    s = ffi.new("struct foo_s *", {'a': list(range(18))})
583    assert s.y == s.a[17] == 17
584
585def test_struct_array_guess_length():
586    ffi = FFI()
587    ffi.cdef("struct foo_s { int a[...]; };")
588    ffi.verify("struct foo_s { int x; int a[17]; int y; };")
589    assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
590    s = ffi.new("struct foo_s *")
591    assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
592    py.test.raises(IndexError, 's.a[17]')
593
594def test_struct_array_c99_1():
595    if sys.platform == 'win32':
596        py.test.skip("requires C99")
597    ffi = FFI()
598    ffi.cdef("struct foo_s { int x; int a[]; };")
599    ffi.verify("struct foo_s { int x; int a[]; };")
600    assert ffi.sizeof('struct foo_s') == 1 * ffi.sizeof('int')
601    s = ffi.new("struct foo_s *", [424242, 4])
602    assert ffi.sizeof(ffi.typeof(s[0])) == 1 * ffi.sizeof('int')
603    assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int')
604    # ^^^ explanation: if you write in C: "char x[5];", then
605    # "sizeof(x)" will evaluate to 5.  The behavior above is
606    # a generalization of that to "struct foo_s[len(a)=5] x;"
607    # if you could do that in C.
608    assert s.a[3] == 0
609    s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]])
610    assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int')
611    assert s.a[3] == -10
612    s = ffi.new("struct foo_s *")
613    assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int')
614    s = ffi.new("struct foo_s *", [424242])
615    assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int')
616
617def test_struct_array_c99_2():
618    if sys.platform == 'win32':
619        py.test.skip("requires C99")
620    ffi = FFI()
621    ffi.cdef("struct foo_s { int x; int a[]; ...; };")
622    ffi.verify("struct foo_s { int x, y; int a[]; };")
623    assert ffi.sizeof('struct foo_s') == 2 * ffi.sizeof('int')
624    s = ffi.new("struct foo_s *", [424242, 4])
625    assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int')
626    assert s.a[3] == 0
627    s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]])
628    assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int')
629    assert s.a[3] == -10
630    s = ffi.new("struct foo_s *")
631    assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int')
632    s = ffi.new("struct foo_s *", [424242])
633    assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int')
634
635def test_struct_ptr_to_array_field():
636    ffi = FFI()
637    ffi.cdef("struct foo_s { int (*a)[17]; ...; }; struct bar_s { ...; };")
638    ffi.verify("struct foo_s { int x; int (*a)[17]; int y; };\n"
639               "struct bar_s { int x; int *a; int y; };")
640    assert ffi.sizeof('struct foo_s') == ffi.sizeof("struct bar_s")
641    s = ffi.new("struct foo_s *")
642    assert ffi.sizeof(s.a) == ffi.sizeof('int(*)[17]') == ffi.sizeof("int *")
643
644def test_struct_with_bitfield_exact():
645    ffi = FFI()
646    ffi.cdef("struct foo_s { int a:2, b:3; };")
647    ffi.verify("struct foo_s { int a:2, b:3; };")
648    s = ffi.new("struct foo_s *")
649    s.b = 3
650    py.test.raises(OverflowError, "s.b = 4")
651    assert s.b == 3
652
653def test_struct_with_bitfield_enum():
654    ffi = FFI()
655    code = """
656        typedef enum { AA, BB, CC } foo_e;
657        typedef struct { foo_e f:2; } foo_s;
658    """
659    ffi.cdef(code)
660    ffi.verify(code)
661    s = ffi.new("foo_s *")
662    s.f = 2
663    assert s.f == 2
664
665def test_unsupported_struct_with_bitfield_ellipsis():
666    ffi = FFI()
667    py.test.raises(NotImplementedError, ffi.cdef,
668                   "struct foo_s { int a:2, b:3; ...; };")
669
670def test_global_constants():
671    ffi = FFI()
672    # use 'static const int', as generally documented, although in this
673    # case the 'static' is completely ignored.
674    ffi.cdef("static const int AA, BB, CC, DD;")
675    lib = ffi.verify("#define AA 42\n"
676                     "#define BB (-43)   // blah\n"
677                     "#define CC (22*2)  /* foobar */\n"
678                     "#define DD ((unsigned int)142)  /* foo\nbar */\n")
679    assert lib.AA == 42
680    assert lib.BB == -43
681    assert lib.CC == 44
682    assert lib.DD == 142
683
684def test_global_const_int_size():
685    # integer constants: ignore the declared type, always just use the value
686    for value in [-2**63, -2**31, -2**15,
687                  2**15-1, 2**15, 2**31-1, 2**31, 2**32-1, 2**32,
688                  2**63-1, 2**63, 2**64-1]:
689        ffi = FFI()
690        if value == int(ffi.cast("long long", value)):
691            if value < 0:
692                vstr = '(-%dLL-1)' % (~value,)
693            else:
694                vstr = '%dLL' % value
695        elif value == int(ffi.cast("unsigned long long", value)):
696            vstr = '%dULL' % value
697        else:
698            raise AssertionError(value)
699        ffi.cdef("static const unsigned short AA;")
700        lib = ffi.verify("#define AA %s\n" % vstr)
701        assert lib.AA == value
702        assert type(lib.AA) is type(int(lib.AA))
703
704def test_global_constants_non_int():
705    ffi = FFI()
706    ffi.cdef("static char *const PP;")
707    lib = ffi.verify('static char *const PP = "testing!";\n')
708    assert ffi.typeof(lib.PP) == ffi.typeof("char *")
709    assert ffi.string(lib.PP) == b"testing!"
710
711def test_nonfull_enum():
712    ffi = FFI()
713    ffi.cdef("enum ee { EE1, EE2, EE3, ... \n \t };")
714    py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE2')
715    ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
716    assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
717    assert ffi.string(ffi.cast('enum ee', -10)) == "EE3"
718    #
719    # try again
720    ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
721    assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
722    #
723    assert ffi.typeof("enum ee").relements == {'EE1': 10, 'EE2': 11, 'EE3': -10}
724    assert ffi.typeof("enum ee").elements == {10: 'EE1', 11: 'EE2', -10: 'EE3'}
725
726def test_full_enum():
727    ffi = FFI()
728    ffi.cdef("enum ee { EE1, EE2, EE3 };")
729    ffi.verify("enum ee { EE1, EE2, EE3 };")
730    py.test.raises(VerificationError, ffi.verify, "enum ee { EE1, EE2 };")
731    e = py.test.raises(VerificationError, ffi.verify,
732                       "enum ee { EE1, EE3, EE2 };")
733    assert str(e.value) == 'enum ee: EE2 has the real value 2, not 1'
734    # extra items cannot be seen and have no bad consequence anyway
735    lib = ffi.verify("enum ee { EE1, EE2, EE3, EE4 };")
736    assert lib.EE3 == 2
737
738def test_enum_usage():
739    ffi = FFI()
740    ffi.cdef("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;")
741    lib = ffi.verify("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;")
742    assert lib.EE2 == 1
743    s = ffi.new("sp", [lib.EE2])
744    assert s.x == 1
745    s.x = 17
746    assert s.x == 17
747
748def test_anonymous_enum():
749    ffi = FFI()
750    ffi.cdef("enum { EE1 }; enum { EE2, EE3 };")
751    lib = ffi.verify("enum { EE1 }; enum { EE2, EE3 };")
752    assert lib.EE1 == 0
753    assert lib.EE2 == 0
754    assert lib.EE3 == 1
755
756def test_nonfull_anonymous_enum():
757    ffi = FFI()
758    ffi.cdef("enum { EE1, ... }; enum { EE3, ... };")
759    lib = ffi.verify("enum { EE2, EE1 }; enum { EE3 };")
760    assert lib.EE1 == 1
761    assert lib.EE3 == 0
762
763def test_nonfull_enum_syntax2():
764    ffi = FFI()
765    ffi.cdef("enum ee { EE1, EE2=\t..., EE3 };")
766    py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1')
767    ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
768    assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2'
769    assert ffi.string(ffi.cast('enum ee', -10)) == 'EE3'
770    #
771    ffi = FFI()
772    ffi.cdef("enum ee { EE1, EE2=\t... };")
773    py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1')
774    ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
775    assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2'
776    #
777    ffi = FFI()
778    ffi.cdef("enum ee2 { EE4=..., EE5=..., ... };")
779    ffi.verify("enum ee2 { EE4=-1234-5, EE5 }; ")
780    assert ffi.string(ffi.cast('enum ee2', -1239)) == 'EE4'
781    assert ffi.string(ffi.cast('enum ee2', -1238)) == 'EE5'
782
783def test_nonfull_enum_bug3():
784    ffi = FFI()
785    ffi.cdef("enum ee2 { EE4=..., EE5=... };")
786    ffi.cdef("enum ee6 { EE7=10, EE8=..., EE9=... };")
787
788def test_get_set_errno():
789    ffi = FFI()
790    ffi.cdef("int foo(int);")
791    lib = ffi.verify("""
792        static int foo(int x)
793        {
794            errno += 1;
795            return x * 7;
796        }
797    """)
798    ffi.errno = 15
799    assert lib.foo(6) == 42
800    assert ffi.errno == 16
801
802def test_define_int():
803    ffi = FFI()
804    ffi.cdef("#define FOO ...\n"
805             "\t#\tdefine\tBAR\t...\t\n"
806             "#define BAZ ...\n")
807    lib = ffi.verify("#define FOO 42\n"
808                     "#define BAR (-44)\n"
809                     "#define BAZ 0xffffffffffffffffULL\n")
810    assert lib.FOO == 42
811    assert lib.BAR == -44
812    assert lib.BAZ == 0xffffffffffffffff
813
814def test_access_variable():
815    ffi = FFI()
816    ffi.cdef("int foo(void);\n"
817             "int somenumber;")
818    lib = ffi.verify("""
819        static int somenumber = 2;
820        static int foo(void) {
821            return somenumber * 7;
822        }
823    """)
824    assert lib.somenumber == 2
825    assert lib.foo() == 14
826    lib.somenumber = -6
827    assert lib.foo() == -42
828    assert lib.somenumber == -6
829    lib.somenumber = 2   # reset for the next run, if any
830
831def test_access_address_of_variable():
832    # access the address of 'somenumber': need a trick
833    ffi = FFI()
834    ffi.cdef("int somenumber; static int *const somenumberptr;")
835    lib = ffi.verify("""
836        static int somenumber = 2;
837        #define somenumberptr (&somenumber)
838    """)
839    assert lib.somenumber == 2
840    lib.somenumberptr[0] = 42
841    assert lib.somenumber == 42
842    lib.somenumber = 2    # reset for the next run, if any
843
844def test_access_array_variable(length=5):
845    ffi = FFI()
846    ffi.cdef("int foo(int);\n"
847             "int somenumber[%s];" % (length,))
848    lib = ffi.verify("""
849        static int somenumber[] = {2, 2, 3, 4, 5};
850        static int foo(int i) {
851            return somenumber[i] * 7;
852        }
853    """)
854    if length == '':
855        # a global variable of an unknown array length is implicitly
856        # transformed into a global pointer variable, because we can only
857        # work with array instances whose length we know.  using a pointer
858        # instead of an array gives the correct effects.
859        assert repr(lib.somenumber).startswith("<cdata 'int *' 0x")
860        py.test.raises(TypeError, len, lib.somenumber)
861    else:
862        assert repr(lib.somenumber).startswith("<cdata 'int[%s]' 0x" % length)
863        assert len(lib.somenumber) == 5
864    assert lib.somenumber[3] == 4
865    assert lib.foo(3) == 28
866    lib.somenumber[3] = -6
867    assert lib.foo(3) == -42
868    assert lib.somenumber[3] == -6
869    assert lib.somenumber[4] == 5
870    lib.somenumber[3] = 4    # reset for the next run, if any
871
872def test_access_array_variable_length_hidden():
873    test_access_array_variable(length='')
874
875def test_access_struct_variable():
876    ffi = FFI()
877    ffi.cdef("struct foo { int x; ...; };\n"
878             "int foo(int);\n"
879             "struct foo stuff;")
880    lib = ffi.verify("""
881        struct foo { int x, y, z; };
882        static struct foo stuff = {2, 5, 8};
883        static int foo(int i) {
884            switch (i) {
885            case 0: return stuff.x * 7;
886            case 1: return stuff.y * 7;
887            case 2: return stuff.z * 7;
888            }
889            return -1;
890        }
891    """)
892    assert lib.stuff.x == 2
893    assert lib.foo(0) == 14
894    assert lib.foo(1) == 35
895    assert lib.foo(2) == 56
896    lib.stuff.x = -6
897    assert lib.foo(0) == -42
898    assert lib.foo(1) == 35
899    lib.stuff.x = 2      # reset for the next run, if any
900
901def test_access_callback():
902    ffi = FFI()
903    ffi.cdef("int (*cb)(int);\n"
904             "int foo(int);\n"
905             "void reset_cb(void);")
906    lib = ffi.verify("""
907        static int g(int x) { return x * 7; }
908        static int (*cb)(int);
909        static int foo(int i) { return cb(i) - 1; }
910        static void reset_cb(void) { cb = g; }
911    """)
912    lib.reset_cb()
913    assert lib.foo(6) == 41
914    my_callback = ffi.callback("int(*)(int)", lambda n: n * 222)
915    lib.cb = my_callback
916    assert lib.foo(4) == 887
917
918def test_access_callback_function_typedef():
919    ffi = FFI()
920    ffi.cdef("typedef int mycallback_t(int);\n"
921             "mycallback_t *cb;\n"
922             "int foo(int);\n"
923             "void reset_cb(void);")
924    lib = ffi.verify("""
925        static int g(int x) { return x * 7; }
926        static int (*cb)(int);
927        static int foo(int i) { return cb(i) - 1; }
928        static void reset_cb(void) { cb = g; }
929    """)
930    lib.reset_cb()
931    assert lib.foo(6) == 41
932    my_callback = ffi.callback("int(*)(int)", lambda n: n * 222)
933    lib.cb = my_callback
934    assert lib.foo(4) == 887
935
936def test_ctypes_backend_forces_generic_engine():
937    from cffi.backend_ctypes import CTypesBackend
938    ffi = FFI(backend=CTypesBackend())
939    ffi.cdef("int func(int a);")
940    lib = ffi.verify("int func(int a) { return a * 42; }")
941    assert not hasattr(lib, '_cffi_python_module')
942    assert hasattr(lib, '_cffi_generic_module')
943    assert lib.func(100) == 4200
944
945def test_call_with_struct_ptr():
946    ffi = FFI()
947    ffi.cdef("typedef struct { int x; ...; } foo_t; int foo(foo_t *);")
948    lib = ffi.verify("""
949        typedef struct { int y, x; } foo_t;
950        static int foo(foo_t *f) { return f->x * 7; }
951    """)
952    f = ffi.new("foo_t *")
953    f.x = 6
954    assert lib.foo(f) == 42
955
956def test_unknown_type():
957    ffi = FFI()
958    ffi.cdef("""
959        typedef ... token_t;
960        int foo(token_t *);
961        #define TOKEN_SIZE ...
962    """)
963    lib = ffi.verify("""
964        typedef float token_t;
965        static int foo(token_t *tk) {
966            if (!tk)
967                return -42;
968            *tk += 1.601f;
969            return (int)*tk;
970        }
971        #define TOKEN_SIZE sizeof(token_t)
972    """)
973    # we cannot let ffi.new("token_t *") work, because we don't know ahead of
974    # time if it's ok to ask 'sizeof(token_t)' in the C code or not.
975    # See test_unknown_type_2.  Workaround.
976    tkmem = ffi.new("char[]", lib.TOKEN_SIZE)    # zero-initialized
977    tk = ffi.cast("token_t *", tkmem)
978    results = [lib.foo(tk) for i in range(6)]
979    assert results == [1, 3, 4, 6, 8, 9]
980    assert lib.foo(ffi.NULL) == -42
981
982def test_unknown_type_2():
983    ffi = FFI()
984    ffi.cdef("typedef ... token_t;")
985    lib = ffi.verify("typedef struct token_s token_t;")
986    # assert did not crash, even though 'sizeof(token_t)' is not valid in C.
987
988def test_unknown_type_3():
989    ffi = FFI()
990    ffi.cdef("""
991        typedef ... *token_p;
992        token_p foo(token_p);
993    """)
994    lib = ffi.verify("""
995        typedef struct _token_s *token_p;
996        token_p foo(token_p arg) {
997            if (arg)
998                return (token_p)0x12347;
999            else
1000                return (token_p)0x12345;
1001        }
1002    """)
1003    p = lib.foo(ffi.NULL)
1004    assert int(ffi.cast("intptr_t", p)) == 0x12345
1005    q = lib.foo(p)
1006    assert int(ffi.cast("intptr_t", q)) == 0x12347
1007
1008def test_varargs():
1009    ffi = FFI()
1010    ffi.cdef("int foo(int x, ...);")
1011    lib = ffi.verify("""
1012        int foo(int x, ...) {
1013            va_list vargs;
1014            va_start(vargs, x);
1015            x -= va_arg(vargs, int);
1016            x -= va_arg(vargs, int);
1017            va_end(vargs);
1018            return x;
1019        }
1020    """)
1021    assert lib.foo(50, ffi.cast("int", 5), ffi.cast("int", 3)) == 42
1022
1023def test_varargs_exact():
1024    if sys.platform == 'win32':
1025        py.test.skip("XXX fixme: only gives warnings")
1026    ffi = FFI()
1027    ffi.cdef("int foo(int x, ...);")
1028    py.test.raises(VerificationError, ffi.verify, """
1029        int foo(long long x, ...) {
1030            return x;
1031        }
1032    """)
1033
1034def test_varargs_struct():
1035    ffi = FFI()
1036    ffi.cdef("struct foo_s { char a; int b; }; int foo(int x, ...);")
1037    lib = ffi.verify("""
1038        struct foo_s {
1039            char a; int b;
1040        };
1041        int foo(int x, ...) {
1042            va_list vargs;
1043            struct foo_s s;
1044            va_start(vargs, x);
1045            s = va_arg(vargs, struct foo_s);
1046            va_end(vargs);
1047            return s.a - s.b;
1048        }
1049    """)
1050    s = ffi.new("struct foo_s *", [b'B', 1])
1051    assert lib.foo(50, s[0]) == ord('A')
1052
1053def test_autofilled_struct_as_argument():
1054    ffi = FFI()
1055    ffi.cdef("struct foo_s { long a; double b; ...; };\n"
1056             "int foo(struct foo_s);")
1057    lib = ffi.verify("""
1058        struct foo_s {
1059            double b;
1060            long a;
1061        };
1062        int foo(struct foo_s s) {
1063            return (int)s.a - (int)s.b;
1064        }
1065    """)
1066    s = ffi.new("struct foo_s *", [100, 1])
1067    assert lib.foo(s[0]) == 99
1068    assert lib.foo([100, 1]) == 99
1069
1070def test_autofilled_struct_as_argument_dynamic():
1071    ffi = FFI()
1072    ffi.cdef("struct foo_s { long a; ...; };\n"
1073             "int (*foo)(struct foo_s);")
1074    lib = ffi.verify("""
1075        struct foo_s {
1076            double b;
1077            long a;
1078        };
1079        int foo1(struct foo_s s) {
1080            return (int)s.a - (int)s.b;
1081        }
1082        int (*foo)(struct foo_s s) = &foo1;
1083    """)
1084    e = py.test.raises(NotImplementedError, lib.foo, "?")
1085    msg = ("ctype 'struct foo_s' not supported as argument.  It is a struct "
1086           'declared with "...;", but the C calling convention may depend on '
1087           "the missing fields; or, it contains anonymous struct/unions.  "
1088           "Such structs are only supported as argument "
1089           "if the function is 'API mode' and non-variadic (i.e. declared "
1090           "inside ffibuilder.cdef()+ffibuilder.set_source() and not taking "
1091           "a final '...' argument)")
1092    assert str(e.value) == msg
1093
1094def test_func_returns_struct():
1095    ffi = FFI()
1096    ffi.cdef("""
1097        struct foo_s { int aa, bb; };
1098        struct foo_s foo(int a, int b);
1099    """)
1100    lib = ffi.verify("""
1101        struct foo_s { int aa, bb; };
1102        struct foo_s foo(int a, int b) {
1103            struct foo_s r;
1104            r.aa = a*a;
1105            r.bb = b*b;
1106            return r;
1107        }
1108    """)
1109    s = lib.foo(6, 7)
1110    assert repr(s) == "<cdata 'struct foo_s' owning 8 bytes>"
1111    assert s.aa == 36
1112    assert s.bb == 49
1113
1114def test_func_as_funcptr():
1115    ffi = FFI()
1116    ffi.cdef("int *(*const fooptr)(void);")
1117    lib = ffi.verify("""
1118        int *foo(void) {
1119            return (int*)"foobar";
1120        }
1121        int *(*fooptr)(void) = foo;
1122    """)
1123    foochar = ffi.cast("char *(*)(void)", lib.fooptr)
1124    s = foochar()
1125    assert ffi.string(s) == b"foobar"
1126
1127def test_funcptr_as_argument():
1128    ffi = FFI()
1129    ffi.cdef("""
1130        void qsort(void *base, size_t nel, size_t width,
1131            int (*compar)(const void *, const void *));
1132    """)
1133    ffi.verify("#include <stdlib.h>")
1134
1135def test_func_as_argument():
1136    ffi = FFI()
1137    ffi.cdef("""
1138        void qsort(void *base, size_t nel, size_t width,
1139            int compar(const void *, const void *));
1140    """)
1141    ffi.verify("#include <stdlib.h>")
1142
1143def test_array_as_argument():
1144    ffi = FFI()
1145    ffi.cdef("""
1146        size_t strlen(char string[]);
1147    """)
1148    ffi.verify("#include <string.h>")
1149
1150def test_enum_as_argument():
1151    ffi = FFI()
1152    ffi.cdef("""
1153        enum foo_e { AA, BB, ... };
1154        int foo_func(enum foo_e);
1155    """)
1156    lib = ffi.verify("""
1157        enum foo_e { AA, CC, BB };
1158        int foo_func(enum foo_e e) { return (int)e; }
1159    """)
1160    assert lib.foo_func(lib.BB) == 2
1161    py.test.raises(TypeError, lib.foo_func, "BB")
1162
1163def test_enum_as_function_result():
1164    ffi = FFI()
1165    ffi.cdef("""
1166        enum foo_e { AA, BB, ... };
1167        enum foo_e foo_func(int x);
1168    """)
1169    lib = ffi.verify("""
1170        enum foo_e { AA, CC, BB };
1171        enum foo_e foo_func(int x) { return (enum foo_e)x; }
1172    """)
1173    assert lib.foo_func(lib.BB) == lib.BB == 2
1174
1175def test_enum_values():
1176    ffi = FFI()
1177    ffi.cdef("enum enum1_e { AA, BB };")
1178    lib = ffi.verify("enum enum1_e { AA, BB };")
1179    assert lib.AA == 0
1180    assert lib.BB == 1
1181    assert ffi.string(ffi.cast("enum enum1_e", 1)) == 'BB'
1182
1183def test_typedef_complete_enum():
1184    ffi = FFI()
1185    ffi.cdef("typedef enum { AA, BB } enum1_t;")
1186    lib = ffi.verify("typedef enum { AA, BB } enum1_t;")
1187    assert ffi.string(ffi.cast("enum1_t", 1)) == 'BB'
1188    assert lib.AA == 0
1189    assert lib.BB == 1
1190
1191def test_typedef_broken_complete_enum():
1192    ffi = FFI()
1193    ffi.cdef("typedef enum { AA, BB } enum1_t;")
1194    py.test.raises(VerificationError, ffi.verify,
1195                   "typedef enum { AA, CC, BB } enum1_t;")
1196
1197def test_typedef_incomplete_enum():
1198    ffi = FFI()
1199    ffi.cdef("typedef enum { AA, BB, ... } enum1_t;")
1200    lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;")
1201    assert ffi.string(ffi.cast("enum1_t", 1)) == '1'
1202    assert ffi.string(ffi.cast("enum1_t", 2)) == 'BB'
1203    assert lib.AA == 0
1204    assert lib.BB == 2
1205
1206def test_typedef_enum_as_argument():
1207    ffi = FFI()
1208    ffi.cdef("""
1209        typedef enum { AA, BB, ... } foo_t;
1210        int foo_func(foo_t);
1211    """)
1212    lib = ffi.verify("""
1213        typedef enum { AA, CC, BB } foo_t;
1214        int foo_func(foo_t e) { return (int)e; }
1215    """)
1216    assert lib.foo_func(lib.BB) == lib.BB == 2
1217    py.test.raises(TypeError, lib.foo_func, "BB")
1218
1219def test_typedef_enum_as_function_result():
1220    ffi = FFI()
1221    ffi.cdef("""
1222        typedef enum { AA, BB, ... } foo_t;
1223        foo_t foo_func(int x);
1224    """)
1225    lib = ffi.verify("""
1226        typedef enum { AA, CC, BB } foo_t;
1227        foo_t foo_func(int x) { return (foo_t)x; }
1228    """)
1229    assert lib.foo_func(lib.BB) == lib.BB == 2
1230
1231def test_function_typedef():
1232    ffi = FFI()
1233    ffi.cdef("""
1234        typedef double func_t(double);
1235        func_t sin;
1236    """)
1237    lib = ffi.verify('#include <math.h>', libraries=lib_m)
1238    assert lib.sin(1.23) == math.sin(1.23)
1239
1240def test_opaque_integer_as_function_result():
1241    #import platform
1242    #if platform.machine().startswith('sparc'):
1243    #    py.test.skip('Breaks horribly on sparc (SIGILL + corrupted stack)')
1244    #elif platform.machine() == 'mips64' and sys.maxsize > 2**32:
1245    #    py.test.skip('Segfaults on mips64el')
1246    # XXX bad abuse of "struct { ...; }".  It only works a bit by chance
1247    # anyway.  XXX think about something better :-(
1248    ffi = FFI()
1249    ffi.cdef("""
1250        typedef struct { ...; } myhandle_t;
1251        myhandle_t foo(void);
1252    """)
1253    lib = ffi.verify("""
1254        typedef short myhandle_t;
1255        myhandle_t foo(void) { return 42; }
1256    """)
1257    h = lib.foo()
1258    assert ffi.sizeof(h) == ffi.sizeof("short")
1259
1260def test_return_partial_struct():
1261    ffi = FFI()
1262    ffi.cdef("""
1263        typedef struct { int x; ...; } foo_t;
1264        foo_t foo(void);
1265    """)
1266    lib = ffi.verify("""
1267        typedef struct { int y, x; } foo_t;
1268        foo_t foo(void) { foo_t r = { 45, 81 }; return r; }
1269    """)
1270    h = lib.foo()
1271    assert ffi.sizeof(h) == 2 * ffi.sizeof("int")
1272    assert h.x == 81
1273
1274def test_take_and_return_partial_structs():
1275    ffi = FFI()
1276    ffi.cdef("""
1277        typedef struct { int x; ...; } foo_t;
1278        foo_t foo(foo_t, foo_t);
1279    """)
1280    lib = ffi.verify("""
1281        typedef struct { int y, x; } foo_t;
1282        foo_t foo(foo_t a, foo_t b) {
1283            foo_t r = { 100, a.x * 5 + b.x * 7 };
1284            return r;
1285        }
1286    """)
1287    args = ffi.new("foo_t[3]")
1288    args[0].x = 1000
1289    args[2].x = -498
1290    h = lib.foo(args[0], args[2])
1291    assert ffi.sizeof(h) == 2 * ffi.sizeof("int")
1292    assert h.x == 1000 * 5 - 498 * 7
1293
1294def test_cannot_name_struct_type():
1295    ffi = FFI()
1296    ffi.cdef("typedef struct { int x; } **sp; void foo(sp);")
1297    e = py.test.raises(VerificationError, ffi.verify,
1298                       "typedef struct { int x; } **sp; void foo(sp x) { }")
1299    assert 'in argument of foo: unknown type name' in str(e.value)
1300
1301def test_dont_check_unnamable_fields():
1302    ffi = FFI()
1303    ffi.cdef("struct foo_s { struct { int x; } someone; };")
1304    ffi.verify("struct foo_s { struct { int x; } someone; };")
1305    # assert did not crash
1306
1307def test_nested_anonymous_struct_exact():
1308    if sys.platform == 'win32':
1309        py.test.skip("nested anonymous struct/union")
1310    ffi = FFI()
1311    ffi.cdef("""
1312        struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1313    """)
1314    ffi.verify("""
1315        struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1316    """)
1317    p = ffi.new("struct foo_s *")
1318    assert ffi.sizeof(p[0]) == 3 * ffi.sizeof("int")    # with alignment
1319    p.a = 1234567
1320    p.b = b'X'
1321    p.c = b'Y'
1322    assert p.a == 1234567
1323    assert p.b == b'X'
1324    assert p.c == b'Y'
1325    assert p.d == b'Y'
1326
1327def test_nested_anonymous_struct_exact_error():
1328    if sys.platform == 'win32':
1329        py.test.skip("nested anonymous struct/union")
1330    ffi = FFI()
1331    ffi.cdef("""
1332        struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1333    """)
1334    py.test.raises(VerificationError, ffi.verify, """
1335        struct foo_s { struct { int a; short b; }; union { char c, d; }; };
1336    """)
1337    py.test.raises(VerificationError, ffi.verify, """
1338        struct foo_s { struct { int a; char e, b; }; union { char c, d; }; };
1339    """)
1340
1341def test_nested_anonymous_struct_inexact_1():
1342    ffi = FFI()
1343    ffi.cdef("""
1344        struct foo_s { struct { char b; ...; }; union { char c, d; }; };
1345    """)
1346    ffi.verify("""
1347        struct foo_s { int a, padding; char c, d, b; };
1348    """)
1349    assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
1350
1351def test_nested_anonymous_struct_inexact_2():
1352    ffi = FFI()
1353    ffi.cdef("""
1354        struct foo_s { union { char c, d; }; struct { int a; char b; }; ...; };
1355    """)
1356    ffi.verify("""
1357        struct foo_s { int a, padding; char c, d, b; };
1358    """)
1359    assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
1360
1361def test_ffi_union():
1362    ffi = FFI()
1363    ffi.cdef("union foo_u { char x; long *z; };")
1364    ffi.verify("union foo_u { char x; int y; long *z; };")
1365
1366def test_ffi_union_partial():
1367    ffi = FFI()
1368    ffi.cdef("union foo_u { char x; ...; };")
1369    ffi.verify("union foo_u { char x; int y; };")
1370    assert ffi.sizeof("union foo_u") == 4
1371
1372def test_ffi_union_with_partial_struct():
1373    ffi = FFI()
1374    ffi.cdef("struct foo_s { int x; ...; }; union foo_u { struct foo_s s; };")
1375    ffi.verify("struct foo_s { int a; int x; }; "
1376               "union foo_u { char b[32]; struct foo_s s; };")
1377    assert ffi.sizeof("struct foo_s") == 8
1378    assert ffi.sizeof("union foo_u") == 32
1379
1380def test_ffi_union_partial_2():
1381    ffi = FFI()
1382    ffi.cdef("typedef union { char x; ...; } u1;")
1383    ffi.verify("typedef union { char x; int y; } u1;")
1384    assert ffi.sizeof("u1") == 4
1385
1386def test_ffi_union_with_partial_struct_2():
1387    ffi = FFI()
1388    ffi.cdef("typedef struct { int x; ...; } s1;"
1389             "typedef union { s1 s; } u1;")
1390    ffi.verify("typedef struct { int a; int x; } s1; "
1391               "typedef union { char b[32]; s1 s; } u1;")
1392    assert ffi.sizeof("s1") == 8
1393    assert ffi.sizeof("u1") == 32
1394    assert ffi.offsetof("u1", "s") == 0
1395
1396def test_ffi_struct_packed():
1397    if sys.platform == 'win32':
1398        py.test.skip("needs a GCC extension")
1399    ffi = FFI()
1400    ffi.cdef("struct foo_s { int b; ...; };")
1401    ffi.verify("""
1402        struct foo_s {
1403            char a;
1404            int b;
1405        } __attribute__((packed));
1406    """)
1407
1408def test_tmpdir():
1409    import tempfile, os
1410    from testing.udir import udir
1411    tmpdir = tempfile.mkdtemp(dir=str(udir))
1412    ffi = FFI()
1413    ffi.cdef("int foo(int);")
1414    lib = ffi.verify("int foo(int a) { return a + 42; }", tmpdir=tmpdir)
1415    assert os.listdir(tmpdir)
1416    assert lib.foo(100) == 142
1417
1418def test_relative_to():
1419    import tempfile, os
1420    from testing.udir import udir
1421    tmpdir = tempfile.mkdtemp(dir=str(udir))
1422    ffi = FFI()
1423    ffi.cdef("int foo(int);")
1424    f = open(os.path.join(tmpdir, 'foo.h'), 'w')
1425    f.write("int foo(int a) { return a + 42; }\n")
1426    f.close()
1427    lib = ffi.verify('#include "foo.h"',
1428                     include_dirs=['.'],
1429                     relative_to=os.path.join(tmpdir, 'x'))
1430    assert lib.foo(100) == 142
1431
1432def test_bug1():
1433    ffi = FFI()
1434    ffi.cdef("""
1435        typedef struct tdlhandle_s { ...; } *tdl_handle_t;
1436        typedef struct my_error_code_ {
1437            tdl_handle_t *rh;
1438        } my_error_code_t;
1439    """)
1440    ffi.verify("""
1441        typedef struct tdlhandle_s { int foo; } *tdl_handle_t;
1442        typedef struct my_error_code_ {
1443            tdl_handle_t *rh;
1444        } my_error_code_t;
1445    """)
1446
1447def test_bool():
1448    if sys.platform == 'win32':
1449        py.test.skip("_Bool not in MSVC")
1450    ffi = FFI()
1451    ffi.cdef("struct foo_s { _Bool x; };"
1452             "_Bool foo(_Bool); _Bool (*foop)(_Bool);")
1453    lib = ffi.verify("""
1454        struct foo_s { _Bool x; };
1455        int foo(int arg) {
1456            return !arg;
1457        }
1458        _Bool _foofunc(_Bool x) {
1459            return !x;
1460        }
1461        _Bool (*foop)(_Bool) = _foofunc;
1462    """)
1463    p = ffi.new("struct foo_s *")
1464    p.x = 1
1465    assert p.x is True
1466    py.test.raises(OverflowError, "p.x = -1")
1467    py.test.raises(TypeError, "p.x = 0.0")
1468    assert lib.foop(1) is False
1469    assert lib.foop(True) is False
1470    assert lib.foop(0) is True
1471    py.test.raises(OverflowError, lib.foop, 42)
1472    py.test.raises(TypeError, lib.foop, 0.0)
1473    assert lib.foo(1) is False
1474    assert lib.foo(True) is False
1475    assert lib.foo(0) is True
1476    py.test.raises(OverflowError, lib.foo, 42)
1477    py.test.raises(TypeError, lib.foo, 0.0)
1478    assert int(ffi.cast("_Bool", long(1))) == 1
1479    assert int(ffi.cast("_Bool", long(0))) == 0
1480    assert int(ffi.cast("_Bool", long(-1))) == 1
1481    assert int(ffi.cast("_Bool", 10**200)) == 1
1482    assert int(ffi.cast("_Bool", 10**40000)) == 1
1483    #
1484    class Foo(object):
1485        def __int__(self):
1486            self.seen = 1
1487            return result
1488    f = Foo()
1489    f.seen = 0
1490    result = 42
1491    assert int(ffi.cast("_Bool", f)) == 1
1492    assert f.seen
1493    f.seen = 0
1494    result = 0
1495    assert int(ffi.cast("_Bool", f)) == 0
1496    assert f.seen
1497    #
1498    py.test.raises(TypeError, ffi.cast, "_Bool", [])
1499
1500def test_bool_on_long_double():
1501    if sys.platform == 'win32':
1502        py.test.skip("_Bool not in MSVC")
1503    f = 1E-250
1504    if f == 0.0 or f*f != 0.0:
1505        py.test.skip("unexpected precision")
1506    ffi = FFI()
1507    ffi.cdef("long double square(long double f); _Bool opposite(_Bool);")
1508    lib = ffi.verify("long double square(long double f) { return f*f; }\n"
1509                     "_Bool opposite(_Bool x) { return !x; }")
1510    f0 = lib.square(0.0)
1511    f2 = lib.square(f)
1512    f3 = lib.square(f * 2.0)
1513    if repr(f2) == repr(f3):
1514        py.test.skip("long double doesn't have enough precision")
1515    assert float(f0) == float(f2) == float(f3) == 0.0  # too tiny for 'double'
1516    assert int(ffi.cast("_Bool", f2)) == 1
1517    assert int(ffi.cast("_Bool", f3)) == 1
1518    assert int(ffi.cast("_Bool", f0)) == 0
1519    py.test.raises(TypeError, lib.opposite, f2)
1520
1521def test_cannot_pass_float():
1522    for basetype in ['char', 'short', 'int', 'long', 'long long']:
1523        for sign in ['signed', 'unsigned']:
1524            type = '%s %s' % (sign, basetype)
1525            ffi = FFI()
1526            ffi.cdef("struct foo_s { %s x; };\n"
1527                     "int foo(%s);" % (type, type))
1528            lib = ffi.verify("""
1529                struct foo_s { %s x; };
1530                int foo(%s arg) {
1531                    return !arg;
1532                }
1533            """ % (type, type))
1534            p = ffi.new("struct foo_s *")
1535            py.test.raises(TypeError, "p.x = 0.0")
1536            assert lib.foo(42) == 0
1537            assert lib.foo(0) == 1
1538            py.test.raises(TypeError, lib.foo, 0.0)
1539
1540def test_cast_from_int_type_to_bool():
1541    ffi = FFI()
1542    for basetype in ['char', 'short', 'int', 'long', 'long long']:
1543        for sign in ['signed', 'unsigned']:
1544            type = '%s %s' % (sign, basetype)
1545            assert int(ffi.cast("_Bool", ffi.cast(type, 42))) == 1
1546            assert int(ffi.cast("bool", ffi.cast(type, 42))) == 1
1547            assert int(ffi.cast("_Bool", ffi.cast(type, 0))) == 0
1548
1549def test_addressof():
1550    ffi = FFI()
1551    ffi.cdef("""
1552        struct point_s { int x, y; };
1553        struct foo_s { int z; struct point_s point; };
1554        struct point_s sum_coord(struct point_s *);
1555    """)
1556    lib = ffi.verify("""
1557        struct point_s { int x, y; };
1558        struct foo_s { int z; struct point_s point; };
1559        struct point_s sum_coord(struct point_s *point) {
1560            struct point_s r;
1561            r.x = point->x + point->y;
1562            r.y = point->x - point->y;
1563            return r;
1564        }
1565    """)
1566    p = ffi.new("struct foo_s *")
1567    p.point.x = 16
1568    p.point.y = 9
1569    py.test.raises(TypeError, lib.sum_coord, p.point)
1570    res = lib.sum_coord(ffi.addressof(p.point))
1571    assert res.x == 25
1572    assert res.y == 7
1573    res2 = lib.sum_coord(ffi.addressof(res))
1574    assert res2.x == 32
1575    assert res2.y == 18
1576    py.test.raises(TypeError, lib.sum_coord, res2)
1577
1578def test_callback_in_thread():
1579    if sys.platform == 'win32':
1580        py.test.skip("pthread only")
1581    import os, subprocess, imp
1582    arg = os.path.join(os.path.dirname(__file__), 'callback_in_thread.py')
1583    g = subprocess.Popen([sys.executable, arg,
1584                          os.path.dirname(imp.find_module('cffi')[1])])
1585    result = g.wait()
1586    assert result == 0
1587
1588def test_keepalive_lib():
1589    ffi = FFI()
1590    ffi.cdef("int foobar(void);")
1591    lib = ffi.verify("int foobar(void) { return 42; }")
1592    func = lib.foobar
1593    ffi_r = weakref.ref(ffi)
1594    lib_r = weakref.ref(lib)
1595    del ffi
1596    import gc; gc.collect()       # lib stays alive
1597    assert lib_r() is not None
1598    assert ffi_r() is not None
1599    assert func() == 42
1600
1601def test_keepalive_ffi():
1602    ffi = FFI()
1603    ffi.cdef("int foobar(void);")
1604    lib = ffi.verify("int foobar(void) { return 42; }")
1605    func = lib.foobar
1606    ffi_r = weakref.ref(ffi)
1607    lib_r = weakref.ref(lib)
1608    del lib
1609    import gc; gc.collect()       # ffi stays alive
1610    assert ffi_r() is not None
1611    assert lib_r() is not None
1612    assert func() == 42
1613
1614def test_FILE_stored_in_stdout():
1615    if not sys.platform.startswith('linux'):
1616        py.test.skip("likely, we cannot assign to stdout")
1617    ffi = FFI()
1618    ffi.cdef("int printf(const char *, ...); FILE *setstdout(FILE *);")
1619    lib = ffi.verify("""
1620        #include <stdio.h>
1621        FILE *setstdout(FILE *f) {
1622            FILE *result = stdout;
1623            stdout = f;
1624            return result;
1625        }
1626    """)
1627    import os
1628    fdr, fdw = os.pipe()
1629    fw1 = os.fdopen(fdw, 'wb', 256)
1630    old_stdout = lib.setstdout(fw1)
1631    try:
1632        #
1633        fw1.write(b"X")
1634        r = lib.printf(b"hello, %d!\n", ffi.cast("int", 42))
1635        fw1.close()
1636        assert r == len("hello, 42!\n")
1637        #
1638    finally:
1639        lib.setstdout(old_stdout)
1640    #
1641    result = os.read(fdr, 256)
1642    os.close(fdr)
1643    # the 'X' might remain in the user-level buffer of 'fw1' and
1644    # end up showing up after the 'hello, 42!\n'
1645    assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
1646
1647def test_FILE_stored_explicitly():
1648    ffi = FFI()
1649    ffi.cdef("int myprintf11(const char *, int); FILE *myfile;")
1650    lib = ffi.verify("""
1651        #include <stdio.h>
1652        FILE *myfile;
1653        int myprintf11(const char *out, int value) {
1654            return fprintf(myfile, out, value);
1655        }
1656    """)
1657    import os
1658    fdr, fdw = os.pipe()
1659    fw1 = os.fdopen(fdw, 'wb', 256)
1660    lib.myfile = ffi.cast("FILE *", fw1)
1661    #
1662    fw1.write(b"X")
1663    r = lib.myprintf11(b"hello, %d!\n", ffi.cast("int", 42))
1664    fw1.close()
1665    assert r == len("hello, 42!\n")
1666    #
1667    result = os.read(fdr, 256)
1668    os.close(fdr)
1669    # the 'X' might remain in the user-level buffer of 'fw1' and
1670    # end up showing up after the 'hello, 42!\n'
1671    assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
1672
1673def test_global_array_with_missing_length():
1674    ffi = FFI()
1675    ffi.cdef("int fooarray[];")
1676    lib = ffi.verify("int fooarray[50];")
1677    assert repr(lib.fooarray).startswith("<cdata 'int *'")
1678
1679def test_global_array_with_dotdotdot_length():
1680    ffi = FFI()
1681    ffi.cdef("int fooarray[...];")
1682    lib = ffi.verify("int fooarray[50];")
1683    assert repr(lib.fooarray).startswith("<cdata 'int[50]'")
1684
1685def test_bad_global_array_with_dotdotdot_length():
1686    ffi = FFI()
1687    ffi.cdef("int fooarray[...];")
1688    py.test.raises(VerificationError, ffi.verify, "char fooarray[23];")
1689
1690def test_struct_containing_struct():
1691    ffi = FFI()
1692    ffi.cdef("struct foo_s { ...; }; struct bar_s { struct foo_s f; ...; };")
1693    ffi.verify("struct foo_s { int x; }; struct bar_s { struct foo_s f; };")
1694    #
1695    ffi = FFI()
1696    ffi.cdef("struct foo_s { struct bar_s f; ...; }; struct bar_s { ...; };")
1697    ffi.verify("struct bar_s { int x; }; struct foo_s { struct bar_s f; };")
1698
1699def test_struct_returned_by_func():
1700    ffi = FFI()
1701    ffi.cdef("typedef ... foo_t; foo_t myfunc(void);")
1702    e = py.test.raises(TypeError, ffi.verify,
1703                       "typedef struct { int x; } foo_t; "
1704                       "foo_t myfunc(void) { foo_t x = { 42 }; return x; }")
1705    assert str(e.value) == (
1706        "function myfunc: 'foo_t' is used as result type, but is opaque")
1707
1708def test_include():
1709    ffi1 = FFI()
1710    ffi1.cdef("typedef struct { int x; ...; } foo_t;")
1711    ffi1.verify("typedef struct { int y, x; } foo_t;")
1712    ffi2 = FFI()
1713    ffi2.include(ffi1)
1714    ffi2.cdef("int myfunc(foo_t *);")
1715    lib = ffi2.verify("typedef struct { int y, x; } foo_t;"
1716                      "int myfunc(foo_t *p) { return 42 * p->x; }")
1717    res = lib.myfunc(ffi2.new("foo_t *", {'x': 10}))
1718    assert res == 420
1719    res = lib.myfunc(ffi1.new("foo_t *", {'x': -10}))
1720    assert res == -420
1721
1722def test_include_enum():
1723    ffi1 = FFI()
1724    ffi1.cdef("enum foo_e { AA, ... };")
1725    lib1 = ffi1.verify("enum foo_e { CC, BB, AA };")
1726    ffi2 = FFI()
1727    ffi2.include(ffi1)
1728    ffi2.cdef("int myfunc(enum foo_e);")
1729    lib2 = ffi2.verify("enum foo_e { CC, BB, AA };"
1730                       "int myfunc(enum foo_e x) { return (int)x; }")
1731    res = lib2.myfunc(lib2.AA)
1732    assert res == 2
1733
1734def test_named_pointer_as_argument():
1735    ffi = FFI()
1736    ffi.cdef("typedef struct { int x; } *mystruct_p;\n"
1737             "mystruct_p ff5a(mystruct_p);")
1738    lib = ffi.verify("typedef struct { int x; } *mystruct_p;\n"
1739                     "mystruct_p ff5a(mystruct_p p) { p->x += 40; return p; }")
1740    p = ffi.new("mystruct_p", [-2])
1741    q = lib.ff5a(p)
1742    assert q == p
1743    assert p.x == 38
1744
1745def test_enum_size():
1746    cases = [('123',           4, 4294967295),
1747             ('4294967295U',   4, 4294967295),
1748             ('-123',          4, -1),
1749             ('-2147483647-1', 4, -1),
1750             ]
1751    if FFI().sizeof("long") == 8:
1752        cases += [('4294967296L',        8, 2**64-1),
1753                  ('%dUL' % (2**64-1),   8, 2**64-1),
1754                  ('-2147483649L',       8, -1),
1755                  ('%dL-1L' % (1-2**63), 8, -1)]
1756    for hidden_value, expected_size, expected_minus1 in cases:
1757        if sys.platform == 'win32' and 'U' in hidden_value:
1758            continue   # skipped on Windows
1759        ffi = FFI()
1760        ffi.cdef("enum foo_e { AA, BB, ... };")
1761        lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value)
1762        assert lib.AA == 0
1763        assert lib.BB == eval(hidden_value.replace('U', '').replace('L', ''))
1764        assert ffi.sizeof("enum foo_e") == expected_size
1765        assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
1766    # test with the large value hidden:
1767    # disabled so far, doesn't work
1768##    for hidden_value, expected_size, expected_minus1 in cases:
1769##        ffi = FFI()
1770##        ffi.cdef("enum foo_e { AA, BB, ... };")
1771##        lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value)
1772##        assert lib.AA == 0
1773##        assert ffi.sizeof("enum foo_e") == expected_size
1774##        assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
1775
1776def test_enum_bug118():
1777    maxulong = 256 ** FFI().sizeof("unsigned long") - 1
1778    for c1, c2, c2c in [(0xffffffff, -1, ''),
1779                        (maxulong, -1, ''),
1780                        (-1, 0xffffffff, 'U'),
1781                        (-1, maxulong, 'UL')]:
1782        if c2c and sys.platform == 'win32':
1783            continue     # enums may always be signed with MSVC
1784        ffi = FFI()
1785        ffi.cdef("enum foo_e { AA=%s };" % c1)
1786        e = py.test.raises(VerificationError, ffi.verify,
1787                           "enum foo_e { AA=%s%s };" % (c2, c2c))
1788        assert str(e.value) == ('enum foo_e: AA has the real value %d, not %d'
1789                                % (c2, c1))
1790
1791def test_string_to_voidp_arg():
1792    ffi = FFI()
1793    ffi.cdef("int myfunc(void *);")
1794    lib = ffi.verify("int myfunc(void *p) { return ((signed char *)p)[0]; }")
1795    res = lib.myfunc(b"hi!")
1796    assert res == ord(b"h")
1797    p = ffi.new("char[]", b"gah")
1798    res = lib.myfunc(p)
1799    assert res == ord(b"g")
1800    res = lib.myfunc(ffi.cast("void *", p))
1801    assert res == ord(b"g")
1802    res = lib.myfunc(ffi.cast("int *", p))
1803    assert res == ord(b"g")
1804
1805def test_callback_indirection():
1806    ffi = FFI()
1807    ffi.cdef("""
1808        int (*python_callback)(int how_many, int *values);
1809        int (*const c_callback)(int,...);   /* pass this ptr to C routines */
1810        int some_c_function(int(*cb)(int,...));
1811    """)
1812    lib = ffi.verify("""
1813        #include <stdarg.h>
1814        #ifdef _WIN32
1815        #include <malloc.h>
1816        #define alloca _alloca
1817        #else
1818        # ifdef __FreeBSD__
1819        #  include <stdlib.h>
1820        # else
1821        #  include <alloca.h>
1822        # endif
1823        #endif
1824        static int (*python_callback)(int how_many, int *values);
1825        static int c_callback(int how_many, ...) {
1826            va_list ap;
1827            /* collect the "..." arguments into the values[] array */
1828            int i, *values = alloca((size_t)how_many * sizeof(int));
1829            va_start(ap, how_many);
1830            for (i=0; i<how_many; i++)
1831                values[i] = va_arg(ap, int);
1832            va_end(ap);
1833            return python_callback(how_many, values);
1834        }
1835        int some_c_function(int(*cb)(int,...)) {
1836            int result = cb(2, 10, 20);
1837            result += cb(3, 30, 40, 50);
1838            return result;
1839        }
1840    """)
1841    seen = []
1842    @ffi.callback("int(int, int*)")
1843    def python_callback(how_many, values):
1844        seen.append([values[i] for i in range(how_many)])
1845        return 42
1846    lib.python_callback = python_callback
1847
1848    res = lib.some_c_function(lib.c_callback)
1849    assert res == 84
1850    assert seen == [[10, 20], [30, 40, 50]]
1851
1852def test_floatstar_argument():
1853    ffi = FFI()
1854    ffi.cdef("float sum3floats(float *);")
1855    lib = ffi.verify("""
1856        float sum3floats(float *f) {
1857            return f[0] + f[1] + f[2];
1858        }
1859    """)
1860    assert lib.sum3floats((1.5, 2.5, 3.5)) == 7.5
1861    p = ffi.new("float[]", (1.5, 2.5, 3.5))
1862    assert lib.sum3floats(p) == 7.5
1863
1864def test_charstar_argument():
1865    ffi = FFI()
1866    ffi.cdef("char sum3chars(char *);")
1867    lib = ffi.verify("""
1868        char sum3chars(char *f) {
1869            return (char)(f[0] + f[1] + f[2]);
1870        }
1871    """)
1872    assert lib.sum3chars((b'\x10', b'\x20', b'\x30')) == b'\x60'
1873    p = ffi.new("char[]", b'\x10\x20\x30')
1874    assert lib.sum3chars(p) == b'\x60'
1875
1876def test_passing_string_or_NULL():
1877    ffi = FFI()
1878    ffi.cdef("int seeme1(char *); int seeme2(int *);")
1879    lib = ffi.verify("""
1880        int seeme1(char *x) {
1881            return (x == NULL);
1882        }
1883        int seeme2(int *x) {
1884            return (x == NULL);
1885        }
1886    """)
1887    assert lib.seeme1(b"foo") == 0
1888    assert lib.seeme1(ffi.NULL) == 1
1889    assert lib.seeme2([42, 43]) == 0
1890    assert lib.seeme2(ffi.NULL) == 1
1891    py.test.raises(TypeError, lib.seeme1, None)
1892    py.test.raises(TypeError, lib.seeme2, None)
1893    py.test.raises(TypeError, lib.seeme1, 0.0)
1894    py.test.raises(TypeError, lib.seeme2, 0.0)
1895    py.test.raises(TypeError, lib.seeme1, 0)
1896    py.test.raises(TypeError, lib.seeme2, 0)
1897    zeroL  = 99999999999999999999
1898    zeroL -= 99999999999999999999
1899    py.test.raises(TypeError, lib.seeme2, zeroL)
1900
1901def test_typeof_function():
1902    ffi = FFI()
1903    ffi.cdef("int foo(int, char);")
1904    lib = ffi.verify("int foo(int x, char y) { (void)x; (void)y; return 42; }")
1905    ctype = ffi.typeof(lib.foo)
1906    assert len(ctype.args) == 2
1907    assert ctype.result == ffi.typeof("int")
1908
1909def test_call_with_voidstar_arg():
1910    ffi = FFI()
1911    ffi.cdef("int f(void *);")
1912    lib = ffi.verify("int f(void *x) { return ((char*)x)[0]; }")
1913    assert lib.f(b"foobar") == ord(b"f")
1914
1915def test_dir():
1916    ffi = FFI()
1917    ffi.cdef("""void somefunc(void);
1918                extern int somevar, somearray[2];
1919                static char *const sv2;
1920                enum my_e { AA, BB, ... };
1921                #define FOO ...""")
1922    lib = ffi.verify("""void somefunc(void) { }
1923                        int somevar, somearray[2];
1924                        #define sv2 "text"
1925                        enum my_e { AA, BB };
1926                        #define FOO 42""")
1927    assert dir(lib) == ['AA', 'BB', 'FOO', 'somearray',
1928                        'somefunc', 'somevar', 'sv2']
1929
1930def test_typeof_func_with_struct_argument():
1931    ffi = FFI()
1932    ffi.cdef("""struct s { int a; }; int foo(struct s);""")
1933    lib = ffi.verify("""struct s { int a; };
1934                        int foo(struct s x) { return x.a; }""")
1935    s = ffi.new("struct s *", [-1234])
1936    m = lib.foo(s[0])
1937    assert m == -1234
1938    assert repr(ffi.typeof(lib.foo)) == "<ctype 'int(*)(struct s)'>"
1939
1940def test_bug_const_char_ptr_array_1():
1941    ffi = FFI()
1942    ffi.cdef("""const char *a[...];""")
1943    lib = ffi.verify("""const char *a[5];""")
1944    assert repr(ffi.typeof(lib.a)) == "<ctype 'char *[5]'>"
1945
1946def test_bug_const_char_ptr_array_2():
1947    from cffi import FFI     # ignore warnings
1948    ffi = FFI()
1949    ffi.cdef("""const int a[];""")
1950    lib = ffi.verify("""const int a[5];""")
1951    assert repr(ffi.typeof(lib.a)) == "<ctype 'int *'>"
1952
1953def _test_various_calls(force_libffi):
1954    cdef_source = """
1955    int xvalue;
1956    long long ivalue, rvalue;
1957    float fvalue;
1958    double dvalue;
1959    long double Dvalue;
1960    signed char tf_bb(signed char x, signed char c);
1961    unsigned char tf_bB(signed char x, unsigned char c);
1962    short tf_bh(signed char x, short c);
1963    unsigned short tf_bH(signed char x, unsigned short c);
1964    int tf_bi(signed char x, int c);
1965    unsigned int tf_bI(signed char x, unsigned int c);
1966    long tf_bl(signed char x, long c);
1967    unsigned long tf_bL(signed char x, unsigned long c);
1968    long long tf_bq(signed char x, long long c);
1969    unsigned long long tf_bQ(signed char x, unsigned long long c);
1970    float tf_bf(signed char x, float c);
1971    double tf_bd(signed char x, double c);
1972    long double tf_bD(signed char x, long double c);
1973    """
1974    if force_libffi:
1975        cdef_source = (cdef_source
1976            .replace('tf_', '(*const tf_')
1977            .replace('(signed char x', ')(signed char x'))
1978    ffi = FFI()
1979    ffi.cdef(cdef_source)
1980    lib = ffi.verify("""
1981    int xvalue;
1982    long long ivalue, rvalue;
1983    float fvalue;
1984    double dvalue;
1985    long double Dvalue;
1986
1987    typedef signed char b_t;
1988    typedef unsigned char B_t;
1989    typedef short h_t;
1990    typedef unsigned short H_t;
1991    typedef int i_t;
1992    typedef unsigned int I_t;
1993    typedef long l_t;
1994    typedef unsigned long L_t;
1995    typedef long long q_t;
1996    typedef unsigned long long Q_t;
1997    typedef float f_t;
1998    typedef double d_t;
1999    typedef long double D_t;
2000    #define S(letter)  xvalue = (int)x; letter##value = (letter##_t)c;
2001    #define R(letter)  return (letter##_t)rvalue;
2002
2003    signed char tf_bb(signed char x, signed char c) { S(i) R(b) }
2004    unsigned char tf_bB(signed char x, unsigned char c) { S(i) R(B) }
2005    short tf_bh(signed char x, short c) { S(i) R(h) }
2006    unsigned short tf_bH(signed char x, unsigned short c) { S(i) R(H) }
2007    int tf_bi(signed char x, int c) { S(i) R(i) }
2008    unsigned int tf_bI(signed char x, unsigned int c) { S(i) R(I) }
2009    long tf_bl(signed char x, long c) { S(i) R(l) }
2010    unsigned long tf_bL(signed char x, unsigned long c) { S(i) R(L) }
2011    long long tf_bq(signed char x, long long c) { S(i) R(q) }
2012    unsigned long long tf_bQ(signed char x, unsigned long long c) { S(i) R(Q) }
2013    float tf_bf(signed char x, float c) { S(f) R(f) }
2014    double tf_bd(signed char x, double c) { S(d) R(d) }
2015    long double tf_bD(signed char x, long double c) { S(D) R(D) }
2016    """)
2017    lib.rvalue = 0x7182838485868788
2018    for kind, cname in [('b', 'signed char'),
2019                        ('B', 'unsigned char'),
2020                        ('h', 'short'),
2021                        ('H', 'unsigned short'),
2022                        ('i', 'int'),
2023                        ('I', 'unsigned int'),
2024                        ('l', 'long'),
2025                        ('L', 'unsigned long'),
2026                        ('q', 'long long'),
2027                        ('Q', 'unsigned long long'),
2028                        ('f', 'float'),
2029                        ('d', 'double'),
2030                        ('D', 'long double')]:
2031        sign = +1 if 'unsigned' in cname else -1
2032        lib.xvalue = 0
2033        lib.ivalue = 0
2034        lib.fvalue = 0
2035        lib.dvalue = 0
2036        lib.Dvalue = 0
2037        fun = getattr(lib, 'tf_b' + kind)
2038        res = fun(-42, sign * 99)
2039        if kind == 'D':
2040            res = float(res)
2041        assert res == int(ffi.cast(cname, 0x7182838485868788))
2042        assert lib.xvalue == -42
2043        if kind in 'fdD':
2044            assert float(getattr(lib, kind + 'value')) == -99.0
2045        else:
2046            assert lib.ivalue == sign * 99
2047
2048def test_various_calls_direct():
2049    _test_various_calls(force_libffi=False)
2050
2051def test_various_calls_libffi():
2052    _test_various_calls(force_libffi=True)
2053
2054def test_ptr_to_opaque():
2055    ffi = FFI()
2056    ffi.cdef("typedef ... foo_t; int f1(foo_t*); foo_t *f2(int);")
2057    lib = ffi.verify("""
2058        #include <stdlib.h>
2059        typedef struct { int x; } foo_t;
2060        int f1(foo_t* p) {
2061            int x = p->x;
2062            free(p);
2063            return x;
2064        }
2065        foo_t *f2(int x) {
2066            foo_t *p = malloc(sizeof(foo_t));
2067            p->x = x;
2068            return p;
2069        }
2070    """)
2071    p = lib.f2(42)
2072    x = lib.f1(p)
2073    assert x == 42
2074
2075def _run_in_multiple_threads(test1):
2076    test1()
2077    import sys
2078    try:
2079        import thread
2080    except ImportError:
2081        import _thread as thread
2082    errors = []
2083    def wrapper(lock):
2084        try:
2085            test1()
2086        except:
2087            errors.append(sys.exc_info())
2088        lock.release()
2089    locks = []
2090    for i in range(10):
2091        _lock = thread.allocate_lock()
2092        _lock.acquire()
2093        thread.start_new_thread(wrapper, (_lock,))
2094        locks.append(_lock)
2095    for _lock in locks:
2096        _lock.acquire()
2097        if errors:
2098            raise errors[0][1]
2099
2100def test_errno_working_even_with_pypys_jit():
2101    ffi = FFI()
2102    ffi.cdef("int f(int);")
2103    lib = ffi.verify("""
2104        #include <errno.h>
2105        int f(int x) { return (errno = errno + x); }
2106    """)
2107    @_run_in_multiple_threads
2108    def test1():
2109        ffi.errno = 0
2110        for i in range(10000):
2111            e = lib.f(1)
2112            assert e == i + 1
2113            assert ffi.errno == e
2114        for i in range(10000):
2115            ffi.errno = i
2116            e = lib.f(42)
2117            assert e == i + 42
2118
2119def test_getlasterror_working_even_with_pypys_jit():
2120    if sys.platform != 'win32':
2121        py.test.skip("win32-only test")
2122    ffi = FFI()
2123    ffi.cdef("void SetLastError(DWORD);")
2124    lib = ffi.dlopen("Kernel32.dll")
2125    @_run_in_multiple_threads
2126    def test1():
2127        for i in range(10000):
2128            n = (1 << 29) + i
2129            lib.SetLastError(n)
2130            assert ffi.getwinerror()[0] == n
2131
2132def test_verify_dlopen_flags():
2133    # Careful with RTLD_GLOBAL.  If by chance the FFI is not deleted
2134    # promptly, like on PyPy, then other tests may see the same
2135    # exported symbols as well.  So we must not export a simple name
2136    # like 'foo'!
2137    ffi1 = FFI()
2138    ffi1.cdef("int foo_verify_dlopen_flags;")
2139
2140    lib1 = ffi1.verify("int foo_verify_dlopen_flags;",
2141                       flags=ffi1.RTLD_GLOBAL | ffi1.RTLD_LAZY)
2142    lib2 = get_second_lib()
2143
2144    lib1.foo_verify_dlopen_flags = 42
2145    assert lib2.foo_verify_dlopen_flags == 42
2146    lib2.foo_verify_dlopen_flags += 1
2147    assert lib1.foo_verify_dlopen_flags == 43
2148
2149def get_second_lib():
2150    # Hack, using modulename makes the test fail
2151    ffi2 = FFI()
2152    ffi2.cdef("int foo_verify_dlopen_flags;")
2153    lib2 = ffi2.verify("int foo_verify_dlopen_flags;",
2154                       flags=ffi2.RTLD_GLOBAL | ffi2.RTLD_LAZY)
2155    return lib2
2156
2157def test_consider_not_implemented_function_type():
2158    ffi = FFI()
2159    ffi.cdef("typedef union { int a; float b; } Data;"
2160             "typedef struct { int a:2; } MyStr;"
2161             "typedef void (*foofunc_t)(Data);"
2162             "typedef Data (*bazfunc_t)(void);"
2163             "typedef MyStr (*barfunc_t)(void);")
2164    fooptr = ffi.cast("foofunc_t", 123)
2165    bazptr = ffi.cast("bazfunc_t", 123)
2166    barptr = ffi.cast("barfunc_t", 123)
2167    # assert did not crash so far
2168    e = py.test.raises(NotImplementedError, fooptr, ffi.new("Data *"))
2169    assert str(e.value) == (
2170        "ctype 'Data' not supported as argument by libffi.  Unions are only "
2171        "supported as argument if the function is 'API mode' and "
2172        "non-variadic (i.e. declared inside ffibuilder.cdef()+"
2173        "ffibuilder.set_source() and not taking a final '...' argument)")
2174    e = py.test.raises(NotImplementedError, bazptr)
2175    assert str(e.value) == (
2176        "ctype 'Data' not supported as return value by libffi.  Unions are "
2177        "only supported as return value if the function is 'API mode' and "
2178        "non-variadic (i.e. declared inside ffibuilder.cdef()+"
2179        "ffibuilder.set_source() and not taking a final '...' argument)")
2180    e = py.test.raises(NotImplementedError, barptr)
2181    assert str(e.value) == (
2182        "ctype 'MyStr' not supported as return value.  It is a struct with "
2183        "bit fields, which libffi does not support.  Such structs are only "
2184        "supported as return value if the function is 'API mode' and non-"
2185        "variadic (i.e. declared inside ffibuilder.cdef()+ffibuilder."
2186        "set_source() and not taking a final '...' argument)")
2187
2188def test_verify_extra_arguments():
2189    ffi = FFI()
2190    ffi.cdef("#define ABA ...")
2191    lib = ffi.verify("", define_macros=[('ABA', '42')])
2192    assert lib.ABA == 42
2193
2194def test_implicit_unicode_on_windows():
2195    if sys.platform != 'win32':
2196        py.test.skip("win32-only test")
2197    ffi = FFI()
2198    e = py.test.raises(FFIError, ffi.cdef, "int foo(LPTSTR);")
2199    assert str(e.value) == ("The Windows type 'LPTSTR' is only available after"
2200                            " you call ffi.set_unicode()")
2201    for with_unicode in [True, False]:
2202        ffi = FFI()
2203        ffi.set_unicode(with_unicode)
2204        ffi.cdef("""
2205            DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename,
2206                                    DWORD nSize);
2207        """)
2208        lib = ffi.verify("""
2209            #include <windows.h>
2210        """, libraries=['Kernel32'])
2211        outbuf = ffi.new("TCHAR[]", 200)
2212        n = lib.GetModuleFileName(ffi.NULL, outbuf, 500)
2213        assert 0 < n < 500
2214        for i in range(n):
2215            #print repr(outbuf[i])
2216            assert ord(outbuf[i]) != 0
2217        assert ord(outbuf[n]) == 0
2218        assert ord(outbuf[0]) < 128     # should be a letter, or '\'
2219
2220def test_use_local_dir():
2221    ffi = FFI()
2222    lib = ffi.verify("", modulename="test_use_local_dir")
2223    this_dir = os.path.dirname(__file__)
2224    pycache_files = os.listdir(os.path.join(this_dir, '__pycache__'))
2225    assert any('test_use_local_dir' in s for s in pycache_files)
2226
2227def test_define_known_value():
2228    ffi = FFI()
2229    ffi.cdef("#define FOO 0x123")
2230    lib = ffi.verify("#define FOO 0x123")
2231    assert lib.FOO == 0x123
2232
2233def test_define_wrong_value():
2234    ffi = FFI()
2235    ffi.cdef("#define FOO 123")
2236    e = py.test.raises(VerificationError, ffi.verify, "#define FOO 124")
2237    assert str(e.value).endswith("FOO has the real value 124, not 123")
2238
2239def test_static_const_int_known_value():
2240    ffi = FFI()
2241    ffi.cdef("static const int FOO = 0x123;")
2242    lib = ffi.verify("#define FOO 0x123")
2243    assert lib.FOO == 0x123
2244
2245def test_static_const_int_wrong_value():
2246    ffi = FFI()
2247    ffi.cdef("static const int FOO = 123;")
2248    e = py.test.raises(VerificationError, ffi.verify, "#define FOO 124")
2249    assert str(e.value).endswith("FOO has the real value 124, not 123")
2250
2251def test_const_struct_global():
2252    ffi = FFI()
2253    ffi.cdef("typedef struct { int x; ...; } T; const T myglob;")
2254    lib = ffi.verify("typedef struct { double y; int x; } T;"
2255                     "const T myglob = { 0.1, 42 };")
2256    assert ffi.typeof(lib.myglob) == ffi.typeof("T")
2257    assert lib.myglob.x == 42
2258
2259def test_dont_support_int_dotdotdot():
2260    ffi = FFI()
2261    ffi.cdef("typedef int... t1;")
2262    e = py.test.raises(VerificationError, ffi.verify, "")
2263    assert str(e.value) == ("feature not supported with ffi.verify(), but only "
2264                            "with ffi.set_source(): 'typedef int... t1'")
2265    ffi = FFI()
2266    ffi.cdef("typedef double ... t1;")
2267    e = py.test.raises(VerificationError, ffi.verify, "")
2268    assert str(e.value) == ("feature not supported with ffi.verify(), but only "
2269                         "with ffi.set_source(): 'typedef float... t1'")
2270
2271def test_const_fields():
2272    ffi = FFI()
2273    ffi.cdef("""struct foo_s { const int a; void *const b; };""")
2274    ffi.verify("""struct foo_s { const int a; void *const b; };""")
2275    foo_s = ffi.typeof("struct foo_s")
2276    assert foo_s.fields[0][0] == 'a'
2277    assert foo_s.fields[0][1].type is ffi.typeof("int")
2278    assert foo_s.fields[1][0] == 'b'
2279    assert foo_s.fields[1][1].type is ffi.typeof("void *")
2280
2281def test_win32_calling_convention_0():
2282    ffi = FFI()
2283    ffi.cdef("""
2284        int call1(int(__cdecl   *cb)(int));
2285        int (*const call2)(int(__stdcall *cb)(int));
2286    """)
2287    lib = ffi.verify(r"""
2288        #ifndef _MSC_VER
2289        #  define __stdcall  /* nothing */
2290        #endif
2291        int call1(int(*cb)(int)) {
2292            int i, result = 0;
2293            //printf("call1: cb = %p\n", cb);
2294            for (i = 0; i < 1000; i++)
2295                result += cb(i);
2296            //printf("result = %d\n", result);
2297            return result;
2298        }
2299        int call2(int(__stdcall *cb)(int)) {
2300            int i, result = 0;
2301            //printf("call2: cb = %p\n", cb);
2302            for (i = 0; i < 1000; i++)
2303                result += cb(-i);
2304            //printf("result = %d\n", result);
2305            return result;
2306        }
2307    """)
2308    @ffi.callback("int(int)")
2309    def cb1(x):
2310        return x * 2
2311    @ffi.callback("int __stdcall(int)")
2312    def cb2(x):
2313        return x * 3
2314    #print 'cb1 =', cb1
2315    res = lib.call1(cb1)
2316    assert res == 500*999*2
2317    #print 'cb2 =', cb2
2318    #print ffi.typeof(lib.call2)
2319    #print 'call2 =', lib.call2
2320    res = lib.call2(cb2)
2321    #print '...'
2322    assert res == -500*999*3
2323    #print 'done'
2324    if sys.platform == 'win32' and sys.maxsize < 2**32:
2325        assert '__stdcall' in str(ffi.typeof(cb2))
2326        assert '__stdcall' not in str(ffi.typeof(cb1))
2327        py.test.raises(TypeError, lib.call1, cb2)
2328        py.test.raises(TypeError, lib.call2, cb1)
2329    else:
2330        assert '__stdcall' not in str(ffi.typeof(cb2))
2331        assert ffi.typeof(cb2) is ffi.typeof(cb1)
2332
2333def test_win32_calling_convention_1():
2334    ffi = FFI()
2335    ffi.cdef("""
2336        int __cdecl   call1(int(__cdecl   *cb)(int));
2337        int __stdcall call2(int(__stdcall *cb)(int));
2338        int (__cdecl   *const cb1)(int);
2339        int (__stdcall *const cb2)(int);
2340    """)
2341    lib = ffi.verify(r"""
2342        #ifndef _MSC_VER
2343        #  define __cdecl
2344        #  define __stdcall
2345        #endif
2346        int __cdecl   cb1(int x) { return x * 2; }
2347        int __stdcall cb2(int x) { return x * 3; }
2348
2349        int __cdecl call1(int(__cdecl *cb)(int)) {
2350            int i, result = 0;
2351            //printf("here1\n");
2352            //printf("cb = %p, cb1 = %p\n", cb, (void *)cb1);
2353            for (i = 0; i < 1000; i++)
2354                result += cb(i);
2355            //printf("result = %d\n", result);
2356            return result;
2357        }
2358        int __stdcall call2(int(__stdcall *cb)(int)) {
2359            int i, result = 0;
2360            //printf("here1\n");
2361            //printf("cb = %p, cb2 = %p\n", cb, (void *)cb2);
2362            for (i = 0; i < 1000; i++)
2363                result += cb(-i);
2364            //printf("result = %d\n", result);
2365            return result;
2366        }
2367    """)
2368    assert lib.call1(lib.cb1) == 500*999*2
2369    assert lib.call2(lib.cb2) == -500*999*3
2370
2371def test_win32_calling_convention_2():
2372    # any mistake in the declaration of plain function (including the
2373    # precise argument types and, here, the calling convention) are
2374    # automatically corrected.  But this does not apply to the 'cb'
2375    # function pointer argument.
2376    ffi = FFI()
2377    ffi.cdef("""
2378        int __stdcall call1(int(__cdecl   *cb)(int));
2379        int __cdecl   call2(int(__stdcall *cb)(int));
2380        int (__cdecl   *const cb1)(int);
2381        int (__stdcall *const cb2)(int);
2382    """)
2383    lib = ffi.verify(r"""
2384        #ifndef _MSC_VER
2385        #  define __cdecl
2386        #  define __stdcall
2387        #endif
2388        int __cdecl call1(int(__cdecl *cb)(int)) {
2389            int i, result = 0;
2390            for (i = 0; i < 1000; i++)
2391                result += cb(i);
2392            return result;
2393        }
2394        int __stdcall call2(int(__stdcall *cb)(int)) {
2395            int i, result = 0;
2396            for (i = 0; i < 1000; i++)
2397                result += cb(-i);
2398            return result;
2399        }
2400        int __cdecl   cb1(int x) { return x * 2; }
2401        int __stdcall cb2(int x) { return x * 3; }
2402    """)
2403    assert lib.call1(lib.cb1) == 500*999*2
2404    assert lib.call2(lib.cb2) == -500*999*3
2405
2406def test_win32_calling_convention_3():
2407    ffi = FFI()
2408    ffi.cdef("""
2409        struct point { int x, y; };
2410
2411        int (*const cb1)(struct point);
2412        int (__stdcall *const cb2)(struct point);
2413
2414        struct point __stdcall call1(int(*cb)(struct point));
2415        struct point call2(int(__stdcall *cb)(struct point));
2416    """)
2417    lib = ffi.verify(r"""
2418        #ifndef _MSC_VER
2419        #  define __cdecl
2420        #  define __stdcall
2421        #endif
2422        struct point { int x, y; };
2423        int           cb1(struct point pt) { return pt.x + 10 * pt.y; }
2424        int __stdcall cb2(struct point pt) { return pt.x + 100 * pt.y; }
2425        struct point __stdcall call1(int(__cdecl *cb)(struct point)) {
2426            int i;
2427            struct point result = { 0, 0 };
2428            //printf("here1\n");
2429            //printf("cb = %p, cb1 = %p\n", cb, (void *)cb1);
2430            for (i = 0; i < 1000; i++) {
2431                struct point p = { i, -i };
2432                int r = cb(p);
2433                result.x += r;
2434                result.y -= r;
2435            }
2436            return result;
2437        }
2438        struct point __cdecl call2(int(__stdcall *cb)(struct point)) {
2439            int i;
2440            struct point result = { 0, 0 };
2441            for (i = 0; i < 1000; i++) {
2442                struct point p = { -i, i };
2443                int r = cb(p);
2444                result.x += r;
2445                result.y -= r;
2446            }
2447            return result;
2448        }
2449    """)
2450    if sys.platform == 'win32' and sys.maxsize < 2**32:
2451        py.test.raises(TypeError, lib.call1, lib.cb2)
2452        py.test.raises(TypeError, lib.call2, lib.cb1)
2453    pt = lib.call1(lib.cb1)
2454    assert (pt.x, pt.y) == (-9*500*999, 9*500*999)
2455    pt = lib.call2(lib.cb2)
2456    assert (pt.x, pt.y) == (99*500*999, -99*500*999)
2457
2458def _only_test_on_linux_intel():
2459    if not sys.platform.startswith('linux'):
2460        py.test.skip('only running the memory-intensive test on Linux')
2461    import platform
2462    machine = platform.machine()
2463    if 'x86' not in machine and 'x64' not in machine:
2464        py.test.skip('only running the memory-intensive test on x86/x64')
2465
2466def test_ffi_gc_size_arg():
2467    # with PyPy's GC, these calls to ffi.gc() would rapidly consume
2468    # 40 GB of RAM without the third argument
2469    _only_test_on_linux_intel()
2470    ffi = FFI()
2471    ffi.cdef("void *malloc(size_t); void free(void *);")
2472    lib = ffi.verify(r"""
2473        #include <stdlib.h>
2474    """)
2475    for i in range(2000):
2476        p = lib.malloc(20*1024*1024)    # 20 MB
2477        p1 = ffi.cast("char *", p)
2478        for j in range(0, 20*1024*1024, 4096):
2479            p1[j] = b'!'
2480        p = ffi.gc(p, lib.free, 20*1024*1024)
2481        del p
2482
2483def test_ffi_gc_size_arg_2():
2484    # a variant of the above: this "attack" works on cpython's cyclic gc too
2485    # and I found no obvious way to prevent that.  So for now, this test
2486    # is skipped on CPython, where it eats all the memory.
2487    if '__pypy__' not in sys.builtin_module_names:
2488        py.test.skip("find a way to tweak the cyclic GC of CPython")
2489    _only_test_on_linux_intel()
2490    ffi = FFI()
2491    ffi.cdef("void *malloc(size_t); void free(void *);")
2492    lib = ffi.verify(r"""
2493        #include <stdlib.h>
2494    """)
2495    class X(object):
2496        pass
2497    for i in range(2000):
2498        p = lib.malloc(50*1024*1024)    # 50 MB
2499        p1 = ffi.cast("char *", p)
2500        for j in range(0, 50*1024*1024, 4096):
2501            p1[j] = b'!'
2502        p = ffi.gc(p, lib.free, 50*1024*1024)
2503        x = X()
2504        x.p = p
2505        x.cyclic = x
2506        del p, x
2507
2508def test_ffi_new_with_cycles():
2509    # still another variant, with ffi.new()
2510    if '__pypy__' not in sys.builtin_module_names:
2511        py.test.skip("find a way to tweak the cyclic GC of CPython")
2512    ffi = FFI()
2513    ffi.cdef("")
2514    lib = ffi.verify("")
2515    class X(object):
2516        pass
2517    for i in range(2000):
2518        p = ffi.new("char[]", 50*1024*1024)    # 50 MB
2519        for j in range(0, 50*1024*1024, 4096):
2520            p[j] = b'!'
2521        x = X()
2522        x.p = p
2523        x.cyclic = x
2524        del p, x
2525