1""" 2Tests for the new-style metadata format interface. 3 4Note: Tests for calling from python into ObjC are in test_metadata.py 5 6TODO: 7- Add more testcases: python methods that return the wrong value 8- The python->C interface (that is the contents of the metadata object) is 9 likely to change when the bridge is feature-complete. 10- Probably need special-casing for arrays (numarray and array.array)! 11""" 12import objc 13from PyObjCTools.TestSupport import * 14import warnings 15 16from PyObjCTest.metadata import * 17 18# To ensure we have the right metadata 19import PyObjCTest.test_metadata 20 21def setupMetaData(): 22 # Note to self: what we think of as the first argument of a method is 23 # actually the third one, the objc runtime implicitly passed 'self' and 24 # the selector as well. Therefore we need to start counting at 2 instead 25 # of 0. 26 # 27 # Note2: the code below would normally be done using a metadata file 28 # instead of hardcoding. 29 30 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"make4Tuple:on:", 31 dict( 32 arguments={ 33 2+0: dict(type_modifier=objc._C_IN, c_array_of_fixed_length=4, null_accepted=False), 34 } 35 ) 36 ) 37 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"null4Tuple:on:", 38 dict( 39 arguments={ 40 2+0: dict(type_modifier=objc._C_IN, c_array_of_fixed_length=4, null_accepted=True), 41 } 42 ) 43 ) 44 45 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"makeObjectArray:on:", 46 dict( 47 arguments={ 48 2+0: dict(type_modifier=objc._C_IN, c_array_delimited_by_null=True, null_accepted=False), 49 } 50 ) 51 ) 52 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"makeStringArray:on:", 53 dict( 54 arguments={ 55 2+0: dict(type_modifier=objc._C_IN, c_array_delimited_by_null=True, null_accepted=False), 56 } 57 ) 58 ) 59 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"nullStringArray:on:", 60 dict( 61 arguments={ 62 2+0: dict(type_modifier=objc._C_IN, c_array_delimited_by_null=True, null_accepted=True), 63 } 64 ) 65 ) 66 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"makeIntArray:count:on:", 67 dict( 68 arguments={ 69 2+0: dict(type_modifier=objc._C_IN, c_array_length_in_arg=2+1, null_accepted=False), 70 } 71 ) 72 ) 73 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"makeIntArray:countPtr:on:", 74 dict( 75 arguments={ 76 2+0: dict(type_modifier=objc._C_IN, c_array_length_in_arg=2+1, null_accepted=False), 77 2+1: dict(type_modifier=objc._C_IN, null_accepted=False), 78 } 79 ) 80 ) 81 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"nullIntArray:count:on:", 82 dict( 83 arguments={ 84 2+0: dict(type_modifier=objc._C_IN, c_array_length_in_arg=2+1, null_accepted=True), 85 } 86 ) 87 ) 88 89 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"fillArray:uptoCount:on:", 90 dict( 91 arguments={ 92 2+0: dict(type_modifier=objc._C_OUT, c_array_length_in_arg=2+1, c_array_length_in_result=True, null_accepted=False), 93 } 94 ) 95 ) 96 97 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"fillArray:count:on:", 98 dict( 99 arguments={ 100 2+0: dict(type_modifier=objc._C_OUT, c_array_length_in_arg=2+1, null_accepted=False), 101 } 102 ) 103 ) 104 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"nullfillArray:count:on:", 105 dict( 106 arguments={ 107 2+0: dict(type_modifier=objc._C_OUT, c_array_length_in_arg=2+1, null_accepted=True), 108 } 109 ) 110 ) 111 112 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"maybeFillArray:on:", 113 dict( 114 arguments={ 115 2+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 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"fill4Tuple:on:", 120 dict( 121 arguments={ 122 2+0: dict(type_modifier=objc._C_OUT, c_array_of_fixed_length=4, null_accepted=False), 123 } 124 ) 125 ) 126 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"nullfill4Tuple:on:", 127 dict( 128 arguments={ 129 2+0: dict(type_modifier=objc._C_OUT, c_array_of_fixed_length=4, null_accepted=True), 130 } 131 ) 132 ) 133 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"fillStringArray:on:", 134 dict( 135 arguments={ 136 2+0: dict(type_modifier=objc._C_OUT, c_array_delimited_by_null=True, null_accepted=False), 137 } 138 ) 139 ) 140 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"nullfillStringArray:on:", 141 dict( 142 arguments={ 143 2+0: dict(type_modifier=objc._C_OUT, c_array_delimited_by_null=True, null_accepted=True), 144 } 145 ) 146 ) 147 148 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"reverseArray:uptoCount:on:", 149 dict( 150 arguments={ 151 2+0: dict(type_modifier=objc._C_INOUT, c_array_length_in_arg=2+1, c_array_length_in_result=True, null_accepted=False), 152 } 153 ) 154 ) 155 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"reverseArray:count:on:", 156 dict( 157 arguments={ 158 2+0: dict(type_modifier=objc._C_INOUT, c_array_length_in_arg=2+1, null_accepted=False), 159 } 160 ) 161 ) 162 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"nullreverseArray:count:on:", 163 dict( 164 arguments={ 165 2+0: dict(type_modifier=objc._C_INOUT, c_array_length_in_arg=2+1, null_accepted=True), 166 } 167 ) 168 ) 169 170 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"reverseStrings:on:", 171 dict( 172 arguments={ 173 2+0: dict(type_modifier=objc._C_INOUT, c_array_delimited_by_null=True, null_accepted=False), 174 } 175 ) 176 ) 177 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"nullreverseStrings:on:", 178 dict( 179 arguments={ 180 2+0: dict(type_modifier=objc._C_INOUT, c_array_delimited_by_null=True, null_accepted=True), 181 } 182 ) 183 ) 184 185 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"maybeReverseArray:on:", 186 dict( 187 arguments={ 188 2+0: dict(type_modifier=objc._C_INOUT, c_array_of_fixed_length=4, c_array_length_in_result=True, null_accepted=True), 189 } 190 ) 191 ) 192 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"reverse4Tuple:on:", 193 dict( 194 arguments={ 195 2+0: dict(type_modifier=objc._C_INOUT, c_array_of_fixed_length=4, null_accepted=False), 196 } 197 ) 198 ) 199 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"nullreverse4Tuple:on:", 200 dict( 201 arguments={ 202 2+0: dict(type_modifier=objc._C_INOUT, c_array_of_fixed_length=4, null_accepted=True), 203 } 204 ) 205 ) 206 207 208 209 210 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"makeIntArrayOf5On:", 211 dict( 212 retval=dict(c_array_of_fixed_length=5) 213 ), 214 ) 215 216 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"makeStringArrayOn:", 217 dict( 218 retval=dict(c_array_delimited_by_null=True), 219 ), 220 ) 221 222 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"makeIntArrayOf:on:", 223 dict( 224 retval=dict(c_array_length_in_arg=2+0) 225 ), 226 ) 227 228 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"nullIntArrayOf5On:", 229 dict( 230 retval=dict(c_array_of_fixed_length=5) 231 ), 232 ) 233 234 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"nullStringArrayOn:", 235 dict( 236 retval=dict(c_array_delimited_by_null=True), 237 ), 238 ) 239 240 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"nullIntArrayOf:on:", 241 dict( 242 retval=dict(c_array_length_in_arg=2+0) 243 ), 244 ) 245 246 247 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"sumX:andY:on:", 248 dict(arguments={ 249 2+0: dict(type_modifier=objc._C_IN, null_accepted=False), 250 2+1: dict(type_modifier=objc._C_IN, null_accepted=False), 251 })) 252 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"divBy5:remainder:on:", 253 dict(arguments={ 254 2+1: dict(type_modifier=objc._C_OUT, null_accepted=False), 255 })) 256 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"swapX:andY:on:", 257 dict(arguments={ 258 2+0: dict(type_modifier=objc._C_INOUT, null_accepted=False), 259 2+1: dict(type_modifier=objc._C_INOUT, null_accepted=False), 260 })) 261 objc.registerMetaDataForSelector(b"OC_MetaDataTest", b"input:output:inputAndOutput:on:", 262 dict(arguments={ 263 2+0: dict(type_modifier=objc._C_IN, null_accepted=True), 264 2+1: dict(type_modifier=objc._C_OUT, null_accepted=True), 265 2+2: dict(type_modifier=objc._C_INOUT, null_accepted=True), 266 })) 267 268 269setupMetaData() 270 271class Py_MetaDataTest_AllArgs (OC_MetaDataTest): 272 # Return value arrays: 273 def makeIntArrayOf5(self): 274 return [100, 200, 300, 400, 500] 275 276 def makeStringArray(self): 277 return [ b"jaap", b"pieter", b"hans" ] 278 279 def makeIntArrayOf_(self, count): 280 return [ i + 20 for i in range(count) ] 281 282 def nullIntArrayOf5(self): 283 return objc.NULL 284 285 def nullStringArray(self): 286 return objc.NULL 287 288 def nullIntArrayOf_(self, count): 289 return objc.NULL 290 291 # In arrays: 292 def makeIntArray_count_(self, data, count): return [data, count] 293 def makeIntArray_countPtr_(self, data, count): return [data, count] 294 def nullIntArray_count_(self, data, count): return [data, count] 295 def makeStringArray_(self, data): return [[ x.decode('latin1') for x in data]] 296 def makeObjectArray_(self, data): return [data] 297 def nullStringArray_(self, data): return [data] 298 def make4Tuple_(self, data): return [data] 299 def null4Tuple_(self, data): return [data] 300 301 # Out arrays: 302 def fillArray_count_(self, data, count): 303 if data is None: 304 return range(10, count+10) 305 else: 306 return range(20, count+20) 307 308 def nullfillArray_count_(self, data, count): 309 if data is objc.NULL: 310 return 1, None 311 312 elif data is None: 313 return 2, range(30, count+30) 314 315 else: 316 return 3, range(40, count+40) 317 318 def fill4Tuple_(self, data): 319 if data is None: 320 return range(9, 13) 321 else: 322 return range(14, 18) 323 324 def nullfill4Tuple_(self, data): 325 if data is None: 326 return 1, range(1, 5) 327 elif data is objc.NULL: 328 return 2, range(6, 10) 329 else: 330 return 3, range(100, 104) 331 332 def fillArray_uptoCount_(self, data, count): 333 if data is None: 334 return int(count/2), range(10, 10 + int(count/2)) 335 else: 336 return int(count/2), range(15, 15 + int(count/2)) 337 338 def maybeFillArray_(self, data): 339 if data is None: 340 return 2, range(2) 341 else: 342 return 2, range(2, 4) 343 344 def fillStringArray_(self, data): 345 raise RuntimeError("Should not reach this") 346 347 def nullfillStringArray_(self, data): 348 if data is objc.NULL: 349 return 9, objc.NULL 350 351 raise RuntimeError("Should not reach this") 352 353 # In/out arrays: 354 def reverseArray_count_(self, data, count): 355 if count == len(data): 356 x = 1 357 else: 358 x = 2 359 360 data = list(data) 361 for i in range(len(data)): 362 data[i] += x 363 364 return data 365 366 def nullreverseArray_count_(self, data, count): 367 if data is objc.NULL: 368 return 2, objc.NULL 369 370 else: 371 data = list(data) 372 for i in range(len(data)): 373 data[i] += 42 374 return 9, data 375 376 def reverseStrings_(self, data): 377 data = list(data) 378 for i in range(len(data)): 379 data[i] = data[i][::-1] 380 return data 381 382 def nullreverseStrings_(self, data): 383 if data is objc.NULL: 384 return 9, objc.NULL 385 386 else: 387 data = list(data) 388 for i in range(len(data)): 389 data[i] = data[i][::-1] 390 return 10, data 391 392 def reverse4Tuple_(self, data): 393 data = list(data) 394 for i in range(len(data)): 395 data[i] += 42 396 return data 397 398 def nullreverse4Tuple_(self, data): 399 if data is objc.NULL: 400 return -1, objc.NULL 401 402 else: 403 data = list(data) 404 for i in range(len(data)): 405 data[i] += 42 406 return 1, data 407 408 def reverseArray_uptoCount_(self, data, count): 409 data = list(data) 410 for i in range(int(len(data)/2)): 411 data[i] = data[i] * 10 412 413 return count/2, data 414 415 def maybeReverseArray_(self, data): 416 return 2, (data[0] + 44, data[1] + 49) 417 418 # pass-by-reference 419 def sumX_andY_(self, x, y): 420 return x ** 2 + y ** 2 421 422 def divBy5_remainder_(self, v, r): 423 if r is None: 424 return v / 7, v % 7 425 else: 426 return v / 9, v % 9 427 428 def swapX_andY_(self, x, y): 429 return y * 2, x * 2 430 431 def input_output_inputAndOutput_(self, x, y, z): 432 if x is not objc.NULL and y is not objc.NULL and z is not objc.NULL: 433 return [x, y, z], 9, 10 434 435 elif x is objc.NULL: 436 return [x, y, z], 11, 12 437 438 elif y is objc.NULL: 439 return [x, y, z], 13, 14 440 441 elif z is objc.NULL: 442 return [x, y, z], 15, 16 443 444class TestArrayDefault (TestCase): 445 # TODO: what is the default anyway? 446 pass 447 448class TestArraysOut (TestCase): 449 def testFixedSize(self): 450 o = Py_MetaDataTest_AllArgs.new() 451 452 v = OC_MetaDataTest.fill4Tuple_on_(None, o) 453 self.assertEqual(list(v), list(range(9, 13))) 454 455 v = OC_MetaDataTest.fill4Tuple_on_(None, o) 456 self.assertEqual(list(v), list(range(9, 13))) 457 458 self.assertRaises(ValueError, OC_MetaDataTest.fill4Tuple_on_, objc.NULL, o) 459 460 n, v = OC_MetaDataTest.nullfill4Tuple_on_(None, o) 461 self.assertEqual(n, 1) 462 self.assertEqual(list(v), list(range(1, 5))) 463 464 n, v = OC_MetaDataTest.nullfill4Tuple_on_(None, o) 465 self.assertEqual(n, 1) 466 self.assertEqual(list(v), list(range(1, 5))) 467 468 n, v = OC_MetaDataTest.nullfill4Tuple_on_(objc.NULL, o) 469 self.assertEqual(n, 2) 470 self.assertIs(v, objc.NULL) 471 472 def testNullTerminated(self): 473 o = Py_MetaDataTest_AllArgs.new() 474 475 # Output only arrays of null-terminated arrays cannot be 476 # wrapped automaticly. How is the bridge supposed to know 477 # how much memory it should allocate for the C-array? 478 self.assertRaises(TypeError, OC_MetaDataTest.fillStringArray_on_, None, o) 479 self.assertRaises(ValueError, OC_MetaDataTest.fillStringArray_on_, objc.NULL, o) 480 481 self.assertRaises(TypeError, OC_MetaDataTest.nullfillStringArray_on_, o) 482 self.assertRaises(TypeError, OC_MetaDataTest.nullfillStringArray_on_, None, o) 483 n, v = OC_MetaDataTest.nullfillStringArray_on_(objc.NULL, o) 484 self.assertEqual(n, 9) 485 self.assertIs(v, objc.NULL) 486 487 def testWithCount(self): 488 o = Py_MetaDataTest_AllArgs.new() 489 490 v = OC_MetaDataTest.fillArray_count_on_(None, 3, o) 491 self.assertEqual(list(v), [10, 11, 12]) 492 493 v = OC_MetaDataTest.fillArray_count_on_(None, 5, o) 494 self.assertEqual(list(v), [10, 11, 12, 13, 14]) 495 496 v = OC_MetaDataTest.fillArray_count_on_(None, 0, o) 497 self.assertEqual(list(v), []) 498 499 self.assertRaises(ValueError, OC_MetaDataTest.fillArray_count_on_, objc.NULL, 0, o) 500 501 n, v = OC_MetaDataTest.nullfillArray_count_on_(None, 3, o) 502 self.assertEqual(n, 2) 503 self.assertEqual(list(v), [30,31,32]) 504 505 506 n, v = OC_MetaDataTest.nullfillArray_count_on_(objc.NULL, 3, o) 507 self.assertEqual(n, 1) 508 self.assertIs(v, objc.NULL) 509 510 def testWithCountInResult(self): 511 o = Py_MetaDataTest_AllArgs.new() 512 513 c, v = OC_MetaDataTest.fillArray_uptoCount_on_(None, 20, o) 514 self.assertEqual(c, 10) 515 self.assertEqual(list(v), [i+10 for i in range(10)]) 516 517 c, v = OC_MetaDataTest.maybeFillArray_on_(None, o) 518 self.assertEqual(c, 2) 519 self.assertEqual(list(v), [0, 1]) 520 521class TestArraysInOut (TestCase): 522 def testFixedSize(self): 523 o = Py_MetaDataTest_AllArgs.new() 524 525 a = (1,2,3,4) 526 v = OC_MetaDataTest.reverse4Tuple_on_(a, o) 527 self.assertEqual(a, (1,2,3,4)) 528 self.assertEqual(v, (43, 44, 45, 46)) 529 530 self.assertRaises(ValueError, OC_MetaDataTest.reverse4Tuple_on_, (1,2,3), o) 531 self.assertRaises(ValueError, OC_MetaDataTest.reverse4Tuple_on_, (1,2,3,4,5), o) 532 self.assertRaises(ValueError, OC_MetaDataTest.reverse4Tuple_on_, objc.NULL, o) 533 534 a = (1,2,3,4) 535 n, v = OC_MetaDataTest.nullreverse4Tuple_on_(a, o) 536 self.assertEqual(n, 1) 537 self.assertEqual(a, (1,2,3,4)) 538 self.assertEqual(v, (43, 44, 45, 46)) 539 540 n, v = OC_MetaDataTest.nullreverse4Tuple_on_(objc.NULL, o) 541 self.assertEqual(n, -1) 542 self.assertIs(v, objc.NULL) 543 544 def testNullTerminated(self): 545 o = Py_MetaDataTest_AllArgs.new() 546 547 a = (b'aap', b'boot', b'cello') 548 v = OC_MetaDataTest.reverseStrings_on_(a, o) 549 self.assertEqual(a, (b'aap', b'boot', b'cello')) 550 self.assertEqual(v, (b'paa', b'toob', b'ollec')) 551 552 self.assertRaises(ValueError, OC_MetaDataTest.reverseStrings_on_, (1,2), o) 553 self.assertRaises(ValueError, OC_MetaDataTest.reverseStrings_on_, objc.NULL, o) 554 555 a = (b'aap', b'boot', b'cello') 556 n, v = OC_MetaDataTest.nullreverseStrings_on_(a, o) 557 self.assertEqual(n, 10) 558 self.assertEqual(a, (b'aap', b'boot', b'cello')) 559 self.assertEqual(v, (b'paa', b'toob', b'ollec')) 560 561 n, v = OC_MetaDataTest.nullreverseStrings_on_(objc.NULL, o) 562 self.assertEqual(n, 9) 563 self.assertIs(v, objc.NULL) 564 565 def testWithCount(self): 566 o = Py_MetaDataTest_AllArgs.new() 567 568 a = (1.0, 2.0, 3.0, 4.0, 5.0) 569 v = OC_MetaDataTest.reverseArray_count_on_(a, 4, o) 570 self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) 571 self.assertEqual(v, (2.0, 3.0, 4.0, 5.0)) 572 573 a = (1.0, 2.0, 3.0, 4.0, 5.0) 574 v = OC_MetaDataTest.reverseArray_count_on_(a, 5, o) 575 self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) 576 self.assertEqual(v, (2.0, 3.0, 4.0, 5.0, 6.0)) 577 578 # Nice to have, but doesn't work without major 579 # surgery: 580 #a = (1.0, 2.0, 3.0, 4.0, 5.0) 581 #v = OC_MetaDataTest.reverseArray_count_on_(a, None, o) 582 #self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) 583 #self.assertEqual(v, (2.0, 3.0, 4.0, 5.0, 6.0)) 584 585 self.assertRaises(ValueError, OC_MetaDataTest.reverseArray_count_on_, (1.0, 2.0), 5, o) 586 self.assertRaises(ValueError, OC_MetaDataTest.reverseArray_count_on_, objc.NULL, 0, o) 587 588 a = (1.0, 2.0, 3.0, 4.0, 5.0) 589 n, v = OC_MetaDataTest.nullreverseArray_count_on_(a, 5, o) 590 self.assertEqual(n, 9) 591 self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) 592 self.assertEqual(v, (43.0, 44.0, 45.0, 46.0, 47.0)) 593 594 n, v = OC_MetaDataTest.nullreverseArray_count_on_(objc.NULL, 0, o) 595 self.assertEqual(n, 2) 596 self.assertIs(v, objc.NULL) 597 598 def testWithCountInResult(self): 599 o = Py_MetaDataTest_AllArgs.new() 600 601 c, v = OC_MetaDataTest.reverseArray_uptoCount_on_(range(10), 10, o) 602 self.assertEqual(c, 5) 603 self.assertEqual(len(v), 5) 604 self.assertEqual(list(v), [0, 10, 20, 30, 40]) 605 606 c, v = OC_MetaDataTest.maybeReverseArray_on_([1,2,3,4], o) 607 self.assertEqual(c, 2) 608 self.assertEqual(len(v), 2) 609 self.assertEqual(list(v), [45, 51]) 610 611class TestArraysIn (TestCase): 612 def testFixedSize(self): 613 o = Py_MetaDataTest_AllArgs.new() 614 615 v, = OC_MetaDataTest.make4Tuple_on_((1.0, 4.0, 8.0, 12.5), o) 616 self.assertEqual(len(v), 4) 617 self.assertEqual(list(v), [1.0, 4.0, 8.0, 12.5]) 618 619 v, = OC_MetaDataTest.make4Tuple_on_((1, 2, 3, 4), o) 620 self.assertEqual(len(v), 4) 621 self.assertEqual(list(v), [1.0, 2.0, 3.0, 4.0]) 622 623 self.assertRaises(ValueError, OC_MetaDataTest.make4Tuple_on_, (1, 2, 3), o) 624 self.assertRaises(ValueError, OC_MetaDataTest.make4Tuple_on_, (1, 2, 3, 4, 5), o) 625 self.assertRaises(ValueError, OC_MetaDataTest.make4Tuple_on_, objc.NULL, o) 626 627 v, = OC_MetaDataTest.null4Tuple_on_(objc.NULL, o) 628 self.assertIs(v, objc.NULL) 629 630 def testNullTerminated(self): 631 o = Py_MetaDataTest_AllArgs.new() 632 633 v, = OC_MetaDataTest.makeStringArray_on_((b"hello", b"world", b"there"), o) 634 self.assertEqual(len(v), 3) 635 self.assertEqual(list(v), ["hello", "world", "there"]) 636 637 NSObject = objc.lookUpClass('NSObject') 638 p, q = NSObject.new(), NSObject.new() 639 v, = o.makeObjectArray_((p, q)) 640 self.assertEqual(len(v), 2) 641 self.assertIs(v[0], p) 642 self.assertIs(v[1], q) 643 644 v, = OC_MetaDataTest.makeStringArray_on_((), o) 645 self.assertEqual(len(v), 0) 646 647 self.assertRaises(ValueError, OC_MetaDataTest.makeStringArray_on_, [1,2], o) 648 self.assertRaises(ValueError, OC_MetaDataTest.makeStringArray_on_, objc.NULL, o) 649 650 v, = OC_MetaDataTest.nullStringArray_on_(objc.NULL, o) 651 self.assertEqual(v, objc.NULL) 652 653 def testWithCount(self): 654 o = Py_MetaDataTest_AllArgs.new() 655 656 v, c = OC_MetaDataTest.makeIntArray_count_on_((1,2,3,4), 3, o) 657 self.assertEqual(c, 3) 658 self.assertEqual(len(v), 3) 659 self.assertEqual(list(v), [1,2,3]) 660 661 # XXX: This one would be nice to have, but not entirely trivial 662 #v, c = OC_MetaDataTest.makeIntArray_count_on_((1,2,3,4), None, o) 663 #self.assertEqual(c, 3) 664 #self.assertEqual(len(v), 3) 665 #self.assertEqual(list(v), [1,2,3,4]) 666 667 self.assertRaises(ValueError, OC_MetaDataTest.makeIntArray_count_on_, [1,2,3], 4, o) 668 self.assertRaises(ValueError, OC_MetaDataTest.makeIntArray_count_on_, objc.NULL, 0, o) 669 self.assertRaises(ValueError, OC_MetaDataTest.makeIntArray_count_on_, objc.NULL, 1, o) 670 671 v, c = OC_MetaDataTest.nullIntArray_count_on_(objc.NULL, 0, o) 672 self.assertEqual(c, 0) 673 self.assertEqual(v, objc.NULL) 674 675 self.assertRaises(ValueError, OC_MetaDataTest.makeIntArray_count_on_, objc.NULL, 1, o) 676 677 # Make sure this also works when the length is in a pass-by-reference argument 678 v, c = OC_MetaDataTest.makeIntArray_countPtr_on_((1,2,3,4), 4, o) 679 self.assertEqual(c, 4) 680 self.assertEqual(len(v), 4) 681 self.assertEqual(list(v), [1,2,3,4]) 682 683class TestArrayReturns (TestCase): 684 # TODO: 685 # - Add null-terminated arrays of various supported types: 686 # -> integers 687 # -> CF-types 688 def testFixedSize(self): 689 o = Py_MetaDataTest_AllArgs.new() 690 691 v = OC_MetaDataTest.makeIntArrayOf5On_(o) 692 self.assertEqual( len(v), 5 ) 693 self.assertEqual( list(v), [100, 200, 300, 400, 500] ) 694 695 v = OC_MetaDataTest.nullIntArrayOf5On_(o) 696 self.assertEqual(v, objc.NULL) 697 698 def testSizeInArgument(self): 699 o = Py_MetaDataTest_AllArgs.new() 700 v = OC_MetaDataTest.makeIntArrayOf_on_(3, o) 701 self.assertEqual(len(v), 3) 702 self.assertEqual(list(v), [20, 21, 22]) 703 704 v = OC_MetaDataTest.makeIntArrayOf_on_(10, o) 705 self.assertEqual(len(v), 10) 706 self.assertEqual(list(v), list(range(20, 30))) 707 708 v = OC_MetaDataTest.nullIntArrayOf_on_(100, o) 709 self.assertEqual(v, objc.NULL) 710 711 def testNULLterminated(self): 712 o = Py_MetaDataTest_AllArgs.new() 713 714 v = OC_MetaDataTest.makeStringArrayOn_(o) 715 self.assertEqual(len(v), 3) 716 self.assertEqual(list(v), [ b"jaap", b"pieter", b"hans" ]) 717 718 v = OC_MetaDataTest.nullStringArrayOn_(o) 719 self.assertEqual(v, objc.NULL) 720 721class TestByReference (TestCase): 722 # Pass by reference arguments. 723 # Note that these tests aren't exhaustive, we have test_methods and 724 # test_methods2 for that :-) 725 726 def testInput(self): 727 o = Py_MetaDataTest_AllArgs.new() 728 729 r = OC_MetaDataTest.sumX_andY_on_(1, 2, o) 730 self.assertEqual(r, 1**2+2**2) 731 732 r = OC_MetaDataTest.sumX_andY_on_(2535, 5325, o) 733 self.assertEqual(r, 2535**2 + 5325**2) 734 735 self.assertRaises(ValueError, OC_MetaDataTest.sumX_andY_on_, 42, objc.NULL, o) 736 737 def testOutput(self): 738 o = Py_MetaDataTest_AllArgs.new() 739 740 div, rem = OC_MetaDataTest.divBy5_remainder_on_(55, None, o) 741 self.assertEqual(div, int(55 / 7)) 742 self.assertEqual(rem, int(55 % 7)) 743 744 div, rem = OC_MetaDataTest.divBy5_remainder_on_(13, None, o) 745 self.assertEqual(div, int(13 / 7)) 746 self.assertEqual(rem, int(13 % 7)) 747 748 self.assertRaises(ValueError, OC_MetaDataTest.divBy5_remainder_on_, 42, objc.NULL, o) 749 750 def testInputOutput(self): 751 o = Py_MetaDataTest_AllArgs.new() 752 x, y = OC_MetaDataTest.swapX_andY_on_(42, 284, o) 753 self.assertEqual(x, 284*2) 754 self.assertEqual(y, 42*2) 755 756 self.assertRaises(ValueError, OC_MetaDataTest.swapX_andY_on_, 42, objc.NULL, o) 757 758 def testNullAccepted(self): 759 # Note: the commented-out test-cases require a change in the pyobjc-core 760 o = Py_MetaDataTest_AllArgs.new(); 761 762 def makeNum(value): 763 return int(value, 0) 764 765 # All arguments present 766 r, y, z = OC_MetaDataTest.input_output_inputAndOutput_on_(1, None, 2, o) 767 self.assertEqual(len(r), 3) 768 self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 3) 769 self.assertEqual(y, 9) 770 self.assertEqual(z, 10) 771 772 r, y, z = OC_MetaDataTest.input_output_inputAndOutput_on_(1, None, 2, o) 773 self.assertEqual(len(r), 3) 774 self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 3) 775 self.assertEqual(y, 9) 776 self.assertEqual(z, 10) 777 778 # Argument 1 is NULL 779 r, y, z = OC_MetaDataTest.input_output_inputAndOutput_on_(objc.NULL, None, 2, o) 780 self.assertEqual(len(r), 3) 781 self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 2) 782 self.assertEqual(y, 11) 783 self.assertEqual(z, 12) 784 785 r, y, z = OC_MetaDataTest.input_output_inputAndOutput_on_(objc.NULL, None, 2, o) 786 self.assertEqual(len(r), 3) 787 self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 2) 788 self.assertEqual(y, 11) 789 self.assertEqual(z, 12) 790 791 # Argument 2 is NULL 792 r, y, z = OC_MetaDataTest.input_output_inputAndOutput_on_(1, objc.NULL, 2, o) 793 self.assertEqual(len(r), 3) 794 self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 2) 795 self.assertEqual(y, objc.NULL) 796 self.assertEqual(z, 14) 797 798 # Argument 3 is NULL 799 r, y, z = OC_MetaDataTest.input_output_inputAndOutput_on_(1, None, objc.NULL, o) 800 self.assertEqual(len(r), 3) 801 self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 2) 802 self.assertEqual(y, 15) 803 self.assertEqual(z, objc.NULL) 804 805 r, y, z = OC_MetaDataTest.input_output_inputAndOutput_on_(1, None, objc.NULL, o) 806 self.assertEqual(len(r), 3) 807 self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 2) 808 self.assertEqual(y, 15) 809 self.assertEqual(z, objc.NULL) 810 811if __name__ == "__main__": 812 main() 813