RCNThrottlingTests.m 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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 <OCMock/OCMock.h>
  17. #import <XCTest/XCTest.h>
  18. #import "FirebaseRemoteConfig/Sources/Private/RCNConfigFetch.h"
  19. #import "FirebaseRemoteConfig/Sources/Private/RCNConfigSettings.h"
  20. #import "FirebaseRemoteConfig/Sources/RCNConfigContent.h"
  21. #import "FirebaseRemoteConfig/Sources/RCNConfigDBManager.h"
  22. #import "FirebaseRemoteConfig/Sources/RCNConfigExperiment.h"
  23. #import "FirebaseRemoteConfig/Tests/Unit/RCNTestUtilities.h"
  24. #import "FirebaseCore/Extension/FirebaseCoreInternal.h"
  25. @interface RCNThrottlingTests : XCTestCase {
  26. RCNConfigContent *_configContentMock;
  27. RCNConfigSettings *_settings;
  28. RCNConfigExperiment *_experimentMock;
  29. RCNConfigFetch *_configFetch;
  30. NSString *_DBPath;
  31. }
  32. @end
  33. @implementation RCNThrottlingTests
  34. - (void)setUp {
  35. [super setUp];
  36. // Put setup code here. This method is called before the invocation of each test method in the
  37. // class.
  38. if (![FIRApp defaultApp]) {
  39. [FIRApp configure];
  40. }
  41. [[FIRConfiguration sharedInstance] setLoggerLevel:FIRLoggerLevelMax];
  42. // Get a test database.
  43. _DBPath = [RCNTestUtilities remoteConfigPathForTestDatabase];
  44. id classMock = OCMClassMock([RCNConfigDBManager class]);
  45. OCMStub([classMock remoteConfigPathForDatabase]).andReturn(_DBPath);
  46. RCNConfigDBManager *DBManager = [[RCNConfigDBManager alloc] init];
  47. _configContentMock = OCMClassMock([RCNConfigContent class]);
  48. _settings = [[RCNConfigSettings alloc] initWithDatabaseManager:DBManager
  49. namespace:FIRNamespaceGoogleMobilePlatform
  50. app:[FIRApp defaultApp]];
  51. _experimentMock = OCMClassMock([RCNConfigExperiment class]);
  52. dispatch_queue_t _queue = dispatch_queue_create(
  53. "com.google.GoogleConfigService.FIRRemoteConfigTest", DISPATCH_QUEUE_SERIAL);
  54. _configFetch = [[RCNConfigFetch alloc] initWithContent:_configContentMock
  55. DBManager:DBManager
  56. settings:_settings
  57. experiment:_experimentMock
  58. queue:_queue
  59. namespace:FIRNamespaceGoogleMobilePlatform
  60. app:[FIRApp defaultApp]];
  61. }
  62. - (void)mockFetchResponseWithStatusCode:(NSInteger)statusCode {
  63. // Mock successful network fetches with an empty config response.
  64. RCNConfigFetcherTestBlock testBlock = ^(RCNConfigFetcherCompletion completion) {
  65. NSURL *url = [[NSURL alloc] initWithString:@"https://google.com"];
  66. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url
  67. statusCode:statusCode
  68. HTTPVersion:nil
  69. headerFields:@{@"etag" : @"etag1"}];
  70. NSData *data =
  71. [NSJSONSerialization dataWithJSONObject:@{@"key1" : @"val1", @"state" : @"UPDATE"}
  72. options:0
  73. error:nil];
  74. completion(data, response, nil);
  75. };
  76. [RCNConfigFetch setGlobalTestBlock:testBlock];
  77. }
  78. /// Regular case of calling fetch should succeed.
  79. - (void)testRegularFetchDoesNotGetThrottled {
  80. [self mockFetchResponseWithStatusCode:200];
  81. XCTestExpectation *expectation = [self expectationWithDescription:@"throttlingExpectation"];
  82. [_configFetch fetchAllConfigsWithExpirationDuration:0
  83. completionHandler:^(FIRRemoteConfigFetchStatus status,
  84. NSError *_Nullable error) {
  85. XCTAssertNil(error);
  86. XCTAssertEqual(FIRRemoteConfigFetchStatusSuccess, status);
  87. [expectation fulfill];
  88. }];
  89. // TODO(dmandar): Investigate using a smaller timeout. b/122674668
  90. [self waitForExpectationsWithTimeout:4.0 handler:nil];
  91. }
  92. - (void)testServerThrottleHTTP429ReturnsAThrottledError {
  93. [self mockFetchResponseWithStatusCode:429];
  94. XCTestExpectation *expectation = [self expectationWithDescription:@"throttlingExpectation"];
  95. [_configFetch
  96. fetchAllConfigsWithExpirationDuration:0
  97. completionHandler:^(FIRRemoteConfigFetchStatus status,
  98. NSError *_Nullable error) {
  99. XCTAssertNotNil(error);
  100. NSNumber *endTime = error.userInfo[@"error_throttled_end_time_seconds"];
  101. XCTAssertGreaterThanOrEqual([endTime doubleValue],
  102. [[NSDate date] timeIntervalSinceNow]);
  103. XCTAssertEqual(FIRRemoteConfigFetchStatusThrottled, status);
  104. [expectation fulfill];
  105. }];
  106. [self waitForExpectationsWithTimeout:4.0 handler:nil];
  107. }
  108. - (void)testServerInternalError500ReturnsAThrottledError {
  109. [self mockFetchResponseWithStatusCode:500];
  110. XCTestExpectation *expectation = [self expectationWithDescription:@"throttlingExpectation"];
  111. [_configFetch
  112. fetchAllConfigsWithExpirationDuration:0
  113. completionHandler:^(FIRRemoteConfigFetchStatus status,
  114. NSError *_Nullable error) {
  115. XCTAssertNotNil(error);
  116. NSNumber *endTime = error.userInfo[@"error_throttled_end_time_seconds"];
  117. XCTAssertGreaterThanOrEqual([endTime doubleValue],
  118. [[NSDate date] timeIntervalSinceNow]);
  119. XCTAssertEqual(FIRRemoteConfigFetchStatusThrottled, status);
  120. [expectation fulfill];
  121. }];
  122. [self waitForExpectationsWithTimeout:4.0 handler:nil];
  123. }
  124. - (void)testServerUnavailableError503ReturnsAThrottledError {
  125. [self mockFetchResponseWithStatusCode:503];
  126. XCTestExpectation *expectation = [self expectationWithDescription:@"throttlingExpectation"];
  127. [_configFetch
  128. fetchAllConfigsWithExpirationDuration:0
  129. completionHandler:^(FIRRemoteConfigFetchStatus status,
  130. NSError *_Nullable error) {
  131. XCTAssertNotNil(error);
  132. NSNumber *endTime = error.userInfo[@"error_throttled_end_time_seconds"];
  133. XCTAssertGreaterThanOrEqual([endTime doubleValue],
  134. [[NSDate date] timeIntervalSinceNow]);
  135. XCTAssertEqual(FIRRemoteConfigFetchStatusThrottled, status);
  136. [expectation fulfill];
  137. }];
  138. [self waitForExpectationsWithTimeout:4.0 handler:nil];
  139. }
  140. - (void)testThrottleReturnsAThrottledErrorAndThrottlesSubsequentRequests {
  141. [self mockFetchResponseWithStatusCode:429];
  142. XCTestExpectation *expectation = [self expectationWithDescription:@"throttlingExpectation"];
  143. XCTestExpectation *expectation2 = [self expectationWithDescription:@"throttlingExpectation2"];
  144. [_configFetch
  145. fetchAllConfigsWithExpirationDuration:0
  146. completionHandler:^(FIRRemoteConfigFetchStatus status,
  147. NSError *_Nullable error) {
  148. XCTAssertNotNil(error);
  149. NSNumber *endTime = error.userInfo[@"error_throttled_end_time_seconds"];
  150. XCTAssertGreaterThanOrEqual([endTime doubleValue],
  151. [[NSDate date] timeIntervalSinceNow]);
  152. XCTAssertEqual(FIRRemoteConfigFetchStatusThrottled, status);
  153. [expectation fulfill];
  154. // follow-up request.
  155. [_configFetch
  156. fetchAllConfigsWithExpirationDuration:0
  157. completionHandler:^(
  158. FIRRemoteConfigFetchStatus status,
  159. NSError *_Nullable error) {
  160. XCTAssertNotNil(error);
  161. NSNumber *endTime =
  162. error.userInfo
  163. [@"error_throttled_end_time_seconds"];
  164. XCTAssertGreaterThanOrEqual(
  165. [endTime doubleValue],
  166. [[NSDate date] timeIntervalSinceNow]);
  167. XCTAssertEqual(
  168. FIRRemoteConfigFetchStatusThrottled,
  169. status);
  170. [expectation2 fulfill];
  171. }];
  172. }];
  173. [self waitForExpectationsWithTimeout:4.0 handler:nil];
  174. }
  175. @end