1// TEST_CONFIG MEM=mrc 2// TEST_CRASHES 3/* 4TEST_RUN_OUTPUT 5objc\[\d+\]: Cannot form weak reference to instance \(0x[0-9a-f]+\) of class Crash. It is possible that this object was over-released, or is in the process of deallocation. 6CRASHED: SIG(ILL|TRAP) 7END 8*/ 9 10#include "test.h" 11 12#include <Foundation/NSObject.h> 13 14static id weak; 15static id weak2; 16static bool did_dealloc; 17 18@interface Test : NSObject @end 19@implementation Test 20-(void)dealloc { 21 testassert(weak == self); 22 testassert(weak2 == self); 23 24 testprintf("Weak references clear during super dealloc\n"); 25 testassert(weak2 != NULL); 26 [super dealloc]; 27 testassert(weak2 == NULL); 28 29 did_dealloc = true; 30} 31@end 32 33@interface Crash : NSObject @end 34@implementation Crash 35-(void)dealloc { 36 testassert(weak == self); 37 testassert(weak2 == self); 38 39 testprintf("Weak store crashes while deallocating\n"); 40 objc_storeWeak(&weak, self); 41 fail("objc_storeWeak of deallocating value should have crashed"); 42 [super dealloc]; 43} 44@end 45 46 47void cycle(Test *obj, Test *obj2) 48{ 49 id result; 50 51 testprintf("Weak assignment\n"); 52 result = objc_storeWeak(&weak, obj); 53 testassert(result == obj); 54 testassert(weak == obj); 55 56 testprintf("Weak assignment to the same value\n"); 57 result = objc_storeWeak(&weak, obj); 58 testassert(result == obj); 59 testassert(weak == obj); 60 61 testprintf("Weak assignment to different value\n"); 62 result = objc_storeWeak(&weak, obj2); 63 testassert(result == obj2); 64 testassert(weak == obj2); 65 66 testprintf("Weak assignment to NULL\n"); 67 result = objc_storeWeak(&weak, NULL); 68 testassert(result == NULL); 69 testassert(weak == NULL); 70 71 testprintf("Weak re-assignment to NULL\n"); 72 result = objc_storeWeak(&weak, NULL); 73 testassert(result == NULL); 74 testassert(weak == NULL); 75 76 testprintf("Weak move\n"); 77 result = objc_storeWeak(&weak, obj); 78 testassert(result == obj); 79 testassert(weak == obj); 80 weak2 = (id)(PAGE_SIZE-16); 81 objc_moveWeak(&weak2, &weak); 82 testassert(weak == nil); 83 testassert(weak2 == obj); 84 objc_storeWeak(&weak2, NULL); 85 86 testprintf("Weak copy\n"); 87 result = objc_storeWeak(&weak, obj); 88 testassert(result == obj); 89 testassert(weak == obj); 90 weak2 = (id)(PAGE_SIZE-16); 91 objc_copyWeak(&weak2, &weak); 92 testassert(weak == obj); 93 testassert(weak2 == obj); 94 objc_storeWeak(&weak, NULL); 95 objc_storeWeak(&weak2, NULL); 96 97 testprintf("Weak clear\n"); 98 99 id obj3 = [Test new]; 100 101 result = objc_storeWeak(&weak, obj3); 102 testassert(result == obj3); 103 testassert(weak == obj3); 104 105 result = objc_storeWeak(&weak2, obj3); 106 testassert(result == obj3); 107 testassert(weak2 == obj3); 108 109 did_dealloc = false; 110 [obj3 release]; 111 testassert(did_dealloc); 112 testassert(weak == NULL); 113 testassert(weak2 == NULL); 114} 115 116 117int main() 118{ 119 Test *obj = [Test new]; 120 Test *obj2 = [Test new]; 121 id result; 122 123 for (int i = 0; i < 100000; i++) { 124 if (i == 10) leak_mark(); 125 cycle(obj, obj2); 126 } 127 // allow some slop for [Test new] inside cycle() 128 // to land in different side table stripes 129 leak_check(3072); 130 131 132 // rdar://14105994 133 id weaks[8]; 134 for (size_t i = 0; i < sizeof(weaks)/sizeof(weaks[0]); i++) { 135 objc_storeWeak(&weaks[i], obj); 136 } 137 for (size_t i = 0; i < sizeof(weaks)/sizeof(weaks[0]); i++) { 138 objc_storeWeak(&weaks[i], nil); 139 } 140 141 142 Crash *obj3 = [Crash new]; 143 result = objc_storeWeak(&weak, obj3); 144 testassert(result == obj3); 145 testassert(weak == obj3); 146 147 result = objc_storeWeak(&weak2, obj3); 148 testassert(result == obj3); 149 testassert(weak2 == obj3); 150 151 [obj3 release]; 152 fail("should have crashed in -[Crash dealloc]"); 153} 154