| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- /*
- * Copyright 2025, gRPC Authors All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- import GRPCCore
- import GRPCNIOTransportHTTP2
- import Testing
- struct HTTP2TransportRegressionTests {
- @Test
- @available(gRPCSwiftNIOTransport 2.2, *)
- func testCancelledServerDoesntWedge() async throws {
- // Checks that a gRPC server with an active RPC shuts down when the server task
- // is cancelled. The flavour of transport doesn't matter here so long as it's HTTP/2.
- // Yield a signal so that we know when to cancel the server task. Then sleep
- // so that the RPC is still running when the server task is cancelled.
- let signal = AsyncStream.makeStream(of: Void.self)
- let helloWorld = HelloWorldService { request, _ in
- signal.continuation.yield()
- try await Task.sleep(for: .seconds(60))
- return HelloResponse(message: "Hello, \(request.name)!")
- }
- let server = GRPCServer(
- transport: .http2NIOPosix(
- address: .ipv4(host: "127.0.0.1", port: 0),
- transportSecurity: .plaintext
- ),
- services: [helloWorld]
- )
- let serverTask = Task {
- try await server.serve()
- }
- let address = try await server.listeningAddress
- let port = try #require(address?.ipv4?.port)
- try await withGRPCClient(
- transport: .http2NIOPosix(
- target: .ipv4(address: "127.0.0.1", port: port),
- transportSecurity: .plaintext
- )
- ) { client in
- let helloWorld = HelloWorld.Client(wrapping: client)
- // Kick this off then wait for the signal.
- let clientTask = Task {
- try await helloWorld.sayHello(HelloRequest(name: "World"))
- }
- for await _ in signal.stream {
- break
- }
- // The RPC is in progress, so cancel the server.
- serverTask.cancel()
- // Now the client should complete.
- #if compiler(>=6.1)
- let error = await #expect(throws: RPCError.self) {
- try await clientTask.value
- }
- #expect(error?.code == .unavailable)
- #else
- await #expect(throws: RPCError.self) {
- try await clientTask.value
- }
- #endif
- }
- }
- }
|