michael@0: // michael@0: // GTMSenTestCase.h michael@0: // michael@0: // Copyright 2007-2008 Google Inc. michael@0: // michael@0: // Licensed under the Apache License, Version 2.0 (the "License"); you may not michael@0: // use this file except in compliance with the License. You may obtain a copy michael@0: // of the License at michael@0: // michael@0: // http://www.apache.org/licenses/LICENSE-2.0 michael@0: // michael@0: // Unless required by applicable law or agreed to in writing, software michael@0: // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT michael@0: // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the michael@0: // License for the specific language governing permissions and limitations under michael@0: // the License. michael@0: // michael@0: michael@0: // Portions of this file fall under the following license, marked with michael@0: // SENTE_BEGIN - SENTE_END michael@0: // michael@0: // Copyright (c) 1997-2005, Sen:te (Sente SA). All rights reserved. michael@0: // michael@0: // Use of this source code is governed by the following license: michael@0: // michael@0: // Redistribution and use in source and binary forms, with or without modification, michael@0: // are permitted provided that the following conditions are met: michael@0: // michael@0: // (1) Redistributions of source code must retain the above copyright notice, michael@0: // this list of conditions and the following disclaimer. michael@0: // michael@0: // (2) Redistributions in binary form must reproduce the above copyright notice, michael@0: // this list of conditions and the following disclaimer in the documentation michael@0: // and/or other materials provided with the distribution. michael@0: // michael@0: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' michael@0: // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED michael@0: // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. michael@0: // IN NO EVENT SHALL Sente SA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT michael@0: // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) michael@0: // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, michael@0: // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, michael@0: // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: // michael@0: // Note: this license is equivalent to the FreeBSD license. michael@0: // michael@0: // This notice may not be removed from this file. michael@0: michael@0: // Some extra test case macros that would have been convenient for SenTestingKit michael@0: // to provide. I didn't stick GTM in front of the Macro names, so that they would michael@0: // be easy to remember. michael@0: michael@0: #import "GTMDefines.h" michael@0: michael@0: #if (!GTM_IPHONE_SDK) || (GTM_IPHONE_USE_SENTEST) michael@0: #import michael@0: #else michael@0: #import michael@0: #ifdef __cplusplus michael@0: extern "C" { michael@0: #endif michael@0: michael@0: #if defined __clang__ michael@0: // gcc and gcc-llvm do not allow you to use STAssert(blah, nil) with nil michael@0: // as a description if you have the NS_FORMAT_FUNCTION on. michael@0: // clang however will not compile without warnings if you don't have it. michael@0: NSString *STComposeString(NSString *, ...) NS_FORMAT_FUNCTION(1, 2); michael@0: #else michael@0: NSString *STComposeString(NSString *, ...); michael@0: #endif // __clang__ michael@0: michael@0: #ifdef __cplusplus michael@0: } michael@0: #endif michael@0: michael@0: #endif // !GTM_IPHONE_SDK || GTM_IPHONE_USE_SENTEST michael@0: michael@0: // Generates a failure when a1 != noErr michael@0: // Args: michael@0: // a1: should be either an OSErr or an OSStatus michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertNoErr(a1, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: OSStatus a1value = (a1); \ michael@0: if (a1value != noErr) { \ michael@0: NSString *_expression = [NSString stringWithFormat:@"Expected noErr, got %ld for (%s)", (long)a1value, #a1]; \ michael@0: [self failWithException:([NSException failureInCondition:_expression \ michael@0: isTrue:NO \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == noErr fails", #a1] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: // Generates a failure when a1 != a2 michael@0: // Args: michael@0: // a1: received value. Should be either an OSErr or an OSStatus michael@0: // a2: expected value. Should be either an OSErr or an OSStatus michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertErr(a1, a2, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: OSStatus a1value = (a1); \ michael@0: OSStatus a2value = (a2); \ michael@0: if (a1value != a2value) { \ michael@0: NSString *_expression = [NSString stringWithFormat:@"Expected %s(%ld) but got %ld for (%s)", #a2, (long)a2value, (long)a1value, #a1]; \ michael@0: [self failWithException:([NSException failureInCondition:_expression \ michael@0: isTrue:NO \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s) fails", #a1, #a2] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: michael@0: // Generates a failure when a1 is NULL michael@0: // Args: michael@0: // a1: should be a pointer (use STAssertNotNil for an object) michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertNotNULL(a1, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: __typeof__(a1) a1value = (a1); \ michael@0: if (a1value == (__typeof__(a1))NULL) { \ michael@0: NSString *_expression = [NSString stringWithFormat:@"((%s) != NULL)", #a1]; \ michael@0: [self failWithException:([NSException failureInCondition:_expression \ michael@0: isTrue:NO \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != NULL fails", #a1] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: // Generates a failure when a1 is not NULL michael@0: // Args: michael@0: // a1: should be a pointer (use STAssertNil for an object) michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertNULL(a1, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: __typeof__(a1) a1value = (a1); \ michael@0: if (a1value != (__typeof__(a1))NULL) { \ michael@0: NSString *_expression = [NSString stringWithFormat:@"((%s) == NULL)", #a1]; \ michael@0: [self failWithException:([NSException failureInCondition:_expression \ michael@0: isTrue:NO \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == NULL fails", #a1] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: // Generates a failure when a1 is equal to a2. This test is for C scalars, michael@0: // structs and unions. michael@0: // Args: michael@0: // a1: argument 1 michael@0: // a2: argument 2 michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertNotEquals(a1, a2, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ michael@0: [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } else { \ michael@0: __typeof__(a1) a1value = (a1); \ michael@0: __typeof__(a2) a2value = (a2); \ michael@0: NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ michael@0: NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ michael@0: if ([a1encoded isEqualToValue:a2encoded]) { \ michael@0: NSString *_expression = [NSString stringWithFormat:@"((%s) != (%s))", #a1, #a2]; \ michael@0: [self failWithException:([NSException failureInCondition:_expression \ michael@0: isTrue:NO \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ michael@0: }\ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: // Generates a failure when a1 is equal to a2. This test is for objects. michael@0: // Args: michael@0: // a1: argument 1. object. michael@0: // a2: argument 2. object. michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertNotEqualObjects(a1, a2, description, ...) \ michael@0: do { \ michael@0: @try {\ michael@0: id a1value = (a1); \ michael@0: id a2value = (a2); \ michael@0: if ( (strcmp(@encode(__typeof__(a1value)), @encode(id)) == 0) && \ michael@0: (strcmp(@encode(__typeof__(a2value)), @encode(id)) == 0) && \ michael@0: (![(id)a1value isEqual:(id)a2value]) ) continue; \ michael@0: [self failWithException:([NSException failureInEqualityBetweenObject:a1value \ michael@0: andObject:a2value \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ michael@0: }\ michael@0: @catch (id anException) {\ michael@0: [self failWithException:([NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ michael@0: }\ michael@0: } while(0) michael@0: michael@0: // Generates a failure when a1 is not 'op' to a2. This test is for C scalars. michael@0: // Args: michael@0: // a1: argument 1 michael@0: // a2: argument 2 michael@0: // op: operation michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertOperation(a1, a2, op, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ michael@0: [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } else { \ michael@0: __typeof__(a1) a1value = (a1); \ michael@0: __typeof__(a2) a2value = (a2); \ michael@0: if (!(a1value op a2value)) { \ michael@0: double a1DoubleValue = a1value; \ michael@0: double a2DoubleValue = a2value; \ michael@0: NSString *_expression = [NSString stringWithFormat:@"(%s (%lg) %s %s (%lg))", #a1, a1DoubleValue, #op, #a2, a2DoubleValue]; \ michael@0: [self failWithException:([NSException failureInCondition:_expression \ michael@0: isTrue:NO \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \ michael@0: } \ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException \ michael@0: failureInRaise:[NSString stringWithFormat:@"(%s) %s (%s)", #a1, #op, #a2] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: // Generates a failure when a1 is not > a2. This test is for C scalars. michael@0: // Args: michael@0: // a1: argument 1 michael@0: // a2: argument 2 michael@0: // op: operation michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertGreaterThan(a1, a2, description, ...) \ michael@0: STAssertOperation(a1, a2, >, description, ##__VA_ARGS__) michael@0: michael@0: // Generates a failure when a1 is not >= a2. This test is for C scalars. michael@0: // Args: michael@0: // a1: argument 1 michael@0: // a2: argument 2 michael@0: // op: operation michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertGreaterThanOrEqual(a1, a2, description, ...) \ michael@0: STAssertOperation(a1, a2, >=, description, ##__VA_ARGS__) michael@0: michael@0: // Generates a failure when a1 is not < a2. This test is for C scalars. michael@0: // Args: michael@0: // a1: argument 1 michael@0: // a2: argument 2 michael@0: // op: operation michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertLessThan(a1, a2, description, ...) \ michael@0: STAssertOperation(a1, a2, <, description, ##__VA_ARGS__) michael@0: michael@0: // Generates a failure when a1 is not <= a2. This test is for C scalars. michael@0: // Args: michael@0: // a1: argument 1 michael@0: // a2: argument 2 michael@0: // op: operation michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertLessThanOrEqual(a1, a2, description, ...) \ michael@0: STAssertOperation(a1, a2, <=, description, ##__VA_ARGS__) michael@0: michael@0: // Generates a failure when string a1 is not equal to string a2. This call michael@0: // differs from STAssertEqualObjects in that strings that are different in michael@0: // composition (precomposed vs decomposed) will compare equal if their final michael@0: // representation is equal. michael@0: // ex O + umlaut decomposed is the same as O + umlaut composed. michael@0: // Args: michael@0: // a1: string 1 michael@0: // a2: string 2 michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertEqualStrings(a1, a2, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: id a1value = (a1); \ michael@0: id a2value = (a2); \ michael@0: if (a1value == a2value) continue; \ michael@0: if ([a1value isKindOfClass:[NSString class]] && \ michael@0: [a2value isKindOfClass:[NSString class]] && \ michael@0: [a1value compare:a2value options:0] == NSOrderedSame) continue; \ michael@0: [self failWithException:[NSException failureInEqualityBetweenObject:a1value \ michael@0: andObject:a2value \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: // Generates a failure when string a1 is equal to string a2. This call michael@0: // differs from STAssertEqualObjects in that strings that are different in michael@0: // composition (precomposed vs decomposed) will compare equal if their final michael@0: // representation is equal. michael@0: // ex O + umlaut decomposed is the same as O + umlaut composed. michael@0: // Args: michael@0: // a1: string 1 michael@0: // a2: string 2 michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertNotEqualStrings(a1, a2, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: id a1value = (a1); \ michael@0: id a2value = (a2); \ michael@0: if ([a1value isKindOfClass:[NSString class]] && \ michael@0: [a2value isKindOfClass:[NSString class]] && \ michael@0: [a1value compare:a2value options:0] != NSOrderedSame) continue; \ michael@0: [self failWithException:[NSException failureInEqualityBetweenObject:a1value \ michael@0: andObject:a2value \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: // Generates a failure when c-string a1 is not equal to c-string a2. michael@0: // Args: michael@0: // a1: string 1 michael@0: // a2: string 2 michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertEqualCStrings(a1, a2, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: const char* a1value = (a1); \ michael@0: const char* a2value = (a2); \ michael@0: if (a1value == a2value) continue; \ michael@0: if (strcmp(a1value, a2value) == 0) continue; \ michael@0: [self failWithException:[NSException failureInEqualityBetweenObject:[NSString stringWithUTF8String:a1value] \ michael@0: andObject:[NSString stringWithUTF8String:a2value] \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: // Generates a failure when c-string a1 is equal to c-string a2. michael@0: // Args: michael@0: // a1: string 1 michael@0: // a2: string 2 michael@0: // description: A format string as in the printf() function. Can be nil or michael@0: // an empty string but must be present. michael@0: // ...: A variable number of arguments to the format string. Can be absent. michael@0: #define STAssertNotEqualCStrings(a1, a2, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: const char* a1value = (a1); \ michael@0: const char* a2value = (a2); \ michael@0: if (strcmp(a1value, a2value) != 0) continue; \ michael@0: [self failWithException:[NSException failureInEqualityBetweenObject:[NSString stringWithUTF8String:a1value] \ michael@0: andObject:[NSString stringWithUTF8String:a2value] \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: /*" Generates a failure when a1 is not equal to a2 within + or - accuracy is false. michael@0: This test is for GLKit types (GLKVector, GLKMatrix) where small differences michael@0: could make these items not exactly equal. Do not use this version directly. michael@0: Use the explicit STAssertEqualGLKVectors and STAssertEqualGLKMatrices defined michael@0: below. michael@0: _{a1 The GLKType on the left.} michael@0: _{a2 The GLKType on the right.} michael@0: _{accuracy The maximum difference between a1 and a2 for these values to be michael@0: considered equal.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: michael@0: #define STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ michael@0: [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } else { \ michael@0: __typeof__(a1) a1GLKValue = (a1); \ michael@0: __typeof__(a2) a2GLKValue = (a2); \ michael@0: __typeof__(accuracy) accuracyvalue = (accuracy); \ michael@0: float *a1FloatValue = ((float*)&a1GLKValue); \ michael@0: float *a2FloatValue = ((float*)&a2GLKValue); \ michael@0: for (size_t i = 0; i < sizeof(__typeof__(a1)) / sizeof(float); ++i) { \ michael@0: float a1value = a1FloatValue[i]; \ michael@0: float a2value = a2FloatValue[i]; \ michael@0: if (STAbsoluteDifference(a1value, a2value) > accuracyvalue) { \ michael@0: NSMutableArray *strings = [NSMutableArray arrayWithCapacity:sizeof(a1) / sizeof(float)]; \ michael@0: NSString *string; \ michael@0: for (size_t j = 0; j < sizeof(__typeof__(a1)) / sizeof(float); ++j) { \ michael@0: string = [NSString stringWithFormat:@"(%0.3f == %0.3f)", a1FloatValue[j], a2FloatValue[j]]; \ michael@0: [strings addObject:string]; \ michael@0: } \ michael@0: string = [strings componentsJoinedByString:@", "]; \ michael@0: NSString *desc = STComposeString(description, ##__VA_ARGS__); \ michael@0: desc = [NSString stringWithFormat:@"%@ With Accuracy %0.3f: %@", string, (float)accuracyvalue, desc]; \ michael@0: [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", desc]]; \ michael@0: break; \ michael@0: } \ michael@0: } \ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: #define STAssertEqualGLKVectors(a1, a2, accuracy, description, ...) \ michael@0: STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ##__VA_ARGS__) michael@0: michael@0: #define STAssertEqualGLKMatrices(a1, a2, accuracy, description, ...) \ michael@0: STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ##__VA_ARGS__) michael@0: michael@0: #define STAssertEqualGLKQuaternions(a1, a2, accuracy, description, ...) \ michael@0: STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ##__VA_ARGS__) michael@0: michael@0: #if GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST michael@0: // When not using the Xcode provided version, define everything ourselves. michael@0: michael@0: // SENTE_BEGIN michael@0: /*" Generates a failure when !{ [a1 isEqualTo:a2] } is false michael@0: (or one is nil and the other is not). michael@0: _{a1 The object on the left.} michael@0: _{a2 The object on the right.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: #define STAssertEqualObjects(a1, a2, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: id a1value = (a1); \ michael@0: id a2value = (a2); \ michael@0: if (a1value == a2value) continue; \ michael@0: if ((strcmp(@encode(__typeof__(a1value)), @encode(id)) == 0) && \ michael@0: (strcmp(@encode(__typeof__(a2value)), @encode(id)) == 0) && \ michael@0: [(id)a1value isEqual:(id)a2value]) continue; \ michael@0: [self failWithException:[NSException failureInEqualityBetweenObject:a1value \ michael@0: andObject:a2value \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: michael@0: /*" Generates a failure when a1 is not equal to a2. This test is for michael@0: C scalars, structs and unions. michael@0: _{a1 The argument on the left.} michael@0: _{a2 The argument on the right.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: #define STAssertEquals(a1, a2, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ michael@0: [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } else { \ michael@0: __typeof__(a1) a1value = (a1); \ michael@0: __typeof__(a2) a2value = (a2); \ michael@0: NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ michael@0: NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ michael@0: if (![a1encoded isEqualToValue:a2encoded]) { \ michael@0: [self failWithException:[NSException failureInEqualityBetweenValue:a1encoded \ michael@0: andValue:a2encoded \ michael@0: withAccuracy:nil \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: #define STAbsoluteDifference(left,right) (MAX(left,right)-MIN(left,right)) michael@0: michael@0: michael@0: /*" Generates a failure when a1 is not equal to a2 within + or - accuracy is false. michael@0: This test is for scalars such as floats and doubles where small differences michael@0: could make these items not exactly equal, but also works for all scalars. michael@0: _{a1 The scalar on the left.} michael@0: _{a2 The scalar on the right.} michael@0: _{accuracy The maximum difference between a1 and a2 for these values to be michael@0: considered equal.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: michael@0: #define STAssertEqualsWithAccuracy(a1, a2, accuracy, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ michael@0: [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } else { \ michael@0: __typeof__(a1) a1value = (a1); \ michael@0: __typeof__(a2) a2value = (a2); \ michael@0: __typeof__(accuracy) accuracyvalue = (accuracy); \ michael@0: if (STAbsoluteDifference(a1value, a2value) > accuracyvalue) { \ michael@0: NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ michael@0: NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ michael@0: NSValue *accuracyencoded = [NSValue value:&accuracyvalue withObjCType:@encode(__typeof__(accuracy))]; \ michael@0: [self failWithException:[NSException failureInEqualityBetweenValue:a1encoded \ michael@0: andValue:a2encoded \ michael@0: withAccuracy:accuracyencoded \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: michael@0: michael@0: /*" Generates a failure unconditionally. michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: #define STFail(description, ...) \ michael@0: [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]] michael@0: michael@0: michael@0: michael@0: /*" Generates a failure when a1 is not nil. michael@0: _{a1 An object.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: #define STAssertNil(a1, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: id a1value = (a1); \ michael@0: if (a1value != nil) { \ michael@0: NSString *_a1 = [NSString stringWithUTF8String:#a1]; \ michael@0: NSString *_expression = [NSString stringWithFormat:@"((%@) == nil)", _a1]; \ michael@0: [self failWithException:[NSException failureInCondition:_expression \ michael@0: isTrue:NO \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == nil fails", #a1] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: michael@0: /*" Generates a failure when a1 is nil. michael@0: _{a1 An object.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: #define STAssertNotNil(a1, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: id a1value = (a1); \ michael@0: if (a1value == nil) { \ michael@0: NSString *_a1 = [NSString stringWithUTF8String:#a1]; \ michael@0: NSString *_expression = [NSString stringWithFormat:@"((%@) != nil)", _a1]; \ michael@0: [self failWithException:[NSException failureInCondition:_expression \ michael@0: isTrue:NO \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != nil fails", #a1] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while(0) michael@0: michael@0: michael@0: /*" Generates a failure when expression evaluates to false. michael@0: _{expr The expression that is tested.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: #define STAssertTrue(expr, description, ...) \ michael@0: do { \ michael@0: BOOL _evaluatedExpression = (expr); \ michael@0: if (!_evaluatedExpression) { \ michael@0: NSString *_expression = [NSString stringWithUTF8String:#expr]; \ michael@0: [self failWithException:[NSException failureInCondition:_expression \ michael@0: isTrue:NO \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while (0) michael@0: michael@0: michael@0: /*" Generates a failure when expression evaluates to false and in addition will michael@0: generate error messages if an exception is encountered. michael@0: _{expr The expression that is tested.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: #define STAssertTrueNoThrow(expr, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: BOOL _evaluatedExpression = (expr); \ michael@0: if (!_evaluatedExpression) { \ michael@0: NSString *_expression = [NSString stringWithUTF8String:#expr]; \ michael@0: [self failWithException:[NSException failureInCondition:_expression \ michael@0: isTrue:NO \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) ", #expr] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while (0) michael@0: michael@0: michael@0: /*" Generates a failure when the expression evaluates to true. michael@0: _{expr The expression that is tested.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: #define STAssertFalse(expr, description, ...) \ michael@0: do { \ michael@0: BOOL _evaluatedExpression = (expr); \ michael@0: if (_evaluatedExpression) { \ michael@0: NSString *_expression = [NSString stringWithUTF8String:#expr]; \ michael@0: [self failWithException:[NSException failureInCondition:_expression \ michael@0: isTrue:YES \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while (0) michael@0: michael@0: michael@0: /*" Generates a failure when the expression evaluates to true and in addition michael@0: will generate error messages if an exception is encountered. michael@0: _{expr The expression that is tested.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: #define STAssertFalseNoThrow(expr, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: BOOL _evaluatedExpression = (expr); \ michael@0: if (_evaluatedExpression) { \ michael@0: NSString *_expression = [NSString stringWithUTF8String:#expr]; \ michael@0: [self failWithException:[NSException failureInCondition:_expression \ michael@0: isTrue:YES \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"!(%s) ", #expr] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while (0) michael@0: michael@0: michael@0: /*" Generates a failure when expression does not throw an exception. michael@0: _{expression The expression that is evaluated.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent. michael@0: "*/ michael@0: #define STAssertThrows(expr, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: (expr); \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: continue; \ michael@0: } \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ michael@0: exception:nil \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } while (0) michael@0: michael@0: michael@0: /*" Generates a failure when expression does not throw an exception of a michael@0: specific class. michael@0: _{expression The expression that is evaluated.} michael@0: _{specificException The specified class of the exception.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: #define STAssertThrowsSpecific(expr, specificException, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: (expr); \ michael@0: } \ michael@0: @catch (specificException *anException) { \ michael@0: continue; \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \ michael@0: continue; \ michael@0: } \ michael@0: NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ michael@0: exception:nil \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \ michael@0: } while (0) michael@0: michael@0: michael@0: /*" Generates a failure when expression does not throw an exception of a michael@0: specific class with a specific name. Useful for those frameworks like michael@0: AppKit or Foundation that throw generic NSException w/specific names michael@0: (NSInvalidArgumentException, etc). michael@0: _{expression The expression that is evaluated.} michael@0: _{specificException The specified class of the exception.} michael@0: _{aName The name of the specified exception.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: michael@0: "*/ michael@0: #define STAssertThrowsSpecificNamed(expr, specificException, aName, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: (expr); \ michael@0: } \ michael@0: @catch (specificException *anException) { \ michael@0: if ([aName isEqualToString:[anException name]]) continue; \ michael@0: NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description); \ michael@0: [self failWithException: \ michael@0: [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \ michael@0: continue; \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \ michael@0: [self failWithException: \ michael@0: [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \ michael@0: continue; \ michael@0: } \ michael@0: NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \ michael@0: [self failWithException: \ michael@0: [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ michael@0: exception:nil \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \ michael@0: } while (0) michael@0: michael@0: michael@0: /*" Generates a failure when expression does throw an exception. michael@0: _{expression The expression that is evaluated.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: #define STAssertNoThrow(expr, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: (expr); \ michael@0: } \ michael@0: @catch (id anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: } while (0) michael@0: michael@0: michael@0: /*" Generates a failure when expression does throw an exception of the specitied michael@0: class. Any other exception is okay (i.e. does not generate a failure). michael@0: _{expression The expression that is evaluated.} michael@0: _{specificException The specified class of the exception.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: "*/ michael@0: #define STAssertNoThrowSpecific(expr, specificException, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: (expr); \ michael@0: } \ michael@0: @catch (specificException *anException) { \ michael@0: [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: @catch (id anythingElse) { \ michael@0: ; \ michael@0: } \ michael@0: } while (0) michael@0: michael@0: michael@0: /*" Generates a failure when expression does throw an exception of a michael@0: specific class with a specific name. Useful for those frameworks like michael@0: AppKit or Foundation that throw generic NSException w/specific names michael@0: (NSInvalidArgumentException, etc). michael@0: _{expression The expression that is evaluated.} michael@0: _{specificException The specified class of the exception.} michael@0: _{aName The name of the specified exception.} michael@0: _{description A format string as in the printf() function. Can be nil or michael@0: an empty string but must be present.} michael@0: _{... A variable number of arguments to the format string. Can be absent.} michael@0: michael@0: "*/ michael@0: #define STAssertNoThrowSpecificNamed(expr, specificException, aName, description, ...) \ michael@0: do { \ michael@0: @try { \ michael@0: (expr); \ michael@0: } \ michael@0: @catch (specificException *anException) { \ michael@0: if ([aName isEqualToString:[anException name]]) { \ michael@0: NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description); \ michael@0: [self failWithException: \ michael@0: [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \ michael@0: exception:anException \ michael@0: inFile:[NSString stringWithUTF8String:__FILE__] \ michael@0: atLine:__LINE__ \ michael@0: withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \ michael@0: } \ michael@0: continue; \ michael@0: } \ michael@0: @catch (id anythingElse) { \ michael@0: ; \ michael@0: } \ michael@0: } while (0) michael@0: michael@0: michael@0: michael@0: @interface NSException (GTMSenTestAdditions) michael@0: + (NSException *)failureInFile:(NSString *)filename michael@0: atLine:(int)lineNumber michael@0: withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(3, 4); michael@0: + (NSException *)failureInCondition:(NSString *)condition michael@0: isTrue:(BOOL)isTrue michael@0: inFile:(NSString *)filename michael@0: atLine:(int)lineNumber michael@0: withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(5, 6); michael@0: + (NSException *)failureInEqualityBetweenObject:(id)left michael@0: andObject:(id)right michael@0: inFile:(NSString *)filename michael@0: atLine:(int)lineNumber michael@0: withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(5, 6); michael@0: + (NSException *)failureInEqualityBetweenValue:(NSValue *)left michael@0: andValue:(NSValue *)right michael@0: withAccuracy:(NSValue *)accuracy michael@0: inFile:(NSString *)filename michael@0: atLine:(int) ineNumber michael@0: withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(6, 7); michael@0: + (NSException *)failureInRaise:(NSString *)expression michael@0: inFile:(NSString *)filename michael@0: atLine:(int)lineNumber michael@0: withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(4, 5); michael@0: + (NSException *)failureInRaise:(NSString *)expression michael@0: exception:(NSException *)exception michael@0: inFile:(NSString *)filename michael@0: atLine:(int)lineNumber michael@0: withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(5, 6); michael@0: @end michael@0: michael@0: // SENTE_END michael@0: michael@0: @protocol SenTestCase michael@0: + (id)testCaseWithInvocation:(NSInvocation *)anInvocation; michael@0: - (id)initWithInvocation:(NSInvocation *)anInvocation; michael@0: - (void)setUp; michael@0: - (void)invokeTest; michael@0: - (void)tearDown; michael@0: - (void)performTest; michael@0: - (void)failWithException:(NSException*)exception; michael@0: - (NSInvocation *)invocation; michael@0: - (SEL)selector; michael@0: + (NSArray *)testInvocations; michael@0: @end michael@0: michael@0: @interface SenTestCase : NSObject { michael@0: @private michael@0: NSInvocation *invocation_; michael@0: } michael@0: @end michael@0: michael@0: GTM_EXTERN NSString *const SenTestFailureException; michael@0: michael@0: GTM_EXTERN NSString *const SenTestFilenameKey; michael@0: GTM_EXTERN NSString *const SenTestLineNumberKey; michael@0: michael@0: #endif // GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST michael@0: michael@0: // All unittest cases in GTM should inherit from GTMTestCase. It makes sure michael@0: // to set up our logging system correctly to verify logging calls. michael@0: // See GTMUnitTestDevLog.h for details michael@0: @interface GTMTestCase : SenTestCase michael@0: michael@0: // Returns YES if this is an abstract testCase class as opposed to a concrete michael@0: // testCase class that you want tests run against. SenTestCase is not designed michael@0: // out of the box to handle an abstract class hierarchy descending from it with michael@0: // some concrete subclasses. In some cases we want all the "concrete" michael@0: // subclasses of an abstract subclass of SenTestCase to run a test, but we don't michael@0: // want that test to be run against an instance of an abstract subclass itself. michael@0: // By returning "YES" here, the tests defined by this class won't be run against michael@0: // an instance of this class. As an example class hierarchy: michael@0: // michael@0: // FooExtensionTestCase michael@0: // GTMTestCase <- ExtensionAbstractTestCase < michael@0: // BarExtensionTestCase michael@0: // michael@0: // So FooExtensionTestCase and BarExtensionTestCase inherit from michael@0: // ExtensionAbstractTestCase (and probably FooExtension and BarExtension inherit michael@0: // from a class named Extension). We want the tests in ExtensionAbstractTestCase michael@0: // to be run as part of FooExtensionTestCase and BarExtensionTestCase, but we michael@0: // don't want them run against ExtensionAbstractTestCase. The default michael@0: // implementation checks to see if the name of the class contains the word michael@0: // "AbstractTest" (case sensitive). michael@0: + (BOOL)isAbstractTestCase; michael@0: michael@0: @end