1//
2//  GTMSenTestCase.h
3//
4//  Copyright 2007-2008 Google Inc.
5//
6//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
7//  use this file except in compliance with the License.  You may obtain a copy
8//  of the License at
9//
10//  http://www.apache.org/licenses/LICENSE-2.0
11//
12//  Unless required by applicable law or agreed to in writing, software
13//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
15//  License for the specific language governing permissions and limitations under
16//  the License.
17//
18
19// Portions of this file fall under the following license, marked with
20// SENTE_BEGIN - SENTE_END
21//
22// Copyright (c) 1997-2005, Sen:te (Sente SA).  All rights reserved.
23//
24// Use of this source code is governed by the following license:
25//
26// Redistribution and use in source and binary forms, with or without modification,
27// are permitted provided that the following conditions are met:
28//
29// (1) Redistributions of source code must retain the above copyright notice,
30// this list of conditions and the following disclaimer.
31//
32// (2) Redistributions in binary form must reproduce the above copyright notice,
33// this list of conditions and the following disclaimer in the documentation
34// and/or other materials provided with the distribution.
35//
36// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
37// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
39// IN NO EVENT SHALL Sente SA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
41// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
43// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
44// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45//
46// Note: this license is equivalent to the FreeBSD license.
47//
48// This notice may not be removed from this file.
49
50// Some extra test case macros that would have been convenient for SenTestingKit
51// to provide. I didn't stick GTM in front of the Macro names, so that they would
52// be easy to remember.
53
54#import "GTMDefines.h"
55
56#if (!GTM_IPHONE_SDK) || (GTM_IPHONE_USE_SENTEST)
57#import <SenTestingKit/SenTestingKit.h>
58#else
59#import <Foundation/Foundation.h>
60#ifdef __cplusplus
61extern "C" {
62#endif
63
64#if defined __clang__
65// gcc and gcc-llvm do not allow you to use STAssert(blah, nil) with nil
66// as a description if you have the NS_FORMAT_FUNCTION on.
67// clang however will not compile without warnings if you don't have it.
68NSString *STComposeString(NSString *, ...) NS_FORMAT_FUNCTION(1, 2);
69#else
70NSString *STComposeString(NSString *, ...);
71#endif  // __clang__
72
73#ifdef __cplusplus
74}
75#endif
76
77#endif  // !GTM_IPHONE_SDK || GTM_IPHONE_USE_SENTEST
78
79// Generates a failure when a1 != noErr
80//  Args:
81//    a1: should be either an OSErr or an OSStatus
82//    description: A format string as in the printf() function. Can be nil or
83//                 an empty string but must be present.
84//    ...: A variable number of arguments to the format string. Can be absent.
85#define STAssertNoErr(a1, description, ...) \
86do { \
87  @try { \
88    OSStatus a1value = (a1); \
89    if (a1value != noErr) { \
90      NSString *_expression = [NSString stringWithFormat:@"Expected noErr, got %ld for (%s)", (long)a1value, #a1]; \
91      [self failWithException:([NSException failureInCondition:_expression \
92                       isTrue:NO \
93                       inFile:[NSString stringWithUTF8String:__FILE__] \
94                       atLine:__LINE__ \
95              withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
96    } \
97  } \
98  @catch (id anException) { \
99    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == noErr fails", #a1] \
100                                              exception:anException \
101                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
102                                                 atLine:__LINE__ \
103                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
104  } \
105} while(0)
106
107// Generates a failure when a1 != a2
108//  Args:
109//    a1: received value. Should be either an OSErr or an OSStatus
110//    a2: expected value. Should be either an OSErr or an OSStatus
111//    description: A format string as in the printf() function. Can be nil or
112//                 an empty string but must be present.
113//    ...: A variable number of arguments to the format string. Can be absent.
114#define STAssertErr(a1, a2, description, ...) \
115do { \
116  @try { \
117    OSStatus a1value = (a1); \
118    OSStatus a2value = (a2); \
119    if (a1value != a2value) { \
120      NSString *_expression = [NSString stringWithFormat:@"Expected %s(%ld) but got %ld for (%s)", #a2, (long)a2value, (long)a1value, #a1]; \
121      [self failWithException:([NSException failureInCondition:_expression \
122                       isTrue:NO \
123                       inFile:[NSString stringWithUTF8String:__FILE__] \
124                       atLine:__LINE__ \
125              withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
126    } \
127  } \
128  @catch (id anException) { \
129    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s) fails", #a1, #a2] \
130                                              exception:anException \
131                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
132                                                 atLine:__LINE__ \
133                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
134  } \
135} while(0)
136
137
138// Generates a failure when a1 is NULL
139//  Args:
140//    a1: should be a pointer (use STAssertNotNil for an object)
141//    description: A format string as in the printf() function. Can be nil or
142//                 an empty string but must be present.
143//    ...: A variable number of arguments to the format string. Can be absent.
144#define STAssertNotNULL(a1, description, ...) \
145do { \
146  @try { \
147    __typeof__(a1) a1value = (a1); \
148    if (a1value == (__typeof__(a1))NULL) { \
149      NSString *_expression = [NSString stringWithFormat:@"((%s) != NULL)", #a1]; \
150      [self failWithException:([NSException failureInCondition:_expression \
151                       isTrue:NO \
152                       inFile:[NSString stringWithUTF8String:__FILE__] \
153                       atLine:__LINE__ \
154              withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
155    } \
156  } \
157  @catch (id anException) { \
158    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != NULL fails", #a1] \
159                                              exception:anException \
160                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
161                                                 atLine:__LINE__ \
162                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
163  } \
164} while(0)
165
166// Generates a failure when a1 is not NULL
167//  Args:
168//    a1: should be a pointer (use STAssertNil for an object)
169//    description: A format string as in the printf() function. Can be nil or
170//                 an empty string but must be present.
171//    ...: A variable number of arguments to the format string. Can be absent.
172#define STAssertNULL(a1, description, ...) \
173do { \
174  @try { \
175    __typeof__(a1) a1value = (a1); \
176    if (a1value != (__typeof__(a1))NULL) { \
177      NSString *_expression = [NSString stringWithFormat:@"((%s) == NULL)", #a1]; \
178      [self failWithException:([NSException failureInCondition:_expression \
179                                                        isTrue:NO \
180                                                        inFile:[NSString stringWithUTF8String:__FILE__] \
181                                                        atLine:__LINE__ \
182                                               withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
183    } \
184  } \
185  @catch (id anException) { \
186    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == NULL fails", #a1] \
187                                              exception:anException \
188                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
189                                                 atLine:__LINE__ \
190                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
191  } \
192} while(0)
193
194// Generates a failure when a1 is equal to a2. This test is for C scalars,
195// structs and unions.
196//  Args:
197//    a1: argument 1
198//    a2: argument 2
199//    description: A format string as in the printf() function. Can be nil or
200//                 an empty string but must be present.
201//    ...: A variable number of arguments to the format string. Can be absent.
202#define STAssertNotEquals(a1, a2, description, ...) \
203do { \
204  @try { \
205    if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \
206      [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
207                                                  atLine:__LINE__ \
208                                         withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \
209    } else { \
210      __typeof__(a1) a1value = (a1); \
211      __typeof__(a2) a2value = (a2); \
212      NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \
213      NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \
214      if ([a1encoded isEqualToValue:a2encoded]) { \
215        NSString *_expression = [NSString stringWithFormat:@"((%s) != (%s))", #a1, #a2]; \
216        [self failWithException:([NSException failureInCondition:_expression \
217                         isTrue:NO \
218                         inFile:[NSString stringWithUTF8String:__FILE__] \
219                         atLine:__LINE__ \
220                withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
221      }\
222    } \
223  } \
224  @catch (id anException) { \
225    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \
226                                              exception:anException \
227                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
228                                                 atLine:__LINE__ \
229            withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
230  } \
231} while(0)
232
233// Generates a failure when a1 is equal to a2. This test is for objects.
234//  Args:
235//    a1: argument 1. object.
236//    a2: argument 2. object.
237//    description: A format string as in the printf() function. Can be nil or
238//                 an empty string but must be present.
239//    ...: A variable number of arguments to the format string. Can be absent.
240#define STAssertNotEqualObjects(a1, a2, description, ...) \
241do { \
242  @try {\
243    id a1value = (a1); \
244    id a2value = (a2); \
245    if ( (strcmp(@encode(__typeof__(a1value)), @encode(id)) == 0) && \
246         (strcmp(@encode(__typeof__(a2value)), @encode(id)) == 0) && \
247         (![(id)a1value isEqual:(id)a2value]) ) continue; \
248    [self failWithException:([NSException failureInEqualityBetweenObject:a1value \
249                  andObject:a2value \
250                     inFile:[NSString stringWithUTF8String:__FILE__] \
251                     atLine:__LINE__ \
252            withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
253  }\
254  @catch (id anException) {\
255    [self failWithException:([NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \
256                                               exception:anException \
257                                                  inFile:[NSString stringWithUTF8String:__FILE__] \
258                                                  atLine:__LINE__ \
259                                         withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
260  }\
261} while(0)
262
263// Generates a failure when a1 is not 'op' to a2. This test is for C scalars.
264//  Args:
265//    a1: argument 1
266//    a2: argument 2
267//    op: operation
268//    description: A format string as in the printf() function. Can be nil or
269//                 an empty string but must be present.
270//    ...: A variable number of arguments to the format string. Can be absent.
271#define STAssertOperation(a1, a2, op, description, ...) \
272do { \
273  @try { \
274    if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \
275      [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
276                                                  atLine:__LINE__ \
277                                         withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \
278    } else { \
279      __typeof__(a1) a1value = (a1); \
280      __typeof__(a2) a2value = (a2); \
281      if (!(a1value op a2value)) { \
282        double a1DoubleValue = a1value; \
283        double a2DoubleValue = a2value; \
284        NSString *_expression = [NSString stringWithFormat:@"(%s (%lg) %s %s (%lg))", #a1, a1DoubleValue, #op, #a2, a2DoubleValue]; \
285        [self failWithException:([NSException failureInCondition:_expression \
286                         isTrue:NO \
287                         inFile:[NSString stringWithUTF8String:__FILE__] \
288                         atLine:__LINE__ \
289                withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
290      } \
291    } \
292  } \
293  @catch (id anException) { \
294    [self failWithException:[NSException \
295             failureInRaise:[NSString stringWithFormat:@"(%s) %s (%s)", #a1, #op, #a2] \
296                  exception:anException \
297                     inFile:[NSString stringWithUTF8String:__FILE__] \
298                     atLine:__LINE__ \
299            withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
300  } \
301} while(0)
302
303// Generates a failure when a1 is not > a2. This test is for C scalars.
304//  Args:
305//    a1: argument 1
306//    a2: argument 2
307//    op: operation
308//    description: A format string as in the printf() function. Can be nil or
309//                 an empty string but must be present.
310//    ...: A variable number of arguments to the format string. Can be absent.
311#define STAssertGreaterThan(a1, a2, description, ...) \
312  STAssertOperation(a1, a2, >, description, ##__VA_ARGS__)
313
314// Generates a failure when a1 is not >= a2. This test is for C scalars.
315//  Args:
316//    a1: argument 1
317//    a2: argument 2
318//    op: operation
319//    description: A format string as in the printf() function. Can be nil or
320//                 an empty string but must be present.
321//    ...: A variable number of arguments to the format string. Can be absent.
322#define STAssertGreaterThanOrEqual(a1, a2, description, ...) \
323  STAssertOperation(a1, a2, >=, description, ##__VA_ARGS__)
324
325// Generates a failure when a1 is not < a2. This test is for C scalars.
326//  Args:
327//    a1: argument 1
328//    a2: argument 2
329//    op: operation
330//    description: A format string as in the printf() function. Can be nil or
331//                 an empty string but must be present.
332//    ...: A variable number of arguments to the format string. Can be absent.
333#define STAssertLessThan(a1, a2, description, ...) \
334  STAssertOperation(a1, a2, <, description, ##__VA_ARGS__)
335
336// Generates a failure when a1 is not <= a2. This test is for C scalars.
337//  Args:
338//    a1: argument 1
339//    a2: argument 2
340//    op: operation
341//    description: A format string as in the printf() function. Can be nil or
342//                 an empty string but must be present.
343//    ...: A variable number of arguments to the format string. Can be absent.
344#define STAssertLessThanOrEqual(a1, a2, description, ...) \
345  STAssertOperation(a1, a2, <=, description, ##__VA_ARGS__)
346
347// Generates a failure when string a1 is not equal to string a2. This call
348// differs from STAssertEqualObjects in that strings that are different in
349// composition (precomposed vs decomposed) will compare equal if their final
350// representation is equal.
351// ex O + umlaut decomposed is the same as O + umlaut composed.
352//  Args:
353//    a1: string 1
354//    a2: string 2
355//    description: A format string as in the printf() function. Can be nil or
356//                 an empty string but must be present.
357//    ...: A variable number of arguments to the format string. Can be absent.
358#define STAssertEqualStrings(a1, a2, description, ...) \
359do { \
360  @try { \
361    id a1value = (a1); \
362    id a2value = (a2); \
363    if (a1value == a2value) continue; \
364    if ([a1value isKindOfClass:[NSString class]] && \
365        [a2value isKindOfClass:[NSString class]] && \
366        [a1value compare:a2value options:0] == NSOrderedSame) continue; \
367     [self failWithException:[NSException failureInEqualityBetweenObject:a1value \
368                                                               andObject:a2value \
369                                                                  inFile:[NSString stringWithUTF8String:__FILE__] \
370                                                                  atLine:__LINE__ \
371                                                         withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
372  } \
373  @catch (id anException) { \
374    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \
375                                              exception:anException \
376                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
377                                                 atLine:__LINE__ \
378                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
379  } \
380} while(0)
381
382// Generates a failure when string a1 is equal to string a2. This call
383// differs from STAssertEqualObjects in that strings that are different in
384// composition (precomposed vs decomposed) will compare equal if their final
385// representation is equal.
386// ex O + umlaut decomposed is the same as O + umlaut composed.
387//  Args:
388//    a1: string 1
389//    a2: string 2
390//    description: A format string as in the printf() function. Can be nil or
391//                 an empty string but must be present.
392//    ...: A variable number of arguments to the format string. Can be absent.
393#define STAssertNotEqualStrings(a1, a2, description, ...) \
394do { \
395  @try { \
396    id a1value = (a1); \
397    id a2value = (a2); \
398    if ([a1value isKindOfClass:[NSString class]] && \
399        [a2value isKindOfClass:[NSString class]] && \
400        [a1value compare:a2value options:0] != NSOrderedSame) continue; \
401     [self failWithException:[NSException failureInEqualityBetweenObject:a1value \
402                                                               andObject:a2value \
403                                                                  inFile:[NSString stringWithUTF8String:__FILE__] \
404                                                                  atLine:__LINE__ \
405                                                         withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
406  } \
407  @catch (id anException) { \
408    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \
409                                              exception:anException \
410                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
411                                                 atLine:__LINE__ \
412                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
413  } \
414} while(0)
415
416// Generates a failure when c-string a1 is not equal to c-string a2.
417//  Args:
418//    a1: string 1
419//    a2: string 2
420//    description: A format string as in the printf() function. Can be nil or
421//                 an empty string but must be present.
422//    ...: A variable number of arguments to the format string. Can be absent.
423#define STAssertEqualCStrings(a1, a2, description, ...) \
424do { \
425  @try { \
426    const char* a1value = (a1); \
427    const char* a2value = (a2); \
428    if (a1value == a2value) continue; \
429    if (strcmp(a1value, a2value) == 0) continue; \
430    [self failWithException:[NSException failureInEqualityBetweenObject:[NSString stringWithUTF8String:a1value] \
431                                                              andObject:[NSString stringWithUTF8String:a2value] \
432                                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
433                                                                 atLine:__LINE__ \
434                                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
435  } \
436  @catch (id anException) { \
437    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \
438                                              exception:anException \
439                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
440                                                 atLine:__LINE__ \
441                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
442  } \
443} while(0)
444
445// Generates a failure when c-string a1 is equal to c-string a2.
446//  Args:
447//    a1: string 1
448//    a2: string 2
449//    description: A format string as in the printf() function. Can be nil or
450//                 an empty string but must be present.
451//    ...: A variable number of arguments to the format string. Can be absent.
452#define STAssertNotEqualCStrings(a1, a2, description, ...) \
453do { \
454  @try { \
455    const char* a1value = (a1); \
456    const char* a2value = (a2); \
457    if (strcmp(a1value, a2value) != 0) continue; \
458    [self failWithException:[NSException failureInEqualityBetweenObject:[NSString stringWithUTF8String:a1value] \
459                                                              andObject:[NSString stringWithUTF8String:a2value] \
460                                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
461                                                                 atLine:__LINE__ \
462                                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
463  } \
464  @catch (id anException) { \
465    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \
466                                              exception:anException \
467                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
468                                                 atLine:__LINE__ \
469                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
470  } \
471} while(0)
472
473/*" Generates a failure when a1 is not equal to a2 within + or - accuracy is false.
474  This test is for GLKit types (GLKVector, GLKMatrix) where small differences
475  could  make these items not exactly equal. Do not use this version directly.
476  Use the explicit STAssertEqualGLKVectors and STAssertEqualGLKMatrices defined
477  below.
478  _{a1    The GLKType on the left.}
479  _{a2    The GLKType on the right.}
480  _{accuracy  The maximum difference between a1 and a2 for these values to be
481  considered equal.}
482  _{description A format string as in the printf() function. Can be nil or
483                      an empty string but must be present.}
484  _{... A variable number of arguments to the format string. Can be absent.}
485"*/
486
487#define STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ...) \
488do { \
489  @try { \
490    if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \
491      [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
492                                                                                 atLine:__LINE__ \
493                                                                        withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \
494    } else { \
495      __typeof__(a1) a1GLKValue = (a1); \
496      __typeof__(a2) a2GLKValue = (a2); \
497      __typeof__(accuracy) accuracyvalue = (accuracy); \
498      float *a1FloatValue = ((float*)&a1GLKValue); \
499      float *a2FloatValue = ((float*)&a2GLKValue); \
500      for (size_t i = 0; i < sizeof(__typeof__(a1)) / sizeof(float); ++i) { \
501        float a1value = a1FloatValue[i]; \
502        float a2value = a2FloatValue[i]; \
503        if (STAbsoluteDifference(a1value, a2value) > accuracyvalue) { \
504          NSMutableArray *strings = [NSMutableArray arrayWithCapacity:sizeof(a1) / sizeof(float)]; \
505          NSString *string; \
506          for (size_t j = 0; j < sizeof(__typeof__(a1)) / sizeof(float); ++j) { \
507            string = [NSString stringWithFormat:@"(%0.3f == %0.3f)", a1FloatValue[j], a2FloatValue[j]]; \
508            [strings addObject:string]; \
509          } \
510          string = [strings componentsJoinedByString:@", "]; \
511          NSString *desc = STComposeString(description, ##__VA_ARGS__); \
512          desc = [NSString stringWithFormat:@"%@ With Accuracy %0.3f: %@", string, (float)accuracyvalue, desc]; \
513          [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
514                                                      atLine:__LINE__ \
515                                             withDescription:@"%@", desc]]; \
516          break; \
517        } \
518      } \
519    } \
520  } \
521  @catch (id anException) { \
522    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \
523                                              exception:anException \
524                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
525                                                 atLine:__LINE__ \
526                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
527  } \
528} while(0)
529
530#define STAssertEqualGLKVectors(a1, a2, accuracy, description, ...) \
531     STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ##__VA_ARGS__)
532
533#define STAssertEqualGLKMatrices(a1, a2, accuracy, description, ...) \
534     STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ##__VA_ARGS__)
535
536#define STAssertEqualGLKQuaternions(a1, a2, accuracy, description, ...) \
537     STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ##__VA_ARGS__)
538
539#if GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST
540// When not using the Xcode provided version, define everything ourselves.
541
542// SENTE_BEGIN
543/*" Generates a failure when !{ [a1 isEqualTo:a2] } is false
544	(or one is nil and the other is not).
545	_{a1    The object on the left.}
546	_{a2    The object on the right.}
547	_{description A format string as in the printf() function. Can be nil or
548		an empty string but must be present.}
549	_{... A variable number of arguments to the format string. Can be absent.}
550"*/
551#define STAssertEqualObjects(a1, a2, description, ...) \
552do { \
553  @try { \
554    id a1value = (a1); \
555    id a2value = (a2); \
556    if (a1value == a2value) continue; \
557    if ((strcmp(@encode(__typeof__(a1value)), @encode(id)) == 0) && \
558        (strcmp(@encode(__typeof__(a2value)), @encode(id)) == 0) && \
559        [(id)a1value isEqual:(id)a2value]) continue; \
560    [self failWithException:[NSException failureInEqualityBetweenObject:a1value \
561                                                              andObject:a2value \
562                                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
563                                                                 atLine:__LINE__ \
564                                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
565  } \
566  @catch (id anException) { \
567    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \
568                                              exception:anException \
569                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
570                                                 atLine:__LINE__ \
571                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
572  } \
573} while(0)
574
575
576/*" Generates a failure when a1 is not equal to a2. This test is for
577    C scalars, structs and unions.
578    _{a1    The argument on the left.}
579    _{a2    The argument on the right.}
580    _{description A format string as in the printf() function. Can be nil or
581                        an empty string but must be present.}
582    _{... A variable number of arguments to the format string. Can be absent.}
583"*/
584#define STAssertEquals(a1, a2, description, ...) \
585do { \
586  @try { \
587    if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \
588      [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
589                                                                                 atLine:__LINE__ \
590                                                                        withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \
591    } else { \
592      __typeof__(a1) a1value = (a1); \
593      __typeof__(a2) a2value = (a2); \
594      NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \
595      NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \
596      if (![a1encoded isEqualToValue:a2encoded]) { \
597        [self failWithException:[NSException failureInEqualityBetweenValue:a1encoded \
598                                                                  andValue:a2encoded \
599                                                              withAccuracy:nil \
600                                                                    inFile:[NSString stringWithUTF8String:__FILE__] \
601                                                                    atLine:__LINE__ \
602                                                           withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
603      } \
604    } \
605  } \
606  @catch (id anException) { \
607    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \
608                                              exception:anException \
609                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
610                                                 atLine:__LINE__ \
611                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
612  } \
613} while(0)
614
615#define STAbsoluteDifference(left,right) (MAX(left,right)-MIN(left,right))
616
617
618/*" Generates a failure when a1 is not equal to a2 within + or - accuracy is false.
619  This test is for scalars such as floats and doubles where small differences
620  could make these items not exactly equal, but also works for all scalars.
621  _{a1    The scalar on the left.}
622  _{a2    The scalar on the right.}
623  _{accuracy  The maximum difference between a1 and a2 for these values to be
624  considered equal.}
625  _{description A format string as in the printf() function. Can be nil or
626                      an empty string but must be present.}
627  _{... A variable number of arguments to the format string. Can be absent.}
628"*/
629
630#define STAssertEqualsWithAccuracy(a1, a2, accuracy, description, ...) \
631do { \
632  @try { \
633    if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \
634      [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
635                                                                                 atLine:__LINE__ \
636                                                                        withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \
637    } else { \
638      __typeof__(a1) a1value = (a1); \
639      __typeof__(a2) a2value = (a2); \
640      __typeof__(accuracy) accuracyvalue = (accuracy); \
641      if (STAbsoluteDifference(a1value, a2value) > accuracyvalue) { \
642              NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \
643              NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \
644              NSValue *accuracyencoded = [NSValue value:&accuracyvalue withObjCType:@encode(__typeof__(accuracy))]; \
645              [self failWithException:[NSException failureInEqualityBetweenValue:a1encoded \
646                                                                        andValue:a2encoded \
647                                                                    withAccuracy:accuracyencoded \
648                                                                          inFile:[NSString stringWithUTF8String:__FILE__] \
649                                                                          atLine:__LINE__ \
650                                                                 withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
651      } \
652    } \
653  } \
654  @catch (id anException) { \
655    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \
656                                                                         exception:anException \
657                                                                            inFile:[NSString stringWithUTF8String:__FILE__] \
658                                                                            atLine:__LINE__ \
659                                                                   withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
660  } \
661} while(0)
662
663
664
665/*" Generates a failure unconditionally.
666  _{description A format string as in the printf() function. Can be nil or
667                      an empty string but must be present.}
668  _{... A variable number of arguments to the format string. Can be absent.}
669"*/
670#define STFail(description, ...) \
671[self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
672                                            atLine:__LINE__ \
673                                   withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]
674
675
676
677/*" Generates a failure when a1 is not nil.
678  _{a1    An object.}
679  _{description A format string as in the printf() function. Can be nil or
680    an empty string but must be present.}
681  _{... A variable number of arguments to the format string. Can be absent.}
682"*/
683#define STAssertNil(a1, description, ...) \
684do { \
685  @try { \
686    id a1value = (a1); \
687    if (a1value != nil) { \
688      NSString *_a1 = [NSString stringWithUTF8String:#a1]; \
689      NSString *_expression = [NSString stringWithFormat:@"((%@) == nil)", _a1]; \
690      [self failWithException:[NSException failureInCondition:_expression \
691                                                       isTrue:NO \
692                                                       inFile:[NSString stringWithUTF8String:__FILE__] \
693                                                       atLine:__LINE__ \
694                                              withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
695    } \
696  } \
697  @catch (id anException) { \
698    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == nil fails", #a1] \
699                                              exception:anException \
700                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
701                                                 atLine:__LINE__ \
702                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
703  } \
704} while(0)
705
706
707/*" Generates a failure when a1 is nil.
708  _{a1    An object.}
709  _{description A format string as in the printf() function. Can be nil or
710  an empty string but must be present.}
711  _{... A variable number of arguments to the format string. Can be absent.}
712"*/
713#define STAssertNotNil(a1, description, ...) \
714do { \
715  @try { \
716    id a1value = (a1); \
717    if (a1value == nil) { \
718      NSString *_a1 = [NSString stringWithUTF8String:#a1]; \
719      NSString *_expression = [NSString stringWithFormat:@"((%@) != nil)", _a1]; \
720      [self failWithException:[NSException failureInCondition:_expression \
721                                                       isTrue:NO \
722                                                       inFile:[NSString stringWithUTF8String:__FILE__] \
723                                                       atLine:__LINE__ \
724                                              withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
725    } \
726  } \
727  @catch (id anException) { \
728    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != nil fails", #a1] \
729                                              exception:anException \
730                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
731                                                 atLine:__LINE__ \
732                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
733  } \
734} while(0)
735
736
737/*" Generates a failure when expression evaluates to false.
738  _{expr    The expression that is tested.}
739  _{description A format string as in the printf() function. Can be nil or
740  an empty string but must be present.}
741  _{... A variable number of arguments to the format string. Can be absent.}
742"*/
743#define STAssertTrue(expr, description, ...) \
744do { \
745  BOOL _evaluatedExpression = (expr); \
746  if (!_evaluatedExpression) { \
747    NSString *_expression = [NSString stringWithUTF8String:#expr]; \
748    [self failWithException:[NSException failureInCondition:_expression \
749                                                     isTrue:NO \
750                                                     inFile:[NSString stringWithUTF8String:__FILE__] \
751                                                     atLine:__LINE__ \
752                                            withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
753  } \
754} while (0)
755
756
757/*" Generates a failure when expression evaluates to false and in addition will
758  generate error messages if an exception is encountered.
759  _{expr    The expression that is tested.}
760  _{description A format string as in the printf() function. Can be nil or
761  an empty string but must be present.}
762  _{... A variable number of arguments to the format string. Can be absent.}
763"*/
764#define STAssertTrueNoThrow(expr, description, ...) \
765do { \
766  @try { \
767    BOOL _evaluatedExpression = (expr); \
768    if (!_evaluatedExpression) { \
769      NSString *_expression = [NSString stringWithUTF8String:#expr]; \
770      [self failWithException:[NSException failureInCondition:_expression \
771                                                       isTrue:NO \
772                                                       inFile:[NSString stringWithUTF8String:__FILE__] \
773                                                       atLine:__LINE__ \
774                                              withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
775    } \
776  } \
777  @catch (id anException) { \
778    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) ", #expr] \
779                                              exception:anException \
780                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
781                                                 atLine:__LINE__ \
782                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
783  } \
784} while (0)
785
786
787/*" Generates a failure when the expression evaluates to true.
788  _{expr    The expression that is tested.}
789  _{description A format string as in the printf() function. Can be nil or
790  an empty string but must be present.}
791  _{... A variable number of arguments to the format string. Can be absent.}
792"*/
793#define STAssertFalse(expr, description, ...) \
794do { \
795  BOOL _evaluatedExpression = (expr); \
796  if (_evaluatedExpression) { \
797    NSString *_expression = [NSString stringWithUTF8String:#expr]; \
798    [self failWithException:[NSException failureInCondition:_expression \
799                                                     isTrue:YES \
800                                                     inFile:[NSString stringWithUTF8String:__FILE__] \
801                                                     atLine:__LINE__ \
802                                            withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
803  } \
804} while (0)
805
806
807/*" Generates a failure when the expression evaluates to true and in addition
808  will generate error messages if an exception is encountered.
809  _{expr    The expression that is tested.}
810  _{description A format string as in the printf() function. Can be nil or
811  an empty string but must be present.}
812  _{... A variable number of arguments to the format string. Can be absent.}
813"*/
814#define STAssertFalseNoThrow(expr, description, ...) \
815do { \
816  @try { \
817    BOOL _evaluatedExpression = (expr); \
818    if (_evaluatedExpression) { \
819      NSString *_expression = [NSString stringWithUTF8String:#expr]; \
820      [self failWithException:[NSException failureInCondition:_expression \
821                                                       isTrue:YES \
822                                                       inFile:[NSString stringWithUTF8String:__FILE__] \
823                                                       atLine:__LINE__ \
824                                              withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
825    } \
826  } \
827  @catch (id anException) { \
828    [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"!(%s) ", #expr] \
829                                              exception:anException \
830                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
831                                                 atLine:__LINE__ \
832                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
833  } \
834} while (0)
835
836
837/*" Generates a failure when expression does not throw an exception.
838  _{expression    The expression that is evaluated.}
839  _{description A format string as in the printf() function. Can be nil or
840  an empty string but must be present.}
841  _{... A variable number of arguments to the format string. Can be absent.
842"*/
843#define STAssertThrows(expr, description, ...) \
844do { \
845  @try { \
846    (expr); \
847  } \
848  @catch (id anException) { \
849    continue; \
850  } \
851  [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
852                                            exception:nil \
853                                               inFile:[NSString stringWithUTF8String:__FILE__] \
854                                               atLine:__LINE__ \
855                                      withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
856} while (0)
857
858
859/*" Generates a failure when expression does not throw an exception of a
860  specific class.
861  _{expression    The expression that is evaluated.}
862  _{specificException    The specified class of the exception.}
863  _{description A format string as in the printf() function. Can be nil or
864  an empty string but must be present.}
865  _{... A variable number of arguments to the format string. Can be absent.}
866"*/
867#define STAssertThrowsSpecific(expr, specificException, description, ...) \
868do { \
869  @try { \
870    (expr); \
871  } \
872  @catch (specificException *anException) { \
873    continue; \
874  } \
875  @catch (id anException) { \
876    NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \
877    [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
878                                              exception:anException \
879                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
880                                                 atLine:__LINE__ \
881                                        withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \
882                                            continue; \
883  } \
884  NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \
885  [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
886                                            exception:nil \
887                                               inFile:[NSString stringWithUTF8String:__FILE__] \
888                                               atLine:__LINE__ \
889                                      withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \
890} while (0)
891
892
893/*" Generates a failure when expression does not throw an exception of a
894  specific class with a specific name.  Useful for those frameworks like
895  AppKit or Foundation that throw generic NSException w/specific names
896  (NSInvalidArgumentException, etc).
897  _{expression    The expression that is evaluated.}
898  _{specificException    The specified class of the exception.}
899  _{aName    The name of the specified exception.}
900  _{description A format string as in the printf() function. Can be nil or
901  an empty string but must be present.}
902  _{... A variable number of arguments to the format string. Can be absent.}
903
904"*/
905#define STAssertThrowsSpecificNamed(expr, specificException, aName, description, ...) \
906do { \
907  @try { \
908    (expr); \
909  } \
910  @catch (specificException *anException) { \
911    if ([aName isEqualToString:[anException name]]) continue; \
912    NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description); \
913    [self failWithException: \
914      [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
915                        exception:anException \
916                           inFile:[NSString stringWithUTF8String:__FILE__] \
917                           atLine:__LINE__ \
918                  withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \
919    continue; \
920  } \
921  @catch (id anException) { \
922    NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \
923    [self failWithException: \
924      [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
925                        exception:anException \
926                           inFile:[NSString stringWithUTF8String:__FILE__] \
927                           atLine:__LINE__ \
928                  withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \
929    continue; \
930  } \
931  NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \
932  [self failWithException: \
933    [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
934                      exception:nil \
935                         inFile:[NSString stringWithUTF8String:__FILE__] \
936                         atLine:__LINE__ \
937                withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \
938} while (0)
939
940
941/*" Generates a failure when expression does throw an exception.
942  _{expression    The expression that is evaluated.}
943  _{description A format string as in the printf() function. Can be nil or
944  an empty string but must be present.}
945  _{... A variable number of arguments to the format string. Can be absent.}
946"*/
947#define STAssertNoThrow(expr, description, ...) \
948do { \
949  @try { \
950    (expr); \
951  } \
952  @catch (id anException) { \
953    [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
954                                              exception:anException \
955                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
956                                                 atLine:__LINE__ \
957                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
958  } \
959} while (0)
960
961
962/*" Generates a failure when expression does throw an exception of the specitied
963  class. Any other exception is okay (i.e. does not generate a failure).
964  _{expression    The expression that is evaluated.}
965  _{specificException    The specified class of the exception.}
966  _{description A format string as in the printf() function. Can be nil or
967  an empty string but must be present.}
968  _{... A variable number of arguments to the format string. Can be absent.}
969"*/
970#define STAssertNoThrowSpecific(expr, specificException, description, ...) \
971do { \
972  @try { \
973    (expr); \
974  } \
975  @catch (specificException *anException) { \
976    [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
977                                              exception:anException \
978                                                 inFile:[NSString stringWithUTF8String:__FILE__] \
979                                                 atLine:__LINE__ \
980                                        withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
981  } \
982  @catch (id anythingElse) { \
983    ; \
984  } \
985} while (0)
986
987
988/*" Generates a failure when expression does throw an exception of a
989  specific class with a specific name.  Useful for those frameworks like
990  AppKit or Foundation that throw generic NSException w/specific names
991  (NSInvalidArgumentException, etc).
992  _{expression    The expression that is evaluated.}
993  _{specificException    The specified class of the exception.}
994  _{aName    The name of the specified exception.}
995  _{description A format string as in the printf() function. Can be nil or
996  an empty string but must be present.}
997  _{... A variable number of arguments to the format string. Can be absent.}
998
999"*/
1000#define STAssertNoThrowSpecificNamed(expr, specificException, aName, description, ...) \
1001do { \
1002  @try { \
1003    (expr); \
1004  } \
1005  @catch (specificException *anException) { \
1006    if ([aName isEqualToString:[anException name]]) { \
1007      NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description); \
1008      [self failWithException: \
1009        [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
1010                          exception:anException \
1011                             inFile:[NSString stringWithUTF8String:__FILE__] \
1012                             atLine:__LINE__ \
1013                    withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \
1014    } \
1015    continue; \
1016  } \
1017  @catch (id anythingElse) { \
1018    ; \
1019  } \
1020} while (0)
1021
1022
1023
1024@interface NSException (GTMSenTestAdditions)
1025+ (NSException *)failureInFile:(NSString *)filename
1026                        atLine:(int)lineNumber
1027               withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(3, 4);
1028+ (NSException *)failureInCondition:(NSString *)condition
1029                             isTrue:(BOOL)isTrue
1030                             inFile:(NSString *)filename
1031                             atLine:(int)lineNumber
1032                    withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(5, 6);
1033+ (NSException *)failureInEqualityBetweenObject:(id)left
1034                                      andObject:(id)right
1035                                         inFile:(NSString *)filename
1036                                         atLine:(int)lineNumber
1037                                withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(5, 6);
1038+ (NSException *)failureInEqualityBetweenValue:(NSValue *)left
1039                                      andValue:(NSValue *)right
1040                                  withAccuracy:(NSValue *)accuracy
1041                                        inFile:(NSString *)filename
1042                                        atLine:(int) ineNumber
1043                               withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(6, 7);
1044+ (NSException *)failureInRaise:(NSString *)expression
1045                         inFile:(NSString *)filename
1046                         atLine:(int)lineNumber
1047                withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(4, 5);
1048+ (NSException *)failureInRaise:(NSString *)expression
1049                      exception:(NSException *)exception
1050                         inFile:(NSString *)filename
1051                         atLine:(int)lineNumber
1052                withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(5, 6);
1053@end
1054
1055// SENTE_END
1056
1057@protocol SenTestCase
1058+ (id)testCaseWithInvocation:(NSInvocation *)anInvocation;
1059- (id)initWithInvocation:(NSInvocation *)anInvocation;
1060- (void)setUp;
1061- (void)invokeTest;
1062- (void)tearDown;
1063- (void)performTest;
1064- (void)failWithException:(NSException*)exception;
1065- (NSInvocation *)invocation;
1066- (SEL)selector;
1067+ (NSArray *)testInvocations;
1068@end
1069
1070@interface SenTestCase : NSObject<SenTestCase> {
1071 @private
1072  NSInvocation *invocation_;
1073}
1074@end
1075
1076GTM_EXTERN NSString *const SenTestFailureException;
1077
1078GTM_EXTERN NSString *const SenTestFilenameKey;
1079GTM_EXTERN NSString *const SenTestLineNumberKey;
1080
1081#endif // GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST
1082
1083// All unittest cases in GTM should inherit from GTMTestCase. It makes sure
1084// to set up our logging system correctly to verify logging calls.
1085// See GTMUnitTestDevLog.h for details
1086@interface GTMTestCase : SenTestCase
1087
1088// Returns YES if this is an abstract testCase class as opposed to a concrete
1089// testCase class that you want tests run against. SenTestCase is not designed
1090// out of the box to handle an abstract class hierarchy descending from it with
1091// some concrete subclasses.  In some cases we want all the "concrete"
1092// subclasses of an abstract subclass of SenTestCase to run a test, but we don't
1093// want that test to be run against an instance of an abstract subclass itself.
1094// By returning "YES" here, the tests defined by this class won't be run against
1095// an instance of this class. As an example class hierarchy:
1096//
1097//                                            FooExtensionTestCase
1098// GTMTestCase <- ExtensionAbstractTestCase <
1099//                                            BarExtensionTestCase
1100//
1101// So FooExtensionTestCase and BarExtensionTestCase inherit from
1102// ExtensionAbstractTestCase (and probably FooExtension and BarExtension inherit
1103// from a class named Extension). We want the tests in ExtensionAbstractTestCase
1104// to be run as part of FooExtensionTestCase and BarExtensionTestCase, but we
1105// don't want them run against ExtensionAbstractTestCase. The default
1106// implementation checks to see if the name of the class contains the word
1107// "AbstractTest" (case sensitive).
1108+ (BOOL)isAbstractTestCase;
1109
1110@end
1111