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;
35 @interface Super : TestRoot
36 @property int superProp;
40 +(void)initialize { super_initialize++; }
42 +(void) classMethod { fail("+[Super classMethod] called"); }
43 +(void) classMethod2 { fail("+[Super classMethod2] called"); }
44 -(void) instanceMethod { fail("-[Super instanceMethod] called"); }
45 -(void) instanceMethod2 { fail("-[Super instanceMethod2] called"); }
50 static void instance_fn(id self, SEL _cmd __attribute__((unused)))
52 testassert(!class_isMetaClass(object_getClass(self)));
56 static void class_fn(id self, SEL _cmd __attribute__((unused)))
58 testassert(class_isMetaClass(object_getClass(self)));
62 static void fail_fn(id self __attribute__((unused)), SEL _cmd)
64 fail("fail_fn '%s' called", sel_getName(_cmd));
68 static void cycle(void)
75 testassert(!objc_getClass("Sub"));
76 testassert([Super class]);
78 // Test subclass with bells and whistles
80 cls = objc_allocateClassPair([Super class], "Sub", 0);
83 class_addMethod(cls, @selector(instanceMethod),
84 (IMP)&instance_fn, "v@:");
85 class_addMethod(object_getClass(cls), @selector(classMethod),
86 (IMP)&class_fn, "v@:");
87 class_addMethod(object_getClass(cls), @selector(initialize),
88 (IMP)&class_fn, "v@:");
89 class_addMethod(object_getClass(cls), @selector(load),
90 (IMP)&fail_fn, "v@:");
92 ok = class_addProtocol(cls, @protocol(Proto));
94 ok = class_addProtocol(cls, @protocol(Proto));
99 objc_property_attribute_t attrs[1];
100 unsigned int attrcount = sizeof(attrs) / sizeof(attrs[0]);
102 attrs[0].name = attrname;
103 attrs[0].value = attrvalue;
104 strcpy(attrname, "T");
105 strcpy(attrvalue, "x");
107 strcpy(namebuf, "subProp");
108 ok = class_addProperty(cls, namebuf, attrs, attrcount);
110 strcpy(namebuf, "subProp");
111 ok = class_addProperty(cls, namebuf, attrs, attrcount);
113 strcpy(attrvalue, "i");
114 class_replaceProperty(cls, namebuf, attrs, attrcount);
115 strcpy(namebuf, "superProp");
116 ok = class_addProperty(cls, namebuf, attrs, attrcount);
118 bzero(namebuf, sizeof(namebuf));
119 bzero(attrs, sizeof(attrs));
120 bzero(attrname, sizeof(attrname));
121 bzero(attrvalue, sizeof(attrvalue));
139 ok = class_addIvar(cls, "ivar", 4, 2, "i");
141 ok = class_addIvar(cls, "ivarid", size, align, "@");
143 ok = class_addIvar(cls, "ivaridstar", size, align, "^@");
145 ok = class_addIvar(cls, "ivarblock", size, align, "@?");
148 ok = class_addIvar(cls, "ivar", 4, 2, "i");
150 ok = class_addIvar(object_getClass(cls), "classvar", 4, 2, "i");
153 objc_registerClassPair(cls);
155 // should call cls's +initialize, not super's
156 // Provoke +initialize using class_getMethodImplementation(class method)
157 // in order to test getNonMetaClass's slow case
158 super_initialize = 0;
160 class_getMethodImplementation(object_getClass(cls), @selector(class));
161 testassert(super_initialize == 0);
162 testassert(state == 1);
164 testassert(cls == [cls class]);
165 testassert(cls == objc_getClass("Sub"));
167 testassert(!class_isMetaClass(cls));
168 testassert(class_isMetaClass(object_getClass(cls)));
170 testassert(class_getSuperclass(cls) == [Super class]);
171 testassert(class_getSuperclass(object_getClass(cls)) == object_getClass([Super class]));
173 testassert(class_getInstanceSize(cls) >= sizeof(Class) + 4 + 3*size);
174 testassert(class_conformsToProtocol(cls, @protocol(Proto)));
176 class_addMethod(cls, @selector(instanceMethod2),
177 (IMP)&instance_fn, "v@:");
178 class_addMethod(object_getClass(cls), @selector(classMethod2),
179 (IMP)&class_fn, "v@:");
181 ok = class_addIvar(cls, "ivar2", 4, 4, "i");
183 ok = class_addIvar(object_getClass(cls), "classvar2", 4, 4, "i");
186 ok = class_addProtocol(cls, @protocol(Proto2));
188 ok = class_addProtocol(cls, @protocol(Proto2));
190 ok = class_addProtocol(cls, @protocol(Proto));
193 attrs[0].name = attrname;
194 attrs[0].value = attrvalue;
195 strcpy(attrname, "T");
196 strcpy(attrvalue, "i");
198 strcpy(namebuf, "subProp2");
199 ok = class_addProperty(cls, namebuf, attrs, attrcount);
201 strcpy(namebuf, "subProp");
202 ok = class_addProperty(cls, namebuf, attrs, attrcount);
204 strcpy(namebuf, "superProp");
205 ok = class_addProperty(cls, namebuf, attrs, attrcount);
207 bzero(namebuf, sizeof(namebuf));
208 bzero(attrs, sizeof(attrs));
209 bzero(attrname, sizeof(attrname));
210 bzero(attrvalue, sizeof(attrvalue));
212 prop = class_getProperty(cls, "subProp");
214 testassert(0 == strcmp(property_getName(prop), "subProp"));
215 testassert(0 == strcmp(property_getAttributes(prop), "Ti"));
216 prop = class_getProperty(cls, "subProp2");
218 testassert(0 == strcmp(property_getName(prop), "subProp2"));
219 testassert(0 == strcmp(property_getAttributes(prop), "Ti"));
221 // note: adding more methods here causes a false leak check failure
225 testassert(state == 2);
227 // put instance tests on a separate thread so they
228 // are reliably deallocated before class destruction
232 [obj instanceMethod];
233 [obj instanceMethod2];
234 testassert(state == 2);
238 // Test ivar layouts of sub-subclass
239 Class cls2 = objc_allocateClassPair(cls, "SubSub", 0);
252 ok = class_addIvar(cls2, "ivarid2", size, align, "@");
254 ok = class_addIvar(cls2, "idarray", 16*sizeof(id), align, "[16@]");
256 ok = class_addIvar(cls2, "ptrarray", 16*sizeof(void*), align, "[16^]");
258 ok = class_addIvar(cls2, "a", 1, 0, "c");
260 ok = class_addIvar(cls2, "b", 1, 0, "c");
262 ok = class_addIvar(cls2, "c", 1, 0, "c");
265 objc_registerClassPair(cls2);
267 // 1-byte ivars should be well packed
268 testassert(ivar_getOffset(class_getInstanceVariable(cls2, "b")) ==
269 ivar_getOffset(class_getInstanceVariable(cls2, "a")) + 1);
270 testassert(ivar_getOffset(class_getInstanceVariable(cls2, "c")) ==
271 ivar_getOffset(class_getInstanceVariable(cls2, "b")) + 1);
273 objc_disposeClassPair(cls2);
274 objc_disposeClassPair(cls);
276 testassert(!objc_getClass("Sub"));
278 // fixme test layout setters
285 // fixme even with this long warmup we still
286 // suffer false 4096-byte leaks occasionally.
287 for (int i = 0; i < 500; i++) {
288 testonthread(^{ cycle(); });
293 testonthread(^{ cycle(); });