aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-10-22 19:16:19 +0000
committerGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-10-22 19:16:19 +0000
commit11938e47355bfbf3b81f1ff5b15f1222b83d4f47 (patch)
tree3794c78559472e4b2efe5eabc0e094d7c14a9743
parent90eba8f973c0b77f36dc7084163ff0d43675a1a8 (diff)
- GTM_INLINE will make sure a function gets inlined, and provides a consistent
way for all GTM code to do it. - Added GTMDebugThreadValidation to allow you to enforce the fact that your code must run in the main thread in DEBUG builds. - Updated some internals of the iPhone unittesting so it doesn't double print the test descriptions, file names, or lines numbers of a test failure line. Also includes the test names in the error output. - Changed the xcconfigs so that know it's easier to set different settings at the different levels and not accidentally overwrite settings set at lower levels in the "settings collapse". Also tightened up warnings significantly. - Changed how gtm_unitTestExposedBindingsTestValues works. If you have an implementation of gtm_unitTestExposedBindingsTestValues in your own code you will need to update to the new way of calling. See implementations in GTMNSObject+BindingUnitTesting.m for details. - Added support for grabbing the build number for a particular OS in GTMSystemVersion and easily comparing it to known build numbers, and switched some types from in GTMSystemVersion from "int" to SInt32 to make 64 bit work better. - Added support for SnowLeopard (10A96). We build cleanly with the 10.6 SDKs and all radar checks were updated accordingly. Build All script was also updated to build on SnowLeopard if you have the SDK available. - Turned off building ppc64 GTM because the SnowLeopard SDK currently doesn't have ppc64 support, so SenTestCase isn't defined. This makes it impossible to build the ppc64 10.5 config on SnowLeopard. We have left the setting in the xcconfig for those of you who need it, but have disabled it in the GTM project settings. - Turned on stack smashing protection on the debug builds for all Leopard and above. - Added ability to easily do leak checking by defining the GTM_ENABLE_LEAKS environment variable. It isn't on by default because several of Apple's frameworks leak. You can work around these false positives by using the GTM_LEAKS_SYMBOLS_TO_IGNORE environment variable. Also if you turn on leaks make sure to turn off zombies by defining the GTM_DISABLE_ZOMBIES variable, otherwise every memory allocation you do will look like a leak.
-rw-r--r--AppKit/GTMGetURLHandler.m (renamed from Foundation/GTMGetURLHandler.m)22
-rw-r--r--AppKit/GTMLargeTypeWindowTest.m2
-rw-r--r--AppKit/GTMLinearRGBShading.m2
-rw-r--r--AppKit/GTMLinearRGBShadingTest.m2
-rw-r--r--AppKit/GTMNSBezierPath+Shading.m2
-rw-r--r--AppKit/GTMNSImage+Scaling.h4
-rw-r--r--AppKit/GTMNSImage+Scaling.m17
-rw-r--r--AppKit/GTMNSImage+ScalingTest.m21
-rw-r--r--AppKit/TestData/GTMNSBezierPath+ShadingTest.tiff (renamed from AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff)bin45080 -> 45080 bytes
-rwxr-xr-xBuildScripts/BuildAllSDKs.sh99
-rw-r--r--DebugUtils/GTMDebugThreadValidation.h55
-rw-r--r--DebugUtils/GTMDebugThreadValidation.m38
-rw-r--r--DebugUtils/GTMDebugThreadValidationTest.m110
-rw-r--r--DebugUtils/GTMMethodCheck.m2
-rw-r--r--DebugUtils/GTMMethodCheckTest.m4
-rw-r--r--Foundation/GTMBase64.m7
-rw-r--r--Foundation/GTMCalculatedRange.m2
-rw-r--r--Foundation/GTMGarbageCollection.h14
-rw-r--r--Foundation/GTMGeometryUtils.h64
-rw-r--r--Foundation/GTMHTTPFetcher.m19
-rw-r--r--Foundation/GTMHTTPFetcherTest.m79
-rw-r--r--Foundation/GTMNSAppleEventDescriptor+Foundation.m5
-rw-r--r--Foundation/GTMNSAppleEventDescriptor+Handler.m2
-rw-r--r--Foundation/GTMNSAppleScript+Handler.h2
-rw-r--r--Foundation/GTMNSAppleScript+Handler.m19
-rw-r--r--Foundation/GTMNSAppleScript+HandlerTest.m20
-rw-r--r--Foundation/GTMNSDictionary+URLArguments.m2
-rw-r--r--Foundation/GTMNSString+XML.m2
-rw-r--r--Foundation/GTMObjC2Runtime.m12
-rw-r--r--Foundation/GTMObjC2RuntimeTest.m54
-rw-r--r--Foundation/GTMProgressMonitorInputStreamTest.m15
-rw-r--r--Foundation/GTMRegex.m17
-rw-r--r--Foundation/GTMScriptRunner.m1
-rw-r--r--Foundation/GTMScriptRunnerTest.m24
-rw-r--r--Foundation/GTMStackTrace.h7
-rw-r--r--Foundation/GTMStackTrace.m40
-rw-r--r--Foundation/GTMStackTraceTest.m19
-rw-r--r--Foundation/GTMSystemVersion.h39
-rw-r--r--Foundation/GTMSystemVersion.m120
-rw-r--r--Foundation/GTMSystemVersionTest.m53
-rw-r--r--Foundation/GTMValidatingContainers.h19
-rw-r--r--Foundation/GTMValidatingContainers.m38
-rw-r--r--GTM.xcodeproj/project.pbxproj379
-rw-r--r--GTMDefines.h24
-rw-r--r--GTMiPhone.xcodeproj/project.pbxproj21
-rw-r--r--ReleaseNotes.txt46
-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
-rw-r--r--XcodeConfig/Project/DebugLeopardOrLater.xcconfig2
-rw-r--r--XcodeConfig/Project/DebugSnowLeopardOrLater.xcconfig37
-rw-r--r--XcodeConfig/Project/DebugTigerOrLater.xcconfig2
-rw-r--r--XcodeConfig/Project/DebugiPhone20.xcconfig3
-rw-r--r--XcodeConfig/Project/DebugiPhone21.xcconfig3
-rw-r--r--XcodeConfig/Project/ReleaseLeopardOrLater.xcconfig3
-rw-r--r--XcodeConfig/Project/ReleaseSnowLeopardOrLater.xcconfig37
-rw-r--r--XcodeConfig/Project/ReleaseTigerOrLater.xcconfig3
-rw-r--r--XcodeConfig/Project/ReleaseiPhone20.xcconfig3
-rw-r--r--XcodeConfig/Project/ReleaseiPhone21.xcconfig3
-rw-r--r--XcodeConfig/subconfig/Debug.xcconfig12
-rw-r--r--XcodeConfig/subconfig/GTMMerge.xcconfig35
-rw-r--r--XcodeConfig/subconfig/General.xcconfig103
-rw-r--r--XcodeConfig/subconfig/LeopardOrLater.xcconfig4
-rw-r--r--XcodeConfig/subconfig/Release.xcconfig11
-rw-r--r--XcodeConfig/subconfig/SnowLeopardOrLater.xcconfig26
-rw-r--r--XcodeConfig/subconfig/iPhone20.xcconfig3
-rw-r--r--XcodeConfig/subconfig/iPhone21.xcconfig3
-rw-r--r--XcodeConfig/xcconfigs-readme.txt25
-rw-r--r--iPhone/GTMABAddressBook.h2
-rw-r--r--iPhone/GTMABAddressBookTest.m22
81 files changed, 2319 insertions, 632 deletions
diff --git a/Foundation/GTMGetURLHandler.m b/AppKit/GTMGetURLHandler.m
index 30d516f..a35dd95 100644
--- a/Foundation/GTMGetURLHandler.m
+++ b/AppKit/GTMGetURLHandler.m
@@ -55,7 +55,7 @@
// }
// @end
-#import <Foundation/Foundation.h>
+#import <AppKit/AppKit.h>
#import "GTMGarbageCollection.h"
#import "GTMNSAppleEventDescriptor+Foundation.h"
#import "GTMMethodCheck.h"
@@ -93,6 +93,7 @@ withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
withDescription:(NSString*)string
toDescriptor:(NSAppleEventDescriptor *)desc;
+ (id)handlerForBundle:(NSBundle *)bundle;
++ (void)appFinishedLaunchingHandler:(NSNotification*)notification;
@end
@implementation GTMGetURLHandler
@@ -101,6 +102,15 @@ GTM_METHOD_CHECK(NSString, gtm_appleEventDescriptor);
+ (void)load {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+ [nc addObserver:self
+ selector:@selector(appFinishedLaunchingHandler:)
+ name:NSApplicationDidFinishLaunchingNotification
+ object:nil];
+ [pool release];
+}
+
++ (void)appFinishedLaunchingHandler:(NSNotification*)notification {
NSBundle *bundle = [NSBundle mainBundle];
GTMGetURLHandler *handler = [GTMGetURLHandler handlerForBundle:bundle];
if (handler) {
@@ -111,13 +121,17 @@ GTM_METHOD_CHECK(NSString, gtm_appleEventDescriptor);
andSelector:@selector(getUrl:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
- }
- [pool release];
+ }
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+ [nc removeObserver:self
+ name:NSApplicationDidFinishLaunchingNotification
+ object:nil];
}
+ (id)handlerForBundle:(NSBundle *)bundle {
GTMGetURLHandler *handler = nil;
- NSArray *urlTypes = [bundle objectForInfoDictionaryKey:kGTMCFBundleURLTypesKey];
+ NSArray *urlTypes
+ = [bundle objectForInfoDictionaryKey:kGTMCFBundleURLTypesKey];
if (urlTypes) {
handler = [[[GTMGetURLHandler alloc] initWithTypes:urlTypes] autorelease];
} else {
diff --git a/AppKit/GTMLargeTypeWindowTest.m b/AppKit/GTMLargeTypeWindowTest.m
index 36e60c3..6e0577a 100644
--- a/AppKit/GTMLargeTypeWindowTest.m
+++ b/AppKit/GTMLargeTypeWindowTest.m
@@ -64,7 +64,7 @@ NSString *const kShortTextBlock = @"Short";
// bug. Please bump the system check as appropriate when new systems are
// tested. Currently broken on 10.5.5 and below.
// Radar 6137322 CIFilter crashing when run with GC enabled
- long major, minor, bugfix;
+ SInt32 major, minor, bugfix;
[GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugfix];
if (!(GTMIsGarbageCollectionEnabled()
&& major <= 10 && minor <= 5 && bugfix <= 5)) {
diff --git a/AppKit/GTMLinearRGBShading.m b/AppKit/GTMLinearRGBShading.m
index ef13986..f0216bf 100644
--- a/AppKit/GTMLinearRGBShading.m
+++ b/AppKit/GTMLinearRGBShading.m
@@ -193,7 +193,7 @@ static void cShadeFunction(void *info, const CGFloat *inPos, CGFloat *outVals) {
// lazily create the colorspace as necessary
if (nil == colorSpace_) {
if (isCalibrated_) {
- colorSpace_ = CGColorSpaceCreateWithName(kCGColorSpaceUserRGB);
+ colorSpace_ = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
} else {
colorSpace_ = CGColorSpaceCreateDeviceRGB();
}
diff --git a/AppKit/GTMLinearRGBShadingTest.m b/AppKit/GTMLinearRGBShadingTest.m
index d70b878..38802e6 100644
--- a/AppKit/GTMLinearRGBShadingTest.m
+++ b/AppKit/GTMLinearRGBShadingTest.m
@@ -44,7 +44,7 @@
- (void)testShadingWith {
// Create a shading with kColorCount colors and make sure all the values are there.
- const NSUInteger kColorCount = 100;
+ enum { kColorCount = 100 };
NSColor *theColors[kColorCount];
CGFloat thePositions[kColorCount];
const CGFloat kColorIncrement = 1.0 / kColorCount;
diff --git a/AppKit/GTMNSBezierPath+Shading.m b/AppKit/GTMNSBezierPath+Shading.m
index eff8dfb..f75876f 100644
--- a/AppKit/GTMNSBezierPath+Shading.m
+++ b/AppKit/GTMNSBezierPath+Shading.m
@@ -154,7 +154,7 @@
@implementation NSBezierPath (GTMBezierPathShadingAdditions)
-GTM_METHOD_CHECK(NSBezierPath, gtm_createCGPath); // COV_NF_LINE
+GTM_METHOD_CHECK(NSBezierPath, gtm_createCGPath);
- (void)gtm_strokeAxiallyFrom:(NSPoint)fromPoint to:(NSPoint)toPoint
extendingStart:(BOOL)extendingStart extendingEnd:(BOOL)extendingEnd
diff --git a/AppKit/GTMNSImage+Scaling.h b/AppKit/GTMNSImage+Scaling.h
index 297d18c..6bf2dd5 100644
--- a/AppKit/GTMNSImage+Scaling.h
+++ b/AppKit/GTMNSImage+Scaling.h
@@ -26,8 +26,12 @@
// Return an existing representation of a size
- (NSImageRep *)gtm_representationOfSize:(NSSize)size;
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
// Return the exact or next largest representation for a size
+// If you are on SnowLeopard use
+// -[NSImage bestRepresentationForRect:context:hints:]
- (NSImageRep *)gtm_bestRepresentationForSize:(NSSize)size;
+#endif
// Create a new represetation for a given size
- (BOOL)gtm_createRepresentationOfSize:(NSSize)size;
diff --git a/AppKit/GTMNSImage+Scaling.m b/AppKit/GTMNSImage+Scaling.m
index 57687fd..5f31190 100644
--- a/AppKit/GTMNSImage+Scaling.m
+++ b/AppKit/GTMNSImage+Scaling.m
@@ -23,6 +23,9 @@
@implementation NSImage (GTMNSImageScaling)
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
+// If you are on SnowLeopard use
+// -[NSImage bestRepresentationForRect:context:hints:]
- (NSImageRep *)gtm_bestRepresentationForSize:(NSSize)size {
NSImageRep *bestRep = [self gtm_representationOfSize:size];
if (bestRep) {
@@ -37,7 +40,7 @@
while ((thisRep = [repEnum nextObject])) {
CGFloat thisDistance;
thisDistance = MIN(size.width - [thisRep size].width,
- size.height-[thisRep size].height);
+ size.height - [thisRep size].height);
if (repDistance < 0 && thisDistance > 0) continue;
if (ABS(thisDistance) < ABS(repDistance)
@@ -53,6 +56,7 @@
return bestRep;
}
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
- (NSImageRep *)gtm_representationOfSize:(NSSize)size {
NSArray *reps = [self representations];
@@ -80,8 +84,15 @@
return NO;
}
- NSBitmapImageRep *bestRep =
- (NSBitmapImageRep *)[self gtm_bestRepresentationForSize:size];
+ NSBitmapImageRep *bestRep;
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
+ bestRep = (NSBitmapImageRep *)[self gtm_bestRepresentationForSize:size];
+#else
+ bestRep
+ = (NSBitmapImageRep *)[self bestRepresentationForRect:GTMNSRectOfSize(size)
+ context:nil
+ hints:nil];
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
NSRect drawRect = GTMNSScaleRectToRect(GTMNSRectOfSize([bestRep size]),
GTMNSRectOfSize(size),
diff --git a/AppKit/GTMNSImage+ScalingTest.m b/AppKit/GTMNSImage+ScalingTest.m
index ec17cc5..5679b7c 100644
--- a/AppKit/GTMNSImage+ScalingTest.m
+++ b/AppKit/GTMNSImage+ScalingTest.m
@@ -21,6 +21,7 @@
#import "GTMSenTestCase.h"
#import "GTMNSImage+Scaling.h"
+#import "GTMGeometryUtils.h"
@interface GTMNSImage_ScalingTest : GTMTestCase
@end
@@ -31,7 +32,16 @@
NSImage *testImage = [NSImage imageNamed:@"NSApplicationIcon"];
NSImageRep *rep = nil;
- rep = [testImage gtm_bestRepresentationForSize:NSMakeSize(99, 99)];
+ NSRect bestRepRect = NSMakeRect(0, 0, 99, 99);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+ rep = [testImage bestRepresentationForRect:bestRepRect
+ context:nil
+ hints:nil];
+#else
+ rep = [testImage gtm_bestRepresentationForSize:bestRepRect.size];
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+
STAssertTrue(NSEqualSizes([rep size], NSMakeSize(128, 128)), nil);
[testImage gtm_createIconRepresentations];
@@ -39,7 +49,14 @@
STAssertNotNil([testImage gtm_representationOfSize:NSMakeSize(32, 32)], nil);
NSImage *duplicate = [testImage gtm_duplicateOfSize: NSMakeSize(48, 48)];
- rep = [duplicate gtm_bestRepresentationForSize:NSMakeSize(50, 50)];
+ bestRepRect = NSMakeRect(0, 0, 50, 50);
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+ rep = [duplicate bestRepresentationForRect:bestRepRect
+ context:nil
+ hints:nil];
+#else
+ rep = [duplicate gtm_bestRepresentationForSize:bestRepRect.size];
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
STAssertTrue(NSEqualSizes([rep size], NSMakeSize(48, 48)), nil);
}
diff --git a/AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff b/AppKit/TestData/GTMNSBezierPath+ShadingTest.tiff
index b44b5bf..b44b5bf 100644
--- a/AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff
+++ b/AppKit/TestData/GTMNSBezierPath+ShadingTest.tiff
Binary files differ
diff --git a/BuildScripts/BuildAllSDKs.sh b/BuildScripts/BuildAllSDKs.sh
index 1e08940..32a867d 100755
--- a/BuildScripts/BuildAllSDKs.sh
+++ b/BuildScripts/BuildAllSDKs.sh
@@ -1,8 +1,8 @@
#!/bin/sh
# BuildAllSDKs.sh
#
-# This script builds the Tiger, Leopard and iPhone versions of the requested
-# target in the current basic config (debug, release, debug-gcov).
+# This script builds the Tiger, Leopard, SnowLeopard and iPhone versions of the
+# requested target in the current basic config (debug, release, debug-gcov).
#
# Copyright 2006-2008 Google Inc.
#
@@ -30,18 +30,30 @@ if [ "${ACTION}" == "clean" ]; then
PROJECT_ACTION="clean"
fi
+# get available SDKs and PLATFORMS
+AVAILABLE_MACOS_SDKS=`eval ls ${DEVELOPER_SDK_DIR}`
+AVAILABLE_PLATFORMS=`eval ls ${DEVELOPER_DIR}/Platforms`
+
# build up our GTMiPhone parts
GTMIPHONE_OPEN_EXTRAS=""
GTMIPHONE_BUILD_EXTRAS=""
if [ "${GTMIPHONE_PROJECT_TARGET}" != "" ]; then
- GTMIPHONE_OPEN_EXTRAS="-- make sure both project files are open
- open posix file \"${SRCROOT}/GTM.xcodeproj\"
- open posix file \"${SRCROOT}/GTMiPhone.xcodeproj\""
- GTMIPHONE_BUILD_EXTRAS="tell project \"GTMiPhone\"
- -- do the GTMiPhone build
- ${PROJECT_ACTION} using build configuration \"${REQUESTED_BUILD_STYLE}\"
- set active target to target \"${STARTING_TARGET}\"
- end tell"
+ GTMIPHONE_OPEN_EXTRAS="
+ if \"${AVAILABLE_PLATFORMS}\" contains \"iPhoneSimulator.platform\" then
+ -- make sure both project files are open
+ open posix file \"${SRCROOT}/GTM.xcodeproj\"
+ open posix file \"${SRCROOT}/GTMiPhone.xcodeproj\"
+ end if"
+ GTMIPHONE_BUILD_EXTRAS="
+ if \"${AVAILABLE_PLATFORMS}\" contains \"iPhoneSimulator.platform\" then
+ with timeout of 9999 seconds
+ tell project \"GTMiPhone\"
+ -- do the GTMiPhone build
+ ${PROJECT_ACTION} using build configuration \"${REQUESTED_BUILD_STYLE}\"
+ set active target to target \"${STARTING_TARGET}\"
+ end tell
+ end timeout
+ end if"
fi
# build up our GTM AppleScript
@@ -49,32 +61,47 @@ OUR_BUILD_SCRIPT="on run
tell application \"Xcode\"
activate
${GTMIPHONE_OPEN_EXTRAS}
- tell project \"GTM\"
- -- wait for build to finish
- set x to 0
- repeat while currently building
- delay 0.5
- set x to x + 1
- if x > 6 then
- display alert \"GTM is still building, can't start.\"
- return
- end if
- end repeat
- -- do the GTM builds
- with timeout of 9999 seconds
- set active target to target \"${GTM_PROJECT_TARGET}\"
- set buildResult to ${PROJECT_ACTION} using build configuration \"TigerOrLater-${REQUESTED_BUILD_STYLE}\"
- if buildResult is not equal to \"Build succeeded\" then
- set active target to target \"${STARTING_TARGET}\"
- return
- end if
- set buildResult to ${PROJECT_ACTION} using build configuration \"LeopardOrLater-${REQUESTED_BUILD_STYLE}\"
- set active target to target \"${STARTING_TARGET}\"
- if buildResult is not equal to \"Build succeeded\" then
- return
- end if
- end timeout
- end tell
+ if \"${AVAILABLE_PLATFORMS}\" contains \"MacOSX.platform\" then
+ tell project \"GTM\"
+ -- wait for build to finish
+ set x to 0
+ repeat while currently building
+ delay 0.5
+ set x to x + 1
+ if x > 6 then
+ display alert \"GTM is still building, can't start.\"
+ return
+ end if
+ end repeat
+ -- do the GTM builds
+ with timeout of 9999 seconds
+ if \"{$AVAILABLE_MACOS_SDKS}\" contains \"MacOSX10.4u.sdk\" then
+ set active target to target \"${GTM_PROJECT_TARGET}\"
+ set buildResult to ${PROJECT_ACTION} using build configuration \"TigerOrLater-${REQUESTED_BUILD_STYLE}\"
+ set active target to target \"${STARTING_TARGET}\"
+ if buildResult is not equal to \"Build succeeded\" then
+ return
+ end if
+ end if
+ if \"{$AVAILABLE_MACOS_SDKS}\" contains \"MacOSX10.5.sdk\" then
+ set active target to target \"${GTM_PROJECT_TARGET}\"
+ set buildResult to ${PROJECT_ACTION} using build configuration \"LeopardOrLater-${REQUESTED_BUILD_STYLE}\"
+ set active target to target \"${STARTING_TARGET}\"
+ if buildResult is not equal to \"Build succeeded\" then
+ return
+ end if
+ end if
+ if \"{$AVAILABLE_MACOS_SDKS}\" contains \"MacOSX10.6.sdk\" then
+ set active target to target \"${GTM_PROJECT_TARGET}\"
+ set buildResult to ${PROJECT_ACTION} using build configuration \"SnowLeopardOrLater-${REQUESTED_BUILD_STYLE}\"
+ set active target to target \"${STARTING_TARGET}\"
+ if buildResult is not equal to \"Build succeeded\" then
+ return
+ end if
+ end if
+ end timeout
+ end tell
+ end if
${GTMIPHONE_BUILD_EXTRAS}
end tell
end run"
diff --git a/DebugUtils/GTMDebugThreadValidation.h b/DebugUtils/GTMDebugThreadValidation.h
new file mode 100644
index 0000000..0636159
--- /dev/null
+++ b/DebugUtils/GTMDebugThreadValidation.h
@@ -0,0 +1,55 @@
+//
+// GTMDebugThreadValidation.h
+//
+// Copyright 2008 Google Inc.
+//
+// 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
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+#if DEBUG
+#import "GTMDefines.h"
+#import <Foundation/Foundation.h>
+
+// GTMAssertRunningOnMainThread will allow you to verify that you are
+// currently running on the main thread. This can be useful for checking
+// under DEBUG to make sure that code that requires being run on the main thread
+// is doing so. Use the GTMAssertRunningOnMainThread macro, don't use
+// the _GTMAssertRunningOnMainThread or _GTMIsRunningOnMainThread
+// helper functions.
+
+// On Leopard and above we can just use NSThread functionality.
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+BOOL _GTMIsRunningOnMainThread(void);
+#else // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+#import <Foundation/Foundation.h>
+GTM_INLINE BOOL _GTMIsRunningOnMainThread(void) {
+ return [NSThread isMainThread];
+}
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+
+GTM_INLINE void _GTMAssertRunningOnMainThread(const char *func,
+ const char *file,
+ int lineNum) {
+ _GTMDevAssert(_GTMIsRunningOnMainThread(),
+ @"%s not being run on main thread (%s - %d)",
+ func, file, lineNum);
+}
+
+#define GTMAssertRunningOnMainThread() \
+ (_GTMAssertRunningOnMainThread(__func__, __FILE__, __LINE__))
+
+#else // DEBUG
+
+#define GTMAssertRunningOnMainThread() do { } while (0)
+
+#endif // DEBUG
diff --git a/DebugUtils/GTMDebugThreadValidation.m b/DebugUtils/GTMDebugThreadValidation.m
new file mode 100644
index 0000000..5889cd8
--- /dev/null
+++ b/DebugUtils/GTMDebugThreadValidation.m
@@ -0,0 +1,38 @@
+//
+// GTMDebugThreadValidation.m
+//
+// Copyright 2008 Google Inc.
+//
+// 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
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+
+#if DEBUG && MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+
+#import "GTMDebugThreadValidation.h"
+
+static NSThread *gGTMMainThread = nil;
+
+static __attribute__((constructor)) void _GTMInitThread(void) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ gGTMMainThread = [NSThread currentThread];
+ [gGTMMainThread retain];
+ [pool release];
+}
+
+
+BOOL _GTMIsRunningOnMainThread(void) {
+ return [[NSThread currentThread] isEqual:gGTMMainThread];
+}
+
+#endif // DEBUG && MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
diff --git a/DebugUtils/GTMDebugThreadValidationTest.m b/DebugUtils/GTMDebugThreadValidationTest.m
new file mode 100644
index 0000000..66bd51b
--- /dev/null
+++ b/DebugUtils/GTMDebugThreadValidationTest.m
@@ -0,0 +1,110 @@
+//
+// GTMDebugThreadValidationTest.m
+// Copyright 2008 Google Inc.
+//
+// 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
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+#import "GTMSenTestCase.h"
+#import "GTMDebugThreadValidation.h"
+
+// GTMDebugThreadValidation only happens on debug builds
+#if DEBUG
+
+@interface GTMDebugThreadValidationTest : GTMTestCase
+@end
+
+// A cheap flag for knowing when our thread has run
+
+static volatile BOOL gGTMDebugThreadValidationTestDone = NO;
+
+// This is an assertion handler that just records that an assertion has fired.
+@interface GTMDebugThreadValidationCheckAssertionHandler : NSAssertionHandler {
+ @private
+ BOOL handledAssertion_;
+}
+- (void)handleFailureInMethod:(SEL)selector
+ object:(id)object
+ file:(NSString *)fileName
+ lineNumber:(NSInteger)line
+ description:(NSString *)format,...;
+
+- (void)handleFailureInFunction:(NSString *)functionName
+ file:(NSString *)fileName
+ lineNumber:(NSInteger)line
+ description:(NSString *)format,...;
+- (BOOL)didHandleAssertion;
+@end
+
+@implementation GTMDebugThreadValidationTest
+- (void)testOnMainThread {
+ STAssertNoThrow(GTMAssertRunningOnMainThread(), nil);
+}
+
+- (void)threadFunc:(NSMutableString *)result {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ // We'll insert our own assertion handler that will get called on the assert
+ // so that we don't have to worry about the log, and exception being thrown.
+ GTMDebugThreadValidationCheckAssertionHandler *handler =
+ [[[GTMDebugThreadValidationCheckAssertionHandler alloc] init] autorelease];
+ NSMutableDictionary *threadDictionary
+ = [[NSThread currentThread] threadDictionary];
+ [threadDictionary setObject:handler forKey:@"NSAssertionHandler"];
+ GTMAssertRunningOnMainThread();
+ if ([handler didHandleAssertion]) {
+ [result setString:@"ASSERTED"];
+ }
+ [threadDictionary removeObjectForKey:@"NSAssertionHandler"];
+ gGTMDebugThreadValidationTestDone = YES;
+ [pool release];
+}
+
+- (void)testOnOtherThread {
+ NSMutableString *result = [NSMutableString string];
+ gGTMDebugThreadValidationTestDone = NO;
+ [NSThread detachNewThreadSelector:@selector(threadFunc:)
+ toTarget:self
+ withObject:result];
+ NSRunLoop *loop = [NSRunLoop currentRunLoop];
+
+ while (!gGTMDebugThreadValidationTestDone) {
+ NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0.01];
+ [loop runUntilDate:date];
+ }
+ STAssertEqualStrings(result, @"ASSERTED", @"GTMAssertRunningOnMainThread did "
+ @"not assert while running on another thread");
+}
+@end
+
+@implementation GTMDebugThreadValidationCheckAssertionHandler
+
+- (void)handleFailureInMethod:(SEL)selector
+ object:(id)object
+ file:(NSString *)fileName
+ lineNumber:(NSInteger)line
+ description:(NSString *)format,... {
+ handledAssertion_ = YES;
+}
+
+- (void)handleFailureInFunction:(NSString *)functionName
+ file:(NSString *)fileName
+ lineNumber:(NSInteger)line
+ description:(NSString *)format,... {
+ handledAssertion_ = YES;
+}
+
+- (BOOL)didHandleAssertion {
+ return handledAssertion_;
+}
+@end
+#endif // DEBUG
diff --git a/DebugUtils/GTMMethodCheck.m b/DebugUtils/GTMMethodCheck.m
index ef3ee4a..2f88dc3 100644
--- a/DebugUtils/GTMMethodCheck.m
+++ b/DebugUtils/GTMMethodCheck.m
@@ -76,6 +76,7 @@ void GTMMethodCheckMethodChecker(void) {
// Run through all the classes looking for class methods that are
// prefixed with xxGMMethodCheckMethod. If it finds one, it calls it.
// See GTMMethodCheck.h to see what it does.
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int numClasses = 0;
int newNumClasses = objc_getClassList(NULL, 0);
int i;
@@ -156,6 +157,7 @@ void GTMMethodCheckMethodChecker(void) {
if (classes) {
free(classes);
}
+ [pool release];
}
#endif // DEBUG
diff --git a/DebugUtils/GTMMethodCheckTest.m b/DebugUtils/GTMMethodCheckTest.m
index 7b9fa0c..974dfaf 100644
--- a/DebugUtils/GTMMethodCheckTest.m
+++ b/DebugUtils/GTMMethodCheckTest.m
@@ -25,8 +25,8 @@ static BOOL gTestCheckVar = NO;
@end
@implementation GTMMethodCheckTest
-GTM_METHOD_CHECK(GTMMethodCheckTest, GTMMethodCheckTestMethod); // COV_NF_LINE
-GTM_METHOD_CHECK(GTMMethodCheckTest, GTMMethodCheckTestClassMethod); // COV_NF_LINE
+GTM_METHOD_CHECK(GTMMethodCheckTest, GTMMethodCheckTestMethod);
+GTM_METHOD_CHECK(GTMMethodCheckTest, GTMMethodCheckTestClassMethod);
- (void)GTMMethodCheckTestMethod {
}
diff --git a/Foundation/GTMBase64.m b/Foundation/GTMBase64.m
index 03914fd..5cbcfa7 100644
--- a/Foundation/GTMBase64.m
+++ b/Foundation/GTMBase64.m
@@ -153,7 +153,7 @@ static const char kWebSafeBase64DecodeChars[] = {
// YES if the character is a whitespace character.
// NO if the character is not a whitespace character.
//
-FOUNDATION_STATIC_INLINE BOOL IsSpace(unsigned char c) {
+GTM_INLINE BOOL IsSpace(unsigned char c) {
// we use our own mapping here because we don't want anything w/ locale
// support.
static BOOL kSpaces[256] = {
@@ -192,8 +192,7 @@ FOUNDATION_STATIC_INLINE BOOL IsSpace(unsigned char c) {
// Returns:
// The guessed encoded length for a source length
//
-FOUNDATION_STATIC_INLINE NSUInteger CalcEncodedLength(NSUInteger srcLen,
- BOOL padded) {
+GTM_INLINE NSUInteger CalcEncodedLength(NSUInteger srcLen, BOOL padded) {
NSUInteger intermediate_result = 8 * srcLen + 5;
NSUInteger len = intermediate_result / 6;
if (padded) {
@@ -209,7 +208,7 @@ FOUNDATION_STATIC_INLINE NSUInteger CalcEncodedLength(NSUInteger srcLen,
// Returns:
// The guessed decoded length for a source length
//
-FOUNDATION_STATIC_INLINE NSUInteger GuessDecodedLength(NSUInteger srcLen) {
+GTM_INLINE NSUInteger GuessDecodedLength(NSUInteger srcLen) {
return (srcLen + 3) / 4 * 3;
}
diff --git a/Foundation/GTMCalculatedRange.m b/Foundation/GTMCalculatedRange.m
index 218b811..ef49d83 100644
--- a/Foundation/GTMCalculatedRange.m
+++ b/Foundation/GTMCalculatedRange.m
@@ -30,7 +30,7 @@
- (CGFloat)position;
@end
-CG_INLINE BOOL FPEqual(CGFloat a, CGFloat b) {
+GTM_INLINE BOOL FPEqual(CGFloat a, CGFloat b) {
return (fpclassify(a - b) == FP_ZERO);
}
diff --git a/Foundation/GTMGarbageCollection.h b/Foundation/GTMGarbageCollection.h
index 7f2873c..b29a13b 100644
--- a/Foundation/GTMGarbageCollection.h
+++ b/Foundation/GTMGarbageCollection.h
@@ -33,13 +33,13 @@
// but there may be a reason the you want to make something collectable
// but not autoreleased, especially in pure GC code where you don't
// want to bother with the nop autorelease.
-FOUNDATION_STATIC_INLINE id GTMNSMakeCollectable(CFTypeRef cf) {
+GTM_INLINE id GTMNSMakeCollectable(CFTypeRef cf) {
return NSMakeCollectable(cf);
}
// GTMNSMakeUncollectable is for global maps, etc. that we don't
// want released ever. You should still retain these in non-gc code.
-FOUNDATION_STATIC_INLINE void GTMNSMakeUncollectable(id object) {
+GTM_INLINE void GTMNSMakeUncollectable(id object) {
[[NSGarbageCollector defaultCollector] disableCollectorForPointer:object];
}
@@ -48,21 +48,21 @@ FOUNDATION_STATIC_INLINE void GTMNSMakeUncollectable(id object) {
// There are some places where GC doesn't work w/ things w/in Apple's
// frameworks, so this is here so GTM unittests and detect it, and not run
// individual tests to work around bugs in Apple's frameworks.
-FOUNDATION_STATIC_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
+GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
return ([NSGarbageCollector defaultCollector] != nil);
}
#else
-FOUNDATION_STATIC_INLINE id GTMNSMakeCollectable(CFTypeRef cf) {
+GTM_INLINE id GTMNSMakeCollectable(CFTypeRef cf) {
// NSMakeCollectable handles NULLs just fine and returns nil as expected.
return (id)cf;
}
-FOUNDATION_STATIC_INLINE void GTMNSMakeUncollectable(id object) {
+GTM_INLINE void GTMNSMakeUncollectable(id object) {
}
-FOUNDATION_STATIC_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
+GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
return NO;
}
@@ -71,7 +71,7 @@ FOUNDATION_STATIC_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
// GTMCFAutorelease makes a CF object collectable in GC mode, or adds it
// to the autorelease pool in non-GC mode. Either way it is taken care
// of.
-FOUNDATION_STATIC_INLINE id GTMCFAutorelease(CFTypeRef cf) {
+GTM_INLINE id GTMCFAutorelease(CFTypeRef cf) {
return [GTMNSMakeCollectable(cf) autorelease];
}
diff --git a/Foundation/GTMGeometryUtils.h b/Foundation/GTMGeometryUtils.h
index 855b97f..c3d6b1a 100644
--- a/Foundation/GTMGeometryUtils.h
+++ b/Foundation/GTMGeometryUtils.h
@@ -52,7 +52,7 @@ typedef NSUInteger GTMRectAlignment;
//
// Returns:
// point located in the middle of min X side of rect
-CG_INLINE CGPoint GTMCGMidMinX(CGRect rect) {
+GTM_INLINE CGPoint GTMCGMidMinX(CGRect rect) {
return CGPointMake(CGRectGetMinX(rect), CGRectGetMidY(rect));
}
@@ -63,7 +63,7 @@ CG_INLINE CGPoint GTMCGMidMinX(CGRect rect) {
//
// Returns:
// point located in the middle of max X side of rect
-CG_INLINE CGPoint GTMCGMidMaxX(CGRect rect) {
+GTM_INLINE CGPoint GTMCGMidMaxX(CGRect rect) {
return CGPointMake(CGRectGetMaxX(rect), CGRectGetMidY(rect));
}
@@ -74,7 +74,7 @@ CG_INLINE CGPoint GTMCGMidMaxX(CGRect rect) {
//
// Returns:
// point located in the middle of max Y side of rect
-CG_INLINE CGPoint GTMCGMidMaxY(CGRect rect) {
+GTM_INLINE CGPoint GTMCGMidMaxY(CGRect rect) {
return CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
}
@@ -85,7 +85,7 @@ CG_INLINE CGPoint GTMCGMidMaxY(CGRect rect) {
//
// Returns:
// point located in the middle of min Y side of rect
-CG_INLINE CGPoint GTMCGMidMinY(CGRect rect) {
+GTM_INLINE CGPoint GTMCGMidMinY(CGRect rect) {
return CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
}
@@ -96,7 +96,7 @@ CG_INLINE CGPoint GTMCGMidMinY(CGRect rect) {
//
// Returns:
// point located in the center of rect
-CG_INLINE CGPoint GTMCGCenter(CGRect rect) {
+GTM_INLINE CGPoint GTMCGCenter(CGRect rect) {
return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
}
@@ -110,7 +110,7 @@ CG_INLINE CGPoint GTMCGCenter(CGRect rect) {
//
// Returns:
// size of rectangle
-CG_INLINE CGSize GTMCGRectSize(CGRect rect) {
+GTM_INLINE CGSize GTMCGRectSize(CGRect rect) {
return CGSizeMake(CGRectGetWidth(rect), CGRectGetHeight(rect));
}
@@ -121,7 +121,7 @@ CG_INLINE CGSize GTMCGRectSize(CGRect rect) {
//
// Returns:
// rectangle of size (origin 0,0)
-CG_INLINE CGRect GTMCGRectOfSize(CGSize size) {
+GTM_INLINE CGRect GTMCGRectOfSize(CGSize size) {
return CGRectMake(0.0f, 0.0f, size.width, size.height);
}
@@ -137,7 +137,7 @@ CG_INLINE CGRect GTMCGRectOfSize(CGSize size) {
//
// Returns:
// Converted Rect
-CG_INLINE CGRect GTMCGRectScale(CGRect inRect, CGFloat xScale, CGFloat yScale) {
+GTM_INLINE CGRect GTMCGRectScale(CGRect inRect, CGFloat xScale, CGFloat yScale) {
return CGRectMake(inRect.origin.x, inRect.origin.y,
inRect.size.width * xScale, inRect.size.height * yScale);
}
@@ -171,7 +171,7 @@ CGRect GTMCGScaleRectangleToSize(CGRect scalee, CGSize size,
//
// Returns:
// Distance
-CG_INLINE CGFloat GTMCGDistanceBetweenPoints(CGPoint pt1, CGPoint pt2) {
+GTM_INLINE CGFloat GTMCGDistanceBetweenPoints(CGPoint pt1, CGPoint pt2) {
CGFloat dX = pt1.x - pt2.x;
CGFloat dY = pt1.y - pt2.y;
#if CGFLOAT_IS_DOUBLE
@@ -200,7 +200,7 @@ CG_INLINE CGFloat GTMCGDistanceBetweenPoints(CGPoint pt1, CGPoint pt2) {
//
// Returns:
// Converted NSPoint
-CG_INLINE NSPoint GTMCGPointToNSPoint(CGPoint inPoint) {
+GTM_INLINE NSPoint GTMCGPointToNSPoint(CGPoint inPoint) {
_GTMCompileAssert(sizeof(NSPoint) == sizeof(CGPoint), NSPoint_and_CGPoint_must_be_the_same_size);
union convertUnion {NSPoint ns; CGPoint cg;};
return ((union convertUnion *)&inPoint)->ns;
@@ -216,7 +216,7 @@ CG_INLINE NSPoint GTMCGPointToNSPoint(CGPoint inPoint) {
//
// Returns:
// Converted CGPoint
-CG_INLINE CGPoint GTMNSPointToCGPoint(NSPoint inPoint) {
+GTM_INLINE CGPoint GTMNSPointToCGPoint(NSPoint inPoint) {
_GTMCompileAssert(sizeof(NSPoint) == sizeof(CGPoint), NSPoint_and_CGPoint_must_be_the_same_size);
union convertUnion {NSPoint ns; CGPoint cg;};
return ((union convertUnion *)&inPoint)->cg;
@@ -235,7 +235,7 @@ CG_INLINE CGPoint GTMNSPointToCGPoint(NSPoint inPoint) {
//
// Returns:
// Converted NSRect
-CG_INLINE NSRect GTMCGRectToNSRect(CGRect inRect) {
+GTM_INLINE NSRect GTMCGRectToNSRect(CGRect inRect) {
_GTMCompileAssert(sizeof(NSRect) == sizeof(CGRect), NSRect_and_CGRect_must_be_the_same_size);
union convertUnion {NSRect ns; CGRect cg;};
return ((union convertUnion *)&inRect)->ns;
@@ -251,7 +251,7 @@ CG_INLINE NSRect GTMCGRectToNSRect(CGRect inRect) {
//
// Returns:
// Converted CGRect
-CG_INLINE CGRect GTMNSRectToCGRect(NSRect inRect) {
+GTM_INLINE CGRect GTMNSRectToCGRect(NSRect inRect) {
_GTMCompileAssert(sizeof(NSRect) == sizeof(CGRect), NSRect_and_CGRect_must_be_the_same_size);
union convertUnion {NSRect ns; CGRect cg;};
return ((union convertUnion *)&inRect)->cg;
@@ -268,7 +268,7 @@ CG_INLINE CGRect GTMNSRectToCGRect(NSRect inRect) {
//
// Returns:
// Converted NSSize
-CG_INLINE NSSize GTMCGSizeToNSSize(CGSize inSize) {
+GTM_INLINE NSSize GTMCGSizeToNSSize(CGSize inSize) {
_GTMCompileAssert(sizeof(NSSize) == sizeof(CGSize), NSSize_and_CGSize_must_be_the_same_size);
union convertUnion {NSSize ns; CGSize cg;};
return ((union convertUnion *)&inSize)->ns;
@@ -281,7 +281,7 @@ CG_INLINE NSSize GTMCGSizeToNSSize(CGSize inSize) {
//
// Returns:
// Converted CGSize
-CG_INLINE CGSize GTMNSSizeToCGSize(NSSize inSize) {
+GTM_INLINE CGSize GTMNSSizeToCGSize(NSSize inSize) {
_GTMCompileAssert(sizeof(NSSize) == sizeof(CGSize), NSSize_and_CGSize_must_be_the_same_size);
union convertUnion {NSSize ns; CGSize cg;};
return ((union convertUnion *)&inSize)->cg;
@@ -297,7 +297,7 @@ CG_INLINE CGSize GTMNSSizeToCGSize(NSSize inSize) {
//
// Returns:
// point located in the middle of min X side of rect
-CG_INLINE NSPoint GTMNSMidMinX(NSRect rect) {
+GTM_INLINE NSPoint GTMNSMidMinX(NSRect rect) {
return NSMakePoint(NSMinX(rect), NSMidY(rect));
}
@@ -308,7 +308,7 @@ CG_INLINE NSPoint GTMNSMidMinX(NSRect rect) {
//
// Returns:
// point located in the middle of max X side of rect
-CG_INLINE NSPoint GTMNSMidMaxX(NSRect rect) {
+GTM_INLINE NSPoint GTMNSMidMaxX(NSRect rect) {
return NSMakePoint(NSMaxX(rect), NSMidY(rect));
}
@@ -319,7 +319,7 @@ CG_INLINE NSPoint GTMNSMidMaxX(NSRect rect) {
//
// Returns:
// point located in the middle of max Y side of rect
-CG_INLINE NSPoint GTMNSMidMaxY(NSRect rect) {
+GTM_INLINE NSPoint GTMNSMidMaxY(NSRect rect) {
return NSMakePoint(NSMidX(rect), NSMaxY(rect));
}
@@ -330,7 +330,7 @@ CG_INLINE NSPoint GTMNSMidMaxY(NSRect rect) {
//
// Returns:
// point located in the middle of min Y side of rect
-CG_INLINE NSPoint GTMNSMidMinY(NSRect rect) {
+GTM_INLINE NSPoint GTMNSMidMinY(NSRect rect) {
return NSMakePoint(NSMidX(rect), NSMinY(rect));
}
@@ -341,7 +341,7 @@ CG_INLINE NSPoint GTMNSMidMinY(NSRect rect) {
//
// Returns:
// point located in the center of rect
-CG_INLINE NSPoint GTMNSCenter(NSRect rect) {
+GTM_INLINE NSPoint GTMNSCenter(NSRect rect) {
return NSMakePoint(NSMidX(rect), NSMidY(rect));
}
@@ -355,7 +355,7 @@ CG_INLINE NSPoint GTMNSCenter(NSRect rect) {
//
// Returns:
// size of rectangle
-CG_INLINE NSSize GTMNSRectSize(NSRect rect) {
+GTM_INLINE NSSize GTMNSRectSize(NSRect rect) {
return NSMakeSize(NSWidth(rect), NSHeight(rect));
}
@@ -366,7 +366,7 @@ CG_INLINE NSSize GTMNSRectSize(NSRect rect) {
//
// Returns:
// rectangle of size (origin 0,0)
-CG_INLINE NSRect GTMNSRectOfSize(NSSize size) {
+GTM_INLINE NSRect GTMNSRectOfSize(NSSize size) {
return NSMakeRect(0.0f, 0.0f, size.width, size.height);
}
@@ -382,7 +382,7 @@ CG_INLINE NSRect GTMNSRectOfSize(NSSize size) {
//
// Returns:
// Converted Rect
-CG_INLINE NSRect GTMNSRectScale(NSRect inRect, CGFloat xScale, CGFloat yScale) {
+GTM_INLINE NSRect GTMNSRectScale(NSRect inRect, CGFloat xScale, CGFloat yScale) {
return NSMakeRect(inRect.origin.x, inRect.origin.y,
inRect.size.width * xScale, inRect.size.height * yScale);
}
@@ -392,8 +392,8 @@ CG_INLINE NSRect GTMNSRectScale(NSRect inRect, CGFloat xScale, CGFloat yScale) {
// Args:
// alignee - rect to be aligned
// aligner - rect to be aligned from
-CG_INLINE NSRect GTMNSAlignRectangles(NSRect alignee, NSRect aligner,
- GTMRectAlignment alignment) {
+GTM_INLINE NSRect GTMNSAlignRectangles(NSRect alignee, NSRect aligner,
+ GTMRectAlignment alignment) {
return GTMCGRectToNSRect(GTMCGAlignRectangles(GTMNSRectToCGRect(alignee),
GTMNSRectToCGRect(aligner),
alignment));
@@ -406,10 +406,10 @@ CG_INLINE NSRect GTMNSAlignRectangles(NSRect alignee, NSRect aligner,
// scaler - rect to scale to
// scaling - way to scale the rectangle
// alignment - way to align the scaled rectangle
-CG_INLINE NSRect GTMNSScaleRectToRect(NSRect scalee,
- NSRect scaler,
- GTMScaling scaling,
- GTMRectAlignment alignment) {
+GTM_INLINE NSRect GTMNSScaleRectToRect(NSRect scalee,
+ NSRect scaler,
+ GTMScaling scaling,
+ GTMRectAlignment alignment) {
return GTMCGRectToNSRect(
GTMCGAlignRectangles(
@@ -426,8 +426,8 @@ CG_INLINE NSRect GTMNSScaleRectToRect(NSRect scalee,
// scalee - rect to be scaled
// size - size to scale to
// scaling - way to scale the rectangle
-CG_INLINE NSRect GTMNSScaleRectangleToSize(NSRect scalee, NSSize size,
- GTMScaling scaling) {
+GTM_INLINE NSRect GTMNSScaleRectangleToSize(NSRect scalee, NSSize size,
+ GTMScaling scaling) {
return GTMCGRectToNSRect(GTMCGScaleRectangleToSize(GTMNSRectToCGRect(scalee),
GTMNSSizeToCGSize(size),
scaling));
@@ -444,7 +444,7 @@ CG_INLINE NSRect GTMNSScaleRectangleToSize(NSRect scalee, NSSize size,
//
// Returns:
// Distance
-CG_INLINE CGFloat GTMNSDistanceBetweenPoints(NSPoint pt1, NSPoint pt2) {
+GTM_INLINE CGFloat GTMNSDistanceBetweenPoints(NSPoint pt1, NSPoint pt2) {
return GTMCGDistanceBetweenPoints(GTMNSPointToCGPoint(pt1),
GTMNSPointToCGPoint(pt2));
}
diff --git a/Foundation/GTMHTTPFetcher.m b/Foundation/GTMHTTPFetcher.m
index 614f3ad..bc93bab 100644
--- a/Foundation/GTMHTTPFetcher.m
+++ b/Foundation/GTMHTTPFetcher.m
@@ -21,6 +21,7 @@
#import "GTMHTTPFetcher.h"
#import "GTMDebugSelectorValidation.h"
#import "GTMGarbageCollection.h"
+#import "GTMSystemVersion.h"
@interface GTMHTTPFetcher (GTMHTTPFetcherLoggingInternal)
- (void)logFetchWithError:(NSError *)error;
@@ -1129,13 +1130,9 @@ CannotBeginFetch:
NSString *scheme = [theURL scheme];
NSString *domain = nil;
- if ([host isEqual:@"localhost"]) {
- // the domain stored into NSHTTPCookies for localhost is "localhost.local"
- domain = @"localhost.local";
- } else {
- if (host) {
- domain = [@"." stringByAppendingString:host];
- }
+
+ if (host) {
+ domain = [[@"." stringByAppendingString:host] lowercaseString];
}
NSUInteger numberOfCookies = [cookieStorageArray count];
@@ -1143,11 +1140,17 @@ CannotBeginFetch:
NSHTTPCookie *storedCookie = [cookieStorageArray objectAtIndex:idx];
- NSString *cookieDomain = [storedCookie domain];
+ NSString *cookieDomain = [[storedCookie domain] lowercaseString];
NSString *cookiePath = [storedCookie path];
BOOL cookieIsSecure = [storedCookie isSecure];
BOOL domainIsOK = [domain hasSuffix:cookieDomain];
+ if (!domainIsOK && [domain hasSuffix:@"localhost"]) {
+ // On Leopard and below, localhost Cookies always come back
+ // with a domain of localhost.local. On SnowLeopard they come
+ // back as just localhost.
+ domainIsOK = [@".localhost.local" hasSuffix:cookieDomain];
+ }
BOOL pathIsOK = [cookiePath isEqual:@"/"] || [path hasPrefix:cookiePath];
BOOL secureIsOK = (!cookieIsSecure) || [scheme isEqual:@"https"];
diff --git a/Foundation/GTMHTTPFetcherTest.m b/Foundation/GTMHTTPFetcherTest.m
index 3c461e0..a541d1f 100644
--- a/Foundation/GTMHTTPFetcherTest.m
+++ b/Foundation/GTMHTTPFetcherTest.m
@@ -19,6 +19,7 @@
#import "GTMSenTestCase.h"
#import "GTMHTTPFetcher.h"
#import "GTMTestHTTPServer.h"
+#import "GTMUnitTestDevLog.h"
@interface GTMHTTPFetcherTest : GTMTestCase {
// these ivars are checked after fetches, and are reset by resetFetchResponse
@@ -97,7 +98,7 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
- (void)tearDown {
[testServer_ release];
testServer_ = nil;
-
+
[self resetFetchResponse];
[fetchHistory_ release];
@@ -136,24 +137,24 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
responseHeaders = [(NSHTTPURLResponse *)fetchedResponse_ allHeaderFields];
NSString *cookiesSetString = [responseHeaders objectForKey:@"Set-Cookie"];
NSString *cookieExpected = [NSString stringWithFormat:@"TestCookie=%@",
- kValidFileName];
+ kValidFileName];
STAssertEqualObjects(cookiesSetString, cookieExpected, @"Unexpected cookie");
// test properties
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
- @"val1", @"key1", @"val2", @"key2", nil];
+ @"val1", @"key1", @"val2", @"key2", nil];
[fetcher setProperties:dict];
STAssertEqualObjects([fetcher properties], dict, @"properties as dictionary");
STAssertEqualObjects([fetcher propertyForKey:@"key2"], @"val2",
- @"single property");
+ @"single property");
NSDictionary *dict2 = [NSDictionary dictionaryWithObjectsAndKeys:
- @"valx1", @"key1", @"val3", @"key3", nil];
+ @"valx1", @"key1", @"val3", @"key3", nil];
[fetcher setProperty:@"valx1" forKey:@"key1"];
[fetcher setProperty:nil forKey:@"key2"];
[fetcher setProperty:@"val3" forKey:@"key3"];
STAssertEqualObjects([fetcher properties], dict2, @"property changes");
-
+
// make a copy of the fetched data to compare with our next fetch from the
// cache
NSData *originalFetchedData = [[fetchedData_ copy] autorelease];
@@ -161,7 +162,7 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
// Now fetch again so the "If modified since" header will be set (because
// we're calling setFetchHistory: below) and caching ON, and verify that we
// got a good data from the cache, along with a "Not modified" status
-
+
[self resetFetchResponse];
[self doFetchWithURLString:urlString cachingDatedData:YES];
@@ -196,19 +197,19 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
[fetchHistory_ removeAllObjects];
[self doFetchWithURLString:urlString cachingDatedData:NO];
-
+
STAssertEqualObjects(fetchedData_, originalFetchedData,
@"cache data mismatch");
-
+
[self resetFetchResponse];
[self doFetchWithURLString:urlString cachingDatedData:NO];
-
+
STAssertNotNil(fetchedData_, @"");
STAssertEquals([fetchedData_ length], (NSUInteger)0, @"unexpected data");
STAssertEquals(fetchedStatus_, (NSInteger)kGTMHTTPFetcherStatusNotModified,
@"fetching data expected status 304, instead got %d", fetchedStatus_);
STAssertNil(fetcherError_, @"unexpected error: %@", fetcherError_);
-
+
}
- (void)testBogusFetch {
@@ -221,29 +222,29 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
if (fetchedStatus_ == kServiceUnavailableStatus) {
// some proxies give a "service unavailable" error for bogus fetches
} else {
-
+
if (fetchedData_) {
NSString *str = [[[NSString alloc] initWithData:fetchedData_
encoding:NSUTF8StringEncoding] autorelease];
STAssertNil(fetchedData_, @"fetched unexpected data: %@", str);
}
-
+
STAssertNotNil(fetcherError_, @"failed to receive fetching error");
STAssertEquals(fetchedStatus_, (NSInteger)0,
@"fetching data expected no status from no response, instead got %d",
fetchedStatus_);
}
-
+
// fetch with a specific status code from our http server
[self resetFetchResponse];
-
+
NSString *invalidWebPageFile =
[kValidFileName stringByAppendingString:@"?status=400"];
NSString *statusUrlString =
[self fileURLStringToTestFileName:invalidWebPageFile];
-
+
[self doFetchWithURLString:statusUrlString cachingDatedData:NO];
-
+
STAssertNotNil(fetchedData_, @"fetch lacked data with error info");
STAssertNil(fetcherError_, @"expected bad status but got an error");
STAssertEquals(fetchedStatus_, (NSInteger)400,
@@ -258,7 +259,7 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
SEL countRetriesSel = @selector(countRetriesFetcher:willRetry:forError:);
SEL fixRequestSel = @selector(fixRequestFetcher:willRetry:forError:);
-
+
//
// test: retry until timeout, then expect failure with status message
//
@@ -310,6 +311,44 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
STAssertEquals([fetcher retryCount], 1U, @"retry count unexpected");
}
+- (void)testNilFetch {
+ GTMHTTPFetcher *fetcher = [[GTMHTTPFetcher alloc] init];
+ [GTMUnitTestDevLog expectString:@"beginFetchWithDelegate requires a request"];
+ BOOL wasGood = [fetcher beginFetchWithDelegate:nil
+ didFinishSelector:NULL
+ didFailSelector:NULL];
+ STAssertFalse(wasGood, nil);
+}
+
+- (void)testCookies {
+ // This is checking part one of
+ // rdar://6293862 NSHTTPCookie cookieWithProperties doesn't work with
+ // NSHTTPCookieOriginURL key
+ NSString *urlString = @"http://www.apple.com/index.html";
+ NSURL *url = [NSURL URLWithString:@"http://www.apple.com/index.html"];
+
+ NSDictionary *properties = [NSDictionary dictionaryWithObjectsAndKeys:
+ url, NSHTTPCookieOriginURL,
+ @"testCookies", NSHTTPCookieName,
+ @"1", NSHTTPCookieValue,
+ nil];
+ NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:properties];
+
+ STAssertNil(cookie, nil);
+
+ // This is checking part two of
+ // rdar://6293862 NSHTTPCookie cookieWithProperties doesn't work with
+ // NSHTTPCookieOriginURL key
+ properties = [NSDictionary dictionaryWithObjectsAndKeys:
+ urlString, NSHTTPCookieOriginURL,
+ @"testCookies", NSHTTPCookieName,
+ @"1", NSHTTPCookieValue,
+ nil];
+ cookie = [NSHTTPCookie cookieWithProperties:properties];
+
+ STAssertNil(cookie, nil);
+}
+
#pragma mark -
- (GTMHTTPFetcher *)doFetchWithURLString:(NSString *)urlString
@@ -327,7 +366,7 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
retrySelector:(SEL)retrySel
maxRetryInterval:(NSTimeInterval)maxRetryInterval
userData:(id)userData {
-
+
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *req = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringCacheData
@@ -387,7 +426,7 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
// return a localhost:port URL for the test file
NSString *urlString = [NSString stringWithFormat:@"http://localhost:%d/%@",
- [testServer_ port], name];
+ [testServer_ port], name];
// we exclude the "?status=" that would indicate that the URL
// should cause a retryable error
diff --git a/Foundation/GTMNSAppleEventDescriptor+Foundation.m b/Foundation/GTMNSAppleEventDescriptor+Foundation.m
index deb375f..14f256d 100644
--- a/Foundation/GTMNSAppleEventDescriptor+Foundation.m
+++ b/Foundation/GTMNSAppleEventDescriptor+Foundation.m
@@ -507,13 +507,12 @@ static NSMutableDictionary *gTypeMap = nil;
BOOL isGood = YES;
AppleEvent replyEvent = { typeNull, NULL };
OSStatus err = AESendMessage([self aeDesc], &replyEvent, mode, timeout * 60);
+ NSAppleEventDescriptor *replyDesc
+ = [[[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&replyEvent] autorelease];
if (err) {
isGood = NO;
_GTMDevLog(@"Unable to send message: %@ %d", self, err);
- replyEvent.descriptorType = typeNull;
- replyEvent.dataHandle = NULL;
}
- NSAppleEventDescriptor *replyDesc = [[[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&replyEvent] autorelease];
if (isGood) {
NSAppleEventDescriptor *errorDesc = [replyDesc descriptorForKeyword:keyErrorNumber];
if (errorDesc && [errorDesc int32Value]) {
diff --git a/Foundation/GTMNSAppleEventDescriptor+Handler.m b/Foundation/GTMNSAppleEventDescriptor+Handler.m
index da0197b..76b6e85 100644
--- a/Foundation/GTMNSAppleEventDescriptor+Handler.m
+++ b/Foundation/GTMNSAppleEventDescriptor+Handler.m
@@ -22,7 +22,7 @@
#import <Carbon/Carbon.h>
@implementation NSAppleEventDescriptor (GTMAppleEventDescriptorHandlerAdditions)
-GTM_METHOD_CHECK(NSProcessInfo, gtm_appleEventDescriptor); // COV_NF_LINE
+GTM_METHOD_CHECK(NSProcessInfo, gtm_appleEventDescriptor);
+ (id)gtm_descriptorWithPositionalHandler:(NSString*)handler
parametersArray:(NSArray*)params {
diff --git a/Foundation/GTMNSAppleScript+Handler.h b/Foundation/GTMNSAppleScript+Handler.h
index 2c38f36..e63eaee 100644
--- a/Foundation/GTMNSAppleScript+Handler.h
+++ b/Foundation/GTMNSAppleScript+Handler.h
@@ -21,7 +21,7 @@
// :::WARNING::: NSAppleScript and Garbage Collect (GC)
//
-// As of 10.5.4 (and below) Apple has bugs in NSAppleScript when running with
+// As of 10.5.5 (and below) Apple has bugs in NSAppleScript when running with
// GC; ie-things crash that have nothing to do w/ this or your code. See
// http://rails.wincent.com/issues/640 for a good amount of detail about the
// problems and simple cases that show it.
diff --git a/Foundation/GTMNSAppleScript+Handler.m b/Foundation/GTMNSAppleScript+Handler.m
index ec6f5d0..592aca6 100644
--- a/Foundation/GTMNSAppleScript+Handler.m
+++ b/Foundation/GTMNSAppleScript+Handler.m
@@ -22,6 +22,7 @@
#import "GTMNSAppleEventDescriptor+Handler.h"
#import "GTMFourCharCode.h"
#import "GTMMethodCheck.h"
+#import "GTMDebugThreadValidation.h"
// Some private methods that we need to call
@interface NSAppleScript (NSPrivate)
@@ -70,9 +71,9 @@
@end
@implementation NSAppleScript(GTMAppleScriptHandlerAdditions)
-GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_descriptorWithPositionalHandler:parametersArray:); // COV_NF_LINE
-GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_descriptorWithLabeledHandler:labels:parameters:count:); // COV_NF_LINE
-GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:); // COV_NF_LINE
+GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_descriptorWithPositionalHandler:parametersArray:);
+GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_descriptorWithLabeledHandler:labels:parameters:count:);
+GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
+ (void)load {
DescType types[] = {
@@ -104,6 +105,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
- (NSAppleEventDescriptor *)gtm_executeAppleEvent:(NSAppleEventDescriptor *)event
error:(NSDictionary **)error {
+ GTMAssertRunningOnMainThread();
if (![self isCompiled]) {
if (![self compileAndReturnError:error]) {
return nil;
@@ -225,7 +227,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
desc = [[[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&result]
autorelease];
} else {
- _GTMDevLog(@"Unable to coerce script %d", error); // COV_NF_LINE
+ _GTMDevLog(@"Unable to coerce script %d", error);
}
return desc;
}
@@ -247,7 +249,8 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
- (void)forwardInvocation:(NSInvocation *)invocation {
SEL sel = [invocation selector];
- NSMutableString *handlerName = [NSStringFromSelector(sel) mutableCopy];
+ NSMutableString *handlerName
+ = [[NSStringFromSelector(sel) mutableCopy] autorelease];
NSUInteger handlerOrigLength = [handlerName length];
[handlerName replaceOccurrencesOfString:@":"
withString:@""
@@ -285,6 +288,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
}
- (NSAppleEventDescriptor*)gtm_valueDescriptorForProperty:(id)property {
+ GTMAssertRunningOnMainThread();
OSAError error = paramErr;
NSAppleEventDescriptor *desc = nil;
NSAppleEventDescriptor *propertyName
@@ -335,6 +339,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
}
- (NSSet*)gtm_scriptHandlers {
+ GTMAssertRunningOnMainThread();
AEDescList names = { typeNull, NULL };
NSArray *array = nil;
ComponentInstance component;
@@ -353,6 +358,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
}
- (NSSet*)gtm_scriptProperties {
+ GTMAssertRunningOnMainThread();
AEDescList names = { typeNull, NULL };
NSArray *array = nil;
ComponentInstance component;
@@ -371,6 +377,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
}
- (OSAID)gtm_genericID:(OSAID)osaID forComponent:(ComponentInstance)component {
+ GTMAssertRunningOnMainThread();
ComponentInstance genericComponent = [NSAppleScript _defaultScriptingComponent];
OSAID exactID = osaID;
OSAError error = OSARealToGenericID(genericComponent, &exactID, component);
@@ -383,6 +390,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
- (NSAppleEventDescriptor*)descForScriptID:(OSAID)osaID
component:(ComponentInstance)component {
+ GTMAssertRunningOnMainThread();
NSAppleEventDescriptor *desc = nil;
// If we have a script, return a typeGTMOSAID, otherwise convert it to
// it's default AEDesc using OSACoerceToDesc with typeWildCard.
@@ -422,6 +430,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
}
- (OSAID)gtm_realIDAndComponent:(ComponentInstance*)component {
+ GTMAssertRunningOnMainThread();
if (![self isCompiled]) {
NSDictionary *error;
if (![self compileAndReturnError:&error]) {
diff --git a/Foundation/GTMNSAppleScript+HandlerTest.m b/Foundation/GTMNSAppleScript+HandlerTest.m
index d4bb9bc..102332e 100644
--- a/Foundation/GTMNSAppleScript+HandlerTest.m
+++ b/Foundation/GTMNSAppleScript+HandlerTest.m
@@ -36,11 +36,11 @@
// GTMNSAppleScript+Handler.h for more details, but we disable them to avoid
// the tests failing (crashing) when it's Apple's bug. Please bump the system
// check as appropriate when new systems are tested. Currently broken on
- // 10.5.4 and below. Radar 6126682.
- long major, minor, bugfix;
+ // 10.5.5 and below. Radar 6126682.
+ SInt32 major, minor, bugfix;
[GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugfix];
if (!(GTMIsGarbageCollectionEnabled()
- && major <= 10 && minor <= 5 && bugfix <= 4)) {
+ && major <= 10 && minor <= 5 && bugfix <= 5)) {
[super invokeTest];
} else {
NSLog(@"--- %@ NOT run because of GC incompatibilites ---", [self name]);
@@ -286,6 +286,12 @@
@"testadd",
@"testgetscript",
nil];
+ if ([GTMSystemVersion isBuildEqualTo:kGTMSystemBuild10_6_0_WWDC]) {
+ // Workaround for bug in SnowLeopard
+ // rdar://66688601 OSAGetHandlersNames returns names in camelcase instead
+ // of smallcaps.
+ handlers = [handlers valueForKey:@"lowercaseString"];
+ }
STAssertEqualObjects(handlers, expected, @"Unexpected handlers?");
}
@@ -345,13 +351,19 @@
[GTMFourCharCode fourCharCodeWithFourCharCode:pASWeeks],
[GTMFourCharCode fourCharCodeWithFourCharCode:pTextItemDelimiters],
// Applescript properties should be pASSeconds, but
- // on 10.5.4 it is actually using cSeconds.
+ // on 10.5.4/10.5.5 it is actually using cSeconds.
// Radar 6132696 Applescript root level property is cSeconds
// instead of pASSeconds
[GTMFourCharCode fourCharCodeWithFourCharCode:cSeconds],
[GTMFourCharCode fourCharCodeWithFourCharCode:pASHours],
[GTMFourCharCode fourCharCodeWithFourCharCode:pASTab],
nil];
+ if ([GTMSystemVersion isBuildEqualTo:kGTMSystemBuild10_6_0_WWDC]) {
+ // Workaround for bug in SnowLeopard
+ // rdar://6289077 OSAGetPropertyNames returns names in camelcase instead
+ // of lowercase.
+ properties = [properties valueForKey:@"lowercaseString"];
+ }
STAssertEqualObjects(properties, expected, @"Unexpected properties?");
id value = [script gtm_valueForProperty:@"testScriptProperty"];
STAssertEqualObjects(value, [NSNumber numberWithInt:5], @"bad property?");
diff --git a/Foundation/GTMNSDictionary+URLArguments.m b/Foundation/GTMNSDictionary+URLArguments.m
index 9b3d67e..d67572c 100644
--- a/Foundation/GTMNSDictionary+URLArguments.m
+++ b/Foundation/GTMNSDictionary+URLArguments.m
@@ -22,7 +22,7 @@
@implementation NSDictionary (GTMNSDictionaryURLArgumentsAdditions)
-GTM_METHOD_CHECK(NSString, gtm_stringByEscapingForURLArgument); // COV_NF_LINE
+GTM_METHOD_CHECK(NSString, gtm_stringByEscapingForURLArgument);
- (NSString *)gtm_httpArgumentsString {
NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:[self count]];
diff --git a/Foundation/GTMNSString+XML.m b/Foundation/GTMNSString+XML.m
index 909a8f1..0e16ddb 100644
--- a/Foundation/GTMNSString+XML.m
+++ b/Foundation/GTMNSString+XML.m
@@ -40,7 +40,7 @@ static NSString *gXMLEntityList[] = {
@"&gt;",
};
-FOUNDATION_STATIC_INLINE GTMXMLCharMode XMLModeForUnichar(UniChar c) {
+GTM_INLINE GTMXMLCharMode XMLModeForUnichar(UniChar c) {
// Per XML spec Section 2.2 Characters
// ( http://www.w3.org/TR/REC-xml/#charsets )
diff --git a/Foundation/GTMObjC2Runtime.m b/Foundation/GTMObjC2Runtime.m
index df3c9ca..ba0cb74 100644
--- a/Foundation/GTMObjC2Runtime.m
+++ b/Foundation/GTMObjC2Runtime.m
@@ -108,8 +108,16 @@ IMP method_setImplementation(Method method, IMP imp) {
// because it seems odd that this API won't accept nil for method considering
// all the other apis will accept nil args.
// If this does get fixed, remember to enable the unit tests.
- IMP oldImp = method->method_imp;
- method->method_imp = imp;
+ // This method works differently on SnowLeopard than
+ // on Leopard. If you pass in a nil for IMP on SnowLeopard
+ // it doesn't change anything. On Leopard it will. Since
+ // attempting to change a sel to nil is probably an error
+ // we follow the SnowLeopard way of doing things.
+ IMP oldImp = NULL;
+ if (imp) {
+ oldImp = method->method_imp;
+ method->method_imp = imp;
+ }
return oldImp;
}
diff --git a/Foundation/GTMObjC2RuntimeTest.m b/Foundation/GTMObjC2RuntimeTest.m
index 6fb5bdf..1bc0ee3 100644
--- a/Foundation/GTMObjC2RuntimeTest.m
+++ b/Foundation/GTMObjC2RuntimeTest.m
@@ -18,6 +18,10 @@
#import "GTMObjC2Runtime.h"
#import "GTMSenTestCase.h"
+#import "GTMSystemVersion.h"
+
+
+
#import <string.h>
@protocol GTMObjC2Runtime_TestProtocol
@@ -270,11 +274,6 @@ AT_REQUIRED
}
- (void)test_method_setImplementation {
- // Nil Checks
- // This case intentionally not tested. Passing nil to method_setImplementation
- // on Leopard crashes. It does on Tiger as well.
- // STAssertNULL(method_setImplementation(nil, nil), nil);
-
// Standard use check
GTMObjC2Runtime_TestClass *test = [[GTMObjC2Runtime_TestClass alloc] init];
Method *list = class_copyMethodList(cls_, nil);
@@ -297,12 +296,45 @@ AT_REQUIRED
STAssertNotEquals(oldImp, newImp, nil);
// test nils
- oldImp = method_setImplementation(list[0], nil);
- STAssertNotNULL(oldImp, nil);
-
- newImp = method_setImplementation(list[0], oldImp);
- STAssertNULL(newImp, nil);
-
+ // Apparently it was a bug that we could call setImplementation with a nil
+ // so we now test to make sure that setting to nil works as expected on
+ // all systems.
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ // Built for less then leopard gives us the behaviors we defined...
+ // (doesn't take nil)
+ IMP nullImp = method_setImplementation(list[0], nil);
+ STAssertNULL(nullImp, nil);
+ IMP testImp = method_setImplementation(list[0], newImp);
+ STAssertEquals(testImp, oldImp, nil);
+#else
+ // Built for leopard or later means we get the os runtime behavior...
+ if ([GTMSystemVersion isLeopard]) {
+ // (takes nil)
+ oldImp = method_setImplementation(list[0], nil);
+ STAssertNotNULL(oldImp, nil);
+ newImp = method_setImplementation(list[0], oldImp);
+ STAssertNULL(newImp, nil);
+ } else {
+ // (doesn't take nil)
+ IMP nullImp = method_setImplementation(list[0], nil);
+ STAssertNULL(nullImp, nil);
+ IMP testImp = method_setImplementation(list[0], newImp);
+ STAssertEquals(testImp, oldImp, nil);
+ }
+#endif
+
+ // This case intentionally not tested. Passing nil to method_setImplementation
+ // on Leopard crashes. It does on Tiger as well. Half works on SnowLeopard.
+ // We made our Tiger implementation the same as the SnowLeopard
+ // implementation.
+ // Logged as radar 5572981.
+ if (![GTMSystemVersion isLeopard]) {
+ STAssertNULL(method_setImplementation(nil, nil), nil);
+ }
+ if ([GTMSystemVersion isBuildGreaterThan:kGTMSystemBuild10_6_0_WWDC]) {
+ STAssertNULL(method_setImplementation(nil, newImp), nil);
+ }
+
[test release];
free(list);
}
diff --git a/Foundation/GTMProgressMonitorInputStreamTest.m b/Foundation/GTMProgressMonitorInputStreamTest.m
index 1d0d1aa..69d331a 100644
--- a/Foundation/GTMProgressMonitorInputStreamTest.m
+++ b/Foundation/GTMProgressMonitorInputStreamTest.m
@@ -19,7 +19,7 @@
#import "GTMSenTestCase.h"
#import "GTMProgressMonitorInputStream.h"
#import "GTMUnitTestDevLog.h"
-
+#import "GTMSystemVersion.h"
@interface GTMProgressMonitorInputStreamTest : GTMTestCase
@end
@@ -111,10 +111,15 @@ static const unsigned long long kSourceDataByteCount = (10000*10);
[monStream setDelegate:nil];
STAssertNil([monStream delegate], nil);
- // error (we get unknown error before we open things)
-
- NSError *err = [monStream streamError];
- STAssertEqualObjects([err domain], @"NSUnknownErrorDomain", nil);
+ if (![GTMSystemVersion isBuildEqualTo:kGTMSystemBuild10_6_0_WWDC]) {
+ // error (we get unknown error before we open things)
+ // This was changed on SnowLeopard.
+ // rdar://689714 Calling streamError on unopened stream no longer returns
+ // error
+ // was filed to check this behaviour.
+ NSError *err = [monStream streamError];
+ STAssertEqualObjects([err domain], @"NSUnknownErrorDomain", nil);
+ }
// status and properties
diff --git a/Foundation/GTMRegex.m b/Foundation/GTMRegex.m
index 33c5b25..71d5050 100644
--- a/Foundation/GTMRegex.m
+++ b/Foundation/GTMRegex.m
@@ -444,13 +444,16 @@ static NSString *const kReplacementPattern =
NSString *result = @"internal error";
// size the buffer we need
- size_t len = regerror(errCode, &regexData_, nil, 0);
- char buffer[len];
- // fetch the error
- if (len == regerror(errCode, &regexData_, buffer, len)) {
- NSString *generatedError = [NSString stringWithUTF8String:buffer];
- if (generatedError)
- result = generatedError;
+ size_t len = regerror(errCode, &regexData_, NULL, 0);
+ char *buffer = (char*)malloc(sizeof(char) * len);
+ if (buffer) {
+ // fetch the error
+ if (len == regerror(errCode, &regexData_, buffer, len)) {
+ NSString *generatedError = [NSString stringWithUTF8String:buffer];
+ if (generatedError)
+ result = generatedError;
+ }
+ free(buffer);
}
return result;
}
diff --git a/Foundation/GTMScriptRunner.m b/Foundation/GTMScriptRunner.m
index 8a76c4a..fce6915 100644
--- a/Foundation/GTMScriptRunner.m
+++ b/Foundation/GTMScriptRunner.m
@@ -72,6 +72,7 @@ static BOOL LaunchNSTaskCatchingExceptions(NSTask *task);
}
- (void)dealloc {
+ [environment_ release];
[interpreter_ release];
[interpreterArgs_ release];
[super dealloc];
diff --git a/Foundation/GTMScriptRunnerTest.m b/Foundation/GTMScriptRunnerTest.m
index 9545045..3d74b9e 100644
--- a/Foundation/GTMScriptRunnerTest.m
+++ b/Foundation/GTMScriptRunnerTest.m
@@ -183,12 +183,13 @@
GTMScriptRunner *sr = [GTMScriptRunner runner];
STAssertNotNil(sr, @"Script runner must not be nil");
NSString *output = nil;
-
+ NSString *error = nil;
STAssertNil([sr environment], @"should start w/ empty env");
- output = [sr run:@"/usr/bin/env | wc -l"];
+ output = [sr run:@"/usr/bin/env | wc -l" standardError:&error];
int numVars = [output intValue];
- STAssertGreaterThan(numVars, 0, @"numVars should be positive");
+ STAssertGreaterThan(numVars, 0,
+ @"numVars should be positive. StdErr %@", error);
// By default the environment is wiped clean, however shells often add a few
// of their own env vars after things have been wiped. For example, sh will
// add about 3 env vars (PWD, _, and SHLVL).
@@ -197,15 +198,14 @@
NSDictionary *newEnv = [NSDictionary dictionaryWithObject:@"bar"
forKey:@"foo"];
[sr setEnvironment:newEnv];
-
- output = [sr run:@"/usr/bin/env | wc -l"];
+ output = [sr run:@"/usr/bin/env | wc -l" standardError:&error];
STAssertEquals([output intValue], numVars + 1,
- @"should have one more env var now");
+ @"should have one more env var now. StdErr %@", error);
[sr setEnvironment:nil];
- output = [sr run:@"/usr/bin/env | wc -l"];
+ output = [sr run:@"/usr/bin/env | wc -l" standardError:&error];
STAssertEquals([output intValue], numVars,
- @"should be back down to %d vars", numVars);
+ @"should be back down to %d vars. StdErr:%@", numVars, error);
NSMutableDictionary *currVars
= [[[[NSProcessInfo processInfo] environment] mutableCopy] autorelease];
@@ -216,9 +216,11 @@
[currVars setObject:@"/usr/bin/env" forKey:@"_"];
[sr setEnvironment:currVars];
- output = [sr run:@"/usr/bin/env | wc -l"];
- STAssertEquals([output intValue], (int)[currVars count],
- @"should be back down to %d vars", numVars);
+ output = [sr run:@"/usr/bin/env | /usr/bin/sort" standardError:&error];
+ NSArray *lineArray = [output componentsSeparatedByString:@"\n"];
+ STAssertEquals([lineArray count], [currVars count],
+ @"StdErr:%@\nCurrentEnvironment:\n%@\nExpected environment:\n%@",
+ error, output, currVars);
}
- (void)testDescription {
diff --git a/Foundation/GTMStackTrace.h b/Foundation/GTMStackTrace.h
index a77ca93..3b6965d 100644
--- a/Foundation/GTMStackTrace.h
+++ b/Foundation/GTMStackTrace.h
@@ -17,6 +17,7 @@
//
#include <CoreFoundation/CoreFoundation.h>
+#import "GTMDefines.h"
#ifdef __cplusplus
extern "C" {
@@ -66,7 +67,7 @@ NSString *GTMStackTrace(void);
// Returns:
// The number of program counters actually added to outPcs.
//
-int GTMGetStackProgramCounters(void *outPcs[], int count);
+NSUInteger GTMGetStackProgramCounters(void *outPcs[], NSUInteger count);
// Returns an array of GTMAddressDescriptors from the current thread's stack.
// *** You should probably use GTMStackTrace() instead of this function ***
@@ -84,8 +85,8 @@ int GTMGetStackProgramCounters(void *outPcs[], int count);
// Returns:
// The number of program counters actually added to outPcs.
//
-int GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
- int count);
+NSUInteger GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
+ NSUInteger count);
#ifdef __cplusplus
}
#endif
diff --git a/Foundation/GTMStackTrace.m b/Foundation/GTMStackTrace.m
index a7198dc..8a14bcf 100644
--- a/Foundation/GTMStackTrace.m
+++ b/Foundation/GTMStackTrace.m
@@ -42,7 +42,7 @@ struct GTMClassDescription {
#pragma mark Private utility functions
-static struct GTMClassDescription *GTMClassDescriptions(int *total_count) {
+static struct GTMClassDescription *GTMClassDescriptions(NSUInteger *total_count) {
int class_count = objc_getClassList(nil, 0);
struct GTMClassDescription *class_descs
= calloc(class_count, sizeof(struct GTMClassDescription));
@@ -74,9 +74,9 @@ static struct GTMClassDescription *GTMClassDescriptions(int *total_count) {
}
static void GTMFreeClassDescriptions(struct GTMClassDescription *class_descs,
- int count) {
- if (!class_descs || count < 0) return;
- for (int i = 0; i < count; ++i) {
+ NSUInteger count) {
+ if (!class_descs) return;
+ for (NSUInteger i = 0; i < count; ++i) {
if (class_descs[i].instance_methods) {
free(class_descs[i].instance_methods);
}
@@ -95,7 +95,7 @@ static void GTMFreeClassDescriptions(struct GTMClassDescription *class_descs,
// great on i386, but PPC requires a little more work because the PC (or link
// register) isn't always stored on the stack.
//
-int GTMGetStackProgramCounters(void *outPcs[], int count) {
+NSUInteger GTMGetStackProgramCounters(void *outPcs[], NSUInteger count) {
if (!outPcs || (count < 1)) return 0;
struct GTMStackFrame *fp;
@@ -108,7 +108,7 @@ int GTMGetStackProgramCounters(void *outPcs[], int count) {
#error architecture not supported
#endif
- int level = 0;
+ NSUInteger level = 0;
while (level < count) {
if (fp == NULL) {
level--;
@@ -122,15 +122,15 @@ int GTMGetStackProgramCounters(void *outPcs[], int count) {
return level;
}
-int GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
- int count) {
- if (count < 1) return 0;
+NSUInteger GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
+ NSUInteger count) {
+ if (count < 1 || !outDescs) return 0;
void **pcs = calloc(count, sizeof(void*));
if (!pcs) return 0;
- int newSize = GTMGetStackProgramCounters(pcs, count);
- int class_desc_count;
+ NSUInteger newSize = GTMGetStackProgramCounters(pcs, count);
+ NSUInteger class_desc_count;
// Get our obj-c class descriptions. This is expensive, so we do it once
// at the top. We go through this because dladdr doesn't work with
@@ -139,7 +139,7 @@ int GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
= GTMClassDescriptions(&class_desc_count);
// Iterate through the stack.
- for (int i = 0; i < newSize; ++i) {
+ for (NSUInteger i = 0; i < newSize; ++i) {
const char *class_name = NULL;
Boolean is_class_method = FALSE;
size_t smallest_diff = SIZE_MAX;
@@ -147,9 +147,9 @@ int GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
currDesc->address = pcs[i];
Method best_method = NULL;
// Iterate through all the classes we know of.
- for (int j = 0; j < class_desc_count; ++j) {
+ for (NSUInteger j = 0; j < class_desc_count; ++j) {
// First check the class methods.
- for (unsigned int k = 0; k < class_descs[j].class_method_count; ++k) {
+ for (NSUInteger k = 0; k < class_descs[j].class_method_count; ++k) {
IMP imp = method_getImplementation(class_descs[j].class_methods[k]);
if (imp <= (IMP)currDesc->address) {
size_t diff = (size_t)currDesc->address - (size_t)imp;
@@ -162,7 +162,7 @@ int GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
}
}
// Then check the instance methods.
- for (unsigned int k = 0; k < class_descs[j].instance_method_count; ++k) {
+ for (NSUInteger k = 0; k < class_descs[j].instance_method_count; ++k) {
IMP imp = method_getImplementation(class_descs[j].instance_methods[k]);
if (imp <= (IMP)currDesc->address) {
size_t diff = (size_t)currDesc->address - (size_t)imp;
@@ -194,6 +194,7 @@ int GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
currDesc->filename = info.dli_fname;
}
GTMFreeClassDescriptions(class_descs, class_desc_count);
+ free(pcs);
return newSize;
}
@@ -201,17 +202,16 @@ NSString *GTMStackTrace(void) {
// The maximum number of stack frames that we will walk. We limit this so
// that super-duper recursive functions (or bugs) don't send us for an
// infinite loop.
- const int kMaxStackTraceDepth = 100;
- struct GTMAddressDescriptor descs[kMaxStackTraceDepth];
- int depth = kMaxStackTraceDepth;
+ struct GTMAddressDescriptor descs[100];
+ size_t depth = sizeof(descs) / sizeof(struct GTMAddressDescriptor);
depth = GTMGetStackAddressDescriptors(descs, depth);
NSMutableString *trace = [NSMutableString string];
// Start at the second item so that GTMStackTrace and it's utility calls (of
// which there is currently 1) is not included in the output.
- const int kTracesToStrip = 2;
- for (int i = kTracesToStrip; i < depth; i++) {
+ const size_t kTracesToStrip = 2;
+ for (size_t i = kTracesToStrip; i < depth; i++) {
if (descs[i].class_name) {
[trace appendFormat:@"#%-2d 0x%08lx %s[%s %s] (%s)\n",
i - kTracesToStrip, descs[i].address,
diff --git a/Foundation/GTMStackTraceTest.m b/Foundation/GTMStackTraceTest.m
index dd92fe9..dc5ea57 100644
--- a/Foundation/GTMStackTraceTest.m
+++ b/Foundation/GTMStackTraceTest.m
@@ -47,11 +47,12 @@
- (void)testProgramCountersBasic {
void *pcs[10];
- int depth = 10;
+ NSUInteger depth = 10;
depth = GTMGetStackProgramCounters(pcs, depth);
- STAssertGreaterThan(depth, 3, @"stack trace must have > 3 lines");
- STAssertLessThanOrEqual(depth, 10, @"stack trace must have < 10 lines");
+ STAssertGreaterThan(depth, (NSUInteger)3, @"stack trace must have > 3 lines");
+ STAssertLessThanOrEqual(depth, (NSUInteger)10,
+ @"stack trace must have < 10 lines");
// pcs is an array of program counters from the stack. pcs[0] should match
// the call into GTMGetStackProgramCounters, which is tough for us to check.
@@ -63,19 +64,19 @@
- (void)testProgramCountersMore {
void *pcs0[0];
- int depth0 = 0;
+ NSUInteger depth0 = 0;
depth0 = GTMGetStackProgramCounters(pcs0, depth0);
- STAssertEquals(depth0, 0, @"stack trace must have 0 lines");
+ STAssertEquals(depth0, (NSUInteger)0, @"stack trace must have 0 lines");
void *pcs1[1];
- int depth1 = 1;
+ NSUInteger depth1 = 1;
depth1 = GTMGetStackProgramCounters(pcs1, depth1);
- STAssertEquals(depth1, 1, @"stack trace must have 1 lines");
+ STAssertEquals(depth1, (NSUInteger)1, @"stack trace must have 1 lines");
void *pcs2[2];
- int depth2 = 2;
+ NSUInteger depth2 = 2;
depth2 = GTMGetStackProgramCounters(pcs2, depth2);
- STAssertEquals(depth2, 2, @"stack trace must have 2 lines");
+ STAssertEquals(depth2, (NSUInteger)2, @"stack trace must have 2 lines");
void *current_pc = __builtin_return_address(0);
STAssertEquals(pcs2[1], current_pc, @"pcs[1] should equal the current PC");
}
diff --git a/Foundation/GTMSystemVersion.h b/Foundation/GTMSystemVersion.h
index 0f19596..959d2af 100644
--- a/Foundation/GTMSystemVersion.h
+++ b/Foundation/GTMSystemVersion.h
@@ -23,7 +23,20 @@
@interface GTMSystemVersion : NSObject
// Returns the current system version major.minor.bugFix
-+ (void)getMajor:(long*)major minor:(long*)minor bugFix:(long*)bugFix;
++ (void)getMajor:(SInt32*)major minor:(SInt32*)minor bugFix:(SInt32*)bugFix;
+
+// Returns the build number of the OS. Useful when looking for bug fixes
+// in new OSes which all have a set system version.
+// eg 10.5.5's build number is 9F33. Easy way to check the build number
+// is to choose "About this Mac" from the Apple menu and click on the version
+// number.
++ (NSString*)build;
+
++ (BOOL)isBuildLessThan:(NSString*)build;
++ (BOOL)isBuildLessThanOrEqualTo:(NSString*)build;
++ (BOOL)isBuildGreaterThan:(NSString*)build;
++ (BOOL)isBuildGreaterThanOrEqualTo:(NSString*)build;
++ (BOOL)isBuildEqualTo:(NSString *)build;
#if GTM_MACOS_SDK
// Returns YES if running on 10.3, NO otherwise.
@@ -35,6 +48,9 @@
// Returns YES if running on 10.5, NO otherwise.
+ (BOOL)isLeopard;
+// Returns YES if running on 10.6, NO otherwise.
++ (BOOL)isSnowLeopard;
+
// Returns a YES/NO if the system is 10.3 or better
+ (BOOL)isPantherOrGreater;
@@ -43,6 +59,27 @@
// Returns a YES/NO if the system is 10.5 or better
+ (BOOL)isLeopardOrGreater;
+
+// Returns a YES/NO if the system is 10.6 or better
++ (BOOL)isSnowLeopardOrGreater;
#endif // GTM_MACOS_SDK
+// Returns one of the achitecture strings below. Note that this is the
+// architecture that we are currently running as, not the hardware architecture.
++ (NSString *)runtimeArchitecture;
@end
+
+// Architecture Strings
+// TODO: Should probably break iPhone up into iPhone_ARM and iPhone_Simulator
+// but haven't found a need yet.
+extern NSString *const kGTMArch_iPhone;
+extern NSString *const kGTMArch_ppc;
+extern NSString *const kGTMArch_ppc64;
+extern NSString *const kGTMArch_x86_64;
+extern NSString *const kGTMArch_i386;
+
+// System Build Number constants
+extern NSString *const kGTMSystemBuild10_5_5;
+extern NSString *const kGTMSystemBuild10_6_0_WWDC;
+
+
diff --git a/Foundation/GTMSystemVersion.m b/Foundation/GTMSystemVersion.m
index da767ae..868f6b8 100644
--- a/Foundation/GTMSystemVersion.m
+++ b/Foundation/GTMSystemVersion.m
@@ -17,6 +17,7 @@
//
#import "GTMSystemVersion.h"
+#import "GTMGarbageCollection.h"
#if GTM_MACOS_SDK
#import <Carbon/Carbon.h>
#endif
@@ -24,6 +25,18 @@
static SInt32 sGTMSystemVersionMajor = 0;
static SInt32 sGTMSystemVersionMinor = 0;
static SInt32 sGTMSystemVersionBugFix = 0;
+static NSString *sBuild = nil;
+
+NSString *const kGTMArch_iPhone = @"iPhone";
+NSString *const kGTMArch_ppc = @"ppc";
+NSString *const kGTMArch_ppc64 = @"ppc64";
+NSString *const kGTMArch_x86_64 = @"x86_64";
+NSString *const kGTMArch_i386 = @"i386";
+
+static NSString *const kSystemVersionPlistPath = @"/System/Library/CoreServices/SystemVersion.plist";
+
+NSString *const kGTMSystemBuild10_5_5 = @"9F33";
+NSString *const kGTMSystemBuild10_6_0_WWDC = @"10A96";
@implementation GTMSystemVersion
+ (void)initialize {
@@ -51,9 +64,9 @@ static SInt32 sGTMSystemVersionBugFix = 0;
// Note that this code will return x.9.9 for any system rev parts that are
// greater than 9 (i.e., 10.10.10 will be 10.9.9). This shouldn't ever be a
// problem as the code above takes care of 10.4+.
- int msb = (binaryCodedDec & 0x0000F000L) >> 12;
+ SInt32 msb = (binaryCodedDec & 0x0000F000L) >> 12;
msb *= 10;
- int lsb = (binaryCodedDec & 0x00000F00L) >> 8;
+ SInt32 lsb = (binaryCodedDec & 0x00000F00L) >> 8;
sGTMSystemVersionMajor = msb + lsb;
sGTMSystemVersionMinor = (binaryCodedDec & 0x000000F0L) >> 4;
sGTMSystemVersionBugFix = (binaryCodedDec & 0x0000000FL);
@@ -61,14 +74,17 @@ static SInt32 sGTMSystemVersionBugFix = 0;
#else // GTM_MACOS_SDK
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSDictionary *systemVersionPlist = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
+ NSDictionary *systemVersionPlist
+ = [NSDictionary dictionaryWithContentsOfFile:kSystemVersionPlistPath];
NSString *version = [systemVersionPlist objectForKey:@"ProductVersion"];
_GTMDevAssert(version, @"Unable to get version");
NSArray *versionInfo = [version componentsSeparatedByString:@"."];
NSUInteger length = [versionInfo count];
- _GTMDevAssert(length > 1 && length < 4, @"Unparseable version %@", version);
+ _GTMDevAssert(length > 1 && length < 4,
+ @"Unparseable version %@", version);
sGTMSystemVersionMajor = [[versionInfo objectAtIndex:0] intValue];
- _GTMDevAssert(sGTMSystemVersionMajor != 0, @"Unknown version for %@", version);
+ _GTMDevAssert(sGTMSystemVersionMajor != 0,
+ @"Unknown version for %@", version);
sGTMSystemVersionMinor = [[versionInfo objectAtIndex:1] intValue];
if (length == 3) {
sGTMSystemVersionBugFix = [[versionInfo objectAtIndex:2] intValue];
@@ -78,7 +94,7 @@ static SInt32 sGTMSystemVersionBugFix = 0;
}
}
-+ (void)getMajor:(long*)major minor:(long*)minor bugFix:(long*)bugFix {
++ (void)getMajor:(SInt32*)major minor:(SInt32*)minor bugFix:(SInt32*)bugFix {
if (major) {
*major = sGTMSystemVersionMajor;
}
@@ -90,6 +106,57 @@ static SInt32 sGTMSystemVersionBugFix = 0;
}
}
++ (NSString*)build {
+ @synchronized(self) {
+ // Not cached at initialization time because we don't expect "real"
+ // software to want this, and it costs a bit to get at startup.
+ // This will mainly be for unit test cases.
+ if (!sBuild) {
+ NSDictionary *systemVersionPlist
+ = [NSDictionary dictionaryWithContentsOfFile:kSystemVersionPlistPath];
+ sBuild = [[systemVersionPlist objectForKey:@"ProductBuildVersion"] retain];
+ GTMNSMakeUncollectable(sBuild);
+ _GTMDevAssert(sBuild, @"Unable to get build version");
+ }
+ }
+ return sBuild;
+}
+
++ (BOOL)isBuildLessThan:(NSString*)build {
+ NSComparisonResult result
+ = [[self build] compare:build
+ options:NSNumericSearch | NSCaseInsensitiveSearch];
+ return result == NSOrderedAscending;
+}
+
++ (BOOL)isBuildLessThanOrEqualTo:(NSString*)build {
+ NSComparisonResult result
+ = [[self build] compare:build
+ options:NSNumericSearch | NSCaseInsensitiveSearch];
+ return result != NSOrderedDescending;
+}
+
++ (BOOL)isBuildGreaterThan:(NSString*)build {
+ NSComparisonResult result
+ = [[self build] compare:build
+ options:NSNumericSearch | NSCaseInsensitiveSearch];
+ return result == NSOrderedDescending;
+}
+
++ (BOOL)isBuildGreaterThanOrEqualTo:(NSString*)build {
+ NSComparisonResult result
+ = [[self build] compare:build
+ options:NSNumericSearch | NSCaseInsensitiveSearch];
+ return result != NSOrderedAscending;
+}
+
++ (BOOL)isBuildEqualTo:(NSString *)build {
+ NSComparisonResult result
+ = [[self build] compare:build
+ options:NSNumericSearch | NSCaseInsensitiveSearch];
+ return result == NSOrderedSame;
+}
+
#if GTM_MACOS_SDK
+ (BOOL)isPanther {
return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 3;
@@ -103,6 +170,10 @@ static SInt32 sGTMSystemVersionBugFix = 0;
return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 5;
}
++ (BOOL)isSnowLeopard {
+ return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 6;
+}
+
+ (BOOL)isPantherOrGreater {
return (sGTMSystemVersionMajor > 10) ||
(sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 3);
@@ -118,6 +189,43 @@ static SInt32 sGTMSystemVersionBugFix = 0;
(sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 5);
}
++ (BOOL)isSnowLeopardOrGreater {
+ return (sGTMSystemVersionMajor > 10) ||
+ (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 6);
+}
+
#endif // GTM_MACOS_SDK
++ (NSString *)runtimeArchitecture {
+ NSString *architecture = nil;
+#if GTM_IPHONE_SDK
+ architecture = kGTMArch_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__
+ architecture = kGTMArch_ppc64;
+#else // !__LP64__
+ architecture = kGTMArch_ppc;
+#endif // __LP64__
+#else // !__POWERPC__
+#if __LP64__
+ architecture = kGTMArch_x86_64;
+#else // !__LP64__
+ architecture = kGTMArch_i386;
+#endif // __LP64__
+#endif // !__POWERPC__
+
+#endif // GTM_IPHONE_SDK
+ return architecture;
+}
+
@end
diff --git a/Foundation/GTMSystemVersionTest.m b/Foundation/GTMSystemVersionTest.m
index e95a33d..b6952da 100644
--- a/Foundation/GTMSystemVersionTest.m
+++ b/Foundation/GTMSystemVersionTest.m
@@ -24,9 +24,9 @@
@implementation GTMSystemVersionTest
- (void)testBasics {
- long major;
- long minor;
- long bugFix;
+ SInt32 major;
+ SInt32 minor;
+ SInt32 bugFix;
[GTMSystemVersion getMajor:nil minor:nil bugFix:nil];
[GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
@@ -37,17 +37,54 @@
BOOL isPanther = (major == 10) && (minor == 3);
BOOL isTiger = (major == 10) && (minor == 4);
BOOL isLeopard = (major == 10) && (minor == 5);
- BOOL isLater = (major > 10) || ((major == 10) && (minor > 5));
+ BOOL isSnowLeopard = (major == 10) && (minor == 6);
+
+ BOOL isLater = (major > 10) || ((major == 10) && (minor > 6));
STAssertEquals([GTMSystemVersion isPanther], isPanther, nil);
STAssertEquals([GTMSystemVersion isPantherOrGreater],
- (BOOL)(isPanther || isTiger || isLeopard || isLater), nil);
+ (BOOL)(isPanther || isTiger
+ || isLeopard || isSnowLeopard || isLater), nil);
STAssertEquals([GTMSystemVersion isTiger], isTiger, nil);
STAssertEquals([GTMSystemVersion isTigerOrGreater],
- (BOOL)(isTiger || isLeopard || isLater), nil);
+ (BOOL)(isTiger || isLeopard || isSnowLeopard || isLater), nil);
STAssertEquals([GTMSystemVersion isLeopard], isLeopard, nil);
STAssertEquals([GTMSystemVersion isLeopardOrGreater],
- (BOOL)(isLeopard || isLater), nil);
-#endif
+ (BOOL)(isLeopard || isSnowLeopard || isLater), nil);
+ STAssertEquals([GTMSystemVersion isSnowLeopard], isSnowLeopard, nil);
+ STAssertEquals([GTMSystemVersion isSnowLeopardOrGreater],
+ (BOOL)(isSnowLeopard || isLater), nil);
+#endif
+}
+
+- (void)testRuntimeArchitecture {
+ // Not sure how to test this short of recoding it and verifying.
+ // This at least executes the code for me.
+ STAssertNotNil([GTMSystemVersion runtimeArchitecture], nil);
}
+- (void)testBuild {
+ // Not sure how to test this short of coding up a large fragile table.
+ // This at least executes the code for me.
+ NSString *systemVersion = [GTMSystemVersion build];
+ STAssertNotEquals([systemVersion length], (NSUInteger)0, nil);
+
+ NSString *smallVersion = @"1A00";
+ NSString *largeVersion = @"100Z100";
+ STAssertTrue([GTMSystemVersion isBuildGreaterThan:smallVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildGreaterThan:systemVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildGreaterThan:largeVersion], nil);
+ STAssertTrue([GTMSystemVersion isBuildGreaterThanOrEqualTo:smallVersion], nil);
+ STAssertTrue([GTMSystemVersion isBuildGreaterThanOrEqualTo:systemVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildGreaterThanOrEqualTo:largeVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildEqualTo:smallVersion], nil);
+ STAssertTrue([GTMSystemVersion isBuildEqualTo:systemVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildEqualTo:largeVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildLessThanOrEqualTo:smallVersion], nil);
+ STAssertTrue([GTMSystemVersion isBuildLessThanOrEqualTo:systemVersion], nil);
+ STAssertTrue([GTMSystemVersion isBuildLessThanOrEqualTo:largeVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildLessThan:smallVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildLessThan:systemVersion], nil);
+ STAssertTrue([GTMSystemVersion isBuildLessThan:largeVersion], nil);
+
+}
@end
diff --git a/Foundation/GTMValidatingContainers.h b/Foundation/GTMValidatingContainers.h
index 1b11f1b..e53b541 100644
--- a/Foundation/GTMValidatingContainers.h
+++ b/Foundation/GTMValidatingContainers.h
@@ -33,7 +33,7 @@
// GTMValidatingArray *array = [GTMValidatingArray validatingArrayWithTarget:target
// selector:selector];
// [array addObject:@"foo"]; // Will be good
-// [array addObject:[NSNumber numberWithInt:2]; // Will fail
+// [array addObject:[NSNumber numberWithInt:2]]; // Will fail
//
// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and
// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens
@@ -84,18 +84,19 @@ void _GTMValidateContainerContainsMemberOfClass(id container, Class cls);
void _GTMValidateContainerConformsToProtocol(id container, Protocol *prot);
void _GTMValidateContainerItemsRespondToSelector(id container, SEL sel);
#else
-inline void _GTMValidateContainer(id container, id target, SEL selector) {
+GTM_INLINE void _GTMValidateContainer(id container, id target, SEL selector) {
}
-inline void _GTMValidateContainerContainsKindOfClass(id container, Class cls) {
+GTM_INLINE void _GTMValidateContainerContainsKindOfClass(id container,
+ Class cls) {
}
-inline void _GTMValidateContainerContainsMemberOfClass(id container,
- Class cls) {
+GTM_INLINE void _GTMValidateContainerContainsMemberOfClass(id container,
+ Class cls) {
}
-inline void _GTMValidateContainerConformsToProtocol(id container,
- Protocol *prot) {
+GTM_INLINE void _GTMValidateContainerConformsToProtocol(id container,
+ Protocol *prot) {
}
-inline void _GTMValidateContainerItemsRespondToSelector(id container,
- SEL sel) {
+GTM_INLINE void _GTMValidateContainerItemsRespondToSelector(id container,
+ SEL sel) {
}
#endif
diff --git a/Foundation/GTMValidatingContainers.m b/Foundation/GTMValidatingContainers.m
index f46ba3f..3b31356 100644
--- a/Foundation/GTMValidatingContainers.m
+++ b/Foundation/GTMValidatingContainers.m
@@ -34,10 +34,10 @@
#import <objc/objc-runtime.h>
#endif // GTM_IPHONE_SDK
-static inline BOOL VerifyObjectWithTargetAndSelectorForContainer(id anObject,
- id target,
- SEL selector,
- id container) {
+GTM_INLINE BOOL VerifyObjectWithTargetAndSelectorForContainer(id anObject,
+ id target,
+ SEL selector,
+ id container) {
// We must take care here, since Intel leaves junk in high bytes of return
// register for predicates that return BOOL.
// For details see:
@@ -59,7 +59,7 @@ static inline BOOL VerifyObjectWithTargetAndSelectorForContainer(id anObject,
return isGood;
}
-static inline void VerifySelectorOnTarget(SEL sel, id target) {
+GTM_INLINE void VerifySelectorOnTarget(SEL sel, id target) {
GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(target,
sel,
@encode(BOOL),
@@ -207,7 +207,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
- (id)initValidatingWithCapacity:(NSUInteger)capacity
target:(id)target
selector:(SEL)sel {
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return [[NSMutableArray alloc] initWithCapacity:capacity];
}
#endif // GTM_CONTAINERS_VALIDATE
@@ -282,7 +284,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
- (id)initValidatingWithCapacity:(NSUInteger)capacity
target:(id)target
selector:(SEL)sel {
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return [[NSMutableDictionary alloc] initWithCapacity:capacity];
}
@@ -359,7 +363,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
- (id)initValidatingWithCapacity:(NSUInteger)capacity
target:(id)target
selector:(SEL)sel {
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return [[NSMutableSet alloc] initWithCapacity:capacity];
}
#endif // GTM_CONTAINERS_VALIDATE
@@ -384,7 +390,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
}
return self;
#else // GTM_CONTAINERS_VALIDATE
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return nil;
#endif // GTM_CONTAINERS_VALIDATE
}
@@ -411,7 +419,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
}
return self;
#else // GTM_CONTAINERS_VALIDATE
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return nil;
#endif // GTM_CONTAINERS_VALIDATE
}
@@ -438,7 +448,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
}
return self;
#else // GTM_CONTAINERS_VALIDATE
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return nil;
#endif // GTM_CONTAINERS_VALIDATE
}
@@ -465,7 +477,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
}
return self;
#else // GTM_CONTAINERS_VALIDATE
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return nil;
#endif // GTM_CONTAINERS_VALIDATE
}
diff --git a/GTM.xcodeproj/project.pbxproj b/GTM.xcodeproj/project.pbxproj
index 7f1a92c..017d952 100644
--- a/GTM.xcodeproj/project.pbxproj
+++ b/GTM.xcodeproj/project.pbxproj
@@ -47,6 +47,9 @@
7F3EB3940E5E0A2100A7A75E /* GTMNSImage+ScalingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F3EB3930E5E0A2100A7A75E /* GTMNSImage+ScalingTest.m */; };
7F3EB5540E5F0B0400A7A75E /* GTMUnitTestingImage.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 8BEEA90A0DA7446300894774 /* GTMUnitTestingImage.tiff */; };
7F3EB5870E5F0CBB00A7A75E /* GTMLargeTypeWindowTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B1801A40E2533DB00280961 /* GTMLargeTypeWindowTest.m */; };
+ 84978FBC0EA6A67C00C5DC83 /* GTMSystemVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = F48FE2930D198D24009257D2 /* GTMSystemVersion.m */; };
+ 84B91B8B0EA3CC2E0087500F /* GTMUnitTestingImage.10.6.0.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 84B91B890EA3CC2E0087500F /* GTMUnitTestingImage.10.6.0.tiff */; };
+ 84B91B8C0EA3CC2E0087500F /* GTMUnitTestingWindow.10.6.0.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 84B91B8A0EA3CC2E0087500F /* GTMUnitTestingWindow.10.6.0.tiff */; };
8B1801A20E2533D500280961 /* GTMLargeTypeWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B1801A00E2533D500280961 /* GTMLargeTypeWindow.m */; };
8B1801A30E2533D500280961 /* GTMLargeTypeWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B1801A10E2533D500280961 /* GTMLargeTypeWindow.h */; settings = {ATTRIBUTES = (Public, ); }; };
8B1801AE0E25341B00280961 /* GTMLargeTypeWindowImageTest.gtmUTState in Resources */ = {isa = PBXBuildFile; fileRef = 8B1801A80E25341B00280961 /* GTMLargeTypeWindowImageTest.gtmUTState */; };
@@ -92,7 +95,9 @@
8B61FDC00E4CDB8000FF9C21 /* GTMStackTrace.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B61FDBF0E4CDB8000FF9C21 /* GTMStackTrace.m */; };
8B6F32080DA34A1B0052CA40 /* GTMObjC2RuntimeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B6F32050DA34A1B0052CA40 /* GTMObjC2RuntimeTest.m */; };
8B6F32160DA34C830052CA40 /* GTMMethodCheckTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B6F31F10DA347720052CA40 /* GTMMethodCheckTest.m */; };
- 8B7AD49A0DABBB5800B84F4A /* GTMNSBezierPath+ShadingTest.10.5.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 8B7AD4970DABBB5800B84F4A /* GTMNSBezierPath+ShadingTest.10.5.tiff */; };
+ 8B6F4B630E8856CA00425D9F /* GTMDebugThreadValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B6F4B610E8856CA00425D9F /* GTMDebugThreadValidation.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8B6F4B640E8856CA00425D9F /* GTMDebugThreadValidation.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B6F4B620E8856CA00425D9F /* GTMDebugThreadValidation.m */; };
+ 8B7AD49A0DABBB5800B84F4A /* GTMNSBezierPath+ShadingTest.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 8B7AD4970DABBB5800B84F4A /* GTMNSBezierPath+ShadingTest.tiff */; };
8B7AD49B0DABBB5800B84F4A /* GTMNSBezierPath+CGPathTest.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 8B7AD4980DABBB5800B84F4A /* GTMNSBezierPath+CGPathTest.tiff */; };
8B7AD49C0DABBB5800B84F4A /* GTMNSBezierPath+RoundRectTest.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 8B7AD4990DABBB5800B84F4A /* GTMNSBezierPath+RoundRectTest.tiff */; };
8B7AD4AE0DABBFEE00B84F4A /* GTMUnitTestingBindingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B7AD4AD0DABBFEE00B84F4A /* GTMUnitTestingBindingTest.m */; };
@@ -123,6 +128,7 @@
8BE281B20DEC7E930035B3F8 /* GTMNSAppleEventDescriptor+Foundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B33441F0DBF7A36009FD32C /* GTMNSAppleEventDescriptor+Foundation.h */; settings = {ATTRIBUTES = (Public, ); }; };
8BE2836F0DED0F130035B3F8 /* GTMFourCharCodeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BE2836C0DED0F130035B3F8 /* GTMFourCharCodeTest.m */; };
8BE283730DED13AB0035B3F8 /* GTMFourCharCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BE2836D0DED0F130035B3F8 /* GTMFourCharCode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8BE839AA0E8AF72E00C611B0 /* GTMDebugThreadValidationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BE839A80E8AF72500C611B0 /* GTMDebugThreadValidationTest.m */; };
8BE869730DBE89C100749827 /* GTMNSBezierPath+RoundRectTest.x86_64.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 8BE869720DBE89C100749827 /* GTMNSBezierPath+RoundRectTest.x86_64.tiff */; };
8BEEA90D0DA7446300894774 /* GTMUnitTestingImage.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 8BEEA90A0DA7446300894774 /* GTMUnitTestingImage.tiff */; };
8BEEA90E0DA7446300894774 /* GTMUnitTestingWindow.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 8BEEA90B0DA7446300894774 /* GTMUnitTestingWindow.tiff */; };
@@ -303,6 +309,11 @@
7F3EB38C0E5E09C700A7A75E /* GTMNSImage+Scaling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSImage+Scaling.h"; sourceTree = "<group>"; };
7F3EB38D0E5E09C700A7A75E /* GTMNSImage+Scaling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSImage+Scaling.m"; sourceTree = "<group>"; };
7F3EB3930E5E0A2100A7A75E /* GTMNSImage+ScalingTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSImage+ScalingTest.m"; sourceTree = "<group>"; };
+ 848269C80E9FF4BD006E6D9C /* DebugSnowLeopardOrLater.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugSnowLeopardOrLater.xcconfig; sourceTree = "<group>"; };
+ 848269C90E9FF4BD006E6D9C /* ReleaseSnowLeopardOrLater.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ReleaseSnowLeopardOrLater.xcconfig; sourceTree = "<group>"; };
+ 84B91B890EA3CC2E0087500F /* GTMUnitTestingImage.10.6.0.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GTMUnitTestingImage.10.6.0.tiff; sourceTree = "<group>"; };
+ 84B91B8A0EA3CC2E0087500F /* GTMUnitTestingWindow.10.6.0.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GTMUnitTestingWindow.10.6.0.tiff; sourceTree = "<group>"; };
+ 84D99F360EA661C900C007D5 /* BuildAllSDKs.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = BuildAllSDKs.sh; sourceTree = "<group>"; };
8B1801A00E2533D500280961 /* GTMLargeTypeWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMLargeTypeWindow.m; sourceTree = "<group>"; };
8B1801A10E2533D500280961 /* GTMLargeTypeWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMLargeTypeWindow.h; sourceTree = "<group>"; };
8B1801A40E2533DB00280961 /* GTMLargeTypeWindowTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMLargeTypeWindowTest.m; sourceTree = "<group>"; };
@@ -355,9 +366,11 @@
8B6F32040DA34A1B0052CA40 /* GTMObjC2Runtime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMObjC2Runtime.m; sourceTree = "<group>"; };
8B6F32050DA34A1B0052CA40 /* GTMObjC2RuntimeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMObjC2RuntimeTest.m; sourceTree = "<group>"; };
8B6F32060DA34A1B0052CA40 /* GTMObjC2Runtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMObjC2Runtime.h; sourceTree = "<group>"; };
+ 8B6F4B610E8856CA00425D9F /* GTMDebugThreadValidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMDebugThreadValidation.h; sourceTree = "<group>"; };
+ 8B6F4B620E8856CA00425D9F /* GTMDebugThreadValidation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMDebugThreadValidation.m; sourceTree = "<group>"; };
8B726BD00D91C0860090C251 /* GTMCALayer+UnitTesting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMCALayer+UnitTesting.m"; sourceTree = "<group>"; };
8B726BD10D91C0860090C251 /* GTMCALayer+UnitTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMCALayer+UnitTesting.h"; sourceTree = "<group>"; };
- 8B7AD4970DABBB5800B84F4A /* GTMNSBezierPath+ShadingTest.10.5.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "GTMNSBezierPath+ShadingTest.10.5.tiff"; sourceTree = "<group>"; };
+ 8B7AD4970DABBB5800B84F4A /* GTMNSBezierPath+ShadingTest.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "GTMNSBezierPath+ShadingTest.tiff"; sourceTree = "<group>"; };
8B7AD4980DABBB5800B84F4A /* GTMNSBezierPath+CGPathTest.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "GTMNSBezierPath+CGPathTest.tiff"; sourceTree = "<group>"; };
8B7AD4990DABBB5800B84F4A /* GTMNSBezierPath+RoundRectTest.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "GTMNSBezierPath+RoundRectTest.tiff"; sourceTree = "<group>"; };
8B7AD4AD0DABBFEE00B84F4A /* GTMUnitTestingBindingTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMUnitTestingBindingTest.m; sourceTree = "<group>"; };
@@ -370,6 +383,7 @@
8BE2836B0DED0F130035B3F8 /* GTMFourCharCode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMFourCharCode.m; sourceTree = "<group>"; };
8BE2836C0DED0F130035B3F8 /* GTMFourCharCodeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMFourCharCodeTest.m; sourceTree = "<group>"; };
8BE2836D0DED0F130035B3F8 /* GTMFourCharCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMFourCharCode.h; sourceTree = "<group>"; };
+ 8BE839A80E8AF72500C611B0 /* GTMDebugThreadValidationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMDebugThreadValidationTest.m; sourceTree = "<group>"; };
8BE869720DBE89C100749827 /* GTMNSBezierPath+RoundRectTest.x86_64.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "GTMNSBezierPath+RoundRectTest.x86_64.tiff"; sourceTree = "<group>"; };
8BEEA90A0DA7446300894774 /* GTMUnitTestingImage.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GTMUnitTestingImage.tiff; sourceTree = "<group>"; };
8BEEA90B0DA7446300894774 /* GTMUnitTestingWindow.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GTMUnitTestingWindow.tiff; sourceTree = "<group>"; };
@@ -577,6 +591,7 @@
F48FE23E0D197F70009257D2 /* XcodeConfig */,
F48B91030D94485500D45044 /* TigerGcov */,
0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
+ 84D99F350EA661C900C007D5 /* BuildScripts */,
034768DFFF38A50411DB9C8B /* Products */,
32DBCF5E0370ADEE00C91783 /* GTM_Prefix.pch */,
F42E086E0D199A5B00D5DDE0 /* GTM-Info.plist */,
@@ -600,6 +615,14 @@
name = "External Frameworks and Libraries";
sourceTree = "<group>";
};
+ 84D99F350EA661C900C007D5 /* BuildScripts */ = {
+ isa = PBXGroup;
+ children = (
+ 84D99F360EA661C900C007D5 /* BuildAllSDKs.sh */,
+ );
+ path = BuildScripts;
+ sourceTree = "<group>";
+ };
8B45A2A20DA49C47001148C5 /* GTMUIUnitTestingHarness */ = {
isa = PBXGroup;
children = (
@@ -613,6 +636,8 @@
F435E46C0DC8F23A0069CDE8 /* TestData */ = {
isa = PBXGroup;
children = (
+ 84B91B890EA3CC2E0087500F /* GTMUnitTestingImage.10.6.0.tiff */,
+ 84B91B8A0EA3CC2E0087500F /* GTMUnitTestingWindow.10.6.0.tiff */,
8B45A2DE0DA51A7E001148C5 /* GTMUnitTestingTest.nib */,
8B45A6B90DA67DD5001148C5 /* GTMUnitTestingImage.gtmUTState */,
8B45A5F50DA5EB9F001148C5 /* GTMUnitTestingWindow.gtmUTState */,
@@ -637,7 +662,7 @@
8B7AD4990DABBB5800B84F4A /* GTMNSBezierPath+RoundRectTest.tiff */,
F435DE8A0DC0B7620069CDE8 /* GTMNSBezierPath+RoundRectTest.ppc64.tiff */,
8BE869720DBE89C100749827 /* GTMNSBezierPath+RoundRectTest.x86_64.tiff */,
- 8B7AD4970DABBB5800B84F4A /* GTMNSBezierPath+ShadingTest.10.5.tiff */,
+ 8B7AD4970DABBB5800B84F4A /* GTMNSBezierPath+ShadingTest.tiff */,
);
path = TestData;
sourceTree = "<group>";
@@ -673,6 +698,7 @@
children = (
F48FE27C0D198D0E009257D2 /* GTMDelegatingTableColumn.h */,
F48FE27D0D198D0E009257D2 /* GTMDelegatingTableColumn.m */,
+ 8B58E9940E547EB000A0E02E /* GTMGetURLHandler.m */,
8B1801A10E2533D500280961 /* GTMLargeTypeWindow.h */,
8B1801A00E2533D500280961 /* GTMLargeTypeWindow.m */,
8B1801A40E2533DB00280961 /* GTMLargeTypeWindowTest.m */,
@@ -725,7 +751,6 @@
F48FE27E0D198D0E009257D2 /* GTMGeometryUtils.h */,
F48FE27F0D198D0E009257D2 /* GTMGeometryUtils.m */,
F48FE2800D198D0E009257D2 /* GTMGeometryUtilsTest.m */,
- 8B58E9940E547EB000A0E02E /* GTMGetURLHandler.m */,
F47F1D2D0D4914AD00925B8F /* GTMCalculatedRange.h */,
F47F1D2E0D4914AD00925B8F /* GTMCalculatedRange.m */,
F47F1D2F0D4914AD00925B8F /* GTMCalculatedRangeTest.m */,
@@ -840,8 +865,10 @@
F4CA852B0DAFA92A00B4AB10 /* Project */ = {
isa = PBXGroup;
children = (
+ 848269C80E9FF4BD006E6D9C /* DebugSnowLeopardOrLater.xcconfig */,
F4CA864A0DB3ACB200B4AB10 /* DebugLeopardOrLater.xcconfig */,
F48FE2410D197F9A009257D2 /* DebugTigerOrLater.xcconfig */,
+ 848269C90E9FF4BD006E6D9C /* ReleaseSnowLeopardOrLater.xcconfig */,
F4CA864B0DB3ACB200B4AB10 /* ReleaseLeopardOrLater.xcconfig */,
F48FE2440D197F9A009257D2 /* ReleaseTigerOrLater.xcconfig */,
);
@@ -870,6 +897,9 @@
8B6F31EF0DA347720052CA40 /* GTMMethodCheck.m */,
8B6F31F40DA3489B0052CA40 /* GTMMethodCheck.h */,
8B6F31F10DA347720052CA40 /* GTMMethodCheckTest.m */,
+ 8B6F4B610E8856CA00425D9F /* GTMDebugThreadValidation.h */,
+ 8B6F4B620E8856CA00425D9F /* GTMDebugThreadValidation.m */,
+ 8BE839A80E8AF72500C611B0 /* GTMDebugThreadValidationTest.m */,
);
path = DebugUtils;
sourceTree = "<group>";
@@ -927,6 +957,7 @@
8B1B49180E5F8E2100A08972 /* GTMExceptionalInlines.h in Headers */,
7F3EB38E0E5E09C700A7A75E /* GTMNSImage+Scaling.h in Headers */,
8B3590160E8190FA0041E21C /* GTMTestTimer.h in Headers */,
+ 8B6F4B630E8856CA00425D9F /* GTMDebugThreadValidation.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1099,6 +1130,8 @@
8BEEA90D0DA7446300894774 /* GTMUnitTestingImage.tiff in Resources */,
8BEEA90E0DA7446300894774 /* GTMUnitTestingWindow.tiff in Resources */,
8BEEA90F0DA7446300894774 /* GTMUnitTestingView.tiff in Resources */,
+ 84B91B8B0EA3CC2E0087500F /* GTMUnitTestingImage.10.6.0.tiff in Resources */,
+ 84B91B8C0EA3CC2E0087500F /* GTMUnitTestingWindow.10.6.0.tiff in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1129,7 +1162,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 8B7AD49A0DABBB5800B84F4A /* GTMNSBezierPath+ShadingTest.10.5.tiff in Resources */,
+ 8B7AD49A0DABBB5800B84F4A /* GTMNSBezierPath+ShadingTest.tiff in Resources */,
8B7AD49B0DABBB5800B84F4A /* GTMNSBezierPath+CGPathTest.tiff in Resources */,
8B7AD49C0DABBB5800B84F4A /* GTMNSBezierPath+RoundRectTest.tiff in Resources */,
8BE869730DBE89C100749827 /* GTMNSBezierPath+RoundRectTest.x86_64.tiff in Resources */,
@@ -1216,6 +1249,7 @@
8B7DCBC40DFF0F800017E983 /* GTMMethodCheck.m in Sources */,
8B7DCEF10E002C210017E983 /* GTMDevLogUnitTestingBridge.m in Sources */,
8B4D7A150E40D79200EFEDD8 /* GTMObjC2Runtime.m in Sources */,
+ 84978FBC0EA6A67C00C5DC83 /* GTMSystemVersion.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1259,6 +1293,7 @@
F95803FB0E2FB0A80049A088 /* GTMLoggerRingBufferWriterTest.m in Sources */,
F427EFC40E4023DD00ADD2AA /* GTMProgressMonitorInputStreamTest.m in Sources */,
8B1B49260E5F97C800A08972 /* GTMExceptionalInlinesTest.m in Sources */,
+ 8BE839AA0E8AF72E00C611B0 /* GTMDebugThreadValidationTest.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1308,6 +1343,7 @@
8B58E9950E547EB000A0E02E /* GTMGetURLHandler.m in Sources */,
8B1B49190E5F8E2100A08972 /* GTMExceptionalInlines.m in Sources */,
7F3EB38F0E5E09C700A7A75E /* GTMNSImage+Scaling.m in Sources */,
+ 8B6F4B640E8856CA00425D9F /* GTMDebugThreadValidation.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1405,6 +1441,297 @@
};
name = "TigerOrLater-Release";
};
+ 842575E60E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 848269C80E9FF4BD006E6D9C /* DebugSnowLeopardOrLater.xcconfig */;
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = GTM_Prefix.pch;
+ };
+ name = "SnowLeopardOrLater-Debug";
+ };
+ 842575E70E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F4CA864C0DB3ACD200B4AB10 /* LoadableBundleGCSupported.xcconfig */;
+ buildSettings = {
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_VERSION = A;
+ INFOPLIST_FILE = "GTM-Info.plist";
+ INSTALL_PATH = "@loader_path/../Frameworks";
+ PRODUCT_NAME = GoogleToolboxForMac;
+ };
+ name = "SnowLeopardOrLater-Debug";
+ };
+ 842575E80E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "All UnitTests";
+ };
+ name = "SnowLeopardOrLater-Debug";
+ };
+ 842575E90E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F48FE2420D197F9A009257D2 /* DebugUnittest.xcconfig */;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(value)",
+ "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)",
+ );
+ GCC_ENABLE_OBJC_GC = supported;
+ INFOPLIST_FILE = "UnitTest-Info.plist";
+ PRODUCT_NAME = "UnitTest - AppKit";
+ };
+ name = "SnowLeopardOrLater-Debug";
+ };
+ 842575EA0E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F48FE2420D197F9A009257D2 /* DebugUnittest.xcconfig */;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(value)",
+ "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)",
+ );
+ GCC_ENABLE_OBJC_GC = supported;
+ GTM_NO_DEBUG_FRAMEWORKS = YES;
+ INFOPLIST_FILE = "UnitTest-Info.plist";
+ PRODUCT_NAME = "UnitTest - Foundation";
+ };
+ name = "SnowLeopardOrLater-Debug";
+ };
+ 842575EB0E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F48FE2420D197F9A009257D2 /* DebugUnittest.xcconfig */;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(value)",
+ "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)",
+ );
+ GCC_ENABLE_OBJC_GC = supported;
+ INFOPLIST_FILE = "UnitTest-Info.plist";
+ PRODUCT_NAME = "UnitTest - UnitTesting";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GTMUIUnitTestingHarness.app/Contents/MacOS/GTMUIUnitTestingHarness";
+ };
+ name = "SnowLeopardOrLater-Debug";
+ };
+ 842575EC0E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_ENABLE_OBJC_GC = supported;
+ INFOPLIST_FILE = UnitTesting/GTMUIUnitTestingHarness/Info.plist;
+ PRODUCT_NAME = GTMUIUnitTestingHarness;
+ };
+ name = "SnowLeopardOrLater-Debug";
+ };
+ 842575ED0E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "Build GTM All SDKs";
+ };
+ name = "SnowLeopardOrLater-Debug";
+ };
+ 842575EE0E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "All UnitTests All SDKs";
+ };
+ name = "SnowLeopardOrLater-Debug";
+ };
+ 842575EF0E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 848269C80E9FF4BD006E6D9C /* DebugSnowLeopardOrLater.xcconfig */;
+ buildSettings = {
+ GCC_GENERATE_TEST_COVERAGE_FILES = YES;
+ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = GTM_Prefix.pch;
+ OTHER_LDFLAGS = "-lgcov";
+ };
+ name = "SnowLeopardOrLater-Debug-gcov";
+ };
+ 842575F00E9FCFB8003E4511 /* SnowLeopardOrLater-Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 848269C90E9FF4BD006E6D9C /* ReleaseSnowLeopardOrLater.xcconfig */;
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = GTM_Prefix.pch;
+ };
+ name = "SnowLeopardOrLater-Release";
+ };
+ 842575F10E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F4CA864C0DB3ACD200B4AB10 /* LoadableBundleGCSupported.xcconfig */;
+ buildSettings = {
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_VERSION = A;
+ INFOPLIST_FILE = "GTM-Info.plist";
+ INSTALL_PATH = "@loader_path/../Frameworks";
+ PRODUCT_NAME = GoogleToolboxForMac;
+ };
+ name = "SnowLeopardOrLater-Debug-gcov";
+ };
+ 842575F20E9FCFB8003E4511 /* SnowLeopardOrLater-Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F4CA864C0DB3ACD200B4AB10 /* LoadableBundleGCSupported.xcconfig */;
+ buildSettings = {
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_VERSION = A;
+ INFOPLIST_FILE = "GTM-Info.plist";
+ INSTALL_PATH = "@loader_path/../Frameworks";
+ PRODUCT_NAME = GoogleToolboxForMac;
+ };
+ name = "SnowLeopardOrLater-Release";
+ };
+ 842575F30E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "All UnitTests";
+ };
+ name = "SnowLeopardOrLater-Debug-gcov";
+ };
+ 842575F40E9FCFB8003E4511 /* SnowLeopardOrLater-Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "All UnitTests";
+ };
+ name = "SnowLeopardOrLater-Release";
+ };
+ 842575F50E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F48FE2420D197F9A009257D2 /* DebugUnittest.xcconfig */;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(value)",
+ "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)",
+ );
+ GCC_ENABLE_OBJC_GC = supported;
+ INFOPLIST_FILE = "UnitTest-Info.plist";
+ PRODUCT_NAME = "UnitTest - AppKit";
+ };
+ name = "SnowLeopardOrLater-Debug-gcov";
+ };
+ 842575F60E9FCFB8003E4511 /* SnowLeopardOrLater-Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F48FE2450D197F9A009257D2 /* ReleaseUnittest.xcconfig */;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(value)",
+ "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)",
+ );
+ GCC_ENABLE_OBJC_GC = supported;
+ INFOPLIST_FILE = "UnitTest-Info.plist";
+ PRODUCT_NAME = "UnitTest - AppKit";
+ };
+ name = "SnowLeopardOrLater-Release";
+ };
+ 842575F70E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F48FE2420D197F9A009257D2 /* DebugUnittest.xcconfig */;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(value)",
+ "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)",
+ );
+ GCC_ENABLE_OBJC_GC = supported;
+ GTM_NO_DEBUG_FRAMEWORKS = YES;
+ INFOPLIST_FILE = "UnitTest-Info.plist";
+ PRODUCT_NAME = "UnitTest - Foundation";
+ };
+ name = "SnowLeopardOrLater-Debug-gcov";
+ };
+ 842575F80E9FCFB8003E4511 /* SnowLeopardOrLater-Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F48FE2450D197F9A009257D2 /* ReleaseUnittest.xcconfig */;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(value)",
+ "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)",
+ );
+ GCC_ENABLE_OBJC_GC = supported;
+ GTM_NO_DEBUG_FRAMEWORKS = YES;
+ INFOPLIST_FILE = "UnitTest-Info.plist";
+ PRODUCT_NAME = "UnitTest - Foundation";
+ };
+ name = "SnowLeopardOrLater-Release";
+ };
+ 842575F90E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F48FE2420D197F9A009257D2 /* DebugUnittest.xcconfig */;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(value)",
+ "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)",
+ );
+ GCC_ENABLE_OBJC_GC = supported;
+ INFOPLIST_FILE = "UnitTest-Info.plist";
+ PRODUCT_NAME = "UnitTest - UnitTesting";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GTMUIUnitTestingHarness.app/Contents/MacOS/GTMUIUnitTestingHarness";
+ };
+ name = "SnowLeopardOrLater-Debug-gcov";
+ };
+ 842575FA0E9FCFB8003E4511 /* SnowLeopardOrLater-Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F48FE2450D197F9A009257D2 /* ReleaseUnittest.xcconfig */;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(value)",
+ "$(DEVELOPER_FRAMEWORKS_DIR_QUOTED)",
+ );
+ GCC_ENABLE_OBJC_GC = supported;
+ INFOPLIST_FILE = "UnitTest-Info.plist";
+ PRODUCT_NAME = "UnitTest - UnitTesting";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GTMUIUnitTestingHarness.app/Contents/MacOS/GTMUIUnitTestingHarness";
+ };
+ name = "SnowLeopardOrLater-Release";
+ };
+ 842575FB0E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_ENABLE_OBJC_GC = supported;
+ INFOPLIST_FILE = UnitTesting/GTMUIUnitTestingHarness/Info.plist;
+ PRODUCT_NAME = GTMUIUnitTestingHarness;
+ };
+ name = "SnowLeopardOrLater-Debug-gcov";
+ };
+ 842575FC0E9FCFB8003E4511 /* SnowLeopardOrLater-Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_ENABLE_OBJC_GC = supported;
+ INFOPLIST_FILE = UnitTesting/GTMUIUnitTestingHarness/Info.plist;
+ PRODUCT_NAME = GTMUIUnitTestingHarness;
+ };
+ name = "SnowLeopardOrLater-Release";
+ };
+ 842575FD0E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "Build GTM All SDKs";
+ };
+ name = "SnowLeopardOrLater-Debug-gcov";
+ };
+ 842575FE0E9FCFB8003E4511 /* SnowLeopardOrLater-Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "Build GTM All SDKs";
+ };
+ name = "SnowLeopardOrLater-Release";
+ };
+ 842575FF0E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "All UnitTests All SDKs";
+ };
+ name = "SnowLeopardOrLater-Debug-gcov";
+ };
+ 842576000E9FCFB8003E4511 /* SnowLeopardOrLater-Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "All UnitTests All SDKs";
+ };
+ name = "SnowLeopardOrLater-Release";
+ };
8B45A02A0DA4696D001148C5 /* TigerOrLater-Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = F48FE2420D197F9A009257D2 /* DebugUnittest.xcconfig */;
@@ -1716,6 +2043,11 @@
isa = XCBuildConfiguration;
baseConfigurationReference = F4CA864A0DB3ACB200B4AB10 /* DebugLeopardOrLater.xcconfig */;
buildSettings = {
+ "ARCHS[sdk=macosx10.5*]" = (
+ i386,
+ x86_64,
+ ppc,
+ );
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = GTM_Prefix.pch;
};
@@ -1798,6 +2130,11 @@
isa = XCBuildConfiguration;
baseConfigurationReference = F4CA864A0DB3ACB200B4AB10 /* DebugLeopardOrLater.xcconfig */;
buildSettings = {
+ "ARCHS[sdk=macosx10.5*]" = (
+ i386,
+ x86_64,
+ ppc,
+ );
GCC_GENERATE_TEST_COVERAGE_FILES = YES;
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
@@ -1883,6 +2220,11 @@
isa = XCBuildConfiguration;
baseConfigurationReference = F4CA864B0DB3ACB200B4AB10 /* ReleaseLeopardOrLater.xcconfig */;
buildSettings = {
+ "ARCHS[sdk=macosx10.5*]" = (
+ i386,
+ x86_64,
+ ppc,
+ );
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = GTM_Prefix.pch;
};
@@ -1973,6 +2315,9 @@
F4CA864F0DB3ACE500B4AB10 /* LeopardOrLater-Debug */,
F4CA865A0DB3AD0300B4AB10 /* LeopardOrLater-Debug-gcov */,
F4CA86610DB3AD0D00B4AB10 /* LeopardOrLater-Release */,
+ 842575E60E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */,
+ 842575EF0E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */,
+ 842575F00E9FCFB8003E4511 /* SnowLeopardOrLater-Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = "TigerOrLater-Release";
@@ -1986,6 +2331,9 @@
F4CA86540DB3ACE500B4AB10 /* LeopardOrLater-Debug */,
F4CA865F0DB3AD0300B4AB10 /* LeopardOrLater-Debug-gcov */,
F4CA86660DB3AD0D00B4AB10 /* LeopardOrLater-Release */,
+ 842575EB0E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */,
+ 842575F90E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */,
+ 842575FA0E9FCFB8003E4511 /* SnowLeopardOrLater-Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = "TigerOrLater-Release";
@@ -1999,6 +2347,9 @@
F4CA86550DB3ACE500B4AB10 /* LeopardOrLater-Debug */,
F4CA86600DB3AD0300B4AB10 /* LeopardOrLater-Debug-gcov */,
F4CA86670DB3AD0D00B4AB10 /* LeopardOrLater-Release */,
+ 842575EC0E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */,
+ 842575FB0E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */,
+ 842575FC0E9FCFB8003E4511 /* SnowLeopardOrLater-Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = "TigerOrLater-Release";
@@ -2012,6 +2363,9 @@
F41A6EE40E02DB4F00788A6C /* LeopardOrLater-Debug */,
F41A6EE50E02DB4F00788A6C /* LeopardOrLater-Debug-gcov */,
F41A6EE60E02DB4F00788A6C /* LeopardOrLater-Release */,
+ 842575ED0E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */,
+ 842575FD0E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */,
+ 842575FE0E9FCFB8003E4511 /* SnowLeopardOrLater-Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = "TigerOrLater-Release";
@@ -2025,6 +2379,9 @@
F41A6EFC0E02DCFC00788A6C /* LeopardOrLater-Debug */,
F41A6EFD0E02DCFC00788A6C /* LeopardOrLater-Debug-gcov */,
F41A6EFE0E02DCFC00788A6C /* LeopardOrLater-Release */,
+ 842575EE0E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */,
+ 842575FF0E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */,
+ 842576000E9FCFB8003E4511 /* SnowLeopardOrLater-Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = "TigerOrLater-Release";
@@ -2038,6 +2395,9 @@
F4CA86530DB3ACE500B4AB10 /* LeopardOrLater-Debug */,
F4CA865E0DB3AD0300B4AB10 /* LeopardOrLater-Debug-gcov */,
F4CA86650DB3AD0D00B4AB10 /* LeopardOrLater-Release */,
+ 842575EA0E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */,
+ 842575F70E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */,
+ 842575F80E9FCFB8003E4511 /* SnowLeopardOrLater-Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = "TigerOrLater-Release";
@@ -2051,6 +2411,9 @@
F4CA86500DB3ACE500B4AB10 /* LeopardOrLater-Debug */,
F4CA865B0DB3AD0300B4AB10 /* LeopardOrLater-Debug-gcov */,
F4CA86620DB3AD0D00B4AB10 /* LeopardOrLater-Release */,
+ 842575E70E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */,
+ 842575F10E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */,
+ 842575F20E9FCFB8003E4511 /* SnowLeopardOrLater-Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = "TigerOrLater-Release";
@@ -2064,6 +2427,9 @@
F4CA86510DB3ACE500B4AB10 /* LeopardOrLater-Debug */,
F4CA865C0DB3AD0300B4AB10 /* LeopardOrLater-Debug-gcov */,
F4CA86630DB3AD0D00B4AB10 /* LeopardOrLater-Release */,
+ 842575E80E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */,
+ 842575F30E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */,
+ 842575F40E9FCFB8003E4511 /* SnowLeopardOrLater-Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = "TigerOrLater-Release";
@@ -2077,6 +2443,9 @@
F4CA86520DB3ACE500B4AB10 /* LeopardOrLater-Debug */,
F4CA865D0DB3AD0300B4AB10 /* LeopardOrLater-Debug-gcov */,
F4CA86640DB3AD0D00B4AB10 /* LeopardOrLater-Release */,
+ 842575E90E9FCFA5003E4511 /* SnowLeopardOrLater-Debug */,
+ 842575F50E9FCFB8003E4511 /* SnowLeopardOrLater-Debug-gcov */,
+ 842575F60E9FCFB8003E4511 /* SnowLeopardOrLater-Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = "TigerOrLater-Release";
diff --git a/GTMDefines.h b/GTMDefines.h
index 0cf7e95..1d1c908 100644
--- a/GTMDefines.h
+++ b/GTMDefines.h
@@ -18,6 +18,13 @@
// ============================================================================
+#include <AvailabilityMacros.h>
+
+#ifndef MAC_OS_X_VERSION_10_6
+// MAC_OS_X_VERSION_10_6 not defined in some earlier SDKs
+#define MAC_OS_X_VERSION_10_6 1060
+#endif
+
// ----------------------------------------------------------------------------
// CPP symbols that can be overridden in a prefix to control how the toolbox
// is compiled.
@@ -132,6 +139,11 @@ extern void _GTMUnitTestDevLog(NSString *format, ...);
#if TARGET_OS_IPHONE // iPhone SDK
// For iPhone specific stuff
#define GTM_IPHONE_SDK 1
+ #if TARGET_IPHONE_SIMULATOR
+ #define GTM_IPHONE_SIMULATOR 1
+ #else
+ #define GTM_IPHONE_DEVICE 1
+ #endif // TARGET_IPHONE_SIMULATOR
#else
// For MacOS specific stuff
#define GTM_MACOS_SDK 1
@@ -171,3 +183,15 @@ extern void _GTMUnitTestDevLog(NSString *format, ...);
#define CGFLOAT_DEFINED 1
#endif // CGFLOAT_DEFINED
#endif // MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+
+
+// Give ourselves a consistent way to do inlines. Apple's macros even use
+// a few different actual definitions, so we're based off of the foundation
+// one.
+#if !defined(GTM_INLINE)
+ #if defined (__GNUC__) && (__GNUC__ == 4)
+ #define GTM_INLINE static __inline__ __attribute__((always_inline))
+ #else
+ #define GTM_INLINE static __inline__
+ #endif
+#endif
diff --git a/GTMiPhone.xcodeproj/project.pbxproj b/GTMiPhone.xcodeproj/project.pbxproj
index f470ec8..aa2bb78 100644
--- a/GTMiPhone.xcodeproj/project.pbxproj
+++ b/GTMiPhone.xcodeproj/project.pbxproj
@@ -71,6 +71,8 @@
8BDA25120E759A6300C9769D /* GTMHTTPFetcherTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B3AA91E0E033624007E31B5 /* GTMHTTPFetcherTest.m */; };
8BDA25130E759A6400C9769D /* GTMHTTPServerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B3AA9210E033624007E31B5 /* GTMHTTPServerTest.m */; };
8BDA25140E759A6500C9769D /* GTMNSData+zlibTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BC047800DAE928A00C2D1CA /* GTMNSData+zlibTest.m */; };
+ 8BE839890E89C74B00C611B0 /* GTMDebugThreadValidation.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BE839870E89C74A00C611B0 /* GTMDebugThreadValidation.m */; };
+ 8BE83A660E8B059A00C611B0 /* GTMDebugThreadValidationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BE83A650E8B059A00C611B0 /* GTMDebugThreadValidationTest.m */; };
F418AF990E7558EC004FB565 /* GTMExceptionalInlines.m in Sources */ = {isa = PBXBuildFile; fileRef = F418AF940E7558DC004FB565 /* GTMExceptionalInlines.m */; };
F418AF9A0E7558EC004FB565 /* GTMExceptionalInlinesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F418AF950E7558DC004FB565 /* GTMExceptionalInlinesTest.m */; };
F418AFA50E7559C7004FB565 /* GTMLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = F418AFA30E7559C7004FB565 /* GTMLogger.m */; };
@@ -182,6 +184,9 @@
8BC04A740DAF145200C2D1CA /* GTMSystemVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMSystemVersion.m; sourceTree = "<group>"; };
8BC04D470DB0088500C2D1CA /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
8BC04DE70DB023D400C2D1CA /* ReleaseNotes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ReleaseNotes.txt; sourceTree = "<group>"; };
+ 8BE839870E89C74A00C611B0 /* GTMDebugThreadValidation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMDebugThreadValidation.m; sourceTree = "<group>"; };
+ 8BE839880E89C74A00C611B0 /* GTMDebugThreadValidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMDebugThreadValidation.h; sourceTree = "<group>"; };
+ 8BE83A650E8B059A00C611B0 /* GTMDebugThreadValidationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMDebugThreadValidationTest.m; sourceTree = "<group>"; };
F418AF6D0E755732004FB565 /* GTMiPhone-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GTMiPhone-Info.plist"; sourceTree = "<group>"; };
F418AF910E755893004FB565 /* xcconfigs-readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "xcconfigs-readme.txt"; sourceTree = "<group>"; };
F418AF930E7558DC004FB565 /* GTMExceptionalInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMExceptionalInlines.h; sourceTree = "<group>"; };
@@ -370,6 +375,9 @@
isa = PBXGroup;
children = (
8BC0479B0DAE928A00C2D1CA /* GTMDebugSelectorValidation.h */,
+ 8BE83A650E8B059A00C611B0 /* GTMDebugThreadValidationTest.m */,
+ 8BE839870E89C74A00C611B0 /* GTMDebugThreadValidation.m */,
+ 8BE839880E89C74A00C611B0 /* GTMDebugThreadValidation.h */,
8BC0479C0DAE928A00C2D1CA /* GTMMethodCheck.h */,
8BC0479D0DAE928A00C2D1CA /* GTMMethodCheck.m */,
8BC0479E0DAE928A00C2D1CA /* GTMMethodCheckTest.m */,
@@ -523,7 +531,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "\"${SRCROOT}/UnitTesting/RunIPhoneUnitTest.sh\"";
+ shellScript = "# Run the unit tests in this test bundle.\n\"${SRCROOT}/UnitTesting/RunIPhoneUnitTest.sh\"\n";
};
/* End PBXShellScriptBuildPhase section */
@@ -586,6 +594,8 @@
8BDA25120E759A6300C9769D /* GTMHTTPFetcherTest.m in Sources */,
8BDA25130E759A6400C9769D /* GTMHTTPServerTest.m in Sources */,
8BDA25140E759A6500C9769D /* GTMNSData+zlibTest.m in Sources */,
+ 8BE839890E89C74B00C611B0 /* GTMDebugThreadValidation.m in Sources */,
+ 8BE83A660E8B059A00C611B0 /* GTMDebugThreadValidationTest.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -605,6 +615,7 @@
buildSettings = {
INFOPLIST_FILE = "GTMiPhone-Info.plist";
PRODUCT_NAME = GTMiPhoneTest;
+ SDKROOT = iphonesimulator2.0;
};
name = Debug;
};
@@ -613,6 +624,7 @@
buildSettings = {
INFOPLIST_FILE = "GTMiPhone-Info.plist";
PRODUCT_NAME = GTMiPhoneTest;
+ SDKROOT = iphonesimulator2.0;
};
name = Release;
};
@@ -620,8 +632,8 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 8BC049850DAEC59100C2D1CA /* DebugiPhone20.xcconfig */;
buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = GTM_Prefix.pch;
- SDKROOT = iphonesimulator2.0;
};
name = "Debug-gcov";
};
@@ -631,6 +643,7 @@
buildSettings = {
INFOPLIST_FILE = "GTMiPhone-Info.plist";
PRODUCT_NAME = GTMiPhoneTest;
+ SDKROOT = iphonesimulator2.0;
};
name = "Debug-gcov";
};
@@ -638,8 +651,8 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 8BC049850DAEC59100C2D1CA /* DebugiPhone20.xcconfig */;
buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = GTM_Prefix.pch;
- SDKROOT = iphonesimulator2.0;
};
name = Debug;
};
@@ -647,8 +660,8 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 8BC049890DAEC59100C2D1CA /* ReleaseiPhone20.xcconfig */;
buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = GTM_Prefix.pch;
- SDKROOT = iphonesimulator2.0;
};
name = Release;
};
diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt
index 220e105..1ffac73 100644
--- a/ReleaseNotes.txt
+++ b/ReleaseNotes.txt
@@ -101,9 +101,6 @@ Changes since 1.5.1
- Added GTMTestTimer.h for doing high fidelity timings.
-- Added leaks checking to iPhone unit test script. It can be controlled by
- the GTM_DISABLE_LEAKS environment variable
-
- Added ability to control using zombies to iPhone unit test script. It can be
controlled by the GTM_DISABLE_ZOMBIES environment variable
@@ -114,6 +111,49 @@ Changes since 1.5.1
- Updated the iPhone xcconfigs to support the different OS versions.
+- GTM_INLINE will make sure a function gets inlined, and provides a consistent
+ way for all GTM code to do it.
+
+- Added GTMDebugThreadValidation to allow you to enforce the fact that your
+ code must run in the main thread in DEBUG builds.
+
+- Updated some internals of the iPhone unittesting so it doesn't double print
+ the test descriptions, file names, or lines numbers of a test failure line.
+ Also includes the test names in the error output.
+
+- Changed the xcconfigs so that know it's easier to set different settings at
+ the different levels and not accidentally overwrite settings set at lower
+ levels in the "settings collapse". Also tightened up warnings significantly.
+
+- Changed how gtm_unitTestExposedBindingsTestValues works. If you have an
+ implementation of gtm_unitTestExposedBindingsTestValues in your own code
+ you will need to update to the new way of calling. See implementations in
+ GTMNSObject+BindingUnitTesting.m for details.
+
+- Added support for grabbing the build number for a particular OS in
+ GTMSystemVersion and easily comparing it to known build numbers, and switched
+ some types from in GTMSystemVersion from "int" to SInt32 to make 64 bit work
+ better.
+
+- Added support for SnowLeopard (10A96). We build cleanly with the 10.6 SDKs and
+ all radar checks were updated accordingly. Build All script was also updated
+ to build on SnowLeopard if you have the SDK available.
+
+- Turned off building ppc64 GTM because the SnowLeopard SDK currently
+ doesn't have ppc64 support, so SenTestCase isn't defined. This makes it
+ impossible to build the ppc64 10.5 config on SnowLeopard. We have left the
+ setting in the xcconfig for those of you who need it, but have disabled
+ it in the GTM project settings.
+
+- Turned on stack smashing protection on the debug builds for all Leopard
+ and above.
+
+- Added ability to easily do leak checking by defining the GTM_ENABLE_LEAKS
+ environment variable. It isn't on by default because several of Apple's
+ frameworks leak. You can work around these false positives by using the
+ GTM_LEAKS_SYMBOLS_TO_IGNORE environment variable. Also if you turn on leaks
+ make sure to turn off zombies by defining the GTM_DISABLE_ZOMBIES variable,
+ otherwise every memory allocation you do will look like a leak.
Release 1.5.1
Changes since 1.5.0
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
diff --git a/XcodeConfig/Project/DebugLeopardOrLater.xcconfig b/XcodeConfig/Project/DebugLeopardOrLater.xcconfig
index 5bbd4a2..b00a6cc 100644
--- a/XcodeConfig/Project/DebugLeopardOrLater.xcconfig
+++ b/XcodeConfig/Project/DebugLeopardOrLater.xcconfig
@@ -33,3 +33,5 @@
// Debug settings
#include "../subconfig/Debug.xcconfig"
+// Merge settings
+#include "../subconfig/GTMMerge.xcconfig"
diff --git a/XcodeConfig/Project/DebugSnowLeopardOrLater.xcconfig b/XcodeConfig/Project/DebugSnowLeopardOrLater.xcconfig
new file mode 100644
index 0000000..a090412
--- /dev/null
+++ b/XcodeConfig/Project/DebugSnowLeopardOrLater.xcconfig
@@ -0,0 +1,37 @@
+//
+// DebugSnowLeopardOrLater.xcconfig
+//
+// Xcode configuration file for building a Debug configuration of a project
+// on SnowLeopard or later.
+//
+// This is a _Configuration_ Xcode config file for use in the "Based on" popup
+// of the project configuration editor. Do _not_ use this as the config base
+// and individual Xcode target, there are other configuration files for that
+// purpose.
+//
+// Copyright 2008 Google Inc.
+//
+// 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
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+// Pull in the general settings
+#include "../subconfig/General.xcconfig"
+
+// SnowLeopard or later
+#include "../subconfig/SnowLeopardOrLater.xcconfig"
+
+// Debug settings
+#include "../subconfig/Debug.xcconfig"
+
+// Merge settings
+#include "../subconfig/GTMMerge.xcconfig"
diff --git a/XcodeConfig/Project/DebugTigerOrLater.xcconfig b/XcodeConfig/Project/DebugTigerOrLater.xcconfig
index b8893ce..34b7b1c 100644
--- a/XcodeConfig/Project/DebugTigerOrLater.xcconfig
+++ b/XcodeConfig/Project/DebugTigerOrLater.xcconfig
@@ -33,3 +33,5 @@
// Debug settings
#include "../subconfig/Debug.xcconfig"
+// Merge settings
+#include "../subconfig/GTMMerge.xcconfig"
diff --git a/XcodeConfig/Project/DebugiPhone20.xcconfig b/XcodeConfig/Project/DebugiPhone20.xcconfig
index 1f08ee4..7424704 100644
--- a/XcodeConfig/Project/DebugiPhone20.xcconfig
+++ b/XcodeConfig/Project/DebugiPhone20.xcconfig
@@ -32,3 +32,6 @@
// Release settings
#include "../subconfig/Debug.xcconfig"
+
+// Merge settings
+#include "../subconfig/GTMMerge.xcconfig"
diff --git a/XcodeConfig/Project/DebugiPhone21.xcconfig b/XcodeConfig/Project/DebugiPhone21.xcconfig
index b718cfa..18c923a 100644
--- a/XcodeConfig/Project/DebugiPhone21.xcconfig
+++ b/XcodeConfig/Project/DebugiPhone21.xcconfig
@@ -32,3 +32,6 @@
// Release settings
#include "../subconfig/Debug.xcconfig"
+
+// Merge settings
+#include "../subconfig/GTMMerge.xcconfig"
diff --git a/XcodeConfig/Project/ReleaseLeopardOrLater.xcconfig b/XcodeConfig/Project/ReleaseLeopardOrLater.xcconfig
index f62b287..31ac835 100644
--- a/XcodeConfig/Project/ReleaseLeopardOrLater.xcconfig
+++ b/XcodeConfig/Project/ReleaseLeopardOrLater.xcconfig
@@ -32,3 +32,6 @@
// Release settings
#include "../subconfig/Release.xcconfig"
+
+// Merge settings
+#include "../subconfig/GTMMerge.xcconfig"
diff --git a/XcodeConfig/Project/ReleaseSnowLeopardOrLater.xcconfig b/XcodeConfig/Project/ReleaseSnowLeopardOrLater.xcconfig
new file mode 100644
index 0000000..0d24069
--- /dev/null
+++ b/XcodeConfig/Project/ReleaseSnowLeopardOrLater.xcconfig
@@ -0,0 +1,37 @@
+//
+// ReleaseSnowLeopardOrLater.xcconfig
+//
+// Xcode configuration file for building a Release configuration of a project
+// on SnowLeopard or later.
+//
+// This is a _Configuration_ Xcode config file for use in the "Based on" popup
+// of the project configuration editor. Do _not_ use this as the config base
+// and individual Xcode target, there are other configuration files for that
+// purpose.
+//
+// Copyright 2008 Google Inc.
+//
+// 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
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+// Pull in the general settings
+#include "../subconfig/General.xcconfig"
+
+// SnowLeopard or later
+#include "../subconfig/SnowLeopardOrLater.xcconfig"
+
+// Release settings
+#include "../subconfig/Release.xcconfig"
+
+// Merge settings
+#include "../subconfig/GTMMerge.xcconfig"
diff --git a/XcodeConfig/Project/ReleaseTigerOrLater.xcconfig b/XcodeConfig/Project/ReleaseTigerOrLater.xcconfig
index d604d88..9301912 100644
--- a/XcodeConfig/Project/ReleaseTigerOrLater.xcconfig
+++ b/XcodeConfig/Project/ReleaseTigerOrLater.xcconfig
@@ -32,3 +32,6 @@
// Release settings
#include "../subconfig/Release.xcconfig"
+
+// Merge settings
+#include "../subconfig/GTMMerge.xcconfig"
diff --git a/XcodeConfig/Project/ReleaseiPhone20.xcconfig b/XcodeConfig/Project/ReleaseiPhone20.xcconfig
index 16895c5..8d31ead 100644
--- a/XcodeConfig/Project/ReleaseiPhone20.xcconfig
+++ b/XcodeConfig/Project/ReleaseiPhone20.xcconfig
@@ -32,3 +32,6 @@
// Release settings
#include "../subconfig/Release.xcconfig"
+
+// Merge settings
+#include "../subconfig/GTMMerge.xcconfig"
diff --git a/XcodeConfig/Project/ReleaseiPhone21.xcconfig b/XcodeConfig/Project/ReleaseiPhone21.xcconfig
index 4ea90d6..8a9a0c3 100644
--- a/XcodeConfig/Project/ReleaseiPhone21.xcconfig
+++ b/XcodeConfig/Project/ReleaseiPhone21.xcconfig
@@ -32,3 +32,6 @@
// Release settings
#include "../subconfig/Release.xcconfig"
+
+// Merge settings
+#include "../subconfig/GTMMerge.xcconfig"
diff --git a/XcodeConfig/subconfig/Debug.xcconfig b/XcodeConfig/subconfig/Debug.xcconfig
index a6290c3..d8fbd1c 100644
--- a/XcodeConfig/subconfig/Debug.xcconfig
+++ b/XcodeConfig/subconfig/Debug.xcconfig
@@ -30,8 +30,14 @@ DEAD_CODE_STRIPPING = NO
// Debug symbols should be on obviously
GCC_GENERATE_DEBUGGING_SYMBOLS = YES
-// Define the DEBUG macro in all debug builds
-OTHER_CFLAGS = $(OTHER_CFLAGS) -DDEBUG=1
+// Turn off warnings about uninitialized autos
+// can only be done when GCC_OPTIMIZATION_LEVEL is actually optimizing
+GCC_WARN_UNINITIALIZED_AUTOS = NO
// Turns on special C++ STL checks to "encourage" good STL use
-GCC_PREPROCESSOR_DEFINITIONS = $(GCC_PREPROCESSOR_DEFINITIONS) _GLIBCXX_DEBUG_PEDANTIC _GLIBCXX_DEBUG _GLIBCPP_CONCEPT_CHECKS
+GTM_CONFIGURATION_GCC_PREPROCESSOR_DEFINITIONS = _GLIBCXX_DEBUG_PEDANTIC _GLIBCXX_DEBUG _GLIBCPP_CONCEPT_CHECKS DEBUG=1
+
+// Turns on stack protection on debug builds for Leopard and above
+GTM_CONFIGURATION_OTHER_CFLAGS = -fstack-protector -fstack-protector-all
+// Stack protection doesn't exist on Tiger
+GTM_CONFIGURATION_OTHER_CFLAGS[sdk=macosx10.4*] =
diff --git a/XcodeConfig/subconfig/GTMMerge.xcconfig b/XcodeConfig/subconfig/GTMMerge.xcconfig
new file mode 100644
index 0000000..33d3e70
--- /dev/null
+++ b/XcodeConfig/subconfig/GTMMerge.xcconfig
@@ -0,0 +1,35 @@
+//
+// GTMMerge.xcconfig
+//
+// Xcode configuration file that merges other xcconfig settings.
+//
+// Copyright 2008 Google Inc.
+//
+// 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
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+// Xcode doesn't allow you to "inherit" settings with includes so you always
+// end up overriding settings accidentally. To avoid this, we instead
+// allow you to define settings at different levels
+// (GENERAL, PLATFORM (iPhone/Mac), CONFIGURATION (Release/Debug) and we merge
+// those together here.
+// We DO NOT inherit OTHER_CPLUSPLUSFLAGS because OTHER_CPLUSPLUSFLAGS by default
+// takes on OTHER_CFLAGS settings, and we don't want those applied to our
+// C++ files. OTHER_CFLAGS is the only way to set C specific settings on our
+// C files that we don't want to have applied to our C++ files such as
+// -Wold-style-definition
+WARNING_CFLAGS = $(inherited) $(GTM_GENERAL_WARNING_CFLAGS) $(GTM_PLATFORM_WARNING_CFLAGS) $(GTM_CONFIGURATION_WARNING_CFLAGS)
+OTHER_CFLAGS = $(inherited) $(GTM_GENERAL_OTHER_CFLAGS) $(GTM_PLATFORM_OTHER_CFLAGS) $(GTM_CONFIGURATION_OTHER_CFLAGS)
+OTHER_CPLUSPLUSFLAGS = $(GTM_GENERAL_OTHER_CPLUSPLUSFLAGS) $(GTM_PLATFORM_OTHER_CPLUSPLUSFLAGS) $(GTM_CONFIGURATION_OTHER_CPLUSPLUSFLAGS)
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(GTM_GENERAL_GCC_PREPROCESSOR_DEFINITIONS) $(GTM_PLATFORM_GCC_PREPROCESSOR_DEFINITIONS) $(GTM_CONFIGURATION_GCC_PREPROCESSOR_DEFINITIONS)
+OTHER_LDFLAGS = $(inherited) $(GTM_GENERAL_OTHER_LDFLAGS) $(GTM_PLATFORM_OTHER_LDFLAGS) $(GTM_CONFIGURATION_OTHER_LDFLAGS)
diff --git a/XcodeConfig/subconfig/General.xcconfig b/XcodeConfig/subconfig/General.xcconfig
index 114b718..89304b9 100644
--- a/XcodeConfig/subconfig/General.xcconfig
+++ b/XcodeConfig/subconfig/General.xcconfig
@@ -27,10 +27,18 @@
// for Mac OS developement, the values are:
// SDK_NAME macosx10.4
// SDK_NAME macosx10.5
+// SDK_NAME macosx10.6
-// Build for PPC and Intel (Leopard gets 64bit also)
+// Build for PPC and Intel (Leopard/SnowLeopard gets 64 bit also)
+// Note that you can't build 10.5 with using SenTestingKit on ppc64 with
+// SnowLeopard XCode because it doesn't ship with a ppc64 version of
+// SenTestingKit. For this reason we are NOT building/testing GTM
+// with ppc64 at this time. We override the 10.5 setting in the project
+// file to turn it off.
ARCHS[sdk=macosx10.4*] = i386 ppc
ARCHS[sdk=macosx10.5*] = i386 x86_64 ppc ppc64
+ARCHS[sdk=macosx10.6*] = i386 x86_64 ppc
+
// Build for arm for iPhone or Intel for the iPhone Simulator
ARCHS[sdk=iphoneos*] = armv6
ARCHS[sdk=iphonesimulator*] = i386
@@ -44,9 +52,6 @@ ZERO_LINK = NO
// Prebinding considered unhelpful in 10.3 and later
PREBINDING = NO
-// Strictest warning policy
-WARNING_CFLAGS = -Wall -Werror -Wendif-labels -Wnewline-eof
-
// Work around Xcode bugs by using external strip. See:
// http://lists.apple.com/archives/Xcode-users/2006/Feb/msg00050.html
SEPARATE_STRIP = YES
@@ -63,8 +68,94 @@ ALWAYS_SEARCH_USER_PATHS = NO
// Turn on position dependent code for most cases (overridden where appropriate)
GCC_DYNAMIC_NO_PIC = YES
+// For ObjC++ we want C++ cdtors called
+GCC_OBJC_CALL_CXX_CDTORS = YES
+
+// Use Obj-C fast dispatch
+GCC_FAST_OBJC_DISPATCH = YES
+
// Warn on implicit data conversions in 64bit builds
GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64*] = YES
-// Use Obj-C fast dispatch (configs don't support 10.2 where you don't want it)
-GCC_FAST_OBJC_DISPATCH = YES
+// Strictest warning policy that we can do
+// Options intentionally turned off
+// http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
+// -Wsystem-headers - since we can't fix them we are going to assume they're ok
+// -Wtraditional - we are compiling with c99, so we don't care about trad
+// -Wdeclaration-after-statement - we are compiling with c99 which allows this
+// -Wpadded - lots of structures will get padded, so although this warning may
+// be useful to show us badly padded structures, it causes to many
+// warnings to be on generally.
+// -Wunreachable-code - several macros use the do {} while (0) which always
+// flags this. e.g. all the ST... macros for unittesting
+// -Wredundant-decls - we sometimes use redundant decls to add an attribute
+// to a function/method (i.e.
+// -Waggregate-return - NSPoint, NSRect etc are often returned as aggregates
+// -Wshorten-64-to-32 - this is defined in the 64 bit build settings
+// -Wcast-qual - Would love to turn this on, but causes issues when converting
+// CFTypes to NSTypes and also has issues with some external
+// libraries (notably zlib)
+// -Wundef - we conditionalize on TARGET_OS_IPHONE which is only defined
+// in the iPhoneSDK making us unable to turn this warning on.
+// -Wstrict-prototypes - breaks the GTM_METHOD_CHECK macro
+// -Wcast-align - causes a whole pile of problems buildng with iPhoneSDK
+
+// Objective C warnings
+// http://gcc.gnu.org/onlinedocs/gcc/Objective_002dC-and-Objective_002dC_002b_002b-Dialect-Options.html
+// -Wassign-intercept - this really is more informational than a warning.
+// -Wselector - the system headers define lots of methods with the same selector
+// rendering this mostly useless to us
+// -Wstrict-selector-match - the system headers define lots of methods with the
+// same selector rendering this mostly useless to us
+// Not being used currently because of Radar 5978978
+// GTM_GENERAL_WARNING_OBJC_ONLY_FLAGS=-Wundeclared-selector
+
+// C Only Warnings
+GTM_GENERAL_OTHER_CFLAGS = -Wdiv-by-zero -Wbad-function-cast -Wnested-externs -Wold-style-definition
+
+// C++ Only Warnings
+GTM_GENERAL_OTHER_CPLUSPLUSFLAGS = -Wabi -Wctor-dtor-privacy -Wstrict-null-sentinel -Wsign-promo
+GCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = YES
+GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES
+GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES
+GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES
+
+// General C/C++/ObjC/ObjC++ warnings
+// These are generally ordered in easiest to hardest to support.
+// If you are transitioning, you can turn on the levels one level at a time
+// in your project file by editing GTM_GENERAL_WARNING_CFLAGS and only
+// including the warning levels that you currently are compiling against.
+// GTM should always compile with full warnings.
+GTM_GENERAL_WARNING_CFLAGS1 = -Wall -Wendif-labels -Winvalid-pch -Wformat=2 -Wmissing-format-attribute -Wwrite-strings -Wstack-protector -Wstrict-aliasing=2
+GTM_GENERAL_WARNING_CFLAGS2 = -Wpacked -Wmissing-field-initializers
+GTM_GENERAL_WARNING_CFLAGS3 = -Wextra -Wno-unused-parameter -Wpointer-arith -Wdisabled-optimization -Wfloat-equal
+GTM_GENERAL_WARNING_CFLAGS = $(GTM_GENERAL_WARNING_CFLAGS1) $(GTM_GENERAL_WARNING_CFLAGS2) $(GTM_GENERAL_WARNING_CFLAGS3)
+
+// GCC_WARN_UNINITIALIZED_AUTOS is defined in the release/debug xcconfigs.
+GCC_WARN_CHECK_SWITCH_STATEMENTS = YES
+GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES
+GCC_WARN_ABOUT_MISSING_NEWLINE = YES
+GCC_TREAT_WARNINGS_AS_ERRORS = YES
+GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES
+GCC_WARN_ABOUT_RETURN_TYPE = YES
+GCC_WARN_MISSING_PARENTHESES = YES
+GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES
+GCC_WARN_SIGN_COMPARE = YES
+GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES
+GCC_WARN_UNKNOWN_PRAGMAS = YES
+GCC_WARN_UNUSED_LABEL = YES
+GCC_WARN_UNUSED_FUNCTION = YES
+GCC_WARN_UNUSED_VALUE = YES
+GCC_WARN_UNUSED_VARIABLE = YES
+GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES
+GCC_WARN_SHADOW = YES
+
+GCC_WARN_PEDANTIC = NO
+GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO
+GCC_WARN_PROTOTYPE_CONVERSION = NO
+GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = NO
+GCC_TREAT_NONCONFORMANT_CODE_ERRORS_AS_WARNINGS = NO
+GCC_WARN_UNUSED_PARAMETER = NO
+// Use of Gestalt requires 4 char constants (amongst other things)
+GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO
+
diff --git a/XcodeConfig/subconfig/LeopardOrLater.xcconfig b/XcodeConfig/subconfig/LeopardOrLater.xcconfig
index fa4dfce..c0f75bc 100644
--- a/XcodeConfig/subconfig/LeopardOrLater.xcconfig
+++ b/XcodeConfig/subconfig/LeopardOrLater.xcconfig
@@ -1,8 +1,8 @@
//
// LeopardOrLater.xcconfig
//
-// Xcode configuration file for projects targeting 10.4 Tiger or later. These
-// settings produce a Universal binary compatible with 10.4 for PPC and Intel.
+// Xcode configuration file for projects targeting 10.5 Leopard or later. These
+// settings produce a Universal binary compatible with 10.5 for PPC and Intel.
//
// Copyright 2006-2008 Google Inc.
//
diff --git a/XcodeConfig/subconfig/Release.xcconfig b/XcodeConfig/subconfig/Release.xcconfig
index 74df258..4c5ad8a 100644
--- a/XcodeConfig/subconfig/Release.xcconfig
+++ b/XcodeConfig/subconfig/Release.xcconfig
@@ -30,9 +30,16 @@ GCC_GENERATE_DEBUGGING_SYMBOLS = NO
// Dead code strip does not affect ObjC code but can help for C
DEAD_CODE_STRIPPING = YES
-// NDEBUG is used by things like assert.h, so define it for general compat.
// ASSERT going away in release tends to create unused vars.
-OTHER_CFLAGS = $(OTHER_CFLAGS) -DNDEBUG=1 -Wno-unused-variable
+// init-self can only be turned on when optimizations are on
+GTM_CONFIGURATION_WARNING_CFLAGS = -Wno-unused-variable -Winit-self -Wno-extra
+
+// NDEBUG is used by things like assert.h, so define it for general compat.
+GTM_CONFIGURATION_GCC_PREPROCESSOR_DEFINITIONS = NDEBUG=1
+
+// Give us warnings about uninitialized autos
+// can only be done when GCC_OPTIMIZATION_LEVEL is actually optimizing
+GCC_WARN_UNINITIALIZED_AUTOS = YES
// When we strip we want to strip all symbols in release, but save externals.
STRIP_STYLE = all
diff --git a/XcodeConfig/subconfig/SnowLeopardOrLater.xcconfig b/XcodeConfig/subconfig/SnowLeopardOrLater.xcconfig
new file mode 100644
index 0000000..0a7475e
--- /dev/null
+++ b/XcodeConfig/subconfig/SnowLeopardOrLater.xcconfig
@@ -0,0 +1,26 @@
+//
+// SnowLeopardOrLater.xcconfig
+//
+// Xcode configuration file for projects targeting 10.6 SnowLeopard or later.
+// These settings produce a Universal binary compatible with 10.6 for
+// PPC and Intel.
+//
+// Copyright 2008 Google Inc.
+//
+// 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
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+// Default SDK and minimum OS version is 10.6
+SDKROOT = ${DEVELOPER_SDK_DIR}/MacOSX10.6.sdk
+MACOSX_DEPLOYMENT_TARGET = 10.6
+GCC_VERSION = 4.0
diff --git a/XcodeConfig/subconfig/iPhone20.xcconfig b/XcodeConfig/subconfig/iPhone20.xcconfig
index fea781b..2509ba8 100644
--- a/XcodeConfig/subconfig/iPhone20.xcconfig
+++ b/XcodeConfig/subconfig/iPhone20.xcconfig
@@ -17,9 +17,6 @@
// License for the specific language governing permissions and limitations under
// the License.
-// Code signing. Should be overridden if releasing
-CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer
-
// Default SDK and minimum OS version is the iphone SDK.
SDKROOT = iphoneos2.0
MACOSX_DEPLOYMENT_TARGET = 10.5
diff --git a/XcodeConfig/subconfig/iPhone21.xcconfig b/XcodeConfig/subconfig/iPhone21.xcconfig
index 6265000..e543ce5 100644
--- a/XcodeConfig/subconfig/iPhone21.xcconfig
+++ b/XcodeConfig/subconfig/iPhone21.xcconfig
@@ -17,9 +17,6 @@
// License for the specific language governing permissions and limitations under
// the License.
-// Code signing. Should be overridden if releasing
-CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer
-
// Default SDK and minimum OS version is the iphone SDK.
SDKROOT = iphoneos2.1
MACOSX_DEPLOYMENT_TARGET = 10.5
diff --git a/XcodeConfig/xcconfigs-readme.txt b/XcodeConfig/xcconfigs-readme.txt
index 5a44bb0..87a6dd7 100644
--- a/XcodeConfig/xcconfigs-readme.txt
+++ b/XcodeConfig/xcconfigs-readme.txt
@@ -1,4 +1,4 @@
-Xcode Config is sorta a black art, any time you have a set of rules, you
+Xcode Configs are sort of a black art, any time you have a set of rules, you
quickly hit a few exceptions.
The main goal of using these is as follow:
@@ -6,7 +6,7 @@ The main goal of using these is as follow:
Edit your Project level build settings by removing as much as possible, and
then set the per Configuration settings to one of the project xcode config
files w/in the Project subfolder here. This will batch setup the project to
-build Debug/Release w/ a specific SDK.
+build Debug/Release with a specific SDK.
If you are building a Shared Library, Loadable Bundle (Framework) or UnitTest
you will need to apply a further Xcode Config file at the target level. You do
@@ -30,3 +30,24 @@ support to make mixing SDKs easier.
Remember: When using the configs at any given layer, make sure you set them for
each build configuration you need (not just the active one).
+
+Many of the build settings are more than just yes/no flags and take
+a list of values that you may want to change at different levels.
+Xcode doesn't allow you to "inherit" settings with includes so you always
+end up overriding settings accidentally. To avoid this, we instead
+allow you to define settings at different levels
+(GENERAL, PLATFORM (iPhone/Mac), CONFIGURATION (Release/Debug).
+We do this by setting a GTM version of the setting (so for OTHER_CFLAGS it's
+GTM_XXX_OTHER_CFLAGS where xxx is GENERAL, PLATFORM or CONFIGURATION depending
+at what level the flag is set. These are all merged together in the
+GTMMerge.xcconfig. Do not modify the base setting (OTHER_CFLAGS) instead modify
+the GTM one at the level you want it modified.
+
+The major place this may affect you is that we have really tightened down on
+the warnings. To make it easier for you to move your code onto the new
+xcconfig files, we have split the warnings up into three categories, which in
+general you can think of as easy, moderate and extreme. If you run into a lot
+of warnings when you compile, look at changing the GTM_GENERAL_WARNING_CFLAGS
+setting to only include lower levels (eg GTM_GENERAL_WARNING_CFLAGS1) and see
+if that makes it easier on you. Look inside General.xcconfig and search for
+GTM_GENERAL_WARNING_CFLAGS1 for more info.
diff --git a/iPhone/GTMABAddressBook.h b/iPhone/GTMABAddressBook.h
index 48e7f88..1a73545 100644
--- a/iPhone/GTMABAddressBook.h
+++ b/iPhone/GTMABAddressBook.h
@@ -26,6 +26,8 @@
// (GTMABAddressBook.strings).
//
// If things seem strange, it may be due to one of the following radars:
+// 6240394 AddressBook framework constants not initialized until
+// ABCreateAddressBook called
// 6208390 Integer and real values don't work in ABMultiValueRefs
// (and this isn't part of the title, but dictionaries don't work
// either)
diff --git a/iPhone/GTMABAddressBookTest.m b/iPhone/GTMABAddressBookTest.m
index 56106a9..29f46a6 100644
--- a/iPhone/GTMABAddressBookTest.m
+++ b/iPhone/GTMABAddressBookTest.m
@@ -491,7 +491,7 @@
STAssertNotNULL(ref, nil);
NSString *label = [[NSString alloc] initWithString:@"label"];
STAssertNotNil(label, nil);
- id val;
+ id val = nil;
switch (type) {
case kABDictionaryPropertyType:
val = [[NSDictionary alloc] initWithObjectsAndKeys:@"1", @"1", nil];
@@ -562,4 +562,24 @@
CFRelease(ref);
}
}
+
+// Globals used by testRadar6240394.
+static ABPropertyID gGTMTestID;
+static const ABPropertyID *gGTMTestIDPtr;
+
+void __attribute__((constructor))SetUpIDForTestRadar6240394(void) {
+ // These must be set up BEFORE ABAddressBookCreate is called.
+ gGTMTestID = kABPersonLastNameProperty;
+ gGTMTestIDPtr = &kABPersonLastNameProperty;
+}
+
+- (void)testRadar6240394 {
+ // As of iPhone SDK 2.1, the property IDs aren't initialized until
+ // ABAddressBookCreate is actually called. They will return zero until
+ // then. Logged as radar 6240394.
+ STAssertEquals(gGTMTestID, 0, @"If this isn't zero, Apple has fixed 6240394");
+ (void)ABAddressBookCreate();
+ STAssertEquals(*gGTMTestIDPtr, kABPersonLastNameProperty,
+ @"If this doesn't work, something else has broken");
+}
@end