RetryDelaySequenceTests.swift 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * Copyright 2023, gRPC Authors All rights reserved.
  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
  17. @testable import GRPCCore
  18. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  19. final class RetryDelaySequenceTests: XCTestCase {
  20. func testSequence() {
  21. let policy = RetryPolicy(
  22. maximumAttempts: 3, // ignored here
  23. initialBackoff: .seconds(1),
  24. maximumBackoff: .seconds(8),
  25. backoffMultiplier: 2.0,
  26. retryableStatusCodes: [.aborted] // ignored here
  27. )
  28. let sequence = RetryDelaySequence(policy: policy)
  29. var iterator = sequence.makeIterator()
  30. // The iterator will never return 'nil', '!' is safe.
  31. XCTAssertLessThanOrEqual(iterator.next()!, .seconds(1))
  32. XCTAssertLessThanOrEqual(iterator.next()!, .seconds(2))
  33. XCTAssertLessThanOrEqual(iterator.next()!, .seconds(4))
  34. XCTAssertLessThanOrEqual(iterator.next()!, .seconds(8))
  35. XCTAssertLessThanOrEqual(iterator.next()!, .seconds(8)) // Clamped
  36. }
  37. func testSequenceSupportsMultipleIteration() {
  38. let policy = RetryPolicy(
  39. maximumAttempts: 3, // ignored here
  40. initialBackoff: .seconds(1),
  41. maximumBackoff: .seconds(8),
  42. backoffMultiplier: 2.0,
  43. retryableStatusCodes: [.aborted] // ignored here
  44. )
  45. let sequence = RetryDelaySequence(policy: policy)
  46. for _ in 0 ..< 10 {
  47. var iterator = sequence.makeIterator()
  48. // The iterator will never return 'nil', '!' is safe.
  49. XCTAssertLessThanOrEqual(iterator.next()!, .seconds(1))
  50. XCTAssertLessThanOrEqual(iterator.next()!, .seconds(2))
  51. XCTAssertLessThanOrEqual(iterator.next()!, .seconds(4))
  52. XCTAssertLessThanOrEqual(iterator.next()!, .seconds(8))
  53. XCTAssertLessThanOrEqual(iterator.next()!, .seconds(8)) // Clamped
  54. }
  55. }
  56. func testDurationToDouble() {
  57. let testData: [(Duration, Double)] = [
  58. (.zero, 0.0),
  59. (.seconds(1), 1.0),
  60. (.milliseconds(1500), 1.5),
  61. (.nanoseconds(1_000_000_000), 1.0),
  62. (.nanoseconds(3_141_592_653 as Int64), 3.141592653),
  63. ]
  64. for (duration, expected) in testData {
  65. XCTAssertEqual(RetryDelaySequence.Iterator._durationToTimeInterval(duration), expected)
  66. }
  67. }
  68. func testDoubleToDuration() {
  69. let testData: [(Double, Duration)] = [
  70. (0.0, .zero),
  71. (1.0, .seconds(1)),
  72. (1.5, .milliseconds(1500)),
  73. (1.0, .nanoseconds(1_000_000_000)),
  74. (3.141592653, .nanoseconds(3_141_592_653 as Int64)),
  75. ]
  76. for (seconds, expected) in testData {
  77. let actual = RetryDelaySequence.Iterator._timeIntervalToDuration(seconds)
  78. XCTAssertEqual(actual.components.seconds, expected.components.seconds)
  79. // We lose some precision in the conversion, that's fine.
  80. XCTAssertEqual(actual.components.attoseconds / 1_000, expected.components.attoseconds / 1_000)
  81. }
  82. }
  83. }