X-Git-Url: https://git.saurik.com/apple/objc4.git/blobdiff_plain/7c0e6487d7b67b6bf6c632300ee4b74e8950b051..7af964d1562d70f51a8e9aca24215ac3d83d0624:/test/addMethod.m diff --git a/test/addMethod.m b/test/addMethod.m new file mode 100644 index 0000000..2608b51 --- /dev/null +++ b/test/addMethod.m @@ -0,0 +1,105 @@ +#include "test.h" +#include + +@interface Super { @public id isa; } @end +@implementation Super ++(void)initialize { } ++class { return self; } ++(id) new { return class_createInstance(self, 0); } + +-(int)superMethod { return 0; } +-(int)bothMethod { return 0; } +@end + +@interface Sub : Super @end +@implementation Sub +-(int)subMethod { return 0; } +-(int)bothMethod { return 0; } +@end + +@interface Sub2 : Super @end +@implementation Sub2 +-(int)subMethod { return 0; } +-(int)bothMethod { return 0; } +@end + + +id fn(id self __attribute__((unused)), SEL cmd __attribute__((unused)), ...) { return nil; } + +int main() +{ + IMP superMethodFromSuper = class_getMethodImplementation([Super class], @selector(superMethod)); + IMP bothMethodFromSuper = class_getMethodImplementation([Super class], @selector(bothMethod)); + IMP subMethodFromSub = class_getMethodImplementation([Sub class], @selector(subMethod)); + IMP bothMethodFromSub = class_getMethodImplementation([Sub class], @selector(bothMethod)); + IMP subMethodFromSub2 = class_getMethodImplementation([Sub2 class], @selector(subMethod)); + IMP bothMethodFromSub2 = class_getMethodImplementation([Sub2 class], @selector(bothMethod)); + + testassert(superMethodFromSuper); + testassert(bothMethodFromSuper); + testassert(subMethodFromSub); + testassert(bothMethodFromSub); + testassert(subMethodFromSub2); + testassert(bothMethodFromSub2); + + BOOL ok; + IMP imp; + + // class_addMethod doesn't replace existing implementations + ok = class_addMethod([Super class], @selector(superMethod), &fn, NULL); + testassert(!ok); + testassert(class_getMethodImplementation([Super class], @selector(superMethod)) == superMethodFromSuper); + + // class_addMethod does override superclass implementations + ok = class_addMethod([Sub class], @selector(superMethod), &fn, NULL); + testassert(ok); + testassert(class_getMethodImplementation([Sub class], @selector(superMethod)) == &fn); + + // class_addMethod does add root implementations + ok = class_addMethod([Super class], @selector(superMethodNew2), &fn, NULL); + testassert(ok); + testassert(class_getMethodImplementation([Super class], @selector(superMethodNew2)) == &fn); + testassert(class_getMethodImplementation([Sub class], @selector(superMethodNew2)) == &fn); + + + // class_replaceMethod does add new implementations, + // returning NULL if super has an implementation + imp = class_replaceMethod([Sub2 class], @selector(superMethod), &fn, NULL); + testassert(imp == NULL); + testassert(class_getMethodImplementation([Sub2 class], @selector(superMethod)) == fn); + + // class_replaceMethod does add new implementations, + // returning NULL if super has no implementation + imp = class_replaceMethod([Sub2 class], @selector(subMethodNew), &fn, NULL); + testassert(imp == NULL); + testassert(class_getMethodImplementation([Sub2 class], @selector(subMethodNew)) == fn); + + // class_replaceMethod does add new implemetations + // returning NULL if there is no super class + imp = class_replaceMethod([Super class], @selector(superMethodNew), &fn, NULL); + testassert(imp == NULL); + testassert(class_getMethodImplementation([Super class], @selector(superMethodNew)) == fn); + + + // class_replaceMethod does replace existing implementations, + // returning existing implementation (regardless of super) + imp = class_replaceMethod([Sub2 class], @selector(subMethod), &fn, NULL); + testassert(imp == subMethodFromSub2); + testassert(class_getMethodImplementation([Sub2 class], @selector(subMethod)) == fn); + + // class_replaceMethod does replace existing implemetations, + // returning existing implementation (regardless of super) + imp = class_replaceMethod([Sub2 class], @selector(bothMethod), &fn, NULL); + testassert(imp == bothMethodFromSub2); + testassert(class_getMethodImplementation([Sub2 class], @selector(bothMethod)) == fn); + + // class_replaceMethod does replace existing implemetations, + // returning existing implementation (regardless of super) + imp = class_replaceMethod([Super class], @selector(superMethod), &fn, NULL); + testassert(imp == superMethodFromSuper); + testassert(class_getMethodImplementation([Super class], @selector(superMethod)) == fn); + + // fixme actually try calling them + + succeed(__FILE__); +}