ServerCodeTranslatorSnippetBasedTests.swift 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * Copyright 2023, 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 Testing
  17. @testable import GRPCCodeGen
  18. @Suite
  19. final class ServerCodeTranslatorSnippetBasedTests {
  20. @Test
  21. func translate() {
  22. let method = MethodDescriptor(
  23. documentation: "/// Documentation for unaryMethod",
  24. name: Name(base: "UnaryMethod", generatedUpperCase: "Unary", generatedLowerCase: "unary"),
  25. isInputStreaming: false,
  26. isOutputStreaming: false,
  27. inputType: "NamespaceA_ServiceARequest",
  28. outputType: "NamespaceA_ServiceAResponse"
  29. )
  30. let service = ServiceDescriptor(
  31. documentation: "/// Documentation for ServiceA",
  32. name: Name(
  33. base: "AlongNameForServiceA",
  34. generatedUpperCase: "ServiceA",
  35. generatedLowerCase: "serviceA"
  36. ),
  37. namespace: Name(
  38. base: "namespaceA",
  39. generatedUpperCase: "NamespaceA",
  40. generatedLowerCase: "namespaceA"
  41. ),
  42. methods: [method]
  43. )
  44. let expectedSwift = """
  45. extension NamespaceA_ServiceA {
  46. /// Streaming variant of the service protocol for the "namespaceA.AlongNameForServiceA" service.
  47. ///
  48. /// This protocol is the lowest-level of the service protocols generated for this service
  49. /// giving you the most flexibility over the implementation of your service. This comes at
  50. /// the cost of more verbose and less strict APIs. Each RPC requires you to implement it in
  51. /// terms of a request stream and response stream. Where only a single request or response
  52. /// message is expected, you are responsible for enforcing this invariant is maintained.
  53. ///
  54. /// Where possible, prefer using the stricter, less-verbose ``ServiceProtocol``
  55. /// or ``SimpleServiceProtocol`` instead.
  56. ///
  57. /// > Source IDL Documentation:
  58. /// >
  59. /// > Documentation for ServiceA
  60. public protocol StreamingServiceProtocol: GRPCCore.RegistrableRPCService {
  61. /// Handle the "UnaryMethod" method.
  62. ///
  63. /// > Source IDL Documentation:
  64. /// >
  65. /// > Documentation for unaryMethod
  66. ///
  67. /// - Parameters:
  68. /// - request: A streaming request of `NamespaceA_ServiceARequest` messages.
  69. /// - context: Context providing information about the RPC.
  70. /// - Throws: Any error which occurred during the processing of the request. Thrown errors
  71. /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted
  72. /// to an internal error.
  73. /// - Returns: A streaming response of `NamespaceA_ServiceAResponse` messages.
  74. func unary(
  75. request: GRPCCore.StreamingServerRequest<NamespaceA_ServiceARequest>,
  76. context: GRPCCore.ServerContext
  77. ) async throws -> GRPCCore.StreamingServerResponse<NamespaceA_ServiceAResponse>
  78. }
  79. /// Service protocol for the "namespaceA.AlongNameForServiceA" service.
  80. ///
  81. /// This protocol is higher level than ``StreamingServiceProtocol`` but lower level than
  82. /// the ``SimpleServiceProtocol``, it provides access to request and response metadata and
  83. /// trailing response metadata. If you don't need these then consider using
  84. /// the ``SimpleServiceProtocol``. If you need fine grained control over your RPCs then
  85. /// use ``StreamingServiceProtocol``.
  86. ///
  87. /// > Source IDL Documentation:
  88. /// >
  89. /// > Documentation for ServiceA
  90. public protocol ServiceProtocol: NamespaceA_ServiceA.StreamingServiceProtocol {
  91. /// Handle the "UnaryMethod" method.
  92. ///
  93. /// > Source IDL Documentation:
  94. /// >
  95. /// > Documentation for unaryMethod
  96. ///
  97. /// - Parameters:
  98. /// - request: A request containing a single `NamespaceA_ServiceARequest` message.
  99. /// - context: Context providing information about the RPC.
  100. /// - Throws: Any error which occurred during the processing of the request. Thrown errors
  101. /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted
  102. /// to an internal error.
  103. /// - Returns: A response containing a single `NamespaceA_ServiceAResponse` message.
  104. func unary(
  105. request: GRPCCore.ServerRequest<NamespaceA_ServiceARequest>,
  106. context: GRPCCore.ServerContext
  107. ) async throws -> GRPCCore.ServerResponse<NamespaceA_ServiceAResponse>
  108. }
  109. /// Simple service protocol for the "namespaceA.AlongNameForServiceA" service.
  110. ///
  111. /// This is the highest level protocol for the service. The API is the easiest to use but
  112. /// doesn't provide access to request or response metadata. If you need access to these
  113. /// then use ``ServiceProtocol`` instead.
  114. ///
  115. /// > Source IDL Documentation:
  116. /// >
  117. /// > Documentation for ServiceA
  118. public protocol SimpleServiceProtocol: NamespaceA_ServiceA.ServiceProtocol {
  119. /// Handle the "UnaryMethod" method.
  120. ///
  121. /// > Source IDL Documentation:
  122. /// >
  123. /// > Documentation for unaryMethod
  124. ///
  125. /// - Parameters:
  126. /// - request: A `NamespaceA_ServiceARequest` message.
  127. /// - context: Context providing information about the RPC.
  128. /// - Throws: Any error which occurred during the processing of the request. Thrown errors
  129. /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted
  130. /// to an internal error.
  131. /// - Returns: A `NamespaceA_ServiceAResponse` to respond with.
  132. func unary(
  133. request: NamespaceA_ServiceARequest,
  134. context: GRPCCore.ServerContext
  135. ) async throws -> NamespaceA_ServiceAResponse
  136. }
  137. }
  138. // Default implementation of 'registerMethods(with:)'.
  139. extension NamespaceA_ServiceA.StreamingServiceProtocol {
  140. public func registerMethods(with router: inout GRPCCore.RPCRouter) {
  141. router.registerHandler(
  142. forMethod: NamespaceA_ServiceA.Method.Unary.descriptor,
  143. deserializer: GRPCProtobuf.ProtobufDeserializer<NamespaceA_ServiceARequest>(),
  144. serializer: GRPCProtobuf.ProtobufSerializer<NamespaceA_ServiceAResponse>(),
  145. handler: { request, context in
  146. try await self.unary(
  147. request: request,
  148. context: context
  149. )
  150. }
  151. )
  152. }
  153. }
  154. // Default implementation of streaming methods from 'StreamingServiceProtocol'.
  155. extension NamespaceA_ServiceA.ServiceProtocol {
  156. public func unary(
  157. request: GRPCCore.StreamingServerRequest<NamespaceA_ServiceARequest>,
  158. context: GRPCCore.ServerContext
  159. ) async throws -> GRPCCore.StreamingServerResponse<NamespaceA_ServiceAResponse> {
  160. let response = try await self.unary(
  161. request: GRPCCore.ServerRequest(stream: request),
  162. context: context
  163. )
  164. return GRPCCore.StreamingServerResponse(single: response)
  165. }
  166. }
  167. // Default implementation of methods from 'ServiceProtocol'.
  168. extension NamespaceA_ServiceA.SimpleServiceProtocol {
  169. public func unary(
  170. request: GRPCCore.ServerRequest<NamespaceA_ServiceARequest>,
  171. context: GRPCCore.ServerContext
  172. ) async throws -> GRPCCore.ServerResponse<NamespaceA_ServiceAResponse> {
  173. return GRPCCore.ServerResponse<NamespaceA_ServiceAResponse>(
  174. message: try await self.unary(
  175. request: request.message,
  176. context: context
  177. ),
  178. metadata: [:]
  179. )
  180. }
  181. }
  182. """
  183. let rendered = self.render(accessLevel: .public, service: service)
  184. #expect(rendered == expectedSwift)
  185. }
  186. private func render(
  187. accessLevel: AccessModifier,
  188. service: ServiceDescriptor
  189. ) -> String {
  190. let translator = ServerCodeTranslator()
  191. let codeBlocks = translator.translate(accessModifier: accessLevel, service: service) {
  192. "GRPCProtobuf.ProtobufSerializer<\($0)>()"
  193. } deserializer: {
  194. "GRPCProtobuf.ProtobufDeserializer<\($0)>()"
  195. }
  196. let renderer = TextBasedRenderer.default
  197. renderer.renderCodeBlocks(codeBlocks)
  198. return renderer.renderedContents()
  199. }
  200. }