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