RPCErrorTests.swift 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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 GRPCCore
  17. import Testing
  18. @Suite("RPCError Tests")
  19. struct RPCErrorTests {
  20. @Test("Custom String Convertible")
  21. func testCustomStringConvertible() {
  22. #expect(String(describing: RPCError(code: .dataLoss, message: "")) == #"dataLoss: """#)
  23. #expect(
  24. String(describing: RPCError(code: .unknown, message: "message")) == #"unknown: "message""#
  25. )
  26. #expect(
  27. String(describing: RPCError(code: .aborted, message: "message")) == #"aborted: "message""#
  28. )
  29. struct TestError: Error {}
  30. #expect(
  31. String(describing: RPCError(code: .aborted, message: "message", cause: TestError()))
  32. == #"aborted: "message" (cause: "TestError()")"#
  33. )
  34. }
  35. @Test("Error from Status")
  36. func testErrorFromStatus() throws {
  37. var status = Status(code: .ok, message: "")
  38. // ok isn't an error
  39. #expect(RPCError(status: status) == nil)
  40. status.code = .invalidArgument
  41. var error = try #require(RPCError(status: status))
  42. #expect(error.code == .invalidArgument)
  43. #expect(error.message == "")
  44. #expect(error.metadata == [:])
  45. status.code = .cancelled
  46. status.message = "an error message"
  47. error = try #require(RPCError(status: status))
  48. #expect(error.code == .cancelled)
  49. #expect(error.message == "an error message")
  50. #expect(error.metadata == [:])
  51. }
  52. @Test(
  53. "Error Code from Status Code",
  54. arguments: [
  55. (Status.Code.ok, nil),
  56. (Status.Code.cancelled, RPCError.Code.cancelled),
  57. (Status.Code.unknown, RPCError.Code.unknown),
  58. (Status.Code.invalidArgument, RPCError.Code.invalidArgument),
  59. (Status.Code.deadlineExceeded, RPCError.Code.deadlineExceeded),
  60. (Status.Code.notFound, RPCError.Code.notFound),
  61. (Status.Code.alreadyExists, RPCError.Code.alreadyExists),
  62. (Status.Code.permissionDenied, RPCError.Code.permissionDenied),
  63. (Status.Code.resourceExhausted, RPCError.Code.resourceExhausted),
  64. (Status.Code.failedPrecondition, RPCError.Code.failedPrecondition),
  65. (Status.Code.aborted, RPCError.Code.aborted),
  66. (Status.Code.outOfRange, RPCError.Code.outOfRange),
  67. (Status.Code.unimplemented, RPCError.Code.unimplemented),
  68. (Status.Code.internalError, RPCError.Code.internalError),
  69. (Status.Code.unavailable, RPCError.Code.unavailable),
  70. (Status.Code.dataLoss, RPCError.Code.dataLoss),
  71. (Status.Code.unauthenticated, RPCError.Code.unauthenticated),
  72. ]
  73. )
  74. func testErrorCodeFromStatusCode(statusCode: Status.Code, rpcErrorCode: RPCError.Code?) throws {
  75. #expect(RPCError.Code(statusCode) == rpcErrorCode)
  76. }
  77. @Test("Equatable Conformance")
  78. func testEquatableConformance() {
  79. #expect(
  80. RPCError(code: .cancelled, message: "")
  81. == RPCError(code: .cancelled, message: "")
  82. )
  83. #expect(
  84. RPCError(code: .cancelled, message: "message")
  85. == RPCError(code: .cancelled, message: "message")
  86. )
  87. #expect(
  88. RPCError(code: .cancelled, message: "message", metadata: ["foo": "bar"])
  89. == RPCError(code: .cancelled, message: "message", metadata: ["foo": "bar"])
  90. )
  91. #expect(
  92. RPCError(code: .cancelled, message: "")
  93. != RPCError(code: .cancelled, message: "message")
  94. )
  95. #expect(
  96. RPCError(code: .cancelled, message: "message")
  97. != RPCError(code: .unknown, message: "message")
  98. )
  99. #expect(
  100. RPCError(code: .cancelled, message: "message", metadata: ["foo": "bar"])
  101. != RPCError(code: .cancelled, message: "message", metadata: ["foo": "baz"])
  102. )
  103. }
  104. @Test(
  105. "Status Code Raw Values",
  106. arguments: [
  107. (RPCError.Code.cancelled, 1),
  108. (.unknown, 2),
  109. (.invalidArgument, 3),
  110. (.deadlineExceeded, 4),
  111. (.notFound, 5),
  112. (.alreadyExists, 6),
  113. (.permissionDenied, 7),
  114. (.resourceExhausted, 8),
  115. (.failedPrecondition, 9),
  116. (.aborted, 10),
  117. (.outOfRange, 11),
  118. (.unimplemented, 12),
  119. (.internalError, 13),
  120. (.unavailable, 14),
  121. (.dataLoss, 15),
  122. (.unauthenticated, 16),
  123. ]
  124. )
  125. func testStatusCodeRawValues(statusCode: RPCError.Code, rawValue: Int) {
  126. #expect(statusCode.rawValue == rawValue, "\(statusCode) had unexpected raw value")
  127. }
  128. @Test("Flatten causes with same status code")
  129. func testFlattenCausesWithSameStatusCode() {
  130. let error1 = RPCError(code: .unknown, message: "Error 1.")
  131. let error2 = RPCError(code: .unknown, message: "Error 2.", cause: error1)
  132. let error3 = RPCError(code: .dataLoss, message: "Error 3.", cause: error2)
  133. let error4 = RPCError(code: .aborted, message: "Error 4.", cause: error3)
  134. let error5 = RPCError(
  135. code: .aborted,
  136. message: "Error 5.",
  137. cause: error4
  138. )
  139. let unknownMerged = RPCError(code: .unknown, message: "Error 2. Error 1.")
  140. let dataLossMerged = RPCError(code: .dataLoss, message: "Error 3.", cause: unknownMerged)
  141. let abortedMerged = RPCError(
  142. code: .aborted,
  143. message: "Error 5. Error 4.",
  144. cause: dataLossMerged
  145. )
  146. #expect(error5 == abortedMerged)
  147. }
  148. @Test("Causes of errors with different status codes aren't flattened")
  149. func testDifferentStatusCodeAreNotFlattened() throws {
  150. let error1 = RPCError(code: .unknown, message: "Error 1.")
  151. let error2 = RPCError(code: .dataLoss, message: "Error 2.", cause: error1)
  152. let error3 = RPCError(code: .alreadyExists, message: "Error 3.", cause: error2)
  153. let error4 = RPCError(code: .aborted, message: "Error 4.", cause: error3)
  154. let error5 = RPCError(
  155. code: .deadlineExceeded,
  156. message: "Error 5.",
  157. cause: error4
  158. )
  159. #expect(error5.code == .deadlineExceeded)
  160. #expect(error5.message == "Error 5.")
  161. let wrappedError4 = try #require(error5.cause as? RPCError)
  162. #expect(wrappedError4.code == .aborted)
  163. #expect(wrappedError4.message == "Error 4.")
  164. let wrappedError3 = try #require(wrappedError4.cause as? RPCError)
  165. #expect(wrappedError3.code == .alreadyExists)
  166. #expect(wrappedError3.message == "Error 3.")
  167. let wrappedError2 = try #require(wrappedError3.cause as? RPCError)
  168. #expect(wrappedError2.code == .dataLoss)
  169. #expect(wrappedError2.message == "Error 2.")
  170. let wrappedError1 = try #require(wrappedError2.cause as? RPCError)
  171. #expect(wrappedError1.code == .unknown)
  172. #expect(wrappedError1.message == "Error 1.")
  173. #expect(wrappedError1.cause == nil)
  174. }
  175. }