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