// TEST_CONFIG
#include "test.h"
#include <string.h>
#include <objc/objc-runtime.h>
static int state = 0;
@interface Super { id isa; } @end
@implementation Super
+(void)initialize { }
+class { return self; }
-(void)instancemethod { fail("-instancemethod not overridden by category"); }
+(void)method { fail("+method not overridden by category"); }
@end
@interface Super (Category) @end
@implementation Super (Category)
+(void)method {
testprintf("in [Super(Category) method]\n");
testassert(self == [Super class]);
testassert(state == 0);
state = 1;
}
-(void)instancemethod {
testprintf("in [Super(Category) instancemethod]\n");
testassert(self->isa == [Super class]);
testassert(state == 1);
state = 2;
}
@end
@interface Super (PropertyCategory)
@property int i;
@end
@implementation Super (PropertyCategory)
- (int)i { return 0; }
- (void)setI:(int)value { (void)value; }
@end
// rdar://5086110 memory smasher in category with class method and property
@interface Super (r5086110)
@property int property5086110;
@end
@implementation Super (r5086110)
+(void)method5086110 {
fail("method method5086110 called!");
}
- (int)property5086110 { fail("property5086110 called!"); return 0; }
- (void)setProperty5086110:(int)value { fail("setProperty5086110 called!"); (void)value; }
@end
@interface PropertyClass : Super {
int q;
}
@property(readonly) int q;
@end
@implementation PropertyClass
@synthesize q;
@end
@interface PropertyClass (PropertyCategory)
@property int q;
@end
@implementation PropertyClass (PropertyCategory)
@dynamic q;
@end
int main()
{
id buf[10] = {0};
// methods introduced by category
state = 0;
[Super method];
buf[0] = [Super class];
[(Super *)buf instancemethod];
testassert(state == 2);
// property introduced by category
objc_property_t p = class_getProperty([Super class], "i");
testassert(p);
testassert(0 == strcmp(property_getName(p), "i"));
testassert(property_getAttributes(p));
// methods introduced by category's property
Method m;
m = class_getInstanceMethod([Super class], @selector(i));
testassert(m);
m = class_getInstanceMethod([Super class], @selector(setI:));
testassert(m);
// class's property shadowed by category's property
objc_property_t *plist = class_copyPropertyList([PropertyClass class], NULL);
testassert(plist);
testassert(plist[0]);
testassert(0 == strcmp(property_getName(plist[0]), "q"));
testassert(0 == strcmp(property_getAttributes(plist[0]), "Ti,D"));
testassert(plist[1]);
testassert(0 == strcmp(property_getName(plist[1]), "q"));
testassert(0 == strcmp(property_getAttributes(plist[1]), "Ti,R,Vq"));
testassert(!plist[2]);
free(plist);
succeed(__FILE__);
}