]> git.saurik.com Git - apple/objc4.git/blob - test/duplicateClass.m
objc4-756.2.tar.gz
[apple/objc4.git] / test / duplicateClass.m
1 // TEST_CFLAGS -Wno-deprecated-declarations -Wl,-no_objc_category_merging
2
3 #include "test.h"
4 #include "testroot.i"
5 #include <objc/runtime.h>
6
7 static int state;
8
9 @protocol Proto
10 +(void)classMethod;
11 -(void)instanceMethod;
12 @end
13
14 @interface Super : TestRoot <Proto> {
15 int i;
16 }
17 @property int i;
18 @end
19
20 @implementation Super
21 @synthesize i;
22
23 +(void)classMethod {
24 state = 1;
25 }
26
27 -(void)instanceMethod {
28 state = 3;
29 }
30
31 @end
32
33
34 #if __clang__
35 #pragma clang diagnostic push
36 #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
37 #endif
38
39 @implementation Super (Category)
40
41 +(void)classMethod {
42 state = 2;
43 }
44
45 -(void)instanceMethod {
46 state = 4;
47 }
48
49 @end
50
51 #if __clang__
52 #pragma clang diagnostic pop
53 #endif
54
55
56 int main()
57 {
58 Class clone;
59 Class cls;
60 Method *m1, *m2;
61 int i;
62
63 cls = [Super class];
64 clone = objc_duplicateClass(cls, "Super_copy", 0);
65
66 testassert(clone != cls);
67 testassert(object_getClass(clone) == object_getClass(cls));
68 testassert(class_getSuperclass(clone) == class_getSuperclass(cls));
69 testassert(class_getVersion(clone) == class_getVersion(cls));
70 testassert(class_isMetaClass(clone) == class_isMetaClass(cls));
71 testassert(class_getIvarLayout(clone) == class_getIvarLayout(cls));
72 testassert(class_getWeakIvarLayout(clone) == class_getWeakIvarLayout(cls));
73
74 // Check method list
75
76 m1 = class_copyMethodList(cls, NULL);
77 m2 = class_copyMethodList(clone, NULL);
78 testassert(m1);
79 testassert(m2);
80 for (i = 0; m1[i] && m2[i]; i++) {
81 testassert(m1[i] != m2[i]); // method list must be deep-copied
82 testassert(method_getName(m1[i]) == method_getName(m2[i]));
83 testassert(method_getImplementation(m1[i]) == method_getImplementation(m2[i]));
84 testassert(method_getTypeEncoding(m1[i]) == method_getTypeEncoding(m2[i]));
85 }
86 testassert(m1[i] == NULL && m2[i] == NULL);
87 free(m1);
88 free(m2);
89
90 // Check ivar list
91 Ivar *i1 = class_copyIvarList(cls, NULL);
92 Ivar *i2 = class_copyIvarList(clone, NULL);
93 testassert(i1);
94 testassert(i2);
95 for (i = 0; i1[i] && i2[i]; i++) {
96 testassert(i1[i] == i2[i]); // ivars are not deep-copied
97 }
98 testassert(i1[i] == NULL && i2[i] == NULL);
99 free(i1);
100 free(i2);
101
102 // Check protocol list
103 Protocol * __unsafe_unretained *p1 = class_copyProtocolList(cls, NULL);
104 Protocol * __unsafe_unretained *p2 = class_copyProtocolList(clone, NULL);
105 testassert(p1);
106 testassert(p2);
107 for (i = 0; p1[i] && p2[i]; i++) {
108 testassert(p1[i] == p2[i]); // protocols are not deep-copied
109 }
110 testassert(p1[i] == NULL && p2[i] == NULL);
111 free(p1);
112 free(p2);
113
114 // Check property list
115 objc_property_t *o1 = class_copyPropertyList(cls, NULL);
116 objc_property_t *o2 = class_copyPropertyList(clone, NULL);
117 testassert(o1);
118 testassert(o2);
119 for (i = 0; o1[i] && o2[i]; i++) {
120 testassert(o1[i] == o2[i]); // properties are not deep-copied
121 }
122 testassert(o1[i] == NULL && o2[i] == NULL);
123 free(o1);
124 free(o2);
125
126 // Check method calls
127
128 state = 0;
129 [cls classMethod];
130 testassert(state == 2);
131 state = 0;
132 [clone classMethod];
133 testassert(state == 2);
134
135 // #4511660 Make sure category implementation is still the preferred one
136 id obj;
137 obj = [cls new];
138 state = 0;
139 [obj instanceMethod];
140 testassert(state == 4);
141 RELEASE_VAR(obj);
142
143 obj = [clone new];
144 state = 0;
145 [obj instanceMethod];
146 testassert(state == 4);
147 RELEASE_VAR(obj);
148
149 succeed(__FILE__);
150 }