From a6027ddd857a4ff37b994e5bc6718f36a88c7b2d Mon Sep 17 00:00:00 2001 From: Aleksander Rainko Date: Sat, 18 Nov 2023 20:52:07 +0100 Subject: [PATCH] add tests for error reporting and logger's log level --- .../arainko/ducktape/internal/Logger.scala | 2 +- .../total/DerivedTransformerSuite.scala | 2 +- .../ducktape/total/ErrorReportingSuite.scala | 133 +++++++++++++++++- .../arainko/ducktape/total/LoggerSuite.scala | 11 ++ 4 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/LoggerSuite.scala diff --git a/ducktapeNext/src/main/scala/io/github/arainko/ducktape/internal/Logger.scala b/ducktapeNext/src/main/scala/io/github/arainko/ducktape/internal/Logger.scala index 270beca9..45279e10 100644 --- a/ducktapeNext/src/main/scala/io/github/arainko/ducktape/internal/Logger.scala +++ b/ducktapeNext/src/main/scala/io/github/arainko/ducktape/internal/Logger.scala @@ -9,7 +9,7 @@ import scala.annotation.nowarn private[ducktape] object Logger { // Logger Config - private transparent inline def level = Level.Debug + private[ducktape] transparent inline given level: Level = Level.Off private val output = Output.StdOut @nowarn private def filter(msg: String, meta: Metainformation) = meta.contains("DeprecatedConfig") diff --git a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/DerivedTransformerSuite.scala b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/DerivedTransformerSuite.scala index 590300bf..9b9f7029 100644 --- a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/DerivedTransformerSuite.scala +++ b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/DerivedTransformerSuite.scala @@ -372,6 +372,6 @@ class DerivedTransformerSuite extends DucktapeSuite { } test("derivation fails when going from a sum with more cases to a sum with less cases") { - assertFailsToCompileWith("MoreCases.Case3.to[LessCases]")("No child named 'Case4 found in io.github.arainko.ducktape.total.DerivedTransformerSuite.LessCases @ MoreCases.at[io.github.arainko.ducktape.total.DerivedTransformerSuite.MoreCases.Case4]") + assertFailsToCompileWith("MoreCases.Case3.to[LessCases]")("No child named 'Case4' found in io.github.arainko.ducktape.total.DerivedTransformerSuite.LessCases @ MoreCases.at[io.github.arainko.ducktape.total.DerivedTransformerSuite.MoreCases.Case4]") } } diff --git a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/ErrorReportingSuite.scala b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/ErrorReportingSuite.scala index b08d2a65..38c223b1 100644 --- a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/ErrorReportingSuite.scala +++ b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/ErrorReportingSuite.scala @@ -1,7 +1,136 @@ package io.github.arainko.ducktape.total -import io.github.arainko.ducktape.DucktapeSuite +import io.github.arainko.ducktape.* +import scala.annotation.nowarn class ErrorReportingSuite extends DucktapeSuite { - + test("errors for all missing fields are reported at once") { + final case class SourceToplevel1(level1: SourceLevel1) + final case class SourceLevel1(level2: SourceLevel2) + final case class SourceLevel2(int: Int) + + final case class DestToplevel1(level1: DestLevel1) + final case class DestLevel1(level2: DestLevel2, level1Extra: Int, level2Extra: String) + final case class DestLevel2(int: Int, level3extra: String) + + def source: SourceToplevel1 = ??? + + assertFailsToCompileWith { + """ + source.to[DestToplevel1] + """ + } { + """No field 'level2Extra' found in SourceLevel1 @ DestToplevel1.level1.level2Extra + |No field 'level1Extra' found in SourceLevel1 @ DestToplevel1.level1.level1Extra + |No field 'level3extra' found in SourceLevel2 @ DestToplevel1.level1.level2.level3extra""".stripMargin + } + }: @nowarn("msg=unused local definition") + + test("errors for all missing coproduct cases are reported at once") { + enum SourceToplevel1 { + case Level1(level2: SourceLevel2) + case Level1Extra1 + case Level1Extra2 + } + + enum SourceLevel2 { + case Level2(level3: SourceLevel3) + case Level2Extra1 + case Level2Extra2 + } + + enum SourceLevel3 { + case One + case Two + case Extra + } + + enum DestToplevel1 { + case Level1(level2: DestLevel2) + } + + enum DestLevel2 { + case Level2(level3: DestLevel3) + } + + enum DestLevel3 { + case One + case Two + } + + def source: SourceToplevel1 = ??? + + assertFailsToCompileWith { + """ + source.to[DestToplevel1] + """ + } { + """No child named 'Level1Extra2' found in DestToplevel1 @ SourceToplevel1.at[SourceToplevel1.Level1Extra2] + |No child named 'Level1Extra1' found in DestToplevel1 @ SourceToplevel1.at[SourceToplevel1.Level1Extra1] + |No child named 'Level2Extra2' found in DestLevel2 @ SourceToplevel1.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2Extra2] + |No child named 'Level2Extra1' found in DestLevel2 @ SourceToplevel1.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2Extra1] + |No child named 'Extra' found in DestLevel3 @ SourceToplevel1.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.Extra]""".stripMargin + } + }: @nowarn("msg=unused local definition") + + test("product configurations should fail when using a path component that doesn't belong to the actual transformation path") { + final case class SourceToplevel1(level1: SourceLevel1) + final case class SourceLevel1(level2: SourceLevel2) + final case class SourceLevel2(int: Int) + + final case class DestToplevel1(level1: DestLevel1) + final case class DestLevel1(level2: DestLevel2) + final case class DestLevel2(int: Int, level3extra: String) + + def source: SourceToplevel1 = ??? + + assertFailsToCompileWith { + """ + source.into[DestToplevel1].transform(Field.const(_.level1.level2.int.toByte.toByte.toByte, 1.toByte)) + """ + }( + "The path segment 'toByte' is not valid as it is not a field of a case class or an argument of a function @ DestToplevel1.level1.level2.int", + "No field 'level3extra' found in SourceLevel2 @ DestToplevel1.level1.level2.level3extra" + ) + }: @nowarn("msg=unused local definition") + + test("coproduct configurations fail when using a case component that isn't a subtype") { + enum SourceToplevel1 { + case Level1(level2: SourceLevel2) + } + + enum SourceLevel2 { + case Level2(level3: SourceLevel3) + } + + enum SourceLevel3 { + case One + case Two + case Extra + } + + enum DestToplevel1 { + case Level1(level2: DestLevel2) + } + + enum DestLevel2 { + case Level2(level3: DestLevel3) + } + + enum DestLevel3 { + case One + case Two + } + + def source: SourceToplevel1 = ??? + + assertFailsToCompileWith { + """ + source.into[DestToplevel1].transform(Case.const(_.at[SourceToplevel1.Level1].level2.at[SourceLevel2], 123)) + """ + }( + "No child named 'Extra' found in DestLevel3 @ SourceToplevel1.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.Extra]", + "'at[SourceLevel2]' is not a valid case accessor @ SourceToplevel1.at[SourceToplevel1.Level1].level2" + ) + }: @nowarn("msg=unused local definition") } diff --git a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/LoggerSuite.scala b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/LoggerSuite.scala new file mode 100644 index 00000000..24d89e13 --- /dev/null +++ b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/LoggerSuite.scala @@ -0,0 +1,11 @@ +package io.github.arainko.ducktape + +import io.github.arainko.ducktape.DucktapeSuite +import io.github.arainko.ducktape.internal.* + +class LoggerSuite extends DucktapeSuite { + test("log level should be Off") { + val result = compiletime.testing.typeChecks("""val level: Logger.Level.Off.type = summon[Logger.Level]""") + assertEquals(result, true, "Logger's log level should be set to Off to turn all log statements into ()") + } +}