6 #include <objc/runtime.h>
10 -(void) instanceMethod;
13 -(void) instanceMethod2;
18 -(void) instanceMethod;
21 -(void) instanceMethod2;
22 +(void) classMethod_that_does_not_exist;
26 -(void) instanceMethod;
27 +(void) classMethod_that_does_not_exist;
29 -(void) instanceMethod2;
33 static int super_initialize;
34 static int super_cxxctor;
35 static int super_cxxdtor;
39 super_cxx() : foo(0) {
47 @interface Super : TestRoot
48 @property int superProp;
50 @implementation Super {
54 +(void)initialize { super_initialize++; }
56 +(void) classMethod { fail("+[Super classMethod] called"); }
57 +(void) classMethod2 { fail("+[Super classMethod2] called"); }
58 -(void) instanceMethod { fail("-[Super instanceMethod] called"); }
59 -(void) instanceMethod2 { fail("-[Super instanceMethod2] called"); }
64 static void instance_fn(id self, SEL _cmd __attribute__((unused)))
66 testassert(!class_isMetaClass(object_getClass(self)));
70 static void class_fn(id self, SEL _cmd __attribute__((unused)))
72 testassert(class_isMetaClass(object_getClass(self)));
76 static void fail_fn(id self __attribute__((unused)), SEL _cmd)
78 fail("fail_fn '%s' called", sel_getName(_cmd));
82 static void cycle(void)
89 testassert(!objc_getClass("Sub"));
90 testassert([Super class]);
92 // Test subclass with bells and whistles
94 cls = objc_allocateClassPair([Super class], "Sub", 0);
97 class_addMethod(cls, @selector(instanceMethod),
98 (IMP)&instance_fn, "v@:");
99 class_addMethod(object_getClass(cls), @selector(classMethod),
100 (IMP)&class_fn, "v@:");
101 class_addMethod(object_getClass(cls), @selector(initialize),
102 (IMP)&class_fn, "v@:");
103 class_addMethod(object_getClass(cls), @selector(load),
104 (IMP)&fail_fn, "v@:");
106 ok = class_addProtocol(cls, @protocol(Proto));
108 ok = class_addProtocol(cls, @protocol(Proto));
113 objc_property_attribute_t attrs[1];
114 unsigned int attrcount = sizeof(attrs) / sizeof(attrs[0]);
116 attrs[0].name = attrname;
117 attrs[0].value = attrvalue;
118 strcpy(attrname, "T");
119 strcpy(attrvalue, "x");
121 strcpy(namebuf, "subProp");
122 ok = class_addProperty(cls, namebuf, attrs, attrcount);
124 strcpy(namebuf, "subProp");
125 ok = class_addProperty(cls, namebuf, attrs, attrcount);
127 strcpy(attrvalue, "i");
128 class_replaceProperty(cls, namebuf, attrs, attrcount);
129 strcpy(namebuf, "superProp");
130 ok = class_addProperty(cls, namebuf, attrs, attrcount);
132 bzero(namebuf, sizeof(namebuf));
133 bzero(attrs, sizeof(attrs));
134 bzero(attrname, sizeof(attrname));
135 bzero(attrvalue, sizeof(attrvalue));
153 ok = class_addIvar(cls, "ivar", 4, 2, "i");
155 ok = class_addIvar(cls, "ivarid", size, align, "@");
157 ok = class_addIvar(cls, "ivaridstar", size, align, "^@");
159 ok = class_addIvar(cls, "ivarblock", size, align, "@?");
162 ok = class_addIvar(cls, "ivar", 4, 2, "i");
164 ok = class_addIvar(object_getClass(cls), "classvar", 4, 2, "i");
167 objc_registerClassPair(cls);
169 // should call cls's +initialize, not super's
170 // Provoke +initialize using class_getMethodImplementation(class method)
171 // in order to test getNonMetaClass's slow case
172 super_initialize = 0;
174 class_getMethodImplementation(object_getClass(cls), @selector(class));
175 testassert(super_initialize == 0);
176 testassert(state == 1);
178 testassert(cls == [cls class]);
179 testassert(cls == objc_getClass("Sub"));
181 testassert(!class_isMetaClass(cls));
182 testassert(class_isMetaClass(object_getClass(cls)));
184 testassert(class_getSuperclass(cls) == [Super class]);
185 testassert(class_getSuperclass(object_getClass(cls)) == object_getClass([Super class]));
187 testassert(class_getInstanceSize(cls) >= sizeof(Class) + 4 + 3*size);
188 testassert(class_conformsToProtocol(cls, @protocol(Proto)));
190 class_addMethod(cls, @selector(instanceMethod2),
191 (IMP)&instance_fn, "v@:");
192 class_addMethod(object_getClass(cls), @selector(classMethod2),
193 (IMP)&class_fn, "v@:");
195 ok = class_addIvar(cls, "ivar2", 4, 4, "i");
197 ok = class_addIvar(object_getClass(cls), "classvar2", 4, 4, "i");
200 ok = class_addProtocol(cls, @protocol(Proto2));
202 ok = class_addProtocol(cls, @protocol(Proto2));
204 ok = class_addProtocol(cls, @protocol(Proto));
207 attrs[0].name = attrname;
208 attrs[0].value = attrvalue;
209 strcpy(attrname, "T");
210 strcpy(attrvalue, "i");
212 strcpy(namebuf, "subProp2");
213 ok = class_addProperty(cls, namebuf, attrs, attrcount);
215 strcpy(namebuf, "subProp");
216 ok = class_addProperty(cls, namebuf, attrs, attrcount);
218 strcpy(namebuf, "superProp");
219 ok = class_addProperty(cls, namebuf, attrs, attrcount);
221 bzero(namebuf, sizeof(namebuf));
222 bzero(attrs, sizeof(attrs));
223 bzero(attrname, sizeof(attrname));
224 bzero(attrvalue, sizeof(attrvalue));
226 prop = class_getProperty(cls, "subProp");
228 testassert(0 == strcmp(property_getName(prop), "subProp"));
229 testassert(0 == strcmp(property_getAttributes(prop), "Ti"));
230 prop = class_getProperty(cls, "subProp2");
232 testassert(0 == strcmp(property_getName(prop), "subProp2"));
233 testassert(0 == strcmp(property_getAttributes(prop), "Ti"));
235 // note: adding more methods here causes a false leak check failure
239 testassert(state == 2);
241 // put instance tests on a separate thread so they
242 // are reliably deallocated before class destruction
247 testassert(super_cxxctor == 1);
248 testassert(super_cxxdtor == 0);
250 [obj instanceMethod];
251 [obj instanceMethod2];
252 testassert(state == 2);
254 testassert(super_cxxctor == 1);
255 testassert(super_cxxdtor == 1);
258 // Test ivar layouts of sub-subclass
259 Class cls2 = objc_allocateClassPair(cls, "SubSub", 0);
272 ok = class_addIvar(cls2, "ivarid2", size, align, "@");
274 ok = class_addIvar(cls2, "idarray", 16*sizeof(id), align, "[16@]");
276 ok = class_addIvar(cls2, "ptrarray", 16*sizeof(void*), align, "[16^]");
278 ok = class_addIvar(cls2, "a", 1, 0, "c");
280 ok = class_addIvar(cls2, "b", 1, 0, "c");
282 ok = class_addIvar(cls2, "c", 1, 0, "c");
285 objc_registerClassPair(cls2);
287 // 1-byte ivars should be well packed
288 testassert(ivar_getOffset(class_getInstanceVariable(cls2, "b")) ==
289 ivar_getOffset(class_getInstanceVariable(cls2, "a")) + 1);
290 testassert(ivar_getOffset(class_getInstanceVariable(cls2, "c")) ==
291 ivar_getOffset(class_getInstanceVariable(cls2, "b")) + 1);
293 objc_disposeClassPair(cls2);
294 objc_disposeClassPair(cls);
296 testassert(!objc_getClass("Sub"));
298 // fixme test layout setters
305 // fixme even with this long warmup we still
306 // suffer false 4096-byte leaks occasionally.
307 for (int i = 0; i < 500; i++) {
308 testonthread(^{ cycle(); });
313 testonthread(^{ cycle(); });