GRPCStatusCodeTests.swift 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /*
  2. * Copyright 2019, 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 Foundation
  17. @testable import GRPC
  18. import NIO
  19. import NIOHTTP1
  20. import NIOHTTP2
  21. import XCTest
  22. class GRPCStatusCodeTests: XCTestCase {
  23. var channel: EmbeddedChannel!
  24. var metadataPromise: EventLoopPromise<HTTPHeaders>!
  25. var responsePromise: EventLoopPromise<Echo_EchoResponse>!
  26. var statusPromise: EventLoopPromise<GRPCStatus>!
  27. override func setUp() {
  28. super.setUp()
  29. self.channel = EmbeddedChannel()
  30. self.metadataPromise = self.channel.eventLoop.makePromise()
  31. self.responsePromise = self.channel.eventLoop.makePromise()
  32. self.statusPromise = self.channel.eventLoop.makePromise()
  33. try! self.channel.pipeline.addHandlers([
  34. HTTP1ToRawGRPCClientCodec(),
  35. GRPCClientCodec<Echo_EchoRequest, Echo_EchoResponse>(),
  36. GRPCClientUnaryResponseChannelHandler<Echo_EchoResponse>(
  37. initialMetadataPromise: self.metadataPromise,
  38. responsePromise: self.responsePromise,
  39. statusPromise: self.statusPromise,
  40. errorDelegate: nil,
  41. timeout: .infinite)
  42. ]).wait()
  43. }
  44. override func tearDown() {
  45. self.metadataPromise.fail(GRPCError.client(.cancelledByClient))
  46. self.responsePromise.fail(GRPCError.client(.cancelledByClient))
  47. self.statusPromise.fail(GRPCError.client(.cancelledByClient))
  48. }
  49. func responseHead(code: HTTPResponseStatus, headers: HTTPHeaders = HTTPHeaders()) -> HTTPClientResponsePart {
  50. return .head(HTTPResponseHead(version: HTTPVersion(major: 2, minor: 0), status: code, headers: headers))
  51. }
  52. func testTooManyRequests() throws {
  53. XCTAssertNoThrow(try self.channel.writeInbound(self.responseHead(code: .tooManyRequests)))
  54. XCTAssertEqual(try statusPromise.futureResult.map { $0.code }.wait(), .unavailable)
  55. }
  56. func testBadGateway() throws {
  57. XCTAssertNoThrow(try self.channel.writeInbound(self.responseHead(code: .badGateway)))
  58. XCTAssertEqual(try statusPromise.futureResult.map { $0.code }.wait(), .unavailable)
  59. }
  60. func testServiceUnavailable() throws {
  61. XCTAssertNoThrow(try self.channel.writeInbound(self.responseHead(code: .serviceUnavailable)))
  62. XCTAssertEqual(try statusPromise.futureResult.map { $0.code }.wait(), .unavailable)
  63. }
  64. func testGatewayTimeout() throws {
  65. XCTAssertNoThrow(try self.channel.writeInbound(self.responseHead(code: .gatewayTimeout)))
  66. XCTAssertEqual(try statusPromise.futureResult.map { $0.code }.wait(), .unavailable)
  67. }
  68. func testBadRequest() throws {
  69. XCTAssertNoThrow(try self.channel.writeInbound(self.responseHead(code: .badRequest)))
  70. XCTAssertEqual(try statusPromise.futureResult.map { $0.code }.wait(), .internalError)
  71. }
  72. func testUnauthorized() throws {
  73. XCTAssertNoThrow(try self.channel.writeInbound(self.responseHead(code: .unauthorized)))
  74. XCTAssertEqual(try statusPromise.futureResult.map { $0.code }.wait(), .unauthenticated)
  75. }
  76. func testForbidden() throws {
  77. XCTAssertNoThrow(try self.channel.writeInbound(self.responseHead(code: .forbidden)))
  78. XCTAssertEqual(try statusPromise.futureResult.map { $0.code }.wait(), .permissionDenied)
  79. }
  80. func testNotFound() throws {
  81. XCTAssertNoThrow(try self.channel.writeInbound(self.responseHead(code: .notFound)))
  82. XCTAssertEqual(try statusPromise.futureResult.map { $0.code }.wait(), .unimplemented)
  83. }
  84. func testStatusCodeAndMessageAreRespectedForNon200Responses() throws {
  85. let statusCode: GRPCStatus.Code = .doNotUse
  86. let statusMessage = "Not the HTTP error phrase"
  87. var headers = HTTPHeaders()
  88. headers.add(name: GRPCHeaderName.statusCode, value: "\(statusCode.rawValue)")
  89. headers.add(name: GRPCHeaderName.statusMessage, value: statusMessage)
  90. XCTAssertNoThrow(try self.channel.writeInbound(self.responseHead(code: .imATeapot, headers: headers)))
  91. let status = try statusPromise.futureResult.wait()
  92. XCTAssertEqual(status.code, statusCode)
  93. XCTAssertEqual(status.message, statusMessage)
  94. }
  95. }