isaValidation.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. #include "test.h"
  108. #include "testroot.i"
  109. #include <spawn.h>
  110. @protocol P
  111. @end
  112. extern char **environ;
  113. id dummyIMP(id self, SEL _cmd) { (void)_cmd; return self; }
  114. char *dupeName(Class cls) {
  115. char *name;
  116. asprintf(&name, "%sDuplicate", class_getName(cls));
  117. return name;
  118. }
  119. typedef void (^TestBlock)(Class);
  120. struct TestCase {
  121. const char *name;
  122. TestBlock block;
  123. };
  124. #define NAMED_TESTCASE(name, ...) { name, ^(Class cls) { __VA_ARGS__; } }
  125. #define TESTCASE(...) NAMED_TESTCASE(#__VA_ARGS__, __VA_ARGS__)
  126. #define TESTCASE_NOMETA(...) \
  127. NAMED_TESTCASE( #__VA_ARGS__, if(class_isMetaClass(cls)) return; __VA_ARGS__; )
  128. #define TESTCASE_OBJ(...) NAMED_TESTCASE( \
  129. #__VA_ARGS__, \
  130. if(class_isMetaClass(cls)) return; \
  131. id obj = [TestRoot alloc]; \
  132. *(Class *)obj = cls; \
  133. __VA_ARGS__; \
  134. )
  135. struct TestCase TestCases[] = {
  136. TESTCASE_OBJ(object_getMethodImplementation(obj, @selector(init))),
  137. TESTCASE(class_getInstanceMethod(cls, @selector(init))),
  138. TESTCASE(class_getMethodImplementation(cls, @selector(init))),
  139. TESTCASE(class_respondsToSelector(cls, @selector(init))),
  140. TESTCASE(class_conformsToProtocol(cls, @protocol(P))),
  141. TESTCASE(free(class_copyProtocolList(cls, NULL))),
  142. TESTCASE(class_getProperty(cls, "x")),
  143. TESTCASE(free(class_copyPropertyList(cls, NULL))),
  144. TESTCASE(class_addMethod(cls, @selector(nop), (IMP)dummyIMP, "v@:")),
  145. TESTCASE(class_replaceMethod(cls, @selector(nop), (IMP)dummyIMP, "v@:")),
  146. TESTCASE(class_addIvar(cls, "x", sizeof(int), sizeof(int), @encode(int))),
  147. TESTCASE(class_addProtocol(cls, @protocol(P))),
  148. TESTCASE(class_addProperty(cls, "x", NULL, 0)),
  149. TESTCASE(class_replaceProperty(cls, "x", NULL, 0)),
  150. TESTCASE(class_setIvarLayout(cls, NULL)),
  151. TESTCASE(class_setWeakIvarLayout(cls, NULL)),
  152. TESTCASE_NOMETA(objc_registerClassPair(cls)),
  153. TESTCASE_NOMETA(objc_duplicateClass(cls, dupeName(cls), 0)),
  154. TESTCASE_NOMETA(objc_disposeClassPair(cls)),
  155. };
  156. void parent(char *argv0)
  157. {
  158. int testCount = sizeof(TestCases) / sizeof(*TestCases);
  159. for (int i = 0; i < testCount; i++) {
  160. char *testIndex;
  161. asprintf(&testIndex, "%d", i);
  162. char *argvSpawn[] = {
  163. argv0,
  164. testIndex,
  165. NULL
  166. };
  167. pid_t pid;
  168. int result = posix_spawn(&pid, argv0, NULL, NULL, argvSpawn, environ);
  169. if (result != 0) {
  170. fprintf(stderr, "Could not spawn child process: (%d) %s\n",
  171. errno, strerror(errno));
  172. exit(1);
  173. }
  174. free(testIndex);
  175. result = waitpid(pid, NULL, 0);
  176. if (result == -1) {
  177. fprintf(stderr, "Error waiting for termination of child process: (%d) %s\n",
  178. errno, strerror(errno));
  179. exit(1);
  180. }
  181. }
  182. fprintf(stderr, "Completed!\n");
  183. }
  184. void child(char *argv1)
  185. {
  186. long index = strtol(argv1, NULL, 10);
  187. struct TestCase testCase = TestCases[index];
  188. TestBlock block = testCase.block;
  189. const char *name = testCase.name;
  190. if (strncmp(name, "free(", 5) == 0)
  191. name += 5;
  192. const char *paren = strchr(name, '(');
  193. long len = paren != NULL ? paren - name : strlen(name);
  194. fprintf(stderr, "Testing %.*s\n", (int)len, name);
  195. // Make sure plain classes work.
  196. block([TestRoot class]);
  197. block(object_getClass([TestRoot class]));
  198. // And framework classes.
  199. block([NSObject class]);
  200. block(object_getClass([NSObject class]));
  201. // Test a constructed, unregistered class.
  202. Class allocatedClass = objc_allocateClassPair([TestRoot class],
  203. "AllocatedTestClass",
  204. 0);
  205. class_getMethodImplementation(allocatedClass, @selector(self));
  206. block(object_getClass(allocatedClass));
  207. block(allocatedClass);
  208. // Test a constructed, registered class. (Do this separately so
  209. // test cases can dispose of the class if needed.)
  210. allocatedClass = objc_allocateClassPair([TestRoot class],
  211. "AllocatedTestClass2",
  212. 0);
  213. objc_registerClassPair(allocatedClass);
  214. block(object_getClass(allocatedClass));
  215. block(allocatedClass);
  216. // Test a duplicated class.
  217. Class duplicatedClass = objc_duplicateClass([TestRoot class],
  218. "DuplicateClass",
  219. 0);
  220. block(object_getClass(duplicatedClass));
  221. block(duplicatedClass);
  222. fprintf(stderr, "Completed test on good classes.\n");
  223. // Test a fake class.
  224. Class templateClass = objc_allocateClassPair([TestRoot class],
  225. "TemplateClass",
  226. 0);
  227. void *fakeClass = malloc(malloc_size(templateClass));
  228. memcpy(fakeClass, templateClass, malloc_size(templateClass));
  229. block((Class)fakeClass);
  230. fail("Should have died on the fake class");
  231. }
  232. int main(int argc, char **argv)
  233. {
  234. // We want to run a bunch of tests, all of which end in _objc_fatal
  235. // (at least if they succeed). Spawn one subprocess per test and
  236. // have the parent process manage it all. The test will begin by
  237. // running parent(), which will repeatedly re-spawn this program to
  238. // call child() with the index of the test to run.
  239. if (argc == 1) {
  240. parent(argv[0]);
  241. } else {
  242. child(argv[1]);
  243. }
  244. }