ClientResponseTests.swift 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. final class ClientResponseTests: XCTestCase {
  19. func testAcceptedSingleResponseConvenienceMethods() {
  20. let response = ClientResponse(
  21. message: "message",
  22. metadata: ["foo": "bar"],
  23. trailingMetadata: ["bar": "baz"]
  24. )
  25. XCTAssertEqual(response.metadata, ["foo": "bar"])
  26. XCTAssertEqual(try response.message, "message")
  27. XCTAssertEqual(response.trailingMetadata, ["bar": "baz"])
  28. }
  29. func testRejectedSingleResponseConvenienceMethods() {
  30. let error = RPCError(code: .aborted, message: "error message", metadata: ["bar": "baz"])
  31. let response = ClientResponse(of: String.self, error: error)
  32. XCTAssertEqual(response.metadata, [:])
  33. XCTAssertThrowsRPCError(try response.message) {
  34. XCTAssertEqual($0, error)
  35. }
  36. XCTAssertEqual(response.trailingMetadata, ["bar": "baz"])
  37. }
  38. func testAcceptedButFailedSingleResponseConvenienceMethods() {
  39. let error = RPCError(code: .aborted, message: "error message", metadata: ["bar": "baz"])
  40. let response = ClientResponse(of: String.self, metadata: ["foo": "bar"], error: error)
  41. XCTAssertEqual(response.metadata, ["foo": "bar"])
  42. XCTAssertThrowsRPCError(try response.message) {
  43. XCTAssertEqual($0, error)
  44. }
  45. XCTAssertEqual(response.trailingMetadata, ["bar": "baz"])
  46. }
  47. func testAcceptedStreamResponseConvenienceMethods_Messages() async throws {
  48. let response = StreamingClientResponse(
  49. of: String.self,
  50. metadata: ["foo": "bar"],
  51. bodyParts: RPCAsyncSequence(
  52. wrapping: AsyncThrowingStream {
  53. $0.yield(.message("foo"))
  54. $0.yield(.message("bar"))
  55. $0.yield(.message("baz"))
  56. $0.yield(.trailingMetadata(["baz": "baz"]))
  57. $0.finish()
  58. }
  59. )
  60. )
  61. XCTAssertEqual(response.metadata, ["foo": "bar"])
  62. let messages = try await response.messages.collect()
  63. XCTAssertEqual(messages, ["foo", "bar", "baz"])
  64. }
  65. func testAcceptedStreamResponseConvenienceMethods_BodyParts() async throws {
  66. let response = StreamingClientResponse(
  67. of: String.self,
  68. metadata: ["foo": "bar"],
  69. bodyParts: RPCAsyncSequence(
  70. wrapping: AsyncThrowingStream {
  71. $0.yield(.message("foo"))
  72. $0.yield(.message("bar"))
  73. $0.yield(.message("baz"))
  74. $0.yield(.trailingMetadata(["baz": "baz"]))
  75. $0.finish()
  76. }
  77. )
  78. )
  79. XCTAssertEqual(response.metadata, ["foo": "bar"])
  80. let bodyParts = try await response.bodyParts.collect()
  81. XCTAssertEqual(
  82. bodyParts,
  83. [.message("foo"), .message("bar"), .message("baz"), .trailingMetadata(["baz": "baz"])]
  84. )
  85. }
  86. func testRejectedStreamResponseConvenienceMethods() async throws {
  87. let error = RPCError(code: .aborted, message: "error message", metadata: ["bar": "baz"])
  88. let response = StreamingClientResponse(of: String.self, error: error)
  89. XCTAssertEqual(response.metadata, [:])
  90. await XCTAssertThrowsRPCErrorAsync {
  91. try await response.messages.collect()
  92. } errorHandler: {
  93. XCTAssertEqual($0, error)
  94. }
  95. await XCTAssertThrowsRPCErrorAsync {
  96. try await response.bodyParts.collect()
  97. } errorHandler: {
  98. XCTAssertEqual($0, error)
  99. }
  100. }
  101. func testStreamToSingleConversionForValidStream() async throws {
  102. let stream = StreamingClientResponse(
  103. of: String.self,
  104. metadata: ["foo": "bar"],
  105. bodyParts: .elements(.message("foo"), .trailingMetadata(["bar": "baz"]))
  106. )
  107. let single = await ClientResponse(stream: stream)
  108. XCTAssertEqual(single.metadata, ["foo": "bar"])
  109. XCTAssertEqual(try single.message, "foo")
  110. XCTAssertEqual(single.trailingMetadata, ["bar": "baz"])
  111. }
  112. func testStreamToSingleConversionForFailedStream() async throws {
  113. let error = RPCError(code: .aborted, message: "aborted", metadata: ["bar": "baz"])
  114. let stream = StreamingClientResponse(of: String.self, error: error)
  115. let single = await ClientResponse(stream: stream)
  116. XCTAssertEqual(single.metadata, [:])
  117. XCTAssertThrowsRPCError(try single.message) {
  118. XCTAssertEqual($0, error)
  119. }
  120. XCTAssertEqual(single.trailingMetadata, ["bar": "baz"])
  121. }
  122. func testStreamToSingleConversionForInvalidSingleStream() async throws {
  123. let bodies: [[StreamingClientResponse<String>.Contents.BodyPart]] = [
  124. [.message("1"), .message("2")], // Too many messages.
  125. [.trailingMetadata([:])], // Too few messages
  126. ]
  127. for body in bodies {
  128. let stream = StreamingClientResponse(
  129. of: String.self,
  130. metadata: ["foo": "bar"],
  131. bodyParts: .elements(body)
  132. )
  133. let single = await ClientResponse(stream: stream)
  134. XCTAssertEqual(single.metadata, [:])
  135. XCTAssertThrowsRPCError(try single.message) { error in
  136. XCTAssertEqual(error.code, .unimplemented)
  137. }
  138. XCTAssertEqual(single.trailingMetadata, [:])
  139. }
  140. }
  141. func testStreamToSingleConversionForInvalidStream() async throws {
  142. let bodies: [[StreamingClientResponse<String>.Contents.BodyPart]] = [
  143. [], // Empty stream
  144. [.trailingMetadata([:]), .trailingMetadata([:])], // Multiple metadatas
  145. [.trailingMetadata([:]), .message("")], // Metadata then message
  146. ]
  147. for body in bodies {
  148. let stream = StreamingClientResponse(
  149. of: String.self,
  150. metadata: ["foo": "bar"],
  151. bodyParts: .elements(body)
  152. )
  153. let single = await ClientResponse(stream: stream)
  154. XCTAssertEqual(single.metadata, [:])
  155. XCTAssertThrowsRPCError(try single.message) { error in
  156. XCTAssertEqual(error.code, .internalError)
  157. }
  158. XCTAssertEqual(single.trailingMetadata, [:])
  159. }
  160. }
  161. func testStreamToSingleConversionForStreamThrowingRPCError() async throws {
  162. let error = RPCError(code: .dataLoss, message: "oops")
  163. let stream = StreamingClientResponse(
  164. of: String.self,
  165. metadata: [:],
  166. bodyParts: .throwing(error)
  167. )
  168. let single = await ClientResponse(stream: stream)
  169. XCTAssertThrowsRPCError(try single.message) {
  170. XCTAssertEqual($0, error)
  171. }
  172. }
  173. func testStreamToSingleConversionForStreamThrowingUnknownError() async throws {
  174. let stream = StreamingClientResponse(
  175. of: String.self,
  176. metadata: [:],
  177. bodyParts: .throwing(CancellationError())
  178. )
  179. let single = await ClientResponse(stream: stream)
  180. XCTAssertThrowsRPCError(try single.message) { error in
  181. XCTAssertEqual(error.code, .unknown)
  182. }
  183. }
  184. }