StructuredSwift+MetadataTests.swift 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. * Copyright 2024, 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. extension StructuedSwiftTests {
  19. @Suite("Metadata")
  20. struct Metadata {
  21. @Test("typealias Input = <Name>", arguments: AccessModifier.allCases)
  22. func methodInputTypealias(access: AccessModifier) {
  23. let decl: TypealiasDescription = .methodInput(accessModifier: access, name: "Foo")
  24. let expected = "\(access) typealias Input = Foo"
  25. #expect(render(.typealias(decl)) == expected)
  26. }
  27. @Test("typealias Output = <Name>", arguments: AccessModifier.allCases)
  28. func methodOutputTypealias(access: AccessModifier) {
  29. let decl: TypealiasDescription = .methodOutput(accessModifier: access, name: "Foo")
  30. let expected = "\(access) typealias Output = Foo"
  31. #expect(render(.typealias(decl)) == expected)
  32. }
  33. @Test(
  34. "static let descriptor = GRPCCore.MethodDescriptor(...)",
  35. arguments: AccessModifier.allCases
  36. )
  37. func staticMethodDescriptorProperty(access: AccessModifier) {
  38. let decl: VariableDescription = .methodDescriptor(
  39. accessModifier: access,
  40. serviceNamespace: "FooService",
  41. literalMethodName: "Bar"
  42. )
  43. let expected = """
  44. \(access) static let descriptor = GRPCCore.MethodDescriptor(
  45. service: FooService.descriptor.fullyQualifiedService,
  46. method: "Bar"
  47. )
  48. """
  49. #expect(render(.variable(decl)) == expected)
  50. }
  51. @Test(
  52. "static let descriptor = GRPCCore.ServiceDescriptor.<Name>",
  53. arguments: AccessModifier.allCases
  54. )
  55. func staticServiceDescriptorProperty(access: AccessModifier) {
  56. let decl: VariableDescription = .serviceDescriptor(
  57. accessModifier: access,
  58. namespacedProperty: "foo"
  59. )
  60. let expected = "\(access) static let descriptor = GRPCCore.ServiceDescriptor.foo"
  61. #expect(render(.variable(decl)) == expected)
  62. }
  63. @Test("extension GRPCCore.ServiceDescriptor { ... }", arguments: AccessModifier.allCases)
  64. func staticServiceDescriptorPropertyExtension(access: AccessModifier) {
  65. let decl: ExtensionDescription = .serviceDescriptor(
  66. accessModifier: access,
  67. propertyName: "foo",
  68. literalNamespace: "echo",
  69. literalService: "EchoService"
  70. )
  71. let expected = """
  72. extension GRPCCore.ServiceDescriptor {
  73. \(access) static let foo = Self(
  74. package: "echo",
  75. service: "EchoService"
  76. )
  77. }
  78. """
  79. #expect(render(.extension(decl)) == expected)
  80. }
  81. @Test(
  82. "static let descriptors: [GRPCCore.MethodDescriptor] = [...]",
  83. arguments: AccessModifier.allCases
  84. )
  85. func staticMethodDescriptorsArray(access: AccessModifier) {
  86. let decl: VariableDescription = .methodDescriptorsArray(
  87. accessModifier: access,
  88. methodNamespaceNames: ["Foo", "Bar", "Baz"]
  89. )
  90. let expected = """
  91. \(access) static let descriptors: [GRPCCore.MethodDescriptor] = [
  92. Foo.descriptor,
  93. Bar.descriptor,
  94. Baz.descriptor
  95. ]
  96. """
  97. #expect(render(.variable(decl)) == expected)
  98. }
  99. @Test("enum <Method> { ... }", arguments: AccessModifier.allCases)
  100. func methodNamespaceEnum(access: AccessModifier) {
  101. let decl: EnumDescription = .methodNamespace(
  102. accessModifier: access,
  103. name: "Foo",
  104. literalMethod: "Foo",
  105. serviceNamespace: "Bar_Baz",
  106. inputType: "FooInput",
  107. outputType: "FooOutput"
  108. )
  109. let expected = """
  110. \(access) enum Foo {
  111. \(access) typealias Input = FooInput
  112. \(access) typealias Output = FooOutput
  113. \(access) static let descriptor = GRPCCore.MethodDescriptor(
  114. service: Bar_Baz.descriptor.fullyQualifiedService,
  115. method: "Foo"
  116. )
  117. }
  118. """
  119. #expect(render(.enum(decl)) == expected)
  120. }
  121. @Test("enum Method { ... }", arguments: AccessModifier.allCases)
  122. func methodsNamespaceEnum(access: AccessModifier) {
  123. let decl: EnumDescription = .methodsNamespace(
  124. accessModifier: access,
  125. serviceNamespace: "Bar_Baz",
  126. methods: [
  127. .init(
  128. documentation: "",
  129. name: .init(base: "Foo", generatedUpperCase: "Foo", generatedLowerCase: "foo"),
  130. isInputStreaming: false,
  131. isOutputStreaming: false,
  132. inputType: "FooInput",
  133. outputType: "FooOutput"
  134. )
  135. ]
  136. )
  137. let expected = """
  138. \(access) enum Method {
  139. \(access) enum Foo {
  140. \(access) typealias Input = FooInput
  141. \(access) typealias Output = FooOutput
  142. \(access) static let descriptor = GRPCCore.MethodDescriptor(
  143. service: Bar_Baz.descriptor.fullyQualifiedService,
  144. method: "Foo"
  145. )
  146. }
  147. \(access) static let descriptors: [GRPCCore.MethodDescriptor] = [
  148. Foo.descriptor
  149. ]
  150. }
  151. """
  152. #expect(render(.enum(decl)) == expected)
  153. }
  154. @Test("enum Method { ... } (no methods)", arguments: AccessModifier.allCases)
  155. func methodsNamespaceEnumNoMethods(access: AccessModifier) {
  156. let decl: EnumDescription = .methodsNamespace(
  157. accessModifier: access,
  158. serviceNamespace: "Bar_Baz",
  159. methods: []
  160. )
  161. let expected = """
  162. \(access) enum Method {
  163. \(access) static let descriptors: [GRPCCore.MethodDescriptor] = []
  164. }
  165. """
  166. #expect(render(.enum(decl)) == expected)
  167. }
  168. @Test("enum <Service> { ... }", arguments: AccessModifier.allCases)
  169. func serviceNamespaceEnum(access: AccessModifier) {
  170. let decl: EnumDescription = .serviceNamespace(
  171. accessModifier: access,
  172. name: "Foo",
  173. serviceDescriptorProperty: "foo",
  174. client: false,
  175. server: false,
  176. methods: [
  177. .init(
  178. documentation: "",
  179. name: .init(base: "Bar", generatedUpperCase: "Bar", generatedLowerCase: "bar"),
  180. isInputStreaming: false,
  181. isOutputStreaming: false,
  182. inputType: "BarInput",
  183. outputType: "BarOutput"
  184. )
  185. ]
  186. )
  187. let expected = """
  188. \(access) enum Foo {
  189. \(access) static let descriptor = GRPCCore.ServiceDescriptor.foo
  190. \(access) enum Method {
  191. \(access) enum Bar {
  192. \(access) typealias Input = BarInput
  193. \(access) typealias Output = BarOutput
  194. \(access) static let descriptor = GRPCCore.MethodDescriptor(
  195. service: Foo.descriptor.fullyQualifiedService,
  196. method: "Bar"
  197. )
  198. }
  199. \(access) static let descriptors: [GRPCCore.MethodDescriptor] = [
  200. Bar.descriptor
  201. ]
  202. }
  203. }
  204. """
  205. #expect(render(.enum(decl)) == expected)
  206. }
  207. @Test(
  208. "enum <Service> { ... } (no methods)",
  209. arguments: AccessModifier.allCases,
  210. [(true, true), (false, false), (true, false), (false, true)]
  211. )
  212. func serviceNamespaceEnumNoMethods(access: AccessModifier, config: (client: Bool, server: Bool))
  213. {
  214. let decl: EnumDescription = .serviceNamespace(
  215. accessModifier: access,
  216. name: "Foo",
  217. serviceDescriptorProperty: "foo",
  218. client: config.client,
  219. server: config.server,
  220. methods: []
  221. )
  222. var expected = """
  223. \(access) enum Foo {
  224. \(access) static let descriptor = GRPCCore.ServiceDescriptor.foo
  225. \(access) enum Method {
  226. \(access) static let descriptors: [GRPCCore.MethodDescriptor] = []
  227. }\n
  228. """
  229. if config.server {
  230. expected += """
  231. \(access) typealias StreamingServiceProtocol = Foo_StreamingServiceProtocol
  232. \(access) typealias ServiceProtocol = Foo_ServiceProtocol
  233. """
  234. }
  235. if config.client {
  236. if config.server {
  237. expected += "\n"
  238. }
  239. expected += """
  240. \(access) typealias ClientProtocol = Foo_ClientProtocol
  241. \(access) typealias Client = Foo_Client
  242. """
  243. }
  244. if config.client || config.server {
  245. expected += "\n}"
  246. } else {
  247. expected += "}"
  248. }
  249. #expect(render(.enum(decl)) == expected)
  250. }
  251. }
  252. }