]> git.saurik.com Git - apple/objc4.git/blame - test/protocol.m
objc4-818.2.tar.gz
[apple/objc4.git] / test / protocol.m
CommitLineData
13ba007e
A
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/*
5TEST_BUILD_OUTPUT
6.*protocol.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
7END
8*/
9
10#include "test.h"
11#include "testroot.i"
12#include <string.h>
13#include <objc/runtime.h>
14#include <objc/objc-internal.h>
15
16@protocol Proto1
17+(id)proto1ClassMethod;
18-(id)proto1InstanceMethod;
19@end
20
21@protocol Proto2
22+(id)proto2ClassMethod;
23-(id)proto2InstanceMethod;
24@end
25
26@protocol Proto3 <Proto2>
27+(id)proto3ClassMethod;
28-(id)proto3InstanceMethod;
29@end
30
31@protocol Proto4
32@property int i;
33@end
34
35// Force some of Proto5's selectors out of address order rdar://10582325
36SEL 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#define SwiftV1MangledName "_TtP6Module15SwiftV1Protocol_"
65
66__attribute__((objc_runtime_name(SwiftV1MangledName)))
67@protocol SwiftV1Protocol
68@end
69
70@interface Super : TestRoot <Proto1> @end
71@implementation Super
72+(id)proto1ClassMethod { return self; }
73-(id)proto1InstanceMethod { return self; }
74@end
75
76@interface SubNoProtocols : Super @end
77@implementation SubNoProtocols @end
78
79@interface SuperNoProtocols : TestRoot @end
80@implementation SuperNoProtocols
81@end
82
83@interface SubProp : Super <Proto4> { int i; } @end
84@implementation SubProp
85@synthesize i;
86@end
87
88
89int main()
90{
91 Class cls;
92 Protocol * __unsafe_unretained *list;
93 Protocol *protocol, *empty;
94 struct objc_method_description desc2;
95 objc_property_t *proplist;
96 unsigned int count;
97
98 protocol = @protocol(Proto3);
99 empty = @protocol(ProtoEmpty);
100 testassert(protocol);
101 testassert(empty);
102
103 testassert(0 == strcmp(protocol_getName(protocol), "Proto3"));
104 testassert(0 == strcmp(protocol_getName(empty), "ProtoEmpty"));
105
106 testassert(class_conformsToProtocol([Super class], @protocol(Proto1)));
107 testassert(!class_conformsToProtocol([SubProp class], @protocol(Proto1)));
108 testassert(class_conformsToProtocol([SubProp class], @protocol(Proto4)));
109 testassert(!class_conformsToProtocol([SubProp class], @protocol(Proto3)));
110 testassert(!class_conformsToProtocol([Super class], @protocol(Proto3)));
111
112 testassert(!protocol_conformsToProtocol(@protocol(Proto1), @protocol(Proto2)));
113 testassert(protocol_conformsToProtocol(@protocol(Proto3), @protocol(Proto2)));
114 testassert(!protocol_conformsToProtocol(@protocol(Proto2), @protocol(Proto3)));
115
116 testassert(protocol_isEqual(@protocol(Proto1), @protocol(Proto1)));
117 testassert(! protocol_isEqual(@protocol(Proto1), @protocol(Proto2)));
118
119 desc2 = protocol_getMethodDescription(protocol, @selector(proto3InstanceMethod), YES, YES);
120 testassert(desc2.name && desc2.types);
121 testassert(desc2.name == @selector(proto3InstanceMethod));
122 desc2 = protocol_getMethodDescription(protocol, @selector(proto3ClassMethod), YES, NO);
123 testassert(desc2.name && desc2.types);
124 testassert(desc2.name == @selector(proto3ClassMethod));
125 desc2 = protocol_getMethodDescription(protocol, @selector(proto2ClassMethod), YES, NO);
126 testassert(desc2.name && desc2.types);
127 testassert(desc2.name == @selector(proto2ClassMethod));
128
129 desc2 = protocol_getMethodDescription(protocol, @selector(proto3ClassMethod), YES, YES);
130 testassert(!desc2.name && !desc2.types);
131 desc2 = protocol_getMethodDescription(protocol, @selector(proto3InstanceMethod), YES, NO);
132 testassert(!desc2.name && !desc2.types);
133 desc2 = protocol_getMethodDescription(empty, @selector(proto3ClassMethod), YES, YES);
134 testassert(!desc2.name && !desc2.types);
135 desc2 = protocol_getMethodDescription(empty, @selector(proto3InstanceMethod), YES, NO);
136 testassert(!desc2.name && !desc2.types);
137
138 count = 100;
139 list = protocol_copyProtocolList(@protocol(Proto2), &count);
140 testassert(!list);
141 testassert(count == 0);
142 count = 100;
143 list = protocol_copyProtocolList(@protocol(Proto3), &count);
144 testassert(list);
145 testassert(count == 1);
146 testassert(protocol_isEqual(list[0], @protocol(Proto2)));
147 testassert(!list[1]);
148 free(list);
149
150 count = 100;
151 cls = objc_getClass("Super");
152 testassert(cls);
153 list = class_copyProtocolList(cls, &count);
154 testassert(list);
155 testassert(list[count] == NULL);
156 testassert(count == 1);
157 testassert(0 == strcmp(protocol_getName(list[0]), "Proto1"));
158 free(list);
159
160 count = 100;
161 cls = objc_getClass("SuperNoProtocols");
162 testassert(cls);
163 list = class_copyProtocolList(cls, &count);
164 testassert(!list);
165 testassert(count == 0);
166
167 count = 100;
168 cls = objc_getClass("SubNoProtocols");
169 testassert(cls);
170 list = class_copyProtocolList(cls, &count);
171 testassert(!list);
172 testassert(count == 0);
173
174
175 cls = objc_getClass("SuperNoProtocols");
176 testassert(cls);
177 list = class_copyProtocolList(cls, NULL);
178 testassert(!list);
179
180 cls = objc_getClass("Super");
181 testassert(cls);
182 list = class_copyProtocolList(cls, NULL);
183 testassert(list);
184 free(list);
185
186 count = 100;
187 list = class_copyProtocolList(NULL, &count);
188 testassert(!list);
189 testassert(count == 0);
190
191
192 // Check property added by protocol
193 cls = objc_getClass("SubProp");
194 testassert(cls);
195
196 count = 100;
197 list = class_copyProtocolList(cls, &count);
198 testassert(list);
199 testassert(count == 1);
200 testassert(0 == strcmp(protocol_getName(list[0]), "Proto4"));
201 testassert(list[1] == NULL);
202 free(list);
203
204 count = 100;
205 proplist = class_copyPropertyList(cls, &count);
206 testassert(proplist);
207 testassert(count == 1);
208 testassert(0 == strcmp(property_getName(proplist[0]), "i"));
209 testassert(proplist[1] == NULL);
210 free(proplist);
211
212 // Check extended type encodings
213 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(DoesNotExist), true, true) == NULL);
214 testassert(_protocol_getMethodTypeEncoding(NULL, @selector(m11), true, true) == NULL);
215 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11), true, false) == NULL);
216 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11), false, false) == NULL);
217 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11), false, true) == NULL);
218 testassert(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m21), true, true) == NULL);
219#if __LP64__
220 const char *types11 = "@24@0:8@\"<Proto1>\"16";
221 const char *types12 = "v24@0:8@\"<Proto1>\"16";
222 const char *types13 = "i24@0:8@\"<Proto1>\"16";
223 const char *types21 = "@\"TestRoot\"24@0:8@\"TestRoot<Proto1>\"16";
224 const char *types22 = "v24@0:8@\"TestRoot<Proto1>\"16";
225 const char *types23 = "i24@0:8@\"TestRoot<Proto1>\"16";
226 const char *types31 = "@?<@@?@>24@0:8@?<@\"<Proto1>\"@?@\"<Proto1>\">16";
227 const char *types32 = "v24@0:8@?<@\"<Proto1>\"@?@\"<Proto1>\">16";
228 const char *types33 = "i24@0:8@?<@\"<Proto1>\"@?@\"<Proto1>\">16";
229 const char *types41 = "@?<@\"TestRoot\"@?@\"TestRoot\">24@0:8@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">16";
230 const char *types42 = "v24@0:8@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">16";
231 const char *types43 = "i24@0:8@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">16";
232#else
233 const char *types11 = "@12@0:4@\"<Proto1>\"8";
234 const char *types12 = "v12@0:4@\"<Proto1>\"8";
235 const char *types13 = "i12@0:4@\"<Proto1>\"8";
236 const char *types21 = "@\"TestRoot\"12@0:4@\"TestRoot<Proto1>\"8";
237 const char *types22 = "v12@0:4@\"TestRoot<Proto1>\"8";
238 const char *types23 = "i12@0:4@\"TestRoot<Proto1>\"8";
239 const char *types31 = "@?<@@?@>12@0:4@?<@\"<Proto1>\"@?@\"<Proto1>\">8";
240 const char *types32 = "v12@0:4@?<@\"<Proto1>\"@?@\"<Proto1>\">8";
241 const char *types33 = "i12@0:4@?<@\"<Proto1>\"@?@\"<Proto1>\">8";
242 const char *types41 = "@?<@\"TestRoot\"@?@\"TestRoot\">12@0:4@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">8";
243 const char *types42 = "v12@0:4@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">8";
244 const char *types43 = "i12@0:4@?<@\"TestRoot<Proto1>\"@?@\"TestRoot<Proto1>\">8";
245#endif
246
247 // Make sure some of Proto5's selectors are out of order rdar://10582325
248 // These comparisons deliberately look weird because they determine the
249 // selector order on some architectures.
250 testassert(sel_registerName("m11:") > sel_registerName("m12:") ||
251 sel_registerName("m21:") > sel_registerName("m22:") ||
252 sel_registerName("m32:") < sel_registerName("m31:") ||
253 sel_registerName("m42:") < sel_registerName("m41:") );
254
255 if (!_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11:), true, true)) {
256 fail("rdar://10492418 extended type encodings not present (is compiler old?)");
257 } else {
258 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m11:), true, true), types11));
259 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m12:), true, true), types12));
260 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m13:), true, true), types13));
261 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m21:), true, false), types21));
262 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m22:), true, false), types22));
263 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m23:), true, false), types23));
264 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m31:), false, true), types31));
265 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m32:), false, true), types32));
266 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m33:), false, true), types33));
267 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m41:), false, false), types41));
268 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m42:), false, false), types42));
269 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto5), @selector(m43:), false, false), types43));
270
271 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto6), @selector(n41:), false, false), types41));
272 testassert(0 == strcmp(_protocol_getMethodTypeEncoding(@protocol(Proto6), @selector(m41:), false, false), types41));
273 }
274
275 testassert(@protocol(SwiftV1Protocol) == objc_getProtocol("Module.SwiftV1Protocol"));
276 testassert(@protocol(SwiftV1Protocol) == objc_getProtocol(SwiftV1MangledName));
277 testassert(0 == strcmp(protocol_getName(@protocol(SwiftV1Protocol)), "Module.SwiftV1Protocol"));
278 testassert(!objc_getProtocol("SwiftV1Protocol"));
279
280 succeed(__FILE__);
281}