aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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