FIRInstanceIDStoreTest.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * Copyright 2019 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <XCTest/XCTest.h>
  17. #import <FirebaseInstanceID/FIRInstanceIDCheckinPreferences.h>
  18. #import <OCMock/OCMock.h>
  19. #import "FIRInstanceIDFakeKeychain.h"
  20. #import "Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h"
  21. #import "Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h"
  22. #import "Firebase/InstanceID/FIRInstanceIDCheckinService.h"
  23. #import "Firebase/InstanceID/FIRInstanceIDCheckinStore.h"
  24. #import "Firebase/InstanceID/FIRInstanceIDStore.h"
  25. #import "Firebase/InstanceID/FIRInstanceIDTokenInfo.h"
  26. #import "Firebase/InstanceID/FIRInstanceIDTokenStore.h"
  27. #import "Firebase/InstanceID/FIRInstanceIDUtilities.h"
  28. static NSString *const kSubDirectoryName = @"FirebaseInstanceIDStoreTest";
  29. static NSString *const kAuthorizedEntity = @"test-audience";
  30. static NSString *const kScope = @"test-scope";
  31. static NSString *const kToken = @"test-token";
  32. static NSString *const kAuthID = @"test-auth-id";
  33. static NSString *const kSecret = @"test-secret";
  34. @interface FIRInstanceIDStore ()
  35. - (NSString *)tokenWithKey:(NSString *)key;
  36. - (void)cacheToken:(NSString *)token withKey:(NSString *)key;
  37. // APNS
  38. + (NSString *)legacyAPNSTokenCacheKeyForServerType:(BOOL)isSandbox;
  39. + (NSData *)dataWithHexString:(NSString *)hex;
  40. - (void)resetCredentialsIfNeeded;
  41. - (BOOL)hasSavedLibraryVersion;
  42. - (BOOL)hasCheckinPlist;
  43. @end
  44. @interface FIRInstanceIDStoreTest : XCTestCase
  45. @property(strong, nonatomic) FIRInstanceIDStore *instanceIDStore;
  46. @property(strong, nonatomic) FIRInstanceIDBackupExcludedPlist *checkinPlist;
  47. @property(strong, nonatomic) FIRInstanceIDCheckinStore *checkinStore;
  48. @property(strong, nonatomic) FIRInstanceIDTokenStore *tokenStore;
  49. @property(strong, nonatomic) id mockCheckinStore;
  50. @property(strong, nonatomic) id mockTokenStore;
  51. @property(strong, nonatomic) id mockInstanceIDStore;
  52. @end
  53. @implementation FIRInstanceIDStoreTest
  54. - (void)setUp {
  55. [super setUp];
  56. [FIRInstanceIDStore createSubDirectory:kSubDirectoryName];
  57. NSString *checkinPlistName = @"com.google.test.IIDStoreTestCheckin";
  58. self.checkinPlist = [[FIRInstanceIDBackupExcludedPlist alloc] initWithFileName:checkinPlistName
  59. subDirectory:kSubDirectoryName];
  60. // checkin store
  61. FIRInstanceIDFakeKeychain *fakeKeychain = [[FIRInstanceIDFakeKeychain alloc] init];
  62. _checkinStore = [[FIRInstanceIDCheckinStore alloc] initWithCheckinPlist:self.checkinPlist
  63. keychain:fakeKeychain];
  64. _mockCheckinStore = OCMPartialMock(_checkinStore);
  65. // token store
  66. FIRInstanceIDFakeKeychain *fakeTokenKeychain = [[FIRInstanceIDFakeKeychain alloc] init];
  67. _tokenStore = [[FIRInstanceIDTokenStore alloc] initWithKeychain:fakeTokenKeychain];
  68. _mockTokenStore = OCMPartialMock(_tokenStore);
  69. #pragma clang diagnostic push
  70. #pragma clang diagnostic ignored "-Wnonnull"
  71. _instanceIDStore = [[FIRInstanceIDStore alloc] initWithCheckinStore:_mockCheckinStore
  72. tokenStore:_mockTokenStore
  73. delegate:nil];
  74. #pragma clang diagnostic pop
  75. _mockInstanceIDStore = OCMPartialMock(_instanceIDStore);
  76. }
  77. - (void)tearDown {
  78. [self.instanceIDStore removeAllCachedTokensWithHandler:nil];
  79. [self.instanceIDStore removeCheckinPreferencesWithHandler:nil];
  80. [FIRInstanceIDStore removeSubDirectory:kSubDirectoryName error:nil];
  81. [_mockCheckinStore stopMocking];
  82. [_mockTokenStore stopMocking];
  83. [_mockInstanceIDStore stopMocking];
  84. [super tearDown];
  85. }
  86. /**
  87. * Tests that an InstanceID token can be stored in the FIRInstanceIDStore for
  88. * an authorizedEntity and scope.
  89. */
  90. - (void)testSaveToken {
  91. XCTestExpectation *tokenExpectation = [self expectationWithDescription:@"token is saved"];
  92. FIRInstanceIDTokenInfo *tokenInfo =
  93. [[FIRInstanceIDTokenInfo alloc] initWithAuthorizedEntity:kAuthorizedEntity
  94. scope:kScope
  95. token:kToken
  96. appVersion:@"1.0"
  97. firebaseAppID:@"firebaseAppID"];
  98. [self.instanceIDStore saveTokenInfo:tokenInfo
  99. handler:^(NSError *error) {
  100. XCTAssertNil(error);
  101. FIRInstanceIDTokenInfo *retrievedTokenInfo = [self.instanceIDStore
  102. tokenInfoWithAuthorizedEntity:kAuthorizedEntity
  103. scope:kScope];
  104. XCTAssertEqualObjects(retrievedTokenInfo.token, kToken);
  105. [tokenExpectation fulfill];
  106. }];
  107. [self waitForExpectationsWithTimeout:1 handler:nil];
  108. }
  109. /**
  110. * Tests that a token can be removed from from FIRInstanceIDStore's cache when specifying
  111. * its authorizedEntity and scope.
  112. */
  113. - (void)testRemoveCachedToken {
  114. XCTestExpectation *tokenExpectation = [self expectationWithDescription:@"token is removed"];
  115. FIRInstanceIDTokenInfo *tokenInfo =
  116. [[FIRInstanceIDTokenInfo alloc] initWithAuthorizedEntity:kAuthorizedEntity
  117. scope:kScope
  118. token:kToken
  119. appVersion:@"1.0"
  120. firebaseAppID:@"firebaseAppID"];
  121. [self.instanceIDStore
  122. saveTokenInfo:tokenInfo
  123. handler:^(NSError *error) {
  124. XCTAssertNotNil([self.instanceIDStore tokenInfoWithAuthorizedEntity:kAuthorizedEntity
  125. scope:kScope]);
  126. [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:kAuthorizedEntity
  127. scope:kScope];
  128. XCTAssertNil([self.instanceIDStore tokenInfoWithAuthorizedEntity:kAuthorizedEntity
  129. scope:kScope]);
  130. [tokenExpectation fulfill];
  131. }];
  132. [self waitForExpectationsWithTimeout:1 handler:nil];
  133. }
  134. /**
  135. * Tests that a checkin authentication ID can be stored in the FIRInstanceIDStore.
  136. */
  137. - (void)testSaveCheckinAuthID {
  138. XCTestExpectation *checkinExpectation = [self expectationWithDescription:@"checkin is saved"];
  139. NSDictionary *plistContent = @{
  140. kFIRInstanceIDDigestStringKey : @"digest-xyz",
  141. kFIRInstanceIDLastCheckinTimeKey : @(FIRInstanceIDCurrentTimestampInMilliseconds())
  142. };
  143. FIRInstanceIDCheckinPreferences *preferences =
  144. [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:kAuthID secretToken:kSecret];
  145. [preferences updateWithCheckinPlistContents:plistContent];
  146. [self.instanceIDStore
  147. saveCheckinPreferences:preferences
  148. handler:^(NSError *_Nonnull error) {
  149. XCTAssertNil(error);
  150. FIRInstanceIDCheckinPreferences *cachedPreferences =
  151. [self.instanceIDStore cachedCheckinPreferences];
  152. XCTAssertEqualObjects(cachedPreferences.deviceID, kAuthID);
  153. XCTAssertEqualObjects(cachedPreferences.secretToken, kSecret);
  154. [checkinExpectation fulfill];
  155. }];
  156. [self waitForExpectationsWithTimeout:1 handler:nil];
  157. }
  158. /**
  159. * Tests that a checkin authentication ID can be removed from FIRInstanceIDStore's cache.
  160. */
  161. - (void)testRemoveCheckinPreferences {
  162. XCTestExpectation *checkinExpectation = [self expectationWithDescription:@"checkin is removed"];
  163. NSDictionary *plistContent = @{
  164. kFIRInstanceIDDigestStringKey : @"digest-xyz",
  165. kFIRInstanceIDLastCheckinTimeKey : @(FIRInstanceIDCurrentTimestampInMilliseconds())
  166. };
  167. FIRInstanceIDCheckinPreferences *preferences =
  168. [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:kAuthID secretToken:kSecret];
  169. [preferences updateWithCheckinPlistContents:plistContent];
  170. [self.instanceIDStore
  171. saveCheckinPreferences:preferences
  172. handler:^(NSError *error) {
  173. XCTAssertNil(error);
  174. [self.instanceIDStore
  175. removeCheckinPreferencesWithHandler:^(NSError *_Nullable error) {
  176. XCTAssertNil(error);
  177. FIRInstanceIDCheckinPreferences *cachedPreferences =
  178. [self.instanceIDStore cachedCheckinPreferences];
  179. XCTAssertNil(cachedPreferences.deviceID);
  180. XCTAssertNil(cachedPreferences.secretToken);
  181. [checkinExpectation fulfill];
  182. }];
  183. }];
  184. [self waitForExpectationsWithTimeout:1 handler:nil];
  185. }
  186. - (void)testResetCredentialsWithFreshInstall {
  187. FIRInstanceIDCheckinPreferences *checkinPreferences =
  188. [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:kAuthID secretToken:kSecret];
  189. // Expect checkin is removed if it's a fresh install.
  190. [[_mockCheckinStore expect]
  191. removeCheckinPreferencesWithHandler:[OCMArg invokeBlockWithArgs:[NSNull null], nil]];
  192. // Always setting up stub after expect.
  193. OCMStub([_mockCheckinStore cachedCheckinPreferences]).andReturn(checkinPreferences);
  194. // Plist file doesn't exist, meaning this is a fresh install.
  195. OCMStub([_mockCheckinStore hasCheckinPlist]).andReturn(NO);
  196. [_mockInstanceIDStore resetCredentialsIfNeeded];
  197. OCMVerifyAll(_mockCheckinStore);
  198. }
  199. - (void)testResetCredentialsWithoutFreshInstall {
  200. FIRInstanceIDCheckinPreferences *checkinPreferences =
  201. [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:kAuthID secretToken:kSecret];
  202. // Expect migration happens if it's not a fresh install.
  203. [[_mockCheckinStore expect] migrateCheckinItemIfNeeded];
  204. // Always setting up stub after expect.
  205. OCMStub([_mockCheckinStore cachedCheckinPreferences]).andReturn(checkinPreferences);
  206. // Mock plist exists, meaning this is not a fresh install.
  207. OCMStub([_mockCheckinStore hasCheckinPlist]).andReturn(YES);
  208. [_mockInstanceIDStore resetCredentialsIfNeeded];
  209. OCMVerifyAll(_mockCheckinStore);
  210. }
  211. - (void)testResetCredentialsWithNoCachedCheckin {
  212. id niceMockCheckinStore = [OCMockObject niceMockForClass:[FIRInstanceIDCheckinStore class]];
  213. [[niceMockCheckinStore reject]
  214. removeCheckinPreferencesWithHandler:[OCMArg invokeBlockWithArgs:[NSNull null], nil]];
  215. // Always setting up stub after expect.
  216. OCMStub([_mockCheckinStore cachedCheckinPreferences]).andReturn(nil);
  217. [_instanceIDStore resetCredentialsIfNeeded];
  218. OCMVerifyAll(niceMockCheckinStore);
  219. }
  220. @end