|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.0 (the 'License'). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License." ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: // Test all possible Objective-C method return types ! 25: // This test exercises both _msg and _msgSuper to make sure that ! 26: // all possible return types and handled correctly. There are ! 27: // two classes used: MsgTest and SuperTest. ! 28: // ! 29: // Class MsgTest defines one method for each possible return type. ! 30: // Each method takes a single argument which is a pointer to a ! 31: // location to put a copy of the return value. Each method stores ! 32: // its return value in that location, then returns it. The caller ! 33: // verifies that the return value and the stored copy match. ! 34: // ! 35: // Class SuperTest does the same, and simply passes the message and ! 36: // argument on to the superclass via a message to "super". ! 37: // ! 38: // Usage: ! 39: // rettest [ msgFlag ] ! 40: // ! 41: // If invoked with an argument, the message trace flag is enabled. ! 42: // ! 43: // Diagnostics: ! 44: // ERROR: return value mismatch while testing '%s' in class %s ! 45: // ! 46: // A return value does not match what was expected. ! 47: // ! 48: // The first '%s' says which type is currently under test; the second ! 49: // names either "MsgTest" or "SuperTest" to indicate which message ! 50: // routine may be faulty. Note that because SuperTest simply passes ! 51: // the message on, if there is a problem in the _msg function, it will ! 52: // show up on both tests. ! 53: // ! 54: // This diagnostic will also be accompanied by "%V:%V", where "%V" ! 55: // indicates some representation of a value. The first is the value ! 56: // actually returned; the second is what was expected. ! 57: // ! 58: // Also printed is the filename and line number containing the test ! 59: // which failed. ! 60: // ! 61: // For example, if a method returning a double didn't match the expected ! 62: // value, you would see an error like: ! 63: // ! 64: // return value mismatch while testing 'double' in class MsgTest ! 65: // line 179 in file "rettest.m": ! 66: // 3.1416:2.9999935e+231 ! 67: // ! 68: // ERROR: unexpected exit while processing test '%s' using %s. ! 69: // ! 70: // An unexpected exit was called during testing, most likely indicating ! 71: // a program fault. If so, the fault will also be diagnosed with a stack ! 72: // backtrace. ! 73: // ! 74: // As before, the first '%s' is the type currently under test; the ! 75: // second is either "MsgTest" or "SuperTest". ! 76: ! 77: ! 78: #include <objc/objc.h> ! 79: #include "rettest.h" ! 80: #include <objc/objc-class.h> ! 81: #include <stdio.h> ! 82: ! 83: int currentLine = 0; ! 84: char *currentTest = "", *currentFile = ""; ! 85: id currentReceiver = nil; ! 86: int nErrors = 0; ! 87: ! 88: ! 89: #import "ret1.h" ! 90: #import "ret2.h" ! 91: ! 92: ! 93: // exit handler ! 94: // This prints a diagnostic if an exit is called in the middle of processing, ! 95: // for example if a segmentation violation resulted from one of the test ! 96: // methods. ! 97: myCleanup(estat,arg) ! 98: int estat; ! 99: char* arg; ! 100: { ! 101: if (estat != 0) { ! 102: fprintf (stderr, ! 103: "ERROR: unexpected exit while processing test '%s' using %s\n\t", ! 104: currentTest, [currentReceiver str]); ! 105: fprintf (stderr, "line %d in file \"%s\"\n", currentLine, currentFile); ! 106: } ! 107: } ! 108: ! 109: //extern id (*_objc_msgPreop)(); ! 110: //extern void _objc_msgCollectStats(); ! 111: //extern void _objc_msgPrintStats(); ! 112: ! 113: main(argc, argv) ! 114: int argc; ! 115: char **argv; ! 116: { ! 117: id foo = 0; ! 118: ! 119: if (argc > 1) ! 120: { ! 121: // _objc_msgPreop = _objc_msgCollectStats; ! 122: } ! 123: ! 124: currentReceiver = [MsgTest new]; ! 125: ! 126: doTests(currentReceiver); ! 127: // print hit/miss info. ! 128: // if (_objc_msgPreop) ! 129: // _objc_msgPrintStats(); ! 130: ! 131: doTests(currentReceiver); ! 132: // print hit/miss info. ! 133: // if (_objc_msgPreop) ! 134: // _objc_msgPrintStats(); ! 135: ! 136: if (nErrors == 0) ! 137: fprintf (stderr, "All return tests to `MsgTest' succeeded\n"); ! 138: else ! 139: fprintf (stderr, "%d errors noted\n", nErrors); ! 140: ! 141: [foo bar]; ! 142: #if 1 ! 143: currentReceiver = [SuperTest new]; ! 144: doTests(currentReceiver); ! 145: ! 146: // print hit/miss info. ! 147: // if (_objc_msgPreop) ! 148: // _objc_msgPrintStats(); ! 149: ! 150: if (nErrors == 0) ! 151: fprintf (stderr, "All return tests to `SuperTest' succeeded\n"); ! 152: else ! 153: fprintf (stderr, "%d errors noted\n", nErrors); ! 154: ! 155: #endif ! 156: exit (0); // OK exit ! 157: } ! 158: ! 159: // Function to call all the test methods for the argument ! 160: // instance. ! 161: doTests(retInstance) ! 162: id retInstance; ! 163: { ! 164: // scalars ! 165: RETDECL(char); ! 166: RETDECL(uchar_t); ! 167: RETDECL(short); ! 168: RETDECL(ushort_t); ! 169: RETDECL(int); ! 170: RETDECL(unsigned); ! 171: RETDECL(long); ! 172: RETDECL(ulong_t); ! 173: RETDECL(float); ! 174: RETDECL(double); ! 175: // pointers ! 176: RETDECL(id); ! 177: RETDECL(STR); ! 178: // structures ! 179: RETDECL(S_BITS_16_t); ! 180: RETDECL(S_BITS_32_t); ! 181: RETDECL(S_BITS_64_t); ! 182: RETDECL(S_BITS_BIG_t); ! 183: // unions ! 184: RETDECL(U_BITS_16_t); ! 185: RETDECL(U_BITS_32_t); ! 186: RETDECL(U_BITS_64_t); ! 187: RETDECL(U_BITS_BIG_t); ! 188: // enums ! 189: RETDECL(E_BITS_8_t); ! 190: RETDECL(E_BITS_16_t); ! 191: #ifdef INT_32 ! 192: RETDECL(E_BITS_32_t); ! 193: #endif ! 194: ! 195: ! 196: NEXTTEST("char"); ! 197: if (RETTEST(retInstance,char)) { ! 198: RETERR("%d:%d",char_value, char_refValue); ! 199: } ! 200: ! 201: NEXTTEST("unsigned char"); ! 202: if (RETTEST(retInstance,uchar_t)) { ! 203: RETERR("%u:%u",uchar_t_value, uchar_t_refValue); ! 204: } ! 205: ! 206: NEXTTEST("short"); ! 207: if (RETTEST(retInstance,short)) { ! 208: RETERR("%d:%d",short_value, short_refValue); ! 209: } ! 210: ! 211: NEXTTEST("unsigned short"); ! 212: if (RETTEST(retInstance,ushort_t)) { ! 213: RETERR("%u:%u",ushort_t_value, ushort_t_refValue); ! 214: } ! 215: ! 216: NEXTTEST("int"); ! 217: if (RETTEST(retInstance,int)) { ! 218: RETERR("%d:%d",int_value, int_refValue); ! 219: } ! 220: ! 221: NEXTTEST("unsigned int"); ! 222: if (RETTEST(retInstance,unsigned)) { ! 223: RETERR("%u:%u",unsigned_value, unsigned_refValue); ! 224: } ! 225: ! 226: NEXTTEST("long"); ! 227: if (RETTEST(retInstance,long)) { ! 228: RETERR("%ld:%ld",long_value, long_refValue); ! 229: } ! 230: ! 231: NEXTTEST("unsigned long"); ! 232: if (RETTEST(retInstance,ulong_t)) { ! 233: RETERR("%lu:%lu",ulong_t_value, ulong_t_refValue); ! 234: } ! 235: ! 236: NEXTTEST("float"); ! 237: if (RETTEST(retInstance,float)) { ! 238: RETERR("%.8g:%.8g",float_value, float_refValue); ! 239: } ! 240: ! 241: NEXTTEST("double"); ! 242: if (RETTEST(retInstance,double)) { ! 243: RETERR("%.17g:%.17g",double_value, double_refValue); ! 244: } ! 245: ! 246: // pointer types ! 247: NEXTTEST("id"); ! 248: if (RETTEST(retInstance,id)) { ! 249: RETERR("%lx:%lx",id_value, id_refValue); ! 250: } ! 251: ! 252: NEXTTEST("char*"); ! 253: if (RETTEST(retInstance,STR)) { ! 254: RETERR4("%lx=%s:%lx=%s",STR_value, STR_value, ! 255: STR_refValue, STR_refValue); ! 256: } ! 257: ! 258: // Now test the aggregate types ! 259: NEXTTEST("struct S_BITS_16"); ! 260: if (SRETTEST(retInstance,S_BITS_16_t)) { ! 261: RETERR("*%lx:*%lx",&S_BITS_16_t_value, &S_BITS_16_t_refValue); ! 262: } ! 263: ! 264: NEXTTEST("struct S_BITS_32"); ! 265: if (SRETTEST(retInstance,S_BITS_32_t)) { ! 266: RETERR("*%lx:*%lx",&S_BITS_32_t_value, &S_BITS_32_t_refValue); ! 267: } ! 268: ! 269: NEXTTEST("struct S_BITS_64"); ! 270: if (SRETTEST(retInstance,S_BITS_64_t)) { ! 271: RETERR("*%lx:*%lx",&S_BITS_64_t_value, &S_BITS_64_t_refValue); ! 272: } ! 273: ! 274: NEXTTEST("struct S_BITS_BIG"); ! 275: if (SRETTEST(retInstance,S_BITS_BIG_t)) { ! 276: RETERR("*%lx:*%lx",&S_BITS_BIG_t_value, &S_BITS_BIG_t_refValue); ! 277: } ! 278: ! 279: // unions ! 280: NEXTTEST("union U_BITS_16"); ! 281: if (SRETTEST(retInstance,U_BITS_16_t)) { ! 282: RETERR("*%lx:*%lx",&U_BITS_16_t_value, &U_BITS_16_t_refValue); ! 283: } ! 284: ! 285: NEXTTEST("union U_BITS_32"); ! 286: if (SRETTEST(retInstance,U_BITS_32_t)) { ! 287: RETERR("*%lx:*%lx",&U_BITS_32_t_value, &U_BITS_32_t_refValue); ! 288: } ! 289: ! 290: NEXTTEST("union U_BITS_64"); ! 291: if (SRETTEST(retInstance,U_BITS_64_t)) { ! 292: RETERR("*%lx:*%lx",&U_BITS_64_t_value, &U_BITS_64_t_refValue); ! 293: } ! 294: ! 295: NEXTTEST("union U_BITS_BIG"); ! 296: if (SRETTEST(retInstance,U_BITS_BIG_t)) { ! 297: RETERR("*%lx:*%lx",&U_BITS_BIG_t_value, &U_BITS_BIG_t_refValue); ! 298: } ! 299: ! 300: NEXTTEST("enum E_BITS_8"); ! 301: if (RETTEST(retInstance,E_BITS_8_t)) { ! 302: RETERR("*%d:*%d",E_BITS_8_t_value, E_BITS_8_t_refValue); ! 303: } ! 304: ! 305: NEXTTEST("enum E_BITS_16"); ! 306: if (RETTEST(retInstance,E_BITS_16_t)) { ! 307: RETERR("*%d:*%d",E_BITS_16_t_value, E_BITS_16_t_refValue); ! 308: } ! 309: ! 310: #if 0 ! 311: #ifdef INT_32 ! 312: NEXTTEST("enum E_BITS_32"); ! 313: if (RETTEST(retInstance,E_BITS_32_t)) { ! 314: RETERR("*%d:*%d",E_BITS_32_t_value, E_BITS_32_t_refValue); ! 315: } ! 316: #endif ! 317: #endif ! 318: ! 319: } ! 320: ! 321: // function to handle errors coming from return value ! 322: // mismatches. Print a standard tag and the received ! 323: // and expected values. ! 324: #import <stdarg.h> ! 325: ! 326: retError(char *fmt, char *file, int line, ...) ! 327: { ! 328: va_list vp; ! 329: ! 330: nErrors += 1; ! 331: fprintf (stderr, "ERROR: return value mismatch while testing '%s' in class %s\n\t", ! 332: currentTest, [currentReceiver str]); ! 333: fprintf (stderr, "line %d in file \"%s\":\n\t", line, file); ! 334: va_start(vp, line); ! 335: vfprintf(stderr,fmt,vp); ! 336: va_end(vp); ! 337: fputc('\n',stderr); ! 338: } ! 339: ! 340: doArgCheck(class,method,self,_cmd) ! 341: Class class; ! 342: SEL method; ! 343: id self; ! 344: SEL _cmd; ! 345: { ! 346: if (self->isa != class && self->isa->super_class != class) ! 347: error("bad 'self' argument in '%s.%s': 0x%lx", ! 348: class->name, SELNAME(method), self); ! 349: if (method != _cmd) ! 350: error("bad '_cmd' argument in '%s.%s': 0x%lx", ! 351: class->name, method, SELNAME(_cmd)); ! 352: } ! 353: ! 354: // General error discovered in some class ! 355: error(char *fmt, ...) ! 356: { ! 357: va_list vp; ! 358: ! 359: nErrors += 1; ! 360: fprintf (stderr, "ERROR: "); ! 361: va_start(vp, fmt); ! 362: vfprintf(stderr,fmt,vp); ! 363: va_end(vp); ! 364: fputc('\n',stderr); ! 365: } ! 366: ! 367: // Compare two arbitrary sized objects one byte at a time. ! 368: retCompare(a1,a2,size) ! 369: char *a1, *a2; ! 370: int size; ! 371: { ! 372: while (size-- > 0) ! 373: if (*a1++ != *a2++) ! 374: return 1; ! 375: return 0; ! 376: } ! 377:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.