/* * Copyright 2024, 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 @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) public protocol InteroperabilityTest { /// Run a test case using the given connection. /// /// The test case is considered unsuccessful if any exception is thrown, conversely if no /// exceptions are thrown it is successful. /// /// - Parameter client: The client to use for the test. /// - Throws: Any exception may be thrown to indicate an unsuccessful test. func run(client: GRPCClient) async throws } /// Test cases as listed by the [gRPC interoperability test description specification] /// (https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md). /// /// This is not a complete list, the following tests have not been implemented: /// - cacheable_unary (caching not supported) /// - cancel_after_begin (if the client cancels the task running the request, there's no response to be /// received, so we can't check we got back a Cancelled status code) /// - cancel_after_first_response (same reason as above) /// - client_compressed_streaming (we don't support per-message compression, so we can't implement this) /// - compute_engine_creds /// - jwt_token_creds /// - oauth2_auth_token /// - per_rpc_creds /// - google_default_credentials /// - compute_engine_channel_credentials /// - timeout_on_sleeping_server (timeouts end up being surfaced as `CancellationError`s, so we /// can't really implement this test) /// /// Note: Tests for compression have not been implemented yet as compression is /// not supported. Once the API which allows for compression will be implemented /// these tests should be added. public enum InteroperabilityTestCase: String, CaseIterable, Sendable { case emptyUnary = "empty_unary" case largeUnary = "large_unary" case clientCompressedUnary = "client_compressed_unary" case serverCompressedUnary = "server_compressed_unary" case clientStreaming = "client_streaming" case serverStreaming = "server_streaming" case serverCompressedStreaming = "server_compressed_streaming" case pingPong = "ping_pong" case emptyStream = "empty_stream" case customMetadata = "custom_metadata" case statusCodeAndMessage = "status_code_and_message" case specialStatusMessage = "special_status_message" case unimplementedMethod = "unimplemented_method" case unimplementedService = "unimplemented_service" public var name: String { return self.rawValue } } @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension InteroperabilityTestCase { /// Return a new instance of the test case. public func makeTest() -> any InteroperabilityTest { switch self { case .emptyUnary: return EmptyUnary() case .largeUnary: return LargeUnary() case .clientCompressedUnary: return ClientCompressedUnary() case .serverCompressedUnary: return ServerCompressedUnary() case .clientStreaming: return ClientStreaming() case .serverStreaming: return ServerStreaming() case .serverCompressedStreaming: return ServerCompressedStreaming() case .pingPong: return PingPong() case .emptyStream: return EmptyStream() case .customMetadata: return CustomMetadata() case .statusCodeAndMessage: return StatusCodeAndMessage() case .specialStatusMessage: return SpecialStatusMessage() case .unimplementedMethod: return UnimplementedMethod() case .unimplementedService: return UnimplementedService() } } }