Test_FeatureResolver.swift 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // Tests/SwiftProtobufPluginLibraryTests/Test_Descriptor.swift - Test Descriptor.swift
  2. //
  3. // Copyright (c) 2014 - 2024 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_FeatureResolver: XCTestCase {
  14. private func simpleResolver(extensions: [any AnyMessageExtension] = []) -> FeatureResolver {
  15. let defaults = try! Google_Protobuf_FeatureSetDefaults(
  16. textFormatString: """
  17. minimum_edition: EDITION_PROTO2
  18. maximum_edition: EDITION_2023
  19. defaults { edition: EDITION_2023 }
  20. """
  21. )
  22. return try! FeatureResolver(
  23. edition: .edition2023,
  24. featureSetDefaults: defaults,
  25. featureExtensions: extensions
  26. )
  27. }
  28. func testInit_EditionBelowMin() {
  29. let defaults = Google_Protobuf_FeatureSetDefaults.with {
  30. $0.minimumEdition = .proto3
  31. $0.maximumEdition = .edition2023
  32. }
  33. XCTAssertThrowsError(try FeatureResolver(edition: .proto2, featureSetDefaults: defaults)) { e in
  34. XCTAssertEqual(
  35. e as! FeatureResolver.Error,
  36. FeatureResolver.Error.unsupported(
  37. edition: .proto2,
  38. supported: Google_Protobuf_Edition.proto3...Google_Protobuf_Edition.edition2023
  39. )
  40. )
  41. }
  42. }
  43. func testInit_EditionAboveMax() {
  44. let defaults = Google_Protobuf_FeatureSetDefaults.with {
  45. $0.minimumEdition = .proto2
  46. $0.maximumEdition = .proto3
  47. }
  48. XCTAssertThrowsError(try FeatureResolver(edition: .edition2023, featureSetDefaults: defaults)) { e in
  49. XCTAssertEqual(
  50. e as! FeatureResolver.Error,
  51. FeatureResolver.Error.unsupported(
  52. edition: .edition2023,
  53. supported: Google_Protobuf_Edition.proto2...Google_Protobuf_Edition.proto3
  54. )
  55. )
  56. }
  57. }
  58. func testInit_EditionDefaultNotFound() {
  59. let defaults = try! Google_Protobuf_FeatureSetDefaults(
  60. textFormatString: """
  61. minimum_edition: EDITION_PROTO2
  62. maximum_edition: EDITION_2023
  63. defaults { edition: EDITION_2023 }
  64. """
  65. )
  66. XCTAssertThrowsError(try FeatureResolver(edition: .proto2, featureSetDefaults: defaults)) { e in
  67. XCTAssertEqual(
  68. e as! FeatureResolver.Error,
  69. FeatureResolver.Error.noDefault(edition: .proto2)
  70. )
  71. }
  72. }
  73. func testInit_EditionExactMatches() throws {
  74. let defaults = try! Google_Protobuf_FeatureSetDefaults(
  75. textFormatString: """
  76. minimum_edition: EDITION_99997_TEST_ONLY
  77. maximum_edition: EDITION_99999_TEST_ONLY
  78. defaults {
  79. edition: EDITION_99997_TEST_ONLY
  80. overridable_features { field_presence: EXPLICIT}
  81. }
  82. defaults {
  83. edition: EDITION_99998_TEST_ONLY
  84. overridable_features { field_presence: IMPLICIT}
  85. }
  86. defaults {
  87. edition: EDITION_99999_TEST_ONLY
  88. overridable_features { field_presence: LEGACY_REQUIRED}
  89. }
  90. """
  91. )
  92. // Ensure the right things were matched and we got the right feature sets.
  93. // If lookup fails, throw out of the test method.
  94. // edition99997TestOnly
  95. let resolver1: FeatureResolver = try FeatureResolver(
  96. edition: .edition99997TestOnly,
  97. featureSetDefaults: defaults
  98. )
  99. XCTAssertEqual(resolver1.edition, .edition99997TestOnly)
  100. XCTAssertEqual(resolver1.defaultFeatureSet.fieldPresence, .explicit)
  101. // edition99998TestOnly
  102. let resolver2 = try FeatureResolver(
  103. edition: .edition99998TestOnly,
  104. featureSetDefaults: defaults
  105. )
  106. XCTAssertEqual(resolver2.edition, .edition99998TestOnly)
  107. XCTAssertEqual(resolver2.defaultFeatureSet.fieldPresence, .implicit)
  108. // edition99999TestOnly
  109. let resolver3 = try FeatureResolver(
  110. edition: .edition99999TestOnly,
  111. featureSetDefaults: defaults
  112. )
  113. XCTAssertEqual(resolver3.edition, .edition99999TestOnly)
  114. XCTAssertEqual(resolver3.defaultFeatureSet.fieldPresence, .legacyRequired)
  115. }
  116. func testInit_EditionMatchesLower() throws {
  117. let defaults = try! Google_Protobuf_FeatureSetDefaults(
  118. textFormatString: """
  119. minimum_edition: EDITION_99997_TEST_ONLY
  120. maximum_edition: EDITION_99999_TEST_ONLY
  121. defaults {
  122. edition: EDITION_99997_TEST_ONLY
  123. overridable_features { field_presence: EXPLICIT}
  124. }
  125. defaults {
  126. edition: EDITION_99999_TEST_ONLY
  127. overridable_features { field_presence: LEGACY_REQUIRED}
  128. }
  129. """
  130. )
  131. // Ensure the right things were matched and we got the right feature sets.
  132. // If lookup fails, throw out of the test method.
  133. // edition99997TestOnly
  134. let resolver1: FeatureResolver = try FeatureResolver(
  135. edition: .edition99997TestOnly,
  136. featureSetDefaults: defaults
  137. )
  138. XCTAssertEqual(resolver1.edition, .edition99997TestOnly)
  139. XCTAssertEqual(resolver1.defaultFeatureSet.fieldPresence, .explicit)
  140. // edition99998TestOnly
  141. // The edition will says 99998 since that's what we requested, but the
  142. // defaults will have what was in 99997
  143. let resolver2 = try FeatureResolver(
  144. edition: .edition99998TestOnly,
  145. featureSetDefaults: defaults
  146. )
  147. XCTAssertEqual(resolver2.edition, .edition99998TestOnly)
  148. XCTAssertEqual(resolver2.defaultFeatureSet.fieldPresence, .explicit)
  149. // edition99999TestOnly
  150. let resolver3 = try FeatureResolver(
  151. edition: .edition99999TestOnly,
  152. featureSetDefaults: defaults
  153. )
  154. XCTAssertEqual(resolver3.edition, .edition99999TestOnly)
  155. XCTAssertEqual(resolver3.defaultFeatureSet.fieldPresence, .legacyRequired)
  156. }
  157. func testInit_BadExtension() throws {
  158. let defaults = try! Google_Protobuf_FeatureSetDefaults(
  159. textFormatString: """
  160. minimum_edition: EDITION_PROTO2
  161. maximum_edition: EDITION_2023
  162. defaults { edition: EDITION_PROTO2 }
  163. """
  164. )
  165. XCTAssertThrowsError(
  166. try FeatureResolver(
  167. edition: .proto2,
  168. featureSetDefaults: defaults,
  169. featureExtensions: [
  170. SwiftFeatureTest_Extensions_test,
  171. SDTExtensions_ext_str,
  172. ]
  173. )
  174. ) { e in
  175. XCTAssertEqual(
  176. e as! FeatureResolver.Error,
  177. FeatureResolver.Error.invalidExtension(type: "swift_descriptor_test.import.ExtendableOne")
  178. )
  179. }
  180. }
  181. func testInit_mergingFixedOverridable() throws {
  182. let defaults = try! Google_Protobuf_FeatureSetDefaults(
  183. textFormatString: """
  184. minimum_edition: EDITION_99997_TEST_ONLY
  185. maximum_edition: EDITION_99999_TEST_ONLY
  186. defaults {
  187. edition: EDITION_99997_TEST_ONLY
  188. overridable_features { field_presence: EXPLICIT }
  189. fixed_features { enum_type: CLOSED }
  190. }
  191. """
  192. )
  193. // Test that fixed and overridable merge
  194. // If lookup fails, throw out of the test method.
  195. let resolver1: FeatureResolver = try FeatureResolver(
  196. edition: .edition99997TestOnly,
  197. featureSetDefaults: defaults
  198. )
  199. XCTAssertEqual(resolver1.edition, .edition99997TestOnly)
  200. XCTAssertEqual(resolver1.defaultFeatureSet.fieldPresence, .explicit)
  201. XCTAssertEqual(resolver1.defaultFeatureSet.enumType, .closed)
  202. }
  203. func testResolve_Basics() {
  204. let resolver = simpleResolver()
  205. let features1 = Google_Protobuf_FeatureSet.with {
  206. $0.fieldPresence = .explicit
  207. $0.messageEncoding = .lengthPrefixed
  208. }
  209. let features2 = Google_Protobuf_FeatureSet.with {
  210. $0.enumType = .open
  211. }
  212. let features3 = Google_Protobuf_FeatureSet.with {
  213. $0.fieldPresence = .legacyRequired
  214. $0.jsonFormat = .legacyBestEffort
  215. }
  216. // No overlap
  217. let merged12 = resolver.resolve(features: features1, resolvedParent: features2)
  218. XCTAssertEqual(merged12.fieldPresence, .explicit)
  219. XCTAssertEqual(merged12.enumType, .open)
  220. XCTAssertEqual(merged12.messageEncoding, .lengthPrefixed)
  221. // Overlap, features overrides parent features
  222. let merged13 = resolver.resolve(features: features1, resolvedParent: features3)
  223. XCTAssertEqual(merged13.fieldPresence, .explicit)
  224. XCTAssertEqual(merged13.jsonFormat, .legacyBestEffort)
  225. XCTAssertEqual(merged13.messageEncoding, .lengthPrefixed)
  226. }
  227. func testResolve_CustomFeature() {
  228. let resolver = simpleResolver(extensions: [SwiftFeatureTest_Extensions_test])
  229. let features1 = Google_Protobuf_FeatureSet.with {
  230. $0.SwiftFeatureTest_test.feature1 = .value2
  231. $0.SwiftFeatureTest_test.feature2 = .value2
  232. }
  233. let features2 = Google_Protobuf_FeatureSet.with {
  234. $0.SwiftFeatureTest_test.feature3 = .value3
  235. }
  236. let features3 = Google_Protobuf_FeatureSet.with {
  237. $0.SwiftFeatureTest_test.feature1 = .value4
  238. $0.SwiftFeatureTest_test.feature3 = .value4
  239. }
  240. // No overlap
  241. let merged12 = resolver.resolve(features: features1, resolvedParent: features2)
  242. XCTAssertEqual(merged12.SwiftFeatureTest_test.feature1, .value2)
  243. XCTAssertEqual(merged12.SwiftFeatureTest_test.feature2, .value2)
  244. XCTAssertEqual(merged12.SwiftFeatureTest_test.feature3, .value3)
  245. // Overlap, features overrides parent features
  246. let merged13 = resolver.resolve(features: features1, resolvedParent: features3)
  247. XCTAssertEqual(merged13.SwiftFeatureTest_test.feature1, .value2)
  248. XCTAssertEqual(merged13.SwiftFeatureTest_test.feature2, .value2)
  249. XCTAssertEqual(merged13.SwiftFeatureTest_test.feature3, .value4)
  250. }
  251. }