5 #include <objc/runtime.h>
7 @interface Super : TestRoot @end
9 -(int)superMethod { return 0; }
10 -(int)bothMethod { return 0; }
13 @interface Sub : Super @end
15 -(int)subMethod { return 0; }
16 -(int)bothMethod { return 0; }
19 @interface Sub2 : Super @end
21 -(int)subMethod { return 0; }
22 -(int)bothMethod { return 0; }
26 id fn(id self __attribute__((unused)), SEL cmd __attribute__((unused)), ...) { return nil; }
30 IMP superMethodFromSuper = class_getMethodImplementation([Super class], @selector(superMethod));
31 IMP bothMethodFromSuper = class_getMethodImplementation([Super class], @selector(bothMethod));
32 IMP subMethodFromSub = class_getMethodImplementation([Sub class], @selector(subMethod));
33 IMP bothMethodFromSub = class_getMethodImplementation([Sub class], @selector(bothMethod));
34 IMP subMethodFromSub2 = class_getMethodImplementation([Sub2 class], @selector(subMethod));
35 IMP bothMethodFromSub2 = class_getMethodImplementation([Sub2 class], @selector(bothMethod));
37 testassert(superMethodFromSuper);
38 testassert(bothMethodFromSuper);
39 testassert(subMethodFromSub);
40 testassert(bothMethodFromSub);
41 testassert(subMethodFromSub2);
42 testassert(bothMethodFromSub2);
47 // class_addMethod doesn't replace existing implementations
48 ok = class_addMethod([Super class], @selector(superMethod), (IMP)fn, NULL);
50 testassert(class_getMethodImplementation([Super class], @selector(superMethod)) == superMethodFromSuper);
52 // class_addMethod does override superclass implementations
53 ok = class_addMethod([Sub class], @selector(superMethod), (IMP)fn, NULL);
55 testassert(class_getMethodImplementation([Sub class], @selector(superMethod)) == (IMP)fn);
57 // class_addMethod does add root implementations
58 ok = class_addMethod([Super class], @selector(superMethodNew2), (IMP)fn, NULL);
60 testassert(class_getMethodImplementation([Super class], @selector(superMethodNew2)) == (IMP)fn);
61 testassert(class_getMethodImplementation([Sub class], @selector(superMethodNew2)) == (IMP)fn);
64 // class_replaceMethod does add new implementations,
65 // returning NULL if super has an implementation
66 imp = class_replaceMethod([Sub2 class], @selector(superMethod), (IMP)fn, NULL);
67 testassert(imp == NULL);
68 testassert(class_getMethodImplementation([Sub2 class], @selector(superMethod)) == (IMP)fn);
70 // class_replaceMethod does add new implementations,
71 // returning NULL if super has no implementation
72 imp = class_replaceMethod([Sub2 class], @selector(subMethodNew), (IMP)fn, NULL);
73 testassert(imp == NULL);
74 testassert(class_getMethodImplementation([Sub2 class], @selector(subMethodNew)) == (IMP)fn);
76 // class_replaceMethod does add new implemetations
77 // returning NULL if there is no super class
78 imp = class_replaceMethod([Super class], @selector(superMethodNew), (IMP)fn, NULL);
79 testassert(imp == NULL);
80 testassert(class_getMethodImplementation([Super class], @selector(superMethodNew)) == (IMP)fn);
83 // class_replaceMethod does replace existing implementations,
84 // returning existing implementation (regardless of super)
85 imp = class_replaceMethod([Sub2 class], @selector(subMethod), (IMP)fn, NULL);
86 testassert(imp == subMethodFromSub2);
87 testassert(class_getMethodImplementation([Sub2 class], @selector(subMethod)) == (IMP)fn);
89 // class_replaceMethod does replace existing implemetations,
90 // returning existing implementation (regardless of super)
91 imp = class_replaceMethod([Sub2 class], @selector(bothMethod), (IMP)fn, NULL);
92 testassert(imp == bothMethodFromSub2);
93 testassert(class_getMethodImplementation([Sub2 class], @selector(bothMethod)) == (IMP)fn);
95 // class_replaceMethod does replace existing implemetations,
96 // returning existing implementation (regardless of super)
97 imp = class_replaceMethod([Super class], @selector(superMethod), (IMP)fn, NULL);
98 testassert(imp == superMethodFromSuper);
99 testassert(class_getMethodImplementation([Super class], @selector(superMethod)) == (IMP)fn);
101 // fixme actually try calling them