1/* 2TEST_BUILD 3 $C{COMPILE} $DIR/future0.m -o future0.dylib -dynamiclib 4 $C{COMPILE} $DIR/future2.m -x none future0.dylib -o future2.dylib -dynamiclib 5 $C{COMPILE} $DIR/future.m -x none future0.dylib -o future.out 6END 7*/ 8 9#include "test.h" 10 11#if __has_feature(objc_arc) 12 13int main() 14{ 15 testwarn("rdar://10041403 future class API is not ARC-compatible"); 16 succeed(__FILE__); 17} 18 19 20#else 21 22#include <objc/runtime.h> 23#include <malloc/malloc.h> 24#include <string.h> 25#include <dlfcn.h> 26#include "future.h" 27 28@implementation Sub2 29+(int)method { 30 return 2; 31} 32+(Class)classref { 33 return [Sub2 class]; 34} 35@end 36 37@implementation SubSub2 38+(int)method { 39 return 1 + [super method]; 40} 41@end 42 43int main() 44{ 45 Class oldTestRoot; 46 Class oldSub1; 47 Class newSub1; 48#if !__OBJC2__ 49 Class oldSub2; 50 Class newSub2; 51 uintptr_t buf[20]; 52#endif 53 54 // objc_getFutureClass with existing class 55 oldTestRoot = objc_getFutureClass("TestRoot"); 56 testassert(oldTestRoot == [TestRoot class]); 57 testassert(! _class_isFutureClass(oldTestRoot)); 58 59 // objc_getFutureClass with missing class 60 oldSub1 = objc_getFutureClass("Sub1"); 61 testassert(oldSub1); 62 testassert(malloc_size(objc_unretainedPointer(oldSub1)) > 0); 63 testassert(objc_getClass("Sub1") == Nil); 64 testassert(_class_isFutureClass(oldSub1)); 65 testassert(0 == strcmp(class_getName(oldSub1), "Sub1")); 66 testassert(object_getClass(oldSub1) == Nil); // CF expects this 67 68 // objc_getFutureClass a second time 69 testassert(oldSub1 == objc_getFutureClass("Sub1")); 70 71#if !__OBJC2__ 72 // objc_setFutureClass with existing class 73 oldSub2 = objc_getClass("Sub2"); 74 testassert(oldSub2 == [Sub2 class]); 75 testassert(oldSub2 == class_getSuperclass(objc_getClass("SubSub2"))); 76 objc_setFutureClass((Class)buf, "Sub2"); 77 testassert(0 == strcmp(class_getName((Class)buf), "Sub2")); 78 newSub2 = objc_getClass("Sub2"); 79 testassert(newSub2 == (Class)buf); 80 testassert(newSub2 != oldSub2); 81 // check classrefs 82 testassert(newSub2 == [Sub2 class]); 83 testassert(newSub2 == [newSub2 class]); 84 testassert(newSub2 == [newSub2 classref]); 85 testassert(newSub2 != [oldSub2 class]); 86 // check superclass chains 87 testassert(newSub2 == class_getSuperclass(objc_getClass("SubSub2"))); 88#else 89 // 64-bit ABI ignores objc_setFutureClass. 90#endif 91 92 // Load class Sub1 93 dlopen("future2.dylib", 0); 94 95 // Verify use of future class 96 newSub1 = objc_getClass("Sub1"); 97 testassert(oldSub1 == newSub1); 98 testassert(newSub1 == [newSub1 classref]); 99 testassert(newSub1 == class_getSuperclass(objc_getClass("SubSub1"))); 100 testassert(! _class_isFutureClass(newSub1)); 101 102 testassert(1 == [oldSub1 method]); 103 testassert(1 == [newSub1 method]); 104#if !__OBJC2__ 105 testassert(2 == [newSub2 method]); 106 testassert(2 == [oldSub2 method]); 107 testassert(3 == [SubSub2 method]); 108#endif 109 110 succeed(__FILE__); 111} 112 113#endif 114