ClientConnectionBackoffTests.swift 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. import GRPC
  18. import NIO
  19. import XCTest
  20. class ClientConnectionBackoffTests: XCTestCase {
  21. let port = 8080
  22. var client: EventLoopFuture<ClientConnection>!
  23. var server: EventLoopFuture<Server>!
  24. var group: EventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
  25. override func tearDown() {
  26. if let server = self.server {
  27. XCTAssertNoThrow(try server.flatMap { $0.channel.close() }.wait())
  28. }
  29. // We don't always expect a client (since we deliberately timeout the connection in some cases).
  30. if let client = try? self.client.wait(), client.channel.isActive {
  31. XCTAssertNoThrow(try client.channel.close().wait())
  32. }
  33. XCTAssertNoThrow(try self.group.syncShutdownGracefully())
  34. }
  35. func makeServer() -> EventLoopFuture<Server> {
  36. let configuration = Server.Configuration(
  37. target: .hostAndPort("localhost", self.port),
  38. eventLoopGroup: self.group,
  39. serviceProviders: [])
  40. return Server.start(configuration: configuration)
  41. }
  42. func makeClientConfiguration() -> ClientConnection.Configuration {
  43. return .init(
  44. target: .hostAndPort("localhost", self.port),
  45. eventLoopGroup: self.group,
  46. connectionBackoff: ConnectionBackoff())
  47. }
  48. func makeClientConnection(
  49. _ configuration: ClientConnection.Configuration
  50. ) -> EventLoopFuture<ClientConnection> {
  51. return ClientConnection.start(configuration)
  52. }
  53. func testClientConnectionFailsWithNoBackoff() throws {
  54. var configuration = self.makeClientConfiguration()
  55. configuration.connectionBackoff = nil
  56. self.client = self.makeClientConnection(configuration)
  57. XCTAssertThrowsError(try self.client.wait()) { error in
  58. XCTAssert(error is NIOConnectionError)
  59. }
  60. }
  61. func testClientEventuallyConnects() throws {
  62. let clientConnected = self.expectation(description: "client connected")
  63. let serverStarted = self.expectation(description: "server started")
  64. // Start the client first.
  65. self.client = self.makeClientConnection(self.makeClientConfiguration())
  66. self.client.assertSuccess(fulfill: clientConnected)
  67. // Sleep for a little bit to make sure we hit the backoff.
  68. Thread.sleep(forTimeInterval: 0.2)
  69. self.server = self.makeServer()
  70. self.server.assertSuccess(fulfill: serverStarted)
  71. self.wait(for: [serverStarted, clientConnected], timeout: 2.0, enforceOrder: true)
  72. }
  73. func testClientEventuallyTimesOut() throws {
  74. var configuration = self.makeClientConfiguration()
  75. configuration.connectionBackoff = ConnectionBackoff(maximumBackoff: 0.1)
  76. self.client = self.makeClientConnection(configuration)
  77. XCTAssertThrowsError(try self.client.wait()) { error in
  78. XCTAssert(error is NIOConnectionError)
  79. }
  80. }
  81. }