1// TEST_CFLAGS -Wl,-no_objc_category_merging 2 3#include "test.h" 4#include "testroot.i" 5#include <string.h> 6#include <objc/runtime.h> 7 8static int state = 0; 9 10@interface Super : TestRoot @end 11@implementation Super 12-(void)instancemethod { fail("-instancemethod not overridden by category"); } 13+(void)method { fail("+method not overridden by category"); } 14@end 15 16@interface Super (Category) @end 17@implementation Super (Category) 18+(void)method { 19 testprintf("in [Super(Category) method]\n"); 20 testassert(self == [Super class]); 21 testassert(state == 0); 22 state = 1; 23} 24-(void)instancemethod { 25 testprintf("in [Super(Category) instancemethod]\n"); 26 testassert(object_getClass(self) == [Super class]); 27 testassert(state == 1); 28 state = 2; 29} 30@end 31 32@interface Super (PropertyCategory) 33@property int i; 34@end 35@implementation Super (PropertyCategory) 36- (int)i { return 0; } 37- (void)setI:(int)value { (void)value; } 38@end 39 40// rdar://5086110 memory smasher in category with class method and property 41@interface Super (r5086110) 42@property int property5086110; 43@end 44@implementation Super (r5086110) 45+(void)method5086110 { 46 fail("method method5086110 called!"); 47} 48- (int)property5086110 { fail("property5086110 called!"); return 0; } 49- (void)setProperty5086110:(int)value { fail("setProperty5086110 called!"); (void)value; } 50@end 51 52 53@interface PropertyClass : Super { 54 int q; 55} 56@property(readonly) int q; 57@end 58@implementation PropertyClass 59@synthesize q; 60@end 61 62@interface PropertyClass (PropertyCategory) 63@property int q; 64@end 65@implementation PropertyClass (PropertyCategory) 66@dynamic q; 67@end 68 69 70int main() 71{ 72 // methods introduced by category 73 state = 0; 74 [Super method]; 75 [[Super new] instancemethod]; 76 testassert(state == 2); 77 78 // property introduced by category 79 objc_property_t p = class_getProperty([Super class], "i"); 80 testassert(p); 81 testassert(0 == strcmp(property_getName(p), "i")); 82 testassert(property_getAttributes(p)); 83 84 // methods introduced by category's property 85 Method m; 86 m = class_getInstanceMethod([Super class], @selector(i)); 87 testassert(m); 88 m = class_getInstanceMethod([Super class], @selector(setI:)); 89 testassert(m); 90 91 // class's property shadowed by category's property 92 objc_property_t *plist = class_copyPropertyList([PropertyClass class], NULL); 93 testassert(plist); 94 testassert(plist[0]); 95 testassert(0 == strcmp(property_getName(plist[0]), "q")); 96 testassert(0 == strcmp(property_getAttributes(plist[0]), "Ti,D")); 97 testassert(plist[1]); 98 testassert(0 == strcmp(property_getName(plist[1]), "q")); 99 testassert(0 == strcmp(property_getAttributes(plist[1]), "Ti,R,Vq")); 100 testassert(!plist[2]); 101 free(plist); 102 103 succeed(__FILE__); 104} 105 106