RCNThrottlingTests.m 9.9 KB

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