1""" 2Tests for the new-style metadata format interface. 3 4These tests are for global function 5""" 6from __future__ import unicode_literals 7import objc 8from PyObjCTools.TestSupport import * 9import warnings 10 11from PyObjCTest.metadatafunction import * 12 13import sys 14if sys.version_info[0] == 3: 15 unicode = str 16 17_FunctionTable = [ 18 ("makeArrayWithFormat_", b'@@', '', 19 dict( 20 variadic=True, 21 arguments={ 22 0: dict(printf_format=True), 23 } 24 )), 25 26 ("makeArrayWithCFormat_", b'@*', '', 27 dict( 28 variadic=True, 29 arguments={ 30 0: dict(printf_format=True), 31 } 32 )), 33 34 ("make4Tuple_", b'@^d', '', 35 dict( 36 arguments={ 37 0: dict(type_modifier=objc._C_IN, c_array_of_fixed_length=4, null_accepted=False), 38 } 39 )), 40 41 ("null4Tuple_", b'@^d', '', 42 dict( 43 arguments={ 44 0: dict(type_modifier=objc._C_IN, c_array_of_fixed_length=4, null_accepted=True), 45 } 46 )), 47 48 ("makeObjectArray_", b'@^@', '', 49 dict( 50 arguments={ 51 0: dict(type_modifier=objc._C_IN, c_array_delimited_by_null=True, null_accepted=False), 52 } 53 )), 54 55 ("makeStringArray_", b'@^*', '', 56 dict( 57 arguments={ 58 0: dict(type_modifier=objc._C_IN, c_array_delimited_by_null=True, null_accepted=False), 59 } 60 )), 61 62 ("nullStringArray_", b'@^*', '', 63 dict( 64 arguments={ 65 0: dict(type_modifier=objc._C_IN, c_array_delimited_by_null=True, null_accepted=True), 66 } 67 )), 68 69 ("makeIntArray_count_", b'@^iI', '', 70 dict( 71 arguments={ 72 0: dict(type_modifier=objc._C_IN, c_array_length_in_arg=1, null_accepted=False), 73 } 74 )), 75 76 ("makeIntArray_countPtr_", b'@^i^I', '', 77 dict( 78 arguments={ 79 0: dict(type_modifier=objc._C_IN, c_array_length_in_arg=1, null_accepted=False), 80 1: dict(type_modifier=objc._C_IN), 81 } 82 )), 83 84 ("nullIntArray_count_", b'@^iI', '', 85 dict( 86 arguments={ 87 0: dict(type_modifier=objc._C_IN, c_array_length_in_arg=1, null_accepted=True), 88 } 89 )), 90 91 ("fillArray_uptoCount_", b'i^ii', '', 92 dict( 93 arguments={ 94 0: dict(type_modifier=objc._C_OUT, c_array_length_in_arg=1, c_array_length_in_result=True, null_accepted=False), 95 } 96 )), 97 98 ("fillArray_count_", b'v^ii', '', 99 dict( 100 arguments={ 101 0: dict(type_modifier=objc._C_OUT, c_array_length_in_arg=1, null_accepted=False), 102 } 103 )), 104 105 ("nullfillArray_count_", b'i^ii', '', 106 dict( 107 arguments={ 108 0: dict(type_modifier=objc._C_OUT, c_array_length_in_arg=1, null_accepted=True), 109 } 110 )), 111 112 ("maybeFillArray_", b'i^i', '', 113 dict( 114 arguments={ 115 0: dict(type_modifier=objc._C_OUT, c_array_of_fixed_length=4, c_array_length_in_result=True, null_accepted=False), 116 } 117 )), 118 119 ("fill4Tuple_", b'v^i', '', 120 dict( 121 arguments={ 122 0: dict(type_modifier=objc._C_OUT, c_array_of_fixed_length=4, null_accepted=False), 123 } 124 )), 125 126 ("nullfill4Tuple_", b'i^i', '', 127 dict( 128 arguments={ 129 0: dict(type_modifier=objc._C_OUT, c_array_of_fixed_length=4, null_accepted=True), 130 } 131 )), 132 133 ("fillStringArray_", b'i^*', '', 134 dict( 135 arguments={ 136 0: dict(type_modifier=objc._C_OUT, c_array_delimited_by_null=True, null_accepted=False), 137 } 138 )), 139 140 ("nullfillStringArray_", b'i^*', '', 141 dict( 142 arguments={ 143 0: dict(type_modifier=objc._C_OUT, c_array_delimited_by_null=True, null_accepted=True), 144 } 145 )), 146 147 ("reverseArray_uptoCount_", b'i^fi', '', 148 dict( 149 arguments={ 150 0: dict(type_modifier=objc._C_INOUT, c_array_length_in_arg=1, c_array_length_in_result=True, null_accepted=False), 151 } 152 )), 153 154 ("reverseArray_count_", b'v^fi', '', 155 dict( 156 arguments={ 157 0: dict(type_modifier=objc._C_INOUT, c_array_length_in_arg=1, null_accepted=False), 158 } 159 )), 160 161 ("nullreverseArray_count_", b'i^fi', '', 162 dict( 163 arguments={ 164 0: dict(type_modifier=objc._C_INOUT, c_array_length_in_arg=1, null_accepted=True), 165 } 166 )), 167 168 ("reverseStrings_", b'v^*', '', 169 dict( 170 arguments={ 171 0: dict(type_modifier=objc._C_INOUT, c_array_delimited_by_null=True, null_accepted=False), 172 } 173 )), 174 175 ("nullreverseStrings_", b'i^*', '', 176 dict( 177 arguments={ 178 0: dict(type_modifier=objc._C_INOUT, c_array_delimited_by_null=True, null_accepted=True), 179 } 180 )), 181 182 ("maybeReverseArray_", b'i^s', '', 183 dict( 184 arguments={ 185 0: dict(type_modifier=objc._C_INOUT, c_array_of_fixed_length=4, c_array_length_in_result=True, null_accepted=False), 186 } 187 )), 188 189 ("reverse4Tuple_", b'v^s', '', 190 dict( 191 arguments={ 192 0: dict(type_modifier=objc._C_INOUT, c_array_of_fixed_length=4, null_accepted=False), 193 } 194 )), 195 196 ("nullreverse4Tuple_", b'i^s', '', 197 dict( 198 arguments={ 199 0: dict(type_modifier=objc._C_INOUT, c_array_of_fixed_length=4, null_accepted=True), 200 } 201 )), 202 203 ("makeIntArrayOf5", b'^i', '', 204 dict( 205 retval=dict(c_array_of_fixed_length=5) 206 )), 207 208 ("makeStringArray", b'^*', '', 209 dict( 210 retval=dict(c_array_delimited_by_null=True), 211 )), 212 213 ("makeIntArrayOf_", b'^ii', '', 214 dict( 215 retval=dict(c_array_length_in_arg=0) 216 )), 217 218 ("nullIntArrayOf5", b'^i', '', 219 dict( 220 retval=dict(c_array_of_fixed_length=5) 221 )), 222 223 ("nullStringArray", b'^*', '', 224 dict( 225 retval=dict(c_array_delimited_by_null=True), 226 )), 227 228 ("nullIntArrayOf_", b'^ii', '', 229 dict( 230 retval=dict(c_array_length_in_arg=0) 231 )), 232 233 234 ("sumX_andY_", b'i^i^i', '', 235 dict(arguments={ 236 0: dict(type_modifier=objc._C_IN, null_accepted=False), 237 1: dict(type_modifier=objc._C_IN, null_accepted=False), 238 })), 239 240 ("divBy5_remainder_", b'ii^i', '', 241 dict(arguments={ 242 1: dict(type_modifier=objc._C_OUT, null_accepted=False), 243 })), 244 245 ("swapX_andY_", b'v^d^d', '', 246 dict(arguments={ 247 0: dict(type_modifier=objc._C_INOUT, null_accepted=False), 248 1: dict(type_modifier=objc._C_INOUT, null_accepted=False), 249 })), 250 251 ("input_output_inputAndOutput_", b'@^i^i^i', '', 252 dict(arguments={ 253 0: dict(type_modifier=objc._C_IN, null_accepted=True), 254 1: dict(type_modifier=objc._C_OUT, null_accepted=True), 255 2: dict(type_modifier=objc._C_INOUT, null_accepted=True), 256 })), 257] 258 259objc.loadFunctionList(function_list, globals(), _FunctionTable, False) 260 261class TestExists (TestCase): 262 def testFunctionsExists(self): 263 for item in _FunctionTable: 264 self.assertIn(item[0], globals()) 265 266class TestArrayDefault (TestCase): 267 # TODO: what is the default anyway? 268 pass 269 270class TestArraysOut (TestCase): 271 def testFixedSize(self): 272 v = fill4Tuple_(None) 273 self.assertEqual(list(v), [0, -1, -8, -27]) 274 275 self.assertRaises(ValueError, fill4Tuple_, objc.NULL) 276 277 n, v = nullfill4Tuple_(None) 278 self.assertEqual(n, 1) 279 self.assertEqual(list(v), [0, -1, -8, -27]) 280 281 n, v = nullfill4Tuple_(objc.NULL) 282 self.assertEqual(n, 0) 283 self.assertIs(v, objc.NULL) 284 285 def testNullTerminated(self): 286 287 # Output only arrays of null-terminated arrays cannot be 288 # wrapped automaticly. How is the bridge supposed to know 289 # how much memory it should allocate for the C-array? 290 self.assertRaises(TypeError, fillStringArray_, None) 291 self.assertRaises(ValueError, fillStringArray_, objc.NULL) 292 293 self.assertRaises(TypeError, nullfillStringArray_) 294 self.assertRaises(TypeError, nullfillStringArray_, None) 295 n, v = nullfillStringArray_(objc.NULL) 296 self.assertEqual(n, 0) 297 self.assertIs(v, objc.NULL) 298 299 def testWithCount(self): 300 301 v = fillArray_count_(None, 3) 302 self.assertEqual(list(v), [0,1,4]) 303 304 v = fillArray_count_(None, 3) 305 self.assertEqual(list(v), [0,1,4]) 306 307 v = fillArray_count_(None, 5) 308 self.assertEqual(list(v), [0,1,4,9,16]) 309 310 v = fillArray_count_(None, 0) 311 self.assertEqual(list(v), []) 312 313 self.assertRaises(ValueError, fillArray_count_, objc.NULL, 0) 314 315 n, v = nullfillArray_count_(None, 3) 316 self.assertEqual(n, 1) 317 self.assertEqual(list(v), [0,1,4]) 318 n, v = nullfillArray_count_(None, 3) 319 self.assertEqual(n, 1) 320 self.assertEqual(list(v), [0,1,4]) 321 322 n, v = nullfillArray_count_(objc.NULL, 3) 323 self.assertEqual(n, 0) 324 self.assertIs(v, objc.NULL ) 325 326 def testWithCountInResult(self): 327 328 c, v = fillArray_uptoCount_(None, 20) 329 self.assertEqual(c, 10) 330 self.assertEqual(list(v), [i+2 for i in range(10)]) 331 332 c, v = maybeFillArray_(None) 333 self.assertEqual(c, 2) 334 self.assertEqual(list(v), [10, 11]) 335 336 337class TestArraysInOut (TestCase): 338 def testFixedSize(self): 339 340 a = (1,2,3,4) 341 v = reverse4Tuple_(a) 342 self.assertEqual(a, (1,2,3,4)) 343 self.assertEqual(v, (4,3,2,1)) 344 345 self.assertRaises(ValueError, reverse4Tuple_, (1,2,3)) 346 self.assertRaises(ValueError, reverse4Tuple_, (1,2,3,4,5)) 347 self.assertRaises(ValueError, reverse4Tuple_, objc.NULL) 348 349 a = (1,2,3,4) 350 n, v = nullreverse4Tuple_(a) 351 self.assertEqual(n, 1) 352 self.assertEqual(a, (1,2,3,4)) 353 self.assertEqual(v, (4,3,2,1)) 354 355 n, v = nullreverse4Tuple_(objc.NULL) 356 self.assertEqual(n, 0) 357 self.assertIs(v, objc.NULL) 358 359 def testNullTerminated(self): 360 361 a = (b'a', b'b', b'c') 362 v = reverseStrings_(a) 363 self.assertEqual(a, (b'a', b'b', b'c')) 364 self.assertEqual(v, (b'c', b'b', b'a')) 365 366 self.assertRaises(ValueError, reverseStrings_, (1,2)) 367 self.assertRaises(ValueError, reverseStrings_, objc.NULL) 368 369 a = (b'a', b'b', b'c') 370 n, v = nullreverseStrings_(a) 371 self.assertEqual(n, 1) 372 self.assertEqual(a, (b'a', b'b', b'c')) 373 self.assertEqual(v, (b'c', b'b', b'a')) 374 375 n, v = nullreverseStrings_(objc.NULL) 376 self.assertEqual(n, 0) 377 self.assertIs(v, objc.NULL) 378 379 def testWithCount(self): 380 381 a = (1.0, 2.0, 3.0, 4.0, 5.0) 382 v = reverseArray_count_(a, 4) 383 self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) 384 self.assertEqual(v, (4.0, 3.0, 2.0, 1.0)) 385 386 a = (1.0, 2.0, 3.0, 4.0, 5.0) 387 v = reverseArray_count_(a, 5) 388 self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) 389 self.assertEqual(v, (5.0, 4.0, 3.0, 2.0, 1.0)) 390 391 # Nice to have, but doesn't work without major 392 # surgery: 393 #a = (1.0, 2.0, 3.0, 4.0, 5.0) 394 #v = reverseArray_count_(a, None) 395 #self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) 396 #self.assertEqual(v, (5.0, 4.0, 3.0, 2.0, 1.0)) 397 398 self.assertRaises(ValueError, reverseArray_count_, (1.0, 2.0), 5) 399 self.assertRaises(ValueError, reverseArray_count_, objc.NULL, 0) 400 401 a = (1.0, 2.0, 3.0, 4.0, 5.0) 402 n, v = nullreverseArray_count_(a, 5) 403 self.assertEqual(n, 1) 404 self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) 405 self.assertEqual(v, (5.0, 4.0, 3.0, 2.0, 1.0)) 406 407 n, v = nullreverseArray_count_(objc.NULL, 0) 408 self.assertEqual(n, 0) 409 self.assertIs(v, objc.NULL) 410 411 def testWithCountInResult(self): 412 413 c, v = reverseArray_uptoCount_(range(10), 10) 414 self.assertEqual(c, 5) 415 self.assertEqual(len(v), 5) 416 self.assertEqual(list(v), [9, 8, 7, 6, 5]) 417 418 c, v = maybeReverseArray_([1,2,3,4]) 419 self.assertEqual(c, 2) 420 self.assertEqual(len(v), 2) 421 self.assertEqual(list(v), [4, 3]) 422 423class TestArraysIn (TestCase): 424 def testFixedSize(self): 425 426 v = make4Tuple_((1.0, 4.0, 8.0, 12.5)) 427 self.assertEqual(len(v), 4) 428 self.assertEqual(list(v), [1.0, 4.0, 8.0, 12.5]) 429 430 v = make4Tuple_((1, 2, 3, 4)) 431 self.assertEqual(len(v), 4) 432 self.assertEqual(list(v), [1.0, 2.0, 3.0, 4.0]) 433 434 self.assertRaises(ValueError, make4Tuple_, (1, 2, 3)) 435 self.assertRaises(ValueError, make4Tuple_, (1, 2, 3, 4, 5)) 436 self.assertRaises(ValueError, make4Tuple_, objc.NULL) 437 438 v = null4Tuple_(objc.NULL) 439 self.assertIs(v, None) 440 441 def testNullTerminated(self): 442 443 v = makeStringArray_((b"hello", b"world", b"there")) 444 self.assertEqual(len(v), 3) 445 self.assertEqual(list(v), ["hello", "world", "there"]) 446 self.assertIsInstance(v, objc.lookUpClass("NSArray")) 447 self.assertIsInstance(v[0], unicode) 448 449 NSObject = objc.lookUpClass('NSObject') 450 p, q, r = NSObject.new(), NSObject.new(), NSObject.new() 451 v = makeObjectArray_((p, q, r)) 452 self.assertEqual(len(v), 3) 453 self.assertIs(v[0], p) 454 self.assertIs(v[1], q) 455 self.assertIs(v[2], r) 456 457 v = makeStringArray_(()) 458 self.assertEqual(len(v), 0) 459 460 self.assertRaises(ValueError, makeStringArray_, [1,2]) 461 self.assertRaises(ValueError, makeStringArray_, objc.NULL) 462 463 v = nullStringArray_(objc.NULL) 464 self.assertEqual(v, None) 465 466 def testWithCount(self): 467 468 v = makeIntArray_count_((1,2,3,4), 3) 469 self.assertEqual(len(v), 3) 470 self.assertEqual(list(v), [1,2,3]) 471 472 # XXX: This one would be nice to have, but not entirely trivial 473 #v = makeIntArray_count_((1,2,3,4), None) 474 #self.assertEqual(len(v), 3) 475 #self.assertEqual(list(v), [1,2,3,4]) 476 477 self.assertRaises(ValueError, makeIntArray_count_, [1,2,3], 4) 478 self.assertRaises(ValueError, makeIntArray_count_, objc.NULL, 0) 479 self.assertRaises(ValueError, makeIntArray_count_, objc.NULL, 1) 480 481 v = nullIntArray_count_(objc.NULL, 0) 482 self.assertEqual(v, None) 483 484 self.assertRaises(ValueError, makeIntArray_count_, objc.NULL, 1) 485 486 # Make sure this also works when the length is in a pass-by-reference argument 487 v = makeIntArray_countPtr_((1,2,3,4), 4) 488 self.assertEqual(len(v), 4) 489 self.assertEqual(list(v), [1,2,3,4]) 490 491class TestArrayReturns (TestCase): 492 # TODO: 493 # - Add null-terminated arrays of various supported types: 494 # -> integers 495 # -> CF-types 496 def testFixedSize(self): 497 498 v = makeIntArrayOf5() 499 self.assertEqual( len(v), 5 ) 500 self.assertEqual( v[0], 0 ) 501 self.assertEqual( v[1], 1 ) 502 self.assertEqual( v[2], 4 ) 503 self.assertEqual( v[3], 9 ) 504 self.assertEqual( v[4], 16 ) 505 506 v = nullIntArrayOf5() 507 self.assertEqual(v, objc.NULL) 508 509 def testSizeInArgument(self): 510 v = makeIntArrayOf_(3) 511 self.assertEqual(len(v), 3) 512 self.assertEqual(v[0], 0) 513 self.assertEqual(v[1], 1) 514 self.assertEqual(v[2], 8) 515 516 v = makeIntArrayOf_(10) 517 self.assertEqual(len(v), 10) 518 for i in range(10): 519 self.assertEqual(v[i], i**3) 520 521 v = nullIntArrayOf_(100) 522 self.assertEqual(v, objc.NULL) 523 524 def testNULLterminated(self): 525 526 v = makeStringArray() 527 self.assertEqual(len(v), 4) 528 self.assertEqual(list(v), [b"hello", b"world", b"out", b"there"]) 529 530 v = nullStringArray() 531 self.assertEqual(v, objc.NULL) 532 533class TestByReference (TestCase): 534 # Pass by reference arguments. 535 # Note that these tests aren't exhaustive, we have test_methods and 536 # test_methods2 for that :-) 537 538 def testInput(self): 539 540 r = sumX_andY_(1, 2) 541 self.assertEqual(r, 1+2) 542 543 r = sumX_andY_(2535, 5325) 544 self.assertEqual(r, 2535 + 5325) 545 546 self.assertRaises(ValueError, sumX_andY_, 42, objc.NULL) 547 548 def testOutput(self): 549 550 div, rem = divBy5_remainder_(55, None) 551 self.assertEqual(div, 11) 552 self.assertEqual(rem, 0) 553 554 div, rem = divBy5_remainder_(13, None) 555 self.assertEqual(div, 2) 556 self.assertEqual(rem, 3) 557 558 self.assertRaises(ValueError, divBy5_remainder_, 42, objc.NULL) 559 560 def testInputOutput(self): 561 x, y = swapX_andY_(42, 284) 562 self.assertEqual(x, 284) 563 self.assertEqual(y, 42) 564 565 self.assertRaises(ValueError, swapX_andY_, 42, objc.NULL) 566 567 def testNullAccepted(self): 568 # Note: the commented-out test-cases require a change in the pyobjc-core 569 570 def makeNum(value): 571 return int(value, 0) 572 573 r, y, z = input_output_inputAndOutput_(1, None, 2) 574 self.assertEqual(len(r), 3) 575 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 3) 576 self.assertEqual(y, 3) 577 self.assertEqual(z, -1) 578 579 # Argument 1 is NULL 580 r, y, z = input_output_inputAndOutput_(objc.NULL, None, 2) 581 self.assertEqual(len(r), 3) 582 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 2) 583 self.assertEqual(y, 40) 584 self.assertEqual(z, -2) 585 586 r, y, z = input_output_inputAndOutput_(objc.NULL, None, 2) 587 self.assertEqual(len(r), 3) 588 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 2) 589 self.assertEqual(y, 40) 590 self.assertEqual(z, -2) 591 592 # Argument 2 is NULL 593 r, y, z = input_output_inputAndOutput_(1, objc.NULL, 2) 594 self.assertEqual(len(r), 3) 595 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 2) 596 self.assertEqual(y, objc.NULL) 597 self.assertEqual(z, -1) 598 599 # Argument 3 is NULL 600 r, y, z = input_output_inputAndOutput_(1, None, objc.NULL) 601 self.assertEqual(len(r), 3) 602 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 2) 603 self.assertEqual(y, 43) 604 self.assertEqual(z, objc.NULL) 605 606 r, y, z = input_output_inputAndOutput_(1, None, objc.NULL) 607 self.assertEqual(len(r), 3) 608 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 2) 609 self.assertEqual(y, 43) 610 self.assertEqual(z, objc.NULL) 611 612class TestPrintfFormat (TestCase): 613 def test_nsformat(self): 614 615 v = makeArrayWithFormat_("%3d", 10) 616 self.assertEqual(list(v), [ "%3d", " 10"]) 617 618 v = makeArrayWithFormat_("hello %s", b"world") 619 self.assertEqual(list(v), [ "hello %s", "hello world"]) 620 621 v = makeArrayWithFormat_("\xf1") 622 self.assertEqual(list(v), [ "\xf1", "\xf1"]) 623 624 625 def test_cformat(self): 626 627 v = makeArrayWithCFormat_(b"%3d", 10) 628 self.assertEqual(list(v), [ "%3d", " 10"]) 629 630 v = makeArrayWithCFormat_(b"hello %s", b"world") 631 self.assertEqual(list(v), [ "hello %s", "hello world"]) 632 633if __name__ == "__main__": 634 main() 635