TimeoutTests.swift 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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, iOS 16, tvOS 16, watchOS 9, *)
  19. final class TimeoutTests: XCTestCase {
  20. func testDecodeInvalidTimeout_Empty() {
  21. let timeoutHeader = ""
  22. XCTAssertNil(Timeout(decoding: timeoutHeader))
  23. }
  24. func testDecodeInvalidTimeout_NoAmount() {
  25. let timeoutHeader = "H"
  26. XCTAssertNil(Timeout(decoding: timeoutHeader))
  27. }
  28. func testDecodeInvalidTimeout_NoUnit() {
  29. let timeoutHeader = "123"
  30. XCTAssertNil(Timeout(decoding: timeoutHeader))
  31. }
  32. func testDecodeInvalidTimeout_TooLongAmount() {
  33. let timeoutHeader = "100000000S"
  34. XCTAssertNil(Timeout(decoding: timeoutHeader))
  35. }
  36. func testDecodeInvalidTimeout_InvalidUnit() {
  37. let timeoutHeader = "123j"
  38. XCTAssertNil(Timeout(decoding: timeoutHeader))
  39. }
  40. func testDecodeValidTimeout_Hours() throws {
  41. let timeoutHeader = "123H"
  42. let timeout = Timeout(decoding: timeoutHeader)
  43. let unwrappedTimeout = try XCTUnwrap(timeout)
  44. XCTAssertEqual(unwrappedTimeout.duration, Duration.hours(123))
  45. XCTAssertEqual(unwrappedTimeout.wireEncoding, timeoutHeader)
  46. }
  47. func testDecodeValidTimeout_Minutes() throws {
  48. let timeoutHeader = "123M"
  49. let timeout = Timeout(decoding: timeoutHeader)
  50. let unwrappedTimeout = try XCTUnwrap(timeout)
  51. XCTAssertEqual(unwrappedTimeout.duration, Duration.minutes(123))
  52. XCTAssertEqual(unwrappedTimeout.wireEncoding, timeoutHeader)
  53. }
  54. func testDecodeValidTimeout_Seconds() throws {
  55. let timeoutHeader = "123S"
  56. let timeout = Timeout(decoding: timeoutHeader)
  57. let unwrappedTimeout = try XCTUnwrap(timeout)
  58. XCTAssertEqual(unwrappedTimeout.duration, Duration.seconds(123))
  59. XCTAssertEqual(unwrappedTimeout.wireEncoding, timeoutHeader)
  60. }
  61. func testDecodeValidTimeout_Milliseconds() throws {
  62. let timeoutHeader = "123m"
  63. let timeout = Timeout(decoding: timeoutHeader)
  64. let unwrappedTimeout = try XCTUnwrap(timeout)
  65. XCTAssertEqual(unwrappedTimeout.duration, Duration.milliseconds(123))
  66. XCTAssertEqual(unwrappedTimeout.wireEncoding, timeoutHeader)
  67. }
  68. func testDecodeValidTimeout_Microseconds() throws {
  69. let timeoutHeader = "123u"
  70. let timeout = Timeout(decoding: timeoutHeader)
  71. let unwrappedTimeout = try XCTUnwrap(timeout)
  72. XCTAssertEqual(unwrappedTimeout.duration, Duration.microseconds(123))
  73. XCTAssertEqual(unwrappedTimeout.wireEncoding, timeoutHeader)
  74. }
  75. func testDecodeValidTimeout_Nanoseconds() throws {
  76. let timeoutHeader = "123n"
  77. let timeout = Timeout(decoding: timeoutHeader)
  78. let unwrappedTimeout = try XCTUnwrap(timeout)
  79. XCTAssertEqual(unwrappedTimeout.duration, Duration.nanoseconds(123))
  80. XCTAssertEqual(unwrappedTimeout.wireEncoding, timeoutHeader)
  81. }
  82. func testEncodeValidTimeout_Hours() {
  83. let duration = Duration.hours(123)
  84. let timeout = Timeout(duration: duration)
  85. XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
  86. XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
  87. }
  88. func testEncodeValidTimeout_Minutes() {
  89. let duration = Duration.minutes(43)
  90. let timeout = Timeout(duration: duration)
  91. XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
  92. XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
  93. }
  94. func testEncodeValidTimeout_Seconds() {
  95. let duration = Duration.seconds(12345)
  96. let timeout = Timeout(duration: duration)
  97. XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
  98. XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
  99. }
  100. func testEncodeValidTimeout_Seconds_TooLong_Minutes() {
  101. let duration = Duration.seconds(111_111_111)
  102. let timeout = Timeout(duration: duration)
  103. // The conversion from seconds to minutes results in a loss of precision.
  104. // 111,111,111 seconds / 60 = 1,851,851.85 minutes -rounding up-> 1,851,852 minutes * 60 = 111,111,120 seconds
  105. let expectedRoundedDuration = Duration.minutes(1_851_852)
  106. XCTAssertEqual(timeout.duration.components.seconds, expectedRoundedDuration.components.seconds)
  107. XCTAssertEqual(
  108. timeout.duration.components.attoseconds,
  109. expectedRoundedDuration.components.attoseconds
  110. )
  111. }
  112. func testEncodeValidTimeout_Seconds_TooLong_Hours() {
  113. let duration = Duration.seconds(9_999_999_999 as Int64)
  114. let timeout = Timeout(duration: duration)
  115. // The conversion from seconds to hours results in a loss of precision.
  116. // 9,999,999,999 seconds / 60 = 166,666,666.65 minutes -rounding up->
  117. // 166,666,667 minutes / 60 = 2,777,777.78 hours -rounding up->
  118. // 2,777,778 hours * 60 -> 166,666,680 minutes * 60 = 10,000,000,800 seconds
  119. let expectedRoundedDuration = Duration.hours(2_777_778)
  120. XCTAssertEqual(timeout.duration.components.seconds, expectedRoundedDuration.components.seconds)
  121. XCTAssertEqual(
  122. timeout.duration.components.attoseconds,
  123. expectedRoundedDuration.components.attoseconds
  124. )
  125. }
  126. func testEncodeValidTimeout_Seconds_TooLong_MaxAmount() {
  127. let duration = Duration.seconds(999_999_999_999 as Int64)
  128. let timeout = Timeout(duration: duration)
  129. // The conversion from seconds to hours results in a number that still has
  130. // more than the maximum allowed 8 digits, so we must clamp it.
  131. // Make sure that `Timeout.maxAmount` is the amount used for the resulting timeout.
  132. let expectedRoundedDuration = Duration.hours(Timeout.maxAmount)
  133. XCTAssertEqual(timeout.duration.components.seconds, expectedRoundedDuration.components.seconds)
  134. XCTAssertEqual(
  135. timeout.duration.components.attoseconds,
  136. expectedRoundedDuration.components.attoseconds
  137. )
  138. }
  139. func testEncodeValidTimeout_SecondsAndMilliseconds() {
  140. let duration = Duration(secondsComponent: 100, attosecondsComponent: Int64(1e+17))
  141. let timeout = Timeout(duration: duration)
  142. XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
  143. XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
  144. }
  145. func testEncodeValidTimeout_SecondsAndMicroseconds() {
  146. let duration = Duration(secondsComponent: 1, attosecondsComponent: Int64(1e+14))
  147. let timeout = Timeout(duration: duration)
  148. XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
  149. XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
  150. }
  151. func testEncodeValidTimeout_SecondsAndNanoseconds() {
  152. let duration = Duration(secondsComponent: 1, attosecondsComponent: Int64(1e+11))
  153. let timeout = Timeout(duration: duration)
  154. // We can't convert seconds to nanoseconds because that would require at least
  155. // 9 digits, and the maximum allowed is 8: we expect to simply drop the nanoseconds.
  156. let expectedRoundedDuration = Duration.seconds(1)
  157. XCTAssertEqual(timeout.duration.components.seconds, expectedRoundedDuration.components.seconds)
  158. XCTAssertEqual(
  159. timeout.duration.components.attoseconds,
  160. expectedRoundedDuration.components.attoseconds
  161. )
  162. }
  163. func testEncodeValidTimeout_Milliseconds() {
  164. let duration = Duration.milliseconds(100)
  165. let timeout = Timeout(duration: duration)
  166. XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
  167. XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
  168. }
  169. func testEncodeValidTimeout_Microseconds() {
  170. let duration = Duration.microseconds(100)
  171. let timeout = Timeout(duration: duration)
  172. XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
  173. XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
  174. }
  175. func testEncodeValidTimeout_Nanoseconds() {
  176. let duration = Duration.nanoseconds(100)
  177. let timeout = Timeout(duration: duration)
  178. XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
  179. XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
  180. }
  181. }