]> git.saurik.com Git - apple/objc4.git/blob - test/addProtocol.m
objc4-756.2.tar.gz
[apple/objc4.git] / test / addProtocol.m
1 /*
2 TEST_CFLAGS -framework Foundation
3 TEST_BUILD_OUTPUT
4 .*addProtocol.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
5 .*addProtocol.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
6 .*addProtocol.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
7 .*addProtocol.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
8 .*addProtocol.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
9 END
10 TEST_RUN_OUTPUT
11 objc\[\d+\]: protocol_addProtocol: added protocol 'EmptyProto' is still under construction!
12 objc\[\d+\]: objc_registerProtocol: protocol 'Proto1' was already registered!
13 objc\[\d+\]: protocol_addProtocol: modified protocol 'Proto1' is not under construction!
14 objc\[\d+\]: protocol_addMethodDescription: protocol 'Proto1' is not under construction!
15 objc\[\d+\]: objc_registerProtocol: protocol 'SuperProto' was already registered!
16 objc\[\d+\]: protocol_addProtocol: modified protocol 'SuperProto' is not under construction!
17 objc\[\d+\]: protocol_addMethodDescription: protocol 'SuperProto' is not under construction!
18 OK: addProtocol.m
19 END
20 */
21
22 #include "test.h"
23
24 #include <objc/runtime.h>
25 #include <Foundation/Foundation.h>
26
27 @protocol SuperProto @end
28 @protocol SuperProto2 @end
29 @protocol UnrelatedProto @end
30
31
32 void Crash(id self, SEL _cmd)
33 {
34 fail("%c[%s %s] called unexpectedly",
35 class_isMetaClass(object_getClass(self)) ? '+' : '-',
36 object_getClassName(self), sel_getName(_cmd));
37 }
38
39
40 int main()
41 {
42 // old-ABI implementation of [Protocol retain]
43 // is added by +[NSObject(NSObject) load] in CF.
44 [NSObject class];
45
46 Protocol *proto, *proto2;
47 Protocol * __unsafe_unretained *protolist;
48 struct objc_method_description *desclist;
49 objc_property_t *proplist;
50 unsigned int count;
51
52 // If objc_registerProtocol() fails to preserve the retain count
53 // then ARC will deallocate Protocol objects too early.
54 class_replaceMethod(objc_getClass("Protocol"),
55 sel_registerName("dealloc"), (IMP)Crash, "v@:");
56 class_replaceMethod(objc_getClass("__IncompleteProtocol"),
57 sel_registerName("dealloc"), (IMP)Crash, "v@:");
58
59 // make sure binary contains hard copies of these protocols
60 proto = @protocol(SuperProto);
61 proto = @protocol(SuperProto2);
62
63 // Adding a protocol
64
65 char *name = strdup("Proto1");
66 proto = objc_allocateProtocol(name);
67 testassert(proto);
68 testassert(!objc_getProtocol(name));
69
70 protocol_addProtocol(proto, @protocol(SuperProto));
71 protocol_addProtocol(proto, @protocol(SuperProto2));
72 // no inheritance cycles
73 proto2 = objc_allocateProtocol("EmptyProto");
74 protocol_addProtocol(proto, proto2); // fails
75 objc_registerProtocol(proto2);
76 protocol_addProtocol(proto, proto2); // succeeds
77
78 char *types = strdup("@:");
79 protocol_addMethodDescription(proto, @selector(ReqInst0), types, YES, YES);
80 protocol_addMethodDescription(proto, @selector(ReqInst1), types, YES, YES);
81 protocol_addMethodDescription(proto, @selector(ReqInst2), types, YES, YES);
82 protocol_addMethodDescription(proto, @selector(ReqInst3), types, YES, YES);
83
84 protocol_addMethodDescription(proto, @selector(ReqClas0), types, YES, NO);
85 protocol_addMethodDescription(proto, @selector(ReqClas1), types, YES, NO);
86 protocol_addMethodDescription(proto, @selector(ReqClas2), types, YES, NO);
87 protocol_addMethodDescription(proto, @selector(ReqClas3), types, YES, NO);
88
89 protocol_addMethodDescription(proto, @selector(OptInst0), types, NO, YES);
90 protocol_addMethodDescription(proto, @selector(OptInst1), types, NO, YES);
91 protocol_addMethodDescription(proto, @selector(OptInst2), types, NO, YES);
92 protocol_addMethodDescription(proto, @selector(OptInst3), types, NO, YES);
93
94 protocol_addMethodDescription(proto, @selector(OptClas0), types, NO, NO);
95 protocol_addMethodDescription(proto, @selector(OptClas1), types, NO, NO);
96 protocol_addMethodDescription(proto, @selector(OptClas2), types, NO, NO);
97 protocol_addMethodDescription(proto, @selector(OptClas3), types, NO, NO);
98
99 char *name0 = strdup("ReqInst0");
100 char *name1 = strdup("ReqInst1");
101 char *name2 = strdup("ReqInst2");
102 char *name3 = strdup("ReqInst3");
103 char *name4 = strdup("ReqClass0");
104 char *name5 = strdup("ReqClass1");
105 char *name6 = strdup("ReqClass2");
106 char *name7 = strdup("ReqClass3");
107 char *attrname = strdup("T");
108 char *attrvalue = strdup("i");
109 objc_property_attribute_t attrs[] = {{attrname, attrvalue}};
110 int attrcount = sizeof(attrs) / sizeof(attrs[0]);
111 protocol_addProperty(proto, name0, attrs, attrcount, YES, YES);
112 protocol_addProperty(proto, name1, attrs, attrcount, YES, YES);
113 protocol_addProperty(proto, name2, attrs, attrcount, YES, YES);
114 protocol_addProperty(proto, name3, attrs, attrcount, YES, YES);
115 protocol_addProperty(proto, name4, attrs, attrcount, YES, NO);
116 protocol_addProperty(proto, name5, attrs, attrcount, YES, NO);
117 protocol_addProperty(proto, name6, attrs, attrcount, YES, NO);
118 protocol_addProperty(proto, name7, attrs, attrcount, YES, NO);
119
120 objc_registerProtocol(proto);
121 testassert(0 == strcmp(protocol_getName(proto), "Proto1"));
122
123 // Use of added protocols
124
125 testassert(proto == objc_getProtocol("Proto1"));
126 strcpy(name, "XXXXXX"); // name is copied
127 testassert(0 == strcmp(protocol_getName(proto), "Proto1"));
128
129 protolist = protocol_copyProtocolList(proto, &count);
130 testassert(protolist);
131 testassert(count == 3);
132 // note this order is not required
133 testassert(protolist[0] == @protocol(SuperProto) &&
134 protolist[1] == @protocol(SuperProto2) &&
135 protolist[2] == proto2);
136 free(protolist);
137
138 testassert(protocol_conformsToProtocol(proto, proto2));
139 testassert(protocol_conformsToProtocol(proto, @protocol(SuperProto)));
140 testassert(!protocol_conformsToProtocol(proto, @protocol(UnrelatedProto)));
141
142 strcpy(types, "XX"); // types is copied
143 desclist = protocol_copyMethodDescriptionList(proto, YES, YES, &count);
144 testassert(desclist && count == 4);
145 testprintf("%p %p\n", desclist[0].name, @selector(ReqInst0));
146 // testassert(desclist[0].name == @selector(ReqInst0));
147 testassert(0 == strcmp(desclist[0].types, "@:"));
148 free(desclist);
149 desclist = protocol_copyMethodDescriptionList(proto, YES, NO, &count);
150 testassert(desclist && count == 4);
151 testassert(desclist[1].name == @selector(ReqClas1));
152 testassert(0 == strcmp(desclist[1].types, "@:"));
153 free(desclist);
154 desclist = protocol_copyMethodDescriptionList(proto, NO, YES, &count);
155 testassert(desclist && count == 4);
156 testassert(desclist[2].name == @selector(OptInst2));
157 testassert(0 == strcmp(desclist[2].types, "@:"));
158 free(desclist);
159 desclist = protocol_copyMethodDescriptionList(proto, NO, NO, &count);
160 testassert(desclist && count == 4);
161 testassert(desclist[3].name == @selector(OptClas3));
162 testassert(0 == strcmp(desclist[3].types, "@:"));
163 free(desclist);
164
165 strcpy(name0, "XXXXXXXX"); // name is copied
166 strcpy(name1, "XXXXXXXX"); // name is copied
167 strcpy(name2, "XXXXXXXX"); // name is copied
168 strcpy(name3, "XXXXXXXX"); // name is copied
169 strcpy(name4, "XXXXXXXXX"); // name is copied
170 strcpy(name5, "XXXXXXXXX"); // name is copied
171 strcpy(name6, "XXXXXXXXX"); // name is copied
172 strcpy(name7, "XXXXXXXXX"); // name is copied
173 strcpy(attrname, "X"); // description is copied
174 strcpy(attrvalue, "X"); // description is copied
175 memset(attrs, 'X', sizeof(attrs)); // description is copied
176
177 // instance properties
178 count = 100;
179 proplist = protocol_copyPropertyList(proto, &count);
180 testassert(proplist);
181 testassert(count == 4);
182 // note this order is not required
183 testassert(0 == strcmp(property_getName(proplist[0]), "ReqInst0"));
184 testassert(0 == strcmp(property_getName(proplist[1]), "ReqInst1"));
185 testassert(0 == strcmp(property_getName(proplist[2]), "ReqInst2"));
186 testassert(0 == strcmp(property_getName(proplist[3]), "ReqInst3"));
187 testassert(0 == strcmp(property_getAttributes(proplist[0]), "Ti"));
188 testassert(0 == strcmp(property_getAttributes(proplist[1]), "Ti"));
189 testassert(0 == strcmp(property_getAttributes(proplist[2]), "Ti"));
190 testassert(0 == strcmp(property_getAttributes(proplist[3]), "Ti"));
191 free(proplist);
192
193 // class properties
194 count = 100;
195 proplist = protocol_copyPropertyList2(proto, &count, YES, NO);
196 testassert(proplist);
197 testassert(count == 4);
198 // note this order is not required
199 testassert(0 == strcmp(property_getName(proplist[0]), "ReqClass0"));
200 testassert(0 == strcmp(property_getName(proplist[1]), "ReqClass1"));
201 testassert(0 == strcmp(property_getName(proplist[2]), "ReqClass2"));
202 testassert(0 == strcmp(property_getName(proplist[3]), "ReqClass3"));
203 testassert(0 == strcmp(property_getAttributes(proplist[0]), "Ti"));
204 testassert(0 == strcmp(property_getAttributes(proplist[1]), "Ti"));
205 testassert(0 == strcmp(property_getAttributes(proplist[2]), "Ti"));
206 testassert(0 == strcmp(property_getAttributes(proplist[3]), "Ti"));
207 free(proplist);
208
209
210 testassert(proto2 == objc_getProtocol("EmptyProto"));
211 testassert(0 == strcmp(protocol_getName(proto2), "EmptyProto"));
212
213 protolist = protocol_copyProtocolList(proto2, &count);
214 testassert(!protolist);
215 testassert(count == 0);
216
217 testassert(!protocol_conformsToProtocol(proto2, proto));
218 testassert(!protocol_conformsToProtocol(proto2,@protocol(SuperProto)));
219 testassert(!protocol_conformsToProtocol(proto2,@protocol(UnrelatedProto)));
220
221 desclist = protocol_copyMethodDescriptionList(proto2, YES, YES, &count);
222 testassert(!desclist && count == 0);
223 desclist = protocol_copyMethodDescriptionList(proto2, YES, NO, &count);
224 testassert(!desclist && count == 0);
225 desclist = protocol_copyMethodDescriptionList(proto2, NO, YES, &count);
226 testassert(!desclist && count == 0);
227 desclist = protocol_copyMethodDescriptionList(proto2, NO, NO, &count);
228 testassert(!desclist && count == 0);
229
230 // Immutability of existing protocols
231
232 objc_registerProtocol(proto);
233 protocol_addProtocol(proto, @protocol(SuperProto2));
234 protocol_addMethodDescription(proto, @selector(foo), "", YES, YES);
235
236 objc_registerProtocol(@protocol(SuperProto));
237 protocol_addProtocol(@protocol(SuperProto), @protocol(SuperProto2));
238 protocol_addMethodDescription(@protocol(SuperProto), @selector(foo), "", YES, YES);
239
240 // No duplicates
241
242 proto = objc_allocateProtocol("SuperProto");
243 testassert(!proto);
244 proto = objc_allocateProtocol("Proto1");
245 testassert(!proto);
246
247 // NULL protocols ignored
248
249 protocol_addProtocol((__bridge Protocol *)((void*)1), NULL);
250 protocol_addProtocol(NULL, (__bridge Protocol *)((void*)1));
251 protocol_addProtocol(NULL, NULL);
252 protocol_addMethodDescription(NULL, @selector(foo), "", YES, YES);
253
254 succeed(__FILE__);
255 }