1import py, sys, platform
2import pytest
3from testing.cffi0 import backend_tests, test_function, test_ownlib
4from testing.support import u
5from cffi import FFI
6import _cffi_backend
7
8
9class TestFFI(backend_tests.BackendTests,
10              test_function.TestFunction,
11              test_ownlib.TestOwnLib):
12    TypeRepr = "<ctype '%s'>"
13
14    @staticmethod
15    def Backend():
16        return _cffi_backend
17
18    def test_not_supported_bitfield_in_result(self):
19        ffi = FFI(backend=self.Backend())
20        ffi.cdef("struct foo_s { int a,b,c,d,e; int x:1; };")
21        e = py.test.raises(NotImplementedError, ffi.callback,
22                           "struct foo_s foo(void)", lambda: 42)
23        assert str(e.value) == ("struct foo_s(*)(): "
24            "callback with unsupported argument or return type or with '...'")
25
26    def test_inspecttype(self):
27        ffi = FFI(backend=self.Backend())
28        assert ffi.typeof("long").kind == "primitive"
29        assert ffi.typeof("long(*)(long, long**, ...)").cname == (
30            "long(*)(long, long * *, ...)")
31        assert ffi.typeof("long(*)(long, long**, ...)").ellipsis is True
32
33    def test_new_handle(self):
34        ffi = FFI(backend=self.Backend())
35        o = [2, 3, 4]
36        p = ffi.new_handle(o)
37        assert ffi.typeof(p) == ffi.typeof("void *")
38        assert ffi.from_handle(p) is o
39        assert ffi.from_handle(ffi.cast("char *", p)) is o
40        py.test.raises(RuntimeError, ffi.from_handle, ffi.NULL)
41
42    def test_callback_onerror(self):
43        ffi = FFI(backend=self.Backend())
44        seen = []
45        def oops(*args):
46            seen.append(args)
47        def otherfunc():
48            raise LookupError
49        def cb(n):
50            otherfunc()
51        a = ffi.callback("int(*)(int)", cb, error=42, onerror=oops)
52        res = a(234)
53        assert res == 42
54        assert len(seen) == 1
55        exc, val, tb = seen[0]
56        assert exc is LookupError
57        assert isinstance(val, LookupError)
58        assert tb.tb_frame.f_code.co_name == 'cb'
59        assert tb.tb_frame.f_locals['n'] == 234
60
61    def test_ffi_new_allocator_2(self):
62        ffi = FFI(backend=self.Backend())
63        seen = []
64        def myalloc(size):
65            seen.append(size)
66            return ffi.new("char[]", b"X" * size)
67        def myfree(raw):
68            seen.append(raw)
69        alloc1 = ffi.new_allocator(myalloc, myfree)
70        alloc2 = ffi.new_allocator(alloc=myalloc, free=myfree,
71                                   should_clear_after_alloc=False)
72        p1 = alloc1("int[10]")
73        p2 = alloc2("int[]", 10)
74        assert seen == [40, 40]
75        assert ffi.typeof(p1) == ffi.typeof("int[10]")
76        assert ffi.sizeof(p1) == 40
77        assert ffi.typeof(p2) == ffi.typeof("int[]")
78        assert ffi.sizeof(p2) == 40
79        assert p1[5] == 0
80        assert p2[6] == ord('X') * 0x01010101
81        raw1 = ffi.cast("char *", p1)
82        raw2 = ffi.cast("char *", p2)
83        del p1, p2
84        retries = 0
85        while len(seen) != 4:
86            retries += 1
87            assert retries <= 5
88            import gc; gc.collect()
89        assert seen == [40, 40, raw1, raw2]
90        assert repr(seen[2]) == "<cdata 'char[]' owning 41 bytes>"
91        assert repr(seen[3]) == "<cdata 'char[]' owning 41 bytes>"
92
93    def test_ffi_new_allocator_3(self):
94        ffi = FFI(backend=self.Backend())
95        seen = []
96        def myalloc(size):
97            seen.append(size)
98            return ffi.new("char[]", b"X" * size)
99        alloc1 = ffi.new_allocator(myalloc)    # no 'free'
100        p1 = alloc1("int[10]")
101        assert seen == [40]
102        assert ffi.typeof(p1) == ffi.typeof("int[10]")
103        assert ffi.sizeof(p1) == 40
104        assert p1[5] == 0
105
106    def test_ffi_new_allocator_4(self):
107        ffi = FFI(backend=self.Backend())
108        py.test.raises(TypeError, ffi.new_allocator, free=lambda x: None)
109        #
110        def myalloc2(size):
111            raise LookupError
112        alloc2 = ffi.new_allocator(myalloc2)
113        py.test.raises(LookupError, alloc2, "int[5]")
114        #
115        def myalloc3(size):
116            return 42
117        alloc3 = ffi.new_allocator(myalloc3)
118        e = py.test.raises(TypeError, alloc3, "int[5]")
119        assert str(e.value) == "alloc() must return a cdata object (got int)"
120        #
121        def myalloc4(size):
122            return ffi.cast("int", 42)
123        alloc4 = ffi.new_allocator(myalloc4)
124        e = py.test.raises(TypeError, alloc4, "int[5]")
125        assert str(e.value) == "alloc() must return a cdata pointer, not 'int'"
126        #
127        def myalloc5(size):
128            return ffi.NULL
129        alloc5 = ffi.new_allocator(myalloc5)
130        py.test.raises(MemoryError, alloc5, "int[5]")
131
132    def test_new_struct_containing_struct_containing_array_varsize(self):
133        ffi = FFI(backend=self.Backend())
134        ffi.cdef("""
135            struct foo_s { int len[100]; short data[]; };
136            struct bar_s { int abc[100]; struct foo_s tail; };
137        """)
138        # loop to try to detect heap overwrites, if the size allocated
139        # is too small
140        for i in range(1, 501, 100):
141            p = ffi.new("struct bar_s *", [[10], [[20], [3,4,5,6,7,8,9] * i]])
142            assert p.abc[0] == 10
143            assert p.tail.len[0] == 20
144            assert p.tail.data[0] == 3
145            assert p.tail.data[6] == 9
146            assert p.tail.data[7 * i - 1] == 9
147
148    def test_bogus_struct_containing_struct_containing_array_varsize(self):
149        ffi = FFI(backend=self.Backend())
150        ffi.cdef("""
151            struct foo_s { signed char len; signed char data[]; };
152            struct bar_s { struct foo_s foo; int bcd; };
153        """)
154        p = ffi.new("struct bar_s *", [[123, [45, 56, 67, 78]], 9999999])
155        assert p.foo.len == 123
156        assert p.foo.data[0] == 45
157        assert p.foo.data[1] == 56
158        assert p.foo.data[2] == 67
159        assert p.bcd == 9999999
160        assert p.foo.data[3] != 78   # has been overwritten with 9999999
161
162
163class TestBitfield:
164    def check(self, source, expected_ofs_y, expected_align, expected_size):
165        # NOTE: 'expected_*' is the numbers expected from GCC.
166        # The numbers expected from MSVC are not explicitly written
167        # in this file, and will just be taken from the compiler.
168        ffi = FFI()
169        ffi.cdef("struct s1 { %s };" % source)
170        ctype = ffi.typeof("struct s1")
171        # verify the information with gcc
172        ffi1 = FFI()
173        ffi1.cdef("""
174            static const int Gofs_y, Galign, Gsize;
175            struct s1 *try_with_value(int fieldnum, long long value);
176        """)
177        fnames = [name for name, cfield in ctype.fields
178                       if name and cfield.bitsize > 0]
179        setters = ['case %d: s.%s = value; break;' % iname
180                   for iname in enumerate(fnames)]
181        lib = ffi1.verify("""
182            #include <string.h>
183            struct s1 { %s };
184            struct sa { char a; struct s1 b; };
185            #define Gofs_y  offsetof(struct s1, y)
186            #define Galign  offsetof(struct sa, b)
187            #define Gsize   sizeof(struct s1)
188            struct s1 *try_with_value(int fieldnum, long long value)
189            {
190                static struct s1 s;
191                memset(&s, 0, sizeof(s));
192                switch (fieldnum) { %s }
193                return &s;
194            }
195        """ % (source, ' '.join(setters)))
196        if sys.platform == 'win32':
197            expected_ofs_y = lib.Gofs_y
198            expected_align = lib.Galign
199            expected_size  = lib.Gsize
200        else:
201            assert (lib.Gofs_y, lib.Galign, lib.Gsize) == (
202                expected_ofs_y, expected_align, expected_size)
203        # the real test follows
204        assert ffi.offsetof("struct s1", "y") == expected_ofs_y
205        assert ffi.alignof("struct s1") == expected_align
206        assert ffi.sizeof("struct s1") == expected_size
207        # compare the actual storage of the two
208        for name, cfield in ctype.fields:
209            if cfield.bitsize < 0 or not name:
210                continue
211            if int(ffi.cast(cfield.type, -1)) == -1:   # signed
212                min_value = -(1 << (cfield.bitsize-1))
213                max_value = (1 << (cfield.bitsize-1)) - 1
214            else:
215                min_value = 0
216                max_value = (1 << cfield.bitsize) - 1
217            for t in [1, 2, 4, 8, 16, 128, 2813, 89728, 981729,
218                     -1,-2,-4,-8,-16,-128,-2813,-89728,-981729]:
219                if min_value <= t <= max_value:
220                    self._fieldcheck(ffi, lib, fnames, name, t)
221
222    def _fieldcheck(self, ffi, lib, fnames, name, value):
223        s = ffi.new("struct s1 *")
224        setattr(s, name, value)
225        assert getattr(s, name) == value
226        raw1 = ffi.buffer(s)[:]
227        buff1 = ffi.buffer(s)
228        t = lib.try_with_value(fnames.index(name), value)
229        raw2 = ffi.buffer(t, len(raw1))[:]
230        assert raw1 == raw2
231        buff2 = ffi.buffer(t, len(buff1))
232        assert buff1 == buff2
233
234    def test_bitfield_basic(self):
235        self.check("int a; int b:9; int c:20; int y;", 8, 4, 12)
236        self.check("int a; short b:9; short c:7; int y;", 8, 4, 12)
237        self.check("int a; short b:9; short c:9; int y;", 8, 4, 12)
238
239    def test_bitfield_reuse_if_enough_space(self):
240        self.check("int a:2; char y;", 1, 4, 4)
241        self.check("int a:1; char b  ; int c:1; char y;", 3, 4, 4)
242        self.check("int a:1; char b:8; int c:1; char y;", 3, 4, 4)
243        self.check("char a; int b:9; char y;", 3, 4, 4)
244        self.check("char a; short b:9; char y;", 4, 2, 6)
245        self.check("int a:2; char b:6; char y;", 1, 4, 4)
246        self.check("int a:2; char b:7; char y;", 2, 4, 4)
247        self.check("int a:2; short b:15; char c:2; char y;", 5, 4, 8)
248        self.check("int a:2; char b:1; char c:1; char y;", 1, 4, 4)
249
250    @pytest.mark.skipif(
251        "not (sys.platform == 'darwin' and platform.machine() == 'arm64')"
252        " and "
253        "platform.machine().startswith(('arm', 'aarch64'))")
254    def test_bitfield_anonymous_no_align(self):
255        L = FFI().alignof("long long")
256        self.check("char y; int :1;", 0, 1, 2)
257        self.check("char x; int z:1; char y;", 2, 4, 4)
258        self.check("char x; int  :1; char y;", 2, 1, 3)
259        self.check("char x; long long z:48; char y;", 7, L, 8)
260        self.check("char x; long long  :48; char y;", 7, 1, 8)
261        self.check("char x; long long z:56; char y;", 8, L, 8 + L)
262        self.check("char x; long long  :56; char y;", 8, 1, 9)
263        self.check("char x; long long z:57; char y;", L + 8, L, L + 8 + L)
264        self.check("char x; long long  :57; char y;", L + 8, 1, L + 9)
265
266    @pytest.mark.skipif(
267        "(sys.platform == 'darwin' and platform.machine() == 'arm64')"
268        " or "
269        "not platform.machine().startswith(('arm', 'aarch64'))")
270    def test_bitfield_anonymous_align_arm(self):
271        L = FFI().alignof("long long")
272        self.check("char y; int :1;", 0, 4, 4)
273        self.check("char x; int z:1; char y;", 2, 4, 4)
274        self.check("char x; int  :1; char y;", 2, 4, 4)
275        self.check("char x; long long z:48; char y;", 7, L, 8)
276        self.check("char x; long long  :48; char y;", 7, 8, 8)
277        self.check("char x; long long z:56; char y;", 8, L, 8 + L)
278        self.check("char x; long long  :56; char y;", 8, L, 8 + L)
279        self.check("char x; long long z:57; char y;", L + 8, L, L + 8 + L)
280        self.check("char x; long long  :57; char y;", L + 8, L, L + 8 + L)
281
282    @pytest.mark.skipif(
283        "not (sys.platform == 'darwin' and platform.machine() == 'arm64')"
284        " and "
285        "platform.machine().startswith(('arm', 'aarch64'))")
286    def test_bitfield_zero(self):
287        L = FFI().alignof("long long")
288        self.check("char y; int :0;", 0, 1, 4)
289        self.check("char x; int :0; char y;", 4, 1, 5)
290        self.check("char x; int :0; int :0; char y;", 4, 1, 5)
291        self.check("char x; long long :0; char y;", L, 1, L + 1)
292        self.check("short x, y; int :0; int :0;", 2, 2, 4)
293        self.check("char x; int :0; short b:1; char y;", 5, 2, 6)
294        self.check("int a:1; int :0; int b:1; char y;", 5, 4, 8)
295
296    @pytest.mark.skipif(
297        "(sys.platform == 'darwin' and platform.machine() == 'arm64')"
298        " or "
299        "not platform.machine().startswith(('arm', 'aarch64'))")
300    def test_bitfield_zero_arm(self):
301        L = FFI().alignof("long long")
302        self.check("char y; int :0;", 0, 4, 4)
303        self.check("char x; int :0; char y;", 4, 4, 8)
304        self.check("char x; int :0; int :0; char y;", 4, 4, 8)
305        self.check("char x; long long :0; char y;", L, 8, L + 8)
306        self.check("short x, y; int :0; int :0;", 2, 4, 4)
307        self.check("char x; int :0; short b:1; char y;", 5, 4, 8)
308        self.check("int a:1; int :0; int b:1; char y;", 5, 4, 8)
309
310    def test_error_cases(self):
311        ffi = FFI()
312        ffi.cdef("struct s1 { float x:1; };")
313        with pytest.raises(TypeError):
314            ffi.new("struct s1 *")
315        ffi.cdef("struct s2 { char x:0; };")
316        with pytest.raises(TypeError):
317            ffi.new("struct s2 *")
318        ffi.cdef("struct s3 { char x:9; };")
319        with pytest.raises(TypeError):
320            ffi.new("struct s3 *")
321
322    def test_struct_with_typedef(self):
323        ffi = FFI()
324        ffi.cdef("typedef struct { float x; } foo_t;")
325        p = ffi.new("foo_t *", [5.2])
326        assert repr(p).startswith("<cdata 'foo_t *' ")
327
328    def test_struct_array_no_length(self):
329        ffi = FFI()
330        ffi.cdef("struct foo_s { int x; int a[]; };")
331        p = ffi.new("struct foo_s *", [100, [200, 300, 400]])
332        assert p.x == 100
333        assert ffi.typeof(p.a) is ffi.typeof("int[]")
334        assert len(p.a) == 3                            # length recorded
335        assert p.a[0] == 200
336        assert p.a[1] == 300
337        assert p.a[2] == 400
338        assert list(p.a) == [200, 300, 400]
339        q = ffi.cast("struct foo_s *", p)
340        assert q.x == 100
341        assert ffi.typeof(q.a) is ffi.typeof("int *")   # no length recorded
342        py.test.raises(TypeError, len, q.a)
343        assert q.a[0] == 200
344        assert q.a[1] == 300
345        assert q.a[2] == 400
346        py.test.raises(TypeError, list, q.a)
347
348    @pytest.mark.skipif("sys.platform != 'win32'")
349    def test_getwinerror(self):
350        ffi = FFI()
351        code, message = ffi.getwinerror(1155)
352        assert code == 1155
353        assert message == ("No application is associated with the "
354                           "specified file for this operation")
355        ffi.cdef("void SetLastError(int);")
356        lib = ffi.dlopen("Kernel32.dll")
357        lib.SetLastError(2)
358        code, message = ffi.getwinerror()
359        assert code == 2
360        assert message == "The system cannot find the file specified"
361        code, message = ffi.getwinerror(-1)
362        assert code == 2
363        assert message == "The system cannot find the file specified"
364
365    def test_from_buffer(self):
366        import array
367        ffi = FFI()
368        a = array.array('H', [10000, 20000, 30000])
369        c = ffi.from_buffer(a)
370        assert ffi.typeof(c) is ffi.typeof("char[]")
371        assert len(c) == 6
372        ffi.cast("unsigned short *", c)[1] += 500
373        assert list(a) == [10000, 20500, 30000]
374        assert c == ffi.from_buffer("char[]", a, True)
375        assert c == ffi.from_buffer(a, require_writable=True)
376        #
377        c = ffi.from_buffer("unsigned short[]", a)
378        assert len(c) == 3
379        assert c[1] == 20500
380        #
381        p = ffi.from_buffer(b"abcd")
382        assert p[2] == b"c"
383        #
384        assert p == ffi.from_buffer(b"abcd", require_writable=False)
385        py.test.raises((TypeError, BufferError), ffi.from_buffer,
386                                                 "char[]", b"abcd", True)
387        py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd",
388                                                 require_writable=True)
389
390    def test_release(self):
391        ffi = FFI()
392        p = ffi.new("int[]", 123)
393        ffi.release(p)
394        # here, reading p[0] might give garbage or segfault...
395        ffi.release(p)   # no effect
396
397    def test_memmove(self):
398        ffi = FFI()
399        p = ffi.new("short[]", [-1234, -2345, -3456, -4567, -5678])
400        ffi.memmove(p, p + 1, 4)
401        assert list(p) == [-2345, -3456, -3456, -4567, -5678]
402        p[2] = 999
403        ffi.memmove(p + 2, p, 6)
404        assert list(p) == [-2345, -3456, -2345, -3456, 999]
405        ffi.memmove(p + 4, ffi.new("char[]", b"\x71\x72"), 2)
406        if sys.byteorder == 'little':
407            assert list(p) == [-2345, -3456, -2345, -3456, 0x7271]
408        else:
409            assert list(p) == [-2345, -3456, -2345, -3456, 0x7172]
410
411    def test_memmove_buffer(self):
412        import array
413        ffi = FFI()
414        a = array.array('H', [10000, 20000, 30000])
415        p = ffi.new("short[]", 5)
416        ffi.memmove(p, a, 6)
417        assert list(p) == [10000, 20000, 30000, 0, 0]
418        ffi.memmove(p + 1, a, 6)
419        assert list(p) == [10000, 10000, 20000, 30000, 0]
420        b = array.array('h', [-1000, -2000, -3000])
421        ffi.memmove(b, a, 4)
422        assert b.tolist() == [10000, 20000, -3000]
423        assert a.tolist() == [10000, 20000, 30000]
424        p[0] = 999
425        p[1] = 998
426        p[2] = 997
427        p[3] = 996
428        p[4] = 995
429        ffi.memmove(b, p, 2)
430        assert b.tolist() == [999, 20000, -3000]
431        ffi.memmove(b, p + 2, 4)
432        assert b.tolist() == [997, 996, -3000]
433        p[2] = -p[2]
434        p[3] = -p[3]
435        ffi.memmove(b, p + 2, 6)
436        assert b.tolist() == [-997, -996, 995]
437
438    def test_memmove_readonly_readwrite(self):
439        ffi = FFI()
440        p = ffi.new("signed char[]", 5)
441        ffi.memmove(p, b"abcde", 3)
442        assert list(p) == [ord("a"), ord("b"), ord("c"), 0, 0]
443        ffi.memmove(p, bytearray(b"ABCDE"), 2)
444        assert list(p) == [ord("A"), ord("B"), ord("c"), 0, 0]
445        py.test.raises((TypeError, BufferError), ffi.memmove, b"abcde", p, 3)
446        ba = bytearray(b"xxxxx")
447        ffi.memmove(dest=ba, src=p, n=3)
448        assert ba == bytearray(b"ABcxx")
449
450    def test_all_primitives(self):
451        ffi = FFI()
452        for name in [
453            "char",
454            "short",
455            "int",
456            "long",
457            "long long",
458            "signed char",
459            "unsigned char",
460            "unsigned short",
461            "unsigned int",
462            "unsigned long",
463            "unsigned long long",
464            "float",
465            "double",
466            "long double",
467            "wchar_t",
468            "char16_t",
469            "char32_t",
470            "_Bool",
471            "int8_t",
472            "uint8_t",
473            "int16_t",
474            "uint16_t",
475            "int32_t",
476            "uint32_t",
477            "int64_t",
478            "uint64_t",
479            "int_least8_t",
480            "uint_least8_t",
481            "int_least16_t",
482            "uint_least16_t",
483            "int_least32_t",
484            "uint_least32_t",
485            "int_least64_t",
486            "uint_least64_t",
487            "int_fast8_t",
488            "uint_fast8_t",
489            "int_fast16_t",
490            "uint_fast16_t",
491            "int_fast32_t",
492            "uint_fast32_t",
493            "int_fast64_t",
494            "uint_fast64_t",
495            "intptr_t",
496            "uintptr_t",
497            "intmax_t",
498            "uintmax_t",
499            "ptrdiff_t",
500            "size_t",
501            "ssize_t",
502            ]:
503            x = ffi.sizeof(name)
504            assert 1 <= x <= 16
505
506    def test_ffi_def_extern(self):
507        ffi = FFI()
508        py.test.raises(ValueError, ffi.def_extern)
509
510    def test_introspect_typedef(self):
511        ffi = FFI()
512        ffi.cdef("typedef int foo_t;")
513        assert ffi.list_types() == (['foo_t'], [], [])
514        assert ffi.typeof('foo_t').kind == 'primitive'
515        assert ffi.typeof('foo_t').cname == 'int'
516        #
517        ffi.cdef("typedef signed char a_t, c_t, g_t, b_t;")
518        assert ffi.list_types() == (['a_t', 'b_t', 'c_t', 'foo_t', 'g_t'],
519                                    [], [])
520
521    def test_introspect_struct(self):
522        ffi = FFI()
523        ffi.cdef("struct foo_s { int a; };")
524        assert ffi.list_types() == ([], ['foo_s'], [])
525        assert ffi.typeof('struct foo_s').kind == 'struct'
526        assert ffi.typeof('struct foo_s').cname == 'struct foo_s'
527
528    def test_introspect_union(self):
529        ffi = FFI()
530        ffi.cdef("union foo_s { int a; };")
531        assert ffi.list_types() == ([], [], ['foo_s'])
532        assert ffi.typeof('union foo_s').kind == 'union'
533        assert ffi.typeof('union foo_s').cname == 'union foo_s'
534
535    def test_introspect_struct_and_typedef(self):
536        ffi = FFI()
537        ffi.cdef("typedef struct { int a; } foo_t;")
538        assert ffi.list_types() == (['foo_t'], [], [])
539        assert ffi.typeof('foo_t').kind == 'struct'
540        assert ffi.typeof('foo_t').cname == 'foo_t'
541
542    def test_introspect_included_type(self):
543        ffi1 = FFI()
544        ffi2 = FFI()
545        ffi1.cdef("typedef signed char schar_t; struct sint_t { int x; };")
546        ffi2.include(ffi1)
547        assert ffi1.list_types() == ffi2.list_types() == (
548            ['schar_t'], ['sint_t'], [])
549
550    def test_introspect_order(self):
551        ffi = FFI()
552        ffi.cdef("union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb;")
553        ffi.cdef("union CFFIg   { int a; }; typedef struct CFFIcc  { int a; } CFFIbbb;")
554        ffi.cdef("union CFFIaa  { int a; }; typedef struct CFFIa   { int a; } CFFIbb;")
555        assert ffi.list_types() == (['CFFIb', 'CFFIbb', 'CFFIbbb'],
556                                    ['CFFIa', 'CFFIcc', 'CFFIccc'],
557                                    ['CFFIaa', 'CFFIaaa', 'CFFIg'])
558
559    def test_unpack(self):
560        ffi = FFI()
561        p = ffi.new("char[]", b"abc\x00def")
562        assert ffi.unpack(p+1, 7) == b"bc\x00def\x00"
563        p = ffi.new("int[]", [-123456789])
564        assert ffi.unpack(p, 1) == [-123456789]
565
566    def test_negative_array_size(self):
567        ffi = FFI()
568        py.test.raises(ValueError, ffi.cast, "int[-5]", 0)
569
570    def test_cannot_instantiate_manually(self):
571        ffi = FFI()
572        ct = type(ffi.typeof("void *"))
573        py.test.raises(TypeError, ct)
574        py.test.raises(TypeError, ct, ffi.NULL)
575        for cd in [type(ffi.cast("void *", 0)),
576                   type(ffi.new("char[]", 3)),
577                   type(ffi.gc(ffi.NULL, lambda x: None))]:
578            py.test.raises(TypeError, cd)
579            py.test.raises(TypeError, cd, ffi.NULL)
580            py.test.raises(TypeError, cd, ffi.typeof("void *"))
581
582    def test_explicitly_defined_char16_t(self):
583        ffi = FFI()
584        ffi.cdef("typedef uint16_t char16_t;")
585        x = ffi.cast("char16_t", 1234)
586        assert ffi.typeof(x) is ffi.typeof("uint16_t")
587
588    def test_char16_t(self):
589        ffi = FFI()
590        x = ffi.new("char16_t[]", 5)
591        assert len(x) == 5 and ffi.sizeof(x) == 10
592        x[2] = u+'\u1324'
593        assert x[2] == u+'\u1324'
594        y = ffi.new("char16_t[]", u+'\u1234\u5678')
595        assert len(y) == 3
596        assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
597        assert ffi.string(y) == u+'\u1234\u5678'
598        z = ffi.new("char16_t[]", u+'\U00012345')
599        assert len(z) == 3
600        assert list(z) == [u+'\ud808', u+'\udf45', u+'\x00']
601        assert ffi.string(z) == u+'\U00012345'
602
603    def test_char32_t(self):
604        ffi = FFI()
605        x = ffi.new("char32_t[]", 5)
606        assert len(x) == 5 and ffi.sizeof(x) == 20
607        x[3] = u+'\U00013245'
608        assert x[3] == u+'\U00013245'
609        y = ffi.new("char32_t[]", u+'\u1234\u5678')
610        assert len(y) == 3
611        assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
612        py_uni = u+'\U00012345'
613        z = ffi.new("char32_t[]", py_uni)
614        assert len(z) == 2
615        assert list(z) == [py_uni, u+'\x00']    # maybe a 2-unichars string
616        assert ffi.string(z) == py_uni
617        if len(py_uni) == 1:    # 4-bytes unicodes in Python
618            s = ffi.new("char32_t[]", u+'\ud808\udf00')
619            assert len(s) == 3
620            assert list(s) == [u+'\ud808', u+'\udf00', u+'\x00']
621