diff options
-rw-r--r-- | GTMiPhone.xcodeproj/project.pbxproj | 16 | ||||
-rw-r--r-- | UnitTesting/GTMIPhoneSecurityLibraryTest.m | 75 | ||||
-rwxr-xr-x | UnitTesting/RunIPhoneLaunchDaemons.sh | 43 | ||||
-rwxr-xr-x | UnitTesting/RunIPhoneUnitTest.sh | 28 |
4 files changed, 115 insertions, 47 deletions
diff --git a/GTMiPhone.xcodeproj/project.pbxproj b/GTMiPhone.xcodeproj/project.pbxproj index 41d7fb0..d241ce9 100644 --- a/GTMiPhone.xcodeproj/project.pbxproj +++ b/GTMiPhone.xcodeproj/project.pbxproj @@ -34,6 +34,10 @@ 1D3623EC0D0F72F000981E51 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */; }; 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 23220A06152C9E980060CB7D /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23220A05152C9E980060CB7D /* Security.framework */; }; + 234E175D152CBB4900CF3542 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23220A05152C9E980060CB7D /* Security.framework */; }; + 234E17DC152CECFB00CF3542 /* GTMIPhoneSecurityLibraryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 234E17DB152CECFB00CF3542 /* GTMIPhoneSecurityLibraryTest.m */; }; + 234E17DD152CECFB00CF3542 /* GTMIPhoneSecurityLibraryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 234E17DB152CECFB00CF3542 /* GTMIPhoneSecurityLibraryTest.m */; }; 448D61FB11AC1F1B0097ACBC /* GTMUIImage+Resize_100x50_flipped.png in Resources */ = {isa = PBXBuildFile; fileRef = 448D61B111AC1AAD0097ACBC /* GTMUIImage+Resize_100x50_flipped.png */; }; 448D61FC11AC1F250097ACBC /* GTMUIImage+Resize_50x100_flipped.png in Resources */ = {isa = PBXBuildFile; fileRef = 448D61B011AC1AAD0097ACBC /* GTMUIImage+Resize_50x100_flipped.png */; }; 6294461C0EDE178D009295EA /* GTMNSArray+MergeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 629446190EDE177A009295EA /* GTMNSArray+MergeTest.m */; }; @@ -319,6 +323,8 @@ 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 1D6058910D05DD3D006BFB54 /* GTMiPhoneTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GTMiPhoneTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 23220A05152C9E980060CB7D /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 234E17DB152CECFB00CF3542 /* GTMIPhoneSecurityLibraryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMIPhoneSecurityLibraryTest.m; sourceTree = "<group>"; }; 32CA4F630368D1EE00C91783 /* GTM_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTM_Prefix.pch; sourceTree = "<group>"; }; 448D61B011AC1AAD0097ACBC /* GTMUIImage+Resize_50x100_flipped.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "GTMUIImage+Resize_50x100_flipped.png"; path = "TestData/GTMUIImage+Resize_50x100_flipped.png"; sourceTree = "<group>"; }; 448D61B111AC1AAD0097ACBC /* GTMUIImage+Resize_100x50_flipped.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "GTMUIImage+Resize_100x50_flipped.png"; path = "TestData/GTMUIImage+Resize_100x50_flipped.png"; sourceTree = "<group>"; }; @@ -506,6 +512,7 @@ 8BC04D480DB0088500C2D1CA /* libz.dylib in Frameworks */, 8B3AA9340E0336AC007E31B5 /* CFNetwork.framework in Frameworks */, 8B5A9E200E71CB6C005DA441 /* AddressBook.framework in Frameworks */, + 23220A06152C9E980060CB7D /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -521,6 +528,7 @@ F4D20F2514852D130001600C /* UIKit.framework in Frameworks */, F4D20F2614852D130001600C /* libz.dylib in Frameworks */, F4D20F4E148532D50001600C /* AddressBook.framework in Frameworks */, + 234E175D152CBB4900CF3542 /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -570,6 +578,7 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + 23220A05152C9E980060CB7D /* Security.framework */, 8B3AA9330E0336AC007E31B5 /* CFNetwork.framework */, 8B5A9E1F0E71CB6C005DA441 /* AddressBook.framework */, 8BC04D470DB0088500C2D1CA /* libz.dylib */, @@ -774,6 +783,7 @@ 8B5547C70DB3BBF20014CC1C /* GTMUIKit+UnitTesting.m */, 8B5547C80DB3BBF20014CC1C /* GTMUIKit+UnitTesting.h */, 8B5547C90DB3BBF20014CC1C /* GTMUIKit+UnitTestingTest.m */, + 234E17DB152CECFB00CF3542 /* GTMIPhoneSecurityLibraryTest.m */, 67A7820A0E00927400EBF506 /* GTMIPhoneUnitTestDelegate.h */, 67A7820B0E00927400EBF506 /* GTMIPhoneUnitTestDelegate.m */, 8BC047DD0DAE928A00C2D1CA /* GTMIPhoneUnitTestMain.m */, @@ -1036,7 +1046,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Nuke coverage data earch run\nexport GTM_REMOVE_GCOV_DATA=1\n# Run the unit tests in this test bundle.\n\"${SRCROOT}/UnitTesting/RunIPhoneUnitTest.sh\"\n"; + shellScript = "# Nuke coverage data earch run\nexport GTM_REMOVE_GCOV_DATA=1\n\n# Enable launch daemons for security tests.\nexport GTM_DISABLE_IPHONE_LAUNCH_DAEMONS=0\n\n# Run the unit tests in this test bundle.\n${SRCROOT}/UnitTesting/RunIPhoneUnitTest.sh\n"; }; F4D20EA814852BFB0001600C /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -1087,6 +1097,7 @@ 8B7DCEAD0DFF4CA60017E983 /* GTMUnitTestDevLog.m in Sources */, 67A7820C0E00927400EBF506 /* GTMIPhoneUnitTestDelegate.m in Sources */, 8B3AA8F30E032FC7007E31B5 /* GTMNSString+URLArguments.m in Sources */, + F4746721129703600022C1FB /* GTMSenTestCaseTest.m in Sources */, 8B3AA8F40E032FC7007E31B5 /* GTMNSString+URLArgumentsTest.m in Sources */, 8B41EC0F0E0711D40040CF9F /* GTMValidatingContainersTest.m in Sources */, 8B41EC100E0711D40040CF9F /* GTMValidatingContainers.m in Sources */, @@ -1131,7 +1142,6 @@ 8BFFCD7811C1934900E45777 /* GTMNSObject+KeyValueObservingTest.m in Sources */, 8B2908B211F8E7070064F50F /* GTMNSFileHandle+UniqueName.m in Sources */, 8B2908B311F8E7070064F50F /* GTMNSFileHandle+UniqueNameTest.m in Sources */, - F4746721129703600022C1FB /* GTMSenTestCaseTest.m in Sources */, 9340CF9F140550CE0026DDC9 /* GTMFadeTruncatingLabel.m in Sources */, 9340CFA0140550CE0026DDC9 /* GTMFadeTruncatingLabelTest.m in Sources */, 169E1E2F1459AAE100E6F562 /* GTMUILocalizer.m in Sources */, @@ -1141,6 +1151,7 @@ 8B6FF394151A664600B0642B /* GTMNSThread+Blocks.m in Sources */, 8B6FF396151A664600B0642B /* GTMNSThread+BlocksTest.m in Sources */, 8B6FF39A151A670100B0642B /* GTMFoundationUnitTestingUtilities.m in Sources */, + 234E17DC152CECFB00CF3542 /* GTMIPhoneSecurityLibraryTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1229,6 +1240,7 @@ 8B6FF395151A664600B0642B /* GTMNSThread+Blocks.m in Sources */, 8B6FF397151A664600B0642B /* GTMNSThread+BlocksTest.m in Sources */, 8B6FF39B151A670100B0642B /* GTMFoundationUnitTestingUtilities.m in Sources */, + 234E17DD152CECFB00CF3542 /* GTMIPhoneSecurityLibraryTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/UnitTesting/GTMIPhoneSecurityLibraryTest.m b/UnitTesting/GTMIPhoneSecurityLibraryTest.m new file mode 100644 index 0000000..951ca98 --- /dev/null +++ b/UnitTesting/GTMIPhoneSecurityLibraryTest.m @@ -0,0 +1,75 @@ +// +// GTMIPhoneSecurityLibraryTest.m +// +// Copyright 2012 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" + +// Tests that using the keychain library within unit tests works correctly. +@interface GTMIPhoneSecurityLibraryTest : GTMTestCase +@end + +@implementation GTMIPhoneSecurityLibraryTest + +static NSString * const kAccount = @"GTMTestingSecurityAccount"; +static NSString * const kService = @"GTMTestingSecurityService"; +static NSString * const kPassword = @"GTMTestingSecurityPassword"; + +- (NSMutableDictionary *)keychainQueryItem { + return [NSMutableDictionary dictionaryWithObjectsAndKeys: + (id)kSecClassGenericPassword, (id)kSecClass, + kAccount, (id)kSecAttrAccount, + kService, (id)kSecAttrService, + nil]; +} + +- (void)assertCorrectPassword { + NSMutableDictionary *keychainQueryItem = [self keychainQueryItem]; + [keychainQueryItem setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; + [keychainQueryItem setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; + + CFDataRef result = NULL; + OSStatus status = SecItemCopyMatching((CFDictionaryRef)keychainQueryItem, + (CFTypeRef *)&result); + STAssertEquals(status, + (OSStatus)noErr, + @"Error retrieving password from keychain"); + STAssertNotNULL(result, @"No password found"); + NSString *password = + [[[NSString alloc] initWithData:(NSData *)result + encoding:NSUTF8StringEncoding] autorelease]; + STAssertEqualStrings(kPassword, password, @"Unexpected password found"); + CFRelease(result); +} + +- (void)testSecurityCalls { + NSMutableDictionary *passwordItem = [self keychainQueryItem]; + NSData *passwordData = [kPassword dataUsingEncoding:NSUTF8StringEncoding]; + [passwordItem setObject:passwordData forKey:(id)kSecValueData]; + + OSStatus result = SecItemAdd((CFDictionaryRef)passwordItem, NULL); + STAssertTrue(result == noErr || result == errSecDuplicateItem, + @"Unexpected result code: %d", + result); + [self assertCorrectPassword]; + + // Test that accessing the keychain will continue to work after a delay. + NSDate *sleepUntil = [NSDate dateWithTimeIntervalSinceNow:30]; + [[NSRunLoop mainRunLoop] runUntilDate:sleepUntil]; + [self assertCorrectPassword]; +} + +@end diff --git a/UnitTesting/RunIPhoneLaunchDaemons.sh b/UnitTesting/RunIPhoneLaunchDaemons.sh deleted file mode 100755 index da230ac..0000000 --- a/UnitTesting/RunIPhoneLaunchDaemons.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -# RunIPhoneLaunchDaemons.sh -# Copyright 2010 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. -# -# Runs all unittests through the iPhone simulator. We don't handle running them -# on the device. To run on the device just choose "run". - -# Starts up securityd for us so that we can access the keychain from our tests. -# Turns out that when you run the simulator without the UI front end, that -# some iPhone launch daemons aren't started correctly. -# This script starts up securityd for us. -# We may need to startup other services in the future. -# This script is launched by launchd. -# -# arg1 - root to the iPhone SDK being used -# arg2 - path to the user directory to use - -set -o errexit -set -o nounset -# Uncomment the next line to trace execution. -#set -o verbose - -# These both need to be set to the root of the iPhone SDK for iPhone -# apps to be able to find their frameworks. -export DYLD_ROOT_PATH="$1" -export IPHONE_SIMULATOR_ROOT="$1" - -# This needs to be set to the user's directory to find preference files. -export CFFIXED_USER_HOME="$2" - -"$IPHONE_SIMULATOR_ROOT/usr/libexec/securityd" diff --git a/UnitTesting/RunIPhoneUnitTest.sh b/UnitTesting/RunIPhoneUnitTest.sh index 7721fcd..ce3f2dc 100755 --- a/UnitTesting/RunIPhoneUnitTest.sh +++ b/UnitTesting/RunIPhoneUnitTest.sh @@ -74,6 +74,26 @@ GTMXcodeNote() { echo ${ThisScript}:${1}: note: GTM ${2} } +# Creates a file containing the plist for the securityd daemon and prints the +# filename to stdout. +GTMCreateLaunchDaemonPlist() { + local plist_file + plist_file="$TMPDIR/securityd.$$.plist" + echo $plist_file + + # Create the plist file with PlistBuddy. + /usr/libexec/PlistBuddy \ + -c "Add :Label string RunIPhoneLaunchDaemons" \ + -c "Add :ProgramArguments array" \ + -c "Add :ProgramArguments: string \"$IPHONE_SIMULATOR_ROOT/usr/libexec/securityd\"" \ + -c "Add :EnvironmentVariables dict" \ + -c "Add :EnvironmentVariables:DYLD_ROOT_PATH string \"$IPHONE_SIMULATOR_ROOT\"" \ + -c "Add :EnvironmentVariables:IPHONE_SIMULATOR_ROOT string \"$IPHONE_SIMULATOR_ROOT\"" \ + -c "Add :EnvironmentVariables:CFFIXED_USER_HOME string \"$CFFIXED_USER_HOME\"" \ + -c "Add :MachServices dict" \ + -c "Add :MachServices:com.apple.securityd bool YES" "$plist_file" > /dev/null +} + 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 @@ -121,9 +141,13 @@ if [ "$PLATFORM_NAME" == "iphonesimulator" ]; then # presence as 'launchctl remove' will kill this script if run from within an # Xcode build. launchctl list | grep RunIPhoneLaunchDaemons && launchctl remove RunIPhoneLaunchDaemons + # If we want to test anything that interacts with the keychain, we need - # securityd up and running. See RunIPhoneLaunchDaemons.sh for details. - launchctl submit -l RunIPhoneLaunchDaemons -- "${ScriptDir}/RunIPhoneLaunchDaemons.sh" $IPHONE_SIMULATOR_ROOT $CFFIXED_USER_HOME + # securityd up and running. + LAUNCH_DAEMON_PLIST="$(GTMCreateLaunchDaemonPlist)" + launchctl load $LAUNCH_DAEMON_PLIST + rm $LAUNCH_DAEMON_PLIST + # No matter how we exit, we want to shut down our launchctl job. trap "launchctl remove RunIPhoneLaunchDaemons" INT TERM EXIT fi |