X-Git-Url: https://git.saurik.com/apple/objc4.git/blobdiff_plain/7c0e6487d7b67b6bf6c632300ee4b74e8950b051..7af964d1562d70f51a8e9aca24215ac3d83d0624:/test/copyMethodList.m diff --git a/test/copyMethodList.m b/test/copyMethodList.m new file mode 100644 index 0000000..b050f40 --- /dev/null +++ b/test/copyMethodList.m @@ -0,0 +1,146 @@ +#include "test.h" +#include +#include + +@interface SuperMethods { } @end +@implementation SuperMethods ++(void)SuperMethodClass { } ++(void)SuperMethodClass2 { } +-(void)SuperMethodInstance { } +-(void)SuperMethodInstance2 { } +@end + +@interface SubMethods { } @end +@implementation SubMethods ++(void)SubMethodClass { } ++(void)SubMethodClass2 { } +-(void)SubMethodInstance { } +-(void)SubMethodInstance2 { } +@end + +@interface SuperMethods (Category) @end +@implementation SuperMethods (Category) ++(void)SuperMethodClassCat { } ++(void)SuperMethodClassCat2 { } +-(void)SuperMethodInstanceCat { } +-(void)SuperMethodInstanceCat2 { } +@end + +@interface SubMethods (Category) @end +@implementation SubMethods (Category) ++(void)SubMethodClassCat { } ++(void)SubMethodClassCat2 { } +-(void)SubMethodInstanceCat { } +-(void)SubMethodInstanceCat2 { } +@end + + +@interface FourMethods @end +@implementation FourMethods +-(void)one { } +-(void)two { } +-(void)three { } +-(void)four { } +@end + +@interface NoMethods @end +@implementation NoMethods @end + +static int isNamed(Method m, const char *name) +{ + return (method_getName(m) == sel_registerName(name)); +} + +int main() +{ + // Class SubMethods has not yet been touched, so runtime must attach + // the lazy categories + Method *methods; + unsigned int count; + Class cls; + + cls = objc_getClass("SubMethods"); + testassert(cls); + + testprintf("calling class_copyMethodList(SubMethods) (should be unmethodized)\n"); + + count = 100; + methods = class_copyMethodList(cls, &count); + testassert(methods); + testassert(count == 4); + // First two methods should be the category methods, + // followed by the class methods + testassert((isNamed(methods[0], "SubMethodInstanceCat") && + isNamed(methods[1], "SubMethodInstanceCat2")) + || + (isNamed(methods[1], "SubMethodInstanceCat") && + isNamed(methods[0], "SubMethodInstanceCat2"))); + testassert((isNamed(methods[2], "SubMethodInstance") && + isNamed(methods[3], "SubMethodInstance2")) + || + (isNamed(methods[3], "SubMethodInstance") && + isNamed(methods[2], "SubMethodInstance2"))); + // methods[] should be null-terminated + testassert(methods[4] == NULL); + free(methods); + + testprintf("calling class_copyMethodList(SubMethods(meta)) (should be unmethodized)\n"); + + count = 100; + methods = class_copyMethodList(cls->isa, &count); + testassert(methods); + testassert(count == 4); + // First two methods should be the category methods, + // followed by the class methods + testassert((isNamed(methods[0], "SubMethodClassCat") && + isNamed(methods[1], "SubMethodClassCat2")) + || + (isNamed(methods[1], "SubMethodClassCat") && + isNamed(methods[0], "SubMethodClassCat2"))); + testassert((isNamed(methods[2], "SubMethodClass") && + isNamed(methods[3], "SubMethodClass2")) + || + (isNamed(methods[3], "SubMethodClass") && + isNamed(methods[2], "SubMethodClass2"))); + // methods[] should be null-terminated + testassert(methods[4] == NULL); + free(methods); + + // Check null-termination - this method list block would be 16 bytes + // if it weren't for the terminator + count = 100; + cls = objc_getClass("FourMethods"); + methods = class_copyMethodList(cls, &count); + testassert(methods); + testassert(count == 4); + testassert(malloc_size(methods) >= 5 * sizeof(Method)); + testassert(methods[3] != NULL); + testassert(methods[4] == NULL); + free(methods); + + // Check NULL count parameter + methods = class_copyMethodList(cls, NULL); + testassert(methods); + testassert(methods[4] == NULL); + testassert(methods[3] != NULL); + free(methods); + + // Check NULL class parameter + count = 100; + methods = class_copyMethodList(NULL, &count); + testassert(!methods); + testassert(count == 0); + + // Check NULL class and count + methods = class_copyMethodList(NULL, NULL); + testassert(!methods); + + // Check class with no methods + count = 100; + cls = objc_getClass("NoMethods"); + methods = class_copyMethodList(cls, &count); + testassert(!methods); + testassert(count == 0); + + succeed(__FILE__); +}