4 #include <objc/runtime.h>
6 @interface Super { @public id isa; } @end
9 +class { return self; }
10 +(id) new { return class_createInstance(self, 0); }
12 -(int)superMethod { return 0; }
13 -(int)bothMethod { return 0; }
16 @interface Sub : Super @end
18 -(int)subMethod { return 0; }
19 -(int)bothMethod { return 0; }
22 @interface Sub2 : Super @end
24 -(int)subMethod { return 0; }
25 -(int)bothMethod { return 0; }
29 id fn(id self __attribute__((unused)), SEL cmd __attribute__((unused)), ...) { return nil; }
33 IMP superMethodFromSuper = class_getMethodImplementation([Super class], @selector(superMethod));
34 IMP bothMethodFromSuper = class_getMethodImplementation([Super class], @selector(bothMethod));
35 IMP subMethodFromSub = class_getMethodImplementation([Sub class], @selector(subMethod));
36 IMP bothMethodFromSub = class_getMethodImplementation([Sub class], @selector(bothMethod));
37 IMP subMethodFromSub2 = class_getMethodImplementation([Sub2 class], @selector(subMethod));
38 IMP bothMethodFromSub2 = class_getMethodImplementation([Sub2 class], @selector(bothMethod));
40 testassert(superMethodFromSuper);
41 testassert(bothMethodFromSuper);
42 testassert(subMethodFromSub);
43 testassert(bothMethodFromSub);
44 testassert(subMethodFromSub2);
45 testassert(bothMethodFromSub2);
50 // class_addMethod doesn't replace existing implementations
51 ok = class_addMethod([Super class], @selector(superMethod), &fn, NULL);
53 testassert(class_getMethodImplementation([Super class], @selector(superMethod)) == superMethodFromSuper);
55 // class_addMethod does override superclass implementations
56 ok = class_addMethod([Sub class], @selector(superMethod), &fn, NULL);
58 testassert(class_getMethodImplementation([Sub class], @selector(superMethod)) == &fn);
60 // class_addMethod does add root implementations
61 ok = class_addMethod([Super class], @selector(superMethodNew2), &fn, NULL);
63 testassert(class_getMethodImplementation([Super class], @selector(superMethodNew2)) == &fn);
64 testassert(class_getMethodImplementation([Sub class], @selector(superMethodNew2)) == &fn);
67 // class_replaceMethod does add new implementations,
68 // returning NULL if super has an implementation
69 imp = class_replaceMethod([Sub2 class], @selector(superMethod), &fn, NULL);
70 testassert(imp == NULL);
71 testassert(class_getMethodImplementation([Sub2 class], @selector(superMethod)) == fn);
73 // class_replaceMethod does add new implementations,
74 // returning NULL if super has no implementation
75 imp = class_replaceMethod([Sub2 class], @selector(subMethodNew), &fn, NULL);
76 testassert(imp == NULL);
77 testassert(class_getMethodImplementation([Sub2 class], @selector(subMethodNew)) == fn);
79 // class_replaceMethod does add new implemetations
80 // returning NULL if there is no super class
81 imp = class_replaceMethod([Super class], @selector(superMethodNew), &fn, NULL);
82 testassert(imp == NULL);
83 testassert(class_getMethodImplementation([Super class], @selector(superMethodNew)) == fn);
86 // class_replaceMethod does replace existing implementations,
87 // returning existing implementation (regardless of super)
88 imp = class_replaceMethod([Sub2 class], @selector(subMethod), &fn, NULL);
89 testassert(imp == subMethodFromSub2);
90 testassert(class_getMethodImplementation([Sub2 class], @selector(subMethod)) == fn);
92 // class_replaceMethod does replace existing implemetations,
93 // returning existing implementation (regardless of super)
94 imp = class_replaceMethod([Sub2 class], @selector(bothMethod), &fn, NULL);
95 testassert(imp == bothMethodFromSub2);
96 testassert(class_getMethodImplementation([Sub2 class], @selector(bothMethod)) == fn);
98 // class_replaceMethod does replace existing implemetations,
99 // returning existing implementation (regardless of super)
100 imp = class_replaceMethod([Super class], @selector(superMethod), &fn, NULL);
101 testassert(imp == superMethodFromSuper);
102 testassert(class_getMethodImplementation([Super class], @selector(superMethod)) == fn);
104 // fixme actually try calling them