/Test.h
C Header | 96 lines | 53 code | 13 blank | 30 comment | 4 complexity | d3592c309256c07e2074d3375635eb80 MD5 | raw file
- //
- // Test.h
- // MYUtilities
- //
- // Created by Jens Alfke on 1/5/08.
- // Copyright 2008 Jens Alfke. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- #import "CollectionUtils.h"
- #import "Logging.h"
- /** Call this first thing in main() to run tests.
- This function is a no-op if the DEBUG macro is not defined (i.e. in a release build).
- At runtime, to cause a particular test "X" to run, add a command-line argument "Test_X".
- To run all tests, add the argument "Test_All".
- To run only tests without starting the main program, add the argument "Test_Only". */
- #if DEBUG
- void RunTestCases( int argc, const char **argv );
- extern BOOL gRunningTestCase;
- #else
- #define RunTestCases(ARGC,ARGV)
- #define gRunningTestCase NO
- #endif
- /** The TestCase() macro declares a test case.
- Its argument is a name for the test case (without quotes), and it's followed with a block
- of code implementing the test.
- The code should raise an exception if anything fails.
- The CAssert, CAssertEqual and CAssertEq macros, below, are the most useful way to do this.
- A test case can register a dependency on another test case by calling RequireTestCase().
- Example:
- TestCase(MyLib) {
- RequireTestCase("LibIDependOn");
- CAssertEq( myFunction(), 12345 );
- }
- Test cases are disabled if the DEBUG macro is not defined (i.e. in a release build). */
- #if DEBUG
- #define TestCase(NAME) __attribute__ ((section ("__TEXT, Tests"))) void Test_##NAME(void); \
- struct TestCaseLink linkToTest##NAME = {&Test_##NAME,#NAME}; \
- __attribute__((constructor)) static void registerTestCase##NAME() \
- {linkToTest##NAME.next = gAllTestCases; gAllTestCases=&linkToTest##NAME; } \
- void Test_##NAME(void)
- #else
- #define TestCase(NAME) __attribute__((unused)) static void Test_##NAME(void)
- #endif
- /** Can call this in a test case to indicate a prerequisite.
- The prerequisite test will be run first, and if it fails, the current test case will be skipped. */
- #if DEBUG
- #define RequireTestCase(NAME) _RequireTestCase(#NAME)
- void _RequireTestCase( const char *name );
- #else
- #define RequireTestCase(NAME)
- #endif
- /** General-purpose assertions, replacing NSAssert etc.. You can use these outside test cases. */
- #define Assert(COND,MSG...) do{ if( __builtin_expect(!(COND),NO) ) { \
- IN_SEGMENT_NORETURN(Logging) {_AssertFailed(self,_cmd, __FILE__, __LINE__,\
- #COND,##MSG,NULL);} } }while(0)
- #define CAssert(COND,MSG...) do{ if( __builtin_expect(!(COND),NO) ) { \
- static const char *_name = __PRETTY_FUNCTION__;\
- IN_SEGMENT_NORETURN(Logging) {_AssertFailed(nil, _name, __FILE__, __LINE__,\
- #COND,##MSG,NULL);} } }while(0)
- // AssertEqual is for Obj-C objects
- #define AssertEqual(VAL,EXPECTED) do{ id _val = VAL, _expected = EXPECTED;\
- Assert(_val==_expected || [_val isEqual: _expected], @"Unexpected value for %s: %@ (expected %@)", #VAL,_val,_expected); \
- }while(0)
- #define CAssertEqual(VAL,EXPECTED) do{ id _val = (VAL), _expected = (EXPECTED);\
- CAssert(_val==_expected || [_val isEqual: _expected], @"Unexpected value for %s: %@ (expected %@)", #VAL,_val,_expected); \
- }while(0)
- // AssertEq is for scalars (int, float...)
- #define AssertEq(VAL,EXPECTED) do{ __typeof(VAL) _val = VAL; __typeof(EXPECTED) _expected = EXPECTED;\
- Assert(_val==_expected, @"Unexpected value for %s: %@ (expected %@)", #VAL,$object(_val),$object(_expected)); \
- }while(0)
- #define CAssertEq(VAL,EXPECTED) do{ __typeof(VAL) _val = VAL; __typeof(EXPECTED) _expected = EXPECTED;\
- CAssert(_val==_expected, @"Unexpected value for %s: %@ (expected %@)", #VAL,$object(_val),$object(_expected)); \
- }while(0)
- #define AssertAbstractMethod() _AssertAbstractMethodFailed(self,_cmd);
- // Nasty internals ...
- #if DEBUG
- void _RunTestCase( void (*testptr)(), const char *name );
- struct TestCaseLink {void (*testptr)(); const char *name; BOOL passed; struct TestCaseLink *next;};
- extern struct TestCaseLink *gAllTestCases;
- #endif DEBUG
- void _AssertFailed( id rcvr, const void *selOrFn, const char *sourceFile, int sourceLine,
- const char *condString, NSString *message, ... ) __attribute__((noreturn));
- void _AssertAbstractMethodFailed( id rcvr, SEL cmd) __attribute__((noreturn));