From d39ccedc199618cff24178d4a5e3cde21a220867 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Mon, 19 Aug 2019 14:04:29 +0100 Subject: [PATCH] Split the Echo example into model, implementation and runtime Motivation: The generated code and implementation for the Echo example is used as part of the example and as well as in the test suite. To make the example more obvious we should split it into its constituent parts: the model (i.e. the definition and generated code), the implementation (of the server), and the runtime (CLI for client and server). Modifications: - Split the Echo example into three modules: `EchoModel` (generated code), `EchoImplementation` (server implementation), and `EchoRuntime` (CLI for client and server). - Update the `Makefile` to target the updated paths - Add missing imports in tests - Make the generated code `public` (instead of `internal`) since we're no longer symlinking into the same module for tests Result: - No more symlinks for Echo - Structure of example is more straightforward --- Makefile | 17 +++++---- Package.swift | 31 ++++++++++++++-- .../{ => Implementation}/EchoProvider.swift | 13 ++++--- Sources/Examples/Echo/Makefile | 11 ------ .../{ => Model}/Generated/echo.grpc.swift | 26 +++++++------- .../Echo/{ => Model}/Generated/echo.pb.swift | 36 +++++++++---------- Sources/Examples/Echo/{ => Model}/echo.proto | 0 Sources/Examples/Echo/README.md | 14 +++++--- Sources/Examples/Echo/RUNME | 7 ---- .../Examples/Echo/{ => Runtime}/main.swift | 2 ++ .../GRPCPerformanceTests/EchoProvider.swift | 1 - .../Generated/echo.grpc.swift | 1 - .../Generated/echo.pb.swift | 1 - Sources/GRPCPerformanceTests/main.swift | 2 ++ Tests/GRPCTests/EchoProvider.swift | 1 - Tests/GRPCTests/echo.grpc.swift | 1 - Tests/GRPCTests/echo.pb.swift | 1 - 17 files changed, 91 insertions(+), 74 deletions(-) rename Sources/Examples/Echo/{ => Implementation}/EchoProvider.swift (78%) delete mode 100644 Sources/Examples/Echo/Makefile rename Sources/Examples/Echo/{ => Model}/Generated/echo.grpc.swift (82%) rename Sources/Examples/Echo/{ => Model}/Generated/echo.pb.swift (75%) rename Sources/Examples/Echo/{ => Model}/echo.proto (100%) delete mode 100755 Sources/Examples/Echo/RUNME rename Sources/Examples/Echo/{ => Runtime}/main.swift (99%) delete mode 120000 Sources/GRPCPerformanceTests/EchoProvider.swift delete mode 120000 Sources/GRPCPerformanceTests/Generated/echo.grpc.swift delete mode 120000 Sources/GRPCPerformanceTests/Generated/echo.pb.swift delete mode 120000 Tests/GRPCTests/EchoProvider.swift delete mode 120000 Tests/GRPCTests/echo.grpc.swift delete mode 120000 Tests/GRPCTests/echo.pb.swift diff --git a/Makefile b/Makefile index 5071986c4..fa44bbcdd 100644 --- a/Makefile +++ b/Makefile @@ -48,12 +48,14 @@ generate-linuxmain: # Generates protobufs and gRPC client and server for the Echo example generate-echo: plugins - protoc Sources/Examples/Echo/echo.proto \ - --proto_path=Sources/Examples/Echo \ + protoc Sources/Examples/Echo/Model/echo.proto \ + --proto_path=Sources/Examples/Echo/Model \ --plugin=${SWIFT_BUILD_PATH}/${SWIFT_BUILD_CONFIGURATION}/protoc-gen-swift \ --plugin=${SWIFT_BUILD_PATH}/${SWIFT_BUILD_CONFIGURATION}/protoc-gen-swiftgrpc \ - --swift_out=Sources/Examples/Echo/Generated \ - --swiftgrpc_out=Sources/Examples/Echo/Generated + --swift_opt=Visibility=Public \ + --swift_out=Sources/Examples/Echo/Model/Generated \ + --swiftgrpc_opt=Visibility=Public \ + --swiftgrpc_out=Sources/Examples/Echo/Model/Generated ### Testing #################################################################### @@ -68,12 +70,13 @@ test-generate-linuxmain: generate-linuxmain # Generates code for the Echo server and client and tests them against 'golden' data. test-plugin: plugins - protoc Sources/Examples/Echo/echo.proto \ - --proto_path=Sources/Examples/Echo \ + protoc Sources/Examples/Echo/Model/echo.proto \ + --proto_path=Sources/Examples/Echo/Model \ --plugin=${SWIFT_BUILD_PATH}/${SWIFT_BUILD_CONFIGURATION}/protoc-gen-swift \ --plugin=${SWIFT_BUILD_PATH}/${SWIFT_BUILD_CONFIGURATION}/protoc-gen-swiftgrpc \ + --swiftgrpc_opt=Visibility=Public \ --swiftgrpc_out=/tmp - diff -u /tmp/echo.grpc.swift Sources/Examples/Echo/Generated/echo.grpc.swift + diff -u /tmp/echo.grpc.swift Sources/Examples/Echo/Model/Generated/echo.grpc.swift ### Misc. ###################################################################### diff --git a/Package.swift b/Package.swift index d73087e5c..22685639c 100644 --- a/Package.swift +++ b/Package.swift @@ -125,6 +125,8 @@ let package = Package( name: "GRPCPerformanceTests", dependencies: [ "GRPC", + "EchoModel", + "EchoImplementation", "NIO", "NIOSSL", "Commander", @@ -137,16 +139,41 @@ let package = Package( dependencies: ["NIOSSL"] ), - // Echo example. + // Echo example CLI. .target( name: "Echo", dependencies: [ + "EchoModel", + "EchoImplementation", "GRPC", "GRPCSampleData", "SwiftProtobuf", "Commander" ], - path: "Sources/Examples/Echo" + path: "Sources/Examples/Echo/Runtime" + ), + + // Echo example service implementation. + .target( + name: "EchoImplementation", + dependencies: [ + "EchoModel", + "GRPC", + "SwiftProtobuf" + ], + path: "Sources/Examples/Echo/Implementation" + ), + + // Model for Echo example. + .target( + name: "EchoModel", + dependencies: [ + "GRPC", + "NIO", + "NIOHTTP1", + "SwiftProtobuf" + ], + path: "Sources/Examples/Echo/Model" ), ] ) diff --git a/Sources/Examples/Echo/EchoProvider.swift b/Sources/Examples/Echo/Implementation/EchoProvider.swift similarity index 78% rename from Sources/Examples/Echo/EchoProvider.swift rename to Sources/Examples/Echo/Implementation/EchoProvider.swift index 8b7543869..ce918c1c2 100644 --- a/Sources/Examples/Echo/EchoProvider.swift +++ b/Sources/Examples/Echo/Implementation/EchoProvider.swift @@ -16,15 +16,18 @@ import Foundation import NIO import GRPC +import EchoModel -class EchoProvider: Echo_EchoProvider { - func get(request: Echo_EchoRequest, context: StatusOnlyCallContext) -> EventLoopFuture { +public class EchoProvider: Echo_EchoProvider { + public init() {} + + public func get(request: Echo_EchoRequest, context: StatusOnlyCallContext) -> EventLoopFuture { var response = Echo_EchoResponse() response.text = "Swift echo get: " + request.text return context.eventLoop.makeSucceededFuture(response) } - func expand(request: Echo_EchoRequest, context: StreamingResponseCallContext) -> EventLoopFuture { + public func expand(request: Echo_EchoRequest, context: StreamingResponseCallContext) -> EventLoopFuture { var endOfSendOperationQueue = context.eventLoop.makeSucceededFuture(()) let parts = request.text.components(separatedBy: " ") for (i, part) in parts.enumerated() { @@ -35,7 +38,7 @@ class EchoProvider: Echo_EchoProvider { return endOfSendOperationQueue.map { GRPCStatus.ok } } - func collect(context: UnaryResponseCallContext) -> EventLoopFuture<(StreamEvent) -> Void> { + public func collect(context: UnaryResponseCallContext) -> EventLoopFuture<(StreamEvent) -> Void> { var parts: [String] = [] return context.eventLoop.makeSucceededFuture({ event in switch event { @@ -50,7 +53,7 @@ class EchoProvider: Echo_EchoProvider { }) } - func update(context: StreamingResponseCallContext) -> EventLoopFuture<(StreamEvent) -> Void> { + public func update(context: StreamingResponseCallContext) -> EventLoopFuture<(StreamEvent) -> Void> { var endOfSendOperationQueue = context.eventLoop.makeSucceededFuture(()) var count = 0 return context.eventLoop.makeSucceededFuture({ event in diff --git a/Sources/Examples/Echo/Makefile b/Sources/Examples/Echo/Makefile deleted file mode 100644 index 6d18c4f0b..000000000 --- a/Sources/Examples/Echo/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: - swift build -c debug --product EchoNIO - cp .build/debug/EchoNIO . - -project: - swift package generate-xcodeproj - -clean : - rm -rf Packages googleapis .build - rm -f Package.pins Echo google.json - rm -rf Package.resolved EchoNIO.xcodeproj EchoNIO diff --git a/Sources/Examples/Echo/Generated/echo.grpc.swift b/Sources/Examples/Echo/Model/Generated/echo.grpc.swift similarity index 82% rename from Sources/Examples/Echo/Generated/echo.grpc.swift rename to Sources/Examples/Echo/Model/Generated/echo.grpc.swift index dc86bae20..2d79a6998 100644 --- a/Sources/Examples/Echo/Generated/echo.grpc.swift +++ b/Sources/Examples/Echo/Model/Generated/echo.grpc.swift @@ -28,24 +28,24 @@ import SwiftProtobuf /// Usage: instantiate Echo_EchoServiceClient, then call methods of this protocol to make API calls. -internal protocol Echo_EchoService { +public protocol Echo_EchoService { func get(_ request: Echo_EchoRequest, callOptions: CallOptions?) -> UnaryCall func expand(_ request: Echo_EchoRequest, callOptions: CallOptions?, handler: @escaping (Echo_EchoResponse) -> Void) -> ServerStreamingCall func collect(callOptions: CallOptions?) -> ClientStreamingCall func update(callOptions: CallOptions?, handler: @escaping (Echo_EchoResponse) -> Void) -> BidirectionalStreamingCall } -internal final class Echo_EchoServiceClient: GRPCServiceClient, Echo_EchoService { - internal let connection: ClientConnection - internal var serviceName: String { return "echo.Echo" } - internal var defaultCallOptions: CallOptions +public final class Echo_EchoServiceClient: GRPCServiceClient, Echo_EchoService { + public let connection: ClientConnection + public var serviceName: String { return "echo.Echo" } + public var defaultCallOptions: CallOptions /// Creates a client for the echo.Echo service. /// /// - Parameters: /// - connection: `ClientConnection` to the service host. /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. - internal init(connection: ClientConnection, defaultCallOptions: CallOptions = CallOptions()) { + public init(connection: ClientConnection, defaultCallOptions: CallOptions = CallOptions()) { self.connection = connection self.defaultCallOptions = defaultCallOptions } @@ -56,7 +56,7 @@ internal final class Echo_EchoServiceClient: GRPCServiceClient, Echo_EchoService /// - request: Request to send to Get. /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. /// - Returns: A `UnaryCall` with futures for the metadata, status and response. - internal func get(_ request: Echo_EchoRequest, callOptions: CallOptions? = nil) -> UnaryCall { + public func get(_ request: Echo_EchoRequest, callOptions: CallOptions? = nil) -> UnaryCall { return self.makeUnaryCall(path: self.path(forMethod: "Get"), request: request, callOptions: callOptions ?? self.defaultCallOptions) @@ -69,7 +69,7 @@ internal final class Echo_EchoServiceClient: GRPCServiceClient, Echo_EchoService /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. /// - handler: A closure called when each response is received from the server. /// - Returns: A `ServerStreamingCall` with futures for the metadata and status. - internal func expand(_ request: Echo_EchoRequest, callOptions: CallOptions? = nil, handler: @escaping (Echo_EchoResponse) -> Void) -> ServerStreamingCall { + public func expand(_ request: Echo_EchoRequest, callOptions: CallOptions? = nil, handler: @escaping (Echo_EchoResponse) -> Void) -> ServerStreamingCall { return self.makeServerStreamingCall(path: self.path(forMethod: "Expand"), request: request, callOptions: callOptions ?? self.defaultCallOptions, @@ -84,7 +84,7 @@ internal final class Echo_EchoServiceClient: GRPCServiceClient, Echo_EchoService /// - Parameters: /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. /// - Returns: A `ClientStreamingCall` with futures for the metadata, status and response. - internal func collect(callOptions: CallOptions? = nil) -> ClientStreamingCall { + public func collect(callOptions: CallOptions? = nil) -> ClientStreamingCall { return self.makeClientStreamingCall(path: self.path(forMethod: "Collect"), callOptions: callOptions ?? self.defaultCallOptions) } @@ -98,7 +98,7 @@ internal final class Echo_EchoServiceClient: GRPCServiceClient, Echo_EchoService /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. /// - handler: A closure called when each response is received from the server. /// - Returns: A `ClientStreamingCall` with futures for the metadata and status. - internal func update(callOptions: CallOptions? = nil, handler: @escaping (Echo_EchoResponse) -> Void) -> BidirectionalStreamingCall { + public func update(callOptions: CallOptions? = nil, handler: @escaping (Echo_EchoResponse) -> Void) -> BidirectionalStreamingCall { return self.makeBidirectionalStreamingCall(path: self.path(forMethod: "Update"), callOptions: callOptions ?? self.defaultCallOptions, handler: handler) @@ -107,7 +107,7 @@ internal final class Echo_EchoServiceClient: GRPCServiceClient, Echo_EchoService } /// To build a server, implement a class that conforms to this protocol. -internal protocol Echo_EchoProvider: CallHandlerProvider { +public protocol Echo_EchoProvider: CallHandlerProvider { func get(request: Echo_EchoRequest, context: StatusOnlyCallContext) -> EventLoopFuture func expand(request: Echo_EchoRequest, context: StreamingResponseCallContext) -> EventLoopFuture func collect(context: UnaryResponseCallContext) -> EventLoopFuture<(StreamEvent) -> Void> @@ -115,11 +115,11 @@ internal protocol Echo_EchoProvider: CallHandlerProvider { } extension Echo_EchoProvider { - internal var serviceName: String { return "echo.Echo" } + public var serviceName: String { return "echo.Echo" } /// Determines, calls and returns the appropriate request handler, depending on the request's method. /// Returns nil for methods not handled by this service. - internal func handleMethod(_ methodName: String, callHandlerContext: CallHandlerContext) -> GRPCCallHandler? { + public func handleMethod(_ methodName: String, callHandlerContext: CallHandlerContext) -> GRPCCallHandler? { switch methodName { case "Get": return UnaryCallHandler(callHandlerContext: callHandlerContext) { context in diff --git a/Sources/Examples/Echo/Generated/echo.pb.swift b/Sources/Examples/Echo/Model/Generated/echo.pb.swift similarity index 75% rename from Sources/Examples/Echo/Generated/echo.pb.swift rename to Sources/Examples/Echo/Model/Generated/echo.pb.swift index 54afebc3a..733d45b23 100644 --- a/Sources/Examples/Echo/Generated/echo.pb.swift +++ b/Sources/Examples/Echo/Model/Generated/echo.pb.swift @@ -33,30 +33,30 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP typealias Version = _2 } -struct Echo_EchoRequest { +public struct Echo_EchoRequest { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. /// The text of a message to be echoed. - var text: String = String() + public var text: String = String() - var unknownFields = SwiftProtobuf.UnknownStorage() + public var unknownFields = SwiftProtobuf.UnknownStorage() - init() {} + public init() {} } -struct Echo_EchoResponse { +public struct Echo_EchoResponse { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. /// The text of an echo response. - var text: String = String() + public var text: String = String() - var unknownFields = SwiftProtobuf.UnknownStorage() + public var unknownFields = SwiftProtobuf.UnknownStorage() - init() {} + public init() {} } // MARK: - Code below here is support for the SwiftProtobuf runtime. @@ -64,12 +64,12 @@ struct Echo_EchoResponse { fileprivate let _protobuf_package = "echo" extension Echo_EchoRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - static let protoMessageName: String = _protobuf_package + ".EchoRequest" - static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + public static let protoMessageName: String = _protobuf_package + ".EchoRequest" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 1: .same(proto: "text"), ] - mutating func decodeMessage(decoder: inout D) throws { + public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { switch fieldNumber { case 1: try decoder.decodeSingularStringField(value: &self.text) @@ -78,14 +78,14 @@ extension Echo_EchoRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImpleme } } - func traverse(visitor: inout V) throws { + public func traverse(visitor: inout V) throws { if !self.text.isEmpty { try visitor.visitSingularStringField(value: self.text, fieldNumber: 1) } try unknownFields.traverse(visitor: &visitor) } - static func ==(lhs: Echo_EchoRequest, rhs: Echo_EchoRequest) -> Bool { + public static func ==(lhs: Echo_EchoRequest, rhs: Echo_EchoRequest) -> Bool { if lhs.text != rhs.text {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true @@ -93,12 +93,12 @@ extension Echo_EchoRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImpleme } extension Echo_EchoResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - static let protoMessageName: String = _protobuf_package + ".EchoResponse" - static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + public static let protoMessageName: String = _protobuf_package + ".EchoResponse" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 1: .same(proto: "text"), ] - mutating func decodeMessage(decoder: inout D) throws { + public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { switch fieldNumber { case 1: try decoder.decodeSingularStringField(value: &self.text) @@ -107,14 +107,14 @@ extension Echo_EchoResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem } } - func traverse(visitor: inout V) throws { + public func traverse(visitor: inout V) throws { if !self.text.isEmpty { try visitor.visitSingularStringField(value: self.text, fieldNumber: 1) } try unknownFields.traverse(visitor: &visitor) } - static func ==(lhs: Echo_EchoResponse, rhs: Echo_EchoResponse) -> Bool { + public static func ==(lhs: Echo_EchoResponse, rhs: Echo_EchoResponse) -> Bool { if lhs.text != rhs.text {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true diff --git a/Sources/Examples/Echo/echo.proto b/Sources/Examples/Echo/Model/echo.proto similarity index 100% rename from Sources/Examples/Echo/echo.proto rename to Sources/Examples/Echo/Model/echo.proto diff --git a/Sources/Examples/Echo/README.md b/Sources/Examples/Echo/README.md index c5a922a4e..b1a683c36 100644 --- a/Sources/Examples/Echo/README.md +++ b/Sources/Examples/Echo/README.md @@ -1,6 +1,10 @@ -# EchoNIO, a gRPC NIO Sample App +# Echo, a gRPC Sample App -This directory contains a simple echo server that demonstrates -all four gRPC API styles (Unary, Server Streaming, Client -Streaming, and Bidirectional Streaming) using the NIO based -Swift gRPC implementation. +This directory contains a simple echo server that demonstrates all four gRPC API +styles (Unary, Server Streaming, Client Streaming, and Bidirectional Streaming) +using the gRPC Swift. + +There are three subdirectories: +* `Model` containing the service and model definitions and generated code, +* `Implementation` containing the server implementation of the generated model, +* `Runtime` containing a CLI for the server and client. diff --git a/Sources/Examples/Echo/RUNME b/Sources/Examples/Echo/RUNME deleted file mode 100755 index e0ec8e437..000000000 --- a/Sources/Examples/Echo/RUNME +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -# -# Use this to run the swift-proto generator -# -protoc echo.proto \ - --swift_out=Generated \ - --swiftgrpc_out=Client=true,Server=true:Generated diff --git a/Sources/Examples/Echo/main.swift b/Sources/Examples/Echo/Runtime/main.swift similarity index 99% rename from Sources/Examples/Echo/main.swift rename to Sources/Examples/Echo/Runtime/main.swift index 4a78592be..0a323d16e 100644 --- a/Sources/Examples/Echo/main.swift +++ b/Sources/Examples/Echo/Runtime/main.swift @@ -20,6 +20,8 @@ import NIO import NIOSSL import GRPC import GRPCSampleData +import EchoImplementation +import EchoModel // Common flags and options let sslFlag = Flag("ssl", description: "if true, use SSL for connections") diff --git a/Sources/GRPCPerformanceTests/EchoProvider.swift b/Sources/GRPCPerformanceTests/EchoProvider.swift deleted file mode 120000 index c9403f74a..000000000 --- a/Sources/GRPCPerformanceTests/EchoProvider.swift +++ /dev/null @@ -1 +0,0 @@ -../Examples/Echo/EchoProvider.swift \ No newline at end of file diff --git a/Sources/GRPCPerformanceTests/Generated/echo.grpc.swift b/Sources/GRPCPerformanceTests/Generated/echo.grpc.swift deleted file mode 120000 index 424e75bf4..000000000 --- a/Sources/GRPCPerformanceTests/Generated/echo.grpc.swift +++ /dev/null @@ -1 +0,0 @@ -../../Examples/Echo/Generated/echo.grpc.swift \ No newline at end of file diff --git a/Sources/GRPCPerformanceTests/Generated/echo.pb.swift b/Sources/GRPCPerformanceTests/Generated/echo.pb.swift deleted file mode 120000 index e209c06ca..000000000 --- a/Sources/GRPCPerformanceTests/Generated/echo.pb.swift +++ /dev/null @@ -1 +0,0 @@ -../../Examples/Echo/Generated/echo.pb.swift \ No newline at end of file diff --git a/Sources/GRPCPerformanceTests/main.swift b/Sources/GRPCPerformanceTests/main.swift index 07594cc45..30eb03b65 100644 --- a/Sources/GRPCPerformanceTests/main.swift +++ b/Sources/GRPCPerformanceTests/main.swift @@ -18,6 +18,8 @@ import GRPC import NIO import NIOSSL import Commander +import EchoImplementation +import EchoModel struct ConnectionFactory { var configuration: ClientConnection.Configuration diff --git a/Tests/GRPCTests/EchoProvider.swift b/Tests/GRPCTests/EchoProvider.swift deleted file mode 120000 index 7d14bfe94..000000000 --- a/Tests/GRPCTests/EchoProvider.swift +++ /dev/null @@ -1 +0,0 @@ -../../Sources/Examples/Echo/EchoProvider.swift \ No newline at end of file diff --git a/Tests/GRPCTests/echo.grpc.swift b/Tests/GRPCTests/echo.grpc.swift deleted file mode 120000 index 9fef35792..000000000 --- a/Tests/GRPCTests/echo.grpc.swift +++ /dev/null @@ -1 +0,0 @@ -../../Sources/Examples/Echo/Generated/echo.grpc.swift \ No newline at end of file diff --git a/Tests/GRPCTests/echo.pb.swift b/Tests/GRPCTests/echo.pb.swift deleted file mode 120000 index 9dbe28075..000000000 --- a/Tests/GRPCTests/echo.pb.swift +++ /dev/null @@ -1 +0,0 @@ -../../Sources/Examples/Echo/Generated/echo.pb.swift \ No newline at end of file