darling-objc4/test/duplicateClass.m
2020-06-09 21:50:17 -04:00

151 lines
3.5 KiB
Objective-C

// TEST_CFLAGS -Wno-deprecated-declarations -Wl,-no_objc_category_merging
#include "test.h"
#include "testroot.i"
#include <objc/runtime.h>
static int state;
@protocol Proto
+(void)classMethod;
-(void)instanceMethod;
@end
@interface Super : TestRoot <Proto> {
int i;
}
@property int i;
@end
@implementation Super
@synthesize i;
+(void)classMethod {
state = 1;
}
-(void)instanceMethod {
state = 3;
}
@end
#if __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
#endif
@implementation Super (Category)
+(void)classMethod {
state = 2;
}
-(void)instanceMethod {
state = 4;
}
@end
#if __clang__
#pragma clang diagnostic pop
#endif
int main()
{
Class clone;
Class cls;
Method *m1, *m2;
int i;
cls = [Super class];
clone = objc_duplicateClass(cls, "Super_copy", 0);
testassert(clone != cls);
testassert(object_getClass(clone) == object_getClass(cls));
testassert(class_getSuperclass(clone) == class_getSuperclass(cls));
testassert(class_getVersion(clone) == class_getVersion(cls));
testassert(class_isMetaClass(clone) == class_isMetaClass(cls));
testassert(class_getIvarLayout(clone) == class_getIvarLayout(cls));
testassert(class_getWeakIvarLayout(clone) == class_getWeakIvarLayout(cls));
// Check method list
m1 = class_copyMethodList(cls, NULL);
m2 = class_copyMethodList(clone, NULL);
testassert(m1);
testassert(m2);
for (i = 0; m1[i] && m2[i]; i++) {
testassert(m1[i] != m2[i]); // method list must be deep-copied
testassert(method_getName(m1[i]) == method_getName(m2[i]));
testassert(method_getImplementation(m1[i]) == method_getImplementation(m2[i]));
testassert(method_getTypeEncoding(m1[i]) == method_getTypeEncoding(m2[i]));
}
testassert(m1[i] == NULL && m2[i] == NULL);
free(m1);
free(m2);
// Check ivar list
Ivar *i1 = class_copyIvarList(cls, NULL);
Ivar *i2 = class_copyIvarList(clone, NULL);
testassert(i1);
testassert(i2);
for (i = 0; i1[i] && i2[i]; i++) {
testassert(i1[i] == i2[i]); // ivars are not deep-copied
}
testassert(i1[i] == NULL && i2[i] == NULL);
free(i1);
free(i2);
// Check protocol list
Protocol * __unsafe_unretained *p1 = class_copyProtocolList(cls, NULL);
Protocol * __unsafe_unretained *p2 = class_copyProtocolList(clone, NULL);
testassert(p1);
testassert(p2);
for (i = 0; p1[i] && p2[i]; i++) {
testassert(p1[i] == p2[i]); // protocols are not deep-copied
}
testassert(p1[i] == NULL && p2[i] == NULL);
free(p1);
free(p2);
// Check property list
objc_property_t *o1 = class_copyPropertyList(cls, NULL);
objc_property_t *o2 = class_copyPropertyList(clone, NULL);
testassert(o1);
testassert(o2);
for (i = 0; o1[i] && o2[i]; i++) {
testassert(o1[i] == o2[i]); // properties are not deep-copied
}
testassert(o1[i] == NULL && o2[i] == NULL);
free(o1);
free(o2);
// Check method calls
state = 0;
[cls classMethod];
testassert(state == 2);
state = 0;
[clone classMethod];
testassert(state == 2);
// #4511660 Make sure category implementation is still the preferred one
id obj;
obj = [cls new];
state = 0;
[obj instanceMethod];
testassert(state == 4);
RELEASE_VAR(obj);
obj = [clone new];
state = 0;
[obj instanceMethod];
testassert(state == 4);
RELEASE_VAR(obj);
succeed(__FILE__);
}