]> git.saurik.com Git - apple/objc4.git/blobdiff - test/getMethod.m
objc4-756.2.tar.gz
[apple/objc4.git] / test / getMethod.m
diff --git a/test/getMethod.m b/test/getMethod.m
new file mode 100644 (file)
index 0000000..3777329
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+TEST_BUILD_OUTPUT
+.*getMethod.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
+.*getMethod.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
+.*getMethod.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
+.*getMethod.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
+END
+*/
+
+#include "test.h"
+#include "testroot.i"
+#include <objc/runtime.h>
+#include <objc/message.h>
+
+static int state = 0;
+
+@interface Super : TestRoot @end
+@implementation Super
++(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
+
+typedef void (*imp_t)(id, SEL);
+
+int main()
+{
+    Class Super_cls, Sub_cls;
+    Class buf[10];
+    Method m;
+    SEL sel;
+    IMP imp;
+
+    id bufobj = (__bridge_transfer id)(void*)buf;
+    
+    // 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(object_getClass(Super_cls), sel));
+    testassert(imp == object_getMethodImplementation(Super_cls, sel));
+    state = 0;
+    (*(imp_t)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(object_getClass(Sub_cls), sel));
+    testassert(imp == object_getMethodImplementation(Sub_cls, sel));
+    state = 0;
+    (*(imp_t)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(object_getClass(Sub_cls), sel));
+    testassert(imp == object_getMethodImplementation(Sub_cls, sel));
+    state = 0;
+    (*(imp_t)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));
+    buf[0] = Super_cls;
+    testassert(imp == object_getMethodImplementation(bufobj, sel));
+    state = 0;
+    (*(imp_t)imp)(bufobj, 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));
+    buf[0] = Sub_cls;
+    testassert(imp == object_getMethodImplementation(bufobj, sel));
+    state = 0;
+    (*(imp_t)imp)(bufobj, 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));
+    buf[0] = Sub_cls;
+    testassert(imp == object_getMethodImplementation(bufobj, sel));
+    state = 0;
+    (*(imp_t)imp)(bufobj, sel);
+    testassert(state == 6);
+
+    // check class_getClassMethod(cls) == class_getInstanceMethod(cls->isa)
+    sel = sel_registerName("classMethod");
+    testassert(class_getClassMethod(Sub_cls, sel) == class_getInstanceMethod(object_getClass(Sub_cls), 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);
+    buf[0] = Sub_cls;
+    testassert(object_getMethodImplementation(bufobj, sel) == (IMP)&_objc_msgForward);
+#if !__arm64__
+    testassert(class_getMethodImplementation_stret(Sub_cls, sel) == (IMP)&_objc_msgForward_stret);
+    testassert(object_getMethodImplementation_stret(bufobj, sel) == (IMP)&_objc_msgForward_stret);
+#endif
+
+    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__);
+}