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 'NSObject'
64 objc\[\d+\]: \*\*\* Can't set ivar layout for already-registered class 'AllocatedTestClass2'
65 objc\[\d+\]: \*\*\* Can't set ivar layout for already-registered class 'DuplicateClass'
66 Completed test on good classes.
67 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
69 Testing class_setWeakIvarLayout
70 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'TestRoot'
71 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'TestRoot'
72 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'NSObject'
73 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'NSObject'
74 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'AllocatedTestClass2'
75 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'AllocatedTestClass2'
76 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'TestRoot'
77 objc\[\d+\]: \*\*\* Can't set weak ivar layout for already-registered class 'DuplicateClass'
78 Completed test on good classes.
79 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
81 Testing objc_registerClassPair
82 objc\[\d+\]: objc_registerClassPair: class 'TestRoot' was not allocated with objc_allocateClassPair!
83 objc\[\d+\]: objc_registerClassPair: class 'NSObject' was not allocated with objc_allocateClassPair!
84 objc\[\d+\]: objc_registerClassPair: class 'AllocatedTestClass2' was already registered!
85 objc\[\d+\]: objc_registerClassPair: class 'DuplicateClass' was not allocated with objc_allocateClassPair!
86 Completed test on good classes.
87 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
89 Testing objc_duplicateClass
90 Completed test on good classes.
91 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
93 Testing objc_disposeClassPair
94 objc\[\d+\]: objc_disposeClassPair: class 'TestRoot' was not allocated with objc_allocateClassPair!
95 objc\[\d+\]: objc_disposeClassPair: class 'NSObject' was not allocated with objc_allocateClassPair!
96 objc\[\d+\]: objc_disposeClassPair: class 'DuplicateClass' was not allocated with objc_allocateClassPair!
97 Completed test on good classes.
98 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
105 #include "testroot.i"
111 extern char **environ;
113 id dummyIMP(id self, SEL _cmd) { (void)_cmd; return self; }
115 char *dupeName(Class cls) {
117 asprintf(&name, "%sDuplicate", class_getName(cls));
121 typedef void (^TestBlock)(Class);
127 #define NAMED_TESTCASE(name, ...) { name, ^(Class cls) { __VA_ARGS__; } }
128 #define TESTCASE(...) NAMED_TESTCASE(#__VA_ARGS__, __VA_ARGS__)
129 #define TESTCASE_NOMETA(...) \
130 NAMED_TESTCASE( #__VA_ARGS__, if(class_isMetaClass(cls)) return; __VA_ARGS__; )
131 #define TESTCASE_OBJ(...) NAMED_TESTCASE( \
133 if(class_isMetaClass(cls)) return; \
134 id obj = [TestRoot alloc]; \
135 *(Class *)obj = cls; \
139 struct TestCase TestCases[] = {
140 TESTCASE_OBJ(object_getMethodImplementation(obj, @selector(init))),
142 TESTCASE(class_getInstanceMethod(cls, @selector(init))),
143 TESTCASE(class_getMethodImplementation(cls, @selector(init))),
144 TESTCASE(class_respondsToSelector(cls, @selector(init))),
145 TESTCASE(class_conformsToProtocol(cls, @protocol(P))),
146 TESTCASE(free(class_copyProtocolList(cls, NULL))),
147 TESTCASE(class_getProperty(cls, "x")),
148 TESTCASE(free(class_copyPropertyList(cls, NULL))),
149 TESTCASE(class_addMethod(cls, @selector(nop), (IMP)dummyIMP, "v@:")),
150 TESTCASE(class_replaceMethod(cls, @selector(nop), (IMP)dummyIMP, "v@:")),
151 TESTCASE(class_addIvar(cls, "x", sizeof(int), sizeof(int), @encode(int))),
152 TESTCASE(class_addProtocol(cls, @protocol(P))),
153 TESTCASE(class_addProperty(cls, "x", NULL, 0)),
154 TESTCASE(class_replaceProperty(cls, "x", NULL, 0)),
155 TESTCASE_NOMETA(class_setIvarLayout(cls, NULL)),
156 TESTCASE(class_setWeakIvarLayout(cls, NULL)),
157 TESTCASE_NOMETA(objc_registerClassPair(cls)),
158 TESTCASE_NOMETA(objc_duplicateClass(cls, dupeName(cls), 0)),
159 TESTCASE_NOMETA(objc_disposeClassPair(cls)),
162 void parent(char *argv0)
164 int testCount = sizeof(TestCases) / sizeof(*TestCases);
165 for (int i = 0; i < testCount; i++) {
167 asprintf(&testIndex, "%d", i);
168 char *argvSpawn[] = {
174 int result = posix_spawn(&pid, argv0, NULL, NULL, argvSpawn, environ);
176 fprintf(stderr, "Could not spawn child process: (%d) %s\n",
177 errno, strerror(errno));
183 result = waitpid(pid, NULL, 0);
185 fprintf(stderr, "Error waiting for termination of child process: (%d) %s\n",
186 errno, strerror(errno));
190 fprintf(stderr, "Completed!\n");
193 void child(char *argv1)
195 long index = strtol(argv1, NULL, 10);
196 struct TestCase testCase = TestCases[index];
197 TestBlock block = testCase.block;
199 const char *name = testCase.name;
200 if (strncmp(name, "free(", 5) == 0)
202 const char *paren = strchr(name, '(');
203 long len = paren != NULL ? paren - name : strlen(name);
204 fprintf(stderr, "Testing %.*s\n", (int)len, name);
206 // Make sure plain classes work.
207 block([TestRoot class]);
208 block(object_getClass([TestRoot class]));
210 // And framework classes.
211 block([NSObject class]);
212 block(object_getClass([NSObject class]));
214 // Test a constructed, unregistered class.
215 Class allocatedClass = objc_allocateClassPair([TestRoot class],
216 "AllocatedTestClass",
218 class_getMethodImplementation(allocatedClass, @selector(self));
219 block(object_getClass(allocatedClass));
220 block(allocatedClass);
222 // Test a constructed, registered class. (Do this separately so
223 // test cases can dispose of the class if needed.)
224 allocatedClass = objc_allocateClassPair([TestRoot class],
225 "AllocatedTestClass2",
227 objc_registerClassPair(allocatedClass);
228 block(object_getClass(allocatedClass));
229 block(allocatedClass);
231 // Test a duplicated class.
233 Class duplicatedClass = objc_duplicateClass([TestRoot class],
236 block(object_getClass(duplicatedClass));
237 block(duplicatedClass);
239 fprintf(stderr, "Completed test on good classes.\n");
241 // Test a fake class.
242 Class templateClass = objc_allocateClassPair([TestRoot class],
245 void *fakeClass = malloc(malloc_size(templateClass));
246 memcpy(fakeClass, templateClass, malloc_size(templateClass));
247 block((Class)fakeClass);
248 fail("Should have died on the fake class");
251 int main(int argc, char **argv)
253 // We want to run a bunch of tests, all of which end in _objc_fatal
254 // (at least if they succeed). Spawn one subprocess per test and
255 // have the parent process manage it all. The test will begin by
256 // running parent(), which will repeatedly re-spawn this program to
257 // call child() with the index of the test to run.