]> git.saurik.com Git - apple/objc4.git/blob - test/isaValidation.m
objc4-818.2.tar.gz
[apple/objc4.git] / test / isaValidation.m
1 // TEST_CRASHES
2 // TEST_CONFIG MEM=mrc
3 /*
4 TEST_RUN_OUTPUT
5 Testing object_getMethodImplementation
6 Completed test on good classes.
7 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
8 objc\[\d+\]: HALTED
9 Testing class_getInstanceMethod
10 Completed test on good classes.
11 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
12 objc\[\d+\]: HALTED
13 Testing class_getMethodImplementation
14 Completed test on good classes.
15 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
16 objc\[\d+\]: HALTED
17 Testing class_respondsToSelector
18 Completed test on good classes.
19 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
20 objc\[\d+\]: HALTED
21 Testing class_conformsToProtocol
22 Completed test on good classes.
23 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
24 objc\[\d+\]: HALTED
25 Testing class_copyProtocolList
26 Completed test on good classes.
27 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
28 objc\[\d+\]: HALTED
29 Testing class_getProperty
30 Completed test on good classes.
31 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
32 objc\[\d+\]: HALTED
33 Testing class_copyPropertyList
34 Completed test on good classes.
35 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
36 objc\[\d+\]: HALTED
37 Testing class_addMethod
38 Completed test on good classes.
39 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
40 objc\[\d+\]: HALTED
41 Testing class_replaceMethod
42 Completed test on good classes.
43 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
44 objc\[\d+\]: HALTED
45 Testing class_addIvar
46 Completed test on good classes.
47 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
48 objc\[\d+\]: HALTED
49 Testing class_addProtocol
50 Completed test on good classes.
51 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
52 objc\[\d+\]: HALTED
53 Testing class_addProperty
54 Completed test on good classes.
55 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
56 objc\[\d+\]: HALTED
57 Testing class_replaceProperty
58 Completed test on good classes.
59 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
60 objc\[\d+\]: HALTED
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]+.
68 objc\[\d+\]: HALTED
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]+.
80 objc\[\d+\]: HALTED
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]+.
88 objc\[\d+\]: HALTED
89 Testing objc_duplicateClass
90 Completed test on good classes.
91 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
92 objc\[\d+\]: HALTED
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]+.
99 objc\[\d+\]: HALTED
100 Completed!
101 END
102 */
103
104 #include "test.h"
105 #include "testroot.i"
106 #include <spawn.h>
107
108 @protocol P
109 @end
110
111 extern char **environ;
112
113 id dummyIMP(id self, SEL _cmd) { (void)_cmd; return self; }
114
115 char *dupeName(Class cls) {
116 char *name;
117 asprintf(&name, "%sDuplicate", class_getName(cls));
118 return name;
119 }
120
121 typedef void (^TestBlock)(Class);
122 struct TestCase {
123 const char *name;
124 TestBlock block;
125 };
126
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( \
132 #__VA_ARGS__, \
133 if(class_isMetaClass(cls)) return; \
134 id obj = [TestRoot alloc]; \
135 *(Class *)obj = cls; \
136 __VA_ARGS__; \
137 )
138
139 struct TestCase TestCases[] = {
140 TESTCASE_OBJ(object_getMethodImplementation(obj, @selector(init))),
141
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)),
160 };
161
162 void parent(char *argv0)
163 {
164 int testCount = sizeof(TestCases) / sizeof(*TestCases);
165 for (int i = 0; i < testCount; i++) {
166 char *testIndex;
167 asprintf(&testIndex, "%d", i);
168 char *argvSpawn[] = {
169 argv0,
170 testIndex,
171 NULL
172 };
173 pid_t pid;
174 int result = posix_spawn(&pid, argv0, NULL, NULL, argvSpawn, environ);
175 if (result != 0) {
176 fprintf(stderr, "Could not spawn child process: (%d) %s\n",
177 errno, strerror(errno));
178 exit(1);
179 }
180
181 free(testIndex);
182
183 result = waitpid(pid, NULL, 0);
184 if (result == -1) {
185 fprintf(stderr, "Error waiting for termination of child process: (%d) %s\n",
186 errno, strerror(errno));
187 exit(1);
188 }
189 }
190 fprintf(stderr, "Completed!\n");
191 }
192
193 void child(char *argv1)
194 {
195 long index = strtol(argv1, NULL, 10);
196 struct TestCase testCase = TestCases[index];
197 TestBlock block = testCase.block;
198
199 const char *name = testCase.name;
200 if (strncmp(name, "free(", 5) == 0)
201 name += 5;
202 const char *paren = strchr(name, '(');
203 long len = paren != NULL ? paren - name : strlen(name);
204 fprintf(stderr, "Testing %.*s\n", (int)len, name);
205
206 // Make sure plain classes work.
207 block([TestRoot class]);
208 block(object_getClass([TestRoot class]));
209
210 // And framework classes.
211 block([NSObject class]);
212 block(object_getClass([NSObject class]));
213
214 // Test a constructed, unregistered class.
215 Class allocatedClass = objc_allocateClassPair([TestRoot class],
216 "AllocatedTestClass",
217 0);
218 class_getMethodImplementation(allocatedClass, @selector(self));
219 block(object_getClass(allocatedClass));
220 block(allocatedClass);
221
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",
226 0);
227 objc_registerClassPair(allocatedClass);
228 block(object_getClass(allocatedClass));
229 block(allocatedClass);
230
231 // Test a duplicated class.
232
233 Class duplicatedClass = objc_duplicateClass([TestRoot class],
234 "DuplicateClass",
235 0);
236 block(object_getClass(duplicatedClass));
237 block(duplicatedClass);
238
239 fprintf(stderr, "Completed test on good classes.\n");
240
241 // Test a fake class.
242 Class templateClass = objc_allocateClassPair([TestRoot class],
243 "TemplateClass",
244 0);
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");
249 }
250
251 int main(int argc, char **argv)
252 {
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.
258 if (argc == 1) {
259 parent(argv[0]);
260 } else {
261 child(argv[1]);
262 }
263 }