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