amplify-swift/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/RequestRetryablePolicyTests...

264 lines
11 KiB
Swift

//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
import Foundation
import XCTest
@testable import AWSDataStorePlugin
class RequestRetryablePolicyTests: XCTestCase {
var retryPolicy: RequestRetryablePolicy!
let defaultTimeout = DispatchTimeInterval.seconds(60)
override func setUp() {
super.setUp()
retryPolicy = RequestRetryablePolicy()
}
func testNoErrorNoHttpURLResponse() {
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: nil,
httpURLResponse: nil,
attemptNumber: 1)
XCTAssertFalse(retryAdvice.shouldRetry)
XCTAssertEqual(retryAdvice.retryInterval, defaultTimeout)
}
func testNoErrorWithHttpURLResponseWithRetryAfterInHeader() {
let headerFields = ["Retry-After": "42"]
let url = URL(string: "http://www.amazon.com")!
let httpURLResponse = HTTPURLResponse(url: url,
statusCode: 429,
httpVersion: "HTTP/1.1",
headerFields: headerFields)!
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: nil,
httpURLResponse: httpURLResponse,
attemptNumber: 1)
XCTAssert(retryAdvice.shouldRetry)
assertSeconds(retryAdvice.retryInterval, seconds: 42)
}
func testNoErrorWithHttpURLResponseWithoutRetryAfterInHeader_attempt1() {
let url = URL(string: "http://www.amazon.com")!
let httpURLResponse = HTTPURLResponse(url: url,
statusCode: 429,
httpVersion: "HTTP/1.1",
headerFields: nil)!
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: nil,
httpURLResponse: httpURLResponse,
attemptNumber: 1)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 200, lessThan: 300)
}
func testNoErrorWithHttpURLResponseWithoutRetryAfterInHeader_attempt2() {
let url = URL(string: "http://www.amazon.com")!
let httpURLResponse = HTTPURLResponse(url: url,
statusCode: 429,
httpVersion: "HTTP/1.1",
headerFields: nil)!
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: nil,
httpURLResponse: httpURLResponse,
attemptNumber: 2)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 400, lessThan: 500)
}
func testNoErrorWithHttpURLResponseBeyondMaxWaitTime() {
let url = URL(string: "http://www.amazon.com")!
let httpURLResponse = HTTPURLResponse(url: url,
statusCode: 429,
httpVersion: "HTTP/1.1",
headerFields: nil)!
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: nil,
httpURLResponse: httpURLResponse,
attemptNumber: 12)
XCTAssertFalse(retryAdvice.shouldRetry)
XCTAssertEqual(retryAdvice.retryInterval, defaultTimeout)
}
func testNoErrorWithHttpURLResponseNotRetryable() {
let url = URL(string: "http://www.amazon.com")!
let httpURLResponse = HTTPURLResponse(url: url,
statusCode: 204,
httpVersion: "HTTP/1.1",
headerFields: nil)!
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: nil,
httpURLResponse: httpURLResponse,
attemptNumber: 1)
XCTAssertFalse(retryAdvice.shouldRetry)
XCTAssertEqual(retryAdvice.retryInterval, defaultTimeout)
}
func testNotConnectedToInternetErrorCode() {
let retryableErrorCode = URLError.init(.notConnectedToInternet)
let attemptNumber = 1
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: retryableErrorCode,
httpURLResponse: nil,
attemptNumber: attemptNumber)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 200, lessThan: 300)
}
func testNotConnectedToInternetErrorCode_attempt2() {
let retryableErrorCode = URLError.init(.notConnectedToInternet)
let attemptNumber = 2
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: retryableErrorCode,
httpURLResponse: nil,
attemptNumber: attemptNumber)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 400, lessThan: 500)
}
func testNotConnectedToInternetErrorCode_attempt3() {
let retryableErrorCode = URLError.init(.notConnectedToInternet)
let attemptNumber = 3
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: retryableErrorCode,
httpURLResponse: nil,
attemptNumber: attemptNumber)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 800, lessThan: 900)
}
func testDNSLookupFailedError() {
let retryableErrorCode = URLError.init(.dnsLookupFailed)
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: retryableErrorCode,
httpURLResponse: nil,
attemptNumber: 1)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 200, lessThan: 300)
}
func testCannotConnectToHostError() {
let retryableErrorCode = URLError.init(.cannotConnectToHost)
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: retryableErrorCode,
httpURLResponse: nil,
attemptNumber: 1)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 200, lessThan: 300)
}
func testCannotFindHostError() {
let retryableErrorCode = URLError.init(.cannotFindHost)
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: retryableErrorCode,
httpURLResponse: nil,
attemptNumber: 1)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 200, lessThan: 300)
}
func testTimedOutError() {
let retryableErrorCode = URLError.init(.timedOut)
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: retryableErrorCode,
httpURLResponse: nil,
attemptNumber: 1)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 200, lessThan: 300)
}
func testCannotParseResponseError() {
let retryableErrorCode = URLError.init(.cannotParseResponse)
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: retryableErrorCode,
httpURLResponse: nil,
attemptNumber: 1)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 200, lessThan: 300)
}
func testHTTPTooManyRedirectsError() {
let nonRetryableErrorCode = URLError.init(.httpTooManyRedirects)
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: nonRetryableErrorCode,
httpURLResponse: nil,
attemptNumber: 1)
XCTAssertFalse(retryAdvice.shouldRetry)
XCTAssertEqual(retryAdvice.retryInterval, defaultTimeout)
}
func testMaxValueRetryDelay() {
let retryableErrorCode = URLError.init(.timedOut)
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: retryableErrorCode,
httpURLResponse: nil,
attemptNumber: 31)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 214_748_364_800, lessThan: 214_748_364_900)
}
func testBeyondMaxValueRetryDelay() {
let retryableErrorCode = URLError.init(.timedOut)
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: retryableErrorCode,
httpURLResponse: nil,
attemptNumber: 32)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 214_748_364_800, lessThan: 214_748_364_900)
}
func testOverflowCase() {
let retryableErrorCode = URLError.init(.timedOut)
let retryAdvice = retryPolicy.retryRequestAdvice(urlError: retryableErrorCode,
httpURLResponse: nil,
attemptNumber: 58)
XCTAssert(retryAdvice.shouldRetry)
assertMilliseconds(retryAdvice.retryInterval, greaterThan: 214_748_364_800, lessThan: 214_748_364_900)
}
func assertMilliseconds(_ retryInterval: DispatchTimeInterval?, greaterThan: Int, lessThan: Int) {
guard let retryInterval = retryInterval else {
XCTFail("retryInterval is nil")
return
}
switch retryInterval {
case .milliseconds(let milliseconds):
XCTAssertGreaterThanOrEqual(milliseconds, greaterThan)
XCTAssertLessThanOrEqual(milliseconds, lessThan)
default:
XCTFail("Expected milliseconds, but received \(retryInterval)")
}
}
func assertSeconds(_ retryInterval: DispatchTimeInterval?, seconds expectedSeconds: Int) {
guard let retryInterval = retryInterval else {
XCTFail("retryInterval is nil")
return
}
switch retryInterval {
case .seconds(let seconds):
XCTAssertEqual(seconds, expectedSeconds)
default:
XCTFail("Expected seconds, but received \(retryInterval)")
}
}
}