ServerCodeTranslatorSnippetBasedTests.swift 23 KB

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