* Assert macros now put the failure code in a separate segment.
* Added $string utility.
5 // Created by Jens Alfke on 1/5/08.
6 // Copyright 2008 Jens Alfke. All rights reserved.
9 #import <Foundation/Foundation.h>
10 #import "CollectionUtils.h"
14 /** Call this first thing in main() to run tests.
15 This function is a no-op if the DEBUG macro is not defined (i.e. in a release build).
16 At runtime, to cause a particular test "X" to run, add a command-line argument "Test_X".
17 To run all tests, add the argument "Test_All".
18 To run only tests without starting the main program, add the argument "Test_Only". */
20 void RunTestCases( int argc, const char **argv );
21 extern BOOL gRunningTestCase;
23 #define RunTestCases(ARGC,ARGV)
24 #define gRunningTestCase NO
27 /** The TestCase() macro declares a test case.
28 Its argument is a name for the test case (without quotes), and it's followed with a block
29 of code implementing the test.
30 The code should raise an exception if anything fails.
31 The CAssert, CAssertEqual and CAssertEq macros, below, are the most useful way to do this.
32 A test case can register a dependency on another test case by calling RequireTestCase().
35 RequireTestCase("LibIDependOn");
36 CAssertEq( myFunction(), 12345 );
38 Test cases are disabled if the DEBUG macro is not defined (i.e. in a release build). */
40 #define TestCase(NAME) __attribute__ ((section ("__TEXT, Tests"))) void Test_##NAME(void); \
41 struct TestCaseLink linkToTest##NAME = {&Test_##NAME,#NAME}; \
42 __attribute__((constructor)) static void registerTestCase##NAME() \
43 {linkToTest##NAME.next = gAllTestCases; gAllTestCases=&linkToTest##NAME; } \
44 void Test_##NAME(void)
46 #define TestCase(NAME) __attribute__((unused)) static void Test_##NAME(void)
49 /** Can call this in a test case to indicate a prerequisite.
50 The prerequisite test will be run first, and if it fails, the current test case will be skipped. */
51 #define RequireTestCase(NAME) _RequireTestCase(#NAME)
52 void _RequireTestCase( const char *name );
56 /** General-purpose assertions, replacing NSAssert etc.. You can use these outside test cases. */
59 #define IN_SEGMENT_NORETURN(SEG)
61 #define IN_SEGMENT_NORETURN(SEG) auto __attribute__ ((section ("__TEXT, "#SEG))) __attribute__ ((noinline)) __attribute__((noreturn)) void _assertfailure_(void);\
63 void _assertfailure_(void)
67 #define Assert(COND,MSG...) do{ if( __builtin_expect(!(COND),NO) ) { \
68 IN_SEGMENT_NORETURN(Logging) {_AssertFailed(self,(const char*)_cmd, __FILE__, __LINE__,\
69 #COND,##MSG,NULL);} } }while(0)
70 #define CAssert(COND,MSG...) do{ if( __builtin_expect(!(COND),NO) ) { \
71 static const char *_name = __PRETTY_FUNCTION__;\
72 IN_SEGMENT_NORETURN(Logging) {_AssertFailed(nil, _name, __FILE__, __LINE__,\
73 #COND,##MSG,NULL);} } }while(0)
75 #define AssertEqual(VAL,EXPECTED) do{ id _val = VAL, _expected = EXPECTED;\
76 Assert(_val==_expected || [_val isEqual: _expected], @"Unexpected value for %s: %@ (expected %@)", #VAL,_val,_expected); \
78 #define CAssertEqual(VAL,EXPECTED) do{ id _val = (VAL), _expected = (EXPECTED);\
79 CAssert(_val==_expected || [_val isEqual: _expected], @"Unexpected value for %s: %@ (expected %@)", #VAL,_val,_expected); \
82 // AssertEq is for scalars (int, float...)
83 #define AssertEq(VAL,EXPECTED) do{ typeof(VAL) _val = VAL; typeof(EXPECTED) _expected = EXPECTED;\
84 Assert(_val==_expected, @"Unexpected value for %s: %@ (expected %@)", #VAL,$object(_val),$object(_expected)); \
86 #define CAssertEq(VAL,EXPECTED) do{ typeof(VAL) _val = VAL; typeof(EXPECTED) _expected = EXPECTED;\
87 CAssert(_val==_expected, @"Unexpected value for %s: %@ (expected %@)", #VAL,$object(_val),$object(_expected)); \
92 #pragma mark EXCEPTION UTILITIES:
94 @interface NSException (MooseyardUtil)
95 /** Returns a textual, human-readable backtrace of the point where the exception was thrown. */
96 - (NSString*) my_callStack;
101 // Nasty internals ...
103 void _RunTestCase( void (*testptr)(), const char *name );
105 struct TestCaseLink {void (*testptr)(); const char *name; BOOL passed; struct TestCaseLink *next;};
106 extern struct TestCaseLink *gAllTestCases;
108 void _AssertFailed( id rcvr, const char *selOrFn, const char *sourceFile, int sourceLine,
109 const char *condString, NSString *message, ... ) __attribute__((noreturn));