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