From 7bb8e9b9b24141f373ed70d7e6674a245c0227cf Mon Sep 17 00:00:00 2001 From: "thomasvl@gmail.com" Date: Mon, 22 Sep 2008 23:33:44 +0000 Subject: - 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 - Added ability to control termination to iPhone unit test script. It can be controlled by the GTM_DISABLE_TERMINATION environment variable - Fixed several leaks found with leak checking enabled. - Added configs for different iPhone OS versions. --- AppKit/GTMLargeTypeWindow.h | 2 +- AppKit/GTMLargeTypeWindowTest.m | 4 +- BuildScripts/BuildAllSDKs.sh | 35 ++++++-- Foundation/GTMExceptionalInlines.h | 1 + Foundation/GTMExceptionalInlines.m | 4 + Foundation/GTMExceptionalInlinesTest.m | 6 ++ Foundation/GTMHTTPServer.m | 1 + Foundation/GTMPathTest.m | 1 + Foundation/GTMRegex.m | 2 + GTM.xcodeproj/project.pbxproj | 80 ++++++++++++++--- GTMiPhone.xcodeproj/project.pbxproj | 63 ++++++++++++-- ReleaseNotes.txt | 13 +++ UnitTesting/GTMIPhoneUnitTestDelegate.m | 40 ++++++++- UnitTesting/GTMNSObject+UnitTesting.m | 2 + UnitTesting/GTMTestTimer.h | 125 +++++++++++++++++++++++++++ UnitTesting/GTMTestTimerTest.m | 56 ++++++++++++ UnitTesting/RunIPhoneUnitTest.sh | 37 +++++++- UnitTesting/RunMacOSUnitTests.sh | 45 +++++++--- XcodeConfig/Project/DebugiPhone.xcconfig | 18 ++-- XcodeConfig/Project/DebugiPhone20.xcconfig | 34 ++++++++ XcodeConfig/Project/DebugiPhone21.xcconfig | 34 ++++++++ XcodeConfig/Project/ReleaseiPhone.xcconfig | 18 ++-- XcodeConfig/Project/ReleaseiPhone20.xcconfig | 34 ++++++++ XcodeConfig/Project/ReleaseiPhone21.xcconfig | 34 ++++++++ XcodeConfig/subconfig/General.xcconfig | 2 + XcodeConfig/subconfig/iPhone.xcconfig | 26 ------ XcodeConfig/subconfig/iPhone20.xcconfig | 26 ++++++ XcodeConfig/subconfig/iPhone21.xcconfig | 26 ++++++ iPhone/GTMABAddressBook.m | 3 + iPhone/GTMABAddressBookTest.m | 33 ++++--- 30 files changed, 694 insertions(+), 111 deletions(-) create mode 100644 UnitTesting/GTMTestTimer.h create mode 100644 UnitTesting/GTMTestTimerTest.m create mode 100644 XcodeConfig/Project/DebugiPhone20.xcconfig create mode 100644 XcodeConfig/Project/DebugiPhone21.xcconfig create mode 100644 XcodeConfig/Project/ReleaseiPhone20.xcconfig create mode 100644 XcodeConfig/Project/ReleaseiPhone21.xcconfig delete mode 100644 XcodeConfig/subconfig/iPhone.xcconfig create mode 100644 XcodeConfig/subconfig/iPhone20.xcconfig create mode 100644 XcodeConfig/subconfig/iPhone21.xcconfig diff --git a/AppKit/GTMLargeTypeWindow.h b/AppKit/GTMLargeTypeWindow.h index 52316fc..c898512 100644 --- a/AppKit/GTMLargeTypeWindow.h +++ b/AppKit/GTMLargeTypeWindow.h @@ -28,7 +28,7 @@ // = [[[GTMLargeTypeWindow alloc] initWithString:@"Foo"] autorelease]; // [window makeKeyAndOrderFront:nil]; -// NB This class appears to have a problem with GC on 10.5.4 and below. +// NB This class appears to have a problem with GC on 10.5.5 and below. // Radar 6137322 CIFilter crashing when run with GC enabled // This appears to be an Apple bug with GC. // We do a copy animation that causes things to crash, but only with GC diff --git a/AppKit/GTMLargeTypeWindowTest.m b/AppKit/GTMLargeTypeWindowTest.m index d9e56c2..36e60c3 100644 --- a/AppKit/GTMLargeTypeWindowTest.m +++ b/AppKit/GTMLargeTypeWindowTest.m @@ -62,12 +62,12 @@ NSString *const kShortTextBlock = @"Short"; // See the comment/warning in the GTMLargeTypeWindow.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. + // tested. Currently broken on 10.5.5 and below. // Radar 6137322 CIFilter crashing when run with GC enabled long major, minor, bugfix; [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugfix]; if (!(GTMIsGarbageCollectionEnabled() - && major <= 10 && minor <= 5 && bugfix <= 4)) { + && major <= 10 && minor <= 5 && bugfix <= 5)) { return YES; } else { NSLog(@"--- animated copy not run because of GC incompatibilites ---"); diff --git a/BuildScripts/BuildAllSDKs.sh b/BuildScripts/BuildAllSDKs.sh index 0928dcd..1e08940 100755 --- a/BuildScripts/BuildAllSDKs.sh +++ b/BuildScripts/BuildAllSDKs.sh @@ -1,7 +1,7 @@ #!/bin/sh # BuildAllSDKs.sh # -# This script builds both the Tiger and Leopard versions of the requested +# This script builds the Tiger, Leopard and iPhone versions of the requested # target in the current basic config (debug, release, debug-gcov). # # Copyright 2006-2008 Google Inc. @@ -18,21 +18,37 @@ # License for the specific language governing permissions and limitations under # the License. -PROJECT_TARGET="$1" +GTM_PROJECT_TARGET="$1" +GTMIPHONE_PROJECT_TARGET="$2" STARTING_TARGET="${TARGET_NAME}" SCRIPT_APP="${TMPDIR}DoBuild.app" -REQUESTED_BUILD_STYLE=$(echo "${BUILD_STYLE}" | sed "s/.*OrLater-\(.*\)/\1/") +REQUESTED_BUILD_STYLE=$(echo "${BUILD_STYLE}" | sed -E "s/(.*OrLater-)?(.*)/\2/") # See if we were told to clean instead of build. PROJECT_ACTION="build" if [ "${ACTION}" == "clean" ]; then PROJECT_ACTION="clean" fi -# build up our AppleScript +# 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" +fi + +# build up our GTM AppleScript OUR_BUILD_SCRIPT="on run tell application \"Xcode\" activate + ${GTMIPHONE_OPEN_EXTRAS} tell project \"GTM\" -- wait for build to finish set x to 0 @@ -44,19 +60,22 @@ OUR_BUILD_SCRIPT="on run return end if end repeat - -- do the build + -- do the GTM builds with timeout of 9999 seconds - set active target to target \"${PROJECT_TARGET}\" + 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 - -- do not need the result since we are not doing another build - ${PROJECT_ACTION} using build configuration \"LeopardOrLater-${REQUESTED_BUILD_STYLE}\" + 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 + ${GTMIPHONE_BUILD_EXTRAS} end tell end run" diff --git a/Foundation/GTMExceptionalInlines.h b/Foundation/GTMExceptionalInlines.h index 25635c1..ce30db9 100644 --- a/Foundation/GTMExceptionalInlines.h +++ b/Foundation/GTMExceptionalInlines.h @@ -37,6 +37,7 @@ // functions where possible. FOUNDATION_EXPORT NSRange GTMNSMakeRange(NSUInteger loc, NSUInteger len); +FOUNDATION_EXPORT CFRange GTMCFRangeMake(NSUInteger loc, NSUInteger len); FOUNDATION_EXPORT CGPoint GTMCGPointMake(CGFloat x, CGFloat y); FOUNDATION_EXPORT CGSize GTMCGSizeMake(CGFloat width, CGFloat height); diff --git a/Foundation/GTMExceptionalInlines.m b/Foundation/GTMExceptionalInlines.m index 120e235..d803ea9 100644 --- a/Foundation/GTMExceptionalInlines.m +++ b/Foundation/GTMExceptionalInlines.m @@ -22,6 +22,10 @@ NSRange GTMNSMakeRange(NSUInteger loc, NSUInteger len) { return NSMakeRange(loc, len); } +CFRange GTMCFRangeMake(NSUInteger loc, NSUInteger len) { + return CFRangeMake(loc, len); +} + CGPoint GTMCGPointMake(CGFloat x, CGFloat y) { return CGPointMake(x, y); } diff --git a/Foundation/GTMExceptionalInlinesTest.m b/Foundation/GTMExceptionalInlinesTest.m index f785301..6142236 100644 --- a/Foundation/GTMExceptionalInlinesTest.m +++ b/Foundation/GTMExceptionalInlinesTest.m @@ -35,6 +35,12 @@ NSRange range1 = GTMNSMakeRange(loc, len); NSRange range2 = NSMakeRange(loc, len); STAssertTrue(NSEqualRanges(range1, range2), nil); + + CFRange cfrange1 = GTMCFRangeMake(loc, len); + CFRange cfrange2 = CFRangeMake(loc, len); + STAssertEquals(cfrange1.length, cfrange2.length, nil); + STAssertEquals(cfrange1.location, cfrange2.location, nil); + CGPoint cgpoint1 = GTMCGPointMake(x, y); CGPoint cgpoint2 = CGPointMake(x, y); diff --git a/Foundation/GTMHTTPServer.m b/Foundation/GTMHTTPServer.m index ffa294c..ecd649c 100644 --- a/Foundation/GTMHTTPServer.m +++ b/Foundation/GTMHTTPServer.m @@ -90,6 +90,7 @@ static NSString *kResponse = @"Response"; - (void)dealloc { [self stop]; + [connections_ release]; [super dealloc]; } diff --git a/Foundation/GTMPathTest.m b/Foundation/GTMPathTest.m index 0570bb3..3a60ea7 100644 --- a/Foundation/GTMPathTest.m +++ b/Foundation/GTMPathTest.m @@ -51,6 +51,7 @@ #else [[NSFileManager defaultManager] removeItemAtPath:testDirectory_ error:NULL]; #endif + [testDirectory_ release]; } - (void)testBasicCreation { diff --git a/Foundation/GTMRegex.m b/Foundation/GTMRegex.m index c142c62..33c5b25 100644 --- a/Foundation/GTMRegex.m +++ b/Foundation/GTMRegex.m @@ -674,6 +674,8 @@ static NSString *const kReplacementPattern = - (id)init { // make sure init is never called, the class in in the header so someone // could try to create it by mistake. + // Call super init and release so we don't leak + [[super init] autorelease]; [self doesNotRecognizeSelector:_cmd]; return nil; // COV_NF_LINE - return is just here to keep gcc happy } diff --git a/GTM.xcodeproj/project.pbxproj b/GTM.xcodeproj/project.pbxproj index 9fb14d1..9d958a4 100644 --- a/GTM.xcodeproj/project.pbxproj +++ b/GTM.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 8B45A0390DA46A20001148C5 /* PBXTargetDependency */, F472042F0D33BEB500E9F378 /* PBXTargetDependency */, F472042D0D33BEB500E9F378 /* PBXTargetDependency */, + 8B5A9D120E717906005DA441 /* PBXTargetDependency */, ); name = "All UnitTests"; productName = "All UnitTests"; @@ -61,6 +62,8 @@ 8B3344250DBF7A36009FD32C /* GTMNSAppleEventDescriptor+FoundationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B33441D0DBF7A36009FD32C /* GTMNSAppleEventDescriptor+FoundationTest.m */; }; 8B33455E0DBF8844009FD32C /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F42E09AD0D19A62F00D5DDE0 /* Carbon.framework */; }; 8B3345890DBF8A55009FD32C /* GTMNSAppleEvent+HandlerTest.applescript in AppleScript */ = {isa = PBXBuildFile; fileRef = 8B3344200DBF7A36009FD32C /* GTMNSAppleEvent+HandlerTest.applescript */; settings = {ATTRIBUTES = (Debug, ); }; }; + 8B3590160E8190FA0041E21C /* GTMTestTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B3590150E8190FA0041E21C /* GTMTestTimer.h */; }; + 8B35901B0E8191750041E21C /* GTMTestTimerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B35901A0E8191750041E21C /* GTMTestTimerTest.m */; }; 8B3AA9F10E033E23007E31B5 /* GTMValidatingContainers.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B3AA9EF0E033E23007E31B5 /* GTMValidatingContainers.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8B3AA9F20E033E23007E31B5 /* GTMValidatingContainers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B3AA9F00E033E23007E31B5 /* GTMValidatingContainers.m */; }; 8B3AA9F80E033E5F007E31B5 /* GTMValidatingContainersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B3AA9F70E033E5F007E31B5 /* GTMValidatingContainersTest.m */; }; @@ -243,6 +246,20 @@ remoteGlobalIDString = 8B45A2890DA49B99001148C5; remoteInfo = UIUnitTestingHarness; }; + 8B5A9D0F0E7178F6005DA441 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8B5A9D070E7178F6005DA441 /* GTMiPhone.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 1D6058910D05DD3D006BFB54; + remoteInfo = GTMiPhoneUnitTesting; + }; + 8B5A9D110E717906005DA441 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8B5A9D070E7178F6005DA441 /* GTMiPhone.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = F4C7F9BF0DC62EC8009BEE5B; + remoteInfo = "All UnitTests"; + }; 8B7DCBA30DFF0EFB0017E983 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; @@ -324,6 +341,8 @@ 8B33441E0DBF7A36009FD32C /* GTMNSAppleEventDescriptor+Foundation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSAppleEventDescriptor+Foundation.m"; sourceTree = ""; }; 8B33441F0DBF7A36009FD32C /* GTMNSAppleEventDescriptor+Foundation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSAppleEventDescriptor+Foundation.h"; sourceTree = ""; }; 8B3344200DBF7A36009FD32C /* GTMNSAppleEvent+HandlerTest.applescript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.applescript; path = "GTMNSAppleEvent+HandlerTest.applescript"; sourceTree = ""; }; + 8B3590150E8190FA0041E21C /* GTMTestTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMTestTimer.h; sourceTree = ""; }; + 8B35901A0E8191750041E21C /* GTMTestTimerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMTestTimerTest.m; sourceTree = ""; }; 8B3AA9EF0E033E23007E31B5 /* GTMValidatingContainers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMValidatingContainers.h; sourceTree = ""; }; 8B3AA9F00E033E23007E31B5 /* GTMValidatingContainers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMValidatingContainers.m; sourceTree = ""; }; 8B3AA9F70E033E5F007E31B5 /* GTMValidatingContainersTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMValidatingContainersTest.m; sourceTree = ""; }; @@ -344,6 +363,7 @@ 8B55479A0DB3B7A50014CC1C /* GTMAppKit+UnitTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMAppKit+UnitTesting.h"; sourceTree = ""; }; 8B55479B0DB3B7A50014CC1C /* GTMAppKit+UnitTesting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMAppKit+UnitTesting.m"; sourceTree = ""; }; 8B58E9940E547EB000A0E02E /* GTMGetURLHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMGetURLHandler.m; sourceTree = ""; }; + 8B5A9D070E7178F6005DA441 /* GTMiPhone.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = GTMiPhone.xcodeproj; sourceTree = ""; }; 8B61FDBF0E4CDB8000FF9C21 /* GTMStackTrace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMStackTrace.m; sourceTree = ""; }; 8B6F31EF0DA347720052CA40 /* GTMMethodCheck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMMethodCheck.m; sourceTree = ""; }; 8B6F31F10DA347720052CA40 /* GTMMethodCheckTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMMethodCheckTest.m; sourceTree = ""; }; @@ -563,6 +583,7 @@ 0867D691FE84028FC02AAC07 /* GTM */ = { isa = PBXGroup; children = ( + 8B5A9D070E7178F6005DA441 /* GTMiPhone.xcodeproj */, F4C978090D5B79C7001C29A6 /* ReleaseNotes.txt */, F440EDB70DFECC4B0003E81F /* BuildingAndUsing.txt */, 8B1A16050D90344B00CA1E8E /* GTMDefines.h */, @@ -606,6 +627,14 @@ path = GTMUIUnitTestingHarness; sourceTree = ""; }; + 8B5A9D080E7178F6005DA441 /* Products */ = { + isa = PBXGroup; + children = ( + 8B5A9D100E7178F6005DA441 /* GTMiPhoneTest.app */, + ); + name = Products; + sourceTree = ""; + }; F435E46C0DC8F23A0069CDE8 /* TestData */ = { isa = PBXGroup; children = ( @@ -804,27 +833,29 @@ F48FE2770D198CEA009257D2 /* UnitTesting */ = { isa = PBXGroup; children = ( - 8B7DCBE10DFF18720017E983 /* GTMDevLogUnitTestingBridge.m */, - 8B7DCBEC0DFF1A4F0017E983 /* GTMUnitTestDevLog.m */, - 8B7DCBF00DFF1A610017E983 /* GTMUnitTestDevLog.h */, - F4BC22CF0DE4C39000108B7D /* GTMTestHTTPServer.h */, - F4BC22D00DE4C39000108B7D /* GTMTestHTTPServer.m */, - 8BC04D140DB0061300C2D1CA /* RunMacOSUnitTests.sh */, 8B55479A0DB3B7A50014CC1C /* GTMAppKit+UnitTesting.h */, 8B55479B0DB3B7A50014CC1C /* GTMAppKit+UnitTesting.m */, - 8B726BD00D91C0860090C251 /* GTMCALayer+UnitTesting.m */, 8B726BD10D91C0860090C251 /* GTMCALayer+UnitTesting.h */, + 8B726BD00D91C0860090C251 /* GTMCALayer+UnitTesting.m */, + 8B7DCBE10DFF18720017E983 /* GTMDevLogUnitTestingBridge.m */, + 8B1A14EA0D900BC800CA1E8E /* GTMNSObject+BindingUnitTesting.h */, + 8B1A14E90D900BC800CA1E8E /* GTMNSObject+BindingUnitTesting.m */, F48FE29B0D198D36009257D2 /* GTMNSObject+UnitTesting.h */, F48FE29C0D198D36009257D2 /* GTMNSObject+UnitTesting.m */, - 8B1A14E90D900BC800CA1E8E /* GTMNSObject+BindingUnitTesting.m */, - 8B1A14EA0D900BC800CA1E8E /* GTMNSObject+BindingUnitTesting.h */, - 8B45A2670DA498A0001148C5 /* GTMUnitTestingUtilities.h */, - 8B45A2680DA498A0001148C5 /* GTMUnitTestingUtilities.m */, F48FE29F0D198D36009257D2 /* GTMSenTestCase.h */, 8B7DCE180DFF39850017E983 /* GTMSenTestCase.m */, + F4BC22CF0DE4C39000108B7D /* GTMTestHTTPServer.h */, + F4BC22D00DE4C39000108B7D /* GTMTestHTTPServer.m */, + 8B3590150E8190FA0041E21C /* GTMTestTimer.h */, + 8B35901A0E8191750041E21C /* GTMTestTimerTest.m */, + 8B7DCBF00DFF1A610017E983 /* GTMUnitTestDevLog.h */, + 8B7DCBEC0DFF1A4F0017E983 /* GTMUnitTestDevLog.m */, + 8B7AD4AD0DABBFEE00B84F4A /* GTMUnitTestingBindingTest.m */, 8B45A2E00DA51ABC001148C5 /* GTMUnitTestingTest.h */, 8B45A2E10DA51ABC001148C5 /* GTMUnitTestingTest.m */, - 8B7AD4AD0DABBFEE00B84F4A /* GTMUnitTestingBindingTest.m */, + 8B45A2670DA498A0001148C5 /* GTMUnitTestingUtilities.h */, + 8B45A2680DA498A0001148C5 /* GTMUnitTestingUtilities.m */, + 8BC04D140DB0061300C2D1CA /* RunMacOSUnitTests.sh */, 8B45A2A20DA49C47001148C5 /* GTMUIUnitTestingHarness */, F435E46C0DC8F23A0069CDE8 /* TestData */, ); @@ -920,6 +951,7 @@ F95803FA0E2FB08F0049A088 /* GTMLoggerRingBufferWriter.h in Headers */, 8B1B49180E5F8E2100A08972 /* GTMExceptionalInlines.h in Headers */, 7F3EB38E0E5E09C700A7A75E /* GTMNSImage+Scaling.h in Headers */, + 8B3590160E8190FA0041E21C /* GTMTestTimer.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -942,7 +974,7 @@ }; F41A6EF80E02DCFC00788A6C /* All UnitTests All SDKs */ = { isa = PBXLegacyTarget; - buildArgumentsString = "\"All UnitTests\""; + buildArgumentsString = "\"All UnitTests\" \"All UnitTests\""; buildConfigurationList = F41A6F070E02DD1500788A6C /* Build configuration list for PBXLegacyTarget "All UnitTests All SDKs" */; buildPhases = ( ); @@ -1066,6 +1098,12 @@ mainGroup = 0867D691FE84028FC02AAC07 /* GTM */; productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 8B5A9D080E7178F6005DA441 /* Products */; + ProjectRef = 8B5A9D070E7178F6005DA441 /* GTMiPhone.xcodeproj */; + }, + ); projectRoot = ""; targets = ( F42E086C0D199A5B00D5DDE0 /* GTM */, @@ -1080,6 +1118,16 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 8B5A9D100E7178F6005DA441 /* GTMiPhoneTest.app */ = { + isa = PBXReferenceProxy; + fileType = wrapper.application; + path = GTMiPhoneTest.app; + remoteRef = 8B5A9D0F0E7178F6005DA441 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 8B45A0230DA4696C001148C5 /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -1196,6 +1244,7 @@ 8B7DCBC30DFF0F7F0017E983 /* GTMMethodCheck.m in Sources */, 8B7DCBEF0DFF1A4F0017E983 /* GTMUnitTestDevLog.m in Sources */, 8B7DCE1B0DFF39850017E983 /* GTMSenTestCase.m in Sources */, + 8B35901B0E8191750041E21C /* GTMTestTimerTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1335,6 +1384,11 @@ target = 8B45A2890DA49B99001148C5 /* UIUnitTestingHarness */; targetProxy = 8B45A2D30DA51A0E001148C5 /* PBXContainerItemProxy */; }; + 8B5A9D120E717906005DA441 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "All UnitTests"; + targetProxy = 8B5A9D110E717906005DA441 /* PBXContainerItemProxy */; + }; 8B7DCBA40DFF0EFB0017E983 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = F42E086C0D199A5B00D5DDE0 /* GTM */; diff --git a/GTMiPhone.xcodeproj/project.pbxproj b/GTMiPhone.xcodeproj/project.pbxproj index bf1133b..f470ec8 100644 --- a/GTMiPhone.xcodeproj/project.pbxproj +++ b/GTMiPhone.xcodeproj/project.pbxproj @@ -174,8 +174,8 @@ 8BC048000DAE928A00C2D1CA /* GTMUIViewUnitTestingTest.gtmUTState */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = GTMUIViewUnitTestingTest.gtmUTState; sourceTree = ""; }; 8BC048010DAE928A00C2D1CA /* GTMUIViewUnitTestingTest.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = GTMUIViewUnitTestingTest.png; sourceTree = ""; }; 8BC0480E0DAE928A00C2D1CA /* RunIPhoneUnitTest.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = RunIPhoneUnitTest.sh; sourceTree = ""; }; - 8BC049850DAEC59100C2D1CA /* DebugiPhone.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugiPhone.xcconfig; sourceTree = ""; }; - 8BC049890DAEC59100C2D1CA /* ReleaseiPhone.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ReleaseiPhone.xcconfig; sourceTree = ""; }; + 8BC049850DAEC59100C2D1CA /* DebugiPhone20.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugiPhone20.xcconfig; sourceTree = ""; }; + 8BC049890DAEC59100C2D1CA /* ReleaseiPhone20.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ReleaseiPhone20.xcconfig; sourceTree = ""; }; 8BC0498F0DAEC59100C2D1CA /* CodeCoverage.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = CodeCoverage.xcconfig; sourceTree = ""; }; 8BC04A6F0DAF144200C2D1CA /* GTMSystemVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMSystemVersion.h; sourceTree = ""; }; 8BC04A710DAF144700C2D1CA /* GTMSystemVersionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMSystemVersionTest.m; sourceTree = ""; }; @@ -425,8 +425,8 @@ 8BC04F020DB15A5300C2D1CA /* Project */ = { isa = PBXGroup; children = ( - 8BC049850DAEC59100C2D1CA /* DebugiPhone.xcconfig */, - 8BC049890DAEC59100C2D1CA /* ReleaseiPhone.xcconfig */, + 8BC049850DAEC59100C2D1CA /* DebugiPhone20.xcconfig */, + 8BC049890DAEC59100C2D1CA /* ReleaseiPhone20.xcconfig */, ); path = Project; sourceTree = ""; @@ -441,6 +441,23 @@ }; /* End PBXGroup section */ +/* Begin PBXLegacyTarget section */ + F4B541440E7F022B004738EC /* All UnitTests all SDKs */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "\"All UnitTests\" \"All UnitTests\""; + buildConfigurationList = F4B5414A0E7F025F004738EC /* Build configuration list for PBXLegacyTarget "All UnitTests all SDKs" */; + buildPhases = ( + ); + buildToolPath = BuildScripts/BuildAllSDKs.sh; + buildWorkingDirectory = "$(SRCROOT)"; + dependencies = ( + ); + name = "All UnitTests all SDKs"; + passBuildSettingsInEnvironment = 1; + productName = "All UnitTests all SDKs"; + }; +/* End PBXLegacyTarget section */ + /* Begin PBXNativeTarget section */ 1D6058900D05DD3D006BFB54 /* GTMiPhoneUnitTesting */ = { isa = PBXNativeTarget; @@ -474,6 +491,7 @@ targets = ( F4C7F9BF0DC62EC8009BEE5B /* All UnitTests */, 1D6058900D05DD3D006BFB54 /* GTMiPhoneUnitTesting */, + F4B541440E7F022B004738EC /* All UnitTests all SDKs */, ); }; /* End PBXProject section */ @@ -600,7 +618,7 @@ }; 8BC0497D0DAEC48600C2D1CA /* Debug-gcov */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8BC049850DAEC59100C2D1CA /* DebugiPhone.xcconfig */; + baseConfigurationReference = 8BC049850DAEC59100C2D1CA /* DebugiPhone20.xcconfig */; buildSettings = { GCC_PREFIX_HEADER = GTM_Prefix.pch; SDKROOT = iphonesimulator2.0; @@ -618,7 +636,7 @@ }; C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8BC049850DAEC59100C2D1CA /* DebugiPhone.xcconfig */; + baseConfigurationReference = 8BC049850DAEC59100C2D1CA /* DebugiPhone20.xcconfig */; buildSettings = { GCC_PREFIX_HEADER = GTM_Prefix.pch; SDKROOT = iphonesimulator2.0; @@ -627,13 +645,34 @@ }; C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8BC049890DAEC59100C2D1CA /* ReleaseiPhone.xcconfig */; + baseConfigurationReference = 8BC049890DAEC59100C2D1CA /* ReleaseiPhone20.xcconfig */; buildSettings = { GCC_PREFIX_HEADER = GTM_Prefix.pch; SDKROOT = iphonesimulator2.0; }; name = Release; }; + F4B541450E7F022B004738EC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "All UnitTests all SDKs"; + }; + name = Debug; + }; + F4B541460E7F022B004738EC /* Debug-gcov */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "All UnitTests all SDKs"; + }; + name = "Debug-gcov"; + }; + F4B541470E7F022B004738EC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "All UnitTests all SDKs"; + }; + name = Release; + }; F4C7F9C00DC62EC8009BEE5B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -678,6 +717,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + F4B5414A0E7F025F004738EC /* Build configuration list for PBXLegacyTarget "All UnitTests all SDKs" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F4B541450E7F022B004738EC /* Debug */, + F4B541460E7F022B004738EC /* Debug-gcov */, + F4B541470E7F022B004738EC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; F4C7F9C50DC62F0C009BEE5B /* Build configuration list for PBXAggregateTarget "All UnitTests" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt index 5dbfe96..1f39568 100644 --- a/ReleaseNotes.txt +++ b/ReleaseNotes.txt @@ -99,6 +99,19 @@ Changes since 1.5.1 - Added several set environment variable statements to RunIPhoneUnitTest.sh to encourage bugs to come out of the woodwork. +- 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 + +- Added ability to control termination to iPhone unit test script. It can be + controlled by the GTM_DISABLE_TERMINATION environment variable + +- Fixed several leaks found with leak checking enabled. + Release 1.5.1 Changes since 1.5.0 diff --git a/UnitTesting/GTMIPhoneUnitTestDelegate.m b/UnitTesting/GTMIPhoneUnitTestDelegate.m index f93c472..a793ff4 100644 --- a/UnitTesting/GTMIPhoneUnitTestDelegate.m +++ b/UnitTesting/GTMIPhoneUnitTestDelegate.m @@ -34,6 +34,33 @@ 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; @@ -58,9 +85,20 @@ static int MethodSort(const void *a, const void *b) { // 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 - [[UIApplication sharedApplication] terminate]; + if (!getenv("GTM_DISABLE_TERMINATION")) { + [[UIApplication sharedApplication] terminate]; + } } // Run through all the registered classes and run test methods on any diff --git a/UnitTesting/GTMNSObject+UnitTesting.m b/UnitTesting/GTMNSObject+UnitTesting.m index 8e0899d..a722b9e 100644 --- a/UnitTesting/GTMNSObject+UnitTesting.m +++ b/UnitTesting/GTMNSObject+UnitTesting.m @@ -26,6 +26,8 @@ #if GTM_IPHONE_SDK #import +#else +#import #endif NSString *const GTMUnitTestingEncodedObjectNotification = @"GTMUnitTestingEncodedObjectNotification"; diff --git a/UnitTesting/GTMTestTimer.h b/UnitTesting/GTMTestTimer.h new file mode 100644 index 0000000..200f9b1 --- /dev/null +++ b/UnitTesting/GTMTestTimer.h @@ -0,0 +1,125 @@ +// +// GTMTestTimer.h +// +// Copyright 2006-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 +#import "GTMDefines.h" +#import + +// GTMTestTimer is done in straight inline C to avoid obj-c calling overhead. +// It is for doing test timings at very high precision. +// Test Timers have standard CoreFoundation Retain/Release rules. +// Test Timers are not thread safe. Test Timers do NOT check their arguments +// for NULL. You will crash if you pass a NULL argument in. + +typedef struct { + mach_timebase_info_data_t time_base_info_; + bool running_; + uint64_t start_; + uint64_t split_; + uint64_t elapsed_; + NSUInteger iterations_; + NSUInteger retainCount_; +} GTMTestTimer; + +// Create a test timer +FOUNDATION_STATIC_INLINE GTMTestTimer *GTMTestTimerCreate(void) { + GTMTestTimer *t = calloc(sizeof(GTMTestTimer), 1); + if (t) { + if (mach_timebase_info(&t->time_base_info_) == KERN_SUCCESS) { + t->retainCount_ = 1; + } else { + // COV_NF_START + free(t); + t = NULL; + // COV_NF_END + } + } + return t; +} + +// Retain a timer +FOUNDATION_STATIC_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) { + t->retainCount_ -= 1; + if (t->retainCount_ == 0) { + free(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) { + 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) { + uint64_t now = mach_absolute_time(); + t->running_ = false; + ++t->iterations_; + t->split_ = now - t->start_; + t->elapsed_ += t->split_; + t->start_ = 0; + return t->split_; +} + +// 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) { + uint64_t total = t->elapsed_; + if (t->running_) { + total += mach_absolute_time() - t->start_; + } + return (double)(total * t->time_base_info_.numer + / t->time_base_info_.denom); +} + +// 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) { + 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) { + 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) { + 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) { + return t->iterations_; +} + +// Returns true if the timer is running. +FOUNDATION_STATIC_INLINE bool GTMTestTimerIsRunning(GTMTestTimer *t) { + return t->running_; +} diff --git a/UnitTesting/GTMTestTimerTest.m b/UnitTesting/GTMTestTimerTest.m new file mode 100644 index 0000000..86f9d22 --- /dev/null +++ b/UnitTesting/GTMTestTimerTest.m @@ -0,0 +1,56 @@ +// +// GTMTestTimerTest.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 "GTMTestTimer.h" + +@interface GTMTestTimerTest : GTMTestCase +@end + +@implementation GTMTestTimerTest +- (void)testTimer { + GTMTestTimer *timer = GTMTestTimerCreate(); + STAssertNotNULL(timer, nil); + GTMTestTimerRetain(timer); + GTMTestTimerRelease(timer); + STAssertEqualsWithAccuracy(GTMTestTimerGetSeconds(timer), 0.0, 0.0, nil); + GTMTestTimerStart(timer); + STAssertTrue(GTMTestTimerIsRunning(timer), nil); + NSRunLoop *loop = [NSRunLoop currentRunLoop]; + [loop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + GTMTestTimerStop(timer); + + // We use greater than (and an almost absurd less than) because + // these tests are very dependant on machine load, and we don't want + // automated tests reporting false negatives. + STAssertGreaterThan(GTMTestTimerGetSeconds(timer), 0.1, nil); + STAssertGreaterThan(GTMTestTimerGetMilliseconds(timer), 100.0,nil); + STAssertGreaterThan(GTMTestTimerGetMicroseconds(timer), 100000.0, nil); + + // Check to make sure we're not WAY off the mark (by a factor of 10) + STAssertLessThan(GTMTestTimerGetMicroseconds(timer), 1000000.0, nil); + + [loop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + GTMTestTimerStart(timer); + [loop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + STAssertGreaterThan(GTMTestTimerGetSeconds(timer), 0.2, nil); + GTMTestTimerStop(timer); + STAssertEquals(GTMTestTimerGetIterations(timer), (NSUInteger)2, nil); + GTMTestTimerRelease(timer); +} +@end diff --git a/UnitTesting/RunIPhoneUnitTest.sh b/UnitTesting/RunIPhoneUnitTest.sh index 0089032..1718bda 100755 --- a/UnitTesting/RunIPhoneUnitTest.sh +++ b/UnitTesting/RunIPhoneUnitTest.sh @@ -17,6 +17,27 @@ # 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. +# +# GTM_DISABLE_LEAKS - +# Set to a non-zero value to turn off the leaks check. +# +# 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. + +ScriptDir=$(dirname $(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")) +ScriptName=$(basename "$0") +ThisScript="${ScriptDir}/${ScriptName}" + +GTMXcodeNote() { + echo ${ThisScript}:${1}: note: GTM ${2} +} if [ "$IPHONEOS_DEPLOYMENT_TARGET" == "" ]; then # We kill the iPhone simulator because otherwise we run into issues where @@ -24,22 +45,30 @@ if [ "$IPHONEOS_DEPLOYMENT_TARGET" == "" ]; then # at this time the iPhone SDK won't allow two simulators running at the same # time. /usr/bin/killall "iPhone Simulator" + 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" - # Encourage errors + # See http://developer.apple.com/technotes/tn2004/tn2124.html for an + # explanation of these environment variables. + export MallocScribble=YES export MallocPreScribble=YES export MallocGuardEdges=YES - export CFZombieLevel=3 + export MallocStackLogging=YES export NSAutoreleaseFreedObjectCheckEnabled=YES - export NSZombieEnabled=YES export OBJC_DEBUG_FRAGILE_SUPERCLASSES=YES + if [ ! $GTM_DISABLE_ZOMBIES ]; then + GTMXcodeNote ${LINENO} "Enabling zombies" + export CFZombieLevel=3 + export NSZombieEnabled=YES + fi + "$TARGET_BUILD_DIR/$EXECUTABLE_PATH" -RegisterForSystemEvents else - echo "note: Skipping running of unittests for device build." + GTMXcodeNote ${LINENO} "Skipping running of unittests for device build." fi exit 0 diff --git a/UnitTesting/RunMacOSUnitTests.sh b/UnitTesting/RunMacOSUnitTests.sh index 45d0afc..5c36a79 100755 --- a/UnitTesting/RunMacOSUnitTests.sh +++ b/UnitTesting/RunMacOSUnitTests.sh @@ -19,21 +19,46 @@ # See http://developer.apple.com/technotes/tn2004/tn2124.html for details. # -export MallocScribble=YES -export MallocPreScribble=YES -export MallocGuardEdges=YES -# 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 +# 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_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 +# (https://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?bundleID=19915) + +ScriptDir=$(dirname $(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")) +ScriptName=$(basename "$0") +ThisScript="${ScriptDir}/${ScriptName}" + +GTMXcodeNote() { + echo ${ThisScript}:${1}: note: GTM ${2} +} + +# 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 + # 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 # unless a target has specifically turned them off if [ ! $GTM_NO_DEBUG_FRAMEWORKS ]; then if [ -f "/System/Library/Frameworks/CoreFoundation.framework/Versions/Current/CoreFoundation_debug" ]; then - echo ---- Using _debug frameworks ---- + GTMXcodeNote ${LINENO} "Using _debug frameworks" export DYLD_IMAGE_SUFFIX=_debug fi fi diff --git a/XcodeConfig/Project/DebugiPhone.xcconfig b/XcodeConfig/Project/DebugiPhone.xcconfig index 4af17bd..6067fff 100644 --- a/XcodeConfig/Project/DebugiPhone.xcconfig +++ b/XcodeConfig/Project/DebugiPhone.xcconfig @@ -1,10 +1,10 @@ // -// DebugiPhoneSimulator.xcconfig +// DebugiPhone.xcconfig // // Xcode configuration file for building a Debug configuration of a project // for iPhone. // -// Copyright 2006-2008 Google Inc. +// 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 @@ -19,16 +19,8 @@ // the License. // -// 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. - -// Pull in the general settings -#include "../subconfig/General.xcconfig" +// This file is deprecated, please use the version specific one instead. +// -// iPhone settings -#include "../subconfig/iPhone.xcconfig" +#include "DebugiPhone20.xcconfig" -// Release settings -#include "../subconfig/Debug.xcconfig" diff --git a/XcodeConfig/Project/DebugiPhone20.xcconfig b/XcodeConfig/Project/DebugiPhone20.xcconfig new file mode 100644 index 0000000..1f08ee4 --- /dev/null +++ b/XcodeConfig/Project/DebugiPhone20.xcconfig @@ -0,0 +1,34 @@ +// +// DebugiPhone20.xcconfig +// +// Xcode configuration file for building a Debug configuration of a project +// for iPhone OS 2.0. +// +// 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. + +// +// 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. + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// iPhone settings +#include "../subconfig/iPhone20.xcconfig" + +// Release settings +#include "../subconfig/Debug.xcconfig" diff --git a/XcodeConfig/Project/DebugiPhone21.xcconfig b/XcodeConfig/Project/DebugiPhone21.xcconfig new file mode 100644 index 0000000..b718cfa --- /dev/null +++ b/XcodeConfig/Project/DebugiPhone21.xcconfig @@ -0,0 +1,34 @@ +// +// DebugiPhone21.xcconfig +// +// Xcode configuration file for building a Debug configuration of a project +// for iPhone OS 2.1. +// +// 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. + +// +// 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. + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// iPhone settings +#include "../subconfig/iPhone21.xcconfig" + +// Release settings +#include "../subconfig/Debug.xcconfig" diff --git a/XcodeConfig/Project/ReleaseiPhone.xcconfig b/XcodeConfig/Project/ReleaseiPhone.xcconfig index 1473a5a..49c1141 100644 --- a/XcodeConfig/Project/ReleaseiPhone.xcconfig +++ b/XcodeConfig/Project/ReleaseiPhone.xcconfig @@ -1,10 +1,10 @@ // -// ReleaseAspenSimulator.xcconfig +// ReleaseiPhone.xcconfig // // Xcode configuration file for building a Release configuration of a project // for iPhone. // -// Copyright 2006-2008 Google Inc. +// 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 @@ -19,16 +19,8 @@ // the License. // -// 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. - -// Pull in the general settings -#include "../subconfig/General.xcconfig" +// This file is deprecated, please use the version specific one instead. +// -// iPhone Settings. -#include "../subconfig/iPhone.xcconfig" +#include "ReleaseiPhone20.xcconfig" -// Release settings -#include "../subconfig/Release.xcconfig" diff --git a/XcodeConfig/Project/ReleaseiPhone20.xcconfig b/XcodeConfig/Project/ReleaseiPhone20.xcconfig new file mode 100644 index 0000000..16895c5 --- /dev/null +++ b/XcodeConfig/Project/ReleaseiPhone20.xcconfig @@ -0,0 +1,34 @@ +// +// ReleaseiPhone20.xcconfig +// +// Xcode configuration file for building a Release configuration of a project +// for iPhone OS 2.0. +// +// 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. + +// +// 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. + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// iPhone Settings. +#include "../subconfig/iPhone20.xcconfig" + +// Release settings +#include "../subconfig/Release.xcconfig" diff --git a/XcodeConfig/Project/ReleaseiPhone21.xcconfig b/XcodeConfig/Project/ReleaseiPhone21.xcconfig new file mode 100644 index 0000000..4ea90d6 --- /dev/null +++ b/XcodeConfig/Project/ReleaseiPhone21.xcconfig @@ -0,0 +1,34 @@ +// +// ReleaseiPhone21.xcconfig +// +// Xcode configuration file for building a Release configuration of a project +// for iPhone OS 2.1. +// +// 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. + +// +// 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. + +// Pull in the general settings +#include "../subconfig/General.xcconfig" + +// iPhone Settings. +#include "../subconfig/iPhone21.xcconfig" + +// Release settings +#include "../subconfig/Release.xcconfig" diff --git a/XcodeConfig/subconfig/General.xcconfig b/XcodeConfig/subconfig/General.xcconfig index 6031f46..114b718 100644 --- a/XcodeConfig/subconfig/General.xcconfig +++ b/XcodeConfig/subconfig/General.xcconfig @@ -21,7 +21,9 @@ // NOTE: as of Xcode 3.1, for iPhone development, the two SDKs you can match are: // SDK_NAME iphoneos2.0 +// SDK_NAME iphoneos2.1 // SDK_NAME iphonesimulator2.0 +// SDK_NAME iphonesimulator2.1 // for Mac OS developement, the values are: // SDK_NAME macosx10.4 // SDK_NAME macosx10.5 diff --git a/XcodeConfig/subconfig/iPhone.xcconfig b/XcodeConfig/subconfig/iPhone.xcconfig deleted file mode 100644 index 0948db8..0000000 --- a/XcodeConfig/subconfig/iPhone.xcconfig +++ /dev/null @@ -1,26 +0,0 @@ -// -// iPhone.xcconfig -// -// Xcode configuration file for building a Debug target on iPhone -// -// Copyright 2006-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. - -// 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 -GCC_VERSION = 4.0 diff --git a/XcodeConfig/subconfig/iPhone20.xcconfig b/XcodeConfig/subconfig/iPhone20.xcconfig new file mode 100644 index 0000000..fea781b --- /dev/null +++ b/XcodeConfig/subconfig/iPhone20.xcconfig @@ -0,0 +1,26 @@ +// +// iPhone20.xcconfig +// +// Xcode configuration file for building a Debug target on iPhone OS 2.0 +// +// 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. + +// 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 +GCC_VERSION = 4.0 diff --git a/XcodeConfig/subconfig/iPhone21.xcconfig b/XcodeConfig/subconfig/iPhone21.xcconfig new file mode 100644 index 0000000..6265000 --- /dev/null +++ b/XcodeConfig/subconfig/iPhone21.xcconfig @@ -0,0 +1,26 @@ +// +// iPhone21.xcconfig +// +// Xcode configuration file for building a Debug target on iPhone OS 2.1 +// +// 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. + +// 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 +GCC_VERSION = 4.0 diff --git a/iPhone/GTMABAddressBook.m b/iPhone/GTMABAddressBook.m index 0c54364..c06b511 100644 --- a/iPhone/GTMABAddressBook.m +++ b/iPhone/GTMABAddressBook.m @@ -189,6 +189,7 @@ typedef struct { - (id)initWithRecord:(ABRecordRef)record { if ((self = [super init])) { if ([self class] == [GTMABRecord class]) { + [self autorelease]; [self doesNotRecognizeSelector:_cmd]; } if (!record) { @@ -509,6 +510,8 @@ typedef struct { @implementation GTMABMultiValue - (id)init { + // Call super init and release so we don't leak + [[super init] autorelease]; [self doesNotRecognizeSelector:_cmd]; return nil; // COV_NF_LINE } diff --git a/iPhone/GTMABAddressBookTest.m b/iPhone/GTMABAddressBookTest.m index 3ecb796..56106a9 100644 --- a/iPhone/GTMABAddressBookTest.m +++ b/iPhone/GTMABAddressBookTest.m @@ -534,24 +534,31 @@ thirdRetainCount, @"Testing type %d, %@", type, val); + id oldVal = val; val = (id)ABMultiValueCopyValueAtIndex(ref, 0); NSUInteger fourthRetainCount = [val retainCount]; - if (type == kABIntegerPropertyType - || type == kABRealPropertyType - || type == kABDictionaryPropertyType) { - // We are verifying that yes indeed 6208390 is still broken - STAssertEquals(fourthRetainCount, - thirdRetainCount, - @"Testing type %d, %@. If you see this error it may " - @"be time to update the code to change retain behaviors" - @"with this os version", type, val); + + // kABDictionaryPropertyTypes appear to do an actual copy, so the retain + // count checking trick won't work. We only check the retain count if + // we didn't get a new version. + if (val == oldVal) { + if (type == kABIntegerPropertyType + || type == kABRealPropertyType) { + // We are verifying that yes indeed 6208390 is still broken + STAssertEquals(fourthRetainCount, + thirdRetainCount, + @"Testing type %d, %@. If you see this error it may " + @"be time to update the code to change retain behaviors" + @"with this os version", type, val); + } else { + STAssertEquals(fourthRetainCount, + thirdRetainCount + 1, + @"Testing type %d, %@", type, val); + [val release]; + } } else { - STAssertEquals(fourthRetainCount, - thirdRetainCount + 1, - @"Testing type %d, %@", type, val); [val release]; } - CFRelease(ref); } } -- cgit v1.2.3