@@ -17,21 +17,31 @@ package org.pkl.config.scala
1717
1818import com .softwaremill .diffx .*
1919import com .softwaremill .diffx .scalatest .DiffShouldMatcher .*
20- import org .pkl .config .java .ConfigEvaluator
20+ import org .pkl .config .java .{ ConfigEvaluator , ConfigEvaluatorBuilder }
2121import org .pkl .config .java .mapper .ConversionException
2222import org .pkl .config .scala .syntax .*
2323import org .pkl .core .{Duration => PDuration , ModuleSource }
24- import org .scalatest .funsuite .AnyFunSuite
24+ import org .scalatest .Outcome
25+ import org .scalatest .funsuite .FixtureAnyFunSuite
2526
2627import java .time .Instant
2728import java .util .concurrent .TimeUnit
2829import scala .concurrent .duration .{Duration , FiniteDuration }
30+ import scala .util .Using
2931import scala .util .matching .Regex
3032
31- class ScalaObjectMapperSpec extends AnyFunSuite {
33+ class ScalaObjectMapperSpec extends FixtureAnyFunSuite {
3234 import ScalaObjectMapperSpec .*
3335
34- test(" evaluate scala types" ) {
36+ type FixtureParam = ConfigEvaluator
37+
38+ override def withFixture (test : OneArgTest ): Outcome = {
39+ val evaluator = ConfigEvaluator .preconfigured().forScala()
40+ try withFixture(test.toNoArgTest(evaluator))
41+ finally evaluator.close()
42+ }
43+
44+ test(" evaluate scala types" ) { evaluator =>
3545
3646 val code = {
3747 """
@@ -75,11 +85,7 @@ class ScalaObjectMapperSpec extends AnyFunSuite {
7585 |""" .stripMargin
7686 }
7787
78- val result = ConfigEvaluator
79- .preconfigured()
80- .forScala()
81- .evaluate(ModuleSource .text(code))
82- .to[ObjectMappingTestContainer ]
88+ val result = evaluator.evaluate(ModuleSource .text(code)).to[ObjectMappingTestContainer ]
8389
8490 result shouldMatchTo ObjectMappingTestContainer (
8591 optionalVal1 = None ,
@@ -102,65 +108,55 @@ class ScalaObjectMapperSpec extends AnyFunSuite {
102108 )
103109 }
104110
105- test(" idiomatic Scala 3 enum routes through PStringToScalaEnum" ) {
111+ test(" idiomatic Scala 3 enum routes through PStringToScalaEnum" ) { evaluator =>
106112 val code = {
107113 """
108114 |module M
109115 |color = "Bbb"
110116 |""" .stripMargin
111117 }
112118
113- val result = ConfigEvaluator
114- .preconfigured()
115- .forScala()
116- .evaluate(ModuleSource .text(code))
117- .to[EnumContainer ]
119+ val result = evaluator.evaluate(ModuleSource .text(code)).to[EnumContainer ]
118120 assert(result.color == SimpleEnum .Bbb )
119121 }
120122
121123 test(" unknown enum value raises ConversionException listing valid members in declaration order" ) {
122- val code = {
123- """
124- |module M
125- |color = "Purple"
126- |""" .stripMargin
127- }
128-
129- val ex = intercept[ConversionException ] {
130- ConfigEvaluator
131- .preconfigured()
132- .forScala()
133- .evaluate(ModuleSource .text(code))
134- .to[EnumContainer ]
135- }
136- val msg = ex.getMessage
137- assert(msg.contains(" Purple" ), s " expected input name in message, got: $msg" )
138- val aaaIdx = msg.indexOf(" Aaa" )
139- val bbbIdx = msg.indexOf(" Bbb" )
140- val cccIdx = msg.indexOf(" Ccc" )
141- assert(
142- aaaIdx >= 0 && bbbIdx > aaaIdx && cccIdx > bbbIdx,
143- s " expected Aaa, Bbb, Ccc in declaration order, got: $msg"
144- )
124+ evaluator =>
125+ val code = {
126+ """
127+ |module M
128+ |color = "Purple"
129+ |""" .stripMargin
130+ }
131+
132+ val ex = intercept[ConversionException ] {
133+ evaluator.evaluate(ModuleSource .text(code)).to[EnumContainer ]
134+ }
135+ val msg = ex.getMessage
136+ assert(msg.contains(" Purple" ), s " expected input name in message, got: $msg" )
137+ val aaaIdx = msg.indexOf(" Aaa" )
138+ val bbbIdx = msg.indexOf(" Bbb" )
139+ val cccIdx = msg.indexOf(" Ccc" )
140+ assert(
141+ aaaIdx >= 0 && bbbIdx > aaaIdx && cccIdx > bbbIdx,
142+ s " expected Aaa, Bbb, Ccc in declaration order, got: $msg"
143+ )
145144 }
146145
147146 test(" Java-compat Scala 3 enum (extends java.lang.Enum) routes through PStringToEnum" ) {
148- val code = {
149- """
150- |module M
151- |color = "Yyy"
152- |""" .stripMargin
153- }
154-
155- val result = ConfigEvaluator
156- .preconfigured()
157- .forScala()
158- .evaluate(ModuleSource .text(code))
159- .to[JavaCompatEnumContainer ]
160- assert(result.color == JavaCompatEnum .Yyy )
147+ evaluator =>
148+ val code = {
149+ """
150+ |module M
151+ |color = "Yyy"
152+ |""" .stripMargin
153+ }
154+
155+ val result = evaluator.evaluate(ModuleSource .text(code)).to[JavaCompatEnumContainer ]
156+ assert(result.color == JavaCompatEnum .Yyy )
161157 }
162158
163- test(" missing required property on case class raises ConversionException" ) {
159+ test(" missing required property on case class raises ConversionException" ) { evaluator =>
164160 val code = {
165161 """
166162 |module M
@@ -169,75 +165,58 @@ class ScalaObjectMapperSpec extends AnyFunSuite {
169165 }
170166
171167 val ex = intercept[ConversionException ] {
172- ConfigEvaluator
173- .preconfigured()
174- .forScala()
175- .evaluate(ModuleSource .text(code))
176- .to[Person ]
168+ evaluator.evaluate(ModuleSource .text(code)).to[Person ]
177169 }
178170 val msg = ex.getMessage
179171 assert(msg.contains(" age" ), s " expected missing property name in message, got: $msg" )
180172 }
181173
182174 test(" type mismatch between Pkl value and case class field raises ConversionException" ) {
183- val code = {
184- """
185- |module M
186- |value = "not an int"
187- |""" .stripMargin
188- }
189-
190- val ex = intercept[ConversionException ] {
191- ConfigEvaluator
192- .preconfigured()
193- .forScala()
194- .evaluate(ModuleSource .text(code))
195- .to[IntContainer ]
196- }
197- val msg = ex.getMessage
198- assert(
199- msg.toLowerCase.contains(" cannot convert" ) ||
200- msg.toLowerCase.contains(" string" ) ||
201- msg.toLowerCase.contains(" int" ),
202- s " expected type-mismatch hint in message, got: $msg"
203- )
175+ evaluator =>
176+ val code = {
177+ """
178+ |module M
179+ |value = "not an int"
180+ |""" .stripMargin
181+ }
182+
183+ val ex = intercept[ConversionException ] {
184+ evaluator.evaluate(ModuleSource .text(code)).to[IntContainer ]
185+ }
186+ val msg = ex.getMessage
187+ assert(
188+ msg.toLowerCase.contains(" cannot convert" ) ||
189+ msg.toLowerCase.contains(" string" ) ||
190+ msg.toLowerCase.contains(" int" ),
191+ s " expected type-mismatch hint in message, got: $msg"
192+ )
204193 }
205194
206- test(" pStringToScalaRegex converts Pkl String to Scala Regex" ) {
195+ test(" pStringToScalaRegex converts Pkl String to Scala Regex" ) { evaluator =>
207196 val code = {
208197 """
209198 |module M
210199 |pattern = "^[0-9]+$"
211200 |""" .stripMargin
212201 }
213202
214- val result = ConfigEvaluator
215- .preconfigured()
216- .forScala()
217- .evaluate(ModuleSource .text(code))
218- .to[RegexContainer ]
203+ val result = evaluator.evaluate(ModuleSource .text(code)).to[RegexContainer ]
219204 assert(result.pattern.pattern.pattern() == " ^[0-9]+$" )
220205 }
221206
222- test(" pRegexToScalaRegex converts Pkl Regex to Scala Regex" ) {
207+ test(" pRegexToScalaRegex converts Pkl Regex to Scala Regex" ) { evaluator =>
223208 val code = {
224209 """
225210 |module M
226211 |pattern: Regex = Regex("^[a-z]+$")
227212 |""" .stripMargin
228213 }
229214
230- val result = ConfigEvaluator
231- .preconfigured()
232- .forScala()
233- .evaluate(ModuleSource .text(code))
234- .to[RegexContainer ]
215+ val result = evaluator.evaluate(ModuleSource .text(code)).to[RegexContainer ]
235216 assert(result.pattern.pattern.pattern() == " ^[a-z]+$" )
236217 }
237218
238- test(" forScala extension on ConfigEvaluatorBuilder wires Scala converters" ) {
239- import org .pkl .config .java .ConfigEvaluatorBuilder
240-
219+ test(" forScala extension on ConfigEvaluatorBuilder wires Scala converters" ) { _ =>
241220 val code = {
242221 """
243222 |module M
@@ -246,18 +225,15 @@ class ScalaObjectMapperSpec extends AnyFunSuite {
246225 |""" .stripMargin
247226 }
248227
249- val evaluator = ConfigEvaluatorBuilder .preconfigured().forScala().build()
250- try {
228+ Using .resource(ConfigEvaluatorBuilder .preconfigured().forScala().build()) { evaluator =>
251229 val result = evaluator.evaluate(ModuleSource .text(code)).to[Person ]
252230 assert(result == Person (" via-builder" , 7 ))
253- } finally {
254- evaluator.close()
255231 }
256232 }
257233
258234 test(
259235 " inherited Java conversions: BigInteger, BigDecimal, URI, URL, Path, File, Char, Bytes, DataSize, Listing, Mapping"
260- ) {
236+ ) { evaluator =>
261237 val code = {
262238 """
263239 |module M
@@ -275,11 +251,7 @@ class ScalaObjectMapperSpec extends AnyFunSuite {
275251 |""" .stripMargin
276252 }
277253
278- val result = ConfigEvaluator
279- .preconfigured()
280- .forScala()
281- .evaluate(ModuleSource .text(code))
282- .to[InheritedTypesContainer ]
254+ val result = evaluator.evaluate(ModuleSource .text(code)).to[InheritedTypesContainer ]
283255
284256 assert(result.bigInt == new java.math.BigInteger (" 9007199254740993" ))
285257 assert(result.bigDec == java.math.BigDecimal .valueOf(1.5 ))
0 commit comments