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