aboutsummaryrefslogtreecommitdiff
path: root/UnitTesting
diff options
context:
space:
mode:
Diffstat (limited to 'UnitTesting')
-rw-r--r--UnitTesting/GTMAppKit+UnitTesting.m2
-rw-r--r--UnitTesting/GTMIPhoneUnitTestDelegate.m44
-rw-r--r--UnitTesting/GTMNSObject+BindingUnitTesting.h32
-rw-r--r--UnitTesting/GTMNSObject+BindingUnitTesting.m347
-rw-r--r--UnitTesting/GTMNSObject+UnitTesting.m90
-rw-r--r--UnitTesting/GTMSenTestCase.h7
-rw-r--r--UnitTesting/GTMSenTestCase.m308
-rw-r--r--UnitTesting/GTMTestTimer.h22
-rw-r--r--UnitTesting/GTMUnitTestingBindingTest.m9
-rw-r--r--UnitTesting/GTMUnitTestingUtilities.m2
-rwxr-xr-xUnitTesting/RunIPhoneUnitTest.sh28
-rwxr-xr-xUnitTesting/RunMacOSUnitTests.sh173
-rw-r--r--UnitTesting/TestData/GTMUnitTestingImage.10.6.0.tiffbin0 -> 21014 bytes
-rw-r--r--UnitTesting/TestData/GTMUnitTestingWindow.10.6.0.tiffbin0 -> 21380 bytes
14 files changed, 709 insertions, 355 deletions
diff --git a/UnitTesting/GTMAppKit+UnitTesting.m b/UnitTesting/GTMAppKit+UnitTesting.m
index 6cb5a8b..0e21491 100644
--- a/UnitTesting/GTMAppKit+UnitTesting.m
+++ b/UnitTesting/GTMAppKit+UnitTesting.m
@@ -30,7 +30,7 @@
#endif
@implementation NSApplication (GMUnitTestingAdditions)
-GTM_METHOD_CHECK(NSObject, gtm_unitTestEncodeState:); // COV_NF_LINE
+GTM_METHOD_CHECK(NSObject, gtm_unitTestEncodeState:);
- (void)gtm_unitTestEncodeState:(NSCoder*)inCoder {
[super gtm_unitTestEncodeState:inCoder];
diff --git a/UnitTesting/GTMIPhoneUnitTestDelegate.m b/UnitTesting/GTMIPhoneUnitTestDelegate.m
index a793ff4..7ef46fc 100644
--- a/UnitTesting/GTMIPhoneUnitTestDelegate.m
+++ b/UnitTesting/GTMIPhoneUnitTestDelegate.m
@@ -34,36 +34,9 @@ static int MethodSort(const void *a, const void *b) {
return strcmp(nameA, nameB);
}
-static void RunLeaks(void) {
- // This is an atexit handler. It runs leaks for us to check if we are
- // leaking anything in our tests. Note that leaks and NSZombieEnabled
- // don't play well together, so we attempt to filter out the zombies from
- // our leaks when NSZombieEnabled is on.
- BOOL zombiesOn = getenv("NSZombieEnabled") != NULL;
- NSString *filterZombies = @"| grep -v _NSZombie";
- NSString *zombieExplanation = @"echo 'Leaks:0: note: NSZombies being "
- @"filtered from leaks. If zombies are on, ignore the \"x leaks for y total "
- @"leaked bytes.\" line above unless actual leaks are reported. "
- @"Set the 'GTM_DISABLE_ZOMBIES' environment variable to turn off "
- @"zombies, and to get more information about the leaks.'";
- NSString *string
- = [NSString stringWithFormat:@"/usr/bin/leaks %@ %d %@"
- @"| /usr/bin/sed \"s/Leak: /Leaks:0: warning: Leak /\"; %@",
- zombiesOn ? @"-nocontext -nostacks" : @"",
- getpid(),
- zombiesOn ? filterZombies : @"",
- zombiesOn ? zombieExplanation : @""];
- int ret = system([string UTF8String]);
- if (ret) {
- fprintf(stderr, "%s:%d: Error: Unable to run leaks. 'system' returned: %d",
- __FILE__, __LINE__, ret);
- fflush(stderr);
- }
-}
-
@interface UIApplication (iPhoneUnitTestAdditions)
// "Private" method that we need
-- (void)terminate;
+- (void)terminateWithSuccess;
@end
@implementation GTMIPhoneUnitTestDelegate
@@ -85,19 +58,14 @@ static void RunLeaks(void) {
// that are subclasses of SenTestCase. Terminate the application upon
// test completion.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
- // Don't want to get leaks on the device as the device doesn't
- // have 'leaks'. We check for this by looking for the
- // IPHONEOS_DEPLOYMENT_TARGET env var. If it isn't there, we are running
- // on the simulator.
- if (!getenv("IPHONEOS_DEPLOYMENT_TARGET")) {
- if (!getenv("GTM_DISABLE_LEAKS")) {
- atexit(&RunLeaks);
- }
- }
[self runTests];
+
// Using private call to end our tests
if (!getenv("GTM_DISABLE_TERMINATION")) {
- [[UIApplication sharedApplication] terminate];
+ // I call this delayed just to make sure that the stack is clean
+ [application performSelector:@selector(terminateWithSuccess)
+ withObject:nil
+ afterDelay:0.00];
}
}
diff --git a/UnitTesting/GTMNSObject+BindingUnitTesting.h b/UnitTesting/GTMNSObject+BindingUnitTesting.h
index 947221a..462bb9b 100644
--- a/UnitTesting/GTMNSObject+BindingUnitTesting.h
+++ b/UnitTesting/GTMNSObject+BindingUnitTesting.h
@@ -58,6 +58,23 @@ do { \
} \
} while(0)
+// Utility class for setting up Binding Tests. Basically a pair of a value to
+// set a binding to, followed by the expected return value.
+// See description of gtm_unitTestExposedBindingsTestValues: below
+// for example of usage.
+@interface GTMBindingUnitTestData : NSObject {
+ @private
+ id valueToSet_;
+ id expectedValue_;
+}
+
++ (id)testWithIdentityValue:(id)value;
++ (id)testWithValue:(id)value expecting:(id)expecting;
+- (id)initWithValue:(id)value expecting:(id)expecting;
+- (id)valueToSet;
+- (id)expectedValue;
+@end
+
@interface NSObject (GTMBindingUnitTestingAdditions)
// Allows you to ignore certain bindings when running GTMTestExposedBindings
// If you have bindings you want to ignore, add them to the array returned
@@ -76,14 +93,15 @@ do { \
// Allows you to set up test values for your different bindings.
// if you have certain values you want to test against your bindings, add
-// them to the dictionary returned by this method. The dictionary is a "value" key
-// and an "expected return" object.
+// them to the array returned by this method. The array is an array of
+// GTMBindingUnitTestData.
// The standard way to implement this would be:
-// - (NSMutableDictionary*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding {
-// NSMutableDictionary *dict = [super unitTestExposedBindingsTestValues:binding];
+// - (NSMutableArray*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding {
+// NSMutableArray *dict = [super unitTestExposedBindingsTestValues:binding];
// if ([binding isEqualToString:@"myBinding"]) {
-// [dict setObject:[[[MySpecialBindingValueSet alloc] init] autorelease]
-// forKey:[[[MySpecialBindingValueGet alloc] init] autorelease]];
+// MySpecialBindingValueSet *value
+// = [[[MySpecialBindingValueSet alloc] init] autorelease];
+// [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
// ...
// else if ([binding isEqualToString:@"myBinding2"]) {
// ...
@@ -94,7 +112,7 @@ do { \
// gives you a reasonable set of test values to start.
// See the implementation for the current list of bindings, and values that we
// set for those bindings.
-- (NSMutableDictionary*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding;
+- (NSMutableArray*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding;
// A special version of isEqualTo to test whether two binding values are equal
// by default it calls directly to isEqualTo: but can be overridden for special
diff --git a/UnitTesting/GTMNSObject+BindingUnitTesting.m b/UnitTesting/GTMNSObject+BindingUnitTesting.m
index 7773542..1ce1c88 100644
--- a/UnitTesting/GTMNSObject+BindingUnitTesting.m
+++ b/UnitTesting/GTMNSObject+BindingUnitTesting.m
@@ -20,6 +20,7 @@
#import "GTMDefines.h"
#import "GTMNSObject+BindingUnitTesting.h"
+#import "GTMSystemVersion.h"
BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
NSArray **errors) {
@@ -36,8 +37,10 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
if (![bindingsToIgnore containsObject:bindingKey]) {
Class theClass = [object valueClassForBinding:bindingKey];
if (!theClass) {
- [errorArray addObject:[NSString stringWithFormat:@"%@ should have valueClassForBinding '%@'",
- object, bindingKey]];
+ NSString *error
+ = [NSString stringWithFormat:@"%@ should have valueClassForBinding '%@'",
+ object, bindingKey];
+ [errorArray addObject:error];
continue;
}
@try {
@@ -45,32 +48,41 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
[object valueForKey:bindingKey];
}
@catch (NSException *e) {
- _GTMDevLog(@"%@ is not key value coding compliant for key %@", object, bindingKey);
+ _GTMDevLog(@"%@ is not key value coding compliant for key %@",
+ object, bindingKey);
continue;
} // COV_NF_LINE - compiler bug
- NSDictionary *testValues = [object gtm_unitTestExposedBindingsTestValues:bindingKey];
- NSEnumerator *testEnum = [testValues keyEnumerator];
- id testValue;
- while ((testValue = [testEnum nextObject])) {
- [object setValue:testValue forKey:bindingKey];
- id value = [object valueForKey:bindingKey];
- id desiredValue = [testValues objectForKey:testValue];
- if (![desiredValue gtm_unitTestIsEqualTo:value]) {
- [errorArray addObject:[NSString stringWithFormat:@"%@ unequal to %@ for binding '%@'",
- value, desiredValue, bindingKey]];
+ NSArray *testValues
+ = [object gtm_unitTestExposedBindingsTestValues:bindingKey];
+ NSEnumerator *testEnum = [testValues objectEnumerator];
+ GTMBindingUnitTestData *testData;
+ while ((testData = [testEnum nextObject])) {
+ id valueToSet = [testData valueToSet];
+ [object setValue:valueToSet forKey:bindingKey];
+ id valueReceived = [object valueForKey:bindingKey];
+ id desiredValue = [testData expectedValue];
+ if (![desiredValue gtm_unitTestIsEqualTo:valueReceived]) {
+ NSString *error
+ = [NSString stringWithFormat:@"%@ unequal to expected %@ for binding '%@'",
+ valueReceived, desiredValue, bindingKey];
+ [errorArray addObject:error];
continue;
}
}
}
@catch(NSException *e) {
- [errorArray addObject:[NSString stringWithFormat:@"%@:%@-> Binding %@",
- [e name], [e reason], bindingKey]];
+ NSString *error
+ = [NSString stringWithFormat:@"%@:%@-> Binding %@",
+ [e name], [e reason], bindingKey];
+ [errorArray addObject:error];
} // COV_NF_LINE - compiler bug
}
}
} else {
- [errorArray addObject:[NSString stringWithFormat:@"%@ does not have any exposed bindings",
- object]];
+ NSString *error =
+ [NSString stringWithFormat:@"%@ does not have any exposed bindings",
+ object];
+ [errorArray addObject:error];
}
if (errors) {
*errors = errorArray;
@@ -78,10 +90,51 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
return [errorArray count] == 0;
}
-// Utility for simplifying unitTestExposedBindingsTestValues implementations
-@interface NSMutableDictionary (GTMUnitTestingAdditions)
-// Sets an object and a key to the same value in a dictionary.
-- (void)gtm_setObjectAndKey:(id)objectAndKey;
+@implementation GTMBindingUnitTestData
++ (id)testWithIdentityValue:(id)value {
+ return [self testWithValue:value expecting:value];
+}
+
++ (id)testWithValue:(id)value expecting:(id)expecting {
+ return [[[self alloc] initWithValue:value expecting:expecting] autorelease];
+}
+
+- (id)initWithValue:(id)value expecting:(id)expecting {
+ if ((self = [super init])) {
+ valueToSet_ = [value retain];
+ expectedValue_ = [expecting retain];
+ }
+ return self;
+}
+
+- (BOOL)isEqual:(id)object {
+ BOOL isEqual = [object isMemberOfClass:[self class]];
+ if (isEqual) {
+ id objValue = [object valueToSet];
+ id objExpect = [object expectedValue];
+ isEqual = (((valueToSet_ == objValue) || ([valueToSet_ isEqual:objValue]))
+ && ((expectedValue_ == objExpect) || ([expectedValue_ isEqual:objExpect])));
+ }
+ return isEqual;
+}
+
+- (NSUInteger)hash {
+ return [valueToSet_ hash] + [expectedValue_ hash];
+}
+
+- (void)dealloc {
+ [valueToSet_ release];
+ [expectedValue_ release];
+ [super dealloc];
+}
+
+- (id)valueToSet {
+ return valueToSet_;
+}
+
+- (id)expectedValue {
+ return expectedValue_;
+}
@end
@implementation NSObject (GTMBindingUnitTestingAdditions)
@@ -98,14 +151,14 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
return array;
}
-- (NSMutableDictionary*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding {
+- (NSMutableArray*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding {
- NSMutableDictionary *dict = [NSMutableDictionary dictionary];
+ NSMutableArray *array = [NSMutableArray array];
id value = [self valueForKey:binding];
// Always test identity if possible
if (value) {
- [dict gtm_setObjectAndKey:value];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
}
// Now some default test values for a variety of bindings to make
@@ -114,21 +167,30 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
// If anybody can think of more to add, please go nuts.
if ([binding isEqualToString:NSAlignmentBinding]) {
- [dict gtm_setObjectAndKey:[NSNumber numberWithInt:NSLeftTextAlignment]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithInt:NSRightTextAlignment]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithInt:NSCenterTextAlignment]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithInt:NSJustifiedTextAlignment]];
- NSNumber *natural = [NSNumber numberWithInt:NSNaturalTextAlignment];
- [dict gtm_setObjectAndKey:natural];
- [dict setObject:natural forKey:[NSNumber numberWithInt:500]];
- [dict setObject:natural forKey:[NSNumber numberWithInt:-1]];
+ value = [NSNumber numberWithInt:NSLeftTextAlignment];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithInt:NSRightTextAlignment];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithInt:NSCenterTextAlignment];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithInt:NSJustifiedTextAlignment];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithInt:NSNaturalTextAlignment];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ NSNumber *valueToSet = [NSNumber numberWithInt:500];
+ [array addObject:[GTMBindingUnitTestData testWithValue:valueToSet
+ expecting:value]];
+ valueToSet = [NSNumber numberWithInt:-1];
+ [array addObject:[GTMBindingUnitTestData testWithValue:valueToSet
+ expecting:value]];
} else if ([binding isEqualToString:NSAlternateImageBinding] ||
[binding isEqualToString:NSImageBinding] ||
[binding isEqualToString:NSMixedStateImageBinding] ||
[binding isEqualToString:NSOffStateImageBinding] ||
[binding isEqualToString:NSOnStateImageBinding]) {
// This handles all image bindings
- [dict gtm_setObjectAndKey:[NSImage imageNamed:@"NSApplicationIcon"]];
+ value = [NSImage imageNamed:@"NSApplicationIcon"];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
} else if ([binding isEqualToString:NSAnimateBinding] ||
[binding isEqualToString:NSDocumentEditedBinding] ||
[binding isEqualToString:NSEditableBinding] ||
@@ -139,57 +201,88 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
// NSTranparentBinding 10.5 only
[binding isEqualToString:@"transparent"]) {
// This handles all bool value bindings
- [dict gtm_setObjectAndKey:[NSNumber numberWithBool:YES]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithBool:NO]];
+ value = [NSNumber numberWithBool:YES];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithBool:NO];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
} else if ([binding isEqualToString:NSAlternateTitleBinding] ||
[binding isEqualToString:NSHeaderTitleBinding] ||
[binding isEqualToString:NSLabelBinding] ||
[binding isEqualToString:NSTitleBinding] ||
[binding isEqualToString:NSToolTipBinding]) {
// This handles all string value bindings
- [dict gtm_setObjectAndKey:@"happy"];
- [dict gtm_setObjectAndKey:@""];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:@"happy"]];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:@""]];
// Test some non-ascii roman text
char a_not_alpha[] = { 'A', 0xE2, 0x89, 0xA2, 0xCE, 0x91, '.', 0x00 };
- [dict gtm_setObjectAndKey:[NSString stringWithUTF8String:a_not_alpha]];
+ value = [NSString stringWithUTF8String:a_not_alpha];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
// Test some korean
char hangugo[] = { 0xED, 0x95, 0x9C, 0xEA, 0xB5,
- 0xAD, 0xEC, 0x96, 0xB4, 0x00 };
- [dict gtm_setObjectAndKey:[NSString stringWithUTF8String:hangugo]];
+ 0xAD, 0xEC, 0x96, 0xB4, 0x00 };
+ value = [NSString stringWithUTF8String:hangugo];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
// Test some japanese
char nihongo[] = { 0xE6, 0x97, 0xA5, 0xE6, 0x9C,
0xAC, 0xE8, 0xAA, 0x9E, 0x00 };
- [dict gtm_setObjectAndKey:[NSString stringWithUTF8String:nihongo]];
+ value = [NSString stringWithUTF8String:nihongo];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
// Test some arabic
char arabic[] = { 0xd9, 0x83, 0xd8, 0xa7, 0xd9, 0x83, 0xd8, 0xa7, 0x00 };
- [dict gtm_setObjectAndKey:[NSString stringWithUTF8String:arabic]];
+ value = [NSString stringWithUTF8String:arabic];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
} else if ([binding isEqualToString:NSRepresentedFilenameBinding]) {
// This handles all path bindings
- [dict gtm_setObjectAndKey:@"/happy"];
- [dict gtm_setObjectAndKey:@"/"];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:@"/happy"]];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:@"/"]];
// Test some non-ascii roman text
char a_not_alpha[] = { '/', 'A', 0xE2, 0x89, 0xA2, 0xCE, 0x91, '.', 0x00 };
- [dict gtm_setObjectAndKey:[NSString stringWithUTF8String:a_not_alpha]];
+ value = [NSString stringWithUTF8String:a_not_alpha];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
// Test some korean
char hangugo[] = { '/', 0xED, 0x95, 0x9C, 0xEA, 0xB5,
- 0xAD, 0xEC, 0x96, 0xB4, 0x00 };
- [dict gtm_setObjectAndKey:[NSString stringWithUTF8String:hangugo]];
+ 0xAD, 0xEC, 0x96, 0xB4, 0x00 };
+ value = [NSString stringWithUTF8String:hangugo];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
// Test some japanese
char nihongo[] = { '/', 0xE6, 0x97, 0xA5, 0xE6, 0x9C,
- 0xAC, 0xE8, 0xAA, 0x9E, 0x00 };
- [dict gtm_setObjectAndKey:[NSString stringWithUTF8String:nihongo]];
+ 0xAC, 0xE8, 0xAA, 0x9E, 0x00 };
+ value = [NSString stringWithUTF8String:nihongo];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
// Test some arabic
char arabic[] = { '/', 0xd9, 0x83, 0xd8, 0xa7, 0xd9, 0x83, 0xd8, 0xa7, 0x00 };
- [dict gtm_setObjectAndKey:[NSString stringWithUTF8String:arabic]];
- } else if ([binding isEqualToString:NSMaximumRecentsBinding] ||
- [binding isEqualToString:NSRowHeightBinding]) {
- // This handles all int value bindings
- [dict gtm_setObjectAndKey:[NSNumber numberWithInt:0]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithInt:-1]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithInt:INT16_MAX]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithInt:INT16_MIN]];
+ value = [NSString stringWithUTF8String:arabic];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ } else if ([binding isEqualToString:NSMaximumRecentsBinding]) {
+ value = [NSNumber numberWithInt:0];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithInt:-1];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithInt:INT16_MAX];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithInt:INT16_MIN];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ } else if ([binding isEqualToString:NSRowHeightBinding]) {
+ NSNumber *valueOne = [NSNumber numberWithInt:1];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:valueOne]];
+ value = [NSNumber numberWithInt:0];
+ id value2 = [NSNumber numberWithInt:INT16_MIN];
+ // Row height no longer accepts <= 0 values on SnowLeopard
+ // which is a good thing.
+ if ([GTMSystemVersion isSnowLeopardOrGreater]) {
+ [array addObject:[GTMBindingUnitTestData testWithValue:value
+ expecting:valueOne]];
+
+ [array addObject:[GTMBindingUnitTestData testWithValue:value2
+ expecting:valueOne]];
+ } else {
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value2]];
+ }
+ value = [NSNumber numberWithInt:INT16_MAX];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
} else if ([binding isEqualToString:NSMaxValueBinding] ||
[binding isEqualToString:NSMaxWidthBinding] ||
[binding isEqualToString:NSMinValueBinding] ||
@@ -198,39 +291,57 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
[binding isEqualToString:NSContentHeightBinding] ||
[binding isEqualToString:NSWidthBinding] ||
[binding isEqualToString:NSAnimationDelayBinding]) {
+ // NSAnimationDelay is deprecated on SnowLeopard. We continue to test it
+ // to make sure it doesn't get broken.
+
// This handles all float value bindings
- [dict gtm_setObjectAndKey:[NSNumber numberWithFloat:0]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithFloat:FLT_MAX]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithFloat:-FLT_MAX]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithFloat:FLT_MIN]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithFloat:-FLT_MIN]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithFloat:FLT_EPSILON]];
- [dict gtm_setObjectAndKey:[NSNumber numberWithFloat:-FLT_EPSILON]];
+ value = [NSNumber numberWithFloat:0];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithFloat:FLT_MAX];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithFloat:-FLT_MAX];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithFloat:FLT_MIN];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithFloat:-FLT_MIN];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithFloat:FLT_EPSILON];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSNumber numberWithFloat:-FLT_EPSILON];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
} else if ([binding isEqualToString:NSTextColorBinding]) {
// This handles all color value bindings
- [dict gtm_setObjectAndKey:[NSColor colorWithCalibratedWhite:1.0 alpha:1.0]];
- [dict gtm_setObjectAndKey:[NSColor colorWithCalibratedWhite:1.0 alpha:0.0]];
- [dict gtm_setObjectAndKey:[NSColor colorWithCalibratedWhite:1.0 alpha:0.5]];
- [dict gtm_setObjectAndKey:[NSColor colorWithCalibratedRed:0.5 green:0.5
- blue:0.5 alpha:0.5]];
- [dict gtm_setObjectAndKey:[NSColor colorWithDeviceCyan:0.25 magenta:0.25
- yellow:0.25 black:0.25
- alpha:0.25]];
+ value = [NSColor colorWithCalibratedWhite:1.0 alpha:1.0];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSColor colorWithCalibratedWhite:1.0 alpha:0.0];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSColor colorWithCalibratedWhite:1.0 alpha:0.5];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSColor colorWithCalibratedRed:0.5 green:0.5 blue:0.5 alpha:0.5];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSColor colorWithDeviceCyan:0.25 magenta:0.25 yellow:0.25
+ black:0.25 alpha:0.25];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
} else if ([binding isEqualToString:NSFontBinding]) {
// This handles all font value bindings
- [dict gtm_setObjectAndKey:[NSFont boldSystemFontOfSize:[NSFont systemFontSize]]];
- [dict gtm_setObjectAndKey:[NSFont toolTipsFontOfSize:[NSFont smallSystemFontSize]]];
- [dict gtm_setObjectAndKey:[NSFont labelFontOfSize:144.0]];
+ value = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSFont toolTipsFontOfSize:[NSFont smallSystemFontSize]];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
+ value = [NSFont labelFontOfSize:144.0];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
} else if ([binding isEqualToString:NSRecentSearchesBinding] ||
[binding isEqualToString:NSSortDescriptorsBinding]) {
// This handles all array value bindings
- [dict gtm_setObjectAndKey:[NSArray array]];
+ value = [NSArray array];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
} else if ([binding isEqualToString:NSTargetBinding]) {
- [dict gtm_setObjectAndKey:[NSNull null]];
+ value = [NSNull null];
+ [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
} else {
_GTMDevLog(@"Skipped Binding: %@ for %@", binding, self); // COV_NF_LINE
}
- return dict;
+ return array;
}
- (BOOL)gtm_unitTestIsEqualTo:(id)value {
@@ -239,13 +350,6 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
@end
-@implementation NSMutableDictionary (GTMUnitTestingAdditions)
-// Sets an object and a key to the same value in a dictionary.
-- (void)gtm_setObjectAndKey:(id)objectAndKey {
- [self setObject:objectAndKey forKey:objectAndKey];
-}
-@end
-
#pragma mark -
#pragma mark All the special AppKit Bindings issues below
@@ -267,10 +371,17 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
@implementation NSScroller (GTMBindingUnitTestingAdditions)
- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
- // rdar://5849154 - NSScroller exposes binding with no value class for NSValueBinding
- [array addObject:NSValueBinding];
- // rdar://5849236 - NSScroller exposes binding for NSFontBinding
- [array addObject:NSFontBinding];
+ SInt32 major, minor, bugFix;
+ [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
+ if (major <= 10 && minor <= 5 && bugFix <= 5) {
+ // rdar://5849154 - NSScroller exposes binding with no value class for NSValueBinding
+ [array addObject:NSValueBinding];
+ }
+ if ([GTMSystemVersion isBuildLessThanOrEqualTo:kGTMSystemBuild10_6_0_WWDC]) {
+ // Broken on SnowLeopard WWDC and below
+ // rdar://5849236 - NSScroller exposes binding for NSFontBinding
+ [array addObject:NSFontBinding];
+ }
return array;
}
@end
@@ -289,13 +400,22 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
return array;
}
-- (NSMutableDictionary*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding {
- NSMutableDictionary *dict = [super gtm_unitTestExposedBindingsTestValues:binding];
+- (NSMutableArray *)gtm_unitTestExposedBindingsTestValues:(NSString*)binding {
+ NSMutableArray *array = [super gtm_unitTestExposedBindingsTestValues:binding];
if ([binding isEqualToString:NSAlignmentBinding]) {
- // rdar://5851487 - If NSAlignmentBinding for a NSTextField is set to -1 and then got it returns 7
- [dict setObject:[NSNumber numberWithInt:7] forKey:[NSNumber numberWithInt:-1]];
+ if ([GTMSystemVersion isBuildLessThanOrEqualTo:kGTMSystemBuild10_6_0_WWDC]) {
+ // rdar://5851487 - If NSAlignmentBinding for a NSTextField is set to -1 and then got it returns 7
+ GTMBindingUnitTestData *dataToRemove =
+ [GTMBindingUnitTestData testWithValue:[NSNumber numberWithInt:-1]
+ expecting:[NSNumber numberWithInt:NSNaturalTextAlignment]];
+ [array removeObject:dataToRemove];
+ GTMBindingUnitTestData *dataToAdd =
+ [GTMBindingUnitTestData testWithValue:[NSNumber numberWithInt:-1]
+ expecting:[NSNumber numberWithInt:7]];
+ [array addObject:dataToAdd];
+ }
}
- return dict;
+ return array;
}
@end
@@ -304,21 +424,15 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
@implementation NSSearchField (GTMBindingUnitTestingAdditions)
-- (NSMutableDictionary*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding {
- NSMutableDictionary *dict = [super gtm_unitTestExposedBindingsTestValues:binding];
-#if !__LP64__
- if ([binding isEqualToString:NSAlignmentBinding]) {
- // rdar://5851491 - Setting NSAlignmentBinding of search field to NSCenterTextAlignment broken
- // This appears to not be a bug in 64 bit. Strange.
- [dict setObject:[NSNumber numberWithInt:NSNaturalTextAlignment]
- forKey:[NSNumber numberWithInt:NSCenterTextAlignment]];
- }
-#endif
- return dict;
-}
-
- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
+ SInt32 major, minor, bugFix;
+ [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
+ if (major <= 10 && minor <= 5 && bugFix <= 5) {
+ // rdar://5851491 - Setting NSAlignmentBinding of search field to NSCenterTextAlignment broken
+ // Broken on 10.5.5 and below.
+ [array addObject:NSAlignmentBinding];
+ }
// Not KVC Compliant
[array addObject:NSPredicateBinding];
return array;
@@ -367,8 +481,11 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
- // rdar://5849684 - NSTableView should throw exception when attempting to set NSFontBinding
- [array addObject:NSFontBinding];
+ if ([GTMSystemVersion isBuildLessThanOrEqualTo:kGTMSystemBuild10_6_0_WWDC]) {
+ // rdar://6288332 - NSTableView does not respond to NSFontBinding
+ // Broken on 10.5, and SnowLeopard WWDC
+ [array addObject:NSFontBinding];
+ }
// Not KVC Compliant
[array addObject:NSContentBinding];
[array addObject:NSDoubleClickTargetBinding];
@@ -386,8 +503,10 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
- //rdar://5849335 - NSTextView only partially KVC compliant for key NSAttributedStringBinding
- [array addObject:NSAttributedStringBinding];
+ if ([GTMSystemVersion isBuildLessThanOrEqualTo:kGTMSystemBuild10_6_0_WWDC]) {
+ //rdar://5849335 - NSTextView only partially KVC compliant for key NSAttributedStringBinding
+ [array addObject:NSAttributedStringBinding];
+ }
// Not KVC Compliant
[array addObject:NSDataBinding];
[array addObject:NSValueURLBinding];
@@ -404,8 +523,10 @@ BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object,
- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
- // rdar://5849248 - NSTabView exposes binding with no value class for NSSelectedIdentifierBinding
- [array addObject:NSSelectedIdentifierBinding];
+ if ([GTMSystemVersion isBuildLessThanOrEqualTo:kGTMSystemBuild10_6_0_WWDC]) {
+ // rdar://5849248 - NSTabView exposes binding with no value class for NSSelectedIdentifierBinding
+ [array addObject:NSSelectedIdentifierBinding];
+ }
// Not KVC Compliant
[array addObject:NSSelectedIndexBinding];
[array addObject:NSSelectedLabelBinding];
diff --git a/UnitTesting/GTMNSObject+UnitTesting.m b/UnitTesting/GTMNSObject+UnitTesting.m
index a722b9e..bc94729 100644
--- a/UnitTesting/GTMNSObject+UnitTesting.m
+++ b/UnitTesting/GTMNSObject+UnitTesting.m
@@ -18,8 +18,6 @@
// the License.
//
-#import <mach-o/arch.h>
-
#import "GTMNSObject+UnitTesting.h"
#import "GTMSystemVersion.h"
#import "GTMGarbageCollection.h"
@@ -68,9 +66,7 @@ BOOL GTMIsObjectImageEqualToImageNamed(id object,
if (isGood) {
isGood = [object gtm_compareWithImageAt:aPath diffImage:&diff];
}
- if (isGood) {
- CGImageRelease(diff);
- } else {
+ if (!isGood) {
if (aPath) {
filename = [filename stringByAppendingString:@"_Failed"];
}
@@ -98,7 +94,6 @@ BOOL GTMIsObjectImageEqualToImageNamed(id object,
NSData *data = nil;
if (diff) {
data = [object gtm_imageDataForImage:diff];
- CFRelease(diff);
}
if ([data writeToFile:diffPath atomically:YES]) {
failString = [NSString stringWithFormat:@"Object image different "
@@ -114,6 +109,7 @@ BOOL GTMIsObjectImageEqualToImageNamed(id object,
}
}
}
+ CGImageRelease(diff);
} else {
failString = @"systemSettings not valid for taking image"; // COV_NF_LINE
}
@@ -225,7 +221,7 @@ BOOL GTMIsObjectStateEqualToStateNamed(id object,
@end
// Small utility function for checking to see if a is b +/- 1.
-static inline BOOL almostEqual(unsigned char a, unsigned char b) {
+GTM_INLINE BOOL almostEqual(unsigned char a, unsigned char b) {
unsigned char diff = a > b ? a - b : b - a;
BOOL notEqual = diff < 2;
return notEqual;
@@ -468,7 +464,7 @@ static NSString *gGTMUnitTestSaveToDirectory = nil;
_GTMDevAssert(myBundle, @"Couldn't find bundle for class: %@ searching for file:%@.%@",
NSStringFromClass(bundleClass), name, extension);
// System Version
- long major, minor, bugFix;
+ SInt32 major, minor, bugFix;
[GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
NSString *systemVersions[4];
systemVersions[0] = [NSString stringWithFormat:@".%d.%d.%d",
@@ -477,33 +473,8 @@ static NSString *gGTMUnitTestSaveToDirectory = nil;
systemVersions[2] = [NSString stringWithFormat:@".%d", major];
systemVersions[3] = @"";
NSString *extensions[2];
-#if GTM_IPHONE_SDK
- extensions[0] = @".iPhone";
-#else // !GTM_IPHONE_SDK
- // In reading arch(3) you'd thing this would work:
- //
- // const NXArchInfo *localInfo = NXGetLocalArchInfo();
- // _GTMDevAssert(localInfo && localInfo->name, @"Couldn't get NXArchInfo");
- // const NXArchInfo *genericInfo = NXGetArchInfoFromCpuType(localInfo->cputype, 0);
- // _GTMDevAssert(genericInfo && genericInfo->name, @"Couldn't get generic NXArchInfo");
- // extensions[0] = [NSString stringWithFormat:@".%s", genericInfo->name];
- //
- // but on 64bit it returns the same things as on 32bit, so...
-#if __POWERPC__
- #if __LP64__
- extensions[0] = @".ppc64";
- #else // !__LP64__
- extensions[0] = @".ppc";
- #endif // __LP64__
-#else // !__POWERPC__
- #if __LP64__
- extensions[0] = @".x86_64";
- #else // !__LP64__
- extensions[0] = @".i386";
- #endif // __LP64__
-#endif // !__POWERPC__
-
-#endif // GTM_IPHONE_SDK
+ extensions[0]
+ = [NSString stringWithFormat:@".%@", [GTMSystemVersion runtimeArchitecture]];
extensions[1] = @"";
size_t i, j;
@@ -529,38 +500,12 @@ static NSString *gGTMUnitTestSaveToDirectory = nil;
- (NSString *)gtm_saveToPathForFileNamed:(NSString*)name
extension:(NSString*)extension {
- char const *systemArchitecture;
-#if GTM_IPHONE_SDK
- systemArchitecture = "iPhone";
-#else
- // In reading arch(3) you'd thing this would work:
- //
- // const NXArchInfo *localInfo = NXGetLocalArchInfo();
- // _GTMDevAssert(localInfo && localInfo->name, @"Couldn't get NXArchInfo");
- // const NXArchInfo *genericInfo = NXGetArchInfoFromCpuType(localInfo->cputype, 0);
- // _GTMDevAssert(genericInfo && genericInfo->name, @"Couldn't get generic NXArchInfo");
- // system = genericInfo->name;
- //
- // but on 64bit it returns the same things as on 32bit, so...
-#if __POWERPC__
- #if __LP64__
- systemArchitecture = "ppc64";
- #else // !__LP64__
- systemArchitecture = "ppc";
- #endif // __LP64__
-#else // !__POWERPC__
- #if __LP64__
- systemArchitecture = "x86_64";
- #else // !__LP64__
- systemArchitecture = "i386";
- #endif // __LP64__
-#endif // !__POWERPC__
+ NSString *systemArchitecture = [GTMSystemVersion runtimeArchitecture];
-#endif
- long major, minor, bugFix;
+ SInt32 major, minor, bugFix;
[GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
- NSString *fullName = [NSString stringWithFormat:@"%@.%s.%d.%d.%d",
+ NSString *fullName = [NSString stringWithFormat:@"%@.%@.%d.%d.%d",
name, systemArchitecture, major, minor, bugFix];
NSString *basePath = [[self class] gtm_getUnitTestSaveToDirectory];
@@ -869,17 +814,14 @@ static NSString *gGTMUnitTestSaveToDirectory = nil;
*diff = CGBitmapContextCreateImage(diffContext);
free(diffData);
CFRelease(diffContext);
- free(fileData);
- CFRelease(fileContext);
- free(imageData);
- CFRelease(imageContext);
- } else {
- CFRelease(fileContext);
- CFRelease(imageContext);
- }
- CFRelease(imageRep);
- CFRelease(fileRep);
+ }
+ free(fileData);
+ CFRelease(fileContext);
+ free(imageData);
+ CFRelease(imageContext);
}
+ CGImageRelease(imageRep);
+ CGImageRelease(fileRep);
return answer;
}
diff --git a/UnitTesting/GTMSenTestCase.h b/UnitTesting/GTMSenTestCase.h
index 4a2bc9f..99f520a 100644
--- a/UnitTesting/GTMSenTestCase.h
+++ b/UnitTesting/GTMSenTestCase.h
@@ -112,7 +112,7 @@ do { \
} \
}\
@catch (id anException) {\
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == noErr fails", #a1] \
+ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s) fails", #a1, #a2] \
exception:anException \
inFile:[NSString stringWithUTF8String:__FILE__] \
atLine:__LINE__ \
@@ -990,7 +990,10 @@ do { \
- (void)failWithException:(NSException*)exception;
@end
-CF_EXPORT NSString * const SenTestFailureException;
+extern NSString *const SenTestFailureException;
+
+extern NSString *const SenTestFilenameKey;
+extern NSString *const SenTestLineNumberKey;
#endif // GTM_IPHONE_SDK
diff --git a/UnitTesting/GTMSenTestCase.m b/UnitTesting/GTMSenTestCase.m
index 856516c..8d45dab 100644
--- a/UnitTesting/GTMSenTestCase.m
+++ b/UnitTesting/GTMSenTestCase.m
@@ -6,9 +6,9 @@
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
-//
+//
// http://www.apache.org/licenses/LICENSE-2.0
-//
+//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -17,38 +17,76 @@
//
#import "GTMSenTestCase.h"
+#import <unistd.h>
-#if GTM_IPHONE_SDK
+#if !GTM_IPHONE_SDK
+#import "GTMGarbageCollection.h"
+#endif // !GTM_IPHONE_SDK
+#if GTM_IPHONE_SDK
#import <stdarg.h>
+@interface NSException (GTMSenTestPrivateAdditions)
++ (NSException *)failureInFile:(NSString *)filename
+ atLine:(int)lineNumber
+ reason:(NSString *)reason;
+@end
+
+@implementation NSException (GTMSenTestPrivateAdditions)
++ (NSException *)failureInFile:(NSString *)filename
+ atLine:(int)lineNumber
+ reason:(NSString *)reason {
+ NSDictionary *userInfo =
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInteger:lineNumber], SenTestLineNumberKey,
+ filename, SenTestFilenameKey,
+ nil];
+
+ return [self exceptionWithName:SenTestFailureException
+ reason:reason
+ userInfo:userInfo];
+}
+@end
+
@implementation NSException (GTMSenTestAdditions)
-+ (NSException *)failureInFile:(NSString *)filename
- atLine:(int)lineNumber
++ (NSException *)failureInFile:(NSString *)filename
+ atLine:(int)lineNumber
withDescription:(NSString *)formatString, ... {
- va_list vl;
- va_start(vl, formatString);
- NSString *reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- reason = [NSString stringWithFormat:@"%@:%d: error: %@", filename, lineNumber, reason];
- return [NSException exceptionWithName:SenTestFailureException
- reason:reason
- userInfo:nil];
-}
-
-+ (NSException *)failureInCondition:(NSString *)condition
- isTrue:(BOOL)isTrue
- inFile:(NSString *)filename
- atLine:(int)lineNumber
+
+ NSString *testDescription = @"";
+ if (formatString) {
+ va_list vl;
+ va_start(vl, formatString);
+ testDescription =
+ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
+ va_end(vl);
+ }
+
+ NSString *reason = testDescription;
+
+ return [self failureInFile:filename atLine:lineNumber reason:reason];
+}
+
++ (NSException *)failureInCondition:(NSString *)condition
+ isTrue:(BOOL)isTrue
+ inFile:(NSString *)filename
+ atLine:(int)lineNumber
withDescription:(NSString *)formatString, ... {
- va_list vl;
- va_start(vl, formatString);
- NSString *reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- reason = [NSString stringWithFormat:@"condition '%@' is %s : %@",
- condition, isTrue ? "TRUE" : "FALSE", reason];
- return [self failureInFile:filename atLine:lineNumber withDescription:reason];
+
+ NSString *testDescription = @"";
+ if (formatString) {
+ va_list vl;
+ va_start(vl, formatString);
+ testDescription =
+ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
+ va_end(vl);
+ }
+
+ NSString *reason = [NSString stringWithFormat:@"'%@' should be %s. %@",
+ condition, isTrue ? "TRUE" : "FALSE", testDescription];
+
+ return [self failureInFile:filename atLine:lineNumber reason:reason];
}
+ (NSException *)failureInEqualityBetweenObject:(id)left
@@ -56,55 +94,99 @@
inFile:(NSString *)filename
atLine:(int)lineNumber
withDescription:(NSString *)formatString, ... {
- va_list vl;
- va_start(vl, formatString);
- NSString *reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- reason = [NSString stringWithFormat:@"%@ != %@ : %@",
- left, right, reason];
- return [self failureInFile:filename atLine:lineNumber withDescription:reason];
-}
-
-+ (NSException *)failureInEqualityBetweenValue:(NSValue *)left
- andValue:(NSValue *)right
- withAccuracy:(NSValue *)accuracy
- inFile:(NSString *)filename
+
+ NSString *testDescription = @"";
+ if (formatString) {
+ va_list vl;
+ va_start(vl, formatString);
+ testDescription =
+ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
+ va_end(vl);
+ }
+
+ NSString *reason =
+ [NSString stringWithFormat:@"'%@' should be equal to '%@'. %@",
+ [left description], [right description], testDescription];
+
+ return [self failureInFile:filename atLine:lineNumber reason:reason];
+}
+
++ (NSException *)failureInEqualityBetweenValue:(NSValue *)left
+ andValue:(NSValue *)right
+ withAccuracy:(NSValue *)accuracy
+ inFile:(NSString *)filename
atLine:(int)lineNumber
withDescription:(NSString *)formatString, ... {
- va_list vl;
- va_start(vl, formatString);
- NSString *reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- reason = [NSString stringWithFormat:@"%@ != %@ with accuracy %@ : %@",
- left, right, accuracy, reason];
- return [self failureInFile:filename atLine:lineNumber withDescription:reason];
+
+ NSString *testDescription = @"";
+ if (formatString) {
+ va_list vl;
+ va_start(vl, formatString);
+ testDescription =
+ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
+ va_end(vl);
+ }
+
+ NSString *reason;
+ if (accuracy) {
+ reason =
+ [NSString stringWithFormat:@"'%@' should be equal to '%@'. %@",
+ left, right, testDescription];
+ } else {
+ reason =
+ [NSString stringWithFormat:@"'%@' should be equal to '%@' +/-'%@'. %@",
+ left, right, accuracy, testDescription];
+ }
+
+ return [self failureInFile:filename atLine:lineNumber reason:reason];
}
-+ (NSException *)failureInRaise:(NSString *)expression
- inFile:(NSString *)filename
++ (NSException *)failureInRaise:(NSString *)expression
+ inFile:(NSString *)filename
atLine:(int)lineNumber
withDescription:(NSString *)formatString, ... {
- va_list vl;
- va_start(vl, formatString);
- NSString *reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- reason = [NSString stringWithFormat:@"failure in raise %@ : %@",
- expression, reason];
- return [self failureInFile:filename atLine:lineNumber withDescription:reason];
-}
-
-+ (NSException *)failureInRaise:(NSString *)expression
- exception:(NSException *)exception
- inFile:(NSString *)filename
- atLine:(int)lineNumber
+
+ NSString *testDescription = @"";
+ if (formatString) {
+ va_list vl;
+ va_start(vl, formatString);
+ testDescription =
+ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
+ va_end(vl);
+ }
+
+ NSString *reason = [NSString stringWithFormat:@"'%@' should raise. %@",
+ expression, testDescription];
+
+ return [self failureInFile:filename atLine:lineNumber reason:reason];
+}
+
++ (NSException *)failureInRaise:(NSString *)expression
+ exception:(NSException *)exception
+ inFile:(NSString *)filename
+ atLine:(int)lineNumber
withDescription:(NSString *)formatString, ... {
- va_list vl;
- va_start(vl, formatString);
- NSString *reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- reason = [NSString stringWithFormat:@"failure in raise %@ (%@) : %@",
- expression, exception, reason];
- return [self failureInFile:filename atLine:lineNumber withDescription:reason];
+
+ NSString *testDescription = @"";
+ if (formatString) {
+ va_list vl;
+ va_start(vl, formatString);
+ testDescription =
+ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
+ va_end(vl);
+ }
+
+ NSString *reason;
+ if ([[exception name] isEqualToString:SenTestFailureException]) {
+ // it's our exception, assume it has the right description on it.
+ reason = [exception reason];
+ } else {
+ // not one of our exception, use the exceptions reason and our description
+ reason = [NSString stringWithFormat:@"'%@' raised '%@'. %@",
+ expression, [exception reason], testDescription];
+ }
+
+ return [self failureInFile:filename atLine:lineNumber reason:reason];
}
@end
@@ -114,17 +196,20 @@ NSString *STComposeString(NSString *formatString, ...) {
if (formatString) {
va_list vl;
va_start(vl, formatString);
- reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
+ reason =
+ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
va_end(vl);
}
return reason;
}
-NSString * const SenTestFailureException = @"SenTestFailureException";
+NSString *const SenTestFailureException = @"SenTestFailureException";
+NSString *const SenTestFilenameKey = @"SenTestFilenameKey";
+NSString *const SenTestLineNumberKey = @"SenTestLineNumberKey";
-@interface SenTestCase (SenTestCasePrivate)
+@interface SenTestCase (SenTestCasePrivate)
// our method of logging errors
-- (void)printError:(NSString *)error;
++ (void)printException:(NSException *)exception fromTestName:(NSString *)name;
@end
@implementation SenTestCase
@@ -140,17 +225,26 @@ NSString * const SenTestFailureException = @"SenTestFailureException";
@try {
[self invokeTest];
} @catch (NSException *exception) {
- [self printError:[exception reason]];
+ [[self class] printException:exception
+ fromTestName:NSStringFromSelector(sel)];
[exception raise];
}
}
-- (void)printError:(NSString *)error {
- if ([error rangeOfString:@"error:"].location == NSNotFound) {
- fprintf(stderr, "error: %s\n", [error UTF8String]);
- } else {
- fprintf(stderr, "%s\n", [error UTF8String]);
++ (void)printException:(NSException *)exception fromTestName:(NSString *)name {
+ NSDictionary *userInfo = [exception userInfo];
+ NSString *filename = [userInfo objectForKey:SenTestFilenameKey];
+ NSNumber *lineNumber = [userInfo objectForKey:SenTestLineNumberKey];
+ NSString *className = NSStringFromClass([self class]);
+ if ([filename length] == 0) {
+ filename = @"Unknown.m";
}
+ fprintf(stderr, "%s:%ld: error: -[%s %s] : %s\n",
+ [filename UTF8String],
+ (long)[lineNumber integerValue],
+ [className UTF8String],
+ [name UTF8String],
+ [[exception reason] UTF8String]);
fflush(stderr);
}
@@ -189,7 +283,7 @@ NSString * const SenTestFailureException = @"SenTestFailureException";
}
@end
-#endif // GTM_IPHONE_SDK
+#endif // GTM_IPHONE_SDK
@implementation GTMTestCase : SenTestCase
- (void)invokeTest {
@@ -197,7 +291,7 @@ NSString * const SenTestFailureException = @"SenTestFailureException";
if (devLogClass) {
[devLogClass performSelector:@selector(enableTracking)];
[devLogClass performSelector:@selector(verifyNoMoreLogsExpected)];
-
+
}
[super invokeTest];
if (devLogClass) {
@@ -206,3 +300,57 @@ NSString * const SenTestFailureException = @"SenTestFailureException";
}
}
@end
+
+// Leak detection
+#if !GTM_IPHONE_DEVICE
+// Don't want to get leaks on the iPhone Device as the device doesn't
+// have 'leaks'. The simulator does though.
+
+static void _GTMRunLeaks(void) {
+ // This is an atexit handler. It runs leaks for us to check if we are
+ // leaking anything in our tests.
+ const char* cExclusionsEnv = getenv("GTM_LEAKS_SYMBOLS_TO_IGNORE");
+ NSMutableString *exclusions = [NSMutableString string];
+ if (cExclusionsEnv) {
+ NSString *exclusionsEnv = [NSString stringWithUTF8String:cExclusionsEnv];
+ NSArray *exclusionsArray = [exclusionsEnv componentsSeparatedByString:@","];
+ NSEnumerator *exclusionsEnum = [exclusionsArray objectEnumerator];
+ NSString *exclusion;
+ NSCharacterSet *wcSet = [NSCharacterSet whitespaceCharacterSet];
+ while ((exclusion = [exclusionsEnum nextObject])) {
+ exclusion = [exclusion stringByTrimmingCharactersInSet:wcSet];
+ [exclusions appendFormat:@"-exclude \"%@\" ", exclusion];
+ }
+ }
+ NSString *string
+ = [NSString stringWithFormat:@"/usr/bin/leaks %@%d"
+ @"| /usr/bin/sed -e 's/Leak: /Leaks:0: warning: Leak /'",
+ exclusions, getpid()];
+ int ret = system([string UTF8String]);
+ if (ret) {
+ fprintf(stderr, "%s:%d: Error: Unable to run leaks. 'system' returned: %d",
+ __FILE__, __LINE__, ret);
+ fflush(stderr);
+ }
+}
+
+static __attribute__((constructor)) void _GTMInstallLeaks(void) {
+ BOOL checkLeaks = YES;
+#if !GTM_IPHONE_SDK
+ checkLeaks = GTMIsGarbageCollectionEnabled() ? NO : YES;
+#endif // !GTM_IPHONE_SDK
+ if (checkLeaks) {
+ checkLeaks = getenv("GTM_ENABLE_LEAKS") ? YES : NO;
+ if (checkLeaks) {
+ if (checkLeaks) {
+ fprintf(stderr, "Leak Checking Enabled\n");
+ fflush(stderr);
+ _GTMDevAssert(atexit(&_GTMRunLeaks) == 0,
+ @"Unable to install _GTMRunLeaks as an atexit handler (%d)",
+ errno);
+ }
+ }
+ }
+}
+
+#endif // !GTM_IPHONE_DEVICE
diff --git a/UnitTesting/GTMTestTimer.h b/UnitTesting/GTMTestTimer.h
index 200f9b1..6c5fc55 100644
--- a/UnitTesting/GTMTestTimer.h
+++ b/UnitTesting/GTMTestTimer.h
@@ -37,7 +37,7 @@ typedef struct {
} GTMTestTimer;
// Create a test timer
-FOUNDATION_STATIC_INLINE GTMTestTimer *GTMTestTimerCreate(void) {
+GTM_INLINE GTMTestTimer *GTMTestTimerCreate(void) {
GTMTestTimer *t = calloc(sizeof(GTMTestTimer), 1);
if (t) {
if (mach_timebase_info(&t->time_base_info_) == KERN_SUCCESS) {
@@ -53,12 +53,12 @@ FOUNDATION_STATIC_INLINE GTMTestTimer *GTMTestTimerCreate(void) {
}
// Retain a timer
-FOUNDATION_STATIC_INLINE void GTMTestTimerRetain(GTMTestTimer *t) {
+GTM_INLINE void GTMTestTimerRetain(GTMTestTimer *t) {
t->retainCount_ += 1;
}
// Release a timer. When release count hits zero, we free it.
-FOUNDATION_STATIC_INLINE void GTMTestTimerRelease(GTMTestTimer *t) {
+GTM_INLINE void GTMTestTimerRelease(GTMTestTimer *t) {
t->retainCount_ -= 1;
if (t->retainCount_ == 0) {
free(t);
@@ -67,13 +67,13 @@ FOUNDATION_STATIC_INLINE void GTMTestTimerRelease(GTMTestTimer *t) {
// Starts a timer timing. Specifically starts a new split. If the timer is
// currently running, it resets the start time of the current split.
-FOUNDATION_STATIC_INLINE void GTMTestTimerStart(GTMTestTimer *t) {
+GTM_INLINE void GTMTestTimerStart(GTMTestTimer *t) {
t->start_ = mach_absolute_time();
t->running_ = true;
}
// Stops a timer and returns split time (time from last start) in nanoseconds.
-FOUNDATION_STATIC_INLINE uint64_t GTMTestTimerStop(GTMTestTimer *t) {
+GTM_INLINE uint64_t GTMTestTimerStop(GTMTestTimer *t) {
uint64_t now = mach_absolute_time();
t->running_ = false;
++t->iterations_;
@@ -85,7 +85,7 @@ FOUNDATION_STATIC_INLINE uint64_t GTMTestTimerStop(GTMTestTimer *t) {
// returns the current timer elapsed time (combined value of all splits, plus
// current split if the timer is running) in nanoseconds.
-FOUNDATION_STATIC_INLINE double GTMTestTimerGetNanoseconds(GTMTestTimer *t) {
+GTM_INLINE double GTMTestTimerGetNanoseconds(GTMTestTimer *t) {
uint64_t total = t->elapsed_;
if (t->running_) {
total += mach_absolute_time() - t->start_;
@@ -96,30 +96,30 @@ FOUNDATION_STATIC_INLINE double GTMTestTimerGetNanoseconds(GTMTestTimer *t) {
// Returns the current timer elapsed time (combined value of all splits, plus
// current split if the timer is running) in seconds.
-FOUNDATION_STATIC_INLINE double GTMTestTimerGetSeconds(GTMTestTimer *t) {
+GTM_INLINE double GTMTestTimerGetSeconds(GTMTestTimer *t) {
return GTMTestTimerGetNanoseconds(t) * 0.000000001;
}
// Returns the current timer elapsed time (combined value of all splits, plus
// current split if the timer is running) in milliseconds.
-FOUNDATION_STATIC_INLINE double GTMTestTimerGetMilliseconds(GTMTestTimer *t) {
+GTM_INLINE double GTMTestTimerGetMilliseconds(GTMTestTimer *t) {
return GTMTestTimerGetNanoseconds(t) * 0.000001;
}
// Returns the current timer elapsed time (combined value of all splits, plus
// current split if the timer is running) in microseconds.
-FOUNDATION_STATIC_INLINE double GTMTestTimerGetMicroseconds(GTMTestTimer *t) {
+GTM_INLINE double GTMTestTimerGetMicroseconds(GTMTestTimer *t) {
return GTMTestTimerGetNanoseconds(t) * 0.001;
}
// Returns the number of splits (start-stop) cycles recorded.
// GTMTestTimerGetSeconds()/GTMTestTimerGetIterations() gives you an average
// of all your splits.
-FOUNDATION_STATIC_INLINE NSUInteger GTMTestTimerGetIterations(GTMTestTimer *t) {
+GTM_INLINE NSUInteger GTMTestTimerGetIterations(GTMTestTimer *t) {
return t->iterations_;
}
// Returns true if the timer is running.
-FOUNDATION_STATIC_INLINE bool GTMTestTimerIsRunning(GTMTestTimer *t) {
+GTM_INLINE bool GTMTestTimerIsRunning(GTMTestTimer *t) {
return t->running_;
}
diff --git a/UnitTesting/GTMUnitTestingBindingTest.m b/UnitTesting/GTMUnitTestingBindingTest.m
index 78e48b1..aabac43 100644
--- a/UnitTesting/GTMUnitTestingBindingTest.m
+++ b/UnitTesting/GTMUnitTestingBindingTest.m
@@ -91,11 +91,10 @@ NSString *const kGTMKeyThatIsntEqual = @"keyThatIsntEqual";
nil];
}
-- (NSMutableDictionary*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding {
-
- NSMutableDictionary *dict = [NSMutableDictionary dictionary];
- [dict setObject:kGTMKeyThatIsntEqual forKey:kGTMKeyThatIsntEqual];
- return dict;
+- (NSArray*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding {
+ GTMBindingUnitTestData *data
+ = [GTMBindingUnitTestData testWithIdentityValue:kGTMKeyThatIsntEqual];
+ return [NSArray arrayWithObject:data];
}
- (Class)valueClassForBinding:(NSString*)binding {
diff --git a/UnitTesting/GTMUnitTestingUtilities.m b/UnitTesting/GTMUnitTestingUtilities.m
index a20023f..39534f7 100644
--- a/UnitTesting/GTMUnitTestingUtilities.m
+++ b/UnitTesting/GTMUnitTestingUtilities.m
@@ -112,6 +112,7 @@ static void RestoreColorProfile(void) {
if (gCurrentColorProfile) {
CGDirectDisplayID displayID = CGMainDisplayID();
CMError error = CMSetProfileByAVID((UInt32)displayID, gCurrentColorProfile);
+ CMCloseProfile(gCurrentColorProfile);
if (error) {
// COV_NF_START
// No way to force this case in a unittest.
@@ -143,6 +144,7 @@ void SetColorProfileToGenericRGB(void) {
// COV_NF_END
}
if (AreCMProfilesEqual(genericProfile, previousProfile)) {
+ CMCloseProfile(previousProfile);
return;
}
CFStringRef previousProfileName;
diff --git a/UnitTesting/RunIPhoneUnitTest.sh b/UnitTesting/RunIPhoneUnitTest.sh
index 1718bda..0b6fe69 100755
--- a/UnitTesting/RunIPhoneUnitTest.sh
+++ b/UnitTesting/RunIPhoneUnitTest.sh
@@ -16,20 +16,28 @@
#
# Runs all unittests through the iPhone simulator. We don't handle running them
# on the device. To run on the device just choose "run".
-
# Controlling environment variables:
#
# GTM_DISABLE_ZOMBIES -
-# Set to a non-zero value to turn off zombie checks that can interfere with
-# leak checking.
+# Set to a non-zero value to turn on zombie checks. You will probably
+# want to turn this off if you enable leaks.
#
-# GTM_DISABLE_LEAKS -
-# Set to a non-zero value to turn off the leaks check.
+# GTM_ENABLE_LEAKS -
+# Set to a non-zero value to turn on the leaks check. You will probably want
+# to disable zombies, otherwise you will get a lot of false positives.
#
# GTM_DISABLE_TERMINATION
# Set to a non-zero value so that the app doesn't terminate when it's finished
# running tests. This is useful when using it with external tools such
# as Instruments.
+#
+# GTM_LEAKS_SYMBOLS_TO_IGNORE
+# List of comma separated symbols that leaks should ignore. Mainly to control
+# leaks in frameworks you don't have control over.
+# Search this file for GTM_LEAKS_SYMBOLS_TO_IGNORE to see examples.
+# Please feel free to add other symbols as you find them but make sure to
+# reference Radars or other bug systems so we can track them.
+#
ScriptDir=$(dirname $(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,"))
ScriptName=$(basename "$0")
@@ -39,7 +47,7 @@ GTMXcodeNote() {
echo ${ThisScript}:${1}: note: GTM ${2}
}
-if [ "$IPHONEOS_DEPLOYMENT_TARGET" == "" ]; then
+if [ "$PLATFORM_NAME" == "iphonesimulator" ]; then
# We kill the iPhone simulator because otherwise we run into issues where
# the unittests fail becuase the simulator is currently running, and
# at this time the iPhone SDK won't allow two simulators running at the same
@@ -49,7 +57,7 @@ if [ "$IPHONEOS_DEPLOYMENT_TARGET" == "" ]; then
export DYLD_ROOT_PATH="$SDKROOT"
export DYLD_FRAMEWORK_PATH="$CONFIGURATION_BUILD_DIR"
export IPHONE_SIMULATOR_ROOT="$SDKROOT"
- export CFFIXED_USER_HOME="$USER_LIBRARY_DIR/Application Support/iPhone Simulator/User"
+ export CFFIXED_USER_HOME="$TEMP_FILES_DIR/iPhone Simulator User Dir"
# See http://developer.apple.com/technotes/tn2004/tn2124.html for an
# explanation of these environment variables.
@@ -60,13 +68,17 @@ if [ "$IPHONEOS_DEPLOYMENT_TARGET" == "" ]; then
export MallocStackLogging=YES
export NSAutoreleaseFreedObjectCheckEnabled=YES
export OBJC_DEBUG_FRAGILE_SUPERCLASSES=YES
-
+
if [ ! $GTM_DISABLE_ZOMBIES ]; then
GTMXcodeNote ${LINENO} "Enabling zombies"
export CFZombieLevel=3
export NSZombieEnabled=YES
fi
+ # 6251475 iPhone simulator leaks @ CFHTTPCookieStore shutdown if
+ # CFFIXED_USER_HOME empty
+ GTM_LEAKS_SYMBOLS_TO_IGNORE="CFHTTPCookieStore"
+
"$TARGET_BUILD_DIR/$EXECUTABLE_PATH" -RegisterForSystemEvents
else
GTMXcodeNote ${LINENO} "Skipping running of unittests for device build."
diff --git a/UnitTesting/RunMacOSUnitTests.sh b/UnitTesting/RunMacOSUnitTests.sh
index 5c36a79..f35092b 100755
--- a/UnitTesting/RunMacOSUnitTests.sh
+++ b/UnitTesting/RunMacOSUnitTests.sh
@@ -21,37 +21,172 @@
# Controlling environment variables:
#
-# GTM_NO_MEMORY_STRESS -
-# Set to zero to prevent the setting of system library/framework debugging
-# environment variables that help find problems in code. See
-# http://developer.apple.com/technotes/tn2004/tn2124.html
-# for details.
+# GTM_DISABLE_ZOMBIES -
+# Set to a non-zero value to turn on zombie checks. You will probably
+# want to turn this off if you enable leaks.
+#
+# GTM_ENABLE_LEAKS -
+# Set to a non-zero value to turn on the leaks check. You will probably want
+# to disable zombies, otherwise you will get a lot of false positives.
+#
# GTM_NO_DEBUG_FRAMEWORKS -
# Set to zero to prevent the use of the debug versions of system
-# libraries/frameworks if you have them installed on your system. The frameworks
-# can be found at http://connect.apple.com > Downloads > Developer Tools
+# libraries/frameworks if you have them installed on your system. The
+# frameworks can be found at
+# http://connect.apple.com > Downloads > Developer Tools
# (https://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?bundleID=19915)
+#
+# GTM_LEAKS_SYMBOLS_TO_IGNORE
+# List of comma separated symbols that leaks should ignore. Mainly to control
+# leaks in frameworks you don't have control over.
+# Search this file for GTM_LEAKS_SYMBOLS_TO_IGNORE to see examples.
+# Please feel free to add other symbols as you find them but make sure to
+# reference Radars or other bug systems so we can track them.
+#
ScriptDir=$(dirname $(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,"))
ScriptName=$(basename "$0")
ThisScript="${ScriptDir}/${ScriptName}"
GTMXcodeNote() {
- echo ${ThisScript}:${1}: note: GTM ${2}
+ echo ${ThisScript}:${1}: note: GTM ${2}
+}
+
+# The workaround below is due to
+# Radar 6248062 otest won't run with MallocHistory enabled under rosetta
+# Basically we go through and check what architecture we are running on
+# and which architectures we can support
+AppendToSymbolsLeaksShouldIgnore() {
+ if [ "${GTM_LEAKS_SYMBOLS_TO_IGNORE}" = "" ]; then
+ GTM_LEAKS_SYMBOLS_TO_IGNORE="${1}"
+ else
+ GTM_LEAKS_SYMBOLS_TO_IGNORE="${GTM_LEAKS_SYMBOLS_TO_IGNORE}, ${1}"
+ fi
+}
+
+AppendToLeakTestArchs() {
+ if [ "${LEAK_TEST_ARCHS}" = "" ]; then
+ LEAK_TEST_ARCHS="${1}"
+ else
+ LEAK_TEST_ARCHS="${LEAK_TEST_ARCHS} ${1}"
+ fi
+}
+
+AppendToNoLeakTestArchs() {
+ if [ "${NO_LEAK_TEST_ARCHS}" = "" ]; then
+ NO_LEAK_TEST_ARCHS="${1}"
+ else
+ NO_LEAK_TEST_ARCHS="${NO_LEAK_TEST_ARCHS} ${1}"
+ fi
+}
+
+UpdateArchitecturesToTest() {
+ case "${NATIVE_ARCH_ACTUAL}" in
+ ppc)
+ if [ "${1}" = "ppc" ]; then
+ AppendToLeakTestArchs "${1}"
+ fi
+ ;;
+
+ ppc64)
+ if [ "${1}" = "ppc" -o "${1}" = "ppc64" ]; then
+ AppendToLeakTestArchs "${1}"
+ fi
+ ;;
+
+ i386)
+ if [ "${1}" = "i386" ]; then
+ AppendToLeakTestArchs "${1}"
+ elif [ "${1}" = "ppc" ]; then
+ AppendToNoLeakTestArchs "${1}"
+ fi
+ ;;
+
+ x86_64)
+ if [ "${1}" = "i386" -o "${1}" = "x86_64" ]; then
+ AppendToLeakTestArchs "${1}"
+ elif [ "${1}" = "ppc" -o "${1}" = "ppc64" ]; then
+ AppendToNoLeakTestArchs "${1}"
+ fi
+ ;;
+
+ *)
+ echo "RunMacOSUnitTests.sh Unknown native architecture: ${NATIVE_ARCH_ACTUAL}"
+ exit 1
+ ;;
+ esac
+}
+
+RunTests() {
+ if [ "${CURRENT_ARCH}" = "" ]; then
+ CURRENT_ARCH=`arch`
+ fi
+
+ if [ "${ONLY_ACTIVE_ARCH}" = "YES" ]; then
+ ARCHS="${CURRENT_ARCH}"
+ fi
+
+ if [ "${ARCHS}" = "" ]; then
+ ARCHS=`arch`
+ fi
+
+ if [ "${VALID_ARCHS}" = "" ]; then
+ VALID_ARCHS=`arch`
+ fi
+
+ if [ "${NATIVE_ARCH_ACTUAL}" = "" ]; then
+ NATIVE_ARCH_ACTUAL=`arch`
+ fi
+
+ LEAK_TEST_ARCHS=""
+ NO_LEAK_TEST_ARCHS=""
+
+ for TEST_ARCH in ${ARCHS}; do
+ for TEST_VALID_ARCH in ${VALID_ARCHS}; do
+ if [ "${TEST_VALID_ARCH}" = "${TEST_ARCH}" ]; then
+ UpdateArchitecturesToTest "${TEST_ARCH}"
+ fi
+ done
+ done
+
+ # These are symbols that leak on OS 10.5.5
+ # radar 6247293 NSCollatorElement leaks in +initialize.
+ AppendToSymbolsLeaksShouldIgnore "+[NSCollatorElement initialize]"
+ # radar 6247911 The first call to udat_open leaks only on x86_64
+ AppendToSymbolsLeaksShouldIgnore "icu::TimeZone::initDefault()"
+ # radar 6263983 +[IMService allServices] leaks
+ AppendToSymbolsLeaksShouldIgnore "-[IMServiceAgentImpl allServices]"
+ # radar 6264034 +[IKSFEffectDescription initialize] Leaks
+ AppendToSymbolsLeaksShouldIgnore "+[IKSFEffectDescription initialize]"
+
+ # Running leaks on architectures that support leaks.
+ export GTM_LEAKS_SYMBOLS_TO_IGNORE="${GTM_LEAKS_SYMBOLS_TO_IGNORE}"
+ ARCHS="${LEAK_TEST_ARCHS}"
+ VALID_ARCHS="${LEAK_TEST_ARCHS}"
+ "${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests"
+
+ # Running leaks on architectures that don't support leaks.
+ unset MallocStackLogging
+ unset GTM_ENABLE_LEAKS
+ ARCHS="${NO_LEAK_TEST_ARCHS}"
+ VALID_ARCHS="${NO_LEAK_TEST_ARCHS}"
+ "${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests"
}
# Jack up some memory stress so we can catch more bugs.
-if [ ! $GTM_NO_MEMORY_STRESS ]; then
- GTMXcodeNote ${LINENO} "Enabling memory stressing"
- export MallocScribble=YES
- export MallocPreScribble=YES
- export MallocGuardEdges=YES
+export MallocScribble=YES
+export MallocPreScribble=YES
+export MallocGuardEdges=YES
+export MallocStackLogging=YES
+export NSAutoreleaseFreedObjectCheckEnabled=YES
+export OBJC_DEBUG_FRAGILE_SUPERCLASSES=YES
+
+if [ ! $GTM_DISABLE_ZOMBIES ]; then
+ GTMXcodeNote ${LINENO} "Enabling zombies"
# CFZombieLevel disabled because it doesn't play well with the
# security framework
# export CFZombieLevel=3
- export NSAutoreleaseFreedObjectCheckEnabled=YES
export NSZombieEnabled=YES
- export OBJC_DEBUG_FRAGILE_SUPERCLASSES=YES
fi
# If we have debug libraries on the machine, we'll use them
@@ -63,4 +198,10 @@ if [ ! $GTM_NO_DEBUG_FRAMEWORKS ]; then
fi
fi
-"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests"
+# If leaks testing is enabled, we have to go through our convoluted path
+# to handle architectures that don't allow us to do leak testing.
+if [ GTM_ENABLE_LEAKS ]; then
+ RunTests
+else
+ "${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests"
+fi
diff --git a/UnitTesting/TestData/GTMUnitTestingImage.10.6.0.tiff b/UnitTesting/TestData/GTMUnitTestingImage.10.6.0.tiff
new file mode 100644
index 0000000..2bbdb9c
--- /dev/null
+++ b/UnitTesting/TestData/GTMUnitTestingImage.10.6.0.tiff
Binary files differ
diff --git a/UnitTesting/TestData/GTMUnitTestingWindow.10.6.0.tiff b/UnitTesting/TestData/GTMUnitTestingWindow.10.6.0.tiff
new file mode 100644
index 0000000..60c362a
--- /dev/null
+++ b/UnitTesting/TestData/GTMUnitTestingWindow.10.6.0.tiff
Binary files differ