1/* 2 * This file contains some unittests for specific functions in the extension 3 * module. 4 * 5 * The PyObjC unittest objc.test.test_ctests executes the tests in this file. 6 */ 7#include "Python.h" 8#include "pyobjc-api.h" 9#include "pyobjc-compat.h" 10 11#if PY_VERSION_HEX >= 0x03000000 12#define PyInt_AsLong PyLong_AsLong 13#endif 14#include "pyobjc-unittest.h" 15 16 17#include <fcntl.h> 18 19#import <Foundation/Foundation.h> 20 21struct Struct1 { 22 int f1; 23 double f2; 24}; 25 26struct Struct2 { 27 int f1; 28 double f2; 29 short s[5]; 30}; 31 32struct Struct3 { 33 char ch; 34 int i; 35}; 36 37struct Struct4 { 38 char ch; 39 long long i; 40}; 41 42struct Struct5 { 43 long i; 44 char ch; 45}; 46 47typedef struct Struct5 Struct5Array[2]; 48 49 50 51/* Helper stuff for TestNSInvoke */ 52 53static struct Struct2 invokeHelper = { 0, 0, { 0, 0, 0, 0, 0 } }; 54 55@interface PyObjCTest_NSInvoke : NSObject 56{ 57} 58-(void)methodWithMyStruct: (struct Struct2)val1 andShort:(short)val2; 59@end 60 61@implementation PyObjCTest_NSInvoke 62-(void)methodWithMyStruct: (struct Struct2)val1 andShort:(short)val2 63{ 64 (void)val2; 65 invokeHelper = val1; 66} 67@end 68 69BEGIN_UNITTEST(CheckNSInvoke) 70 /* This is not a 'real' unittest, but is used to disable a number of 71 * other tests (in objc.test.test_methods2) when NSInvocation isn't 72 * working correctly (MacOS X at least upto 10.2.6). 73 * [Panther previews also have this problem] 74 * 75 * Leopard is even worse, this test causes a crash of the interpreter when 76 * running on PPC64. 77 */ 78#ifdef __ppc64__ 79 ASSERT_EQUALS(0, 1, "%d"); 80#endif 81 82 PyObjCTest_NSInvoke* obj = [[PyObjCTest_NSInvoke alloc] init]; 83 NSInvocation* inv; 84 struct Struct2 v1 = { 1, 2, { 3, 4, 5, 6, 7 } }; 85 short v2 = 8; 86 87 [obj methodWithMyStruct: v1 andShort: v2]; 88 inv = [NSInvocation invocationWithMethodSignature: 89 [obj methodSignatureForSelector:@selector(methodWithMyStruct:andShort:)]]; 90 [inv setTarget: obj]; 91 [inv setSelector: @selector(methodWithMyStruct:andShort:)]; 92 [inv setArgument: &v1 atIndex: 2]; 93 [inv setArgument: &v2 atIndex: 3]; 94 95 [inv invoke]; 96 [obj release]; 97 ASSERT_EQUALS(invokeHelper.f1, v1.f1, "%d"); 98 ASSERT_EQUALS(invokeHelper.f2, v1.f2, "%g"); 99 ASSERT_EQUALS(invokeHelper.s[0], v1.s[0], "%d"); 100 ASSERT_EQUALS(invokeHelper.s[1], v1.s[1], "%d"); 101 ASSERT_EQUALS(invokeHelper.s[2], v1.s[2], "%d"); 102 ASSERT_EQUALS(invokeHelper.s[3], v1.s[3], "%d"); 103 ASSERT_EQUALS(invokeHelper.s[4], v1.s[4], "%d"); 104 105END_UNITTEST 106 107 108BEGIN_UNITTEST(StructSize) 109 110 ASSERT_EQUALS( 111 sizeof(struct Struct1), PyObjCRT_SizeOfType(@encode(struct Struct1)), 112 "%d"); 113 114 ASSERT_EQUALS( 115 sizeof(struct Struct2), PyObjCRT_SizeOfType(@encode(struct Struct2)), 116 "%d"); 117 118 ASSERT_EQUALS( 119 sizeof(struct Struct3), PyObjCRT_SizeOfType(@encode(struct Struct3)), 120 "%d"); 121 122 ASSERT_EQUALS( 123 sizeof(struct Struct4), PyObjCRT_SizeOfType(@encode(struct Struct4)), 124 "%d"); 125 126 ASSERT_EQUALS( 127 sizeof(NSRect), PyObjCRT_SizeOfType(@encode(NSRect)), "%d"); 128 129END_UNITTEST 130 131BEGIN_UNITTEST(StructAlign) 132 133 ASSERT_EQUALS( 134 __alignof__(struct Struct1), 135 PyObjCRT_AlignOfType(@encode(struct Struct1)), 136 "%d"); 137 138 ASSERT_EQUALS( 139 __alignof__(struct Struct2), 140 PyObjCRT_AlignOfType(@encode(struct Struct2)), 141 "%d"); 142 143 ASSERT_EQUALS( 144 __alignof__(struct Struct3), 145 PyObjCRT_AlignOfType(@encode(struct Struct3)), 146 "%d"); 147 148 ASSERT_EQUALS( 149 __alignof__(struct Struct4), 150 PyObjCRT_AlignOfType(@encode(struct Struct4)), 151 "%d"); 152 153END_UNITTEST 154 155 156BEGIN_UNITTEST(FillStruct1) 157 158 PyObject* input; 159 struct Struct1 output; 160 int r; 161 162 input = PyTuple_New(2); 163 FAIL_IF(input == NULL); 164 165 PyTuple_SetItem(input, 0, PyInt_FromLong(1)); 166 PyTuple_SetItem(input, 1, PyFloat_FromDouble(2)); 167 168 r = PyObjC_PythonToObjC(@encode(struct Struct1), input, &output); 169 FAIL_IF(r < 0); 170 171 Py_DECREF(input); 172 173 ASSERT_EQUALS(output.f1, 1, "%d"); 174 ASSERT_EQUALS(output.f2, 2.0, "%g"); 175 176END_UNITTEST 177 178BEGIN_UNITTEST(FillStruct2) 179 180 PyObject* input; 181 PyObject* v; 182 struct Struct2 output; 183 int r; 184 185 input = PyTuple_New(3); 186 FAIL_IF(input == NULL); 187 188 v = PyTuple_New(5); 189 PyTuple_SetItem(v, 0, PyInt_FromLong(10)); 190 PyTuple_SetItem(v, 1, PyInt_FromLong(11)); 191 PyTuple_SetItem(v, 2, PyInt_FromLong(12)); 192 PyTuple_SetItem(v, 3, PyInt_FromLong(13)); 193 PyTuple_SetItem(v, 4, PyInt_FromLong(14)); 194 195 PyTuple_SetItem(input, 0, PyInt_FromLong(1)); 196 PyTuple_SetItem(input, 1, PyFloat_FromDouble(2)); 197 PyTuple_SetItem(input, 2, v); 198 199 r = PyObjC_PythonToObjC(@encode(struct Struct2), input, &output); 200 FAIL_IF(r < 0); 201 202 Py_DECREF(input); 203 204 ASSERT_EQUALS(output.f1, 1, "%d"); 205 ASSERT_EQUALS(output.f2, 2.0, "%g"); 206 ASSERT_EQUALS(output.s[0], 10, "%d"); 207 ASSERT_EQUALS(output.s[1], 11, "%d"); 208 ASSERT_EQUALS(output.s[2], 12, "%d"); 209 ASSERT_EQUALS(output.s[3], 13, "%d"); 210 ASSERT_EQUALS(output.s[4], 14, "%d"); 211 212END_UNITTEST 213 214BEGIN_UNITTEST(FillStruct3) 215 216 PyObject* input; 217 struct Struct3 output; 218 int r; 219 220 input = PyTuple_New(2); 221 FAIL_IF(input == NULL); 222 223 PyTuple_SetItem(input, 0, PyBytes_FromStringAndSize("\001", 1)); 224 PyTuple_SetItem(input, 1, PyInt_FromLong(2)); 225 226 r = PyObjC_PythonToObjC(@encode(struct Struct3), input, &output); 227 FAIL_IF(r < 0); 228 229 Py_DECREF(input); 230 231 ASSERT_EQUALS(output.ch, '\001', "%d"); 232 ASSERT_EQUALS(output.i, 2, "%d"); 233 234END_UNITTEST 235 236BEGIN_UNITTEST(FillStruct4) 237 238 PyObject* input; 239 struct Struct4 output; 240 int r; 241 242 input = PyTuple_New(2); 243 FAIL_IF(input == NULL); 244 245 PyTuple_SetItem(input, 0, PyBytes_FromStringAndSize("\001", 1)); 246 PyTuple_SetItem(input, 1, PyInt_FromLong(500000)); 247 248 r = PyObjC_PythonToObjC(@encode(struct Struct4), input, &output); 249 FAIL_IF(r < 0); 250 251 Py_DECREF(input); 252 253 ASSERT_EQUALS(output.ch, '\001', "%d"); 254 ASSERT_EQUALS(output.i, 500000, "%ll"); 255 256END_UNITTEST 257 258BEGIN_UNITTEST(FillStruct5Array) 259 260 PyObject* input; 261 PyObject* v; 262 Struct5Array output; 263 int r; 264 265 input = PyTuple_New(2); 266 FAIL_IF(input == NULL); 267 268 v = PyTuple_New(2); 269 PyTuple_SetItem(v, 0, PyInt_FromLong(500000)); 270 PyTuple_SetItem(v, 1, PyBytes_FromStringAndSize("\001", 1)); 271 PyTuple_SetItem(input, 0, v); 272 273 v = PyTuple_New(2); 274 PyTuple_SetItem(v, 0, PyInt_FromLong(1000000)); 275 PyTuple_SetItem(v, 1, PyBytes_FromStringAndSize("\002", 1)); 276 PyTuple_SetItem(input, 1, v); 277 278 r = PyObjC_PythonToObjC(@encode(Struct5Array), input, &output); 279 FAIL_IF(r < 0); 280 281 Py_DECREF(input); 282 283 ASSERT_EQUALS(output[0].ch, '\001', "%d"); 284 ASSERT_EQUALS(output[0].i, 500000, "%ll"); 285 ASSERT_EQUALS(output[1].ch, '\002', "%d"); 286 ASSERT_EQUALS(output[1].i, 1000000, "%ll"); 287 288END_UNITTEST 289 290BEGIN_UNITTEST(ExtractStruct1) 291 292 struct Struct1 input; 293 PyObject* output; 294 295 input.f1 = 1; 296 input.f2 = 2; 297 298 output = PyObjC_ObjCToPython(@encode(struct Struct1), &input); 299 FAIL_IF(output == NULL); 300 301 ASSERT_ISINSTANCE(output, Tuple); 302 ASSERT_EQUALS(PyTuple_GET_SIZE(output), 2, "%d"); 303#if PY_VERSION_HEX < 0x03000000 304 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 0), Int); 305#else 306 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 0), Long); 307#endif 308 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 1), Float); 309 ASSERT_EQUALS(PyInt_AsLong(PyTuple_GetItem(output, 0)), 1, "%d"); 310 ASSERT_EQUALS(PyFloat_AsDouble(PyTuple_GetItem(output, 1)), 2.0, "%g"); 311 312END_UNITTEST 313 314BEGIN_UNITTEST(ExtractStruct2) 315 316 struct Struct2 input; 317 PyObject* output; 318 PyObject* tup; 319 PyObject* v; 320 321 input.f1 = 1; 322 input.f2 = 2; 323 input.s[0] = 3; 324 input.s[1] = 4; 325 input.s[2] = 5; 326 input.s[3] = 6; 327 input.s[4] = 7; 328 329 output = PyObjC_ObjCToPython(@encode(struct Struct2), &input); 330 FAIL_IF(output == NULL); 331 332 ASSERT_ISINSTANCE(output, Tuple); 333 ASSERT_EQUALS(PyTuple_GET_SIZE(output), 3, "%d"); 334#if PY_VERSION_HEX < 0x03000000 335 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 0), Int); 336#else 337 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 0), Long); 338#endif 339 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 1), Float); 340 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 2), Tuple); 341 ASSERT_EQUALS(PyInt_AsLong(PyTuple_GetItem(output, 0)), 1, "%d"); 342 ASSERT_EQUALS(PyFloat_AsDouble(PyTuple_GetItem(output, 1)), 2.0, "%g"); 343 344 tup = PyTuple_GetItem(output, 2); 345 ASSERT_EQUALS(PyTuple_GET_SIZE(tup), 5, "%d"); 346 347 v = PyTuple_GetItem(tup, 0); 348#if PY_VERSION_HEX < 0x03000000 349 ASSERT_ISINSTANCE(v, Int); 350#else 351 ASSERT_ISINSTANCE(v, Long); 352#endif 353 ASSERT_EQUALS(PyInt_AsLong(v), 3, "%d"); 354 355 v = PyTuple_GetItem(tup, 1); 356#if PY_VERSION_HEX < 0x03000000 357 ASSERT_ISINSTANCE(v, Int); 358#else 359 ASSERT_ISINSTANCE(v, Long); 360#endif 361 ASSERT_EQUALS(PyInt_AsLong(v), 4, "%d"); 362 363 v = PyTuple_GetItem(tup, 2); 364#if PY_VERSION_HEX < 0x03000000 365 ASSERT_ISINSTANCE(v, Int); 366#else 367 ASSERT_ISINSTANCE(v, Long); 368#endif 369 ASSERT_EQUALS(PyInt_AsLong(v), 5, "%d"); 370 371 v = PyTuple_GetItem(tup, 3); 372#if PY_VERSION_HEX < 0x03000000 373 ASSERT_ISINSTANCE(v, Int); 374#else 375 ASSERT_ISINSTANCE(v, Long); 376#endif 377 ASSERT_EQUALS(PyInt_AsLong(v), 6, "%d"); 378 379 v = PyTuple_GetItem(tup, 4); 380#if PY_VERSION_HEX < 0x03000000 381 ASSERT_ISINSTANCE(v, Int); 382#else 383 ASSERT_ISINSTANCE(v, Long); 384#endif 385 ASSERT_EQUALS(PyInt_AsLong(v), 7, "%d"); 386 387END_UNITTEST 388 389BEGIN_UNITTEST(ExtractStruct3) 390 391 struct Struct3 input; 392 PyObject* output; 393 394 input.ch = 1; 395 input.i = 2; 396 397 output = PyObjC_ObjCToPython(@encode(struct Struct3), &input); 398 FAIL_IF(output == NULL); 399 400 ASSERT_ISINSTANCE(output, Tuple); 401 ASSERT_EQUALS(PyTuple_GET_SIZE(output), 2, "%d"); 402#if PY_VERSION_HEX < 0x03000000 403 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 0), Int); 404 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 1), Int); 405#else 406 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 0), Long); 407 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 1), Long); 408#endif 409 ASSERT_EQUALS(PyInt_AsLong(PyTuple_GetItem(output, 0)), 1, "%d"); 410 ASSERT_EQUALS(PyInt_AsLong(PyTuple_GetItem(output, 1)), 2, "%d"); 411 412END_UNITTEST 413 414BEGIN_UNITTEST(ExtractStruct4) 415 416 struct Struct4 input; 417 PyObject* output; 418 419 input.ch = 1; 420 input.i = 500000; 421 422 output = PyObjC_ObjCToPython(@encode(struct Struct4), &input); 423 FAIL_IF(output == NULL); 424 425 ASSERT_ISINSTANCE(output, Tuple); 426 ASSERT_EQUALS(PyTuple_GET_SIZE(output), 2, "%d"); 427#if PY_VERSION_HEX < 0x03000000 428 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 0), Int); 429#ifdef __LP64__ 430 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 1), Int); 431#else 432 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 1), Long); 433#endif 434#else 435 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 0), Long); 436 ASSERT_ISINSTANCE(PyTuple_GetItem(output, 1), Long); 437#endif 438 439 ASSERT_EQUALS(PyInt_AsLong(PyTuple_GetItem(output, 0)), 1, "%d"); 440 ASSERT_EQUALS(PyInt_AsLong(PyTuple_GetItem(output, 1)), 500000, "%d"); 441 442END_UNITTEST 443 444BEGIN_UNITTEST(ExtractStruct5Array) 445 446 Struct5Array input; 447 PyObject* output; 448 PyObject* v; 449 450 input[0].ch = 1; 451 input[0].i = 500000; 452 input[1].ch = 2; 453 input[1].i = 1000000; 454 455 output = PyObjC_ObjCToPython(@encode(Struct5Array), &input); 456 FAIL_IF(output == NULL); 457 458 ASSERT_ISINSTANCE(output, Tuple); 459 ASSERT_EQUALS(PyTuple_GET_SIZE(output), 2, "%d"); 460 461 v = PyTuple_GetItem(output, 0); 462 ASSERT_ISINSTANCE(v, Tuple); 463#if PY_VERSION_HEX < 0x03000000 464 ASSERT_ISINSTANCE(PyTuple_GetItem(v, 0), Int); 465 ASSERT_ISINSTANCE(PyTuple_GetItem(v, 1), Int); 466#else 467 ASSERT_ISINSTANCE(PyTuple_GetItem(v, 0), Long); 468 ASSERT_ISINSTANCE(PyTuple_GetItem(v, 1), Long); 469#endif 470 ASSERT_EQUALS(PyInt_AsLong(PyTuple_GetItem(v, 0)), 500000, "%d"); 471 ASSERT_EQUALS(PyInt_AsLong(PyTuple_GetItem(v, 1)), 1, "%d"); 472 473 v = PyTuple_GetItem(output, 1); 474 ASSERT_ISINSTANCE(v, Tuple); 475#if PY_VERSION_HEX < 0x03000000 476 ASSERT_ISINSTANCE(PyTuple_GetItem(v, 0), Int); 477 ASSERT_ISINSTANCE(PyTuple_GetItem(v, 1), Int); 478#else 479 ASSERT_ISINSTANCE(PyTuple_GetItem(v, 0), Long); 480 ASSERT_ISINSTANCE(PyTuple_GetItem(v, 1), Long); 481#endif 482 ASSERT_EQUALS(PyInt_AsLong(PyTuple_GetItem(v, 0)), 1000000, "%d"); 483 ASSERT_EQUALS(PyInt_AsLong(PyTuple_GetItem(v, 1)), 2, "%d"); 484 485END_UNITTEST 486 487#ifdef _C_BOOL 488 489BEGIN_UNITTEST(TestSizeOfBool) 490 491 /* Code in libffi_support.m depends on this equality. */ 492#if defined(__ppc__) || defined(__ppc64__) 493 ASSERT_EQUALS(sizeof(bool), sizeof(int), "%d"); 494 495#else 496 ASSERT_EQUALS(sizeof(bool), sizeof(char), "%d"); 497#endif 498 499END_UNITTEST 500 501#endif 502 503BEGIN_UNITTEST(TestTypeCode) 504 505 /* These are manually defined on some platforms */ 506 ASSERT_EQUALS(@encode(long long)[0], 'q', "%c"); 507 ASSERT_EQUALS(@encode(unsigned long long)[0], 'Q', "%c"); 508 509#if defined(MACOSX) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_1 510 ASSERT_EQUALS(@encode(bool)[0], 'B', "%#x"); 511#endif 512 513END_UNITTEST 514 515BEGIN_UNITTEST(TestSimplifySignature) 516 /* Make sure PyObjCRT_SimplifySignature works */ 517 char b[1024]; 518 int r; 519 520 r = PyObjCRT_SimplifySignature("@1234@0:{_NSPoint=ff}02i22", b, sizeof(b)); 521 ASSERT(r != -1); 522 ASSERT_STREQUALS("@@:{_NSPoint=ff}i", b); 523 524 r = PyObjCRT_SimplifySignature("@@:{_NSPoint=ff}i", b, sizeof(b)); 525 ASSERT(r != -1); 526 ASSERT_STREQUALS("@@:{_NSPoint=ff}i", b); 527END_UNITTEST 528 529BEGIN_UNITTEST(TestArrayCoding) 530 /* 531 * According to the docs on Panther, valueForKey: on an array should 532 * return [ o.valueForKey_(key) for o in anArray ]. 533 * On MacOS X 10.2 it doesn't. 534 * 535 * This test was added to make sure PyObjC is not at fault :-), the 536 * test is also used to avoid giving false positives in the unittests 537 * for key-value coding. 538 */ 539 540 NSMutableDictionary* d; 541 NSMutableArray* a; 542 NSObject* v; 543 int haveException; 544 545 NSAutoreleasePool* p; 546 547 p = [[NSAutoreleasePool alloc] init]; 548 549 d = [NSMutableDictionary dictionary]; 550 551 [d setObject:@"foo" forKey:@"keyM"]; 552 553 a = [NSMutableArray arrayWithObjects: d, nil]; 554 555 NS_DURING 556 v = [a valueForKey:@"keyM"]; 557 haveException = 0; 558 NS_HANDLER 559 v = nil; 560 haveException = 1; 561 NS_ENDHANDLER 562 563 [p release]; 564 565 ASSERT(!haveException); 566END_UNITTEST 567 568 569BEGIN_UNITTEST(PythonListAsNSArray) 570 PyObject* aList; 571 NSMutableArray* array; 572 NSArray* array2; 573 574 aList = Py_BuildValue("[iiiii]", 0, 1, 2, 3, 4); 575 FAIL_IF(aList == NULL); 576 577 array = PyObjC_PythonToId(aList); 578 FAIL_IF(array == nil); 579 580 /* Check lenght */ 581 ASSERT_EQUALS(5, [array count], "%d"); 582 583 /* Check basic element access */ 584 ASSERT([[NSNumber numberWithInt:0] isEqual:[array objectAtIndex:0]]); 585 ASSERT([[NSNumber numberWithInt:1] isEqual:[array objectAtIndex:1]]); 586 ASSERT([[NSNumber numberWithInt:2] isEqual:[array objectAtIndex:2]]); 587 ASSERT([[NSNumber numberWithInt:3] isEqual:[array objectAtIndex:3]]); 588 ASSERT([[NSNumber numberWithInt:4] isEqual:[array objectAtIndex:4]]); 589 590 /* Check some other methods */ 591 array2 = [array arrayByAddingObject: [NSNumber numberWithInt:5]]; 592 FAIL_IF(array2 == nil); 593 594 ASSERT_EQUALS(6, [array2 count], "%d"); 595 ASSERT_EQUALS(5, [array count], "%d"); 596 597 ASSERT([[NSNumber numberWithInt:0] isEqual:[array2 objectAtIndex:0]]); 598 ASSERT([[NSNumber numberWithInt:1] isEqual:[array2 objectAtIndex:1]]); 599 ASSERT([[NSNumber numberWithInt:2] isEqual:[array2 objectAtIndex:2]]); 600 ASSERT([[NSNumber numberWithInt:3] isEqual:[array2 objectAtIndex:3]]); 601 ASSERT([[NSNumber numberWithInt:4] isEqual:[array2 objectAtIndex:4]]); 602 ASSERT([[NSNumber numberWithInt:5] isEqual:[array2 objectAtIndex:5]]); 603 604 ASSERT([array containsObject:[NSNumber numberWithInt:4]]); 605 ASSERT(![array containsObject:[NSNumber numberWithInt:10]]); 606 607 /* Mutating methods */ 608 [array addObject: [NSNumber numberWithInt:5]]; 609 ASSERT_EQUALS(6, [array count], "%d"); 610 ASSERT([[NSNumber numberWithInt:5] isEqual:[array objectAtIndex:5]]); 611 612 [array removeLastObject]; 613 ASSERT_EQUALS(5, [array count], "%d"); 614 ASSERT([[NSNumber numberWithInt:0] isEqual:[array objectAtIndex:0]]); 615 ASSERT([[NSNumber numberWithInt:4] isEqual:[array objectAtIndex:4]]); 616 617 [array insertObject: [NSNumber numberWithInt:6] atIndex: 1]; 618 ASSERT_EQUALS(6, [array count], "%d"); 619 ASSERT([[NSNumber numberWithInt:6] isEqual:[array objectAtIndex:1]]); 620 621 [array removeObjectAtIndex: 1]; 622 ASSERT_EQUALS(5, [array count], "%d"); 623 ASSERT([[NSNumber numberWithInt:1] isEqual:[array objectAtIndex:1]]); 624 625 [array replaceObjectAtIndex: 1 withObject: [NSNumber numberWithInt:7]]; 626 ASSERT_EQUALS(5, [array count], "%d"); 627 ASSERT([[NSNumber numberWithInt:7] isEqual:[array objectAtIndex:1]]); 628 629END_UNITTEST 630 631BEGIN_UNITTEST(PythonTupleAsNSArray) 632 PyObject* aTuple; 633 NSArray* array; 634 NSArray* array2; 635 636 aTuple = Py_BuildValue("(iiiii)", 0, 1, 2, 3, 4); 637 FAIL_IF(aTuple == NULL); 638 639 array = PyObjC_PythonToId(aTuple); 640 FAIL_IF(array == nil); 641 642 /* Check lenght */ 643 ASSERT_EQUALS(5, [array count], "%d"); 644 645 /* Check basic element access */ 646 ASSERT([[NSNumber numberWithInt:0] isEqual:[array objectAtIndex:0]]); 647 ASSERT([[NSNumber numberWithInt:1] isEqual:[array objectAtIndex:1]]); 648 ASSERT([[NSNumber numberWithInt:2] isEqual:[array objectAtIndex:2]]); 649 ASSERT([[NSNumber numberWithInt:3] isEqual:[array objectAtIndex:3]]); 650 ASSERT([[NSNumber numberWithInt:4] isEqual:[array objectAtIndex:4]]); 651 652 /* Check some other methods */ 653 array2 = [array arrayByAddingObject: [NSNumber numberWithInt:5]]; 654 ASSERT(array2 != nil); 655 656 ASSERT_EQUALS(6, [array2 count], "%d"); 657 ASSERT_EQUALS(5, [array count], "%d"); 658 659 ASSERT([[NSNumber numberWithInt:0] isEqual:[array2 objectAtIndex:0]]); 660 ASSERT([[NSNumber numberWithInt:1] isEqual:[array2 objectAtIndex:1]]); 661 ASSERT([[NSNumber numberWithInt:2] isEqual:[array2 objectAtIndex:2]]); 662 ASSERT([[NSNumber numberWithInt:3] isEqual:[array2 objectAtIndex:3]]); 663 ASSERT([[NSNumber numberWithInt:4] isEqual:[array2 objectAtIndex:4]]); 664 ASSERT([[NSNumber numberWithInt:5] isEqual:[array2 objectAtIndex:5]]); 665 666 ASSERT([array containsObject:[NSNumber numberWithInt:4]]); 667 ASSERT(![array containsObject:[NSNumber numberWithInt:10]]); 668 669END_UNITTEST 670 671BEGIN_UNITTEST(PythonDictAsNSDictionary) 672 // count, objectForKey:, keyEnumerator 673 // setObject:forKey: removeObjectForKey: 674 PyObject* aDictionary; 675 NSMutableDictionary* dict; 676 NSEnumerator* iter; 677 NSArray* keys; 678 679 aDictionary = Py_BuildValue( 680 "{iiiiiiii}", 681 1, 2, 682 2, 4, 683 3, 6, 684 4, 8 685 ); 686 FAIL_IF(aDictionary == NULL); 687 688 dict = PyObjC_PythonToId(aDictionary); 689 FAIL_IF(dict == nil); 690 691 ASSERT_EQUALS(4, [dict count], "%d"); 692 ASSERT([ 693 [dict objectForKey:[NSNumber numberWithInt:1]] 694 isEqual: [NSNumber numberWithInt: 2]]); 695 696 [dict setObject: [NSNumber numberWithInt:10] 697 forKey: [NSNumber numberWithInt:5]]; 698 ASSERT_EQUALS(5, [dict count], "%d"); 699 ASSERT([ 700 [dict objectForKey:[NSNumber numberWithInt:5]] 701 isEqual: [NSNumber numberWithInt: 10]]); 702 703 [dict removeObjectForKey: [NSNumber numberWithInt:5]]; 704 ASSERT_EQUALS(4, [dict count], "%d"); 705 706 iter = [dict keyEnumerator]; 707 ASSERT(iter != nil); 708 709 keys = [iter allObjects]; 710 ASSERT_EQUALS(4, [keys count], "%d"); 711 ASSERT([[keys objectAtIndex:0] isEqual:[NSNumber numberWithInt:1]]); 712 ASSERT([[keys objectAtIndex:1] isEqual:[NSNumber numberWithInt:2]]); 713 ASSERT([[keys objectAtIndex:2] isEqual:[NSNumber numberWithInt:3]]); 714 ASSERT([[keys objectAtIndex:3] isEqual:[NSNumber numberWithInt:4]]); 715 716END_UNITTEST 717 718BEGIN_UNITTEST(NSLogging) 719 /* This is a pretty lame test ... 720 * 721 * What this does is tests that the proxies of plain Python objects 722 * can be logged. This used to be impossible upto (and including) 723 * release 1.1! 724 */ 725 PyObject* o = (PyObject*)(Py_BuildValue("i", 10)->ob_type); 726 NSObject* value; 727 int fd; 728 int stderr_orig; 729 int r; 730 731 value = PyObjC_PythonToId(o); 732 FAIL_IF(value == nil); 733 734 fd = open("/dev/null", O_WRONLY); 735 ASSERT((fd != -1)); 736 stderr_orig = dup(2); 737 ASSERT(stderr_orig != -1); 738 r = dup2(fd, 2); 739 ASSERT(r != -1); 740 NSLog(@"%@", value); 741 r = dup2(stderr_orig, 2); 742 ASSERT(r != -1); 743 r = close(fd); 744 ASSERT(r != -1); 745END_UNITTEST 746 747BEGIN_UNITTEST(FillNSRect) 748 749 struct output { 750 unsigned int before; 751 NSRect rect; 752 unsigned int after; 753 }; 754 755 756 PyObject* input; 757 PyObject* v; 758 PyObject* t; 759 struct output output; 760 int r; 761 762 output.before = 0xDEADBEEF; 763 output.after = 0xBEEFDEAD; 764 765 input = PyTuple_New(2); 766 FAIL_IF(input == NULL); 767 768 v= PyTuple_New(2); 769 PyTuple_SetItem(v, 0, PyInt_FromLong(10)); 770 PyTuple_SetItem(v, 1, PyInt_FromLong(11)); 771 772 t= PyTuple_New(2); 773 PyTuple_SetItem(t, 0, PyInt_FromLong(20)); 774 PyTuple_SetItem(t, 1, PyInt_FromLong(21)); 775 776 PyTuple_SetItem(input, 0, v); 777 PyTuple_SetItem(input, 1, t); 778 779 r = PyObjC_PythonToObjC(@encode(NSRect), input, &output.rect); 780 FAIL_IF(r < 0); 781 782 Py_DECREF(input); 783 784 ASSERT_EQUALS(output.rect.origin.x, 10, "%d"); 785 ASSERT_EQUALS(output.rect.origin.y, 11, "%d"); 786 ASSERT_EQUALS(output.rect.size.width, 20, "%d"); 787 ASSERT_EQUALS(output.rect.size.height, 21, "%d"); 788 ASSERT_EQUALS(output.before, 0xDEADBEEF, "%x"); 789 ASSERT_EQUALS(output.after, 0xBEEFDEAD, "%x"); 790 791END_UNITTEST 792 793BEGIN_UNITTEST(RemoveFieldNames) 794 char buffer[2048]; 795 const char* end; 796 size_t i; 797 798 /* Simple type */ 799 memset(buffer, '\xab', sizeof(buffer)); 800 end = PyObjCRT_RemoveFieldNames(buffer, "i"); 801 ASSERT(end != NULL); 802 ASSERT_STREQUALS(buffer, "i"); 803 ASSERT_EQUALS(*end, '\0', "%c"); 804 for (i = strlen(buffer)+1; i < sizeof(buffer);i++) { 805 ASSERT_EQUALS(buffer[i], '\xab', "%c"); 806 } 807 808 /* Simple struct */ 809 memset(buffer, '\xab', sizeof(buffer)); 810 end = PyObjCRT_RemoveFieldNames(buffer, "{_NSPoint=\"x1\"f\"y2\"i}"); 811 ASSERT(end != NULL); 812 ASSERT_STREQUALS(buffer, "{_NSPoint=fi}"); 813 ASSERT_EQUALS(*end, '\0', "%c"); 814 for (i = strlen(buffer)+1; i < sizeof(buffer);i++) { 815 ASSERT_EQUALS(buffer[i], '\xab', "%c"); 816 } 817 818 memset(buffer, '\xab', sizeof(buffer)); 819 end = PyObjCRT_RemoveFieldNames(buffer, "{_NSPoint=fi}"); 820 ASSERT(end != NULL); 821 ASSERT_STREQUALS(buffer, "{_NSPoint=fi}"); 822 ASSERT_EQUALS(*end, '\0', "%c"); 823 for (i = strlen(buffer)+1; i < sizeof(buffer);i++) { 824 ASSERT_EQUALS(buffer[i], '\xab', "%c"); 825 } 826 827 /* Simple array */ 828 memset(buffer, '\xab', sizeof(buffer)); 829 end = PyObjCRT_RemoveFieldNames(buffer, "[22f]"); 830 ASSERT(end != NULL); 831 ASSERT_STREQUALS(buffer, "[22f]"); 832 ASSERT_EQUALS(*end, '\0', "%c"); 833 for (i = strlen(buffer)+1; i < sizeof(buffer);i++) { 834 ASSERT_EQUALS(buffer[i], '\xab', "%c"); 835 } 836 837 memset(buffer, '\xab', sizeof(buffer)); 838 end = PyObjCRT_RemoveFieldNames(buffer, "[22{_F=ii}]"); 839 ASSERT(end != NULL); 840 ASSERT_STREQUALS(buffer, "[22{_F=ii}]"); 841 ASSERT_EQUALS(*end, '\0', "%c"); 842 for (i = strlen(buffer)+1; i < sizeof(buffer);i++) { 843 ASSERT_EQUALS(buffer[i], '\xab', "%c"); 844 } 845 846 memset(buffer, '\xab', sizeof(buffer)); 847 end = PyObjCRT_RemoveFieldNames(buffer, "[22{_F=\"ab\"d\"cd\"d}]"); 848 ASSERT(end != NULL); 849 ASSERT_STREQUALS(buffer, "[22{_F=dd}]"); 850 ASSERT_EQUALS(*end, '\0', "%c"); 851 for (i = strlen(buffer)+1; i < sizeof(buffer);i++) { 852 ASSERT_EQUALS(buffer[i], '\xab', "%c"); 853 } 854 855 /* Nested struct */ 856 memset(buffer, '\xab', sizeof(buffer)); 857 end = PyObjCRT_RemoveFieldNames(buffer, "[22{_F=\"ab\"{_G=\"x\"f\"y\"f}\"cd\"{_G=\"x\"f\"y\"f}}]"); 858 ASSERT(end != NULL); 859 ASSERT_STREQUALS(buffer, "[22{_F={_G=ff}{_G=ff}}]"); 860 ASSERT_EQUALS(*end, '\0', "%c"); 861 for (i = strlen(buffer)+1; i < sizeof(buffer);i++) { 862 ASSERT_EQUALS(buffer[i], '\xab', "%c"); 863 } 864 865END_UNITTEST 866 867BEGIN_UNITTEST(UnicodeFunctions) 868 PyObject* unicode = PyUnicode_FromString("hello world"); 869 int ok; 870 871 ok = PyObjC_is_ascii_string(unicode, "hello world"); 872 ASSERT(ok); 873 874 ok = PyObjC_is_ascii_string(unicode, "hello"); 875 ASSERT(!ok); 876 877 ok = PyObjC_is_ascii_string(unicode, "hello world!"); 878 ASSERT(!ok); 879 880 881 ok = PyObjC_is_ascii_prefix(unicode, "hello world", 11); 882 ASSERT(ok); 883 884 ok = PyObjC_is_ascii_prefix(unicode, "hello worlk", 11); 885 ASSERT(!ok); 886 887 ok = PyObjC_is_ascii_prefix(unicode, "hello worlk", 10); 888 ASSERT(ok); 889 890 ok = PyObjC_is_ascii_prefix(unicode, "hello", 5); 891 ASSERT(ok); 892 893 ok = PyObjC_is_ascii_prefix(unicode, "hello world!", 12); 894 ASSERT(ok); 895 896END_UNITTEST 897 898static PyMethodDef mod_methods[] = { 899 TESTDEF(CheckNSInvoke), 900 901 TESTDEF(StructSize), 902 TESTDEF(StructAlign), 903 TESTDEF(FillStruct1), 904 TESTDEF(FillStruct2), 905 TESTDEF(FillStruct3), 906 TESTDEF(FillStruct4), 907 TESTDEF(FillStruct5Array), 908 TESTDEF(ExtractStruct1), 909 TESTDEF(ExtractStruct2), 910 TESTDEF(ExtractStruct3), 911 TESTDEF(ExtractStruct4), 912 TESTDEF(ExtractStruct5Array), 913#ifdef _C_BOOL 914 TESTDEF(TestSizeOfBool), 915#endif 916 TESTDEF(TestTypeCode), 917 TESTDEF(TestSimplifySignature), 918 TESTDEF(TestArrayCoding), 919 TESTDEF(PythonListAsNSArray), 920 TESTDEF(PythonTupleAsNSArray), 921 TESTDEF(PythonDictAsNSDictionary), 922 TESTDEF(NSLogging), 923 TESTDEF(FillNSRect), 924 TESTDEF(RemoveFieldNames), 925 TESTDEF(UnicodeFunctions), 926 { 0, 0, 0, 0 } 927}; 928 929#if PY_VERSION_HEX >= 0x03000000 930 931static struct PyModuleDef mod_module = { 932 PyModuleDef_HEAD_INIT, 933 "ctests", 934 NULL, 935 0, 936 mod_methods, 937 NULL, 938 NULL, 939 NULL, 940 NULL 941}; 942 943#define INITERROR() return NULL 944#define INITDONE() return m 945 946PyObject* PyInit_ctests(void); 947 948PyObject* 949PyInit_ctests(void) 950 951#else 952 953#define INITERROR() return 954#define INITDONE() return 955 956void initctests(void); 957 958void 959initctests(void) 960#endif 961{ 962 PyObject* m; 963 964#if PY_VERSION_HEX >= 0x03000000 965 m = PyModule_Create(&mod_module); 966#else 967 m = Py_InitModule4("ctests", mod_methods, 968 NULL, NULL, PYTHON_API_VERSION); 969#endif 970 if (!m) { 971 INITERROR(); 972 } 973 974 if (PyObjC_ImportAPI(m) < 0) { 975 INITERROR(); 976 } 977 978 INITDONE(); 979} 980