// TEST_CONFIG
#include "test.h"
#include <objc/runtime.h>
#include <objc/message.h>
static int state = 0;
@interface Super { id isa; } @end
@implementation Super
+class { return self; }
+(void)initialize { }
+(void)classMethod { state = 1; }
-(void)instanceMethod { state = 4; }
+(void)classMethodSuperOnly { state = 3; }
-(void)instanceMethodSuperOnly { state = 6; }
@end
@interface Sub : Super @end
@implementation Sub
+(void)classMethod { state = 2; }
-(void)instanceMethod { state = 5; }
@end
int main()
{
Class Super_cls, Sub_cls;
Class buf[10];
Method m;
SEL sel;
IMP imp;
// don't use [Super class] to check laziness handing
Super_cls = objc_getClass("Super");
Sub_cls = objc_getClass("Sub");
sel = sel_registerName("classMethod");
m = class_getClassMethod(Super_cls, sel);
testassert(m);
testassert(sel == method_getName(m));
imp = method_getImplementation(m);
testassert(imp == class_getMethodImplementation(Super_cls->isa, sel));
state = 0;
(*imp)(Super_cls, sel);
testassert(state == 1);
sel = sel_registerName("classMethod");
m = class_getClassMethod(Sub_cls, sel);
testassert(m);
testassert(sel == method_getName(m));
imp = method_getImplementation(m);
testassert(imp == class_getMethodImplementation(Sub_cls->isa, sel));
state = 0;
(*imp)(Sub_cls, sel);
testassert(state == 2);
sel = sel_registerName("classMethodSuperOnly");
m = class_getClassMethod(Sub_cls, sel);
testassert(m);
testassert(sel == method_getName(m));
imp = method_getImplementation(m);
testassert(imp == class_getMethodImplementation(Sub_cls->isa, sel));
state = 0;
(*imp)(Sub_cls, sel);
testassert(state == 3);
sel = sel_registerName("instanceMethod");
m = class_getInstanceMethod(Super_cls, sel);
testassert(m);
testassert(sel == method_getName(m));
imp = method_getImplementation(m);
testassert(imp == class_getMethodImplementation(Super_cls, sel));
state = 0;
buf[0] = Super_cls;
(*imp)((Super *)buf, sel);
testassert(state == 4);
sel = sel_registerName("instanceMethod");
m = class_getInstanceMethod(Sub_cls, sel);
testassert(m);
testassert(sel == method_getName(m));
imp = method_getImplementation(m);
testassert(imp == class_getMethodImplementation(Sub_cls, sel));
state = 0;
buf[0] = Sub_cls;
(*imp)((Sub *)buf, sel);
testassert(state == 5);
sel = sel_registerName("instanceMethodSuperOnly");
m = class_getInstanceMethod(Sub_cls, sel);
testassert(m);
testassert(sel == method_getName(m));
imp = method_getImplementation(m);
testassert(imp == class_getMethodImplementation(Sub_cls, sel));
state = 0;
buf[0] = Sub_cls;
(*imp)((Sub *)buf, sel);
testassert(state == 6);
// check class_getClassMethod(cls) == class_getInstanceMethod(cls->isa)
sel = sel_registerName("classMethod");
testassert(class_getClassMethod(Sub_cls, sel) == class_getInstanceMethod(Sub_cls->isa, sel));
sel = sel_registerName("nonexistent");
testassert(! class_getInstanceMethod(Sub_cls, sel));
testassert(! class_getClassMethod(Sub_cls, sel));
testassert(class_getMethodImplementation(Sub_cls, sel) == (IMP)&_objc_msgForward);
testassert(class_getMethodImplementation_stret(Sub_cls, sel) == (IMP)&_objc_msgForward_stret);
testassert(! class_getInstanceMethod(NULL, NULL));
testassert(! class_getInstanceMethod(NULL, sel));
testassert(! class_getInstanceMethod(Sub_cls, NULL));
testassert(! class_getClassMethod(NULL, NULL));
testassert(! class_getClassMethod(NULL, sel));
testassert(! class_getClassMethod(Sub_cls, NULL));
succeed(__FILE__);
}