]> git.saurik.com Git - apple/objc4.git/blame - test/customrr.m
objc4-818.2.tar.gz
[apple/objc4.git] / test / customrr.m
CommitLineData
13ba007e
A
1// These options must match customrr2.m
2// TEST_CONFIG MEM=mrc
3/*
4TEST_BUILD
1807f628 5 $C{COMPILE} $DIR/customrr.m -fvisibility=default -o customrr.exe -fno-objc-convert-messages-to-runtime-calls
13ba007e
A
6 $C{COMPILE} -bundle -bundle_loader customrr.exe $DIR/customrr-cat1.m -o customrr-cat1.bundle
7 $C{COMPILE} -bundle -bundle_loader customrr.exe $DIR/customrr-cat2.m -o customrr-cat2.bundle
8END
9*/
10
11
12#include "test.h"
13#include <dlfcn.h>
14#include <Foundation/NSObject.h>
15
16static int Retains;
17static int Releases;
18static int Autoreleases;
19static int RetainCounts;
20static int PlusRetains;
21static int PlusReleases;
22static int PlusAutoreleases;
23static int PlusRetainCounts;
24static int Allocs;
25static int AllocWithZones;
26
27static int SubRetains;
28static int SubReleases;
29static int SubAutoreleases;
30static int SubRetainCounts;
31static int SubPlusRetains;
32static int SubPlusReleases;
33static int SubPlusAutoreleases;
34static int SubPlusRetainCounts;
35static int SubAllocs;
36static int SubAllocWithZones;
37
38static int Imps;
39
40static id imp_fn(id self, SEL _cmd __unused, ...)
41{
42 Imps++;
43 return self;
44}
45
46static void zero(void) {
47 Retains = 0;
48 Releases = 0;
49 Autoreleases = 0;
50 RetainCounts = 0;
51 PlusRetains = 0;
52 PlusReleases = 0;
53 PlusAutoreleases = 0;
54 PlusRetainCounts = 0;
55 Allocs = 0;
56 AllocWithZones = 0;
57
58 SubRetains = 0;
59 SubReleases = 0;
60 SubAutoreleases = 0;
61 SubRetainCounts = 0;
62 SubPlusRetains = 0;
63 SubPlusReleases = 0;
64 SubPlusAutoreleases = 0;
65 SubPlusRetainCounts = 0;
66 SubAllocs = 0;
67 SubAllocWithZones = 0;
68
69 Imps = 0;
70}
71
72
73id HackRetain(id self, SEL _cmd __unused) { Retains++; return self; }
74void HackRelease(id self __unused, SEL _cmd __unused) { Releases++; }
75id HackAutorelease(id self, SEL _cmd __unused) { Autoreleases++; return self; }
76NSUInteger HackRetainCount(id self __unused, SEL _cmd __unused) { RetainCounts++; return 1; }
77id HackPlusRetain(id self, SEL _cmd __unused) { PlusRetains++; return self; }
78void HackPlusRelease(id self __unused, SEL _cmd __unused) { PlusReleases++; }
79id HackPlusAutorelease(id self, SEL _cmd __unused) { PlusAutoreleases++; return self; }
80NSUInteger HackPlusRetainCount(id self __unused, SEL _cmd __unused) { PlusRetainCounts++; return 1; }
81id HackAlloc(Class self, SEL _cmd __unused) { Allocs++; return class_createInstance(self, 0); }
82id HackAllocWithZone(Class self, SEL _cmd __unused) { AllocWithZones++; return class_createInstance(self, 0); }
83
84
85@interface OverridingSub : NSObject @end
86@implementation OverridingSub
87
88-(id) retain { SubRetains++; return self; }
89+(id) retain { SubPlusRetains++; return self; }
90-(oneway void) release { SubReleases++; }
91+(oneway void) release { SubPlusReleases++; }
92-(id) autorelease { SubAutoreleases++; return self; }
93+(id) autorelease { SubPlusAutoreleases++; return self; }
94-(NSUInteger) retainCount { SubRetainCounts++; return 1; }
95+(NSUInteger) retainCount { SubPlusRetainCounts++; return 1; }
96
97@end
98
99@interface OverridingASub : NSObject @end
100@implementation OverridingASub
101+(id) alloc { SubAllocs++; return class_createInstance(self, 0); }
102@end
103
104@interface OverridingAWZSub : NSObject @end
105@implementation OverridingAWZSub
106+(id) allocWithZone:(NSZone * __unused)z { SubAllocWithZones++; return class_createInstance(self, 0); }
107@end
108
109@interface OverridingAAWZSub : NSObject @end
110@implementation OverridingAAWZSub
111+(id) alloc { SubAllocs++; return class_createInstance(self, 0); }
112+(id) allocWithZone:(NSZone * __unused)z { SubAllocWithZones++; return class_createInstance(self, 0); }
113@end
114
115
116@interface InheritingSub : NSObject @end
117@implementation InheritingSub @end
118
119@interface InheritingSub2 : NSObject @end
120@implementation InheritingSub2 @end
121@interface InheritingSub2_2 : InheritingSub2 @end
122@implementation InheritingSub2_2 @end
123
124@interface InheritingSub3 : NSObject @end
125@implementation InheritingSub3 @end
126@interface InheritingSub3_2 : InheritingSub3 @end
127@implementation InheritingSub3_2 @end
128
129@interface InheritingSub4 : NSObject @end
130@implementation InheritingSub4 @end
131@interface InheritingSub4_2 : InheritingSub4 @end
132@implementation InheritingSub4_2 @end
133
134@interface InheritingSub5 : NSObject @end
135@implementation InheritingSub5 @end
136@interface InheritingSub5_2 : InheritingSub5 @end
137@implementation InheritingSub5_2 @end
138
139@interface InheritingSub6 : NSObject @end
140@implementation InheritingSub6 @end
141@interface InheritingSub6_2 : InheritingSub6 @end
142@implementation InheritingSub6_2 @end
143
144@interface InheritingSub7 : NSObject @end
145@implementation InheritingSub7 @end
146@interface InheritingSub7_2 : InheritingSub7 @end
147@implementation InheritingSub7_2 @end
148
149@interface InheritingSubCat : NSObject @end
150@implementation InheritingSubCat @end
151@interface InheritingSubCat_2 : InheritingSubCat @end
152@implementation InheritingSubCat_2 @end
153
154
155extern uintptr_t OBJC_CLASS_$_UnrealizedSubA1;
156@interface UnrealizedSubA1 : NSObject @end
157@implementation UnrealizedSubA1 @end
158extern uintptr_t OBJC_CLASS_$_UnrealizedSubA2;
159@interface UnrealizedSubA2 : NSObject @end
160@implementation UnrealizedSubA2 @end
161extern uintptr_t OBJC_CLASS_$_UnrealizedSubA3;
162@interface UnrealizedSubA3 : NSObject @end
163@implementation UnrealizedSubA3 @end
164
165extern uintptr_t OBJC_CLASS_$_UnrealizedSubB1;
166@interface UnrealizedSubB1 : NSObject @end
167@implementation UnrealizedSubB1 @end
168extern uintptr_t OBJC_CLASS_$_UnrealizedSubB2;
169@interface UnrealizedSubB2 : NSObject @end
170@implementation UnrealizedSubB2 @end
171extern uintptr_t OBJC_CLASS_$_UnrealizedSubB3;
172@interface UnrealizedSubB3 : NSObject @end
173@implementation UnrealizedSubB3 @end
174
175extern uintptr_t OBJC_CLASS_$_UnrealizedSubC1;
176@interface UnrealizedSubC1 : NSObject @end
177@implementation UnrealizedSubC1 @end
178extern uintptr_t OBJC_CLASS_$_UnrealizedSubC2;
179@interface UnrealizedSubC2 : NSObject @end
180@implementation UnrealizedSubC2 @end
181extern uintptr_t OBJC_CLASS_$_UnrealizedSubC3;
182@interface UnrealizedSubC3 : NSObject @end
183@implementation UnrealizedSubC3 @end
184
185
186int main(int argc __unused, char **argv)
187{
188 objc_autoreleasePoolPush();
189
190 // Hack NSObject's RR methods.
191 // Don't use runtime functions to do this -
192 // we want the runtime to think that these are NSObject's real code
193 {
13ba007e
A
194 Class cls = [NSObject class];
195 IMP imp = class_getMethodImplementation(cls, @selector(retain));
34d5b5e8
A
196 Method m = class_getInstanceMethod(cls, @selector(retain));
197 testassert(method_getImplementation(m) == imp); // verify Method struct is as we expect
198
199 m = class_getInstanceMethod(cls, @selector(retain));
200 _method_setImplementationRawUnsafe(m, (IMP)HackRetain);
201 m = class_getInstanceMethod(cls, @selector(release));
202 _method_setImplementationRawUnsafe(m, (IMP)HackRelease);
203 m = class_getInstanceMethod(cls, @selector(autorelease));
204 _method_setImplementationRawUnsafe(m, (IMP)HackAutorelease);
205 m = class_getInstanceMethod(cls, @selector(retainCount));
206 _method_setImplementationRawUnsafe(m, (IMP)HackRetainCount);
207 m = class_getClassMethod(cls, @selector(retain));
208 _method_setImplementationRawUnsafe(m, (IMP)HackPlusRetain);
209 m = class_getClassMethod(cls, @selector(release));
210 _method_setImplementationRawUnsafe(m, (IMP)HackPlusRelease);
211 m = class_getClassMethod(cls, @selector(autorelease));
212 _method_setImplementationRawUnsafe(m, (IMP)HackPlusAutorelease);
213 m = class_getClassMethod(cls, @selector(retainCount));
214 _method_setImplementationRawUnsafe(m, (IMP)HackPlusRetainCount);
215 m = class_getClassMethod(cls, @selector(alloc));
216 _method_setImplementationRawUnsafe(m, (IMP)HackAlloc);
217 m = class_getClassMethod(cls, @selector(allocWithZone:));
218 _method_setImplementationRawUnsafe(m, (IMP)HackAllocWithZone);
13ba007e
A
219
220 _objc_flush_caches(cls);
221
222 imp = class_getMethodImplementation(cls, @selector(retain));
223 testassert(imp == (IMP)HackRetain); // verify hack worked
224 }
225
226 Class cls = [NSObject class];
227 Class icl = [InheritingSub class];
228 Class ocl = [OverridingSub class];
229 /*
230 Class oa1 = [OverridingASub class];
231 Class oa2 = [OverridingAWZSub class];
232 Class oa3 = [OverridingAAWZSub class];
233 */
234 NSObject *obj = [NSObject new];
235 InheritingSub *inh = [InheritingSub new];
236 OverridingSub *ovr = [OverridingSub new];
237
238 Class ccc;
239 id ooo;
240 Class cc2;
241 id oo2;
242
243 void *dlh;
244
245
246#if __x86_64__
247 // vtable dispatch can introduce bypass just like the ARC entrypoints
248#else
249 testprintf("method dispatch does not bypass\n");
250 zero();
251
252 [obj retain];
253 testassert(Retains == 1);
254 [obj release];
255 testassert(Releases == 1);
256 [obj autorelease];
257 testassert(Autoreleases == 1);
258
259 [cls retain];
260 testassert(PlusRetains == 1);
261 [cls release];
262 testassert(PlusReleases == 1);
263 [cls autorelease];
264 testassert(PlusAutoreleases == 1);
265
266 [inh retain];
267 testassert(Retains == 2);
268 [inh release];
269 testassert(Releases == 2);
270 [inh autorelease];
271 testassert(Autoreleases == 2);
272
273 [icl retain];
274 testassert(PlusRetains == 2);
275 [icl release];
276 testassert(PlusReleases == 2);
277 [icl autorelease];
278 testassert(PlusAutoreleases == 2);
279
280 [ovr retain];
281 testassert(SubRetains == 1);
282 [ovr release];
283 testassert(SubReleases == 1);
284 [ovr autorelease];
285 testassert(SubAutoreleases == 1);
286
287 [ocl retain];
288 testassert(SubPlusRetains == 1);
289 [ocl release];
290 testassert(SubPlusReleases == 1);
291 [ocl autorelease];
292 testassert(SubPlusAutoreleases == 1);
293
294 [UnrealizedSubA1 retain];
295 testassert(PlusRetains == 3);
296 [UnrealizedSubA2 release];
297 testassert(PlusReleases == 3);
298 [UnrealizedSubA3 autorelease];
299 testassert(PlusAutoreleases == 3);
300#endif
301
302
303 testprintf("objc_msgSend() does not bypass\n");
304 zero();
305
306 id (*retain_fn)(id, SEL) = (id(*)(id, SEL))objc_msgSend;
307 void (*release_fn)(id, SEL) = (void(*)(id, SEL))objc_msgSend;
308 id (*autorelease_fn)(id, SEL) = (id(*)(id, SEL))objc_msgSend;
309
310 retain_fn(obj, @selector(retain));
311 testassert(Retains == 1);
312 release_fn(obj, @selector(release));
313 testassert(Releases == 1);
314 autorelease_fn(obj, @selector(autorelease));
315 testassert(Autoreleases == 1);
316
317 retain_fn(cls, @selector(retain));
318 testassert(PlusRetains == 1);
319 release_fn(cls, @selector(release));
320 testassert(PlusReleases == 1);
321 autorelease_fn(cls, @selector(autorelease));
322 testassert(PlusAutoreleases == 1);
323
324 retain_fn(inh, @selector(retain));
325 testassert(Retains == 2);
326 release_fn(inh, @selector(release));
327 testassert(Releases == 2);
328 autorelease_fn(inh, @selector(autorelease));
329 testassert(Autoreleases == 2);
330
331 retain_fn(icl, @selector(retain));
332 testassert(PlusRetains == 2);
333 release_fn(icl, @selector(release));
334 testassert(PlusReleases == 2);
335 autorelease_fn(icl, @selector(autorelease));
336 testassert(PlusAutoreleases == 2);
337
338 retain_fn(ovr, @selector(retain));
339 testassert(SubRetains == 1);
340 release_fn(ovr, @selector(release));
341 testassert(SubReleases == 1);
342 autorelease_fn(ovr, @selector(autorelease));
343 testassert(SubAutoreleases == 1);
344
345 retain_fn(ocl, @selector(retain));
346 testassert(SubPlusRetains == 1);
347 release_fn(ocl, @selector(release));
348 testassert(SubPlusReleases == 1);
349 autorelease_fn(ocl, @selector(autorelease));
350 testassert(SubPlusAutoreleases == 1);
351
352 retain_fn((Class)&OBJC_CLASS_$_UnrealizedSubB1, @selector(retain));
353 testassert(PlusRetains == 3);
354 release_fn((Class)&OBJC_CLASS_$_UnrealizedSubB2, @selector(release));
355 testassert(PlusReleases == 3);
356 autorelease_fn((Class)&OBJC_CLASS_$_UnrealizedSubB3, @selector(autorelease));
357 testassert(PlusAutoreleases == 3);
358
359
360 testprintf("arc function bypasses instance but not class or override\n");
361 zero();
362
363 objc_retain(obj);
364 testassert(Retains == 0);
365 objc_release(obj);
366 testassert(Releases == 0);
367 objc_autorelease(obj);
368 testassert(Autoreleases == 0);
369
1807f628
A
370#if SUPPORT_NONPOINTER_ISA
371 objc_retain(cls);
372 testassert(PlusRetains == 0);
373 objc_release(cls);
374 testassert(PlusReleases == 0);
375 objc_autorelease(cls);
376 testassert(PlusAutoreleases == 0);
377#else
13ba007e
A
378 objc_retain(cls);
379 testassert(PlusRetains == 1);
380 objc_release(cls);
381 testassert(PlusReleases == 1);
382 objc_autorelease(cls);
383 testassert(PlusAutoreleases == 1);
1807f628 384#endif
13ba007e
A
385
386 objc_retain(inh);
387 testassert(Retains == 0);
388 objc_release(inh);
389 testassert(Releases == 0);
390 objc_autorelease(inh);
391 testassert(Autoreleases == 0);
392
1807f628
A
393#if SUPPORT_NONPOINTER_ISA
394 objc_retain(icl);
395 testassert(PlusRetains == 0);
396 objc_release(icl);
397 testassert(PlusReleases == 0);
398 objc_autorelease(icl);
399 testassert(PlusAutoreleases == 0);
400#else
13ba007e
A
401 objc_retain(icl);
402 testassert(PlusRetains == 2);
403 objc_release(icl);
404 testassert(PlusReleases == 2);
405 objc_autorelease(icl);
406 testassert(PlusAutoreleases == 2);
1807f628 407#endif
13ba007e
A
408
409 objc_retain(ovr);
410 testassert(SubRetains == 1);
411 objc_release(ovr);
412 testassert(SubReleases == 1);
413 objc_autorelease(ovr);
414 testassert(SubAutoreleases == 1);
415
416 objc_retain(ocl);
417 testassert(SubPlusRetains == 1);
418 objc_release(ocl);
419 testassert(SubPlusReleases == 1);
420 objc_autorelease(ocl);
421 testassert(SubPlusAutoreleases == 1);
422
1807f628
A
423#if SUPPORT_NONPOINTER_ISA
424 objc_retain((Class)&OBJC_CLASS_$_UnrealizedSubC1);
425 testassert(PlusRetains == 1);
426 objc_release((Class)&OBJC_CLASS_$_UnrealizedSubC2);
427 testassert(PlusReleases == 1);
428 objc_autorelease((Class)&OBJC_CLASS_$_UnrealizedSubC3);
429 testassert(PlusAutoreleases == 1);
430#else
13ba007e
A
431 objc_retain((Class)&OBJC_CLASS_$_UnrealizedSubC1);
432 testassert(PlusRetains == 3);
433 objc_release((Class)&OBJC_CLASS_$_UnrealizedSubC2);
434 testassert(PlusReleases == 3);
435 objc_autorelease((Class)&OBJC_CLASS_$_UnrealizedSubC3);
436 testassert(PlusAutoreleases == 3);
1807f628 437#endif
13ba007e
A
438
439 testprintf("unrelated addMethod does not clobber\n");
440 zero();
441
442 class_addMethod(cls, @selector(unrelatedMethod), (IMP)imp_fn, "");
443
444 objc_retain(obj);
445 testassert(Retains == 0);
446 objc_release(obj);
447 testassert(Releases == 0);
448 objc_autorelease(obj);
449 testassert(Autoreleases == 0);
450
451
452 testprintf("add class method does not clobber\n");
453 zero();
454
455 objc_retain(obj);
456 testassert(Retains == 0);
457 objc_release(obj);
458 testassert(Releases == 0);
459 objc_autorelease(obj);
460 testassert(Autoreleases == 0);
461
462 class_addMethod(object_getClass(cls), @selector(retain), (IMP)imp_fn, "");
463
464 objc_retain(obj);
465 testassert(Retains == 0);
466 objc_release(obj);
467 testassert(Releases == 0);
468 objc_autorelease(obj);
469 testassert(Autoreleases == 0);
470
471
472 testprintf("addMethod clobbers (InheritingSub2, retain)\n");
473 zero();
474
475 ccc = [InheritingSub2 class];
476 ooo = [ccc new];
477 cc2 = [InheritingSub2_2 class];
478 oo2 = [cc2 new];
479
480 objc_retain(ooo);
481 testassert(Retains == 0);
482 objc_release(ooo);
483 testassert(Releases == 0);
484 objc_autorelease(ooo);
485 testassert(Autoreleases == 0);
486
487 objc_retain(oo2);
488 testassert(Retains == 0);
489 objc_release(oo2);
490 testassert(Releases == 0);
491 objc_autorelease(oo2);
492 testassert(Autoreleases == 0);
493
494 class_addMethod(ccc, @selector(retain), (IMP)imp_fn, "");
495
496 objc_retain(ooo);
497 testassert(Retains == 0);
498 testassert(Imps == 1);
499 objc_release(ooo);
500 testassert(Releases == 1);
501 objc_autorelease(ooo);
502 testassert(Autoreleases == 1);
503
504 objc_retain(oo2);
505 testassert(Retains == 0);
506 testassert(Imps == 2);
507 objc_release(oo2);
508 testassert(Releases == 2);
509 objc_autorelease(oo2);
510 testassert(Autoreleases == 2);
511
512
513 testprintf("addMethod clobbers (InheritingSub3, release)\n");
514 zero();
515
516 ccc = [InheritingSub3 class];
517 ooo = [ccc new];
518 cc2 = [InheritingSub3_2 class];
519 oo2 = [cc2 new];
520
521 objc_retain(ooo);
522 testassert(Retains == 0);
523 objc_release(ooo);
524 testassert(Releases == 0);
525 objc_autorelease(ooo);
526 testassert(Autoreleases == 0);
527
528 objc_retain(oo2);
529 testassert(Retains == 0);
530 objc_release(oo2);
531 testassert(Releases == 0);
532 objc_autorelease(oo2);
533 testassert(Autoreleases == 0);
534
535 class_addMethod(ccc, @selector(release), (IMP)imp_fn, "");
536
537 objc_retain(ooo);
538 testassert(Retains == 1);
539 objc_release(ooo);
540 testassert(Releases == 0);
541 testassert(Imps == 1);
542 objc_autorelease(ooo);
543 testassert(Autoreleases == 1);
544
545 objc_retain(oo2);
546 testassert(Retains == 2);
547 objc_release(oo2);
548 testassert(Releases == 0);
549 testassert(Imps == 2);
550 objc_autorelease(oo2);
551 testassert(Autoreleases == 2);
552
553
554 testprintf("addMethod clobbers (InheritingSub4, autorelease)\n");
555 zero();
556
557 ccc = [InheritingSub4 class];
558 ooo = [ccc new];
559 cc2 = [InheritingSub4_2 class];
560 oo2 = [cc2 new];
561
562 objc_retain(ooo);
563 testassert(Retains == 0);
564 objc_release(ooo);
565 testassert(Releases == 0);
566 objc_autorelease(ooo);
567 testassert(Autoreleases == 0);
568
569 objc_retain(oo2);
570 testassert(Retains == 0);
571 objc_release(oo2);
572 testassert(Releases == 0);
573 objc_autorelease(oo2);
574 testassert(Autoreleases == 0);
575
576 class_addMethod(ccc, @selector(autorelease), (IMP)imp_fn, "");
577
578 objc_retain(ooo);
579 testassert(Retains == 1);
580 objc_release(ooo);
581 testassert(Releases == 1);
582 objc_autorelease(ooo);
583 testassert(Autoreleases == 0);
584 testassert(Imps == 1);
585
586 objc_retain(oo2);
587 testassert(Retains == 2);
588 objc_release(oo2);
589 testassert(Releases == 2);
590 objc_autorelease(oo2);
591 testassert(Autoreleases == 0);
592 testassert(Imps == 2);
593
594
595 testprintf("addMethod clobbers (InheritingSub5, retainCount)\n");
596 zero();
597
598 ccc = [InheritingSub5 class];
599 ooo = [ccc new];
600 cc2 = [InheritingSub5_2 class];
601 oo2 = [cc2 new];
602
603 objc_retain(ooo);
604 testassert(Retains == 0);
605 objc_release(ooo);
606 testassert(Releases == 0);
607 objc_autorelease(ooo);
608 testassert(Autoreleases == 0);
609
610 objc_retain(oo2);
611 testassert(Retains == 0);
612 objc_release(oo2);
613 testassert(Releases == 0);
614 objc_autorelease(oo2);
615 testassert(Autoreleases == 0);
616
617 class_addMethod(ccc, @selector(retainCount), (IMP)imp_fn, "");
618
619 objc_retain(ooo);
620 testassert(Retains == 1);
621 objc_release(ooo);
622 testassert(Releases == 1);
623 objc_autorelease(ooo);
624 testassert(Autoreleases == 1);
625 // no bypassing call for -retainCount
626
627 objc_retain(oo2);
628 testassert(Retains == 2);
629 objc_release(oo2);
630 testassert(Releases == 2);
631 objc_autorelease(oo2);
632 testassert(Autoreleases == 2);
633 // no bypassing call for -retainCount
634
635
636 testprintf("setSuperclass to clean super does not clobber (InheritingSub6)\n");
637 zero();
638
639 ccc = [InheritingSub6 class];
640 ooo = [ccc new];
641 cc2 = [InheritingSub6_2 class];
642 oo2 = [cc2 new];
643
644 objc_retain(ooo);
645 testassert(Retains == 0);
646 objc_release(ooo);
647 testassert(Releases == 0);
648 objc_autorelease(ooo);
649 testassert(Autoreleases == 0);
650
651 objc_retain(oo2);
652 testassert(Retains == 0);
653 objc_release(oo2);
654 testassert(Releases == 0);
655 objc_autorelease(oo2);
656 testassert(Autoreleases == 0);
657
658 class_setSuperclass(ccc, [InheritingSub class]);
659
660 objc_retain(ooo);
661 testassert(Retains == 0);
662 objc_release(ooo);
663 testassert(Releases == 0);
664 objc_autorelease(ooo);
665 testassert(Autoreleases == 0);
666
667 objc_retain(oo2);
668 testassert(Retains == 0);
669 objc_release(oo2);
670 testassert(Releases == 0);
671 objc_autorelease(oo2);
672 testassert(Autoreleases == 0);
673
674
675 testprintf("setSuperclass to dirty super clobbers (InheritingSub7)\n");
676 zero();
677
678 ccc = [InheritingSub7 class];
679 ooo = [ccc new];
680 cc2 = [InheritingSub7_2 class];
681 oo2 = [cc2 new];
682
683 objc_retain(ooo);
684 testassert(Retains == 0);
685 objc_release(ooo);
686 testassert(Releases == 0);
687 objc_autorelease(ooo);
688 testassert(Autoreleases == 0);
689
690 objc_retain(oo2);
691 testassert(Retains == 0);
692 objc_release(oo2);
693 testassert(Releases == 0);
694 objc_autorelease(oo2);
695 testassert(Autoreleases == 0);
696
697 class_setSuperclass(ccc, [OverridingSub class]);
698
699 objc_retain(ooo);
700 testassert(SubRetains == 1);
701 objc_release(ooo);
702 testassert(SubReleases == 1);
703 objc_autorelease(ooo);
704 testassert(SubAutoreleases == 1);
705
706 objc_retain(oo2);
707 testassert(SubRetains == 2);
708 objc_release(oo2);
709 testassert(SubReleases == 2);
710 objc_autorelease(oo2);
711 testassert(SubAutoreleases == 2);
712
713
714 testprintf("category replacement of unrelated method does not clobber (InheritingSubCat)\n");
715 zero();
716
717 ccc = [InheritingSubCat class];
718 ooo = [ccc new];
719 cc2 = [InheritingSubCat_2 class];
720 oo2 = [cc2 new];
721
722 objc_retain(ooo);
723 testassert(Retains == 0);
724 objc_release(ooo);
725 testassert(Releases == 0);
726 objc_autorelease(ooo);
727 testassert(Autoreleases == 0);
728
729 objc_retain(oo2);
730 testassert(Retains == 0);
731 objc_release(oo2);
732 testassert(Releases == 0);
733 objc_autorelease(oo2);
734 testassert(Autoreleases == 0);
735
736 dlh = dlopen("customrr-cat1.bundle", RTLD_LAZY);
737 testassert(dlh);
738
739 objc_retain(ooo);
740 testassert(Retains == 0);
741 objc_release(ooo);
742 testassert(Releases == 0);
743 objc_autorelease(ooo);
744 testassert(Autoreleases == 0);
745
746 objc_retain(oo2);
747 testassert(Retains == 0);
748 objc_release(oo2);
749 testassert(Releases == 0);
750 objc_autorelease(oo2);
751 testassert(Autoreleases == 0);
752
753
754 testprintf("category replacement clobbers (InheritingSubCat)\n");
755 zero();
756
757 ccc = [InheritingSubCat class];
758 ooo = [ccc new];
759 cc2 = [InheritingSubCat_2 class];
760 oo2 = [cc2 new];
761
762 objc_retain(ooo);
763 testassert(Retains == 0);
764 objc_release(ooo);
765 testassert(Releases == 0);
766 objc_autorelease(ooo);
767 testassert(Autoreleases == 0);
768
769 objc_retain(oo2);
770 testassert(Retains == 0);
771 objc_release(oo2);
772 testassert(Releases == 0);
773 objc_autorelease(oo2);
774 testassert(Autoreleases == 0);
775
776 dlh = dlopen("customrr-cat2.bundle", RTLD_LAZY);
777 testassert(dlh);
778
779 objc_retain(ooo);
780 testassert(Retains == 1);
781 objc_release(ooo);
782 testassert(Releases == 1);
783 objc_autorelease(ooo);
784 testassert(Autoreleases == 1);
785
786 objc_retain(oo2);
787 testassert(Retains == 2);
788 objc_release(oo2);
789 testassert(Releases == 2);
790 objc_autorelease(oo2);
791 testassert(Autoreleases == 2);
792
793
794 testprintf("allocateClassPair with clean super does not clobber\n");
795 zero();
796
797 objc_retain(inh);
798 testassert(Retains == 0);
799 objc_release(inh);
800 testassert(Releases == 0);
801 objc_autorelease(inh);
802 testassert(Autoreleases == 0);
803
804 ccc = objc_allocateClassPair([InheritingSub class], "CleanClassPair", 0);
805 objc_registerClassPair(ccc);
806 ooo = [ccc new];
807
808 objc_retain(inh);
809 testassert(Retains == 0);
810 objc_release(inh);
811 testassert(Releases == 0);
812 objc_autorelease(inh);
813 testassert(Autoreleases == 0);
814
815 objc_retain(ooo);
816 testassert(Retains == 0);
817 objc_release(ooo);
818 testassert(Releases == 0);
819 objc_autorelease(ooo);
820 testassert(Autoreleases == 0);
821
822
823 testprintf("allocateClassPair with clobbered super clobbers\n");
824 zero();
825
826 ccc = objc_allocateClassPair([OverridingSub class], "DirtyClassPair", 0);
827 objc_registerClassPair(ccc);
828 ooo = [ccc new];
829
830 objc_retain(ooo);
831 testassert(SubRetains == 1);
832 objc_release(ooo);
833 testassert(SubReleases == 1);
834 objc_autorelease(ooo);
835 testassert(SubAutoreleases == 1);
836
837
838 testprintf("allocateClassPair with clean super and override clobbers\n");
839 zero();
840
841 ccc = objc_allocateClassPair([InheritingSub class], "Dirty2ClassPair", 0);
842 class_addMethod(ccc, @selector(autorelease), (IMP)imp_fn, "");
843 objc_registerClassPair(ccc);
844 ooo = [ccc new];
845
846 objc_retain(ooo);
847 testassert(Retains == 1);
848 objc_release(ooo);
849 testassert(Releases == 1);
850 objc_autorelease(ooo);
851 testassert(Autoreleases == 0);
852 testassert(Imps == 1);
853
854
855 // method_setImplementation and method_exchangeImplementations only
856 // clobber when manipulating NSObject. We can only test one at a time.
857 // To test both, we need two tests: customrr and customrr2.
858
859 // These tests also check recursive clobber.
860
861#if TEST_EXCHANGEIMPLEMENTATIONS
862 testprintf("exchangeImplementations clobbers (recursive)\n");
863#else
864 testprintf("setImplementation clobbers (recursive)\n");
865#endif
866 zero();
867
868 objc_retain(obj);
869 testassert(Retains == 0);
870 objc_release(obj);
871 testassert(Releases == 0);
872 objc_autorelease(obj);
873 testassert(Autoreleases == 0);
874
875 objc_retain(inh);
876 testassert(Retains == 0);
877 objc_release(inh);
878 testassert(Releases == 0);
879 objc_autorelease(inh);
880 testassert(Autoreleases == 0);
881
882 Method meth = class_getInstanceMethod(cls, @selector(retainCount));
883 testassert(meth);
884#if TEST_EXCHANGEIMPLEMENTATIONS
885 method_exchangeImplementations(meth, meth);
886#else
887 method_setImplementation(meth, (IMP)imp_fn);
888#endif
889
890 objc_retain(obj);
891 testassert(Retains == 1);
892 objc_release(obj);
893 testassert(Releases == 1);
894 objc_autorelease(obj);
895 testassert(Autoreleases == 1);
896
897 objc_retain(inh);
898 testassert(Retains == 2);
899 objc_release(inh);
900 testassert(Releases == 2);
901 objc_autorelease(inh);
902 testassert(Autoreleases == 2);
903
904
905 // do not add more tests here - the recursive test must be LAST
906
907 succeed(basename(argv[0]));
908}