]> git.saurik.com Git - apple/objc4.git/blob - test/protocol.m
objc4-532.tar.gz
[apple/objc4.git] / test / protocol.m
1 // TEST_CFLAGS -framework Foundation -Wno-deprecated-declarations
2 // need Foundation to get NSObject compatibility additions for class Protocol
3 // because ARC calls [protocol retain]
4
5 #include "test.h"
6 #include "testroot.i"
7 #include <string.h>
8 #include <objc/runtime.h>
9 #include <objc/objc-internal.h>
10
11 #if !__OBJC2__
12 #include <objc/Protocol.h>
13 #endif
14
15 @protocol Proto1
16 +(id)proto1ClassMethod;
17 -(id)proto1InstanceMethod;
18 @end
19
20 @protocol Proto2
21 +(id)proto2ClassMethod;
22 -(id)proto2InstanceMethod;
23 @end
24
25 @protocol Proto3 <Proto2>
26 +(id)proto3ClassMethod;
27 -(id)proto3InstanceMethod;
28 @end
29
30 @protocol Proto4
31 @property int i;
32 @end
33
34
35 // Force some of Proto5's selectors out of address order rdar://10582325
36 SEL fn(int x) { if (x) return @selector(m12:); else return @selector(m22:); }
37
38 // This declaration order deliberately looks weird because it determines the
39 // selector address order on some architectures rdar://10582325
40 @protocol Proto5
41 -(id)m11:(id<Proto1>)a;
42 -(void)m12:(id<Proto1>)a;
43 -(int)m13:(id<Proto1>)a;
44 +(void)m22:(TestRoot<Proto1>*)a;
45 +(int)m23:(TestRoot<Proto1>*)a;
46 +(TestRoot*)m21:(TestRoot<Proto1>*)a;
47 @optional
48 -(id(^)(id))m31:(id<Proto1>(^)(id<Proto1>))a;
49 -(void)m32:(id<Proto1>(^)(id<Proto1>))a;
50 -(int)m33:(id<Proto1>(^)(id<Proto1>))a;
51 +(void)m42:(TestRoot<Proto1>*(^)(TestRoot<Proto1>*))a;
52 +(int)m43:(TestRoot<Proto1>*(^)(TestRoot<Proto1>*))a;
53 +(TestRoot*(^)(TestRoot*))m41:(TestRoot<Proto1>*(^)(TestRoot<Proto1>*))a;
54 @end
55
56 @protocol Proto6 <Proto5>
57 @optional
58 +(TestRoot*(^)(TestRoot*))n41:(TestRoot<Proto1>*(^)(TestRoot<Proto1>*))a;
59 @end
60
61 @protocol ProtoEmpty
62 @end
63
64 @interface Super : TestRoot <Proto1> @end
65 @implementation Super
66 +(id)proto1ClassMethod { return self; }
67 -(id)proto1InstanceMethod { return self; }
68 @end
69
70 @interface SubNoProtocols : Super @end
71 @implementation SubNoProtocols @end
72
73 @interface SuperNoProtocols : TestRoot @end
74 @implementation SuperNoProtocols
75 @end
76
77 @interface SubProp : Super <Proto4> { int i; } @end
78 @implementation SubProp
79 @synthesize i;
80 @end
81
82
83 int main()
84 {
85 Class cls;
86 Protocol * __unsafe_unretained *list;
87 Protocol *protocol, *empty;
88 #if !__OBJC2__
89 struct objc_method_description *desc;
90 #endif
91 struct objc_method_description desc2;
92 objc_property_t *proplist;
93 unsigned int count;
94
95 protocol = @protocol(Proto3);
96 empty = @protocol(ProtoEmpty);
97 testassert(protocol);
98 testassert(empty);
99
100 #if !__OBJC2__
101 testassert([protocol isKindOf:[Protocol class]]);
102 testassert([empty isKindOf:[Protocol class]]);
103 testassert(0 == strcmp([protocol name], "Proto3"));
104 testassert(0 == strcmp([empty name], "ProtoEmpty"));
105 #endif
106 testassert(0 == strcmp(protocol_getName(protocol), "Proto3"));
107 testassert(0 == strcmp(protocol_getName(empty), "ProtoEmpty"));
108
109 testassert(class_conformsToProtocol([Super class], @protocol(Proto1)));
110 testassert(!class_conformsToProtocol([SubProp class], @protocol(Proto1)));
111 testassert(class_conformsToProtocol([SubProp class], @protocol(Proto4)));
112 testassert(!class_conformsToProtocol([SubProp class], @protocol(Proto3)));
113 testassert(!class_conformsToProtocol([Super class], @protocol(Proto3)));
114
115 testassert(!protocol_conformsToProtocol(@protocol(Proto1), @protocol(Proto2)));
116 testassert(protocol_conformsToProtocol(@protocol(Proto3), @protocol(Proto2)));
117 testassert(!protocol_conformsToProtocol(@protocol(Proto2), @protocol(Proto3)));
118
119 #if !__OBJC2__
120 testassert([@protocol(Proto1) isEqual:@protocol(Proto1)]);
121 testassert(! [@protocol(Proto1) isEqual:@protocol(Proto2)]);
122 #endif
123 testassert(protocol_isEqual(@protocol(Proto1), @protocol(Proto1)));
124 testassert(! protocol_isEqual(@protocol(Proto1), @protocol(Proto2)));
125
126 #if !__OBJC2__
127 desc = [protocol descriptionForInstanceMethod:@selector(proto3InstanceMethod)];
128 testassert(desc);
129 testassert(desc->name == @selector(proto3InstanceMethod));
130 desc = [protocol descriptionForClassMethod:@selector(proto3ClassMethod)];
131 testassert(desc);
132 testassert(desc->name == @selector(proto3ClassMethod));
133 desc = [protocol descriptionForClassMethod:@selector(proto2ClassMethod)];
134 testassert(desc);
135 testassert(desc->name == @selector(proto2ClassMethod));
136
137 desc = [protocol descriptionForInstanceMethod:@selector(proto3ClassMethod)];
138 testassert(!desc);
139 desc = [protocol descriptionForClassMethod:@selector(proto3InstanceMethod)];
140 testassert(!desc);
141 desc = [empty descriptionForInstanceMethod:@selector(proto3ClassMethod)];
142 testassert(!desc);
143 desc = [empty descriptionForClassMethod:@selector(proto3InstanceMethod)];
144 testassert(!desc);
145 #endif
146 desc2 = protocol_getMethodDescription(protocol, @selector(proto3InstanceMethod), YES, YES);
147 testassert(desc2.name && desc2.types);
148 testassert(desc2.name == @selector(proto3InstanceMethod));
149 desc2 = protocol_getMethodDescription(protocol, @selector(proto3ClassMethod), YES, NO);
150 testassert(desc2.name && desc2.types);
151 testassert(desc2.name == @selector(proto3ClassMethod));
152 desc2 = protocol_getMethodDescription(protocol, @selector(proto2ClassMethod), YES, NO);
153 testassert(desc2.name && desc2.types);
154 testassert(desc2.name == @selector(proto2ClassMethod));
155
156 desc2 = protocol_getMethodDescription(protocol, @selector(proto3ClassMethod), YES, YES);
157 testassert(!desc2.name && !desc2.types);
158 desc2 = protocol_getMethodDescription(protocol, @selector(proto3InstanceMethod), YES, NO);
159 testassert(!desc2.name && !desc2.types);
160 desc2 = protocol_getMethodDescription(empty, @selector(proto3ClassMethod), YES, YES);
161 testassert(!desc2.name && !desc2.types);
162 desc2 = protocol_getMethodDescription(empty, @selector(proto3InstanceMethod), YES, NO);
163 testassert(!desc2.name && !desc2.types);
164
165 count = 100;
166 list = protocol_copyProtocolList(@protocol(Proto2), &count);
167 testassert(!list);
168 testassert(count == 0);
169 count = 100;
170 list = protocol_copyProtocolList(@protocol(Proto3), &count);
171 testassert(list);
172 testassert(count == 1);
173 testassert(protocol_isEqual(list[0], @protocol(Proto2)));
174 testassert(!list[1]);
175 free(list);
176
177 count = 100;
178 cls = objc_getClass("Super");
179 testassert(cls);
180 list = class_copyProtocolList(cls, &count);
181 testassert(list);
182 testassert(list[count] == NULL);
183 testassert(count == 1);
184 testassert(0 == strcmp(protocol_getName(list[0]), "Proto1"));
185 free(list);
186
187 count = 100;
188 cls = objc_getClass("SuperNoProtocols");
189 testassert(cls);
190 list = class_copyProtocolList(cls, &count);
191 testassert(!list);
192 testassert(count == 0);
193
194 count = 100;
195 cls = objc_getClass("SubNoProtocols");
196 testassert(cls);
197 list = class_copyProtocolList(cls, &count);
198 testassert(!list);
199 testassert(count == 0);
200
201
202 cls = objc_getClass("SuperNoProtocols");
203 testassert(cls);
204 list = class_copyProtocolList(cls, NULL);
205 testassert(!list);
206
207 cls = objc_getClass("Super");
208 testassert(cls);
209 list = class_copyProtocolList(cls, NULL);
210 testassert(list);
211 free(list);
212
213 count = 100;
214 list = class_copyProtocolList(NULL, &count);
215 testassert(!list);
216 testassert(count == 0);
217
218
219 // Check property added by protocol
220 cls = objc_getClass("SubProp");
221 testassert(cls);
222
223 count = 100;
224 list = class_copyProtocolList(cls, &count);
225 testassert(list);
226 testassert(count == 1);
227 testassert(0 == strcmp(protocol_getName(list[0]), "Proto4"));
228 testassert(list[1] == NULL);
229 free(list);
230
231 count = 100;
232 proplist = class_copyPropertyList(cls, &count);
233 testassert(proplist);
234 testassert(count == 1);
235 testassert(0 == strcmp(property_getName(proplist[0]), "i"));
236 testassert(proplist[1] == NULL);
237 free(proplist);
238
239 // Check extended type encodings
240 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(DoesNotExist), true, true) == NULL);
241 testassert(_protocol_getMethodTypeEncoding(NULL, @selector(m11), true, true) == NULL);
242 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11), true, false) == NULL);
243 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11), false, false) == NULL);
244 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11), false, true) == NULL);
245 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m21), true, true) == NULL);
246 #if __LP64__
247 const char *types11 = "@24@0:8@\"<Proto1>\"16";
248 const char *types12 = "v24@0:8@\"<Proto1>\"16";
249 const char *types13 = "i24@0:8@\"<Proto1>\"16";
250 const char *types21 = "@\"TestRoot\"24@0:8@\"TestRoot<Proto1>\"16";
251 const char *types22 = "v24@0:8@\"TestRoot<Proto1>\"16";
252 const char *types23 = "i24@0:8@\"TestRoot<Proto1>\"16";
253 const char *types31 = "@?<@@?@>24@0:8@?<@\"<Proto1>\"@?@\"<Proto1>\">16";
254 const char *types32 = "v24@0:8@?<@\"<Proto1>\"@?@\"<Proto1>\">16";
255 const char *types33 = "i24@0:8@?<@\"<Proto1>\"@?@\"<Proto1>\">16";
256 const char *types41 = "@?<@\"TestRoot\"@?@\"TestRoot\">24@0:8@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">16";
257 const char *types42 = "v24@0:8@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">16";
258 const char *types43 = "i24@0:8@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">16";
259 #else
260 const char *types11 = "@12@0:4@\"<Proto1>\"8";
261 const char *types12 = "v12@0:4@\"<Proto1>\"8";
262 const char *types13 = "i12@0:4@\"<Proto1>\"8";
263 const char *types21 = "@\"TestRoot\"12@0:4@\"TestRoot<Proto1>\"8";
264 const char *types22 = "v12@0:4@\"TestRoot<Proto1>\"8";
265 const char *types23 = "i12@0:4@\"TestRoot<Proto1>\"8";
266 const char *types31 = "@?<@@?@>12@0:4@?<@\"<Proto1>\"@?@\"<Proto1>\">8";
267 const char *types32 = "v12@0:4@?<@\"<Proto1>\"@?@\"<Proto1>\">8";
268 const char *types33 = "i12@0:4@?<@\"<Proto1>\"@?@\"<Proto1>\">8";
269 const char *types41 = "@?<@\"TestRoot\"@?@\"TestRoot\">12@0:4@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">8";
270 const char *types42 = "v12@0:4@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">8";
271 const char *types43 = "i12@0:4@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">8";
272 #endif
273
274 // Make sure some of Proto5's selectors are out of order rdar://10582325
275 // These comparisons deliberately look weird because they determine the
276 // selector order on some architectures.
277 testassert(sel_registerName("m11:") > sel_registerName("m12:") ||
278 sel_registerName("m21:") > sel_registerName("m22:") ||
279 sel_registerName("m32:") < sel_registerName("m31:") ||
280 sel_registerName("m42:") < sel_registerName("m41:") );
281
282 if (!_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11:), true, true)) {
283 #if __clang__
284 testwarn("rdar://10492418 extended type encodings not present (is compiler old?)");
285 #else
286 // extended type encodings quietly not supported
287 testwarn("rdar://10492418 extended type encodings not present (compiler is not clang?)");
288 #endif
289 } else {
290 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11:), true, true), types11));
291 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m12:), true, true), types12));
292 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m13:), true, true), types13));
293 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m21:), true, false), types21));
294 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m22:), true, false), types22));
295 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m23:), true, false), types23));
296 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m31:), false, true), types31));
297 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m32:), false, true), types32));
298 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m33:), false, true), types33));
299 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m41:), false, false), types41));
300 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m42:), false, false), types42));
301 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m43:), false, false), types43));
302
303 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto6), @selector(n41:), false, false), types41));
304 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto6), @selector(m41:), false, false), types41));
305 }
306
307 succeed(__FILE__);
308 }