1 // TEST_CFLAGS -Wno-deprecated-declarations
4 #include <objc/runtime.h>
7 #include <objc/objc-auto.h>
12 -(void) instanceMethod;
15 -(void) instanceMethod2;
20 -(void) instanceMethod;
23 -(void) instanceMethod2;
24 +(void) classMethod_that_does_not_exist;
28 -(void) instanceMethod;
29 +(void) classMethod_that_does_not_exist;
31 -(void) instanceMethod2;
35 static int super_initialize;
37 @interface Super { @public id isa; }
38 @property int superProp;
42 +(void)initialize { super_initialize++; }
43 +class { return self; }
44 +(id) new { return class_createInstance(self, 0); }
45 -(void) free { object_dispose(self); }
47 +(void) classMethod { fail("+[Super classMethod] called"); }
48 +(void) classMethod2 { fail("+[Super classMethod2] called"); }
49 -(void) instanceMethod { fail("-[Super instanceMethod] called"); }
50 -(void) instanceMethod2 { fail("-[Super instanceMethod2] called"); }
53 @interface WeakSuper : Super { __weak id weakIvar; } @end
54 @implementation WeakSuper @end
58 static void instance_fn(id self, SEL _cmd __attribute__((unused)))
60 testassert(!class_isMetaClass(self->isa));
64 static void class_fn(id self, SEL _cmd __attribute__((unused)))
66 testassert(class_isMetaClass(self->isa));
70 static void fail_fn(id self __attribute__((unused)), SEL _cmd)
72 fail("fail_fn '%s' called", sel_getName(_cmd));
75 static void cycle(void)
82 testassert(!objc_getClass("Sub"));
83 testassert([Super class]);
85 // Test subclass with bells and whistles
87 cls = objc_allocateClassPair([Super class], "Sub", 0);
90 if (objc_collectingEnabled()) {
91 testassert(auto_zone_size(objc_collectableZone(), cls));
92 testassert(auto_zone_size(objc_collectableZone(), cls->isa));
96 class_addMethod(cls, @selector(instanceMethod),
97 (IMP)&instance_fn, "v@:");
98 class_addMethod(cls->isa, @selector(classMethod),
99 (IMP)&class_fn, "v@:");
100 class_addMethod(cls->isa, @selector(initialize),
101 (IMP)&class_fn, "v@:");
102 class_addMethod(cls->isa, @selector(load),
103 (IMP)&fail_fn, "v@:");
105 ok = class_addProtocol(cls, @protocol(Proto));
107 ok = class_addProtocol(cls, @protocol(Proto));
112 objc_property_attribute_t attrs[1];
113 unsigned int attrcount = sizeof(attrs) / sizeof(attrs[0]);
115 attrs[0].name = attrname;
116 attrs[0].value = attrvalue;
117 strcpy(attrname, "T");
118 strcpy(attrvalue, "x");
120 strcpy(namebuf, "subProp");
121 ok = class_addProperty(cls, namebuf, attrs, attrcount);
123 strcpy(namebuf, "subProp");
124 ok = class_addProperty(cls, namebuf, attrs, attrcount);
126 strcpy(attrvalue, "i");
127 class_replaceProperty(cls, namebuf, attrs, attrcount);
128 strcpy(namebuf, "superProp");
129 ok = class_addProperty(cls, namebuf, attrs, attrcount);
131 bzero(namebuf, sizeof(namebuf));
132 bzero(attrs, sizeof(attrs));
133 bzero(attrname, sizeof(attrname));
134 bzero(attrvalue, sizeof(attrvalue));
152 ok = class_addIvar(cls, "ivar", 4, 2, "i");
154 ok = class_addIvar(cls, "ivarid", size, align, "@");
156 ok = class_addIvar(cls, "ivaridstar", size, align, "^@");
158 ok = class_addIvar(cls, "ivarblock", size, align, "@?");
161 ok = class_addIvar(cls, "ivar", 4, 2, "i");
163 ok = class_addIvar(cls->isa, "classvar", 4, 2, "i");
166 objc_registerClassPair(cls);
168 // should call cls's +initialize, not super's
169 super_initialize = 0;
172 testassert(super_initialize == 0);
173 testassert(state == 1);
175 testassert(cls == [cls class]);
176 testassert(cls == objc_getClass("Sub"));
178 testassert(!class_isMetaClass(cls));
179 testassert(class_isMetaClass(cls->isa));
181 testassert(class_getSuperclass(cls) == [Super class]);
182 testassert(class_getSuperclass(cls->isa) == [Super class]->isa);
184 testassert(class_getInstanceSize(cls) >= sizeof(Class) + 4 + 3*size);
185 testassert(class_conformsToProtocol(cls, @protocol(Proto)));
187 if (objc_collectingEnabled()) {
188 testassert(0 == strcmp((char *)class_getIvarLayout(cls), "\x01\x13"));
189 testassert(NULL == class_getWeakIvarLayout(cls));
192 class_addMethod(cls, @selector(instanceMethod2),
193 (IMP)&instance_fn, "v@:");
194 class_addMethod(cls->isa, @selector(classMethod2),
195 (IMP)&class_fn, "v@:");
197 ok = class_addIvar(cls, "ivar2", 4, 4, "i");
199 ok = class_addIvar(cls->isa, "classvar2", 4, 4, "i");
202 ok = class_addProtocol(cls, @protocol(Proto2));
204 ok = class_addProtocol(cls, @protocol(Proto2));
206 ok = class_addProtocol(cls, @protocol(Proto));
209 attrs[0].name = attrname;
210 attrs[0].value = attrvalue;
211 strcpy(attrname, "T");
212 strcpy(attrvalue, "i");
214 strcpy(namebuf, "subProp2");
215 ok = class_addProperty(cls, namebuf, attrs, attrcount);
217 strcpy(namebuf, "subProp");
218 ok = class_addProperty(cls, namebuf, attrs, attrcount);
220 strcpy(namebuf, "superProp");
221 ok = class_addProperty(cls, namebuf, attrs, attrcount);
223 bzero(namebuf, sizeof(namebuf));
224 bzero(attrs, sizeof(attrs));
225 bzero(attrname, sizeof(attrname));
226 bzero(attrvalue, sizeof(attrvalue));
228 prop = class_getProperty(cls, "subProp");
230 testassert(0 == strcmp(property_getName(prop), "subProp"));
231 testassert(0 == strcmp(property_getAttributes(prop), "Ti"));
232 prop = class_getProperty(cls, "subProp2");
234 testassert(0 == strcmp(property_getName(prop), "subProp2"));
235 testassert(0 == strcmp(property_getAttributes(prop), "Ti"));
237 // note: adding more methods here causes a false leak check failure
241 testassert(state == 2);
245 [obj instanceMethod];
246 [obj instanceMethod2];
247 testassert(state == 2);
250 // Test ivar layouts of sub-subclass
251 Class cls2 = objc_allocateClassPair(cls, "SubSub", 0);
264 ok = class_addIvar(cls2, "ivarid2", size, align, "@");
266 ok = class_addIvar(cls2, "idarray", 16*sizeof(id), align, "[16@]");
268 ok = class_addIvar(cls2, "ptrarray", 16*sizeof(void*), align, "[16^]");
270 ok = class_addIvar(cls2, "a", 1, 0, "c");
272 ok = class_addIvar(cls2, "b", 1, 0, "c");
274 ok = class_addIvar(cls2, "c", 1, 0, "c");
277 objc_registerClassPair(cls2);
279 if (objc_collectingEnabled()) {
280 testassert(0 == strcmp((char *)class_getIvarLayout(cls2), "\x01\x1f\x05\xf0\x10"));
281 testassert(NULL == class_getWeakIvarLayout(cls2));
284 // 1-byte ivars should be well packed
285 testassert(ivar_getOffset(class_getInstanceVariable(cls2, "b")) ==
286 ivar_getOffset(class_getInstanceVariable(cls2, "a")) + 1);
287 testassert(ivar_getOffset(class_getInstanceVariable(cls2, "c")) ==
288 ivar_getOffset(class_getInstanceVariable(cls2, "b")) + 1);
290 objc_disposeClassPair(cls2);
292 objc_disposeClassPair(cls);
294 testassert(!objc_getClass("Sub"));
297 // Test unmodified ivar layouts
299 cls = objc_allocateClassPair([Super class], "Sub2", 0);
301 objc_registerClassPair(cls);
302 if (objc_collectingEnabled()) {
304 l1 = (char *)class_getIvarLayout([Super class]);
305 l2 = (char *)class_getIvarLayout(cls);
306 testassert(l1 == l2 || 0 == strcmp(l1, l2));
307 l1 = (char *)class_getWeakIvarLayout([Super class]);
308 l2 = (char *)class_getWeakIvarLayout(cls);
309 testassert(l1 == l2 || 0 == strcmp(l1, l2));
311 objc_disposeClassPair(cls);
313 cls = objc_allocateClassPair([WeakSuper class], "Sub3", 0);
315 objc_registerClassPair(cls);
316 if (objc_collectingEnabled()) {
318 l1 = (char *)class_getIvarLayout([WeakSuper class]);
319 l2 = (char *)class_getIvarLayout(cls);
320 testassert(l1 == l2 || 0 == strcmp(l1, l2));
321 l1 = (char *)class_getWeakIvarLayout([WeakSuper class]);
322 l2 = (char *)class_getWeakIvarLayout(cls);
323 testassert(l1 == l2 || 0 == strcmp(l1, l2));
325 objc_disposeClassPair(cls);
327 // Test layout setters
328 if (objc_collectingEnabled()) {
329 cls = objc_allocateClassPair([Super class], "Sub4", 0);
331 class_setIvarLayout(cls, (uint8_t *)"foo");
332 class_setWeakIvarLayout(cls, NULL);
333 objc_registerClassPair(cls);
334 testassert(0 == strcmp("foo", (char *)class_getIvarLayout(cls)));
335 testassert(NULL == class_getWeakIvarLayout(cls));
336 objc_disposeClassPair(cls);
338 cls = objc_allocateClassPair([Super class], "Sub5", 0);
340 class_setIvarLayout(cls, NULL);
341 class_setWeakIvarLayout(cls, (uint8_t *)"bar");
342 objc_registerClassPair(cls);
343 testassert(NULL == class_getIvarLayout(cls));
344 testassert(0 == strcmp("bar", (char *)class_getWeakIvarLayout(cls)));
345 objc_disposeClassPair(cls);