FakeResponseStreamTests.swift 8.1 KB

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