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