From 200db7e06091a6da5e9b214af442bd23cd83f647 Mon Sep 17 00:00:00 2001 From: Mateusz Kubuszok Date: Mon, 13 Jan 2025 17:48:08 +0100 Subject: [PATCH] Test Option merging with and without flags --- .../TransformOptionToOptionRuleModule.scala | 1 - ....scala => PartialMergingProductSpec.scala} | 2 +- .../chimney/PartialMergingStdLibSpec.scala | 272 ++++++++++++++++++ ...ec.scala => TotalMergingProductSpec.scala} | 2 +- .../chimney/TotalMergingStdLibSpec.scala | 233 +++++++++++++++ 5 files changed, 507 insertions(+), 3 deletions(-) rename chimney/src/test/scala/io/scalaland/chimney/{PartialTransformerMergingSpec.scala => PartialMergingProductSpec.scala} (99%) create mode 100644 chimney/src/test/scala/io/scalaland/chimney/PartialMergingStdLibSpec.scala rename chimney/src/test/scala/io/scalaland/chimney/{TotalTransformerMergingSpec.scala => TotalMergingProductSpec.scala} (99%) create mode 100644 chimney/src/test/scala/io/scalaland/chimney/TotalMergingStdLibSpec.scala diff --git a/chimney/src/main/scala/io/scalaland/chimney/internal/compiletime/derivation/transformer/rules/TransformOptionToOptionRuleModule.scala b/chimney/src/main/scala/io/scalaland/chimney/internal/compiletime/derivation/transformer/rules/TransformOptionToOptionRuleModule.scala index 60f869e70..149773ed7 100644 --- a/chimney/src/main/scala/io/scalaland/chimney/internal/compiletime/derivation/transformer/rules/TransformOptionToOptionRuleModule.scala +++ b/chimney/src/main/scala/io/scalaland/chimney/internal/compiletime/derivation/transformer/rules/TransformOptionToOptionRuleModule.scala @@ -137,6 +137,5 @@ private[compiletime] trait TransformOptionToOptionRuleModule { ) ) } - } } diff --git a/chimney/src/test/scala/io/scalaland/chimney/PartialTransformerMergingSpec.scala b/chimney/src/test/scala/io/scalaland/chimney/PartialMergingProductSpec.scala similarity index 99% rename from chimney/src/test/scala/io/scalaland/chimney/PartialTransformerMergingSpec.scala rename to chimney/src/test/scala/io/scalaland/chimney/PartialMergingProductSpec.scala index 64d87d2a8..7b8e576ad 100644 --- a/chimney/src/test/scala/io/scalaland/chimney/PartialTransformerMergingSpec.scala +++ b/chimney/src/test/scala/io/scalaland/chimney/PartialMergingProductSpec.scala @@ -3,7 +3,7 @@ package io.scalaland.chimney import io.scalaland.chimney.dsl.* import io.scalaland.chimney.fixtures.* -class PartialTransformerMergingSpec extends ChimneySpec { +class PartialMergingProductSpec extends ChimneySpec { group("setting .withFallback(fallbackValue)") { diff --git a/chimney/src/test/scala/io/scalaland/chimney/PartialMergingStdLibSpec.scala b/chimney/src/test/scala/io/scalaland/chimney/PartialMergingStdLibSpec.scala new file mode 100644 index 000000000..0e6b81a05 --- /dev/null +++ b/chimney/src/test/scala/io/scalaland/chimney/PartialMergingStdLibSpec.scala @@ -0,0 +1,272 @@ +package io.scalaland.chimney + +import io.scalaland.chimney.dsl.* +import io.scalaland.chimney.fixtures.* +import io.scalaland.chimney.PartialTransformer + +class PartialMergingStdLibSpec extends ChimneySpec { + + group("setting .withFallback(fallbackValue)") { + + test("should use only source Option when no merging strategy is enabled") { + import merges.Nested + + implicit val s2i: PartialTransformer[String, Int] = PartialTransformer.fromFunction[String, Int](_.toInt) + + "10" + .intoPartial[Option[Int]] + .withFallback(20) + .transform + .asOption ==> Some(Some(10)) + Option("10") + .intoPartial[Option[Int]] + .withFallback(Option(20)) + .transform + .asOption ==> Some(Some(10)) + Option("10") + .intoPartial[Option[Int]] + .withFallback(Option.empty[Int]) + .transform + .asOption ==> Some(Some(10)) + Option + .empty[String] + .intoPartial[Option[Int]] + .withFallback(Option(20)) + .transform + .asOption ==> Some(None) + Option + .empty[String] + .intoPartial[Option[Int]] + .withFallback(Option.empty[Int]) + .transform + .asOption ==> Some(None) + + Nested("10") + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(20)) + .transform + .asOption ==> Some(Nested(Some(10))) + Nested(Option("10")) + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(Option(20))) + .transform + .asOption ==> Some(Nested(Some(10))) + Nested(Option("10")) + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(Option.empty[String])) + .transform + .asOption ==> Some(Nested(Some(10))) + Nested(Option.empty[String]) + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(Option(20))) + .transform + .asOption ==> Some(Nested(None)) + Nested(Option.empty[String]) + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(Option.empty[Int])) + .transform + .asOption ==> Some(Nested(None)) + } + } + + group("setting .withFallbackFrom(selectorFrom)(fallbackValue)") { + + test("should use only source Option when no merging strategy is enabled") { + import merges.Nested + + implicit val s2i: PartialTransformer[String, Int] = PartialTransformer.fromFunction[String, Int](_.toInt) + + Nested("10") + .intoPartial[Nested[Option[Int]]] + .withFallbackFrom(_.value)(20) + .transform.asOption ==> Some(Nested(Some(10))) + Nested(Option("10")) + .intoPartial[Nested[Option[Int]]] + .withFallbackFrom(_.value)(Option(20)) + .transform + .asOption ==> Some(Nested(Some(10))) + Nested(Option("10")) + .intoPartial[Nested[Option[Int]]] + .withFallbackFrom(_.value)(Option.empty[String]) + .transform + .asOption ==> Some(Nested(Some(10))) + Nested(Option.empty[String]) + .intoPartial[Nested[Option[Int]]] + .withFallbackFrom(_.value)(Option(20)) + .transform + .asOption ==> Some(Nested(None)) + Nested(Option.empty[String]) + .intoPartial[Nested[Option[Int]]] + .withFallbackFrom(_.value)(Option.empty[Int]) + .transform + .asOption ==> Some(Nested(None)) + + Nested(Nested("10")) + .intoPartial[Nested[Nested[Option[Int]]]] + .withFallbackFrom(_.value)(Nested(20)) + .transform + .asOption ==> Some(Nested(Nested(Some(10)))) + Nested(Nested(Option("10"))) + .intoPartial[Nested[Nested[Option[Int]]]] + .withFallbackFrom(_.value)(Nested(Option(20))) + .transform + .asOption ==> Some(Nested(Nested(Some(10)))) + Nested(Nested(Option("10"))) + .intoPartial[Nested[Nested[Option[Int]]]] + .withFallbackFrom(_.value)(Nested(Option.empty[Int])) + .transform + .asOption ==> Some(Nested(Nested(Some(10)))) + Nested(Nested(Option.empty[String])) + .intoPartial[Nested[Nested[Option[Int]]]] + .withFallbackFrom(_.value)(Nested(Option(20))) + .transform + .asOption ==> Some(Nested(Nested(None))) + Nested(Nested(Option.empty[String])) + .intoPartial[Nested[Nested[Option[Int]]]] + .withFallbackFrom(_.value)(Nested(Option.empty[Int])) + .transform + .asOption ==> Some(Nested(Nested(None))) + } + } + + group("flag .enableOptionFallbackMerge(SourceOrElseFallback)") { + + test("should merge Options from source to fallback when SourceOrElseFallback strategy is enabled") { + import merges.Nested + + implicit val s2i: PartialTransformer[String, Int] = PartialTransformer.fromFunction[String, Int](_.toInt) + + "10".intoPartial[Option[Int]] + .withFallback(20) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Some(10)) + Option("10") + .intoPartial[Option[Int]] + .withFallback(Option(20)) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Some(10)) + Option("10") + .intoPartial[Option[Int]] + .withFallback(Option.empty[String]) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Some(10)) + Option + .empty[String] + .intoPartial[Option[Int]] + .withFallback(Option(20)) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Some(20)) + Option + .empty[String] + .intoPartial[Option[Int]] + .withFallback(Option.empty[Int]) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(None) + + Nested("10") + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(20)) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Nested(Some(10))) + Nested(Option("10")) + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(Option(20))) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Nested(Some(10))) + Nested(Option("10")) + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(Option.empty[Int])) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Nested(Some(10))) + Nested(Option.empty[String]) + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(Option(20))) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Nested(Some(20))) + Nested(Option.empty[String]) + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(Option.empty[Int])) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform + .asOption ==> Some(Nested(None)) + } + + test("should merge Options from fallback to source when FallbackOrElseSource strategy is enabled") { + import merges.Nested + + implicit val s2i: PartialTransformer[String, Int] = PartialTransformer.fromFunction[String, Int](_.toInt) + + "10".intoPartial[Option[Int]] + .withFallback(20) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Some(20)) + Option("10") + .intoPartial[Option[Int]] + .withFallback(Option(20)) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Some(20)) + Option("10") + .intoPartial[Option[Int]] + .withFallback(Option.empty[Int]) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Some(10)) + Option + .empty[String] + .intoPartial[Option[Int]] + .withFallback(Option(20)) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Some(20)) + Option + .empty[String] + .intoPartial[Option[Int]] + .withFallback(Option.empty[Int]) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(None) + + Nested("10") + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(20)) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Nested(Some(20))) + Nested(Option("10")) + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(Option(20))) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Nested(Some(20))) + Nested(Option("10")) + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(Option.empty[Int])) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Nested(Some(10))) + Nested(Option.empty[String]) + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(Option(20))) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Nested(Some(20))) + Nested(Option.empty[String]) + .intoPartial[Nested[Option[Int]]] + .withFallback(Nested(Option.empty[Int])) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform + .asOption ==> Some(Nested(None)) + } + } +} diff --git a/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerMergingSpec.scala b/chimney/src/test/scala/io/scalaland/chimney/TotalMergingProductSpec.scala similarity index 99% rename from chimney/src/test/scala/io/scalaland/chimney/TotalTransformerMergingSpec.scala rename to chimney/src/test/scala/io/scalaland/chimney/TotalMergingProductSpec.scala index 0d400dd08..8c5433e83 100644 --- a/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerMergingSpec.scala +++ b/chimney/src/test/scala/io/scalaland/chimney/TotalMergingProductSpec.scala @@ -3,7 +3,7 @@ package io.scalaland.chimney import io.scalaland.chimney.dsl.* import io.scalaland.chimney.fixtures.* -class TotalTransformerMergingSpec extends ChimneySpec { +class TotalMergingProductSpec extends ChimneySpec { group("setting .withFallback(fallbackValue)") { diff --git a/chimney/src/test/scala/io/scalaland/chimney/TotalMergingStdLibSpec.scala b/chimney/src/test/scala/io/scalaland/chimney/TotalMergingStdLibSpec.scala new file mode 100644 index 000000000..89c2fd07c --- /dev/null +++ b/chimney/src/test/scala/io/scalaland/chimney/TotalMergingStdLibSpec.scala @@ -0,0 +1,233 @@ +package io.scalaland.chimney + +import io.scalaland.chimney.dsl.* +import io.scalaland.chimney.fixtures.* +import io.scalaland.chimney.Transformer + +class TotalMergingStdLibSpec extends ChimneySpec { + + group("setting .withFallback(fallbackValue)") { + + test("should use only source Option when no merging strategy is enabled") { + import merges.Nested + + implicit val i2s: Transformer[Int, String] = _.toString + + 10 + .into[Option[String]] + .withFallback("fallback") + .transform ==> Some("10") + Option(10) + .into[Option[String]] + .withFallback(Option("fallback")) + .transform ==> Some("10") + Option(10) + .into[Option[String]] + .withFallback(Option.empty[String]) + .transform ==> Some("10") + Option + .empty[Int] + .into[Option[String]] + .withFallback(Option("fallback")) + .transform ==> None + Option + .empty[Int] + .into[Option[String]] + .withFallback(Option.empty[String]) + .transform ==> None + + Nested(10) + .into[Nested[Option[String]]] + .withFallback(Nested("fallback")) + .transform ==> Nested(Some("10")) + Nested(Option(10)) + .into[Nested[Option[String]]] + .withFallback(Nested(Option("fallback"))) + .transform ==> Nested(Some("10")) + Nested(Option(10)) + .into[Nested[Option[String]]] + .withFallback(Nested(Option.empty[String])) + .transform ==> Nested(Some("10")) + Nested(Option.empty[Int]) + .into[Nested[Option[String]]] + .withFallback(Nested(Option("fallback"))) + .transform ==> Nested(None) + Nested(Option.empty[Int]) + .into[Nested[Option[String]]] + .withFallback(Nested(Option.empty[String])) + .transform ==> Nested(None) + } + } + + group("setting .withFallbackFrom(selectorFrom)(fallbackValue)") { + + test("should use only source Option when no merging strategy is enabled") { + import merges.Nested + + implicit val i2s: Transformer[Int, String] = _.toString + + Nested(10) + .into[Nested[Option[String]]] + .withFallbackFrom(_.value)("fallback") + .transform ==> Nested(Some("10")) + Nested(Option(10)) + .into[Nested[Option[String]]] + .withFallbackFrom(_.value)(Option("fallback")) + .transform ==> Nested(Some("10")) + Nested(Option(10)) + .into[Nested[Option[String]]] + .withFallbackFrom(_.value)(Option.empty[String]) + .transform ==> Nested(Some("10")) + Nested(Option.empty[Int]) + .into[Nested[Option[String]]] + .withFallbackFrom(_.value)(Option("fallback")) + .transform ==> Nested(None) + Nested(Option.empty[Int]) + .into[Nested[Option[String]]] + .withFallbackFrom(_.value)(Option.empty[String]) + .transform ==> Nested(None) + + Nested(Nested(10)) + .into[Nested[Nested[Option[String]]]] + .withFallbackFrom(_.value)(Nested("fallback")) + .transform ==> Nested(Nested(Some("10"))) + Nested(Nested(Option(10))) + .into[Nested[Nested[Option[String]]]] + .withFallbackFrom(_.value)(Nested(Option("fallback"))) + .transform ==> Nested(Nested(Some("10"))) + Nested(Nested(Option(10))) + .into[Nested[Nested[Option[String]]]] + .withFallbackFrom(_.value)(Nested(Option.empty[String])) + .transform ==> Nested(Nested(Some("10"))) + Nested(Nested(Option.empty[Int])) + .into[Nested[Nested[Option[String]]]] + .withFallbackFrom(_.value)(Nested(Option("fallback"))) + .transform ==> Nested(Nested(None)) + Nested(Nested(Option.empty[Int])) + .into[Nested[Nested[Option[String]]]] + .withFallbackFrom(_.value)(Nested(Option.empty[String])) + .transform ==> Nested(Nested(None)) + } + } + + group("flag .enableOptionFallbackMerge(SourceOrElseFallback)") { + + test("should merge Options from source to fallback when SourceOrElseFallback strategy is enabled") { + import merges.Nested + + implicit val i2s: Transformer[Int, String] = _.toString + + 10.into[Option[String]] + .withFallback("fallback") + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Some("10") + Option(10) + .into[Option[String]] + .withFallback(Option("fallback")) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Some("10") + Option(10) + .into[Option[String]] + .withFallback(Option.empty[String]) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Some("10") + Option + .empty[Int] + .into[Option[String]] + .withFallback(Option("fallback")) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Some("fallback") + Option + .empty[Int] + .into[Option[String]] + .withFallback(Option.empty[String]) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> None + + Nested(10) + .into[Nested[Option[String]]] + .withFallback(Nested("fallback")) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Nested(Some("10")) + Nested(Option(10)) + .into[Nested[Option[String]]] + .withFallback(Nested(Option("fallback"))) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Nested(Some("10")) + Nested(Option(10)) + .into[Nested[Option[String]]] + .withFallback(Nested(Option.empty[String])) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Nested(Some("10")) + Nested(Option.empty[Int]) + .into[Nested[Option[String]]] + .withFallback(Nested(Option("fallback"))) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Nested(Some("fallback")) + Nested(Option.empty[Int]) + .into[Nested[Option[String]]] + .withFallback(Nested(Option.empty[String])) + .enableOptionFallbackMerge(SourceOrElseFallback) + .transform ==> Nested(None) + } + + test("should merge Options from fallback to source when FallbackOrElseSource strategy is enabled") { + import merges.Nested + + implicit val i2s: Transformer[Int, String] = _.toString + + 10.into[Option[String]] + .withFallback("fallback") + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Some("fallback") + Option(10) + .into[Option[String]] + .withFallback(Option("fallback")) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Some("fallback") + Option(10) + .into[Option[String]] + .withFallback(Option.empty[String]) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Some("10") + Option + .empty[Int] + .into[Option[String]] + .withFallback(Option("fallback")) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Some("fallback") + Option + .empty[Int] + .into[Option[String]] + .withFallback(Option.empty[String]) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> None + + Nested(10) + .into[Nested[Option[String]]] + .withFallback(Nested("fallback")) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Nested(Some("fallback")) + Nested(Option(10)) + .into[Nested[Option[String]]] + .withFallback(Nested(Option("fallback"))) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Nested(Some("fallback")) + Nested(Option(10)) + .into[Nested[Option[String]]] + .withFallback(Nested(Option.empty[String])) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Nested(Some("10")) + Nested(Option.empty[Int]) + .into[Nested[Option[String]]] + .withFallback(Nested(Option("fallback"))) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Nested(Some("fallback")) + Nested(Option.empty[Int]) + .into[Nested[Option[String]]] + .withFallback(Nested(Option.empty[String])) + .enableOptionFallbackMerge(FallbackOrElseSource) + .transform ==> Nested(None) + } + } +}