1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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: %lu",
(unsigned long)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
|