| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /*
- * Copyright 2019 Google
- *
- * 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 <XCTest/XCTest.h>
- #import <OCMock/OCMock.h>
- #import "FBLPromise+Testing.h"
- #import "GoogleUtilities/Example/Tests/Utils/GULTestKeychain.h"
- #import "GoogleUtilities/Environment/Private/GULKeychainStorage.h"
- @interface GULKeychainStorage (Tests)
- - (instancetype)initWithService:(NSString *)service cache:(NSCache *)cache;
- - (void)resetInMemoryCache;
- @end
- @interface GULKeychainStorageTests : XCTestCase
- @property(nonatomic, strong) GULKeychainStorage *storage;
- @property(nonatomic, strong) NSCache *cache;
- @property(nonatomic, strong) id mockCache;
- #if TARGET_OS_OSX
- @property(nonatomic) GULTestKeychain *privateKeychain;
- #endif // TARGET_OSX
- @end
- @implementation GULKeychainStorageTests
- - (void)setUp {
- self.cache = [[NSCache alloc] init];
- self.mockCache = OCMPartialMock(self.cache);
- self.storage = [[GULKeychainStorage alloc] initWithService:@"com.tests.GULKeychainStorageTests"
- cache:self.mockCache];
- #if TARGET_OS_OSX
- self.privateKeychain = [[GULTestKeychain alloc] init];
- self.storage.keychainRef = self.privateKeychain.testKeychainRef;
- #endif // TARGET_OSX
- }
- - (void)tearDown {
- self.storage = nil;
- self.mockCache = nil;
- self.cache = nil;
- #if TARGET_OS_OSX
- self.privateKeychain = nil;
- #endif // TARGET_OSX
- }
- - (void)testSetGetObjectForKey {
- // 1. Write and read object initially.
- [self assertSuccessWriteObject:@[ @1, @2 ] forKey:@"test-key1"];
- [self assertSuccessReadObject:@[ @1, @2 ]
- forKey:@"test-key1"
- class:[NSArray class]
- existsInCache:YES];
- // // 2. Override existing object.
- [self assertSuccessWriteObject:@{@"key" : @"value"} forKey:@"test-key1"];
- [self assertSuccessReadObject:@{@"key" : @"value"}
- forKey:@"test-key1"
- class:[NSDictionary class]
- existsInCache:YES];
- // 3. Read existing object which is not present in in-memory cache.
- [self.cache removeAllObjects];
- [self assertSuccessReadObject:@{@"key" : @"value"}
- forKey:@"test-key1"
- class:[NSDictionary class]
- existsInCache:NO];
- // 4. Write and read an object for another key.
- [self assertSuccessWriteObject:@{@"key" : @"value"} forKey:@"test-key2"];
- [self assertSuccessReadObject:@{@"key" : @"value"}
- forKey:@"test-key2"
- class:[NSDictionary class]
- existsInCache:YES];
- }
- - (void)testGetNonExistingObject {
- [self assertNonExistingObjectForKey:[NSUUID UUID].UUIDString class:[NSArray class]];
- }
- - (void)testGetExistingObjectClassMismatch {
- NSString *key = [NSUUID UUID].UUIDString;
- // Write.
- [self assertSuccessWriteObject:@[ @8 ] forKey:key];
- // Read.
- // Skip in-memory cache because the error is relevant only for Keychain.
- OCMExpect([self.mockCache objectForKey:key]).andReturn(nil);
- FBLPromise<id<NSSecureCoding>> *getPromise = [self.storage getObjectForKey:key
- objectClass:[NSString class]
- accessGroup:nil];
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssertNil(getPromise.value);
- XCTAssertNotNil(getPromise.error);
- // TODO: Test for particular error.
- OCMVerifyAll(self.mockCache);
- }
- - (void)testRemoveExistingObject {
- NSString *key = @"testRemoveExistingObject";
- // Store the object.
- [self assertSuccessWriteObject:@[ @5 ] forKey:(NSString *)key];
- // Remove object.
- [self assertRemoveObjectForKey:key];
- // Check if object is still stored.
- [self assertNonExistingObjectForKey:key class:[NSArray class]];
- }
- - (void)testRemoveNonExistingObject {
- NSString *key = [NSUUID UUID].UUIDString;
- [self assertRemoveObjectForKey:key];
- [self assertNonExistingObjectForKey:key class:[NSArray class]];
- }
- #pragma mark - Common
- - (void)assertSuccessWriteObject:(id<NSSecureCoding>)object forKey:(NSString *)key {
- OCMExpect([self.mockCache setObject:object forKey:key]).andForwardToRealObject();
- FBLPromise<NSNull *> *setPromise = [self.storage setObject:object forKey:key accessGroup:nil];
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssertNil(setPromise.error, @"%@", self.name);
- OCMVerifyAll(self.mockCache);
- // Check in-memory cache.
- XCTAssertEqualObjects([self.cache objectForKey:key], object);
- }
- - (void)assertSuccessReadObject:(id<NSSecureCoding>)object
- forKey:(NSString *)key
- class:(Class)class
- existsInCache:(BOOL)existisInCache {
- OCMExpect([self.mockCache objectForKey:key]).andForwardToRealObject();
- if (!existisInCache) {
- OCMExpect([self.mockCache setObject:object forKey:key]).andForwardToRealObject();
- }
- FBLPromise<id<NSSecureCoding>> *getPromise =
- [self.storage getObjectForKey:key objectClass:class accessGroup:nil];
- XCTAssert(FBLWaitForPromisesWithTimeout(1), @"%@", self.name);
- XCTAssertEqualObjects(getPromise.value, object, @"%@", self.name);
- XCTAssertNil(getPromise.error, @"%@", self.name);
- OCMVerifyAll(self.mockCache);
- // Check in-memory cache.
- XCTAssertEqualObjects([self.cache objectForKey:key], object, @"%@", self.name);
- }
- - (void)assertNonExistingObjectForKey:(NSString *)key class:(Class)class {
- OCMExpect([self.mockCache objectForKey:key]).andForwardToRealObject();
- FBLPromise<id<NSSecureCoding>> *promise =
- [self.storage getObjectForKey:key objectClass:class accessGroup:nil];
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssertNil(promise.error, @"%@", self.name);
- XCTAssertNil(promise.value, @"%@", self.name);
- OCMVerifyAll(self.mockCache);
- }
- - (void)assertRemoveObjectForKey:(NSString *)key {
- OCMExpect([self.mockCache removeObjectForKey:key]).andForwardToRealObject();
- FBLPromise<NSNull *> *removePromise = [self.storage removeObjectForKey:key accessGroup:nil];
- XCTAssert(FBLWaitForPromisesWithTimeout(1));
- XCTAssertNil(removePromise.error);
- OCMVerifyAll(self.mockCache);
- }
- @end
|