|
|
@@ -14,14 +14,14 @@
|
|
|
* limitations under the License.
|
|
|
*/
|
|
|
|
|
|
-#if os(macOS) || os(Linux) // swift-format doesn't like canImport(Foundation.Process)
|
|
|
-
|
|
|
-import XCTest
|
|
|
+import Testing
|
|
|
|
|
|
@testable import GRPCCodeGen
|
|
|
|
|
|
-final class ClientCodeTranslatorSnippetBasedTests: XCTestCase {
|
|
|
- func testClientCodeTranslatorUnaryMethod() throws {
|
|
|
+@Suite
|
|
|
+struct ClientCodeTranslatorSnippetBasedTests {
|
|
|
+ @Test
|
|
|
+ func translate() {
|
|
|
let method = MethodDescriptor(
|
|
|
documentation: "/// Documentation for MethodA",
|
|
|
name: Name(base: "MethodA", generatedUpperCase: "MethodA", generatedLowerCase: "methodA"),
|
|
|
@@ -30,14 +30,15 @@ final class ClientCodeTranslatorSnippetBasedTests: XCTestCase {
|
|
|
inputType: "NamespaceA_ServiceARequest",
|
|
|
outputType: "NamespaceA_ServiceAResponse"
|
|
|
)
|
|
|
+
|
|
|
let service = ServiceDescriptor(
|
|
|
documentation: "/// Documentation for ServiceA",
|
|
|
name: Name(base: "ServiceA", generatedUpperCase: "ServiceA", generatedLowerCase: ""),
|
|
|
namespace: Name(base: "namespaceA", generatedUpperCase: "NamespaceA", generatedLowerCase: ""),
|
|
|
methods: [method]
|
|
|
)
|
|
|
- let expectedSwift =
|
|
|
- """
|
|
|
+
|
|
|
+ let expectedSwift = """
|
|
|
/// Documentation for ServiceA
|
|
|
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
public protocol NamespaceA_ServiceA_ClientProtocol: Sendable {
|
|
|
@@ -121,694 +122,22 @@ final class ClientCodeTranslatorSnippetBasedTests: XCTestCase {
|
|
|
}
|
|
|
"""
|
|
|
|
|
|
- try self.assertClientCodeTranslation(
|
|
|
- codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
|
|
|
- expectedSwift: expectedSwift,
|
|
|
- accessLevel: .public
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- func testClientCodeTranslatorClientStreamingMethod() throws {
|
|
|
- let method = MethodDescriptor(
|
|
|
- documentation: "/// Documentation for MethodA",
|
|
|
- name: Name(base: "MethodA", generatedUpperCase: "MethodA", generatedLowerCase: "methodA"),
|
|
|
- isInputStreaming: true,
|
|
|
- isOutputStreaming: false,
|
|
|
- inputType: "NamespaceA_ServiceARequest",
|
|
|
- outputType: "NamespaceA_ServiceAResponse"
|
|
|
- )
|
|
|
- let service = ServiceDescriptor(
|
|
|
- documentation: "/// Documentation for ServiceA",
|
|
|
- name: Name(base: "ServiceA", generatedUpperCase: "ServiceA", generatedLowerCase: ""),
|
|
|
- namespace: Name(base: "namespaceA", generatedUpperCase: "NamespaceA", generatedLowerCase: ""),
|
|
|
- methods: [method]
|
|
|
- )
|
|
|
- let expectedSwift =
|
|
|
- """
|
|
|
- /// Documentation for ServiceA
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- public protocol NamespaceA_ServiceA_ClientProtocol: Sendable {
|
|
|
- /// Documentation for MethodA
|
|
|
- func methodA<Result>(
|
|
|
- request: GRPCCore.StreamingClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- serializer: some GRPCCore.MessageSerializer<NamespaceA_ServiceARequest>,
|
|
|
- deserializer: some GRPCCore.MessageDeserializer<NamespaceA_ServiceAResponse>,
|
|
|
- options: GRPCCore.CallOptions,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable
|
|
|
- }
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension NamespaceA_ServiceA.ClientProtocol {
|
|
|
- public func methodA<Result>(
|
|
|
- request: GRPCCore.StreamingClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result = { response in
|
|
|
- try response.message
|
|
|
- }
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- try await self.methodA(
|
|
|
- request: request,
|
|
|
- serializer: GRPCProtobuf.ProtobufSerializer<NamespaceA_ServiceARequest>(),
|
|
|
- deserializer: GRPCProtobuf.ProtobufDeserializer<NamespaceA_ServiceAResponse>(),
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension NamespaceA_ServiceA.ClientProtocol {
|
|
|
- /// Documentation for MethodA
|
|
|
- public func methodA<Result>(
|
|
|
- metadata: GRPCCore.Metadata = [:],
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- requestProducer producer: @Sendable @escaping (GRPCCore.RPCWriter<NamespaceA_ServiceARequest>) async throws -> Void,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result = { response in
|
|
|
- try response.message
|
|
|
- }
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- let request = GRPCCore.StreamingClientRequest<NamespaceA_ServiceARequest>(
|
|
|
- metadata: metadata,
|
|
|
- producer: producer
|
|
|
- )
|
|
|
- return try await self.methodA(
|
|
|
- request: request,
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- /// Documentation for ServiceA
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- public struct NamespaceA_ServiceA_Client: NamespaceA_ServiceA.ClientProtocol {
|
|
|
- private let client: GRPCCore.GRPCClient
|
|
|
-
|
|
|
- public init(wrapping client: GRPCCore.GRPCClient) {
|
|
|
- self.client = client
|
|
|
- }
|
|
|
-
|
|
|
- /// Documentation for MethodA
|
|
|
- public func methodA<Result>(
|
|
|
- request: GRPCCore.StreamingClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- serializer: some GRPCCore.MessageSerializer<NamespaceA_ServiceARequest>,
|
|
|
- deserializer: some GRPCCore.MessageDeserializer<NamespaceA_ServiceAResponse>,
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result = { response in
|
|
|
- try response.message
|
|
|
- }
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- try await self.client.clientStreaming(
|
|
|
- request: request,
|
|
|
- descriptor: NamespaceA_ServiceA.Method.MethodA.descriptor,
|
|
|
- serializer: serializer,
|
|
|
- deserializer: deserializer,
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- """
|
|
|
-
|
|
|
- try self.assertClientCodeTranslation(
|
|
|
- codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
|
|
|
- expectedSwift: expectedSwift,
|
|
|
- accessLevel: .public
|
|
|
- )
|
|
|
+ let rendered = self.render(accessLevel: .public, service: service)
|
|
|
+ #expect(rendered == expectedSwift)
|
|
|
}
|
|
|
|
|
|
- func testClientCodeTranslatorServerStreamingMethod() throws {
|
|
|
- let method = MethodDescriptor(
|
|
|
- documentation: "/// Documentation for MethodA",
|
|
|
- name: Name(base: "MethodA", generatedUpperCase: "MethodA", generatedLowerCase: "methodA"),
|
|
|
- isInputStreaming: false,
|
|
|
- isOutputStreaming: true,
|
|
|
- inputType: "NamespaceA_ServiceARequest",
|
|
|
- outputType: "NamespaceA_ServiceAResponse"
|
|
|
- )
|
|
|
- let service = ServiceDescriptor(
|
|
|
- documentation: "/// Documentation for ServiceA",
|
|
|
- name: Name(base: "ServiceA", generatedUpperCase: "ServiceA", generatedLowerCase: ""),
|
|
|
- namespace: Name(base: "namespaceA", generatedUpperCase: "NamespaceA", generatedLowerCase: ""),
|
|
|
- methods: [method]
|
|
|
- )
|
|
|
- let expectedSwift =
|
|
|
- """
|
|
|
- /// Documentation for ServiceA
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- public protocol NamespaceA_ServiceA_ClientProtocol: Sendable {
|
|
|
- /// Documentation for MethodA
|
|
|
- func methodA<Result>(
|
|
|
- request: GRPCCore.ClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- serializer: some GRPCCore.MessageSerializer<NamespaceA_ServiceARequest>,
|
|
|
- deserializer: some GRPCCore.MessageDeserializer<NamespaceA_ServiceAResponse>,
|
|
|
- options: GRPCCore.CallOptions,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable
|
|
|
- }
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension NamespaceA_ServiceA.ClientProtocol {
|
|
|
- public func methodA<Result>(
|
|
|
- request: GRPCCore.ClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- try await self.methodA(
|
|
|
- request: request,
|
|
|
- serializer: GRPCProtobuf.ProtobufSerializer<NamespaceA_ServiceARequest>(),
|
|
|
- deserializer: GRPCProtobuf.ProtobufDeserializer<NamespaceA_ServiceAResponse>(),
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension NamespaceA_ServiceA.ClientProtocol {
|
|
|
- /// Documentation for MethodA
|
|
|
- public func methodA<Result>(
|
|
|
- _ message: NamespaceA_ServiceARequest,
|
|
|
- metadata: GRPCCore.Metadata = [:],
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- let request = GRPCCore.ClientRequest<NamespaceA_ServiceARequest>(
|
|
|
- message: message,
|
|
|
- metadata: metadata
|
|
|
- )
|
|
|
- return try await self.methodA(
|
|
|
- request: request,
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- /// Documentation for ServiceA
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- public struct NamespaceA_ServiceA_Client: NamespaceA_ServiceA.ClientProtocol {
|
|
|
- private let client: GRPCCore.GRPCClient
|
|
|
-
|
|
|
- public init(wrapping client: GRPCCore.GRPCClient) {
|
|
|
- self.client = client
|
|
|
- }
|
|
|
-
|
|
|
- /// Documentation for MethodA
|
|
|
- public func methodA<Result>(
|
|
|
- request: GRPCCore.ClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- serializer: some GRPCCore.MessageSerializer<NamespaceA_ServiceARequest>,
|
|
|
- deserializer: some GRPCCore.MessageDeserializer<NamespaceA_ServiceAResponse>,
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- try await self.client.serverStreaming(
|
|
|
- request: request,
|
|
|
- descriptor: NamespaceA_ServiceA.Method.MethodA.descriptor,
|
|
|
- serializer: serializer,
|
|
|
- deserializer: deserializer,
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- """
|
|
|
-
|
|
|
- try self.assertClientCodeTranslation(
|
|
|
- codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
|
|
|
- expectedSwift: expectedSwift,
|
|
|
- accessLevel: .public
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- func testClientCodeTranslatorBidirectionalStreamingMethod() throws {
|
|
|
- let method = MethodDescriptor(
|
|
|
- documentation: "/// Documentation for MethodA",
|
|
|
- name: Name(base: "MethodA", generatedUpperCase: "MethodA", generatedLowerCase: "methodA"),
|
|
|
- isInputStreaming: true,
|
|
|
- isOutputStreaming: true,
|
|
|
- inputType: "NamespaceA_ServiceARequest",
|
|
|
- outputType: "NamespaceA_ServiceAResponse"
|
|
|
- )
|
|
|
- let service = ServiceDescriptor(
|
|
|
- documentation: "/// Documentation for ServiceA",
|
|
|
- name: Name(base: "ServiceA", generatedUpperCase: "ServiceA", generatedLowerCase: ""),
|
|
|
- namespace: Name(base: "namespaceA", generatedUpperCase: "NamespaceA", generatedLowerCase: ""),
|
|
|
- methods: [method]
|
|
|
- )
|
|
|
- let expectedSwift =
|
|
|
- """
|
|
|
- /// Documentation for ServiceA
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- public protocol NamespaceA_ServiceA_ClientProtocol: Sendable {
|
|
|
- /// Documentation for MethodA
|
|
|
- func methodA<Result>(
|
|
|
- request: GRPCCore.StreamingClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- serializer: some GRPCCore.MessageSerializer<NamespaceA_ServiceARequest>,
|
|
|
- deserializer: some GRPCCore.MessageDeserializer<NamespaceA_ServiceAResponse>,
|
|
|
- options: GRPCCore.CallOptions,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable
|
|
|
- }
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension NamespaceA_ServiceA.ClientProtocol {
|
|
|
- public func methodA<Result>(
|
|
|
- request: GRPCCore.StreamingClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- try await self.methodA(
|
|
|
- request: request,
|
|
|
- serializer: GRPCProtobuf.ProtobufSerializer<NamespaceA_ServiceARequest>(),
|
|
|
- deserializer: GRPCProtobuf.ProtobufDeserializer<NamespaceA_ServiceAResponse>(),
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension NamespaceA_ServiceA.ClientProtocol {
|
|
|
- /// Documentation for MethodA
|
|
|
- public func methodA<Result>(
|
|
|
- metadata: GRPCCore.Metadata = [:],
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- requestProducer producer: @Sendable @escaping (GRPCCore.RPCWriter<NamespaceA_ServiceARequest>) async throws -> Void,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- let request = GRPCCore.StreamingClientRequest<NamespaceA_ServiceARequest>(
|
|
|
- metadata: metadata,
|
|
|
- producer: producer
|
|
|
- )
|
|
|
- return try await self.methodA(
|
|
|
- request: request,
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- /// Documentation for ServiceA
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- public struct NamespaceA_ServiceA_Client: NamespaceA_ServiceA.ClientProtocol {
|
|
|
- private let client: GRPCCore.GRPCClient
|
|
|
-
|
|
|
- public init(wrapping client: GRPCCore.GRPCClient) {
|
|
|
- self.client = client
|
|
|
- }
|
|
|
-
|
|
|
- /// Documentation for MethodA
|
|
|
- public func methodA<Result>(
|
|
|
- request: GRPCCore.StreamingClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- serializer: some GRPCCore.MessageSerializer<NamespaceA_ServiceARequest>,
|
|
|
- deserializer: some GRPCCore.MessageDeserializer<NamespaceA_ServiceAResponse>,
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- try await self.client.bidirectionalStreaming(
|
|
|
- request: request,
|
|
|
- descriptor: NamespaceA_ServiceA.Method.MethodA.descriptor,
|
|
|
- serializer: serializer,
|
|
|
- deserializer: deserializer,
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- """
|
|
|
-
|
|
|
- try self.assertClientCodeTranslation(
|
|
|
- codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
|
|
|
- expectedSwift: expectedSwift,
|
|
|
- accessLevel: .public
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- func testClientCodeTranslatorMultipleMethod() throws {
|
|
|
- let methodA = MethodDescriptor(
|
|
|
- documentation: "/// Documentation for MethodA",
|
|
|
- name: Name(base: "MethodA", generatedUpperCase: "MethodA", generatedLowerCase: "methodA"),
|
|
|
- isInputStreaming: true,
|
|
|
- isOutputStreaming: false,
|
|
|
- inputType: "NamespaceA_ServiceARequest",
|
|
|
- outputType: "NamespaceA_ServiceAResponse"
|
|
|
- )
|
|
|
- let methodB = MethodDescriptor(
|
|
|
- documentation: "/// Documentation for MethodB",
|
|
|
- name: Name(base: "MethodB", generatedUpperCase: "MethodB", generatedLowerCase: "methodB"),
|
|
|
- isInputStreaming: false,
|
|
|
- isOutputStreaming: true,
|
|
|
- inputType: "NamespaceA_ServiceARequest",
|
|
|
- outputType: "NamespaceA_ServiceAResponse"
|
|
|
- )
|
|
|
- let service = ServiceDescriptor(
|
|
|
- documentation: "/// Documentation for ServiceA",
|
|
|
- name: Name(base: "ServiceA", generatedUpperCase: "ServiceA", generatedLowerCase: ""),
|
|
|
- namespace: Name(base: "namespaceA", generatedUpperCase: "NamespaceA", generatedLowerCase: ""),
|
|
|
- methods: [methodA, methodB]
|
|
|
- )
|
|
|
- let expectedSwift =
|
|
|
- """
|
|
|
- /// Documentation for ServiceA
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- package protocol NamespaceA_ServiceA_ClientProtocol: Sendable {
|
|
|
- /// Documentation for MethodA
|
|
|
- func methodA<Result>(
|
|
|
- request: GRPCCore.StreamingClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- serializer: some GRPCCore.MessageSerializer<NamespaceA_ServiceARequest>,
|
|
|
- deserializer: some GRPCCore.MessageDeserializer<NamespaceA_ServiceAResponse>,
|
|
|
- options: GRPCCore.CallOptions,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable
|
|
|
-
|
|
|
- /// Documentation for MethodB
|
|
|
- func methodB<Result>(
|
|
|
- request: GRPCCore.ClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- serializer: some GRPCCore.MessageSerializer<NamespaceA_ServiceARequest>,
|
|
|
- deserializer: some GRPCCore.MessageDeserializer<NamespaceA_ServiceAResponse>,
|
|
|
- options: GRPCCore.CallOptions,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable
|
|
|
- }
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension NamespaceA_ServiceA.ClientProtocol {
|
|
|
- package func methodA<Result>(
|
|
|
- request: GRPCCore.StreamingClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result = { response in
|
|
|
- try response.message
|
|
|
- }
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- try await self.methodA(
|
|
|
- request: request,
|
|
|
- serializer: GRPCProtobuf.ProtobufSerializer<NamespaceA_ServiceARequest>(),
|
|
|
- deserializer: GRPCProtobuf.ProtobufDeserializer<NamespaceA_ServiceAResponse>(),
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- package func methodB<Result>(
|
|
|
- request: GRPCCore.ClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- try await self.methodB(
|
|
|
- request: request,
|
|
|
- serializer: GRPCProtobuf.ProtobufSerializer<NamespaceA_ServiceARequest>(),
|
|
|
- deserializer: GRPCProtobuf.ProtobufDeserializer<NamespaceA_ServiceAResponse>(),
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension NamespaceA_ServiceA.ClientProtocol {
|
|
|
- /// Documentation for MethodA
|
|
|
- package func methodA<Result>(
|
|
|
- metadata: GRPCCore.Metadata = [:],
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- requestProducer producer: @Sendable @escaping (GRPCCore.RPCWriter<NamespaceA_ServiceARequest>) async throws -> Void,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result = { response in
|
|
|
- try response.message
|
|
|
- }
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- let request = GRPCCore.StreamingClientRequest<NamespaceA_ServiceARequest>(
|
|
|
- metadata: metadata,
|
|
|
- producer: producer
|
|
|
- )
|
|
|
- return try await self.methodA(
|
|
|
- request: request,
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- /// Documentation for MethodB
|
|
|
- package func methodB<Result>(
|
|
|
- _ message: NamespaceA_ServiceARequest,
|
|
|
- metadata: GRPCCore.Metadata = [:],
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- let request = GRPCCore.ClientRequest<NamespaceA_ServiceARequest>(
|
|
|
- message: message,
|
|
|
- metadata: metadata
|
|
|
- )
|
|
|
- return try await self.methodB(
|
|
|
- request: request,
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- /// Documentation for ServiceA
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- package struct NamespaceA_ServiceA_Client: NamespaceA_ServiceA.ClientProtocol {
|
|
|
- private let client: GRPCCore.GRPCClient
|
|
|
-
|
|
|
- package init(wrapping client: GRPCCore.GRPCClient) {
|
|
|
- self.client = client
|
|
|
- }
|
|
|
-
|
|
|
- /// Documentation for MethodA
|
|
|
- package func methodA<Result>(
|
|
|
- request: GRPCCore.StreamingClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- serializer: some GRPCCore.MessageSerializer<NamespaceA_ServiceARequest>,
|
|
|
- deserializer: some GRPCCore.MessageDeserializer<NamespaceA_ServiceAResponse>,
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result = { response in
|
|
|
- try response.message
|
|
|
- }
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- try await self.client.clientStreaming(
|
|
|
- request: request,
|
|
|
- descriptor: NamespaceA_ServiceA.Method.MethodA.descriptor,
|
|
|
- serializer: serializer,
|
|
|
- deserializer: deserializer,
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- /// Documentation for MethodB
|
|
|
- package func methodB<Result>(
|
|
|
- request: GRPCCore.ClientRequest<NamespaceA_ServiceARequest>,
|
|
|
- serializer: some GRPCCore.MessageSerializer<NamespaceA_ServiceARequest>,
|
|
|
- deserializer: some GRPCCore.MessageDeserializer<NamespaceA_ServiceAResponse>,
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<NamespaceA_ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- try await self.client.serverStreaming(
|
|
|
- request: request,
|
|
|
- descriptor: NamespaceA_ServiceA.Method.MethodB.descriptor,
|
|
|
- serializer: serializer,
|
|
|
- deserializer: deserializer,
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- """
|
|
|
-
|
|
|
- try self.assertClientCodeTranslation(
|
|
|
- codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
|
|
|
- expectedSwift: expectedSwift,
|
|
|
- accessLevel: .package
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- func testClientCodeTranslatorNoNamespaceService() throws {
|
|
|
- let method = MethodDescriptor(
|
|
|
- documentation: "/// Documentation for MethodA",
|
|
|
- name: Name(base: "MethodA", generatedUpperCase: "MethodA", generatedLowerCase: "methodA"),
|
|
|
- isInputStreaming: false,
|
|
|
- isOutputStreaming: false,
|
|
|
- inputType: "ServiceARequest",
|
|
|
- outputType: "ServiceAResponse"
|
|
|
- )
|
|
|
- let service = ServiceDescriptor(
|
|
|
- documentation: "/// Documentation for ServiceA",
|
|
|
- name: Name(base: "ServiceA", generatedUpperCase: "ServiceA", generatedLowerCase: ""),
|
|
|
- namespace: Name(base: "", generatedUpperCase: "", generatedLowerCase: ""),
|
|
|
- methods: [method]
|
|
|
- )
|
|
|
- let expectedSwift =
|
|
|
- """
|
|
|
- /// Documentation for ServiceA
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- internal protocol ServiceA_ClientProtocol: Sendable {
|
|
|
- /// Documentation for MethodA
|
|
|
- func methodA<Result>(
|
|
|
- request: GRPCCore.ClientRequest<ServiceARequest>,
|
|
|
- serializer: some GRPCCore.MessageSerializer<ServiceARequest>,
|
|
|
- deserializer: some GRPCCore.MessageDeserializer<ServiceAResponse>,
|
|
|
- options: GRPCCore.CallOptions,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<ServiceAResponse>) async throws -> Result
|
|
|
- ) async throws -> Result where Result: Sendable
|
|
|
- }
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension ServiceA.ClientProtocol {
|
|
|
- internal func methodA<Result>(
|
|
|
- request: GRPCCore.ClientRequest<ServiceARequest>,
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<ServiceAResponse>) async throws -> Result = { response in
|
|
|
- try response.message
|
|
|
- }
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- try await self.methodA(
|
|
|
- request: request,
|
|
|
- serializer: GRPCProtobuf.ProtobufSerializer<ServiceARequest>(),
|
|
|
- deserializer: GRPCProtobuf.ProtobufDeserializer<ServiceAResponse>(),
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension ServiceA.ClientProtocol {
|
|
|
- /// Documentation for MethodA
|
|
|
- internal func methodA<Result>(
|
|
|
- _ message: ServiceARequest,
|
|
|
- metadata: GRPCCore.Metadata = [:],
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<ServiceAResponse>) async throws -> Result = { response in
|
|
|
- try response.message
|
|
|
- }
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- let request = GRPCCore.ClientRequest<ServiceARequest>(
|
|
|
- message: message,
|
|
|
- metadata: metadata
|
|
|
- )
|
|
|
- return try await self.methodA(
|
|
|
- request: request,
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- /// Documentation for ServiceA
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- internal struct ServiceA_Client: ServiceA.ClientProtocol {
|
|
|
- private let client: GRPCCore.GRPCClient
|
|
|
-
|
|
|
- internal init(wrapping client: GRPCCore.GRPCClient) {
|
|
|
- self.client = client
|
|
|
- }
|
|
|
-
|
|
|
- /// Documentation for MethodA
|
|
|
- internal func methodA<Result>(
|
|
|
- request: GRPCCore.ClientRequest<ServiceARequest>,
|
|
|
- serializer: some GRPCCore.MessageSerializer<ServiceARequest>,
|
|
|
- deserializer: some GRPCCore.MessageDeserializer<ServiceAResponse>,
|
|
|
- options: GRPCCore.CallOptions = .defaults,
|
|
|
- onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<ServiceAResponse>) async throws -> Result = { response in
|
|
|
- try response.message
|
|
|
- }
|
|
|
- ) async throws -> Result where Result: Sendable {
|
|
|
- try await self.client.unary(
|
|
|
- request: request,
|
|
|
- descriptor: ServiceA.Method.MethodA.descriptor,
|
|
|
- serializer: serializer,
|
|
|
- deserializer: deserializer,
|
|
|
- options: options,
|
|
|
- onResponse: handleResponse
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- """
|
|
|
-
|
|
|
- try self.assertClientCodeTranslation(
|
|
|
- codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
|
|
|
- expectedSwift: expectedSwift,
|
|
|
- accessLevel: .internal
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- func testClientCodeTranslatorMultipleServices() throws {
|
|
|
- let serviceA = ServiceDescriptor(
|
|
|
- documentation: "/// Documentation for ServiceA",
|
|
|
- name: Name(base: "ServiceA", generatedUpperCase: "ServiceA", generatedLowerCase: ""),
|
|
|
- namespace: Name(
|
|
|
- base: "nammespaceA",
|
|
|
- generatedUpperCase: "NamespaceA",
|
|
|
- generatedLowerCase: ""
|
|
|
- ),
|
|
|
- methods: []
|
|
|
- )
|
|
|
- let serviceB = ServiceDescriptor(
|
|
|
- documentation: """
|
|
|
- /// Documentation for ServiceB
|
|
|
- ///
|
|
|
- /// Line 2
|
|
|
- """,
|
|
|
- name: Name(base: "ServiceB", generatedUpperCase: "ServiceB", generatedLowerCase: ""),
|
|
|
- namespace: Name(base: "", generatedUpperCase: "", generatedLowerCase: ""),
|
|
|
- methods: []
|
|
|
- )
|
|
|
- let expectedSwift =
|
|
|
- """
|
|
|
- /// Documentation for ServiceA
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- public protocol NamespaceA_ServiceA_ClientProtocol: Sendable {}
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension NamespaceA_ServiceA.ClientProtocol {
|
|
|
- }
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension NamespaceA_ServiceA.ClientProtocol {
|
|
|
- }
|
|
|
- /// Documentation for ServiceA
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- public struct NamespaceA_ServiceA_Client: NamespaceA_ServiceA.ClientProtocol {
|
|
|
- private let client: GRPCCore.GRPCClient
|
|
|
-
|
|
|
- public init(wrapping client: GRPCCore.GRPCClient) {
|
|
|
- self.client = client
|
|
|
- }
|
|
|
- }
|
|
|
- /// Documentation for ServiceB
|
|
|
- ///
|
|
|
- /// Line 2
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- public protocol ServiceB_ClientProtocol: Sendable {}
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension ServiceB.ClientProtocol {
|
|
|
- }
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- extension ServiceB.ClientProtocol {
|
|
|
- }
|
|
|
- /// Documentation for ServiceB
|
|
|
- ///
|
|
|
- /// Line 2
|
|
|
- @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
|
|
|
- public struct ServiceB_Client: ServiceB.ClientProtocol {
|
|
|
- private let client: GRPCCore.GRPCClient
|
|
|
-
|
|
|
- public init(wrapping client: GRPCCore.GRPCClient) {
|
|
|
- self.client = client
|
|
|
- }
|
|
|
- }
|
|
|
- """
|
|
|
-
|
|
|
- try self.assertClientCodeTranslation(
|
|
|
- codeGenerationRequest: makeCodeGenerationRequest(services: [serviceA, serviceB]),
|
|
|
- expectedSwift: expectedSwift,
|
|
|
- accessLevel: .public
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- private func assertClientCodeTranslation(
|
|
|
- codeGenerationRequest request: CodeGenerationRequest,
|
|
|
- expectedSwift: String,
|
|
|
- accessLevel: SourceGenerator.Config.AccessLevel,
|
|
|
- file: StaticString = #filePath,
|
|
|
- line: UInt = #line
|
|
|
- ) throws {
|
|
|
- let translator = ClientCodeTranslator()
|
|
|
- let codeBlocks = translator.translate(
|
|
|
- accessModifier: AccessModifier(accessLevel),
|
|
|
- services: request.services,
|
|
|
- serializer: request.lookupSerializer,
|
|
|
- deserializer: request.lookupDeserializer
|
|
|
- )
|
|
|
- let renderer = TextBasedRenderer.default
|
|
|
- renderer.renderCodeBlocks(codeBlocks)
|
|
|
- let contents = renderer.renderedContents()
|
|
|
- try XCTAssertEqualWithDiff(contents, expectedSwift, file: file, line: line)
|
|
|
+ private func render(
|
|
|
+ accessLevel: AccessModifier,
|
|
|
+ service: ServiceDescriptor
|
|
|
+ ) -> String {
|
|
|
+ let translator = ClientCodeTranslator()
|
|
|
+ let codeBlocks = translator.translate(accessModifier: accessLevel, services: [service]) {
|
|
|
+ "GRPCProtobuf.ProtobufSerializer<\($0)>()"
|
|
|
+ } deserializer: {
|
|
|
+ "GRPCProtobuf.ProtobufDeserializer<\($0)>()"
|
|
|
+ }
|
|
|
+ let renderer = TextBasedRenderer.default
|
|
|
+ renderer.renderCodeBlocks(codeBlocks)
|
|
|
+ return renderer.renderedContents()
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-#endif // os(macOS) || os(Linux)
|