ServerCodeTranslatorSnippetBasedTests.swift 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  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. #if os(macOS) || os(Linux) // swift-format doesn't like canImport(Foundation.Process)
  17. import XCTest
  18. @testable import GRPCCodeGen
  19. final class ServerCodeTranslatorSnippetBasedTests: XCTestCase {
  20. typealias MethodDescriptor = GRPCCodeGen.CodeGenerationRequest.ServiceDescriptor.MethodDescriptor
  21. typealias ServiceDescriptor = GRPCCodeGen.CodeGenerationRequest.ServiceDescriptor
  22. typealias Name = GRPCCodeGen.CodeGenerationRequest.Name
  23. func testServerCodeTranslatorUnaryMethod() throws {
  24. let method = MethodDescriptor(
  25. documentation: "/// Documentation for unaryMethod",
  26. name: Name(base: "UnaryMethod", generatedUpperCase: "Unary", generatedLowerCase: "unary"),
  27. isInputStreaming: false,
  28. isOutputStreaming: false,
  29. inputType: "NamespaceA_ServiceARequest",
  30. outputType: "NamespaceA_ServiceAResponse"
  31. )
  32. let service = ServiceDescriptor(
  33. documentation: "/// Documentation for ServiceA",
  34. name: Name(
  35. base: "AlongNameForServiceA",
  36. generatedUpperCase: "ServiceA",
  37. generatedLowerCase: "serviceA"
  38. ),
  39. namespace: Name(
  40. base: "namespaceA",
  41. generatedUpperCase: "NamespaceA",
  42. generatedLowerCase: "namespaceA"
  43. ),
  44. methods: [method]
  45. )
  46. let expectedSwift =
  47. """
  48. /// Documentation for ServiceA
  49. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  50. public protocol NamespaceA_ServiceAStreamingServiceProtocol: GRPCCore.RegistrableRPCService {
  51. /// Documentation for unaryMethod
  52. func unary(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.Unary.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.Unary.Output>
  53. }
  54. /// Conformance to `GRPCCore.RegistrableRPCService`.
  55. extension NamespaceA.ServiceA.StreamingServiceProtocol {
  56. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  57. public func registerMethods(with router: inout GRPCCore.RPCRouter) {
  58. router.registerHandler(
  59. forMethod: NamespaceA.ServiceA.Method.Unary.descriptor,
  60. deserializer: ProtobufDeserializer<NamespaceA.ServiceA.Method.Unary.Input>(),
  61. serializer: ProtobufSerializer<NamespaceA.ServiceA.Method.Unary.Output>(),
  62. handler: { request in
  63. try await self.unary(request: request)
  64. }
  65. )
  66. }
  67. }
  68. /// Documentation for ServiceA
  69. public protocol NamespaceA_ServiceAServiceProtocol: NamespaceA.ServiceA.StreamingServiceProtocol {
  70. /// Documentation for unaryMethod
  71. func unary(request: ServerRequest.Single<NamespaceA.ServiceA.Method.Unary.Input>) async throws -> ServerResponse.Single<NamespaceA.ServiceA.Method.Unary.Output>
  72. }
  73. /// Partial conformance to `NamespaceA_ServiceAStreamingServiceProtocol`.
  74. extension NamespaceA.ServiceA.ServiceProtocol {
  75. public func unary(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.Unary.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.Unary.Output> {
  76. let response = try await self.unary(request: ServerRequest.Single(stream: request))
  77. return ServerResponse.Stream(single: response)
  78. }
  79. }
  80. """
  81. try self.assertServerCodeTranslation(
  82. codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
  83. expectedSwift: expectedSwift,
  84. accessLevel: .public
  85. )
  86. }
  87. func testServerCodeTranslatorInputStreamingMethod() throws {
  88. let method = MethodDescriptor(
  89. documentation: "/// Documentation for inputStreamingMethod",
  90. name: Name(
  91. base: "InputStreamingMethod",
  92. generatedUpperCase: "InputStreaming",
  93. generatedLowerCase: "inputStreaming"
  94. ),
  95. isInputStreaming: true,
  96. isOutputStreaming: false,
  97. inputType: "NamespaceA_ServiceARequest",
  98. outputType: "NamespaceA_ServiceAResponse"
  99. )
  100. let service = ServiceDescriptor(
  101. documentation: "/// Documentation for ServiceA",
  102. name: Name(base: "ServiceA", generatedUpperCase: "ServiceA", generatedLowerCase: "serviceA"),
  103. namespace: Name(
  104. base: "namespaceA",
  105. generatedUpperCase: "NamespaceA",
  106. generatedLowerCase: "namespaceA"
  107. ),
  108. methods: [method]
  109. )
  110. let expectedSwift =
  111. """
  112. /// Documentation for ServiceA
  113. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  114. package protocol NamespaceA_ServiceAStreamingServiceProtocol: GRPCCore.RegistrableRPCService {
  115. /// Documentation for inputStreamingMethod
  116. func inputStreaming(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.InputStreaming.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.InputStreaming.Output>
  117. }
  118. /// Conformance to `GRPCCore.RegistrableRPCService`.
  119. extension NamespaceA.ServiceA.StreamingServiceProtocol {
  120. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  121. package func registerMethods(with router: inout GRPCCore.RPCRouter) {
  122. router.registerHandler(
  123. forMethod: NamespaceA.ServiceA.Method.InputStreaming.descriptor,
  124. deserializer: ProtobufDeserializer<NamespaceA.ServiceA.Method.InputStreaming.Input>(),
  125. serializer: ProtobufSerializer<NamespaceA.ServiceA.Method.InputStreaming.Output>(),
  126. handler: { request in
  127. try await self.inputStreaming(request: request)
  128. }
  129. )
  130. }
  131. }
  132. /// Documentation for ServiceA
  133. package protocol NamespaceA_ServiceAServiceProtocol: NamespaceA.ServiceA.StreamingServiceProtocol {
  134. /// Documentation for inputStreamingMethod
  135. func inputStreaming(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.InputStreaming.Input>) async throws -> ServerResponse.Single<NamespaceA.ServiceA.Method.InputStreaming.Output>
  136. }
  137. /// Partial conformance to `NamespaceA_ServiceAStreamingServiceProtocol`.
  138. extension NamespaceA.ServiceA.ServiceProtocol {
  139. package func inputStreaming(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.InputStreaming.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.InputStreaming.Output> {
  140. let response = try await self.inputStreaming(request: request)
  141. return ServerResponse.Stream(single: response)
  142. }
  143. }
  144. """
  145. try self.assertServerCodeTranslation(
  146. codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
  147. expectedSwift: expectedSwift,
  148. accessLevel: .package
  149. )
  150. }
  151. func testServerCodeTranslatorOutputStreamingMethod() throws {
  152. let method = MethodDescriptor(
  153. documentation: "/// Documentation for outputStreamingMethod",
  154. name: Name(
  155. base: "OutputStreamingMethod",
  156. generatedUpperCase: "OutputStreaming",
  157. generatedLowerCase: "outputStreaming"
  158. ),
  159. isInputStreaming: false,
  160. isOutputStreaming: true,
  161. inputType: "NamespaceA_ServiceARequest",
  162. outputType: "NamespaceA_ServiceAResponse"
  163. )
  164. let service = ServiceDescriptor(
  165. documentation: "/// Documentation for ServiceA",
  166. name: Name(
  167. base: "ServiceATest",
  168. generatedUpperCase: "ServiceA",
  169. generatedLowerCase: "serviceA"
  170. ),
  171. namespace: Name(
  172. base: "namespaceA",
  173. generatedUpperCase: "NamespaceA",
  174. generatedLowerCase: "namespaceA"
  175. ),
  176. methods: [method]
  177. )
  178. let expectedSwift =
  179. """
  180. /// Documentation for ServiceA
  181. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  182. public protocol NamespaceA_ServiceAStreamingServiceProtocol: GRPCCore.RegistrableRPCService {
  183. /// Documentation for outputStreamingMethod
  184. func outputStreaming(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.OutputStreaming.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.OutputStreaming.Output>
  185. }
  186. /// Conformance to `GRPCCore.RegistrableRPCService`.
  187. extension NamespaceA.ServiceA.StreamingServiceProtocol {
  188. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  189. public func registerMethods(with router: inout GRPCCore.RPCRouter) {
  190. router.registerHandler(
  191. forMethod: NamespaceA.ServiceA.Method.OutputStreaming.descriptor,
  192. deserializer: ProtobufDeserializer<NamespaceA.ServiceA.Method.OutputStreaming.Input>(),
  193. serializer: ProtobufSerializer<NamespaceA.ServiceA.Method.OutputStreaming.Output>(),
  194. handler: { request in
  195. try await self.outputStreaming(request: request)
  196. }
  197. )
  198. }
  199. }
  200. /// Documentation for ServiceA
  201. public protocol NamespaceA_ServiceAServiceProtocol: NamespaceA.ServiceA.StreamingServiceProtocol {
  202. /// Documentation for outputStreamingMethod
  203. func outputStreaming(request: ServerRequest.Single<NamespaceA.ServiceA.Method.OutputStreaming.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.OutputStreaming.Output>
  204. }
  205. /// Partial conformance to `NamespaceA_ServiceAStreamingServiceProtocol`.
  206. extension NamespaceA.ServiceA.ServiceProtocol {
  207. public func outputStreaming(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.OutputStreaming.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.OutputStreaming.Output> {
  208. let response = try await self.outputStreaming(request: ServerRequest.Single(stream: request))
  209. return response
  210. }
  211. }
  212. """
  213. try self.assertServerCodeTranslation(
  214. codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
  215. expectedSwift: expectedSwift,
  216. accessLevel: .public
  217. )
  218. }
  219. func testServerCodeTranslatorBidirectionalStreamingMethod() throws {
  220. let method = MethodDescriptor(
  221. documentation: "/// Documentation for bidirectionalStreamingMethod",
  222. name: Name(
  223. base: "BidirectionalStreamingMethod",
  224. generatedUpperCase: "BidirectionalStreaming",
  225. generatedLowerCase: "bidirectionalStreaming"
  226. ),
  227. isInputStreaming: true,
  228. isOutputStreaming: true,
  229. inputType: "NamespaceA_ServiceARequest",
  230. outputType: "NamespaceA_ServiceAResponse"
  231. )
  232. let service = ServiceDescriptor(
  233. documentation: "/// Documentation for ServiceA",
  234. name: Name(
  235. base: "ServiceATest",
  236. generatedUpperCase: "ServiceA",
  237. generatedLowerCase: "serviceA"
  238. ),
  239. namespace: Name(
  240. base: "namespaceA",
  241. generatedUpperCase: "NamespaceA",
  242. generatedLowerCase: "namespaceA"
  243. ),
  244. methods: [method]
  245. )
  246. let expectedSwift =
  247. """
  248. /// Documentation for ServiceA
  249. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  250. package protocol NamespaceA_ServiceAStreamingServiceProtocol: GRPCCore.RegistrableRPCService {
  251. /// Documentation for bidirectionalStreamingMethod
  252. func bidirectionalStreaming(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.BidirectionalStreaming.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.BidirectionalStreaming.Output>
  253. }
  254. /// Conformance to `GRPCCore.RegistrableRPCService`.
  255. extension NamespaceA.ServiceA.StreamingServiceProtocol {
  256. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  257. package func registerMethods(with router: inout GRPCCore.RPCRouter) {
  258. router.registerHandler(
  259. forMethod: NamespaceA.ServiceA.Method.BidirectionalStreaming.descriptor,
  260. deserializer: ProtobufDeserializer<NamespaceA.ServiceA.Method.BidirectionalStreaming.Input>(),
  261. serializer: ProtobufSerializer<NamespaceA.ServiceA.Method.BidirectionalStreaming.Output>(),
  262. handler: { request in
  263. try await self.bidirectionalStreaming(request: request)
  264. }
  265. )
  266. }
  267. }
  268. /// Documentation for ServiceA
  269. package protocol NamespaceA_ServiceAServiceProtocol: NamespaceA.ServiceA.StreamingServiceProtocol {
  270. /// Documentation for bidirectionalStreamingMethod
  271. func bidirectionalStreaming(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.BidirectionalStreaming.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.BidirectionalStreaming.Output>
  272. }
  273. /// Partial conformance to `NamespaceA_ServiceAStreamingServiceProtocol`.
  274. extension NamespaceA.ServiceA.ServiceProtocol {
  275. }
  276. """
  277. try self.assertServerCodeTranslation(
  278. codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
  279. expectedSwift: expectedSwift,
  280. accessLevel: .package
  281. )
  282. }
  283. func testServerCodeTranslatorMultipleMethods() throws {
  284. let inputStreamingMethod = MethodDescriptor(
  285. documentation: "/// Documentation for inputStreamingMethod",
  286. name: Name(
  287. base: "InputStreamingMethod",
  288. generatedUpperCase: "InputStreaming",
  289. generatedLowerCase: "inputStreaming"
  290. ),
  291. isInputStreaming: true,
  292. isOutputStreaming: false,
  293. inputType: "NamespaceA_ServiceARequest",
  294. outputType: "NamespaceA_ServiceAResponse"
  295. )
  296. let outputStreamingMethod = MethodDescriptor(
  297. documentation: "/// Documentation for outputStreamingMethod",
  298. name: Name(
  299. base: "outputStreamingMethod",
  300. generatedUpperCase: "OutputStreaming",
  301. generatedLowerCase: "outputStreaming"
  302. ),
  303. isInputStreaming: false,
  304. isOutputStreaming: true,
  305. inputType: "NamespaceA_ServiceARequest",
  306. outputType: "NamespaceA_ServiceAResponse"
  307. )
  308. let service = ServiceDescriptor(
  309. documentation: "/// Documentation for ServiceA",
  310. name: Name(
  311. base: "ServiceATest",
  312. generatedUpperCase: "ServiceA",
  313. generatedLowerCase: "serviceA"
  314. ),
  315. namespace: Name(
  316. base: "namespaceA",
  317. generatedUpperCase: "NamespaceA",
  318. generatedLowerCase: "namespaceA"
  319. ),
  320. methods: [inputStreamingMethod, outputStreamingMethod]
  321. )
  322. let expectedSwift =
  323. """
  324. /// Documentation for ServiceA
  325. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  326. internal protocol NamespaceA_ServiceAStreamingServiceProtocol: GRPCCore.RegistrableRPCService {
  327. /// Documentation for inputStreamingMethod
  328. func inputStreaming(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.InputStreaming.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.InputStreaming.Output>
  329. /// Documentation for outputStreamingMethod
  330. func outputStreaming(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.OutputStreaming.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.OutputStreaming.Output>
  331. }
  332. /// Conformance to `GRPCCore.RegistrableRPCService`.
  333. extension NamespaceA.ServiceA.StreamingServiceProtocol {
  334. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  335. internal func registerMethods(with router: inout GRPCCore.RPCRouter) {
  336. router.registerHandler(
  337. forMethod: NamespaceA.ServiceA.Method.InputStreaming.descriptor,
  338. deserializer: ProtobufDeserializer<NamespaceA.ServiceA.Method.InputStreaming.Input>(),
  339. serializer: ProtobufSerializer<NamespaceA.ServiceA.Method.InputStreaming.Output>(),
  340. handler: { request in
  341. try await self.inputStreaming(request: request)
  342. }
  343. )
  344. router.registerHandler(
  345. forMethod: NamespaceA.ServiceA.Method.OutputStreaming.descriptor,
  346. deserializer: ProtobufDeserializer<NamespaceA.ServiceA.Method.OutputStreaming.Input>(),
  347. serializer: ProtobufSerializer<NamespaceA.ServiceA.Method.OutputStreaming.Output>(),
  348. handler: { request in
  349. try await self.outputStreaming(request: request)
  350. }
  351. )
  352. }
  353. }
  354. /// Documentation for ServiceA
  355. internal protocol NamespaceA_ServiceAServiceProtocol: NamespaceA.ServiceA.StreamingServiceProtocol {
  356. /// Documentation for inputStreamingMethod
  357. func inputStreaming(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.InputStreaming.Input>) async throws -> ServerResponse.Single<NamespaceA.ServiceA.Method.InputStreaming.Output>
  358. /// Documentation for outputStreamingMethod
  359. func outputStreaming(request: ServerRequest.Single<NamespaceA.ServiceA.Method.OutputStreaming.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.OutputStreaming.Output>
  360. }
  361. /// Partial conformance to `NamespaceA_ServiceAStreamingServiceProtocol`.
  362. extension NamespaceA.ServiceA.ServiceProtocol {
  363. internal func inputStreaming(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.InputStreaming.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.InputStreaming.Output> {
  364. let response = try await self.inputStreaming(request: request)
  365. return ServerResponse.Stream(single: response)
  366. }
  367. internal func outputStreaming(request: ServerRequest.Stream<NamespaceA.ServiceA.Method.OutputStreaming.Input>) async throws -> ServerResponse.Stream<NamespaceA.ServiceA.Method.OutputStreaming.Output> {
  368. let response = try await self.outputStreaming(request: ServerRequest.Single(stream: request))
  369. return response
  370. }
  371. }
  372. """
  373. try assertServerCodeTranslation(
  374. codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
  375. expectedSwift: expectedSwift,
  376. accessLevel: .internal
  377. )
  378. }
  379. func testServerCodeTranslatorNoNamespaceService() throws {
  380. let method = MethodDescriptor(
  381. documentation: "/// Documentation for MethodA",
  382. name: Name(base: "methodA", generatedUpperCase: "MethodA", generatedLowerCase: "methodA"),
  383. isInputStreaming: false,
  384. isOutputStreaming: false,
  385. inputType: "NamespaceA_ServiceARequest",
  386. outputType: "NamespaceA_ServiceAResponse"
  387. )
  388. let service = ServiceDescriptor(
  389. documentation: "/// Documentation for ServiceA",
  390. name: Name(
  391. base: "ServiceATest",
  392. generatedUpperCase: "ServiceA",
  393. generatedLowerCase: "serviceA"
  394. ),
  395. namespace: Name(base: "", generatedUpperCase: "", generatedLowerCase: ""),
  396. methods: [method]
  397. )
  398. let expectedSwift =
  399. """
  400. /// Documentation for ServiceA
  401. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  402. internal protocol ServiceAStreamingServiceProtocol: GRPCCore.RegistrableRPCService {
  403. /// Documentation for MethodA
  404. func methodA(request: ServerRequest.Stream<ServiceA.Method.MethodA.Input>) async throws -> ServerResponse.Stream<ServiceA.Method.MethodA.Output>
  405. }
  406. /// Conformance to `GRPCCore.RegistrableRPCService`.
  407. extension ServiceA.StreamingServiceProtocol {
  408. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  409. internal func registerMethods(with router: inout GRPCCore.RPCRouter) {
  410. router.registerHandler(
  411. forMethod: ServiceA.Method.MethodA.descriptor,
  412. deserializer: ProtobufDeserializer<ServiceA.Method.MethodA.Input>(),
  413. serializer: ProtobufSerializer<ServiceA.Method.MethodA.Output>(),
  414. handler: { request in
  415. try await self.methodA(request: request)
  416. }
  417. )
  418. }
  419. }
  420. /// Documentation for ServiceA
  421. internal protocol ServiceAServiceProtocol: ServiceA.StreamingServiceProtocol {
  422. /// Documentation for MethodA
  423. func methodA(request: ServerRequest.Single<ServiceA.Method.MethodA.Input>) async throws -> ServerResponse.Single<ServiceA.Method.MethodA.Output>
  424. }
  425. /// Partial conformance to `ServiceAStreamingServiceProtocol`.
  426. extension ServiceA.ServiceProtocol {
  427. internal func methodA(request: ServerRequest.Stream<ServiceA.Method.MethodA.Input>) async throws -> ServerResponse.Stream<ServiceA.Method.MethodA.Output> {
  428. let response = try await self.methodA(request: ServerRequest.Single(stream: request))
  429. return ServerResponse.Stream(single: response)
  430. }
  431. }
  432. """
  433. try self.assertServerCodeTranslation(
  434. codeGenerationRequest: makeCodeGenerationRequest(services: [service]),
  435. expectedSwift: expectedSwift,
  436. accessLevel: .internal
  437. )
  438. }
  439. func testServerCodeTranslatorMoreServicesOrder() throws {
  440. let serviceA = ServiceDescriptor(
  441. documentation: "/// Documentation for ServiceA",
  442. name: Name(base: "ServiceA", generatedUpperCase: "ServiceA", generatedLowerCase: "serviceA"),
  443. namespace: Name(
  444. base: "namespaceA",
  445. generatedUpperCase: "NamespaceA",
  446. generatedLowerCase: "namespaceA"
  447. ),
  448. methods: []
  449. )
  450. let serviceB = ServiceDescriptor(
  451. documentation: "/// Documentation for ServiceB",
  452. name: Name(base: "ServiceB", generatedUpperCase: "ServiceB", generatedLowerCase: "serviceB"),
  453. namespace: Name(
  454. base: "namespaceA",
  455. generatedUpperCase: "NamespaceA",
  456. generatedLowerCase: "namespaceA"
  457. ),
  458. methods: []
  459. )
  460. let expectedSwift =
  461. """
  462. /// Documentation for ServiceA
  463. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  464. public protocol NamespaceA_ServiceAStreamingServiceProtocol: GRPCCore.RegistrableRPCService {}
  465. /// Conformance to `GRPCCore.RegistrableRPCService`.
  466. extension NamespaceA.ServiceA.StreamingServiceProtocol {
  467. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  468. public func registerMethods(with router: inout GRPCCore.RPCRouter) {}
  469. }
  470. /// Documentation for ServiceA
  471. public protocol NamespaceA_ServiceAServiceProtocol: NamespaceA.ServiceA.StreamingServiceProtocol {}
  472. /// Partial conformance to `NamespaceA_ServiceAStreamingServiceProtocol`.
  473. extension NamespaceA.ServiceA.ServiceProtocol {
  474. }
  475. /// Documentation for ServiceB
  476. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  477. public protocol NamespaceA_ServiceBStreamingServiceProtocol: GRPCCore.RegistrableRPCService {}
  478. /// Conformance to `GRPCCore.RegistrableRPCService`.
  479. extension NamespaceA.ServiceB.StreamingServiceProtocol {
  480. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  481. public func registerMethods(with router: inout GRPCCore.RPCRouter) {}
  482. }
  483. /// Documentation for ServiceB
  484. public protocol NamespaceA_ServiceBServiceProtocol: NamespaceA.ServiceB.StreamingServiceProtocol {}
  485. /// Partial conformance to `NamespaceA_ServiceBStreamingServiceProtocol`.
  486. extension NamespaceA.ServiceB.ServiceProtocol {
  487. }
  488. """
  489. try self.assertServerCodeTranslation(
  490. codeGenerationRequest: makeCodeGenerationRequest(services: [serviceA, serviceB]),
  491. expectedSwift: expectedSwift,
  492. accessLevel: .public
  493. )
  494. }
  495. private func assertServerCodeTranslation(
  496. codeGenerationRequest: CodeGenerationRequest,
  497. expectedSwift: String,
  498. accessLevel: SourceGenerator.Configuration.AccessLevel
  499. ) throws {
  500. let translator = ServerCodeTranslator(accessLevel: accessLevel)
  501. let codeBlocks = try translator.translate(from: codeGenerationRequest)
  502. let renderer = TextBasedRenderer.default
  503. renderer.renderCodeBlocks(codeBlocks)
  504. let contents = renderer.renderedContents()
  505. try XCTAssertEqualWithDiff(contents, expectedSwift)
  506. }
  507. }
  508. #endif // os(macOS) || os(Linux)