aboutsummaryrefslogtreecommitdiff
path: root/UnitTesting/GTMIPhoneSecurityLibraryTest.m
blob: f6fd37acf71d8f8f33f821d51071c71d2146388a (plain)
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