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