4 // Test basic +initialize behavior
5 // * +initialize before class method
6 // * superclass +initialize before subclass +initialize
7 // * subclass inheritance of superclass implementation
8 // * messaging during +initialize
9 // * +initialize provoked by class_getMethodImplementation
10 // * +initialize not provoked by objc_getClass
16 @interface Super0 : TestRoot @end
17 @implementation Super0
19 fail("objc_getClass() must not trigger +initialize");
23 @interface Super : TestRoot @end
26 testprintf("in [Super initialize]\n");
27 testassert(state == 0);
31 fail("[Super method] shouldn't be called");
35 @interface Sub : Super @end
38 testprintf("in [Sub initialize]\n");
39 testassert(state == 1);
43 testprintf("in [Sub method]\n");
44 testassert(state == 2);
50 @interface Super2 : TestRoot @end
51 @interface Sub2 : Super2 @end
53 @implementation Super2
55 if (self == objc_getClass("Sub2")) {
56 testprintf("in [Super2 initialize] of Sub2\n");
57 testassert(state == 1);
59 } else if (self == objc_getClass("Super2")) {
60 testprintf("in [Super2 initialize] of Super2\n");
61 testassert(state == 0);
64 fail("in [Super2 initialize] of unknown class");
68 testprintf("in [Super2 method]\n");
69 testassert(state == 2);
79 @interface Super3 : TestRoot @end
80 @interface Sub3 : Super3 @end
82 @implementation Super3
84 if (self == [Sub3 class]) { // this message triggers [Sub3 initialize]
85 testprintf("in [Super3 initialize] of Sub3\n");
86 testassert(state == 0);
88 } else if (self == [Super3 class]) {
89 testprintf("in [Super3 initialize] of Super3\n");
90 testassert(state == 1);
93 fail("in [Super3 initialize] of unknown class");
97 testprintf("in [Super3 method]\n");
98 testassert(state == 2);
108 @interface Super4 : TestRoot @end
109 @implementation Super4
110 -(void)instanceMethod {
111 testassert(state == 1);
115 testprintf("in [Super4 initialize]\n");
116 testassert(state == 0);
118 id x = [[self alloc] init];
125 @interface Super5 : TestRoot @end
126 @implementation Super5
127 -(void)instanceMethod {
130 testassert(state == 1);
134 testprintf("in [Super5 initialize]\n");
135 testassert(state == 0);
137 class_getMethodImplementation(self, @selector(instanceMethod));
138 // this is the "memoized" case for getNonMetaClass
139 class_getMethodImplementation(object_getClass(self), @selector(classMethod));
145 @interface Super6 : TestRoot @end
146 @interface Sub6 : Super6 @end
147 @implementation Super6
151 testprintf("in [Super6 initialize] (#%d)\n", 1+(int)once);
155 testassert(state == 0);
159 testassert(state == 2);
164 testassert(state == 5);
167 testassert(state == 3);
174 testprintf("in [Sub6 initialize]\n");
175 testassert(state == 1);
178 testassert(state == 4);
184 @interface Super7 : TestRoot @end
185 @interface Sub7 : Super7 @end
186 @implementation Super7
190 testprintf("in [Super7 initialize] (#%d)\n", 1+(int)once);
194 testassert(state == 0);
198 testassert(state == 2);
203 testassert(state == 5);
206 testassert(state == 3);
213 testprintf("in [Sub7 initialize]\n");
214 testassert(state == 1);
217 testassert(state == 4);
224 @interface SuperThrower : TestRoot @end
225 @implementation SuperThrower
227 testprintf("in [SuperThrower initialize]\n");
228 testassert(state == 0);
230 @throw AUTORELEASE([TestRoot new]);
231 fail("@throw didn't throw");
235 @interface SubThrower : SuperThrower @end
236 @implementation SubThrower
238 testprintf("in [SubThrower initialize]\n");
239 testassert(state == 0);
248 // objc_getClass() must not +initialize anything
250 objc_getClass("Super0");
251 testassert(state == 0);
253 // initialize superclass, then subclass
256 testassert(state == 3);
258 // check subclass's inheritance of superclass initialize
261 testassert(state == 3);
263 // check subclass method called from superclass initialize
266 testassert(state == 3);
268 // check class_getMethodImplementation (instance method)
270 cls = objc_getClass("Super4");
271 testassert(state == 0);
272 class_getMethodImplementation(cls, @selector(classMethod));
273 testassert(state == 2);
275 // check class_getMethodImplementation (class method)
276 // this is the "slow" case for getNonMetaClass
278 cls = objc_getClass("Super5");
279 testassert(state == 0);
280 class_getMethodImplementation(object_getClass(cls), @selector(instanceMethod));
281 testassert(state == 2);
283 // check +initialize cycles
284 // this is the "cls is a subclass" case for getNonMetaClass
287 testassert(state == 6);
289 // check +initialize cycles
290 // this is the "cls is a subclass" case for getNonMetaClass
293 testassert(state == 6);
295 // exception from +initialize must be handled cleanly
301 [SuperThrower class];
302 fail("where's the beef^Wexception?");
304 testassert(state == 10);
307 testassert(state == 11);
311 [SuperThrower class];
312 testassert(state == 0);
314 testassert(state == 20);
316 fail("+initialize called again after exception");