| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589 |
- /*
- * 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 <FirebaseInstallations/FirebaseInstallations.h>
- #import "FIRInstanceIDFakeKeychain.h"
- #import "FIRInstanceIDTokenManager+Test.h"
- #import "Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h"
- #import "Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h"
- #import "Firebase/InstanceID/FIRInstanceIDCheckinStore.h"
- #import "Firebase/InstanceID/FIRInstanceIDStore.h"
- #import "Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h"
- #import "Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h"
- #import "Firebase/InstanceID/FIRInstanceIDTokenInfo.h"
- #import "Firebase/InstanceID/FIRInstanceIDTokenManager.h"
- #import "Firebase/InstanceID/FIRInstanceIDTokenOperation.h"
- #import "Firebase/InstanceID/FIRInstanceIDTokenStore.h"
- static NSString *const kSubDirectoryName = @"FirebaseInstanceIDTokenManagerTest";
- static NSString *const kAuthorizedEntity = @"test-authorized-entity";
- static NSString *const kScope = @"test-scope";
- static NSString *const kToken =
- @"cHu_lDPF4EXfo3cdVQhfGg:APA91bGHesgrEsM5j8afb8kKKVwr2Q82NrX_mhLT0URVLYP_"
- @"MVJgvrdNfYfgoiPO4NG8SYA2SsZofP0iRXUv9vKREhLPQh0JDOiQ1MO0ivJyDeRo6_5e8VXLeGTTa0StpzfqETEhMaW7";
- // Use a string (which is converted to NSData) as a placeholder for an actual APNs device token.
- static NSString *const kNewAPNSTokenString = @"newAPNSData";
- @interface FIRInstanceIDTokenOperation ()
- - (void)performTokenOperation;
- - (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result
- token:(nullable NSString *)token
- error:(nullable NSError *)error;
- @end
- @interface FIRInstanceIDTokenManager (ExposedForTests)
- - (BOOL)checkTokenRefreshPolicyForIID:(NSString *)IID;
- - (void)updateToAPNSDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox;
- /**
- * Create a fetch operation. This method can be stubbed to return a particular operation instance,
- * which makes it easier to unit test different behaviors.
- */
- - (FIRInstanceIDTokenFetchOperation *)
- createFetchOperationWithAuthorizedEntity:(NSString *)authorizedEntity
- scope:(NSString *)scope
- options:(NSDictionary<NSString *, NSString *> *)options
- instanceID:(NSString *)instanceID;
- /**
- * Create a delete operation. This method can be stubbed to return a particular operation instance,
- * which makes it easier to unit test different behaviors.
- */
- - (FIRInstanceIDTokenDeleteOperation *)
- createDeleteOperationWithAuthorizedEntity:(NSString *)authorizedEntity
- scope:(NSString *)scope
- checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences
- instanceID:(NSString *)instanceID
- action:(FIRInstanceIDTokenAction)action;
- @end
- @interface FIRInstanceIDTokenManagerTest : XCTestCase
- @property(nonatomic, readwrite, strong) FIRInstanceIDTokenManager *tokenManager;
- @property(nonatomic, readwrite, strong) id mockTokenManager;
- @property(nonatomic, readwrite, strong) FIRInstanceIDBackupExcludedPlist *checkinPlist;
- @property(nonatomic, readwrite, strong) FIRInstanceIDFakeKeychain *fakeKeyChain;
- @property(nonatomic, readwrite, strong) FIRInstanceIDTokenStore *tokenStore;
- @property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *fakeCheckin;
- @property(nonatomic, readwrite, strong) id mockInstallations;
- @property(nonatomic, readwrite, strong) FIRInstallationsAuthTokenResult *FISAuthTokenResult;
- @end
- @implementation FIRInstanceIDTokenManagerTest
- - (void)setUp {
- [super setUp];
- [FIRInstanceIDStore createSubDirectory:kSubDirectoryName];
- NSString *checkinPlistFilename = @"com.google.test.IIDCheckinTest";
- self.checkinPlist =
- [[FIRInstanceIDBackupExcludedPlist alloc] initWithFileName:checkinPlistFilename
- subDirectory:kSubDirectoryName];
- // checkin store
- FIRInstanceIDFakeKeychain *fakeCheckinKeychain = [[FIRInstanceIDFakeKeychain alloc] init];
- FIRInstanceIDCheckinStore *checkinStore =
- [[FIRInstanceIDCheckinStore alloc] initWithCheckinPlist:self.checkinPlist
- keychain:fakeCheckinKeychain];
- // token store
- self.fakeKeyChain = [[FIRInstanceIDFakeKeychain alloc] init];
- self.tokenStore = [[FIRInstanceIDTokenStore alloc] initWithKeychain:_fakeKeyChain];
- self.tokenManager = [[FIRInstanceIDTokenManager alloc] initWithCheckinStore:checkinStore
- tokenStore:self.tokenStore];
- self.mockTokenManager = OCMPartialMock(self.tokenManager);
- self.fakeCheckin = [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:@"fakeDeviceID"
- secretToken:@"fakeSecretToken"];
- // Installations
- self.FISAuthTokenResult = OCMClassMock([FIRInstallationsAuthTokenResult class]);
- OCMStub([self.FISAuthTokenResult authToken]).andReturn(@"FISAuthToken");
- OCMStub([self.FISAuthTokenResult expirationDate]).andReturn([NSDate distantFuture]);
- self.mockInstallations = OCMClassMock([FIRInstallations class]);
- OCMStub([self.mockInstallations installations]).andReturn(self.mockInstallations);
- id authTokenBlockArg = [OCMArg invokeBlockWithArgs:self.FISAuthTokenResult, [NSNull null], nil];
- OCMStub([self.mockInstallations authTokenWithCompletion:authTokenBlockArg]);
- }
- - (void)tearDown {
- self.fakeCheckin = nil;
- [self.mockTokenManager stopMocking];
- self.mockTokenManager = nil;
- self.tokenManager = nil;
- self.tokenStore = nil;
- self.fakeKeyChain = nil;
- NSError *error;
- if (![self.checkinPlist deleteFile:&error]) {
- XCTFail(@"Failed to delete checkin plist %@", error);
- }
- self.checkinPlist = nil;
- [FIRInstanceIDStore removeSubDirectory:kSubDirectoryName error:nil];
- [super tearDown];
- }
- /**
- * Tests that when a new InstanceID token is successfully produced,
- * the callback is invoked with a token that is not an empty string and with no error.
- */
- - (void)testNewTokenSuccess {
- XCTestExpectation *tokenExpectation =
- [self expectationWithDescription:@"New token handler invoked."];
- NSDictionary *tokenOptions = [NSDictionary dictionary];
- // Create a fake operation that always returns success
- FIRInstanceIDTokenFetchOperation *operation =
- [[FIRInstanceIDTokenFetchOperation alloc] initWithAuthorizedEntity:kAuthorizedEntity
- scope:kScope
- options:tokenOptions
- checkinPreferences:self.fakeCheckin
- instanceID:[OCMArg any]];
- id mockOperation = OCMPartialMock(operation);
- [[[mockOperation stub] andDo:^(NSInvocation *invocation) {
- [invocation.target finishWithResult:FIRInstanceIDTokenOperationSucceeded
- token:kToken
- error:nil];
- }] performTokenOperation];
- XCTestExpectation *operationFinishExpectation =
- [self expectationWithDescription:@"operationFinishExpectation"];
- operation.completionBlock = ^{
- [operationFinishExpectation fulfill];
- };
- // Return our fake operation when asked for an operation
- [[[self.mockTokenManager stub] andReturn:operation]
- createFetchOperationWithAuthorizedEntity:[OCMArg any]
- scope:[OCMArg any]
- options:[OCMArg any]
- instanceID:[OCMArg any]];
- [self.tokenManager fetchNewTokenWithAuthorizedEntity:kAuthorizedEntity
- scope:kScope
- instanceID:[OCMArg any]
- options:tokenOptions
- handler:^(NSString *token, NSError *error) {
- XCTAssertNotNil(token);
- XCTAssertGreaterThan(token.length, 0);
- XCTAssertNil(error);
- [tokenExpectation fulfill];
- }];
- [self waitForExpectations:@[ tokenExpectation, operationFinishExpectation ] timeout:1];
- // Make sure the partial mock stops mocking before `operation` is deallocated to avoid crash.
- [mockOperation stopMocking];
- // Keep 'operation' alive, so it's not prematurely destroyed
- XCTAssertNotNil(operation);
- }
- /**
- * Tests that when a new InstanceID token is fetched from the server but unsuccessfully
- * saved on the client we should return an error instead of the fetched token.
- */
- - (void)testNewTokenSaveFailure {
- XCTestExpectation *tokenExpectation =
- [self expectationWithDescription:@"New token handler invoked."];
- NSDictionary *tokenOptions = [NSDictionary dictionary];
- // Simulate write to keychain failure.
- self.fakeKeyChain.cannotWriteToKeychain = YES;
- // Create a fake operation that always returns success
- FIRInstanceIDTokenFetchOperation *operation =
- [[FIRInstanceIDTokenFetchOperation alloc] initWithAuthorizedEntity:kAuthorizedEntity
- scope:kScope
- options:tokenOptions
- checkinPreferences:self.fakeCheckin
- instanceID:[OCMArg any]];
- id mockOperation = OCMPartialMock(operation);
- [[[mockOperation stub] andDo:^(NSInvocation *invocation) {
- [invocation.target finishWithResult:FIRInstanceIDTokenOperationSucceeded
- token:kToken
- error:nil];
- }] performTokenOperation];
- XCTestExpectation *operationFinishExpectation =
- [self expectationWithDescription:@"operationFinishExpectation"];
- operation.completionBlock = ^{
- [operationFinishExpectation fulfill];
- };
- // Return our fake operation when asked for an operation
- [[[self.mockTokenManager stub] andReturn:operation]
- createFetchOperationWithAuthorizedEntity:[OCMArg any]
- scope:[OCMArg any]
- options:[OCMArg any]
- instanceID:[OCMArg any]];
- [self.tokenManager fetchNewTokenWithAuthorizedEntity:kAuthorizedEntity
- scope:kScope
- instanceID:[OCMArg any]
- options:tokenOptions
- handler:^(NSString *token, NSError *error) {
- XCTAssertNil(token);
- XCTAssertNotNil(error);
- [tokenExpectation fulfill];
- }];
- [self waitForExpectations:@[ tokenExpectation, operationFinishExpectation ] timeout:1];
- // Make sure the partial mock stops mocking before `operation` is deallocated to avoid crash.
- [mockOperation stopMocking];
- // Keep 'operation' alive, so it's not prematurely destroyed
- XCTAssertNotNil(operation);
- }
- /**
- * Tests that when there is a failure in producing a new InstanceID token,
- * the callback is invoked with an error and a nil token.
- */
- - (void)testNewTokenFailure {
- XCTestExpectation *tokenExpectation =
- [self expectationWithDescription:@"New token handler invoked."];
- NSDictionary *tokenOptions = [NSDictionary dictionary];
- // Create a fake operation that always returns failure
- FIRInstanceIDTokenFetchOperation *operation =
- [[FIRInstanceIDTokenFetchOperation alloc] initWithAuthorizedEntity:kAuthorizedEntity
- scope:kScope
- options:tokenOptions
- checkinPreferences:self.fakeCheckin
- instanceID:[OCMArg any]];
- id mockOperation = OCMPartialMock(operation);
- [[[mockOperation stub] andDo:^(NSInvocation *invocation) {
- NSError *someError = [[NSError alloc] initWithDomain:@"InstanceIDUnitTest" code:0 userInfo:nil];
- [invocation.target finishWithResult:FIRInstanceIDTokenOperationError token:nil error:someError];
- }] performTokenOperation];
- XCTestExpectation *operationFinishExpectation =
- [self expectationWithDescription:@"operationFinishExpectation"];
- operation.completionBlock = ^{
- [operationFinishExpectation fulfill];
- };
- // Return our fake operation when asked for an operation
- [[[self.mockTokenManager stub] andReturn:operation]
- createFetchOperationWithAuthorizedEntity:[OCMArg any]
- scope:[OCMArg any]
- options:[OCMArg any]
- instanceID:[OCMArg any]];
- [self.tokenManager fetchNewTokenWithAuthorizedEntity:kAuthorizedEntity
- scope:kScope
- instanceID:[OCMArg any]
- options:tokenOptions
- handler:^(NSString *token, NSError *error) {
- XCTAssertNil(token);
- XCTAssertNotNil(error);
- [tokenExpectation fulfill];
- }];
- [self waitForExpectations:@[ tokenExpectation, operationFinishExpectation ] timeout:1];
- // Make sure the partial mock stops mocking before `operation` is deallocated to avoid crash.
- [mockOperation stopMocking];
- // Keep 'operation' alive, so it's not prematurely destroyed
- XCTAssertNotNil(operation);
- }
- /**
- * Tests that when a token is deleted successfully, the callback is invoked with no error.
- */
- - (void)testDeleteTokenSuccess {
- XCTestExpectation *deleteExpectation =
- [self expectationWithDescription:@"Delete handler invoked."];
- // Create a fake operation that always succeeds
- FIRInstanceIDTokenDeleteOperation *operation = [[FIRInstanceIDTokenDeleteOperation alloc]
- initWithAuthorizedEntity:kAuthorizedEntity
- scope:kScope
- checkinPreferences:self.fakeCheckin
- instanceID:[OCMArg any]
- action:FIRInstanceIDTokenActionDeleteToken];
- id mockOperation = OCMPartialMock(operation);
- [[[mockOperation stub] andDo:^(NSInvocation *invocation) {
- [invocation.target finishWithResult:FIRInstanceIDTokenOperationSucceeded token:nil error:nil];
- }] performTokenOperation];
- XCTestExpectation *operationFinishExpectation =
- [self expectationWithDescription:@"operationFinishExpectation"];
- operation.completionBlock = ^{
- [operationFinishExpectation fulfill];
- };
- // Return our fake operation when asked for an operation
- [[[self.mockTokenManager stub] andReturn:operation]
- createDeleteOperationWithAuthorizedEntity:[OCMArg any]
- scope:[OCMArg any]
- checkinPreferences:[OCMArg any]
- instanceID:[OCMArg any]
- action:FIRInstanceIDTokenActionDeleteToken];
- [self.tokenManager deleteTokenWithAuthorizedEntity:kAuthorizedEntity
- scope:kScope
- instanceID:[OCMArg any]
- handler:^(NSError *error) {
- XCTAssertNil(error);
- [deleteExpectation fulfill];
- }];
- [self waitForExpectations:@[ deleteExpectation, operationFinishExpectation ] timeout:1];
- // Make sure the partial mock stops mocking before `operation` is deallocated to avoid crash.
- [mockOperation stopMocking];
- // Keep 'operation' alive, so it's not prematurely destroyed
- XCTAssertNotNil(operation);
- }
- /**
- * Tests that when a token deletion fails, the callback is invoked with an error.
- */
- - (void)testDeleteTokenFailure {
- XCTestExpectation *deleteExpectation =
- [self expectationWithDescription:@"Delete handler invoked."];
- // Create a fake operation that always fails
- FIRInstanceIDTokenDeleteOperation *operation = [[FIRInstanceIDTokenDeleteOperation alloc]
- initWithAuthorizedEntity:kAuthorizedEntity
- scope:kScope
- checkinPreferences:self.fakeCheckin
- instanceID:[OCMArg any]
- action:FIRInstanceIDTokenActionDeleteToken];
- id mockOperation = OCMPartialMock(operation);
- [[[mockOperation stub] andDo:^(NSInvocation *invocation) {
- NSError *someError = [[NSError alloc] initWithDomain:@"InstanceIDUnitTest" code:0 userInfo:nil];
- [invocation.target finishWithResult:FIRInstanceIDTokenOperationError token:nil error:someError];
- }] performTokenOperation];
- XCTestExpectation *operationFinishExpectation =
- [self expectationWithDescription:@"operationFinishExpectation"];
- operation.completionBlock = ^{
- [operationFinishExpectation fulfill];
- };
- // Return our fake operation when asked for an operation
- [[[self.mockTokenManager stub] andReturn:operation]
- createDeleteOperationWithAuthorizedEntity:[OCMArg any]
- scope:[OCMArg any]
- checkinPreferences:[OCMArg any]
- instanceID:[OCMArg any]
- action:FIRInstanceIDTokenActionDeleteToken];
- [self.tokenManager deleteTokenWithAuthorizedEntity:kAuthorizedEntity
- scope:kScope
- instanceID:[OCMArg any]
- handler:^(NSError *error) {
- XCTAssertNotNil(error);
- [deleteExpectation fulfill];
- }];
- [self waitForExpectations:@[ deleteExpectation, operationFinishExpectation ] timeout:1];
- // Make sure the partial mock stops mocking before `operation` is deallocated to avoid crash.
- [mockOperation stopMocking];
- // Keep 'operation' alive, so it's not prematurely destroyed
- XCTAssertNotNil(operation);
- }
- #pragma mark - Cached Token Invalidation
- - (void)testCachedTokensInvalidatedOnAppVersionChange {
- // Write some fake tokens to cache with a old app version "0.9"
- NSArray<NSString *> *entities = @[ @"entity1", @"entity2" ];
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *info =
- [[FIRInstanceIDTokenInfo alloc] initWithAuthorizedEntity:entity
- scope:kScope
- token:@"abcdef"
- appVersion:@"0.9"
- firebaseAppID:nil];
- [self.tokenStore saveTokenInfo:info handler:nil];
- }
- // Ensure they tokens now exist.
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *cachedTokenInfo =
- [self.tokenManager cachedTokenInfoWithAuthorizedEntity:entity scope:kScope];
- XCTAssertNotNil(cachedTokenInfo);
- }
- // Trigger a potential reset, the current app version is 1.0 which is newer than
- // the one set in tokenInfo.
- [self.tokenManager checkTokenRefreshPolicyWithIID:@"abc"];
- // Ensure that token data is now missing
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *cachedTokenInfo =
- [self.tokenManager cachedTokenInfoWithAuthorizedEntity:entity scope:kScope];
- XCTAssertNil(cachedTokenInfo);
- }
- }
- - (void)testTokenShouldBeDeletedIfWrongFormat {
- // Cache some token
- NSArray<NSString *> *entities = @[ @"entity1", @"entity2" ];
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *info = [[FIRInstanceIDTokenInfo alloc] initWithAuthorizedEntity:entity
- scope:kScope
- token:kToken
- appVersion:nil
- firebaseAppID:nil];
- [self.tokenStore saveTokenInfo:info handler:nil];
- }
- // Ensure they tokens now exist.
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *cachedTokenInfo =
- [self.tokenManager cachedTokenInfoWithAuthorizedEntity:entity scope:kScope];
- XCTAssertNotNil(cachedTokenInfo);
- }
- // Trigger a potential reset, the current IID is sth differnt than the token
- [self.tokenManager checkTokenRefreshPolicyWithIID:@"d8xQyABOoV8"];
- // Ensure that token data is now missing
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *cachedTokenInfo =
- [self.tokenManager cachedTokenInfoWithAuthorizedEntity:entity scope:kScope];
- XCTAssertNil(cachedTokenInfo);
- }
- }
- - (void)testCachedTokensInvalidatedOnAPNSAddition {
- // Write some fake tokens to cache, which have no APNs info
- NSArray<NSString *> *entities = @[ @"entity1", @"entity2" ];
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *info = [[FIRInstanceIDTokenInfo alloc] initWithAuthorizedEntity:entity
- scope:kScope
- token:kToken
- appVersion:nil
- firebaseAppID:nil];
- [self.tokenStore saveTokenInfo:info handler:nil];
- }
- // Ensure the tokens now exist.
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *cachedTokenInfo =
- [self.tokenManager cachedTokenInfoWithAuthorizedEntity:entity scope:kScope];
- XCTAssertNotNil(cachedTokenInfo);
- }
- // Trigger a potential reset.
- [self triggerAPNSTokenChange];
- // Ensure that token data is now missing
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *cachedTokenInfo =
- [self.tokenManager cachedTokenInfoWithAuthorizedEntity:entity scope:kScope];
- XCTAssertNil(cachedTokenInfo);
- }
- }
- - (void)testCachedTokensInvalidatedOnAPNSChange {
- // Write some fake tokens to cache
- NSArray<NSString *> *entities = @[ @"entity1", @"entity2" ];
- NSData *oldAPNSData = [@"oldAPNSToken" dataUsingEncoding:NSUTF8StringEncoding];
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *info = [[FIRInstanceIDTokenInfo alloc] initWithAuthorizedEntity:entity
- scope:kScope
- token:kToken
- appVersion:nil
- firebaseAppID:nil];
- info.APNSInfo = [[FIRInstanceIDAPNSInfo alloc] initWithDeviceToken:oldAPNSData isSandbox:NO];
- [self.tokenStore saveTokenInfo:info handler:nil];
- }
- // Ensure the tokens now exist.
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *cachedTokenInfo =
- [self.tokenManager cachedTokenInfoWithAuthorizedEntity:entity scope:kScope];
- XCTAssertNotNil(cachedTokenInfo);
- }
- // Trigger a potential reset.
- [self triggerAPNSTokenChange];
- // Ensure that token data is now missing
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *cachedTokenInfo =
- [self.tokenManager cachedTokenInfoWithAuthorizedEntity:entity scope:kScope];
- XCTAssertNil(cachedTokenInfo);
- }
- }
- - (void)testCachedTokensNotInvalidatedIfAPNSSame {
- // Write some fake tokens to cache, with the current APNs token
- NSArray<NSString *> *entities = @[ @"entity1", @"entity2" ];
- NSString *apnsDataString = kNewAPNSTokenString;
- NSData *currentAPNSData = [apnsDataString dataUsingEncoding:NSUTF8StringEncoding];
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *info = [[FIRInstanceIDTokenInfo alloc] initWithAuthorizedEntity:entity
- scope:kScope
- token:kToken
- appVersion:nil
- firebaseAppID:nil];
- info.APNSInfo = [[FIRInstanceIDAPNSInfo alloc] initWithDeviceToken:currentAPNSData
- isSandbox:NO];
- [self.tokenStore saveTokenInfo:info handler:nil];
- }
- // Ensure the tokens now exist.
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *cachedTokenInfo =
- [self.tokenManager cachedTokenInfoWithAuthorizedEntity:entity scope:kScope];
- XCTAssertNotNil(cachedTokenInfo);
- }
- // Trigger a potential reset.
- [self triggerAPNSTokenChange];
- // Ensure that token data is still there
- for (NSString *entity in entities) {
- FIRInstanceIDTokenInfo *cachedTokenInfo =
- [self.tokenManager cachedTokenInfoWithAuthorizedEntity:entity scope:kScope];
- XCTAssertNotNil(cachedTokenInfo);
- }
- }
- - (void)triggerAPNSTokenChange {
- // Trigger a potential reset.
- NSData *deviceToken = [kNewAPNSTokenString dataUsingEncoding:NSUTF8StringEncoding];
- [self.tokenManager updateTokensToAPNSDeviceToken:deviceToken isSandbox:NO];
- }
- @end
|