|
|
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.