* Added MYReturnError.
* Better iPhone support in ExceptionUtils.
* Make sure "All Tests Passed/Failed" message is always logged.
1.1 --- a/ExceptionUtils.m Sat Apr 04 20:53:53 2009 -0700
1.2 +++ b/ExceptionUtils.m Tue Apr 07 11:13:25 2009 -0700
1.3 @@ -43,7 +43,7 @@
1.4 }
1.5
1.6
1.7 -@implementation NSException (MooseyardUtil)
1.8 +@implementation NSException (MYUtilities)
1.9
1.10
1.11 - (NSArray*) my_callStackReturnAddresses
1.12 @@ -70,10 +70,12 @@
1.13
1.14 - (NSString*) my_callStack
1.15 {
1.16 - NSArray *addresses = [self my_callStackReturnAddressesSkipping: 2 limit: 15];
1.17 + NSArray *addresses = [self my_callStackReturnAddressesSkipping: 1 limit: 15];
1.18 if (!addresses)
1.19 return nil;
1.20
1.21 + FILE *file = NULL;
1.22 +#if !TARGET_OS_IPHONE
1.23 // We pipe the hex return addresses through the 'atos' tool to get symbolic names:
1.24 // Adapted from <http://paste.lisp.org/display/47196>:
1.25 NSMutableString *cmd = [NSMutableString stringWithFormat: @"/usr/bin/atos -p %d", getpid()];
1.26 @@ -81,32 +83,41 @@
1.27 foreach(addr,addresses) {
1.28 [cmd appendFormat: @" %p", [addr pointerValue]];
1.29 }
1.30 - FILE *file = popen( [cmd UTF8String], "r" );
1.31 - if( ! file )
1.32 - return nil;
1.33 -
1.34 - NSMutableData *output = [NSMutableData data];
1.35 - char buffer[512];
1.36 - size_t length;
1.37 - while ((length = fread( buffer, 1, sizeof( buffer ), file ) ))
1.38 - [output appendBytes: buffer length: length];
1.39 - pclose( file );
1.40 - NSString *outStr = [[[NSString alloc] initWithData: output encoding: NSUTF8StringEncoding] autorelease];
1.41 + file = popen( [cmd UTF8String], "r" );
1.42 +#endif
1.43
1.44 NSMutableString *result = [NSMutableString string];
1.45 - NSString *line;
1.46 - foreach( line, [outStr componentsSeparatedByString: @"\n"] ) {
1.47 - // Skip frames that are part of the exception/assertion handling itself:
1.48 - if( [line hasPrefix: @"-[NSAssertionHandler"] || [line hasPrefix: @"+[NSException"]
1.49 - || [line hasPrefix: @"-[NSException"] || [line hasPrefix: @"_AssertFailed"] )
1.50 - continue;
1.51 - if( result.length )
1.52 - [result appendString: @"\n"];
1.53 - [result appendString: @"\t"];
1.54 - [result appendString: line];
1.55 - // Don't show the "__start" frame below "main":
1.56 - if( [line hasPrefix: @"main "] )
1.57 - break;
1.58 + if( file ) {
1.59 + NSMutableData *output = [NSMutableData data];
1.60 + char buffer[512];
1.61 + size_t length;
1.62 + while ((length = fread( buffer, 1, sizeof( buffer ), file ) ))
1.63 + [output appendBytes: buffer length: length];
1.64 + pclose( file );
1.65 + NSString *outStr = [[[NSString alloc] initWithData: output encoding: NSUTF8StringEncoding] autorelease];
1.66 +
1.67 + NSString *line;
1.68 + foreach( line, [outStr componentsSeparatedByString: @"\n"] ) {
1.69 + // Skip frames that are part of the exception/assertion handling itself:
1.70 + if( [line hasPrefix: @"-[NSAssertionHandler"] || [line hasPrefix: @"+[NSException"]
1.71 + || [line hasPrefix: @"-[NSException"] || [line hasPrefix: @"_AssertFailed"]
1.72 + || [line hasPrefix: @"objc_"] )
1.73 + continue;
1.74 + if( result.length )
1.75 + [result appendString: @"\n"];
1.76 + [result appendString: @"\t"];
1.77 + [result appendString: line];
1.78 + // Don't show the "__start" frame below "main":
1.79 + if( [line hasPrefix: @"main "] )
1.80 + break;
1.81 + }
1.82 + } else {
1.83 + NSValue *addr;
1.84 + foreach(addr,addresses) {
1.85 + if( result.length )
1.86 + [result appendString: @" <- "];
1.87 + [result appendFormat: @"%p", [addr pointerValue]];
1.88 + }
1.89 }
1.90 return result;
1.91 }
2.1 --- a/MYErrorUtils.h Sat Apr 04 20:53:53 2009 -0700
2.2 +++ b/MYErrorUtils.h Tue Apr 07 11:13:25 2009 -0700
2.3 @@ -24,6 +24,13 @@
2.4 NSError *MYError( int errorCode, NSString *domain, NSString *messageFormat, ... )
2.5 __attribute__ ((format (__NSString__, 3, 4)));
2.6
2.7 +/** A variant of MYError, useful for returning from a method.
2.8 + If errorCode is nonzero, constructs an NSError and stores it into *outError,
2.9 + then returns NO. Otherwise returns YES. */
2.10 +BOOL MYReturnError( NSError **outError,
2.11 + int errorCode, NSString *domain, NSString *messageFormat, ... )
2.12 + __attribute__ ((format (__NSString__, 4, 5)));
2.13 +
2.14 /** Convenience function for creating NSErrors.
2.15 Stores an NSError into *error, and returns NO.
2.16 Domain will be MYErrorDomain, code will be kMYErrorMisc.
3.1 --- a/MYErrorUtils.m Sat Apr 04 20:53:53 2009 -0700
3.2 +++ b/MYErrorUtils.m Tue Apr 07 11:13:25 2009 -0700
3.3 @@ -10,6 +10,7 @@
3.4 #import "Test.h"
3.5 #import "CollectionUtils.h"
3.6 #import <Foundation/Foundation.h>
3.7 +#import <Security/SecBase.h>
3.8
3.9
3.10 NSString* const MYErrorDomain = @"MYErrorDomain";
3.11 @@ -39,6 +40,22 @@
3.12 }
3.13
3.14
3.15 +BOOL MYReturnError( NSError **outError,
3.16 + int errorCode, NSString *domain, NSString *messageFormat, ... )
3.17 +{
3.18 + if (errorCode) {
3.19 + if (outError) {
3.20 + va_list args;
3.21 + va_start(args,messageFormat);
3.22 + *outError = MYMakeErrorV(errorCode, domain, messageFormat, args);
3.23 + va_end(args);
3.24 + }
3.25 + return NO;
3.26 + } else
3.27 + return YES;
3.28 +}
3.29 +
3.30 +
3.31 BOOL MYMiscError( NSError **error, NSString *message, ... )
3.32 {
3.33 if (error) {
3.34 @@ -106,7 +123,7 @@
3.35 result = nil;
3.36 }
3.37 }
3.38 -#if !TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
3.39 +#if !TARGET_OS_IPHONE || defined(__SEC_TYPES__)
3.40 else if ($equal(domain,NSOSStatusErrorDomain)) {
3.41 // If it's an OSStatus, check whether CarbonCore knows its name:
3.42 const char *name = NULL;
4.1 --- a/Test.m Sat Apr 04 20:53:53 2009 -0700
4.2 +++ b/Test.m Tue Apr 07 11:13:25 2009 -0700
4.3 @@ -107,9 +107,9 @@
4.4 }
4.5 if( sPassed>0 || sFailed>0 || stopAfterTests ) {
4.6 if( sFailed==0 )
4.7 - Log(@"√√√√√√ ALL %i TESTS PASSED √√√√√√", sPassed);
4.8 + AlwaysLog(@"√√√√√√ ALL %i TESTS PASSED √√√√√√", sPassed);
4.9 else {
4.10 - Log(@"****** %i TESTS FAILED, %i PASSED ******", sFailed,sPassed);
4.11 + Warn(@"****** %i TESTS FAILED, %i PASSED ******", sFailed,sPassed);
4.12 exit(1);
4.13 }
4.14 if( stopAfterTests ) {