1// See instructions in weak.h 2 3#include "test.h" 4#include "weak.h" 5 6// Subclass of superclass that isn't there 7@interface MyMissingSuper : MissingSuper 8+(int) method; 9@end 10@implementation MyMissingSuper 11+(int) method { return 1+[super method]; } 12+(void) load { state++; } 13@end 14 15// Subclass of subclass of superclass that isn't there 16@interface MyMissingSub : MyMissingSuper 17+(int) method; 18@end 19@implementation MyMissingSub 20+(int) method { return 1+[super method]; } 21+(void) load { state++; } 22@end 23 24// Subclass of real superclass 25@interface MyNotMissingSuper : NotMissingSuper 26+(int) method; 27@end 28@implementation MyNotMissingSuper 29+(int) method { return 1+[super method]; } 30+(void) load { state++; } 31@end 32 33// Subclass of subclass of superclass that isn't there 34@interface MyNotMissingSub : MyNotMissingSuper 35+(int) method; 36@end 37@implementation MyNotMissingSub 38+(int) method { return 1+[super method]; } 39+(void) load { state++; } 40@end 41 42// Categories on all of the above 43@interface MissingRoot (MissingRootExtras) 44+(void)load; 45+(int) cat_method; 46@end 47@implementation MissingRoot (MissingRootExtras) 48+(void)load { state++; } 49+(int) cat_method { return 40; } 50@end 51 52@interface MissingSuper (MissingSuperExtras) 53+(void)load; 54+(int) cat_method; 55@end 56@implementation MissingSuper (MissingSuperExtras) 57+(void)load { state++; } 58+(int) cat_method { return 1+[super cat_method]; } 59@end 60 61@interface MyMissingSuper (MyMissingSuperExtras) 62+(void)load; 63+(int) cat_method; 64@end 65@implementation MyMissingSuper (MyMissingSuperExtras) 66+(void)load { state++; } 67+(int) cat_method { return 1+[super cat_method]; } 68@end 69 70@interface MyMissingSub (MyMissingSubExtras) 71+(void)load; 72+(int) cat_method; 73@end 74@implementation MyMissingSub (MyMissingSubExtras) 75+(void)load { state++; } 76+(int) cat_method { return 1+[super cat_method]; } 77@end 78 79 80@interface NotMissingRoot (NotMissingRootExtras) 81+(void)load; 82+(int) cat_method; 83@end 84@implementation NotMissingRoot (NotMissingRootExtras) 85+(void)load { state++; } 86+(int) cat_method { return 30; } 87@end 88 89@interface NotMissingSuper (NotMissingSuperExtras) 90+(void)load; 91+(int) cat_method; 92@end 93@implementation NotMissingSuper (NotMissingSuperExtras) 94+(void)load { state++; } 95+(int) cat_method { return 1+[super cat_method]; } 96@end 97 98@interface MyNotMissingSuper (MyNotMissingSuperExtras) 99+(void)load; 100+(int) cat_method; 101@end 102@implementation MyNotMissingSuper (MyNotMissingSuperExtras) 103+(void)load { state++; } 104+(int) cat_method { return 1+[super cat_method]; } 105@end 106 107@interface MyNotMissingSub (MyNotMissingSubExtras) 108+(void)load; 109+(int) cat_method; 110@end 111@implementation MyNotMissingSub (MyNotMissingSubExtras) 112+(void)load { state++; } 113+(int) cat_method { return 1+[super cat_method]; } 114@end 115 116 117#if WEAK_FRAMEWORK 118# define TESTIVAR(cond) testassert(cond) 119#else 120# define TESTIVAR(cond) /* rdar */ 121#endif 122 123static BOOL classInList(__unsafe_unretained Class classes[], const char *name) 124{ 125 for (int i = 0; classes[i] != nil; i++) { 126 if (0 == strcmp(class_getName(classes[i]), name)) return YES; 127 } 128 return NO; 129} 130 131static BOOL classInNameList(const char **names, const char *name) 132{ 133 const char **cp; 134 for (cp = names; *cp; cp++) { 135 if (0 == strcmp(*cp, name)) return YES; 136 } 137 return NO; 138} 139 140int main(int argc __unused, char **argv) 141{ 142 BOOL weakMissing; 143 if (strstr(argv[0], "-not-missing.out")) { 144 weakMissing = NO; 145 } else if (strstr(argv[0], "-missing.out")) { 146 weakMissing = YES; 147 } else { 148 fail("executable name must be weak*-missing.out or weak*-not-missing.out"); 149 } 150 151 // class and category +load methods 152 if (weakMissing) testassert(state == 8); 153 else testassert(state == 16); 154 state = 0; 155 156 // classes 157 testassert([NotMissingRoot class]); 158 testassert([NotMissingSuper class]); 159 testassert([MyNotMissingSuper class]); 160 testassert([MyNotMissingSub class]); 161 if (weakMissing) { 162 testassert([MissingRoot class] == nil); 163 testassert([MissingSuper class] == nil); 164 testassert([MyMissingSuper class] == nil); 165 testassert([MyMissingSub class] == nil); 166 } else { 167 testassert([MissingRoot class]); 168 testassert([MissingSuper class]); 169 testassert([MyMissingSuper class]); 170 testassert([MyMissingSub class]); 171 } 172 173 // objc_getClass 174 testassert(objc_getClass("NotMissingRoot")); 175 testassert(objc_getClass("NotMissingSuper")); 176 testassert(objc_getClass("MyNotMissingSuper")); 177 testassert(objc_getClass("MyNotMissingSub")); 178 if (weakMissing) { 179 testassert(objc_getClass("MissingRoot") == nil); 180 testassert(objc_getClass("MissingSuper") == nil); 181 testassert(objc_getClass("MyMissingSuper") == nil); 182 testassert(objc_getClass("MyMissingSub") == nil); 183 } else { 184 testassert(objc_getClass("MissingRoot")); 185 testassert(objc_getClass("MissingSuper")); 186 testassert(objc_getClass("MyMissingSuper")); 187 testassert(objc_getClass("MyMissingSub")); 188 } 189 190 // class list 191 union { 192 Class *c; 193 void *v; 194 } classes; 195 classes.c = objc_copyClassList(NULL); 196 testassert(classInList(classes.c, "NotMissingRoot")); 197 testassert(classInList(classes.c, "NotMissingSuper")); 198 testassert(classInList(classes.c, "MyNotMissingSuper")); 199 testassert(classInList(classes.c, "MyNotMissingSub")); 200 if (weakMissing) { 201 testassert(! classInList(classes.c, "MissingRoot")); 202 testassert(! classInList(classes.c, "MissingSuper")); 203 testassert(! classInList(classes.c, "MyMissingSuper")); 204 testassert(! classInList(classes.c, "MyMissingSub")); 205 } else { 206 testassert(classInList(classes.c, "MissingRoot")); 207 testassert(classInList(classes.c, "MissingSuper")); 208 testassert(classInList(classes.c, "MyMissingSuper")); 209 testassert(classInList(classes.c, "MyMissingSub")); 210 } 211 free(classes.v); 212 213 // class name list 214 const char *image = class_getImageName(objc_getClass("NotMissingRoot")); 215 testassert(image); 216 const char **names = objc_copyClassNamesForImage(image, NULL); 217 testassert(names); 218 testassert(classInNameList(names, "NotMissingRoot")); 219 testassert(classInNameList(names, "NotMissingSuper")); 220 if (weakMissing) { 221 testassert(! classInNameList(names, "MissingRoot")); 222 testassert(! classInNameList(names, "MissingSuper")); 223 } else { 224 testassert(classInNameList(names, "MissingRoot")); 225 testassert(classInNameList(names, "MissingSuper")); 226 } 227 free(names); 228 229 image = class_getImageName(objc_getClass("MyNotMissingSub")); 230 testassert(image); 231 names = objc_copyClassNamesForImage(image, NULL); 232 testassert(names); 233 testassert(classInNameList(names, "MyNotMissingSuper")); 234 testassert(classInNameList(names, "MyNotMissingSub")); 235 if (weakMissing) { 236 testassert(! classInNameList(names, "MyMissingSuper")); 237 testassert(! classInNameList(names, "MyMissingSub")); 238 } else { 239 testassert(classInNameList(names, "MyMissingSuper")); 240 testassert(classInNameList(names, "MyMissingSub")); 241 } 242 free(names); 243 244 // methods 245 testassert(20 == [NotMissingRoot method]); 246 testassert(21 == [NotMissingSuper method]); 247 testassert(22 == [MyNotMissingSuper method]); 248 testassert(23 == [MyNotMissingSub method]); 249 if (weakMissing) { 250 testassert(0 == [MissingRoot method]); 251 testassert(0 == [MissingSuper method]); 252 testassert(0 == [MyMissingSuper method]); 253 testassert(0 == [MyMissingSub method]); 254 } else { 255 testassert(10 == [MissingRoot method]); 256 testassert(11 == [MissingSuper method]); 257 testassert(12 == [MyMissingSuper method]); 258 testassert(13 == [MyMissingSub method]); 259 } 260 261 // category methods 262 testassert(30 == [NotMissingRoot cat_method]); 263 testassert(31 == [NotMissingSuper cat_method]); 264 testassert(32 == [MyNotMissingSuper cat_method]); 265 testassert(33 == [MyNotMissingSub cat_method]); 266 if (weakMissing) { 267 testassert(0 == [MissingRoot cat_method]); 268 testassert(0 == [MissingSuper cat_method]); 269 testassert(0 == [MyMissingSuper cat_method]); 270 testassert(0 == [MyMissingSub cat_method]); 271 } else { 272 testassert(40 == [MissingRoot cat_method]); 273 testassert(41 == [MissingSuper cat_method]); 274 testassert(42 == [MyMissingSuper cat_method]); 275 testassert(43 == [MyMissingSub cat_method]); 276 } 277 278 // allocations and ivars 279 id obj; 280 NotMissingSuper *obj2; 281 MissingSuper *obj3; 282 testassert((obj = [[NotMissingRoot alloc] init])); 283 RELEASE_VAR(obj); 284 testassert((obj2 = [[NotMissingSuper alloc] init])); 285 TESTIVAR(obj2->ivar == 200); 286 RELEASE_VAR(obj2); 287 testassert((obj2 = [[MyNotMissingSuper alloc] init])); 288 TESTIVAR(obj2->ivar == 200); 289 RELEASE_VAR(obj2); 290 testassert((obj2 = [[MyNotMissingSub alloc] init])); 291 TESTIVAR(obj2->ivar == 200); 292 RELEASE_VAR(obj2); 293 if (weakMissing) { 294 testassert([[MissingRoot alloc] init] == nil); 295 testassert([[MissingSuper alloc] init] == nil); 296 testassert([[MyMissingSuper alloc] init] == nil); 297 testassert([[MyMissingSub alloc] init] == nil); 298 } else { 299 testassert((obj = [[MissingRoot alloc] init])); 300 RELEASE_VAR(obj); 301 testassert((obj3 = [[MissingSuper alloc] init])); 302 TESTIVAR(obj3->ivar == 100); 303 RELEASE_VAR(obj3); 304 testassert((obj3 = [[MyMissingSuper alloc] init])); 305 TESTIVAR(obj3->ivar == 100); 306 RELEASE_VAR(obj3); 307 testassert((obj3 = [[MyMissingSub alloc] init])); 308 TESTIVAR(obj3->ivar == 100); 309 RELEASE_VAR(obj3); 310 } 311 312 *strrchr(argv[0], '.') = 0; 313 succeed(basename(argv[0])); 314 return 0; 315} 316 317