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