]> git.saurik.com Git - apple/objc4.git/blob - test/isaValidation.m
objc4-779.1.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 '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]+.
72 objc\[\d+\]: HALTED
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]+.
84 objc\[\d+\]: HALTED
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]+.
92 objc\[\d+\]: HALTED
93 Testing objc_duplicateClass
94 Completed test on good classes.
95 objc\[\d+\]: Attempt to use unknown class 0x[0-9a-f]+.
96 objc\[\d+\]: HALTED
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]+.
103 objc\[\d+\]: HALTED
104 Completed!
105 END
106 */
107
108 #include "test.h"
109 #include "testroot.i"
110 #include <spawn.h>
111
112 @protocol P
113 @end
114
115 extern char **environ;
116
117 id dummyIMP(id self, SEL _cmd) { (void)_cmd; return self; }
118
119 char *dupeName(Class cls) {
120 char *name;
121 asprintf(&name, "%sDuplicate", class_getName(cls));
122 return name;
123 }
124
125 typedef void (^TestBlock)(Class);
126 struct TestCase {
127 const char *name;
128 TestBlock block;
129 };
130
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( \
136 #__VA_ARGS__, \
137 if(class_isMetaClass(cls)) return; \
138 id obj = [TestRoot alloc]; \
139 *(Class *)obj = cls; \
140 __VA_ARGS__; \
141 )
142
143 struct TestCase TestCases[] = {
144 TESTCASE_OBJ(object_getMethodImplementation(obj, @selector(init))),
145
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)),
164 };
165
166 void parent(char *argv0)
167 {
168 int testCount = sizeof(TestCases) / sizeof(*TestCases);
169 for (int i = 0; i < testCount; i++) {
170 char *testIndex;
171 asprintf(&testIndex, "%d", i);
172 char *argvSpawn[] = {
173 argv0,
174 testIndex,
175 NULL
176 };
177 pid_t pid;
178 int result = posix_spawn(&pid, argv0, NULL, NULL, argvSpawn, environ);
179 if (result != 0) {
180 fprintf(stderr, "Could not spawn child process: (%d) %s\n",
181 errno, strerror(errno));
182 exit(1);
183 }
184
185 free(testIndex);
186
187 result = waitpid(pid, NULL, 0);
188 if (result == -1) {
189 fprintf(stderr, "Error waiting for termination of child process: (%d) %s\n",
190 errno, strerror(errno));
191 exit(1);
192 }
193 }
194 fprintf(stderr, "Completed!\n");
195 }
196
197 void child(char *argv1)
198 {
199 long index = strtol(argv1, NULL, 10);
200 struct TestCase testCase = TestCases[index];
201 TestBlock block = testCase.block;
202
203 const char *name = testCase.name;
204 if (strncmp(name, "free(", 5) == 0)
205 name += 5;
206 const char *paren = strchr(name, '(');
207 long len = paren != NULL ? paren - name : strlen(name);
208 fprintf(stderr, "Testing %.*s\n", (int)len, name);
209
210 // Make sure plain classes work.
211 block([TestRoot class]);
212 block(object_getClass([TestRoot class]));
213
214 // And framework classes.
215 block([NSObject class]);
216 block(object_getClass([NSObject class]));
217
218 // Test a constructed, unregistered class.
219 Class allocatedClass = objc_allocateClassPair([TestRoot class],
220 "AllocatedTestClass",
221 0);
222 class_getMethodImplementation(allocatedClass, @selector(self));
223 block(object_getClass(allocatedClass));
224 block(allocatedClass);
225
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",
230 0);
231 objc_registerClassPair(allocatedClass);
232 block(object_getClass(allocatedClass));
233 block(allocatedClass);
234
235 // Test a duplicated class.
236
237 Class duplicatedClass = objc_duplicateClass([TestRoot class],
238 "DuplicateClass",
239 0);
240 block(object_getClass(duplicatedClass));
241 block(duplicatedClass);
242
243 fprintf(stderr, "Completed test on good classes.\n");
244
245 // Test a fake class.
246 Class templateClass = objc_allocateClassPair([TestRoot class],
247 "TemplateClass",
248 0);
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");
253 }
254
255 int main(int argc, char **argv)
256 {
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.
262 if (argc == 1) {
263 parent(argv[0]);
264 } else {
265 child(argv[1]);
266 }
267 }