Test_NamingUtils.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. // Tests/SwiftProtobufPluginLibraryTests/Test_NamingUtils.swift - Test NamingUtils.swift
  2. //
  3. // Copyright (c) 2014 - 2017 Apple Inc. and the project authors
  4. // Licensed under Apache License v2.0 with Runtime Library Exception
  5. //
  6. // See LICENSE.txt for license information:
  7. // https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt
  8. //
  9. // -----------------------------------------------------------------------------
  10. import SwiftProtobuf
  11. import SwiftProtobufPluginLibrary
  12. import XCTest
  13. final class Test_NamingUtils: XCTestCase {
  14. func testTypePrefix() throws {
  15. // package, swiftPrefix, expected
  16. let tests: [(String, String?, String)] = [
  17. ("", nil, ""),
  18. ("", "", ""),
  19. ("foo", nil, "Foo_"),
  20. ("FOO", nil, "FOO_"),
  21. ("fooBar", nil, "FooBar_"),
  22. ("FooBar", nil, "FooBar_"),
  23. ("foo.bar.baz", nil, "Foo_Bar_Baz_"),
  24. ("foo_bar_baz", nil, "FooBarBaz_"),
  25. ("foo.bar_baz", nil, "Foo_BarBaz_"),
  26. ("foo_bar__baz", nil, "FooBarBaz_"),
  27. ("foo.bar_baz_", nil, "Foo_BarBaz_"),
  28. ("foo._bar_baz", nil, "Foo_BarBaz_"),
  29. ("foo.BAR_baz", nil, "Foo_BARBaz_"),
  30. ("foo.bar_bAZ", nil, "Foo_BarBAZ_"),
  31. ("FOO.BAR_BAZ", nil, "FOO_BARBAZ_"),
  32. ("_foo", nil, "Foo_"),
  33. ("__foo", nil, "Foo_"),
  34. ("_1foo", nil, "_1foo_"),
  35. ("__1foo", nil, "_1foo_"),
  36. ("_1foo.2bar._3baz", nil, "_1foo_2bar_3baz_"),
  37. ("_1foo_2bar_3baz", nil, "_1foo2bar3baz_"),
  38. ("foo.bar.baz", "", ""),
  39. ("", "ABC", "ABC"),
  40. ("foo.bar.baz", "ABC", "ABC"),
  41. ("foo.bar.baz", "abc", "abc"),
  42. ("foo.bar.baz", "aBc", "aBc"),
  43. ]
  44. for (package, prefix, expected) in tests {
  45. var proto = Google_Protobuf_FileOptions()
  46. if let prefix = prefix {
  47. proto.swiftPrefix = prefix
  48. }
  49. let result = NamingUtils.typePrefix(protoPackage: package, fileOptions: proto)
  50. XCTAssertEqual(result, expected, "Package: \(package), Prefix: \(prefix ?? "nil")")
  51. }
  52. }
  53. func testPrefixStripper_strip() {
  54. // prefix, string, expected
  55. let tests: [(String, String, String?)] = [
  56. ("", "", nil),
  57. ("FOO", "FOO", nil),
  58. ("fOo", "FOO", nil),
  59. ("foo_", "FOO", nil),
  60. ("_foo", "FOO", nil),
  61. ("_foo_", "FOO", nil),
  62. ("foo", "FOO_", nil),
  63. ("foo", "_FOO", nil),
  64. ("foo", "_FOO_", nil),
  65. ("foo_", "FOObar", "bar"),
  66. ("_foo", "FOObar", "bar"),
  67. ("_foo_", "FOObar", "bar"),
  68. ("foo", "FOO_bar", "bar"),
  69. ("foo", "_FOObar", "bar"),
  70. ("foo", "_FOO_bar", "bar"),
  71. ("FOO_bar", "foo_BAR_baz", "baz"),
  72. ("FooBar", "foo_bar_Baz", "Baz"),
  73. ("foo_bar", "foobar_bAZ", "bAZ"),
  74. ("_foo_bar", "foobar_bAZ", "bAZ"),
  75. ("foo__bar_", "_foo_bar__baz", "baz"),
  76. ("FooBar", "foo_bar_1", nil),
  77. ("FooBar", "foo_bar_1foo", nil),
  78. ("FooBar", "foo_bar_foo1", "foo1"),
  79. ]
  80. for (prefix, str, expected) in tests {
  81. let stripper = NamingUtils.PrefixStripper(prefix: prefix)
  82. let result = stripper.strip(from: str)
  83. XCTAssertEqual(result, expected, "Prefix: \(prefix), Input: \(str)")
  84. }
  85. }
  86. func testSanitize_messageName() {
  87. // input, expected
  88. let tests: [(String, String)] = [
  89. ("", ""),
  90. ("Foo", "Foo"),
  91. ("FooBar", "FooBar"),
  92. ("foo_bar", "foo_bar"),
  93. // Some of our names get the disambiguator added.
  94. ("SwiftProtobuf", "SwiftProtobufMessage"),
  95. ("RenamedSwiftProtobuf", "RenamedSwiftProtobufMessage"),
  96. ("isInitialized", "isInitializedMessage"),
  97. // Some Swift keywords.
  98. ("associatedtype", "associatedtypeMessage"),
  99. ("class", "classMessage"),
  100. ("break", "breakMessage"),
  101. ("do", "doMessage"),
  102. // Inputs with the disambiguator.
  103. ("classMessage", "classMessageMessage"),
  104. ("classMessageMessage", "classMessageMessageMessage"),
  105. // Underscores
  106. ("_", "_Message"),
  107. ("___", "___Message"),
  108. ]
  109. for (input, expected) in tests {
  110. XCTAssertEqual(
  111. NamingUtils.sanitize(messageName: input, forbiddenTypeNames: ["RenamedSwiftProtobuf"]),
  112. expected
  113. )
  114. }
  115. }
  116. func testSanitize_enumName() {
  117. // input, expected
  118. let tests: [(String, String)] = [
  119. ("", ""),
  120. ("Foo", "Foo"),
  121. ("FooBar", "FooBar"),
  122. ("foo_bar", "foo_bar"),
  123. // Some of our names get the disambiguator added.
  124. ("SwiftProtobuf", "SwiftProtobufEnum"),
  125. ("RenamedSwiftProtobuf", "RenamedSwiftProtobufEnum"),
  126. ("isInitialized", "isInitializedEnum"),
  127. // Some Swift keywords.
  128. ("associatedtype", "associatedtypeEnum"),
  129. ("class", "classEnum"),
  130. ("break", "breakEnum"),
  131. ("do", "doEnum"),
  132. // Inputs with the disambiguator.
  133. ("classEnum", "classEnumEnum"),
  134. ("classEnumEnum", "classEnumEnumEnum"),
  135. // Underscores
  136. ("_", "_Enum"),
  137. ("___", "___Enum"),
  138. ]
  139. for (input, expected) in tests {
  140. XCTAssertEqual(
  141. NamingUtils.sanitize(enumName: input, forbiddenTypeNames: ["RenamedSwiftProtobuf"]),
  142. expected
  143. )
  144. }
  145. }
  146. func testSanitize_oneofName() {
  147. // input, expected
  148. let tests: [(String, String)] = [
  149. ("", ""),
  150. ("Foo", "Foo"),
  151. ("FooBar", "FooBar"),
  152. ("foo_bar", "foo_bar"),
  153. // Some of our names get the disambiguator added.
  154. ("RenamedSwiftProtobuf", "RenamedSwiftProtobufOneof"),
  155. ("isInitialized", "isInitializedOneof"),
  156. // Some Swift keywords.
  157. ("associatedtype", "associatedtypeOneof"),
  158. ("class", "classOneof"),
  159. ("break", "breakOneof"),
  160. ("do", "doOneof"),
  161. // Inputs with the disambiguator.
  162. ("classOneof", "classOneofOneof"),
  163. ("classOneofOneof", "classOneofOneofOneof"),
  164. // Underscores
  165. ("_", "_Oneof"),
  166. ("___", "___Oneof"),
  167. ]
  168. for (input, expected) in tests {
  169. XCTAssertEqual(
  170. NamingUtils.sanitize(oneofName: input, forbiddenTypeNames: ["RenamedSwiftProtobuf"]),
  171. expected
  172. )
  173. }
  174. }
  175. func testSanitize_fieldName() {
  176. // input, expected
  177. let tests: [(String, String)] = [
  178. ("", ""),
  179. ("Foo", "Foo"),
  180. ("FooBar", "FooBar"),
  181. ("foo_bar", "foo_bar"),
  182. // Some of our names get the disambiguator added.
  183. ("debugDescription", "debugDescription_p"),
  184. ("isInitialized", "isInitialized_p"),
  185. // Some Swift keywords.
  186. ("associatedtype", "`associatedtype`"),
  187. ("class", "`class`"),
  188. ("break", "`break`"),
  189. ("do", "`do`"),
  190. // "has"/"clear" get added by us, so they get the disambiguator...
  191. ("hasFoo", "hasFoo_p"),
  192. ("clearFoo", "clearFoo_p"),
  193. // ...but don't catch words...
  194. ("hashtag", "hashtag"),
  195. ("clearable", "clearable"),
  196. ("has911", "has911"),
  197. // ...or by themselves.
  198. ("has", "has"),
  199. ("clear", "clear"),
  200. // Underscores get more underscores.
  201. ("_", "___"),
  202. ("___", "_____"),
  203. ]
  204. for (input, expected) in tests {
  205. XCTAssertEqual(NamingUtils.sanitize(fieldName: input), expected)
  206. let inputPrefixed = "XX" + NamingUtils.uppercaseFirstCharacter(input)
  207. let expected2 = "XX" + NamingUtils.uppercaseFirstCharacter(NamingUtils.trimBackticks(expected))
  208. XCTAssertEqual(NamingUtils.sanitize(fieldName: inputPrefixed, basedOn: input), expected2)
  209. }
  210. }
  211. func testSanitize_enumCaseName() {
  212. // input, expected
  213. let tests: [(String, String)] = [
  214. ("", ""),
  215. ("Foo", "Foo"),
  216. ("FooBar", "FooBar"),
  217. ("foo_bar", "foo_bar"),
  218. // Some of our names get the disambiguator added.
  219. ("debugDescription", "debugDescription_"),
  220. ("dynamicType", "dynamicType_"),
  221. // Some Swift keywords work with backticks
  222. ("associatedtype", "`associatedtype`"),
  223. ("class", "`class`"),
  224. ("break", "`break`"),
  225. ("do", "`do`"),
  226. // Underscores get more underscores.
  227. ("_", "___"),
  228. ("___", "_____"),
  229. ]
  230. for (input, expected) in tests {
  231. XCTAssertEqual(NamingUtils.sanitize(enumCaseName: input), expected)
  232. }
  233. }
  234. func testSanitize_messageScopedExtensionName() {
  235. // input, expected
  236. let tests: [(String, String)] = [
  237. ("", ""),
  238. ("Foo", "Foo"),
  239. ("FooBar", "FooBar"),
  240. ("foo_bar", "foo_bar"),
  241. // Some of our names get the disambiguator added.
  242. ("debugDescription", "debugDescription_"),
  243. ("dynamicType", "dynamicType_"),
  244. // Some Swift keywords work with backticks
  245. ("associatedtype", "`associatedtype`"),
  246. ("class", "`class`"),
  247. ("break", "`break`"),
  248. ("do", "`do`"),
  249. // Underscores get more underscores.
  250. ("_", "___"),
  251. ("___", "_____"),
  252. ]
  253. for (input, expected) in tests {
  254. XCTAssertEqual(NamingUtils.sanitize(messageScopedExtensionName: input), expected)
  255. }
  256. }
  257. func testToCamelCase() {
  258. // input, expectedLower, expectedUpper
  259. let tests: [(String, String, String)] = [
  260. ("", "", ""),
  261. ("foo", "foo", "Foo"),
  262. ("FOO", "foo", "Foo"),
  263. ("foO", "foO", "FoO"),
  264. ("foo_bar", "fooBar", "FooBar"),
  265. ("foo_bar", "fooBar", "FooBar"),
  266. ("foo_bAr_BaZ", "fooBArBaZ", "FooBArBaZ"),
  267. ("foo_bAr_BaZ", "fooBArBaZ", "FooBArBaZ"),
  268. ("foo1bar", "foo1Bar", "Foo1Bar"),
  269. ("foo2bAr3BaZ", "foo2BAr3BaZ", "Foo2BAr3BaZ"),
  270. ("foo_1bar", "foo1Bar", "Foo1Bar"),
  271. ("foo_2bAr_3BaZ", "foo2BAr3BaZ", "Foo2BAr3BaZ"),
  272. ("_0foo_1bar", "_0Foo1Bar", "_0Foo1Bar"),
  273. ("_0foo_2bAr_3BaZ", "_0Foo2BAr3BaZ", "_0Foo2BAr3BaZ"),
  274. ("url", "url", "URL"),
  275. ("http", "http", "HTTP"),
  276. ("https", "https", "HTTPS"),
  277. ("id", "id", "ID"),
  278. ("the_url", "theURL", "TheURL"),
  279. ("use_http", "useHTTP", "UseHTTP"),
  280. ("use_https", "useHTTPS", "UseHTTPS"),
  281. ("request_id", "requestID", "RequestID"),
  282. ("url_number", "urlNumber", "URLNumber"),
  283. ("http_needed", "httpNeeded", "HTTPNeeded"),
  284. ("https_needed", "httpsNeeded", "HTTPSNeeded"),
  285. ("id_number", "idNumber", "IDNumber"),
  286. ("is_url_number", "isURLNumber", "IsURLNumber"),
  287. ("is_http_needed", "isHTTPNeeded", "IsHTTPNeeded"),
  288. ("is_https_needed", "isHTTPSNeeded", "IsHTTPSNeeded"),
  289. ("the_id_number", "theIDNumber", "TheIDNumber"),
  290. ("url_foo_http_id", "urlFooHTTPID", "URLFooHTTPID"),
  291. ("göß", "göß", "Göß"),
  292. ("göo", "göO", "GöO"),
  293. ("gö_o", "göO", "GöO"),
  294. ("g_🎉_o", "g🎉O", "G🎉O"),
  295. ("g🎉o", "g🎉O", "G🎉O"),
  296. ("m\u{AB}n", "m_u171N", "M_u171N"),
  297. ("m\u{AB}_n", "m_u171N", "M_u171N"),
  298. ("m_\u{AB}_n", "m_u171N", "M_u171N"),
  299. ]
  300. for (input, expectedLower, expectedUppper) in tests {
  301. XCTAssertEqual(NamingUtils.toLowerCamelCase(input), expectedLower)
  302. XCTAssertEqual(NamingUtils.toUpperCamelCase(input), expectedUppper)
  303. }
  304. }
  305. }