]> git.saurik.com Git - apple/objc4.git/blob - test/ARCLayouts.m
objc4-818.2.tar.gz
[apple/objc4.git] / test / ARCLayouts.m
1 // Note that test ARCLayoutsWithoutWeak uses the same files
2 // with different build options.
3 /*
4 TEST_CONFIG MEM=arc
5 TEST_BUILD
6 mkdir -p $T{OBJDIR}
7 $C{COMPILE_NOLINK_NOMEM} -c $DIR/MRCBase.m -o $T{OBJDIR}/MRCBase.o
8 $C{COMPILE_NOLINK_NOMEM} -c $DIR/MRCARC.m -o $T{OBJDIR}/MRCARC.o
9 $C{COMPILE_NOLINK} -c $DIR/ARCBase.m -o $T{OBJDIR}/ARCBase.o
10 $C{COMPILE_NOLINK} -c $DIR/ARCMRC.m -o $T{OBJDIR}/ARCMRC.o
11 $C{COMPILE} '-DNAME=\"ARCLayouts.m\"' -fobjc-arc $DIR/ARCLayouts.m -x none $T{OBJDIR}/MRCBase.o $T{OBJDIR}/MRCARC.o $T{OBJDIR}/ARCBase.o $T{OBJDIR}/ARCMRC.o -framework Foundation -o ARCLayouts.exe
12 END
13 */
14
15 #include "test.h"
16 #import <stdio.h>
17 #import <Foundation/Foundation.h>
18 #import <objc/runtime.h>
19
20 #import "ARCMRC.h"
21 #import "MRCARC.h"
22
23 @interface NSObject (Layouts)
24 + (const char *)strongLayout;
25 + (const char *)weakLayout;
26 @end
27
28 void printlayout(const char *name, const uint8_t *layout)
29 {
30 if (!testverbose()) return;
31
32 testprintf("%s: ", name);
33
34 // these use fprintf() to avoid repeated VERBOSE: in the middle of the line
35 if (!layout) {
36 fprintf(stderr, "NULL\n");
37 return;
38 }
39
40 const uint8_t *c;
41 for (c = layout; *c; c++) {
42 fprintf(stderr, "%02x ", *c);
43 }
44
45 fprintf(stderr, "00\n");
46 }
47
48 @implementation NSObject (Layouts)
49
50 + (const char *)strongLayout {
51 const uint8_t *layout = class_getIvarLayout(self);
52 printlayout("strong", layout);
53 return (const char *)layout;
54 }
55
56 + (const char *)weakLayout {
57 const uint8_t *weakLayout = class_getWeakIvarLayout(self);
58 printlayout("weak", weakLayout);
59 return (const char *)weakLayout;
60 }
61
62 + (Ivar)instanceVariable:(const char *)name {
63 return class_getInstanceVariable(self, name);
64 }
65
66 @end
67
68 void checkMM(Class cls, const char *ivarName,
69 objc_ivar_memory_management_t mmExpected)
70 {
71 Ivar ivar = [cls instanceVariable:ivarName];
72 objc_ivar_memory_management_t mm = _class_getIvarMemoryManagement(cls,ivar);
73 testprintf("%s->%s want %d, got %d\n",
74 class_getName(cls), ivarName, mmExpected, mm);
75 testassert(mmExpected == mm);
76 }
77
78 int main (int argc __unused, const char * argv[] __unused) {
79
80 testprintf("ARCMRC\n");
81 testassert(strcmp([ARCMRC strongLayout], "\x01") == 0);
82 testassert([ARCMRC weakLayout] == NULL);
83
84
85 // Verify that ARCBase->misalign and MRCBase->alignment did their thing.
86 testassert(ivar_getOffset(class_getInstanceVariable([ARCBase class], "misalign2")) & 1);
87 testassert(ivar_getOffset(class_getInstanceVariable([MRCBase class], "alignment")) > (ptrdiff_t)sizeof(void*));
88
89 testprintf("ARCMisalign\n");
90 testassert([ARCMisalign strongLayout] == NULL);
91 testassert([ARCMisalign weakLayout] == NULL);
92
93 testprintf("ARCBase\n");
94 if (strcmp([ARCBase strongLayout], "\x11\x30") == 0) {
95 testwarn("1130 layout is a compiler flaw but doesn't fail");
96 } else {
97 testassert(strcmp([ARCBase strongLayout], "\x11") == 0);
98 }
99 testassert(strcmp([ARCBase weakLayout], "\x31") == 0);
100
101 testprintf("MRCARC\n");
102 testassert([MRCARC strongLayout] == NULL);
103 testassert([MRCARC weakLayout] == NULL);
104
105 testprintf("MRCBase\n");
106 // MRC marks __weak only.
107 testassert([MRCBase strongLayout] == NULL);
108 if (supportsMRCWeak) {
109 testassert(strcmp([MRCBase weakLayout], "\x71") == 0);
110 } else {
111 testassert([MRCBase weakLayout] == nil);
112 }
113
114 // now check consistency between dynamic accessors and KVC, etc.
115 ARCMRC *am = [ARCMRC new];
116 MRCARC *ma = [MRCARC new];
117
118 NSString *amValue = [[NSString alloc] initWithFormat:@"%s %p", "ARCMRC", am];
119 NSString *amValue2 = [[NSString alloc] initWithFormat:@"%s %p", "ARCMRC", am];
120 NSString *maValue = [[NSString alloc] initWithFormat:@"%s %p", "MRCARC", ma];
121 NSString *maValue2 = [[NSString alloc] initWithFormat:@"%s %p", "MRCARC", ma];
122
123 am.number = M_PI;
124
125 object_setIvar(am, [ARCMRC instanceVariable:"object"], amValue);
126 testassert(CFGetRetainCount((__bridge CFTypeRef)amValue) == 1);
127 testassert(am.object == amValue);
128
129 object_setIvarWithStrongDefault(am, [ARCMRC instanceVariable:"object"], amValue2);
130 testassert(CFGetRetainCount((__bridge CFTypeRef)amValue2) == 2);
131 testassert(am.object == amValue2);
132
133 am.pointer = @selector(ARCMRC);
134
135 object_setIvar(am, [ARCMRC instanceVariable:"delegate"], ma);
136 testassert(CFGetRetainCount((__bridge CFTypeRef)ma) == 1);
137 testassert(am.delegate == ma);
138
139 object_setIvarWithStrongDefault(am, [ARCMRC instanceVariable:"delegate"], ma);
140 testassert(CFGetRetainCount((__bridge CFTypeRef)ma) == 1);
141 testassert(am.delegate == ma);
142
143
144 ma.number = M_E;
145
146 object_setIvar(ma, [MRCARC instanceVariable:"object"], maValue);
147 testassert(CFGetRetainCount((__bridge CFTypeRef)maValue) == 2);
148 @autoreleasepool {
149 testassert(ma.object == maValue);
150 }
151
152 object_setIvarWithStrongDefault(ma, [MRCARC instanceVariable:"object"], maValue2);
153 testassert(CFGetRetainCount((__bridge CFTypeRef)maValue2) == 2);
154 @autoreleasepool {
155 testassert(ma.object == maValue2);
156 }
157
158 ma.pointer = @selector(MRCARC);
159
160 ma.delegate = am;
161 object_setIvar(ma, [MRCARC instanceVariable:"delegate"], am);
162 testassert(CFGetRetainCount((__bridge CFTypeRef)am) == 1);
163 @autoreleasepool {
164 testassert(ma.delegate == am);
165 }
166
167 object_setIvarWithStrongDefault(ma, [MRCARC instanceVariable:"delegate"], am);
168 testassert(CFGetRetainCount((__bridge CFTypeRef)am) == 1);
169 @autoreleasepool {
170 testassert(ma.delegate == am);
171 }
172
173
174 // Verify that object_copy() handles ARC variables correctly.
175
176 MRCARC *ma2 = docopy(ma);
177 testassert(ma2);
178 testassert(ma2 != ma);
179 testassert(CFGetRetainCount((__bridge CFTypeRef)maValue2) == 3);
180 testassert(CFGetRetainCount((__bridge CFTypeRef)am) == 1);
181 testassert(ma2.number == ma.number);
182 testassert(ma2.object == ma.object);
183 @autoreleasepool {
184 testassert(ma2.delegate == ma.delegate);
185 }
186 testassert(ma2.pointer == ma.pointer);
187
188
189 // Test _class_getIvarMemoryManagement() SPI
190
191 objc_ivar_memory_management_t memoryMRCWeak =
192 supportsMRCWeak ? objc_ivar_memoryWeak : objc_ivar_memoryUnknown;
193 checkMM([ARCMRC class], "number", objc_ivar_memoryUnknown);
194 checkMM([ARCMRC class], "object", objc_ivar_memoryUnknown);
195 checkMM([ARCMRC class], "pointer", objc_ivar_memoryUnknown);
196 checkMM([ARCMRC class], "delegate", memoryMRCWeak);
197 checkMM([ARCMRC class], "dataSource", objc_ivar_memoryStrong);
198
199 checkMM([MRCARC class], "number", objc_ivar_memoryUnretained);
200 checkMM([MRCARC class], "object", objc_ivar_memoryStrong);
201 checkMM([MRCARC class], "pointer", objc_ivar_memoryUnretained);
202 checkMM([MRCARC class], "delegate", objc_ivar_memoryWeak);
203 checkMM([MRCARC class], "dataSource", objc_ivar_memoryUnknown);
204
205 checkMM([ARCBase class], "number", objc_ivar_memoryUnretained);
206 checkMM([ARCBase class], "object", objc_ivar_memoryStrong);
207 checkMM([ARCBase class], "pointer", objc_ivar_memoryUnretained);
208 checkMM([ARCBase class], "delegate", objc_ivar_memoryWeak);
209
210 checkMM([MRCBase class], "number", objc_ivar_memoryUnknown);
211 checkMM([MRCBase class], "object", objc_ivar_memoryUnknown);
212 checkMM([MRCBase class], "pointer", objc_ivar_memoryUnknown);
213 checkMM([MRCBase class], "delegate", memoryMRCWeak);
214
215 succeed(NAME);
216 return 0;
217 }