FakeResponseStreamTests.swift 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * Copyright 2020, 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. @testable import GRPC
  17. import EchoModel
  18. import NIO
  19. import NIOHPACK
  20. import XCTest
  21. class FakeResponseStreamTests: GRPCTestCase {
  22. private typealias Request = Echo_EchoRequest
  23. private typealias Response = Echo_EchoResponse
  24. private typealias ResponsePart = _GRPCClientResponsePart<Response>
  25. func testUnarySendMessage() {
  26. let unary = FakeUnaryResponse<Request, Response>()
  27. unary.activate()
  28. XCTAssertNoThrow(try unary.sendMessage(.with { $0.text = "foo"}))
  29. unary.channel.verifyInbound(as: ResponsePart.self) { part in
  30. part.assertInitialMetadata()
  31. }
  32. unary.channel.verifyInbound(as: ResponsePart.self) { part in
  33. part.assertMessage {
  34. XCTAssertEqual($0, .with { $0.text = "foo" })
  35. }
  36. }
  37. unary.channel.verifyInbound(as: ResponsePart.self) { part in
  38. part.assertTrailingMetadata()
  39. }
  40. unary.channel.verifyInbound(as: ResponsePart.self) { part in
  41. part.assertStatus()
  42. }
  43. }
  44. func testUnarySendError() {
  45. let unary = FakeUnaryResponse<Request, Response>()
  46. unary.activate()
  47. XCTAssertNoThrow(try unary.sendError(GRPCError.RPCNotImplemented(rpc: "uh oh!")))
  48. // Expect trailers and then an error.
  49. unary.channel.verifyInbound(as: ResponsePart.self) { part in
  50. part.assertTrailingMetadata()
  51. }
  52. XCTAssertThrowsError(try unary.channel.throwIfErrorCaught())
  53. }
  54. func testUnaryIgnoresExtraMessages() {
  55. let unary = FakeUnaryResponse<Request, Response>()
  56. unary.activate()
  57. XCTAssertNoThrow(try unary.sendError(GRPCError.RPCNotImplemented(rpc: "uh oh!")))
  58. // Expected.
  59. unary.channel.verifyInbound(as: ResponsePart.self) { part in
  60. part.assertTrailingMetadata()
  61. }
  62. XCTAssertThrowsError(try unary.channel.throwIfErrorCaught())
  63. // Send another error; this should on-op.
  64. XCTAssertThrowsError(try unary.sendError(GRPCError.RPCCancelledByClient())) { error in
  65. XCTAssertTrue(error is FakeResponseProtocolViolation)
  66. }
  67. XCTAssertNil(try unary.channel.readInbound(as: ResponsePart.self))
  68. XCTAssertNoThrow(try unary.channel.throwIfErrorCaught())
  69. // Send a message; this should on-op.
  70. XCTAssertThrowsError(try unary.sendMessage(.with { $0.text = "ignored" })) { error in
  71. XCTAssertTrue(error is FakeResponseProtocolViolation)
  72. }
  73. XCTAssertNil(try unary.channel.readInbound(as: ResponsePart.self))
  74. XCTAssertNoThrow(try unary.channel.throwIfErrorCaught())
  75. }
  76. func testStreamingSendMessage() {
  77. let streaming = FakeStreamingResponse<Request, Response>()
  78. streaming.activate()
  79. XCTAssertNoThrow(try streaming.sendMessage(.with { $0.text = "1" }))
  80. XCTAssertNoThrow(try streaming.sendMessage(.with { $0.text = "2" }))
  81. XCTAssertNoThrow(try streaming.sendMessage(.with { $0.text = "3" }))
  82. XCTAssertNoThrow(try streaming.sendEnd())
  83. streaming.channel.verifyInbound(as: ResponsePart.self) { part in
  84. part.assertInitialMetadata()
  85. }
  86. for expected in ["1", "2", "3"] {
  87. streaming.channel.verifyInbound(as: ResponsePart.self) { part in
  88. part.assertMessage { message in
  89. XCTAssertEqual(message, .with { $0.text = expected })
  90. }
  91. }
  92. }
  93. streaming.channel.verifyInbound(as: ResponsePart.self) { part in
  94. part.assertTrailingMetadata()
  95. }
  96. streaming.channel.verifyInbound(as: ResponsePart.self) { part in
  97. part.assertStatus()
  98. }
  99. }
  100. func testStreamingSendInitialMetadata() {
  101. let streaming = FakeStreamingResponse<Request, Response>()
  102. streaming.activate()
  103. XCTAssertNoThrow(try streaming.sendInitialMetadata(["foo": "bar"]))
  104. streaming.channel.verifyInbound(as: ResponsePart.self) { part in
  105. part.assertInitialMetadata { metadata in
  106. XCTAssertEqual(metadata, ["foo": "bar"])
  107. }
  108. }
  109. // This should be dropped.
  110. XCTAssertThrowsError(try streaming.sendInitialMetadata(["bar": "baz"])) { error in
  111. XCTAssertTrue(error is FakeResponseProtocolViolation)
  112. }
  113. // Trailers and status.
  114. XCTAssertNoThrow(try streaming.sendEnd(trailingMetadata: ["bar": "foo"]))
  115. streaming.channel.verifyInbound(as: ResponsePart.self) { part in
  116. part.assertTrailingMetadata { metadata in
  117. XCTAssertEqual(metadata, ["bar": "foo"])
  118. }
  119. }
  120. streaming.channel.verifyInbound(as: ResponsePart.self) { part in
  121. part.assertStatus()
  122. }
  123. }
  124. func streamingSendError() {
  125. let streaming = FakeStreamingResponse<Request, Response>()
  126. streaming.activate()
  127. XCTAssertNoThrow(try streaming.sendMessage(.with { $0.text = "1" }))
  128. XCTAssertNoThrow(try streaming.sendError(GRPCError.RPCCancelledByClient()))
  129. streaming.channel.verifyInbound(as: ResponsePart.self) { part in
  130. part.assertInitialMetadata()
  131. }
  132. streaming.channel.verifyInbound(as: ResponsePart.self) { part in
  133. part.assertMessage { message in
  134. XCTAssertEqual(message, .with { $0.text = "1" })
  135. }
  136. }
  137. streaming.channel.verifyInbound(as: ResponsePart.self) { part in
  138. part.assertTrailingMetadata()
  139. }
  140. XCTAssertThrowsError(try streaming.channel.throwIfErrorCaught())
  141. }
  142. func testStreamingIgnoresExtraMessages() {
  143. let streaming = FakeStreamingResponse<Request, Response>()
  144. streaming.activate()
  145. XCTAssertNoThrow(try streaming.sendError(GRPCError.RPCNotImplemented(rpc: "uh oh!")))
  146. // Expected.
  147. streaming.channel.verifyInbound(as: ResponsePart.self) { part in
  148. part.assertTrailingMetadata()
  149. }
  150. XCTAssertThrowsError(try streaming.channel.throwIfErrorCaught())
  151. // Send another error; this should on-op.
  152. XCTAssertThrowsError(try streaming.sendError(GRPCError.RPCCancelledByClient())) { error in
  153. XCTAssertTrue(error is FakeResponseProtocolViolation)
  154. }
  155. XCTAssertNil(try streaming.channel.readInbound(as: ResponsePart.self))
  156. XCTAssertNoThrow(try streaming.channel.throwIfErrorCaught())
  157. // Send a message; this should on-op.
  158. XCTAssertThrowsError(try streaming.sendMessage(.with { $0.text = "ignored" })) { error in
  159. XCTAssertTrue(error is FakeResponseProtocolViolation)
  160. }
  161. XCTAssertNil(try streaming.channel.readInbound(as: ResponsePart.self))
  162. XCTAssertNoThrow(try streaming.channel.throwIfErrorCaught())
  163. }
  164. }
  165. fileprivate extension EmbeddedChannel {
  166. func verifyInbound<Inbound>(as: Inbound.Type = Inbound.self, _ verify: (Inbound) -> () = { _ in }) {
  167. do {
  168. if let inbound = try self.readInbound(as: Inbound.self) {
  169. verify(inbound)
  170. } else {
  171. XCTFail("Nothing to read")
  172. }
  173. } catch {
  174. XCTFail("Unable to readInbound: \(error)")
  175. }
  176. }
  177. }
  178. fileprivate extension _GRPCClientResponsePart {
  179. func assertInitialMetadata(_ verify: (HPACKHeaders) -> () = { _ in }) {
  180. switch self {
  181. case .initialMetadata(let headers):
  182. verify(headers)
  183. default:
  184. XCTFail("Expected initial metadata but got: \(self)")
  185. }
  186. }
  187. func assertMessage(_ verify: (Response) -> () = { _ in }) {
  188. switch self {
  189. case .message(let context):
  190. verify(context.message)
  191. default:
  192. XCTFail("Expected message but got: \(self)")
  193. }
  194. }
  195. func assertTrailingMetadata(_ verify: (HPACKHeaders) -> () = { _ in }) {
  196. switch self {
  197. case .trailingMetadata(let headers):
  198. verify(headers)
  199. default:
  200. XCTFail("Expected trailing metadata but got: \(self)")
  201. }
  202. }
  203. func assertStatus(_ verify: (GRPCStatus) -> () = { _ in }) {
  204. switch self {
  205. case .status(let status):
  206. verify(status)
  207. default:
  208. XCTFail("Expected status but got: \(self)")
  209. }
  210. }
  211. }