FIRInstallationsTests.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  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 <OCMock/OCMock.h>
  18. #import "FBLPromise+Testing.h"
  19. #import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
  20. #import "FirebaseInstallations/Source/Tests/Utils/FIRInstallations+Tests.h"
  21. #import "FirebaseInstallations/Source/Tests/Utils/FIRInstallationsErrorUtil+Tests.h"
  22. #import "FirebaseInstallations/Source/Tests/Utils/FIRInstallationsItem+Tests.h"
  23. #import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h"
  24. #import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h"
  25. #import "FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h"
  26. #import "FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h"
  27. #import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h"
  28. #import "FirebaseInstallations/Source/Library/Public/FirebaseInstallations/FIRInstallations.h"
  29. @interface FIRInstallationsTests : XCTestCase
  30. @property(nonatomic) FIRInstallations *installations;
  31. @property(nonatomic) id mockIDController;
  32. @property(nonatomic) FIROptions *appOptions;
  33. @end
  34. @implementation FIRInstallationsTests
  35. - (void)setUp {
  36. [super setUp];
  37. self.appOptions = [[FIROptions alloc] initWithGoogleAppID:@"GoogleAppID"
  38. GCMSenderID:@"GCMSenderID"];
  39. self.appOptions.APIKey = @"AIzaSy-ApiKeyWithValidFormat_0123456789";
  40. self.appOptions.projectID = @"ProjectID";
  41. self.mockIDController = OCMClassMock([FIRInstallationsIDController class]);
  42. self.installations = [[FIRInstallations alloc] initWithAppOptions:self.appOptions
  43. appName:@"appName"
  44. installationsIDController:self.mockIDController
  45. prefetchAuthToken:NO];
  46. }
  47. - (void)tearDown {
  48. self.installations = nil;
  49. self.mockIDController = nil;
  50. [super tearDown];
  51. }
  52. - (void)testDefaultInstallationWhenNoDefaultAppThenIsNil {
  53. XCTAssertThrows([FIRInstallations installations]);
  54. }
  55. - (void)testInstallationIDSuccess {
  56. // Stub get installation.
  57. FIRInstallationsItem *installation = [FIRInstallationsItem createUnregisteredInstallationItem];
  58. OCMExpect([self.mockIDController getInstallationItem])
  59. .andReturn([FBLPromise resolvedWith:installation]);
  60. XCTestExpectation *idExpectation = [self expectationWithDescription:@"InstallationIDSuccess"];
  61. [self.installations
  62. installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) {
  63. XCTAssertNil(error);
  64. XCTAssertNotNil(identifier);
  65. XCTAssertEqualObjects(identifier, installation.firebaseInstallationID);
  66. [idExpectation fulfill];
  67. }];
  68. [self waitForExpectations:@[ idExpectation ] timeout:0.5];
  69. OCMVerifyAll(self.mockIDController);
  70. }
  71. - (void)testInstallationIDError {
  72. // Stub get installation.
  73. FBLPromise *errorPromise = [FBLPromise pendingPromise];
  74. NSError *privateError = [NSError errorWithDomain:@"TestsError" code:-1 userInfo:nil];
  75. [errorPromise reject:privateError];
  76. OCMExpect([self.mockIDController getInstallationItem]).andReturn(errorPromise);
  77. XCTestExpectation *idExpectation = [self expectationWithDescription:@"InstallationIDSuccess"];
  78. [self.installations
  79. installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) {
  80. XCTAssertNil(identifier);
  81. XCTAssertNotNil(error);
  82. XCTAssertEqualObjects(error.domain, kFirebaseInstallationsErrorDomain);
  83. XCTAssertEqualObjects(error.userInfo[NSUnderlyingErrorKey], errorPromise.error);
  84. [idExpectation fulfill];
  85. }];
  86. [self waitForExpectations:@[ idExpectation ] timeout:0.5];
  87. OCMVerifyAll(self.mockIDController);
  88. }
  89. - (void)testAuthTokenSuccess {
  90. FIRInstallationsItem *installationWithToken =
  91. [FIRInstallationsItem createRegisteredInstallationItemWithAppID:self.appOptions.googleAppID
  92. appName:@"appName"];
  93. installationWithToken.authToken.token = @"token";
  94. installationWithToken.authToken.expirationDate = [NSDate dateWithTimeIntervalSinceNow:1000];
  95. OCMExpect([self.mockIDController getAuthTokenForcingRefresh:NO])
  96. .andReturn([FBLPromise resolvedWith:installationWithToken]);
  97. XCTestExpectation *tokenExpectation = [self expectationWithDescription:@"AuthTokenSuccess"];
  98. [self.installations
  99. authTokenWithCompletion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult,
  100. NSError *_Nullable error) {
  101. XCTAssertNotNil(tokenResult);
  102. XCTAssertGreaterThan(tokenResult.authToken.length, 0);
  103. XCTAssertTrue([tokenResult.expirationDate laterDate:[NSDate date]]);
  104. XCTAssertNil(error);
  105. [tokenExpectation fulfill];
  106. }];
  107. [self waitForExpectations:@[ tokenExpectation ] timeout:0.5];
  108. OCMVerifyAll(self.mockIDController);
  109. }
  110. - (void)testAuthTokenError {
  111. FBLPromise *errorPromise = [FBLPromise pendingPromise];
  112. [errorPromise reject:[FIRInstallationsErrorUtil
  113. APIErrorWithHTTPCode:FIRInstallationsHTTPCodesServerInternalError]];
  114. OCMExpect([self.mockIDController getAuthTokenForcingRefresh:NO]).andReturn(errorPromise);
  115. XCTestExpectation *tokenExpectation = [self expectationWithDescription:@"AuthTokenSuccess"];
  116. [self.installations
  117. authTokenWithCompletion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult,
  118. NSError *_Nullable error) {
  119. XCTAssertNil(tokenResult);
  120. XCTAssertEqualObjects(error, errorPromise.error);
  121. [tokenExpectation fulfill];
  122. }];
  123. [self waitForExpectations:@[ tokenExpectation ] timeout:0.5];
  124. OCMVerifyAll(self.mockIDController);
  125. }
  126. - (void)testAuthTokenForcingRefreshSuccess {
  127. FIRInstallationsItem *installationWithToken =
  128. [FIRInstallationsItem createRegisteredInstallationItemWithAppID:self.appOptions.googleAppID
  129. appName:@"appName"];
  130. installationWithToken.authToken.token = @"token";
  131. installationWithToken.authToken.expirationDate = [NSDate dateWithTimeIntervalSinceNow:1000];
  132. OCMExpect([self.mockIDController getAuthTokenForcingRefresh:YES])
  133. .andReturn([FBLPromise resolvedWith:installationWithToken]);
  134. XCTestExpectation *tokenExpectation = [self expectationWithDescription:@"AuthTokenSuccess"];
  135. [self.installations
  136. authTokenForcingRefresh:YES
  137. completion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult,
  138. NSError *_Nullable error) {
  139. XCTAssertNil(error);
  140. XCTAssertNotNil(tokenResult);
  141. XCTAssertEqualObjects(tokenResult.authToken,
  142. installationWithToken.authToken.token);
  143. XCTAssertEqualObjects(tokenResult.expirationDate,
  144. installationWithToken.authToken.expirationDate);
  145. [tokenExpectation fulfill];
  146. }];
  147. [self waitForExpectations:@[ tokenExpectation ] timeout:0.5];
  148. OCMVerifyAll(self.mockIDController);
  149. }
  150. - (void)testAuthTokenForcingRefreshError {
  151. FBLPromise *errorPromise = [FBLPromise pendingPromise];
  152. [errorPromise reject:[FIRInstallationsErrorUtil
  153. APIErrorWithHTTPCode:FIRInstallationsHTTPCodesServerInternalError]];
  154. OCMExpect([self.mockIDController getAuthTokenForcingRefresh:YES]).andReturn(errorPromise);
  155. XCTestExpectation *tokenExpectation = [self expectationWithDescription:@"AuthTokenSuccess"];
  156. [self.installations
  157. authTokenForcingRefresh:YES
  158. completion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult,
  159. NSError *_Nullable error) {
  160. XCTAssertNil(tokenResult);
  161. XCTAssertEqualObjects(error, errorPromise.error);
  162. [tokenExpectation fulfill];
  163. }];
  164. [self waitForExpectations:@[ tokenExpectation ] timeout:0.5];
  165. OCMVerifyAll(self.mockIDController);
  166. }
  167. - (void)testDeleteSuccess {
  168. OCMExpect([self.mockIDController deleteInstallation])
  169. .andReturn([FBLPromise resolvedWith:[NSNull null]]);
  170. XCTestExpectation *deleteExpectation = [self expectationWithDescription:@"DeleteSuccess"];
  171. [self.installations deleteWithCompletion:^(NSError *_Nullable error) {
  172. XCTAssertNil(error);
  173. [deleteExpectation fulfill];
  174. }];
  175. [self waitForExpectations:@[ deleteExpectation ] timeout:0.5];
  176. }
  177. - (void)testDeleteError {
  178. FBLPromise *errorPromise = [FBLPromise pendingPromise];
  179. NSError *APIError =
  180. [FIRInstallationsErrorUtil APIErrorWithHTTPCode:FIRInstallationsHTTPCodesServerInternalError];
  181. [errorPromise reject:APIError];
  182. OCMExpect([self.mockIDController deleteInstallation]).andReturn(errorPromise);
  183. XCTestExpectation *deleteExpectation = [self expectationWithDescription:@"deleteExpectation"];
  184. [self.installations deleteWithCompletion:^(NSError *_Nullable error) {
  185. XCTAssertEqualObjects(error, APIError);
  186. [deleteExpectation fulfill];
  187. }];
  188. [self waitForExpectations:@[ deleteExpectation ] timeout:0.5];
  189. }
  190. #pragma mark - Invalid Firebase configuration
  191. - (void)testInitWhenProjectIDMissingThenThrow {
  192. FIROptions *options = [self.appOptions copy];
  193. options.projectID = nil;
  194. XCTAssertThrows([self createInstallationsWithAppOptions:options appName:@"missingProjectID"]);
  195. options.projectID = @"";
  196. XCTAssertThrows([self createInstallationsWithAppOptions:options appName:@"emptyProjectID"]);
  197. }
  198. - (void)testInitWhenAPIKeyMissingThenThrows {
  199. FIROptions *options = [self.appOptions copy];
  200. options.APIKey = nil;
  201. XCTAssertThrows([self createInstallationsWithAppOptions:options appName:@"missingAPIKey"]);
  202. options.APIKey = @"";
  203. XCTAssertThrows([self createInstallationsWithAppOptions:options appName:@"emptyAPIKey"]);
  204. }
  205. - (void)testInitWhenGoogleAppIDMissingThenThrows {
  206. FIROptions *options = [self.appOptions copy];
  207. options.googleAppID = @"";
  208. XCTAssertThrows([self createInstallationsWithAppOptions:options appName:@"emptyGoogleAppID"]);
  209. }
  210. - (void)testInitWhenGCMSenderIDMissingThenThrows {
  211. FIROptions *options = [self.appOptions copy];
  212. options.GCMSenderID = @"";
  213. XCTAssertNoThrow([self createInstallationsWithAppOptions:options appName:@"emptyGCMSenderID"]);
  214. }
  215. - (void)testInitWhenAppNameMissingThenThrows {
  216. FIROptions *options = [self.appOptions copy];
  217. XCTAssertThrows([self createInstallationsWithAppOptions:options appName:@""]);
  218. XCTAssertThrows([self createInstallationsWithAppOptions:options appName:nil]);
  219. }
  220. - (void)testInitWhenAppOptionsMissingThenThrows {
  221. XCTAssertThrows([self createInstallationsWithAppOptions:nil appName:@"missingOptions"]);
  222. }
  223. - (void)testInitWithAPIKeyIsNotMatchingExpectedFormat {
  224. FIROptions *options = [self.appOptions copy];
  225. options.APIKey = @"AIzaSy-ApiKeyTooShort_0123456789012345";
  226. XCTAssertThrows([self createInstallationsWithAppOptions:options appName:@"shortAPIKey"]);
  227. options.APIKey = @"AIzaSy-ApiKeyWithLengthTooLong_0123456789";
  228. XCTAssertThrows([self createInstallationsWithAppOptions:options appName:@"longAPIKey"]);
  229. options.APIKey = @"BBAIzaSy-ApiKeyInvalidFormat_0123456789";
  230. XCTAssertThrows([self createInstallationsWithAppOptions:options appName:@"wrongFirstCharacter"]);
  231. options.APIKey = @"AIzaSy-+-ApiKeyInvalidFormat_0123456789";
  232. XCTAssertThrows([self createInstallationsWithAppOptions:options appName:@"invalidCharacters"]);
  233. }
  234. #pragma mark - Helpers
  235. - (FIRInstallations *)createInstallationsWithAppOptions:(FIROptions *)options
  236. appName:(NSString *)appName {
  237. id mockIDController = OCMClassMock([FIRInstallationsIDController class]);
  238. return [[FIRInstallations alloc] initWithAppOptions:options
  239. appName:appName
  240. installationsIDController:mockIDController
  241. prefetchAuthToken:NO];
  242. }
  243. @end