5 Testing object_getMethodImplementation
6 Completed test on good classes.
7 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
9 Testing class_getInstanceMethod
10 Completed test on good classes.
11 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
13 Testing class_getMethodImplementation
14 Completed test on good classes.
15 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
17 Testing class_respondsToSelector
18 Completed test on good classes.
19 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
21 Testing class_conformsToProtocol
22 Completed test on good classes.
23 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
25 Testing class_copyProtocolList
26 Completed test on good classes.
27 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
29 Testing class_getProperty
30 Completed test on good classes.
31 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
33 Testing class_copyPropertyList
34 Completed test on good classes.
35 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
37 Testing class_addMethod
38 Completed test on good classes.
39 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
41 Testing class_replaceMethod
42 Completed test on good classes.
43 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
46 Completed test on good classes.
47 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
49 Testing class_addProtocol
50 Completed test on good classes.
51 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
53 Testing class_addProperty
54 Completed test on good classes.
55 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
57 Testing class_replaceProperty
58 Completed test on good classes.
59 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
61 Testing class_setIvarLayout
62 objc\[\d+\]: \*\*\* Can't set ivar layout for already-registered class 'TestRoot'
63 objc\[\d+\]: \*\*\* Can't set ivar layout for already-registered class 'TestRoot'
64 objc\[\d+\]: \*\*\* Can't set ivar layout for already-registered class 'NSObject'
65 objc\[\d+\]: \*\*\* Can't set ivar layout for already-registered class 'NSObject'
66 objc\[\d+\]: \*\*\* Can't set ivar layout for already-registered class 'AllocatedTestClass2'
67 objc\[\d+\]: \*\*\* Can't set ivar layout for already-registered class 'AllocatedTestClass2'
68 objc\[\d+\]: \*\*\* Can't set ivar layout for already-registered class 'TestRoot'
69 objc\[\d+\]: \*\*\* Can't set ivar layout for already-registered class 'DuplicateClass'
70 Completed test on good classes.
71 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
73 Testing class_setWeakIvarLayout
74 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'TestRoot'
75 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'TestRoot'
76 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'NSObject'
77 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'NSObject'
78 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'AllocatedTestClass2'
79 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'AllocatedTestClass2'
80 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'TestRoot'
81 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'DuplicateClass'
82 Completed test on good classes.
83 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
85 Testing objc_registerClassPair
86 objc\[\d+\]: objc_registerClassPair: class 'TestRoot' was not allocated with objc_allocateClassPair!
87 objc\[\d+\]: objc_registerClassPair: class 'NSObject' was not allocated with objc_allocateClassPair!
88 objc\[\d+\]: objc_registerClassPair: class 'AllocatedTestClass2' was already registered!
89 objc\[\d+\]: objc_registerClassPair: class 'DuplicateClass' was not allocated with objc_allocateClassPair!
90 Completed test on good classes.
91 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
93 Testing objc_duplicateClass
94 Completed test on good classes.
95 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
97 Testing objc_disposeClassPair
98 objc\[\d+\]: objc_disposeClassPair: class 'TestRoot' was not allocated with objc_allocateClassPair!
99 objc\[\d+\]: objc_disposeClassPair: class 'NSObject' was not allocated with objc_allocateClassPair!
100 objc\[\d+\]: objc_disposeClassPair: class 'DuplicateClass' was not allocated with objc_allocateClassPair!
101 Completed test on good classes.
102 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
109 #include "testroot.i"
115 extern char **environ;
117 id dummyIMP(id self, SEL _cmd) { (void)_cmd; return self; }
119 char *dupeName(Class cls) {
121 asprintf(&name, "%sDuplicate", class_getName(cls));
125 typedef void (^TestBlock)(Class);
131 #define NAMED_TESTCASE(name, ...) { name, ^(Class cls) { __VA_ARGS__; } }
132 #define TESTCASE(...) NAMED_TESTCASE(#__VA_ARGS__, __VA_ARGS__)
133 #define TESTCASE_NOMETA(...) \
134 NAMED_TESTCASE( #__VA_ARGS__, if(class_isMetaClass(cls)) return; __VA_ARGS__; )
135 #define TESTCASE_OBJ(...) NAMED_TESTCASE( \
137 if(class_isMetaClass(cls)) return; \
138 id obj = [TestRoot alloc]; \
139 *(Class *)obj = cls; \
143 struct TestCase TestCases[] = {
144 TESTCASE_OBJ(object_getMethodImplementation(obj, @selector(init))),
146 TESTCASE(class_getInstanceMethod(cls, @selector(init))),
147 TESTCASE(class_getMethodImplementation(cls, @selector(init))),
148 TESTCASE(class_respondsToSelector(cls, @selector(init))),
149 TESTCASE(class_conformsToProtocol(cls, @protocol(P))),
150 TESTCASE(free(class_copyProtocolList(cls, NULL))),
151 TESTCASE(class_getProperty(cls, "x")),
152 TESTCASE(free(class_copyPropertyList(cls, NULL))),
153 TESTCASE(class_addMethod(cls, @selector(nop), (IMP)dummyIMP, "v@:")),
154 TESTCASE(class_replaceMethod(cls, @selector(nop), (IMP)dummyIMP, "v@:")),
155 TESTCASE(class_addIvar(cls, "x", sizeof(int), sizeof(int), @encode(int))),
156 TESTCASE(class_addProtocol(cls, @protocol(P))),
157 TESTCASE(class_addProperty(cls, "x", NULL, 0)),
158 TESTCASE(class_replaceProperty(cls, "x", NULL, 0)),
159 TESTCASE(class_setIvarLayout(cls, NULL)),
160 TESTCASE(class_setWeakIvarLayout(cls, NULL)),
161 TESTCASE_NOMETA(objc_registerClassPair(cls)),
162 TESTCASE_NOMETA(objc_duplicateClass(cls, dupeName(cls), 0)),
163 TESTCASE_NOMETA(objc_disposeClassPair(cls)),
166 void parent(char *argv0)
168 int testCount = sizeof(TestCases) / sizeof(*TestCases);
169 for (int i = 0; i < testCount; i++) {
171 asprintf(&testIndex, "%d", i);
172 char *argvSpawn[] = {
178 int result = posix_spawn(&pid, argv0, NULL, NULL, argvSpawn, environ);
180 fprintf(stderr, "Could not spawn child process: (%d) %s\n",
181 errno, strerror(errno));
187 result = waitpid(pid, NULL, 0);
189 fprintf(stderr, "Error waiting for termination of child process: (%d) %s\n",
190 errno, strerror(errno));
194 fprintf(stderr, "Completed!\n");
197 void child(char *argv1)
199 long index = strtol(argv1, NULL, 10);
200 struct TestCase testCase = TestCases[index];
201 TestBlock block = testCase.block;
203 const char *name = testCase.name;
204 if (strncmp(name, "free(", 5) == 0)
206 const char *paren = strchr(name, '(');
207 long len = paren != NULL ? paren - name : strlen(name);
208 fprintf(stderr, "Testing %.*s\n", (int)len, name);
210 // Make sure plain classes work.
211 block([TestRoot class]);
212 block(object_getClass([TestRoot class]));
214 // And framework classes.
215 block([NSObject class]);
216 block(object_getClass([NSObject class]));
218 // Test a constructed, unregistered class.
219 Class allocatedClass = objc_allocateClassPair([TestRoot class],
220 "AllocatedTestClass",
222 class_getMethodImplementation(allocatedClass, @selector(self));
223 block(object_getClass(allocatedClass));
224 block(allocatedClass);
226 // Test a constructed, registered class. (Do this separately so
227 // test cases can dispose of the class if needed.)
228 allocatedClass = objc_allocateClassPair([TestRoot class],
229 "AllocatedTestClass2",
231 objc_registerClassPair(allocatedClass);
232 block(object_getClass(allocatedClass));
233 block(allocatedClass);
235 // Test a duplicated class.
237 Class duplicatedClass = objc_duplicateClass([TestRoot class],
240 block(object_getClass(duplicatedClass));
241 block(duplicatedClass);
243 fprintf(stderr, "Completed test on good classes.\n");
245 // Test a fake class.
246 Class templateClass = objc_allocateClassPair([TestRoot class],
249 void *fakeClass = malloc(malloc_size(templateClass));
250 memcpy(fakeClass, templateClass, malloc_size(templateClass));
251 block((Class)fakeClass);
252 fail("Should have died on the fake class");
255 int main(int argc, char **argv)
257 // We want to run a bunch of tests, all of which end in _objc_fatal
258 // (at least if they succeed). Spawn one subprocess per test and
259 // have the parent process manage it all. The test will begin by
260 // running parent(), which will repeatedly re-spawn this program to
261 // call child() with the index of the test to run.