diff --git a/avro/src/main/scala/magnolify/avro/AvroType.scala b/avro/src/main/scala/magnolify/avro/AvroType.scala index e63ed1e65..68697c832 100644 --- a/avro/src/main/scala/magnolify/avro/AvroType.scala +++ b/avro/src/main/scala/magnolify/avro/AvroType.scala @@ -26,7 +26,7 @@ import org.apache.avro.generic.GenericData.EnumSymbol import org.apache.avro.generic._ import org.apache.avro.{JsonProperties, LogicalType, LogicalTypes, Schema} -import scala.annotation.{implicitNotFound, nowarn, StaticAnnotation} +import scala.annotation.{implicitNotFound, nowarn} import scala.collection.concurrent import scala.reflect.ClassTag import scala.jdk.CollectionConverters._ diff --git a/avro/src/test/scala/magnolify/avro/test/AvroTypeSuite.scala b/avro/src/test/scala/magnolify/avro/AvroTypeSuite.scala similarity index 71% rename from avro/src/test/scala/magnolify/avro/test/AvroTypeSuite.scala rename to avro/src/test/scala/magnolify/avro/AvroTypeSuite.scala index af9ef84c6..2561c38f3 100644 --- a/avro/src/test/scala/magnolify/avro/test/AvroTypeSuite.scala +++ b/avro/src/test/scala/magnolify/avro/AvroTypeSuite.scala @@ -14,38 +14,45 @@ * limitations under the License. */ -package magnolify.avro.test +package magnolify.avro -import java.io.{ByteArrayInputStream, ByteArrayOutputStream} -import java.net.URI -import java.nio.ByteBuffer -import java.time.format.DateTimeFormatter -import java.time.{Duration, Instant, LocalDate, LocalDateTime, LocalTime} -import java.util.UUID import cats._ import com.fasterxml.jackson.core.JsonFactory -import com.fasterxml.jackson.databind.{JsonNode, ObjectMapper} +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper import magnolify.avro._ import magnolify.avro.unsafe._ import magnolify.cats.auto._ +import magnolify.cats.TestEq._ import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary._ import magnolify.shared.CaseMapper +import magnolify.shared.TestEnumType._ import magnolify.test.Simple._ -import magnolify.test.Time._ import magnolify.test._ import org.apache.avro.Schema -import org.apache.avro.generic.{ - GenericDatumReader, - GenericDatumWriter, - GenericRecord, - GenericRecordBuilder -} -import org.apache.avro.io.{DecoderFactory, EncoderFactory} +import org.apache.avro.generic.GenericDatumReader +import org.apache.avro.generic.GenericDatumWriter +import org.apache.avro.generic.GenericRecord +import org.apache.avro.generic.GenericRecordBuilder +import org.apache.avro.io.DecoderFactory +import org.apache.avro.io.EncoderFactory import org.scalacheck._ +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.net.URI +import java.nio.ByteBuffer +import java.time.Duration +import java.time.Instant +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.format.DateTimeFormatter +import java.util.UUID +import scala.jdk.CollectionConverters._ import scala.reflect._ import scala.util.Try -import scala.jdk.CollectionConverters._ class AvroTypeSuite extends MagnolifySuite { private def test[T: Arbitrary: ClassTag](implicit @@ -98,6 +105,17 @@ class AvroTypeSuite extends MagnolifySuite { } } + implicit val arbBigDecimal: Arbitrary[BigDecimal] = + Arbitrary(Gen.chooseNum(0L, Long.MaxValue).map(BigDecimal(_, 0))) + implicit val arbCountryCode: Arbitrary[CountryCode] = Arbitrary( + Gen.oneOf("US", "UK", "CA", "MX").map(CountryCode(_)) + ) + implicit val afUri: AvroField[URI] = AvroField.from[String](URI.create)(_.toString) + implicit val afDuration: AvroField[Duration] = + AvroField.from[Long](Duration.ofMillis)(_.toMillis) + implicit val afCountryCode: AvroField[CountryCode] = + AvroField.fixed[CountryCode](2)(bs => CountryCode(new String(bs)))(cc => cc.code.getBytes) + test[Integers] test[Floats] test[Required] @@ -105,27 +123,12 @@ class AvroTypeSuite extends MagnolifySuite { test[Repeated] test[Nested] test[Unsafe] - - { - import Collections._ - test[Collections] - test[MoreCollections] - } - - { - import Enums._ - import UnsafeEnums._ - test[Enums] - test[UnsafeEnums] - } - - { - import Custom._ - implicit val afUri: AvroField[URI] = AvroField.from[String](URI.create)(_.toString) - implicit val afDuration: AvroField[Duration] = - AvroField.from[Long](Duration.ofMillis)(_.toMillis) - test[Custom] - } + test[Collections] + test[MoreCollections] + test[Enums] + test[UnsafeEnums] + test[Custom] + test[AvroTypes] test("AnyVal") { implicit val at: AvroType[HasValueClass] = AvroType[HasValueClass] @@ -138,12 +141,7 @@ class AvroTypeSuite extends MagnolifySuite { } { - implicit val eqByteArray: Eq[Array[Byte]] = Eq.by(_.toList) - test[AvroTypes] - } - - { - def f[T](r: GenericRecord): List[(String, Any)] = + def f(r: GenericRecord): List[(String, Any)] = r.get("m") .asInstanceOf[java.util.Map[CharSequence, Any]] .asScala @@ -158,50 +156,34 @@ class AvroTypeSuite extends MagnolifySuite { test[Logical] { - implicit val arbBigDecimal: Arbitrary[BigDecimal] = - Arbitrary(Gen.chooseNum(0L, Long.MaxValue).map(BigDecimal(_, 0))) - - { - import magnolify.avro.logical.micros._ - implicit val afBigDecimal: AvroField[BigDecimal] = AvroField.bigDecimal(19, 0) - test[LogicalMicros] - } + import magnolify.avro.logical.micros._ + test[LogicalMicros] test("MicrosLogicalTypes") { - import magnolify.avro.logical.micros._ - implicit val afBigDecimal: AvroField[BigDecimal] = AvroField.bigDecimal(19, 0) - val schema = AvroType[LogicalMicros].schema - assertLogicalType(schema, "bd", "decimal") assertLogicalType(schema, "i", "timestamp-micros") assertLogicalType(schema, "dt", "local-timestamp-micros", false) assertLogicalType(schema, "t", "time-micros") } + } - { - import magnolify.avro.logical.millis._ - implicit val afBigDecimal: AvroField[BigDecimal] = AvroField.bigDecimal(19, 0) - test[LogicalMillis] - } + { + import magnolify.avro.logical.millis._ + test[LogicalMillis] test("MilliLogicalTypes") { - import magnolify.avro.logical.millis._ - implicit val afBigDecimal: AvroField[BigDecimal] = AvroField.bigDecimal(19, 0) - val schema = AvroType[LogicalMillis].schema - assertLogicalType(schema, "bd", "decimal") assertLogicalType(schema, "i", "timestamp-millis") assertLogicalType(schema, "dt", "local-timestamp-millis", false) assertLogicalType(schema, "t", "time-millis") } + } - { - import magnolify.avro.logical.bigquery._ - test[LogicalBigQuery] - } + { + import magnolify.avro.logical.bigquery._ + test[LogicalBigQuery] test("BigQueryLogicalTypes") { - import magnolify.avro.logical.bigquery._ // `registerLogicalTypes()` is necessary to correctly parse a custom logical type from string. // if omitted, the returned string schema will be correct, but the logicalType field will be null. // this is unfortunately global mutable state @@ -215,21 +197,13 @@ class AvroTypeSuite extends MagnolifySuite { } } - { - implicit val arbCountryCode: Arbitrary[CountryCode] = Arbitrary( - Gen.oneOf("US", "UK", "CA", "MX").map(CountryCode(_)) - ) - implicit val afCountryCode: AvroField[CountryCode] = - AvroField.fixed[CountryCode](2)(bs => CountryCode(new String(bs)))(cc => cc.code.getBytes) - test[Fixed] - - test("FixedDoc") { - val at = ensureSerializable(AvroType[Fixed]) - val schema = at.schema.getField("countryCode").schema - assertEquals(schema.getName, "CountryCode") - assertEquals(schema.getNamespace, "magnolify.avro.test") - assertEquals(schema.getDoc, "Fixed with doc") - } + test[Fixed] + test("FixedDoc") { + val at = ensureSerializable(AvroType[Fixed]) + val schema = at.schema.getField("countryCode").schema + assertEquals(schema.getName, "CountryCode") + assertEquals(schema.getNamespace, "magnolify.avro") + assertEquals(schema.getDoc, "Fixed with doc") } test("AvroDoc") { @@ -253,10 +227,10 @@ class AvroTypeSuite extends MagnolifySuite { } testFail(AvroType[DoubleRecordDoc])( - "More than one @doc annotation: magnolify.avro.test.DoubleRecordDoc" + "More than one @doc annotation: magnolify.avro.DoubleRecordDoc" ) testFail(AvroType[DoubleFieldDoc])( - "More than one @doc annotation: magnolify.avro.test.DoubleFieldDoc#i" + "More than one @doc annotation: magnolify.avro.DoubleFieldDoc#i" ) test("EnumDoc") { @@ -264,52 +238,51 @@ class AvroTypeSuite extends MagnolifySuite { assertEquals(at.schema.getField("p").schema().getDoc, "Avro enum") } - test("DefaultInner") { + { import magnolify.avro.logical.bigquery._ - val at = ensureSerializable(AvroType[DefaultInner]) - assertEquals(at(new GenericRecordBuilder(at.schema).build()), DefaultInner()) - val inner = DefaultInner( - 2, - Some(2), - List(2, 2), - Map("b" -> 2), - JavaEnums.Color.GREEN, - ScalaEnums.Color.Green, - BigDecimal(222.222), - UUID.fromString("22223333-abcd-abcd-abcd-222233334444"), - Instant.ofEpochSecond(22334455L), - LocalDate.ofEpochDay(2233), - LocalTime.of(2, 3, 4), - LocalDateTime.of(2002, 3, 4, 5, 6, 7) - ) - assertEquals(at(at(inner)), inner) - } + test("DefaultInner") { + val at = ensureSerializable(AvroType[DefaultInner]) + assertEquals(at(new GenericRecordBuilder(at.schema).build()), DefaultInner()) + val inner = DefaultInner( + 2, + Some(2), + List(2, 2), + Map("b" -> 2), + JavaEnums.Color.GREEN, + ScalaEnums.Color.Green, + BigDecimal(222.222), + UUID.fromString("22223333-abcd-abcd-abcd-222233334444"), + Instant.ofEpochSecond(22334455L), + LocalDate.ofEpochDay(2233), + LocalTime.of(2, 3, 4), + LocalDateTime.of(2002, 3, 4, 5, 6, 7) + ) + assertEquals(at(at(inner)), inner) + } - test("DefaultOuter") { - import magnolify.avro.logical.bigquery._ - val at = ensureSerializable(AvroType[DefaultOuter]) - assertEquals(at(new GenericRecordBuilder(at.schema).build()), DefaultOuter()) - val inner = DefaultInner( - 3, - Some(3), - List(3, 3), - Map("c" -> 3), - JavaEnums.Color.BLUE, - ScalaEnums.Color.Blue, - BigDecimal(333.333), - UUID.fromString("33334444-abcd-abcd-abcd-333344445555"), - Instant.ofEpochSecond(33445566L), - LocalDate.ofEpochDay(3344), - LocalTime.of(3, 4, 5), - LocalDateTime.of(2003, 4, 5, 6, 7, 8) - ) - val outer = DefaultOuter(inner, Some(inner)) - assertEquals(at(at(outer)), outer) + test("DefaultOuter") { + val at = ensureSerializable(AvroType[DefaultOuter]) + assertEquals(at(new GenericRecordBuilder(at.schema).build()), DefaultOuter()) + val inner = DefaultInner( + 3, + Some(3), + List(3, 3), + Map("c" -> 3), + JavaEnums.Color.BLUE, + ScalaEnums.Color.Blue, + BigDecimal(333.333), + UUID.fromString("33334444-abcd-abcd-abcd-333344445555"), + Instant.ofEpochSecond(33445566L), + LocalDate.ofEpochDay(3344), + LocalTime.of(3, 4, 5), + LocalDateTime.of(2003, 4, 5, 6, 7, 8) + ) + val outer = DefaultOuter(inner, Some(inner)) + assertEquals(at(at(outer)), outer) + } } - testFail(AvroType[SomeDefault])( - "Option[T] can only default to None" - ) + testFail(AvroType[SomeDefault])("Option[T] can only default to None") { implicit val at: AvroType[LowerCamel] = AvroType[LowerCamel](CaseMapper(_.toUpperCase)) @@ -331,7 +304,7 @@ class AvroTypeSuite extends MagnolifySuite { } test("BigDecimal") { - import magnolify.avro.logical.bigquery._ + implicit val afBigDecimal: AvroField[BigDecimal] = AvroField.bigDecimal(38, 9) val at: AvroType[BigDec] = AvroType[BigDec] val bigInt = "1234567890123456789012345678901234567890" @@ -362,8 +335,8 @@ case class MapPrimitive(m: Map[String, Int]) case class MapNested(m: Map[String, Nested]) case class Logical(u: UUID, d: LocalDate) -case class LogicalMicros(bd: BigDecimal, i: Instant, t: LocalTime, dt: LocalDateTime) -case class LogicalMillis(bd: BigDecimal, i: Instant, t: LocalTime, dt: LocalDateTime) +case class LogicalMicros(i: Instant, t: LocalTime, dt: LocalDateTime) +case class LogicalMillis(i: Instant, t: LocalTime, dt: LocalDateTime) case class LogicalBigQuery(bd: BigDecimal, i: Instant, t: LocalTime, dt: LocalDateTime) case class BigDec(bd: BigDecimal) diff --git a/avro/src/test/scala/magnolify/avro/test/TestData.scala b/avro/src/test/scala/magnolify/avro/TestData.scala similarity index 100% rename from avro/src/test/scala/magnolify/avro/test/TestData.scala rename to avro/src/test/scala/magnolify/avro/TestData.scala diff --git a/bigquery/src/test/scala/magnolify/bigquery/test/TableRowTypeSuite.scala b/bigquery/src/test/scala/magnolify/bigquery/TableRowTypeSuite.scala similarity index 85% rename from bigquery/src/test/scala/magnolify/bigquery/test/TableRowTypeSuite.scala rename to bigquery/src/test/scala/magnolify/bigquery/TableRowTypeSuite.scala index beef2b386..0eba35fca 100644 --- a/bigquery/src/test/scala/magnolify/bigquery/test/TableRowTypeSuite.scala +++ b/bigquery/src/test/scala/magnolify/bigquery/TableRowTypeSuite.scala @@ -14,27 +14,29 @@ * limitations under the License. */ -package magnolify.bigquery.test - -import java.net.URI -import java.time._ -import java.time.format.DateTimeFormatter +package magnolify.bigquery import cats._ -import com.fasterxml.jackson.databind.{ObjectMapper, SerializationFeature} +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.SerializationFeature import com.google.api.services.bigquery.model.TableRow import magnolify.bigquery._ import magnolify.bigquery.unsafe._ import magnolify.cats.auto._ +import magnolify.cats.TestEq._ import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary._ import magnolify.shared.CaseMapper +import magnolify.shared.TestEnumType._ import magnolify.test.Simple._ -import magnolify.test.Time._ import magnolify.test._ import org.scalacheck._ -import scala.reflect._ +import java.net.URI +import java.time._ +import java.time.format.DateTimeFormatter import scala.jdk.CollectionConverters._ +import scala.reflect._ class TableRowTypeSuite extends MagnolifySuite { private val mapper = new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS) @@ -52,40 +54,32 @@ class TableRowTypeSuite extends MagnolifySuite { } } - test[Integers] - - { - // `TableRow` reserves field `f` - implicit val trt = TableRowType[Floats](CaseMapper(s => if (s == "f") "float" else s)) - test[Floats] - } + implicit val arbBigDecimal: Arbitrary[BigDecimal] = + Arbitrary(Gen.chooseNum(0, Int.MaxValue).map(BigDecimal(_))) + // `TableRow` reserves field `f` + implicit val trtFloats: TableRowType[Floats] = + TableRowType[Floats](CaseMapper(s => if (s == "f") "float" else s)) + implicit val trfUri: TableRowField[URI] = TableRowField.from[String](URI.create)(_.toString) + implicit val trfDuration: TableRowField[Duration] = + TableRowField.from[Long](Duration.ofMillis)(_.toMillis) + test[Integers] + test[Floats] test[Required] test[Nullable] test[Repeated] test[Nested] test[Unsafe] - { - import Collections._ - test[Collections] - test[MoreCollections] - } + test[Collections] + test[MoreCollections] - { - import Enums._ - import UnsafeEnums._ - test[Enums] - test[UnsafeEnums] - } + test[Enums] + test[UnsafeEnums] - { - import Custom._ - implicit val trfUri: TableRowField[URI] = TableRowField.from[String](URI.create)(_.toString) - implicit val trfDuration: TableRowField[Duration] = - TableRowField.from[Long](Duration.ofMillis)(_.toMillis) - test[Custom] - } + test[Custom] + + test[BigQueryTypes] test("AnyVal") { implicit val trt: TableRowType[HasValueClass] = TableRowType[HasValueClass] @@ -97,12 +91,6 @@ class TableRowTypeSuite extends MagnolifySuite { assert(record.get("vc") == "String") } - { - implicit val arbBigDecimal: Arbitrary[BigDecimal] = - Arbitrary(Gen.chooseNum(0, Int.MaxValue).map(BigDecimal(_))) - test[BigQueryTypes] - } - test("BigDecimal") { val at: TableRowType[BigDec] = TableRowType[BigDec] val msg1 = "requirement failed: " + @@ -137,10 +125,10 @@ class TableRowTypeSuite extends MagnolifySuite { } testFail(TableRowType[DoubleRecordDesc])( - "More than one @description annotation: magnolify.bigquery.test.DoubleRecordDesc" + "More than one @description annotation: magnolify.bigquery.DoubleRecordDesc" ) testFail(TableRowType[DoubleFieldDesc])( - "More than one @description annotation: magnolify.bigquery.test.DoubleFieldDesc#i" + "More than one @description annotation: magnolify.bigquery.DoubleFieldDesc#i" ) test("DefaultInner") { diff --git a/bigquery/src/test/scala/magnolify/bigquery/test/TestData.scala b/bigquery/src/test/scala/magnolify/bigquery/TestData.scala similarity index 98% rename from bigquery/src/test/scala/magnolify/bigquery/test/TestData.scala rename to bigquery/src/test/scala/magnolify/bigquery/TestData.scala index afdad8f6f..d08f4fdac 100644 --- a/bigquery/src/test/scala/magnolify/bigquery/test/TestData.scala +++ b/bigquery/src/test/scala/magnolify/bigquery/TestData.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.bigquery.test +package magnolify.bigquery import java.io.File import java.time._ diff --git a/bigtable/src/test/scala/magnolify/bigtable/test/BigtableTypeSuite.scala b/bigtable/src/test/scala/magnolify/bigtable/BigtableTypeSuite.scala similarity index 81% rename from bigtable/src/test/scala/magnolify/bigtable/test/BigtableTypeSuite.scala rename to bigtable/src/test/scala/magnolify/bigtable/BigtableTypeSuite.scala index 500c8f6ad..e224fcf88 100644 --- a/bigtable/src/test/scala/magnolify/bigtable/test/BigtableTypeSuite.scala +++ b/bigtable/src/test/scala/magnolify/bigtable/BigtableTypeSuite.scala @@ -14,23 +14,25 @@ * limitations under the License. */ -package magnolify.bigtable.test - -import java.net.URI -import java.time.Duration -import java.util.UUID +package magnolify.bigtable import cats._ import com.google.bigtable.v2.Row import com.google.protobuf.ByteString import magnolify.bigtable._ import magnolify.cats.auto._ +import magnolify.cats.TestEq._ import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary._ import magnolify.shared.CaseMapper +import magnolify.shared.TestEnumType._ import magnolify.test.Simple._ import magnolify.test._ import org.scalacheck._ +import java.net.URI +import java.time.Duration +import java.util.UUID import scala.reflect._ class BigtableTypeSuite extends MagnolifySuite { @@ -52,33 +54,26 @@ class BigtableTypeSuite extends MagnolifySuite { } } + implicit val arbByteString: Arbitrary[ByteString] = + Arbitrary(Gen.alphaNumStr.map(ByteString.copyFromUtf8)) + implicit val eqByteString: Eq[ByteString] = Eq.instance(_ == _) + implicit val eqByteArray: Eq[Array[Byte]] = Eq.by(_.toList) + implicit val btfUri: BigtableField[URI] = + BigtableField.from[String](x => URI.create(x))(_.toString) + implicit val btfDuration: BigtableField[Duration] = + BigtableField.from[Long](Duration.ofMillis)(_.toMillis) + test[Numbers] test[Required] test[Nullable] test[Repeated] test[BigtableNested] - - { - import Collections._ - test[Collections] - test[MoreCollections] - } - - { - import Enums._ - import UnsafeEnums._ - test[Enums] - test[UnsafeEnums] - } - - { - import Custom._ - implicit val btfUri: BigtableField[URI] = - BigtableField.from[String](x => URI.create(x))(_.toString) - implicit val btfDuration: BigtableField[Duration] = - BigtableField.from[Long](Duration.ofMillis)(_.toMillis) - test[Custom] - } + test[Collections] + test[MoreCollections] + test[Enums] + test[UnsafeEnums] + test[Custom] + test[BigtableTypes] test("AnyVal") { implicit val btt: BigtableType[HasValueClass] = BigtableType[HasValueClass] @@ -88,14 +83,6 @@ class BigtableTypeSuite extends MagnolifySuite { assert(records.head.getSetCell.getValue.toStringUtf8 == "String") } - { - implicit val arbByteString: Arbitrary[ByteString] = - Arbitrary(Gen.alphaNumStr.map(ByteString.copyFromUtf8)) - implicit val eqByteString: Eq[ByteString] = Eq.instance(_ == _) - implicit val eqByteArray: Eq[Array[Byte]] = Eq.by(_.toList) - test[BigtableTypes] - } - test("DefaultInner") { val bt = ensureSerializable(BigtableType[DefaultInner]) assertEquals(bt(Row.getDefaultInstance, "cf"), DefaultInner()) diff --git a/build.sbt b/build.sbt index caf854c7e..c686ec5f8 100644 --- a/build.sbt +++ b/build.sbt @@ -66,7 +66,6 @@ ThisBuild / tpolecatDevModeOptions ~= { opts => ScalacOptions.privateOption("retain-trees", _ >= V3_0_0), // allow some nested auto derivation ScalacOptions.advancedOption("max-inlines", List("64"), _ >= V3_0_0), - ScalacOptions.other("-target:jvm-1.8"), ScalacOptions.warnOption("macros:after", _.isBetween(V2_13_0, V3_0_0)), ScalacOptions.privateWarnOption("macros:after", _.isBetween(V2_12_0, V2_13_0)), ScalacOptions.privateBackendParallelism(), @@ -279,7 +278,7 @@ lazy val cats: Project = project ) .dependsOn( shared, - scalacheck % Test, + scalacheck % "test->test", test % "test->test" ) @@ -295,7 +294,7 @@ lazy val guava: Project = project ) .dependsOn( shared, - scalacheck % Test, + scalacheck % "test->test", test % "test->test" ) @@ -340,8 +339,8 @@ lazy val avro: Project = project ) .dependsOn( shared, - cats % Test, - scalacheck % Test, + cats % "test->test", + scalacheck % "test->test", test % "test->test" ) @@ -358,8 +357,8 @@ lazy val bigquery: Project = project ) .dependsOn( shared, - cats % Test, - scalacheck % Test, + cats % "test->test", + scalacheck % "test->test", test % "test->test" ) @@ -375,8 +374,8 @@ lazy val bigtable: Project = project ) .dependsOn( shared, - cats % Test, - scalacheck % Test, + cats % "test->test", + scalacheck % "test->test", test % "test->test" ) @@ -392,8 +391,8 @@ lazy val datastore: Project = project ) .dependsOn( shared, - cats % Test, - scalacheck % Test, + cats % "test->test", + scalacheck % "test->test", test % "test->test" ) @@ -412,8 +411,8 @@ lazy val parquet: Project = project .dependsOn( shared, avro % Test, - cats % Test, - scalacheck % Test, + cats % "test->test", + scalacheck % "test->test", test % "test->test" ) @@ -427,8 +426,8 @@ lazy val protobuf: Project = project ) .dependsOn( shared, - cats % Test, - scalacheck % Test, + cats % "test->test", + scalacheck % "test->test", test % "test->test" ) @@ -464,8 +463,8 @@ lazy val tensorflow: Project = project ) .dependsOn( shared, - cats % Test, - scalacheck % Test, + cats % "test->test", + scalacheck % "test->test", test % "test->test" ) @@ -481,8 +480,8 @@ lazy val neo4j: Project = project ) .dependsOn( shared, - cats % Test, - scalacheck % Test, + cats % "test->test", + scalacheck % "test->test", test % "test->test" ) diff --git a/cats/src/test/scala/magnolify/cats/test/BandDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala similarity index 97% rename from cats/src/test/scala/magnolify/cats/test/BandDerivationSuite.scala rename to cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala index 573271172..8587dc4cb 100644 --- a/cats/src/test/scala/magnolify/cats/test/BandDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.cats.test +package magnolify.cats import cats._ import cats.kernel.Band diff --git a/cats/src/test/scala/magnolify/cats/test/CommutativeGroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala similarity index 98% rename from cats/src/test/scala/magnolify/cats/test/CommutativeGroupDerivationSuite.scala rename to cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala index 563714536..6a1b9fedc 100644 --- a/cats/src/test/scala/magnolify/cats/test/CommutativeGroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.cats.test +package magnolify.cats import cats._ import cats.kernel.CommutativeGroup diff --git a/cats/src/test/scala/magnolify/cats/test/CommutativeMonoidDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala similarity index 98% rename from cats/src/test/scala/magnolify/cats/test/CommutativeMonoidDerivationSuite.scala rename to cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala index 2aafe1393..66527a534 100644 --- a/cats/src/test/scala/magnolify/cats/test/CommutativeMonoidDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.cats.test +package magnolify.cats import cats._ import cats.kernel.CommutativeMonoid diff --git a/cats/src/test/scala/magnolify/cats/test/CommutativeSemigroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala similarity index 98% rename from cats/src/test/scala/magnolify/cats/test/CommutativeSemigroupDerivationSuite.scala rename to cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala index 3db744930..a1ccd5f74 100644 --- a/cats/src/test/scala/magnolify/cats/test/CommutativeSemigroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.cats.test +package magnolify.cats import cats._ import cats.kernel.CommutativeSemigroup diff --git a/cats/src/test/scala/magnolify/cats/test/EqDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala similarity index 81% rename from cats/src/test/scala/magnolify/cats/test/EqDerivationSuite.scala rename to cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala index 2b5374120..5fe7eec68 100644 --- a/cats/src/test/scala/magnolify/cats/test/EqDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala @@ -14,12 +14,18 @@ * limitations under the License. */ -package magnolify.cats.test +package magnolify.cats +import cats.Eq._ import cats._ import cats.kernel.laws.discipline._ import magnolify.cats.auto._ +import magnolify.cats.TestEq.eqArray +import magnolify.cats.TestEq.eqDuration +import magnolify.cats.TestEq.eqUri import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary._ +import magnolify.scalacheck.TestCogen._ import magnolify.test.ADT._ import magnolify.test.Simple._ import magnolify.test._ @@ -38,16 +44,8 @@ class EqDerivationSuite extends MagnolifySuite { test[Nullable] test[Repeated] test[Nested] - - { - implicit val eqArray: Eq[Array[Int]] = Eq.by(_.toList) - test[Collections] - } - - { - import Custom._ - test[Custom] - } + test[Collections] + test[Custom] test[Node] test[GNode[Int]] diff --git a/cats/src/test/scala/magnolify/cats/test/GroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala similarity index 98% rename from cats/src/test/scala/magnolify/cats/test/GroupDerivationSuite.scala rename to cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala index 1044d28f1..5035af0ed 100644 --- a/cats/src/test/scala/magnolify/cats/test/GroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.cats.test +package magnolify.cats import cats._ import cats.kernel.laws.discipline._ diff --git a/cats/src/test/scala/magnolify/cats/test/HashDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala similarity index 67% rename from cats/src/test/scala/magnolify/cats/test/HashDerivationSuite.scala rename to cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala index cccce93cf..bdbb6d62e 100644 --- a/cats/src/test/scala/magnolify/cats/test/HashDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.cats.test +package magnolify.cats import cats._ import cats.kernel.laws.discipline._ @@ -27,8 +27,13 @@ import org.scalacheck._ import scala.reflect._ +import java.net.URI +import java.time.Duration +import cats.Eq._ +import magnolify.scalacheck.TestArbitrary._ +import magnolify.scalacheck.TestCogen._ + class HashDerivationSuite extends MagnolifySuite { - private def test[T: Arbitrary: ClassTag: Cogen: Hash]: Unit = test() private def test[T: Arbitrary: ClassTag: Cogen: Hash](exclusions: String*): Unit = { val hash = ensureSerializable(implicitly[Hash[T]]) @@ -38,26 +43,22 @@ class HashDerivationSuite extends MagnolifySuite { } } + // Use `scala.util.hashing.Hashing[T]` for `Array[Int]`, equivalent to `x.##` and `x.hashCode` + implicit val hash: Hash[Array[Int]] = Hash.fromHashing[Array[Int]] + implicit val hashUri: Hash[URI] = Hash.fromUniversalHashCode + implicit val hashDuration: Hash[Duration] = Hash.fromUniversalHashCode + // Long.## != Long.hashCode for negative values test[Integers]("same as scala hashing", "same as universal hash") - test[Required] - test[Nullable] - test[Repeated] - test[Nested] - - { - // Use `scala.util.hashing.Hashing[T]` for `Array[Int]`, equivalent to `x.##` and `x.hashCode` - implicit val hash: Hash[Array[Int]] = Hash.fromHashing[Array[Int]] - test[Collections] - } - - { - import Custom._ - test[Custom] - } + test[Required]() + test[Nullable]() + test[Repeated]() + test[Nested]() + test[Collections]() + test[Custom]() - test[Node] - test[GNode[Int]] - test[Shape] - test[Color] + test[Node]() + test[GNode[Int]]() + test[Shape]() + test[Color]() } diff --git a/cats/src/test/scala/magnolify/cats/test/MonoidDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala similarity index 72% rename from cats/src/test/scala/magnolify/cats/test/MonoidDerivationSuite.scala rename to cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala index 833bf75ae..183e0fce3 100644 --- a/cats/src/test/scala/magnolify/cats/test/MonoidDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala @@ -14,49 +14,49 @@ * limitations under the License. */ -package magnolify.cats.test - -import java.net.URI -import java.time.Duration +package magnolify.cats +import cats.Eq._ import cats._ import cats.kernel.laws.discipline._ import magnolify.cats.auto._ +import magnolify.cats.TestEq._ +import magnolify.cats.Types.MiniInt import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary._ import magnolify.test.Simple._ import magnolify.test._ import org.scalacheck._ +import java.net.URI +import java.time.Duration import scala.reflect._ class MonoidDerivationSuite extends MagnolifySuite { + import MonoidDerivationSuite._ + private def test[T: Arbitrary: ClassTag: Eq: Monoid]: Unit = { val mon = ensureSerializable(implicitly[Monoid[T]]) include(MonoidTests[T](mon).monoid.all, className[T] + ".") } - import MonoidDerivationSuite._ - test[Record] + implicit val mBool: Monoid[Boolean] = Monoid.instance(false, _ || _) + implicit val mUri: Monoid[URI] = + Monoid.instance(URI.create(""), (x, y) => URI.create(x.toString + y.toString)) + implicit val mDuration: Monoid[Duration] = Monoid.instance(Duration.ZERO, _ plus _) + implicit val mMiniInt: Monoid[MiniInt] = + Monoid.instance(MiniInt(0), (x, y) => MiniInt(x.i + y.i)) - { - implicit val mBool: Monoid[Boolean] = Monoid.instance(false, _ || _) - test[Required] - test[Nullable] - test[Repeated] - test[Nested] - } - { - import Custom._ - implicit val mUri: Monoid[URI] = - Monoid.instance(URI.create(""), (x, y) => URI.create(x.toString + y.toString)) - implicit val mDuration: Monoid[Duration] = Monoid.instance(Duration.ZERO, _ plus _) - test[Custom] - } + test[Required] + test[Nullable] + test[Repeated] + test[Nested] + + test[Custom] + + test[Record] } object MonoidDerivationSuite { - import Types.MiniInt - implicit val mMiniInt: Monoid[MiniInt] = - Monoid.instance(MiniInt(0), (x, y) => MiniInt(x.i + y.i)) case class Record(i: Int, m: MiniInt) } diff --git a/cats/src/test/scala/magnolify/cats/test/PrioritySuite.scala b/cats/src/test/scala/magnolify/cats/PrioritySuite.scala similarity index 98% rename from cats/src/test/scala/magnolify/cats/test/PrioritySuite.scala rename to cats/src/test/scala/magnolify/cats/PrioritySuite.scala index 63e8dcd10..a13ff7ca3 100644 --- a/cats/src/test/scala/magnolify/cats/test/PrioritySuite.scala +++ b/cats/src/test/scala/magnolify/cats/PrioritySuite.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.cats.test +package magnolify.cats import cats._ import com.twitter.algebird.{Semigroup => _, _} @@ -68,7 +68,6 @@ class PrioritySuite extends MagnolifySuite { } { - import Enums._ implicit val hashScalaEnum: Hash[ScalaEnums.Color.Type] = Hash.by(_.toString) implicit val hashJavaEnum: Hash[JavaEnums.Color] = Hash.by(_.name()) implicit val showScalaEnum: Show[ScalaEnums.Color.Type] = Show.show(_.toString) diff --git a/cats/src/test/scala/magnolify/cats/test/ScopeTest.scala b/cats/src/test/scala/magnolify/cats/ScopeTest.scala similarity index 98% rename from cats/src/test/scala/magnolify/cats/test/ScopeTest.scala rename to cats/src/test/scala/magnolify/cats/ScopeTest.scala index 842f69e71..5b8c43f77 100644 --- a/cats/src/test/scala/magnolify/cats/test/ScopeTest.scala +++ b/cats/src/test/scala/magnolify/cats/ScopeTest.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.cats.test +package magnolify.cats import cats._ import cats.kernel.{Band, CommutativeGroup, CommutativeMonoid, CommutativeSemigroup} diff --git a/cats/src/test/scala/magnolify/cats/test/SemigroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala similarity index 73% rename from cats/src/test/scala/magnolify/cats/test/SemigroupDerivationSuite.scala rename to cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala index 6a0e6207c..c6a4b28c3 100644 --- a/cats/src/test/scala/magnolify/cats/test/SemigroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala @@ -14,51 +14,48 @@ * limitations under the License. */ -package magnolify.cats.test - -import java.net.URI -import java.time.Duration +package magnolify.cats +import cats.Eq._ import cats._ import cats.kernel.laws.discipline._ import magnolify.cats.auto._ +import magnolify.cats.TestEq._ +import magnolify.cats.Types.MiniInt import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary._ import magnolify.test.Simple._ import magnolify.test._ import org.scalacheck._ +import java.net.URI +import java.time.Duration import scala.reflect._ class SemigroupDerivationSuite extends MagnolifySuite { + import SemigroupDerivationSuite._ + private def test[T: Arbitrary: ClassTag: Eq: Semigroup]: Unit = { val sg = ensureSerializable(implicitly[Semigroup[T]]) include(SemigroupTests[T](sg).semigroup.all, className[T] + ".") } - import SemigroupDerivationSuite._ - test[Record] + implicit val sgBool: Semigroup[Boolean] = Semigroup.instance(_ ^ _) + implicit val sgUri: Semigroup[URI] = + Semigroup.instance((x, y) => URI.create(x.toString + y.toString)) + implicit val sgDuration: Semigroup[Duration] = Semigroup.instance(_ plus _) + implicit val sgMiniInt: Semigroup[MiniInt] = Semigroup.instance((x, y) => MiniInt(x.i + y.i)) test[Integers] + test[Required] + test[Nullable] + test[Repeated] + test[Nested] + test[Custom] - { - implicit val sgBool: Semigroup[Boolean] = Semigroup.instance(_ ^ _) - test[Required] - test[Nullable] - test[Repeated] - test[Nested] - } - - { - import Custom._ - implicit val sgUri: Semigroup[URI] = - Semigroup.instance((x, y) => URI.create(x.toString + y.toString)) - implicit val sgDuration: Semigroup[Duration] = Semigroup.instance(_ plus _) - test[Custom] - } + test[Record] } object SemigroupDerivationSuite { - import Types.MiniInt - implicit val sgMiniInt: Semigroup[MiniInt] = Semigroup.instance((x, y) => MiniInt(x.i + y.i)) case class Record(i: Int, m: MiniInt) } diff --git a/cats/src/test/scala/magnolify/cats/test/ShowDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala similarity index 78% rename from cats/src/test/scala/magnolify/cats/test/ShowDerivationSuite.scala rename to cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala index 57a848ba5..187c7e636 100644 --- a/cats/src/test/scala/magnolify/cats/test/ShowDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala @@ -14,18 +14,23 @@ * limitations under the License. */ -package magnolify.cats.test +package magnolify.cats import cats._ +import cats.laws.discipline.ContravariantTests +import cats.laws.discipline.MiniInt +import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.eq._ import magnolify.cats.auto._ import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary._ import magnolify.test.ADT._ import magnolify.test.Simple._ import magnolify.test._ import org.scalacheck._ -import cats.laws.discipline.{ContravariantTests, MiniInt} -import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq._ + +import java.net.URI +import java.time.Duration import scala.reflect._ class ShowDerivationSuite extends MagnolifySuite { @@ -43,21 +48,17 @@ class ShowDerivationSuite extends MagnolifySuite { } } + implicit val showArray: Show[Array[Int]] = Show.fromToString + implicit val showUri: Show[URI] = Show.fromToString + implicit val showDuration: Show[Duration] = Show.fromToString + test[Numbers] test[Required] test[Nullable] test[Repeated] test[Nested] - - { - implicit val showArray: Show[Array[Int]] = Show.fromToString[Array[Int]] - test[Collections] - } - - { - import Custom._ - test[Custom] - } + test[Collections] + test[Custom] test[Node] test[GNode[Int]] diff --git a/cats/src/test/scala/magnolify/cats/TestEq.scala b/cats/src/test/scala/magnolify/cats/TestEq.scala new file mode 100644 index 000000000..ac45ec425 --- /dev/null +++ b/cats/src/test/scala/magnolify/cats/TestEq.scala @@ -0,0 +1,81 @@ +/* + * Copyright 2022 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.Eq +import magnolify.cats.semiauto.EqDerivation +import magnolify.test.ADT._ +import magnolify.test.JavaEnums +import magnolify.test.Simple._ +import magnolify.shared.UnsafeEnum + +import java.net.URI +import java.time._ + +object TestEq { + + // other + implicit lazy val eqUri: Eq[URI] = Eq.fromUniversalEquals + implicit lazy val eqArray: Eq[Array[Int]] = Eq.by(_.toList) + implicit def eqIterable[T, C[_]](implicit eq: Eq[T], ti: C[T] => Iterable[T]): Eq[C[T]] = + Eq.instance { (x, y) => + val xs = ti(x) + val ys = ti(y) + xs.size == ys.size && (xs zip ys).forall((eq.eqv _).tupled) + } + + // time + implicit lazy val eqInstant: Eq[Instant] = Eq.by(_.toEpochMilli) + implicit lazy val eqLocalDate: Eq[LocalDate] = Eq.by(_.toEpochDay) + implicit lazy val eqLocalTime: Eq[LocalTime] = Eq.by(_.toNanoOfDay) + implicit lazy val eqLocalDateTime: Eq[LocalDateTime] = Eq.by(_.toEpochSecond(ZoneOffset.UTC)) + implicit lazy val eqOffsetTime: Eq[OffsetTime] = Eq.by(_.toLocalTime.toNanoOfDay) + implicit lazy val eqDuration: Eq[Duration] = Eq.by(_.toMillis) + + // enum + implicit lazy val eqJavaEnum: Eq[JavaEnums.Color] = Eq.fromUniversalEquals + implicit lazy val eqScalaEnum: Eq[ScalaEnums.Color.Type] = Eq.fromUniversalEquals + implicit def eqUnsafeEnum[T](implicit eq: Eq[T]): Eq[UnsafeEnum[T]] = Eq.instance { + case (UnsafeEnum.Known(x), UnsafeEnum.Known(y)) => eq.eqv(x, y) + case (UnsafeEnum.Unknown(x), UnsafeEnum.Unknown(y)) => x == y + case _ => false + } + + // ADT + implicit lazy val eqNode: Eq[Node] = EqDerivation[Node] + implicit lazy val eqGNode: Eq[GNode[Int]] = EqDerivation[GNode[Int]] + implicit lazy val eqShape: Eq[Shape] = EqDerivation[Shape] + implicit lazy val eqColor: Eq[Color] = EqDerivation[Color] + implicit lazy val eqPerson: Eq[Person] = EqDerivation[Person] + + // simple + implicit lazy val eqIntegers: Eq[Integers] = EqDerivation[Integers] + implicit lazy val eqFloats: Eq[Floats] = EqDerivation[Floats] + implicit lazy val eqNumbers: Eq[Numbers] = EqDerivation[Numbers] + implicit lazy val eqRequired: Eq[Required] = EqDerivation[Required] + implicit lazy val eqNullable: Eq[Nullable] = EqDerivation[Nullable] + implicit lazy val eqRepeated: Eq[Repeated] = EqDerivation[Repeated] + implicit lazy val eqNested: Eq[Nested] = EqDerivation[Nested] + implicit lazy val eqCollections: Eq[Collections] = EqDerivation[Collections] + implicit lazy val eqMoreCollections: Eq[MoreCollections] = EqDerivation[MoreCollections] + implicit lazy val eqEnums: Eq[Enums] = EqDerivation[Enums] + implicit lazy val eqUnsafeEnums: Eq[UnsafeEnums] = EqDerivation[UnsafeEnums] + implicit lazy val eqCustom: Eq[Custom] = EqDerivation[Custom] + implicit lazy val eqLowerCamel: Eq[LowerCamel] = EqDerivation[LowerCamel] + implicit lazy val eqLowerCamelInner: Eq[LowerCamelInner] = EqDerivation[LowerCamelInner] + +} diff --git a/cats/src/test/scala/magnolify/cats/test/Types.scala b/cats/src/test/scala/magnolify/cats/Types.scala similarity index 97% rename from cats/src/test/scala/magnolify/cats/test/Types.scala rename to cats/src/test/scala/magnolify/cats/Types.scala index ac76d4476..f04582e8b 100644 --- a/cats/src/test/scala/magnolify/cats/test/Types.scala +++ b/cats/src/test/scala/magnolify/cats/Types.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.cats.test +package magnolify.cats import cats.Eq import org.scalacheck.Arbitrary diff --git a/datastore/src/test/scala/magnolify/datastore/test/EntityTypeSuite.scala b/datastore/src/test/scala/magnolify/datastore/EntityTypeSuite.scala similarity index 85% rename from datastore/src/test/scala/magnolify/datastore/test/EntityTypeSuite.scala rename to datastore/src/test/scala/magnolify/datastore/EntityTypeSuite.scala index e0810712a..c20187d50 100644 --- a/datastore/src/test/scala/magnolify/datastore/test/EntityTypeSuite.scala +++ b/datastore/src/test/scala/magnolify/datastore/EntityTypeSuite.scala @@ -14,26 +14,29 @@ * limitations under the License. */ -package magnolify.datastore.test - -import java.net.URI -import java.time.{Duration, Instant} +package magnolify.datastore import cats._ -import com.google.datastore.v1.{Entity, Key} +import com.google.datastore.v1.Entity +import com.google.datastore.v1.Key import com.google.protobuf.ByteString +import magnolify.cats.auto._ +import magnolify.cats.TestEq._ import magnolify.datastore._ import magnolify.datastore.unsafe._ -import magnolify.cats.auto._ import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary._ import magnolify.shared.CaseMapper +import magnolify.shared.TestEnumType._ import magnolify.test.Simple._ -import magnolify.test.Time._ import magnolify.test._ import org.scalacheck._ -import scala.reflect._ +import java.net.URI +import java.time.Duration +import java.time.Instant import scala.jdk.CollectionConverters._ +import scala.reflect._ class EntityTypeSuite extends MagnolifySuite { private def test[T: Arbitrary: ClassTag](implicit t: EntityType[T], eq: Eq[T]): Unit = { @@ -47,6 +50,13 @@ class EntityTypeSuite extends MagnolifySuite { } } + implicit val arbByteString: Arbitrary[ByteString] = + Arbitrary(Gen.alphaNumStr.map(ByteString.copyFromUtf8)) + implicit val eqByteString: Eq[ByteString] = Eq.fromUniversalEquals + implicit val efUri: EntityField[URI] = EntityField.from[String](URI.create)(_.toString) + implicit val efDuration: EntityField[Duration] = + EntityField.from[Long](Duration.ofMillis)(_.toMillis) + test[Integers] test[Floats] test[Required] @@ -55,26 +65,15 @@ class EntityTypeSuite extends MagnolifySuite { test[Nested] test[Unsafe] - { - import Collections._ - test[Collections] - test[MoreCollections] - } + test[Collections] + test[MoreCollections] - { - import Enums._ - import UnsafeEnums._ - test[Enums] - test[UnsafeEnums] - } + test[Enums] + test[UnsafeEnums] - { - import Custom._ - implicit val efUri: EntityField[URI] = EntityField.from[String](URI.create)(_.toString) - implicit val efDuration: EntityField[Duration] = - EntityField.from[Long](Duration.ofMillis)(_.toMillis) - test[Custom] - } + test[Custom] + + test[DatastoreTypes] test("AnyVal") { implicit val et: EntityType[HasValueClass] = EntityType[HasValueClass] @@ -84,14 +83,6 @@ class EntityTypeSuite extends MagnolifySuite { assert(record.getPropertiesOrThrow("vc").getStringValue == "String") } - { - implicit val arbByteString: Arbitrary[ByteString] = - Arbitrary(Gen.alphaNumStr.map(ByteString.copyFromUtf8)) - implicit val eqByteString: Eq[ByteString] = Eq.instance(_ == _) - implicit val eqByteArray: Eq[Array[Byte]] = Eq.by(_.toList) - test[DatastoreTypes] - } - test("DefaultInner") { val et = ensureSerializable(EntityType[DefaultInner]) assertEquals(et(Entity.getDefaultInstance), DefaultInner()) @@ -126,7 +117,7 @@ class EntityTypeSuite extends MagnolifySuite { } { - val ns = "magnolify.datastore.test" + val ns = "magnolify.datastore" testKey(LongKey(123L), "", ns, "LongKey", _.getId, 123L) testKey(StringKey("abc"), "", ns, "StringKey", _.getName, "abc") testKey(InstantKey(Instant.ofEpochMilli(123L)), "", ns, "InstantKey", _.getId, 123L) @@ -165,14 +156,14 @@ class EntityTypeSuite extends MagnolifySuite { } testFail(EntityType[DoubleKey])( - "More than one @key annotation: magnolify.datastore.test.DoubleKey#k" + "More than one @key annotation: magnolify.datastore.DoubleKey#k" ) testFail(EntityType[MultiKey])( - "More than one field with @key annotation: magnolify.datastore.test.MultiKey#[k1, k2]" + "More than one field with @key annotation: magnolify.datastore.MultiKey#[k1, k2]" ) - testFail(EntityType[NestedKey])("No KeyField[T] instance: magnolify.datastore.test.NestedKey#k") + testFail(EntityType[NestedKey])("No KeyField[T] instance: magnolify.datastore.NestedKey#k") testFail(EntityType[DoubleEntityIndex])( - "More than one @excludeFromIndexes annotation: magnolify.datastore.test.DoubleEntityIndex#i" + "More than one @excludeFromIndexes annotation: magnolify.datastore.DoubleEntityIndex#i" ) { diff --git a/guava/src/test/scala/magnolify/guava/test/FunnelDerivationSuite.scala b/guava/src/test/scala/magnolify/guava/FunnelDerivationSuite.scala similarity index 86% rename from guava/src/test/scala/magnolify/guava/test/FunnelDerivationSuite.scala rename to guava/src/test/scala/magnolify/guava/FunnelDerivationSuite.scala index 8a7b0a7e8..0e7ec7122 100644 --- a/guava/src/test/scala/magnolify/guava/test/FunnelDerivationSuite.scala +++ b/guava/src/test/scala/magnolify/guava/FunnelDerivationSuite.scala @@ -14,21 +14,27 @@ * limitations under the License. */ -package magnolify.guava.test +package magnolify.guava -import java.io.{ByteArrayInputStream, ByteArrayOutputStream, ObjectInputStream, ObjectOutputStream} -import java.net.URI -import java.nio.ByteBuffer -import java.nio.charset.{Charset, StandardCharsets} -import java.time.Duration -import com.google.common.hash.{Funnel, PrimitiveSink} +import com.google.common.hash.Funnel +import com.google.common.hash.PrimitiveSink import magnolify.guava.auto._ import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary._ import magnolify.test.ADT._ import magnolify.test.Simple._ import magnolify.test._ import org.scalacheck._ +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.ObjectInputStream +import java.io.ObjectOutputStream +import java.net.URI +import java.nio.ByteBuffer +import java.nio.charset.Charset +import java.nio.charset.StandardCharsets +import java.time.Duration import scala.reflect._ class FunnelDerivationSuite extends MagnolifySuite { @@ -55,23 +61,17 @@ class FunnelDerivationSuite extends MagnolifySuite { sink.toBytes.toList } + implicit val fUri: Funnel[URI] = FunnelDerivation.by(_.toString) + implicit val fDuration: Funnel[Duration] = FunnelDerivation.by(_.toMillis) + test[Integers] test[Required] test[Nullable] test[FunnelTypes] - { - import Collections._ - test[Repeated] - test((c: Collections) => (c.a.toList, c.l, c.v)) - } - - { - import Custom._ - implicit val fUri: Funnel[URI] = FunnelDerivation.by(_.toString) - implicit val fDuration: Funnel[Duration] = FunnelDerivation.by(_.toMillis) - test[Custom] - } + test[Repeated] + test((c: Collections) => (c.a.toList, c.l, c.v)) + test[Custom] test("AnyVal") { implicit val f: Funnel[HasValueClass] = FunnelDerivation[HasValueClass] diff --git a/guava/src/test/scala/magnolify/guava/test/ScopeTest.scala b/guava/src/test/scala/magnolify/guava/ScopeTest.scala similarity index 96% rename from guava/src/test/scala/magnolify/guava/test/ScopeTest.scala rename to guava/src/test/scala/magnolify/guava/ScopeTest.scala index bf0ed2bf2..2fe3aa846 100644 --- a/guava/src/test/scala/magnolify/guava/test/ScopeTest.scala +++ b/guava/src/test/scala/magnolify/guava/ScopeTest.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.guava.test +package magnolify.guava import com.google.common.hash.Funnel import magnolify.test.Simple._ diff --git a/jmh/src/test/scala/magnolify/jmh/MagnolifyBench.scala b/jmh/src/test/scala/magnolify/jmh/MagnolifyBench.scala index 01022cf63..ccf745160 100644 --- a/jmh/src/test/scala/magnolify/jmh/MagnolifyBench.scala +++ b/jmh/src/test/scala/magnolify/jmh/MagnolifyBench.scala @@ -137,7 +137,7 @@ class EntityBench { @State(Scope.Thread) class ProtobufBench { import magnolify.protobuf._ - import magnolify.test.Proto2._ + import magnolify.protobuf.Proto2._ import MagnolifyBench._ private val protoType = ProtobufType[Nested, NestedP2] private val protoNested = protoType.to(nested) diff --git a/neo4j/src/test/scala/magnolify/neo4j/ValueTypeSuite.scala b/neo4j/src/test/scala/magnolify/neo4j/ValueTypeSuite.scala index 1004ae498..63588b411 100644 --- a/neo4j/src/test/scala/magnolify/neo4j/ValueTypeSuite.scala +++ b/neo4j/src/test/scala/magnolify/neo4j/ValueTypeSuite.scala @@ -17,12 +17,17 @@ package magnolify.neo4j import cats.Eq -import magnolify.test.MagnolifySuite -import magnolify.test.Simple._ import magnolify.cats.auto._ +import magnolify.cats.TestEq._ +import magnolify.neo4j.unsafe._ import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary._ import magnolify.shared.CaseMapper -import org.scalacheck.{Arbitrary, Prop} +import magnolify.shared.TestEnumType._ +import magnolify.test.MagnolifySuite +import magnolify.test.Simple._ +import org.scalacheck.Arbitrary +import org.scalacheck.Prop import java.net.URI import scala.reflect.ClassTag @@ -40,31 +45,21 @@ class ValueTypeSuite extends MagnolifySuite { } } + implicit val vfUri: ValueField[URI] = ValueField.from[String](URI.create)(_.toString) + test[Integers] test[Floats] test[Required] test[Nullable] test[Repeated] - { - import Collections._ - test[Collections] - test[MoreCollections] - } + test[Collections] + test[MoreCollections] - { - import unsafe._ - import Enums._ - import UnsafeEnums._ - test[Enums] - test[UnsafeEnums] - } + test[Enums] + test[UnsafeEnums] - { - import Custom._ - implicit val nvUri: ValueField[URI] = ValueField.from[String](URI.create)(_.toString) - test[Custom] - } + test[Custom] test("AnyVal") { implicit val vt: ValueType[HasValueClass] = ValueType[HasValueClass] diff --git a/parquet/src/main/scala/magnolify/parquet/ParquetField.scala b/parquet/src/main/scala/magnolify/parquet/ParquetField.scala index ca23b94aa..8a257d9b5 100644 --- a/parquet/src/main/scala/magnolify/parquet/ParquetField.scala +++ b/parquet/src/main/scala/magnolify/parquet/ParquetField.scala @@ -31,7 +31,6 @@ import org.apache.parquet.schema.{LogicalTypeAnnotation, Type, Types} import scala.annotation.{implicitNotFound, nowarn} import scala.collection.concurrent -import scala.language.experimental.macros import scala.collection.compat._ sealed trait ParquetField[T] extends Serializable { @@ -226,14 +225,14 @@ object ParquetField { implicit val pfByte = primitive[Byte, Integer]( - c => v => c.addInteger(v), + c => v => c.addInteger(v.toInt), TypeConverter.newInt.map(_.toByte), PrimitiveTypeName.INT32, LogicalTypeAnnotation.intType(8, true) ) implicit val pfShort = primitive[Short, Integer]( - c => v => c.addInteger(v), + c => v => c.addInteger(v.toInt), TypeConverter.newInt.map(_.toShort), PrimitiveTypeName.INT32, LogicalTypeAnnotation.intType(16, true) @@ -401,7 +400,7 @@ object ParquetField { } def decimalFixed(length: Int, precision: Int, scale: Int = 0): Primitive[BigDecimal] = { - val capacity = math.floor(math.log10(math.pow(2, 8 * length - 1) - 1)).toInt + val capacity = math.floor(math.log10(math.pow(2, (8 * length - 1).toDouble) - 1)).toInt require( 1 <= precision && precision <= capacity, s"Precision for FIXED($length) not within [1, $capacity]" @@ -465,6 +464,8 @@ object ParquetField { } implicit val ptDate: Primitive[LocalDate] = - logicalType[Int](LogicalTypeAnnotation.dateType())(LocalDate.ofEpochDay(_))(_.toEpochDay.toInt) + logicalType[Int](LogicalTypeAnnotation.dateType())(x => LocalDate.ofEpochDay(x.toLong))( + _.toEpochDay.toInt + ) } diff --git a/parquet/src/test/scala/magnolify/parquet/test/AvroParquetSuite.scala b/parquet/src/test/scala/magnolify/parquet/AvroParquetSuite.scala similarity index 70% rename from parquet/src/test/scala/magnolify/parquet/test/AvroParquetSuite.scala rename to parquet/src/test/scala/magnolify/parquet/AvroParquetSuite.scala index 38585b540..49fb0b489 100644 --- a/parquet/src/test/scala/magnolify/parquet/test/AvroParquetSuite.scala +++ b/parquet/src/test/scala/magnolify/parquet/AvroParquetSuite.scala @@ -14,21 +14,23 @@ * limitations under the License. */ -package magnolify.parquet.test +package magnolify.parquet import java.time._ import cats._ import magnolify.cats.auto._ +import magnolify.cats.TestEq._ import magnolify.avro._ import magnolify.avro.unsafe._ import magnolify.parquet._ import magnolify.parquet.unsafe._ import magnolify.parquet.ParquetArray.AvroCompat._ -import magnolify.parquet.test.util.AvroSchemaComparer +import magnolify.parquet.util.AvroSchemaComparer import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary._ import magnolify.test._ import magnolify.test.Simple._ -import magnolify.test.Time._ + import org.apache.avro.generic.GenericRecord import org.apache.hadoop.conf.Configuration import org.apache.parquet.avro.{ @@ -108,60 +110,48 @@ class AvroParquetSuite extends MagnolifySuite { test[Required]() test[Nullable]() - { - test[Repeated]() - test[Nested]( - List( - "root.r 'name' are different 'Required' != 'r'", - "root.r 'namespace' are different 'magnolify.test.Simple' != 'null'", - "root.o 'name' are different 'Required' != 'o'", - "root.o 'namespace' are different 'magnolify.test.Simple' != 'null'", - "root.l 'name' are different 'Required' != 'array'", - "root.l 'namespace' are different 'magnolify.test.Simple' != 'null'" - ) + test[Repeated]() + test[Nested]( + List( + "root.r 'name' are different 'Required' != 'r'", + "root.r 'namespace' are different 'magnolify.test.Simple' != 'null'", + "root.o 'name' are different 'Required' != 'o'", + "root.o 'namespace' are different 'magnolify.test.Simple' != 'null'", + "root.l 'name' are different 'Required' != 'array'", + "root.l 'namespace' are different 'magnolify.test.Simple' != 'null'" ) - } + ) test[Unsafe]() - { - import Collections._ - test[Collections]() - test[MoreCollections]() - } + test[Collections]() + test[MoreCollections]() - { - import Enums._ - import UnsafeEnums._ - test[Enums]( - List( - "root.j 'name' are different 'Color' != 'string'", - "root.j 'type' are different 'ENUM' != 'STRING'", - "root.s 'name' are different 'Color' != 'string'", - "root.s 'type' are different 'ENUM' != 'STRING'", - "root.a 'name' are different 'Color' != 'string'", - "root.a 'type' are different 'ENUM' != 'STRING'", - "root.jo 'name' are different 'Color' != 'string'", - "root.jo 'type' are different 'ENUM' != 'STRING'", - "root.so 'name' are different 'Color' != 'string'", - "root.so 'type' are different 'ENUM' != 'STRING'", - "root.ao 'name' are different 'Color' != 'string'", - "root.ao 'type' are different 'ENUM' != 'STRING'", - "root.jr 'name' are different 'Color' != 'string'", - "root.jr 'type' are different 'ENUM' != 'STRING'", - "root.sr 'name' are different 'Color' != 'string'", - "root.sr 'type' are different 'ENUM' != 'STRING'", - "root.ar 'name' are different 'Color' != 'string'", - "root.ar 'type' are different 'ENUM' != 'STRING'" - ) + test[Enums]( + List( + "root.j 'name' are different 'Color' != 'string'", + "root.j 'type' are different 'ENUM' != 'STRING'", + "root.s 'name' are different 'Color' != 'string'", + "root.s 'type' are different 'ENUM' != 'STRING'", + "root.a 'name' are different 'Color' != 'string'", + "root.a 'type' are different 'ENUM' != 'STRING'", + "root.jo 'name' are different 'Color' != 'string'", + "root.jo 'type' are different 'ENUM' != 'STRING'", + "root.so 'name' are different 'Color' != 'string'", + "root.so 'type' are different 'ENUM' != 'STRING'", + "root.ao 'name' are different 'Color' != 'string'", + "root.ao 'type' are different 'ENUM' != 'STRING'", + "root.jr 'name' are different 'Color' != 'string'", + "root.jr 'type' are different 'ENUM' != 'STRING'", + "root.sr 'name' are different 'Color' != 'string'", + "root.sr 'type' are different 'ENUM' != 'STRING'", + "root.ar 'name' are different 'Color' != 'string'", + "root.ar 'type' are different 'ENUM' != 'STRING'" ) - test[UnsafeEnums]() - } + ) + test[UnsafeEnums]() - { - implicit val eqByteArray: Eq[Array[Byte]] = Eq.by(_.toList) - test[ParquetTypes]() - } + test[ParquetTypes]() { import magnolify.avro.logical.bigquery._ @@ -192,21 +182,21 @@ class AvroParquetSuite extends MagnolifySuite { List( "root.nested 'name' are different 'AvroParquetWithAnnotations' != 'nested'", "root.nested 'doc' are different 'Should be ignored' != 'null'", - "root.nested 'namespace' are different 'magnolify.parquet.test' != 'null'" + "root.nested 'namespace' are different 'magnolify.parquet' != 'null'" ) ) test[AvroParquetWithAnnotationsAndOptions]( List( "root.nested 'name' are different 'AvroParquetWithAnnotations' != 'nested'", "root.nested 'doc' are different 'Should be ignored' != 'null'", - "root.nested 'namespace' are different 'magnolify.parquet.test' != 'null'" + "root.nested 'namespace' are different 'magnolify.parquet' != 'null'" ) ) test[AvroParquetWithAnnotationsAndLists]( List( "root.nested 'name' are different 'AvroParquetWithAnnotations' != 'array'", "root.nested 'doc' are different 'Should be ignored' != 'null'", - "root.nested 'namespace' are different 'magnolify.parquet.test' != 'null'" + "root.nested 'namespace' are different 'magnolify.parquet' != 'null'" ) ) } diff --git a/parquet/src/test/scala/magnolify/parquet/test/HadoopSuite.scala b/parquet/src/test/scala/magnolify/parquet/HadoopSuite.scala similarity index 97% rename from parquet/src/test/scala/magnolify/parquet/test/HadoopSuite.scala rename to parquet/src/test/scala/magnolify/parquet/HadoopSuite.scala index 2f135ae09..b6bb2839a 100644 --- a/parquet/src/test/scala/magnolify/parquet/test/HadoopSuite.scala +++ b/parquet/src/test/scala/magnolify/parquet/HadoopSuite.scala @@ -14,9 +14,8 @@ * limitations under the License. */ -package magnolify.parquet.test +package magnolify.parquet -import magnolify.parquet._ import magnolify.scalacheck.auto._ import magnolify.test.Simple._ import munit._ diff --git a/parquet/src/test/scala/magnolify/parquet/test/ParquetTypeSuite.scala b/parquet/src/test/scala/magnolify/parquet/ParquetTypeSuite.scala similarity index 90% rename from parquet/src/test/scala/magnolify/parquet/test/ParquetTypeSuite.scala rename to parquet/src/test/scala/magnolify/parquet/ParquetTypeSuite.scala index 1a3b81aa7..b4427947c 100644 --- a/parquet/src/test/scala/magnolify/parquet/test/ParquetTypeSuite.scala +++ b/parquet/src/test/scala/magnolify/parquet/ParquetTypeSuite.scala @@ -14,28 +14,30 @@ * limitations under the License. */ -package magnolify.parquet.test +package magnolify.parquet -import java.io.{ByteArrayInputStream, ByteArrayOutputStream} -import java.net.URI -import java.time._ -import java.util.UUID import cats._ import magnolify.cats.auto._ -import magnolify.parquet._ +import magnolify.cats.TestEq._ import magnolify.parquet.unsafe._ import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary._ import magnolify.shared.CaseMapper import magnolify.shared.doc +import magnolify.shared.TestEnumType._ import magnolify.test.Simple._ -import magnolify.test.Time._ import magnolify.test._ import org.apache.parquet.io._ import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName import org.scalacheck._ -import scala.reflect.ClassTag +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.net.URI +import java.time._ +import java.util.UUID import scala.jdk.CollectionConverters._ +import scala.reflect.ClassTag class ParquetTypeSuite extends MagnolifySuite { private def test[T: Arbitrary: ClassTag](implicit @@ -60,6 +62,11 @@ class ParquetTypeSuite extends MagnolifySuite { } } + implicit val pfUri: ParquetField[URI] = + ParquetField.from[String](URI.create)(_.toString) + implicit val pfDuration: ParquetField[Duration] = + ParquetField.from[Long](Duration.ofMillis)(_.toMillis) + test[Integers] test[Floats] test[Required] @@ -68,17 +75,25 @@ class ParquetTypeSuite extends MagnolifySuite { test[Nested] test[Unsafe] - { - import Collections._ - test[Collections] - test[MoreCollections] - } + test[Collections] + test[MoreCollections] - { - import Enums._ - import UnsafeEnums._ - test[Enums] - test[UnsafeEnums] + test[Enums] + test[UnsafeEnums] + + test[Custom] + + test[ParquetTypes] + + test("AnyVal") { + implicit val pt: ParquetType[HasValueClass] = ParquetType[HasValueClass] + test[HasValueClass] + + val schema = pt.schema + val index = schema.getFieldIndex("vc") + val field = schema.getFields.get(index) + assert(field.isPrimitive) + assert(field.asPrimitiveType().getPrimitiveTypeName == PrimitiveTypeName.BINARY) } test("ParquetDoc") { @@ -103,30 +118,6 @@ class ParquetTypeSuite extends MagnolifySuite { assert(pf.typeDoc.contains("Parquet with doc with nested list")) } - { - import Custom._ - implicit val pfUri: ParquetField[URI] = ParquetField.from[String](URI.create)(_.toString) - implicit val afDuration: ParquetField[Duration] = - ParquetField.from[Long](Duration.ofMillis)(_.toMillis) - test[Custom] - } - - test("AnyVal") { - implicit val pt: ParquetType[HasValueClass] = ParquetType[HasValueClass] - test[HasValueClass] - - val schema = pt.schema - val index = schema.getFieldIndex("vc") - val field = schema.getFields.get(index) - assert(field.isPrimitive) - assert(field.asPrimitiveType().getPrimitiveTypeName == PrimitiveTypeName.BINARY) - } - - { - implicit val eqByteArray: Eq[Array[Byte]] = Eq.by(_.toList) - test[ParquetTypes] - } - // Precision = number of digits, so 5 means -99999 to 99999 private def decimal(precision: Int): Arbitrary[BigDecimal] = { val nines = math.pow(10, precision.toDouble).toLong - 1 diff --git a/parquet/src/test/scala/magnolify/parquet/test/PredicateSuite.scala b/parquet/src/test/scala/magnolify/parquet/PredicateSuite.scala similarity index 97% rename from parquet/src/test/scala/magnolify/parquet/test/PredicateSuite.scala rename to parquet/src/test/scala/magnolify/parquet/PredicateSuite.scala index b08534359..1ff8dfedf 100644 --- a/parquet/src/test/scala/magnolify/parquet/test/PredicateSuite.scala +++ b/parquet/src/test/scala/magnolify/parquet/PredicateSuite.scala @@ -14,16 +14,14 @@ * limitations under the License. */ -package magnolify.parquet.test +package magnolify.parquet import java.{lang => jl} import java.time.Instant import cats._ import magnolify.cats.auto._ -import magnolify.parquet._ import magnolify.parquet.logical.millis._ import magnolify.test._ -import magnolify.test.Time._ import org.apache.parquet.filter2.compat.FilterCompat import org.apache.parquet.filter2.predicate.{FilterApi, FilterPredicate} import org.apache.parquet.io.api.Binary @@ -31,7 +29,8 @@ import org.apache.parquet.io.api.Binary import scala.reflect.ClassTag class PredicateSuite extends MagnolifySuite { - implicit val baEq: cats.Eq[Array[Byte]] = (x: Array[Byte], y: Array[Byte]) => x.diff(y).isEmpty + + import magnolify.cats.TestEq._ implicit val pfDecimal = ParquetField.decimal32(9) implicit val projectionT = ParquetType[Projection] implicit val projectionSubsetT = ParquetType[ProjectionSmall] diff --git a/parquet/src/test/scala/magnolify/parquet/test/ProjectionSuite.scala b/parquet/src/test/scala/magnolify/parquet/ProjectionSuite.scala similarity index 98% rename from parquet/src/test/scala/magnolify/parquet/test/ProjectionSuite.scala rename to parquet/src/test/scala/magnolify/parquet/ProjectionSuite.scala index db84457e6..a74c01203 100644 --- a/parquet/src/test/scala/magnolify/parquet/test/ProjectionSuite.scala +++ b/parquet/src/test/scala/magnolify/parquet/ProjectionSuite.scala @@ -14,16 +14,14 @@ * limitations under the License. */ -package magnolify.parquet.test +package magnolify.parquet import java.time.Instant import cats._ import magnolify.cats.auto._ -import magnolify.parquet._ import magnolify.parquet.logical.millis._ import magnolify.test._ -import magnolify.test.Time._ import org.apache.parquet.io.InvalidRecordException import scala.reflect.ClassTag diff --git a/parquet/src/test/scala/magnolify/parquet/test/SchemaEvolutionSuite.scala b/parquet/src/test/scala/magnolify/parquet/SchemaEvolutionSuite.scala similarity index 84% rename from parquet/src/test/scala/magnolify/parquet/test/SchemaEvolutionSuite.scala rename to parquet/src/test/scala/magnolify/parquet/SchemaEvolutionSuite.scala index 5834bf4fb..e5fe7ff2e 100644 --- a/parquet/src/test/scala/magnolify/parquet/test/SchemaEvolutionSuite.scala +++ b/parquet/src/test/scala/magnolify/parquet/SchemaEvolutionSuite.scala @@ -14,14 +14,13 @@ * limitations under the License. */ -package magnolify.parquet.test +package magnolify.parquet -import magnolify.parquet._ import magnolify.parquet.unsafe._ import magnolify.shared.UnsafeEnum import magnolify.test._ import org.apache.avro.generic.{GenericRecord, GenericRecordBuilder} -import org.apache.avro.{JsonProperties, Schema} +import org.apache.avro.{JsonProperties, Schema => AvroSchema} import org.apache.hadoop.conf.Configuration import org.apache.parquet.avro.{ AvroParquetReader, @@ -36,18 +35,21 @@ object SchemaEvolutionSuite { private val namespace = "magnolify.parquet" private val nullVal = JsonProperties.NULL_VALUE - private def nullableString: Schema = - Schema.createUnion(List(Schema.Type.NULL, Schema.Type.STRING).map(Schema.create).asJava) + private def nullableString: AvroSchema = + AvroSchema.createUnion( + List(AvroSchema.Type.NULL, AvroSchema.Type.STRING).map(AvroSchema.create).asJava + ) - val (locationSchema1, locationSchema2): (Schema, Schema) = { - def country = new Schema.Field("country", Schema.create(Schema.Type.STRING), "", null) - def state = new Schema.Field("state", Schema.create(Schema.Type.STRING), "", null) + val (locationSchema1, locationSchema2): (AvroSchema, AvroSchema) = { + def country = + new AvroSchema.Field("country", AvroSchema.create(AvroSchema.Type.STRING), "", null) + def state = new AvroSchema.Field("state", AvroSchema.create(AvroSchema.Type.STRING), "", null) - val v1 = Schema.createRecord("LocationV1", "", namespace, false) + val v1 = AvroSchema.createRecord("LocationV1", "", namespace, false) v1.setFields(List(country, state).asJava) - val v2 = Schema.createRecord("LocationV2", "", namespace, false) - val zip = new Schema.Field("zip", nullableString, "", nullVal) + val v2 = AvroSchema.createRecord("LocationV2", "", namespace, false) + val zip = new AvroSchema.Field("zip", nullableString, "", nullVal) v2.setFields(List(country, state, zip).asJava) (v1, v2) @@ -60,21 +62,22 @@ object SchemaEvolutionSuite { - New top level nullable string field "email" - New top level repeated string field "aliases" */ - val (userSchema1, userSchema2): (Schema, Schema) = { - def id = new Schema.Field("id", Schema.create(Schema.Type.LONG), "", null) - def name = new Schema.Field("name", Schema.create(Schema.Type.STRING), "", null) - def accountType = new Schema.Field("account_type", Schema.create(Schema.Type.STRING), "", null) - - val v1 = Schema.createRecord("UserV1", "", namespace, false) - val location1 = new Schema.Field("location", locationSchema1, "", null) + val (userSchema1, userSchema2): (AvroSchema, AvroSchema) = { + def id = new AvroSchema.Field("id", AvroSchema.create(AvroSchema.Type.LONG), "", null) + def name = new AvroSchema.Field("name", AvroSchema.create(AvroSchema.Type.STRING), "", null) + def accountType = + new AvroSchema.Field("account_type", AvroSchema.create(AvroSchema.Type.STRING), "", null) + + val v1 = AvroSchema.createRecord("UserV1", "", namespace, false) + val location1 = new AvroSchema.Field("location", locationSchema1, "", null) v1.setFields(List(id, name, accountType, location1).asJava) - val v2 = Schema.createRecord("UserV2", "", namespace, false) - val location2 = new Schema.Field("location", locationSchema2, "", null) - val email = new Schema.Field("email", nullableString, "", nullVal) - val aliases = new Schema.Field( + val v2 = AvroSchema.createRecord("UserV2", "", namespace, false) + val location2 = new AvroSchema.Field("location", locationSchema2, "", null) + val email = new AvroSchema.Field("email", nullableString, "", nullVal) + val aliases = new AvroSchema.Field( "aliases", - Schema.createArray(Schema.create(Schema.Type.STRING)), + AvroSchema.createArray(AvroSchema.create(AvroSchema.Type.STRING)), "", java.util.Collections.emptyList() ) @@ -83,18 +86,19 @@ object SchemaEvolutionSuite { (v1, v2) } - val (location1ProjectionSchema, user1ProjectionSchema): (Schema, Schema) = { - def id = new Schema.Field("id", Schema.create(Schema.Type.LONG), "", null) - def name = new Schema.Field("name", nullableString, "") + val (location1ProjectionSchema, user1ProjectionSchema): (AvroSchema, AvroSchema) = { + def id = new AvroSchema.Field("id", AvroSchema.create(AvroSchema.Type.LONG), "", null) + def name = new AvroSchema.Field("name", nullableString, "") - def country = new Schema.Field("country", Schema.create(Schema.Type.STRING), "", null) - def state = new Schema.Field("state", nullableString, "", null) + def country = + new AvroSchema.Field("country", AvroSchema.create(AvroSchema.Type.STRING), "", null) + def state = new AvroSchema.Field("state", nullableString, "", null) - val locationSchema1proj = Schema.createRecord("LocationV1", "", namespace, false) + val locationSchema1proj = AvroSchema.createRecord("LocationV1", "", namespace, false) locationSchema1proj.setFields(List(country, state).asJava) - val v1proj = Schema.createRecord("UserV1Projection", "", namespace, false) - val location1proj = new Schema.Field("location", locationSchema1proj, "", null) + val v1proj = AvroSchema.createRecord("UserV1Projection", "", namespace, false) + val location1proj = new AvroSchema.Field("location", locationSchema1proj, "", null) v1proj.setFields(List(id, name, location1proj).asJava) (locationSchema1proj, v1proj) @@ -291,7 +295,7 @@ object SchemaEvolutionSuite { class SchemaEvolutionSuite extends MagnolifySuite { import SchemaEvolutionSuite._ - private def writeAvro(xs: Seq[GenericRecord], schema: Schema): Array[Byte] = { + private def writeAvro(xs: Seq[GenericRecord], schema: AvroSchema): Array[Byte] = { val out = new TestOutputFile val writer = AvroParquetWriter.builder[GenericRecord](out).withSchema(schema).build() xs.foreach(writer.write) @@ -299,7 +303,7 @@ class SchemaEvolutionSuite extends MagnolifySuite { out.getBytes } - private def readAvro(bytes: Array[Byte], schema: Schema): Seq[GenericRecord] = { + private def readAvro(bytes: Array[Byte], schema: AvroSchema): Seq[GenericRecord] = { val in = new TestInputFile(bytes) val conf = new Configuration() AvroReadSupport.setAvroDataSupplier(conf, classOf[GenericDataSupplier]) diff --git a/parquet/src/test/scala/magnolify/parquet/test/SchemaUtilSuite.scala b/parquet/src/test/scala/magnolify/parquet/SchemaUtilSuite.scala similarity index 89% rename from parquet/src/test/scala/magnolify/parquet/test/SchemaUtilSuite.scala rename to parquet/src/test/scala/magnolify/parquet/SchemaUtilSuite.scala index d94d40299..e9449426a 100644 --- a/parquet/src/test/scala/magnolify/parquet/test/SchemaUtilSuite.scala +++ b/parquet/src/test/scala/magnolify/parquet/SchemaUtilSuite.scala @@ -14,12 +14,12 @@ * limitations under the License. */ -package magnolify.parquet.test +package magnolify.parquet import magnolify.parquet.SchemaUtil -import magnolify.parquet.test.util.AvroSchemaComparer +import magnolify.parquet.util.AvroSchemaComparer import magnolify.test.MagnolifySuite -import org.apache.avro.Schema +import org.apache.avro.{Schema => AvroSchema} class SchemaUtilSuite extends MagnolifySuite { @@ -39,7 +39,7 @@ class SchemaUtilSuite extends MagnolifySuite { | } ] |} |""".stripMargin - val inputSchema = new Schema.Parser().parse(nestedSchema) + val inputSchema = new AvroSchema.Parser().parse(nestedSchema) val outputSchema = SchemaUtil.deepCopy( inputSchema, diff --git a/parquet/src/test/scala/magnolify/parquet/test/util/AvroSchemaComparer.scala b/parquet/src/test/scala/magnolify/parquet/util/AvroSchemaComparer.scala similarity index 98% rename from parquet/src/test/scala/magnolify/parquet/test/util/AvroSchemaComparer.scala rename to parquet/src/test/scala/magnolify/parquet/util/AvroSchemaComparer.scala index 77a8cd253..9292d215f 100644 --- a/parquet/src/test/scala/magnolify/parquet/test/util/AvroSchemaComparer.scala +++ b/parquet/src/test/scala/magnolify/parquet/util/AvroSchemaComparer.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.parquet.test.util +package magnolify.parquet.util import magnolify.parquet.SchemaUtil._ import org.apache.avro.Schema diff --git a/protobuf/src/test/protobuf/Proto2.proto b/protobuf/src/test/protobuf/Proto2.proto index 764edc6d1..71ae78689 100644 --- a/protobuf/src/test/protobuf/Proto2.proto +++ b/protobuf/src/test/protobuf/Proto2.proto @@ -1,8 +1,8 @@ syntax = "proto2"; -package magnolify.test; +package magnolify.protobuf; -option java_package = "magnolify.test"; +option java_package = "magnolify.protobuf"; message IntegersP2 { required int32 i = 1; diff --git a/protobuf/src/test/protobuf/Proto3.proto b/protobuf/src/test/protobuf/Proto3.proto index 128c2bb26..1e33411d0 100644 --- a/protobuf/src/test/protobuf/Proto3.proto +++ b/protobuf/src/test/protobuf/Proto3.proto @@ -1,8 +1,8 @@ syntax = "proto3"; -package magnolify.test; +package magnolify.protobuf; -option java_package = "magnolify.test"; +option java_package = "magnolify.protobuf"; message IntegersP3 { int32 i = 1; diff --git a/protobuf/src/test/scala/magnolify/protobuf/test/ProtobufTypeSuite.scala b/protobuf/src/test/scala/magnolify/protobuf/ProtobufTypeSuite.scala similarity index 78% rename from protobuf/src/test/scala/magnolify/protobuf/test/ProtobufTypeSuite.scala rename to protobuf/src/test/scala/magnolify/protobuf/ProtobufTypeSuite.scala index 7f4ea9fb4..4a8e49102 100644 --- a/protobuf/src/test/scala/magnolify/protobuf/test/ProtobufTypeSuite.scala +++ b/protobuf/src/test/scala/magnolify/protobuf/ProtobufTypeSuite.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.protobuf.test +package magnolify.protobuf import java.net.URI import java.time.Duration @@ -24,13 +24,15 @@ import com.google.protobuf.{ByteString, Message} import magnolify.cats.auto._ import magnolify.scalacheck.auto._ import magnolify.protobuf._ +import magnolify.protobuf.Proto2._ +import magnolify.protobuf.Proto3._ import magnolify.protobuf.unsafe._ import magnolify.shared._ -import magnolify.test.Proto2._ -import magnolify.test.Proto3._ import magnolify.test.Simple._ import magnolify.test._ import org.scalacheck._ +import magnolify.scalacheck.TestArbitrary._ +import magnolify.cats.TestEq.{eqEnums => _, eqNullable => _, _} import scala.reflect._ @@ -52,6 +54,7 @@ trait BaseProtobufTypeSuite extends MagnolifySuite { } class ProtobufTypeSuite extends BaseProtobufTypeSuite { + test[Integers, IntegersP2] test[Integers, IntegersP3] test[Floats, FloatsP2] @@ -60,6 +63,19 @@ class ProtobufTypeSuite extends BaseProtobufTypeSuite { test[Required, SingularP3] test[Nullable, NullableP2] + test[Repeated, RepeatedP2] + test[Repeated, RepeatedP3] + test[Nested, NestedP2] + test[NestedNoOption, NestedP3] + test[UnsafeByte, IntegersP2] + test[UnsafeChar, IntegersP2] + test[UnsafeShort, IntegersP2] + + test[Collections, CollectionP2] + test[MoreCollections, MoreCollectionP2] + test[Collections, CollectionP3] + test[MoreCollections, MoreCollectionP3] + // PROTO3 removes the notion of require vs optional fields. // By default `Option[T] are not supported`. test("Fail PROTO3 Option[T]") { @@ -79,22 +95,6 @@ class ProtobufTypeSuite extends BaseProtobufTypeSuite { test[Nullable, SingularP3] } - test[Repeated, RepeatedP2] - test[Repeated, RepeatedP3] - test[Nested, NestedP2] - test[NestedNoOption, NestedP3] - test[UnsafeByte, IntegersP2] - test[UnsafeChar, IntegersP2] - test[UnsafeShort, IntegersP2] - - { - import Collections._ - test[Collections, CollectionP2] - test[MoreCollections, MoreCollectionP2] - test[Collections, CollectionP3] - test[MoreCollections, MoreCollectionP3] - } - test("AnyVal") { test[ProtoHasValueClass, IntegersP2] } @@ -102,26 +102,24 @@ class ProtobufTypeSuite extends BaseProtobufTypeSuite { // Workaround for "Method too large: magnolify/protobuf/test/ProtobufTypeSuite. ()V" class MoreProtobufTypeSuite extends BaseProtobufTypeSuite { - { - implicit val arbByteString: Arbitrary[ByteString] = - Arbitrary(Gen.alphaNumStr.map(ByteString.copyFromUtf8)) - implicit val eqByteString: Eq[ByteString] = Eq.instance(_ == _) - implicit val eqByteArray: Eq[Array[Byte]] = Eq.by(_.toList) - test[BytesA, BytesP2] - test[BytesB, BytesP3] - } + + implicit val arbByteString: Arbitrary[ByteString] = + Arbitrary(Gen.alphaNumStr.map(ByteString.copyFromUtf8)) + implicit val eqByteString: Eq[ByteString] = Eq.instance(_ == _) + implicit val pfUri: ProtobufField[URI] = ProtobufField.from[String](URI.create)(_.toString) + implicit val pfDuration: ProtobufField[Duration] = + ProtobufField.from[Long](Duration.ofMillis)(_.toMillis) + + test[BytesA, BytesP2] + test[BytesB, BytesP3] { - import Enums._ - import UnsafeEnums._ import Proto2Enums._ test[Enums, EnumsP2] test[UnsafeEnums, UnsafeEnumsP2] } { - import Enums._ - import UnsafeEnums._ import Proto3Enums._ import magnolify.protobuf.unsafe.Proto3Option._ // Enums are encoded as integers and default to zero value @@ -143,14 +141,8 @@ class MoreProtobufTypeSuite extends BaseProtobufTypeSuite { test[UnsafeEnums, UnsafeEnumsP3] } - { - import Custom._ - implicit val pfUri: ProtobufField[URI] = ProtobufField.from[String](URI.create)(_.toString) - implicit val pfDuration: ProtobufField[Duration] = - ProtobufField.from[Long](Duration.ofMillis)(_.toMillis) - test[Custom, CustomP2] - test[Custom, CustomP3] - } + test[Custom, CustomP2] + test[Custom, CustomP3] { implicit val pt: ProtobufType[LowerCamel, UpperCaseP3] = @@ -159,45 +151,35 @@ class MoreProtobufTypeSuite extends BaseProtobufTypeSuite { } { - implicit val arbByteString: Arbitrary[ByteString] = - Arbitrary(Gen.alphaNumStr.map(ByteString.copyFromUtf8)) - implicit val eqByteString: Eq[ByteString] = Eq.instance(_ == _) - import Enums._ - - { - import Proto2Enums._ - test[DefaultsRequired2, DefaultRequiredP2] - test[DefaultsNullable2, DefaultNullableP2] - } + import Proto2Enums._ + test[DefaultsRequired2, DefaultRequiredP2] + test[DefaultsNullable2, DefaultNullableP2] + } - { - import Proto3Enums._ - test[DefaultIntegers3, IntegersP3] - test[DefaultFloats3, FloatsP3] - test[DefaultRequired3, SingularP3] - test[DefaultEnums3, EnumsP3] - } + { + import Proto3Enums._ + test[DefaultIntegers3, IntegersP3] + test[DefaultFloats3, FloatsP3] + test[DefaultRequired3, SingularP3] + test[DefaultEnums3, EnumsP3] } { import magnolify.protobuf.unsafe.Proto3Option._ - val eq: Eq[DefaultNullable3] = Eq.by { x => + implicit val eq: Eq[DefaultNullable3] = Eq.by { x => Required(x.b.getOrElse(false), x.i.getOrElse(0), x.s.getOrElse("")) } - val arb: Arbitrary[DefaultNullable3] = implicitly[Arbitrary[DefaultNullable3]] - val pt = ProtobufType[DefaultNullable3, SingularP3] - test(classTag[DefaultNullable3], arb, classTag[SingularP3], pt, eq) + test[DefaultNullable3, SingularP3] } { - import Enums._ import Proto2Enums._ type F[T] = ProtobufType[T, _] testFail[F, DefaultMismatch2](ProtobufType[DefaultMismatch2, DefaultRequiredP2])( - "Default mismatch magnolify.protobuf.test.DefaultMismatch2#i: 321 != 123" + "Default mismatch magnolify.protobuf.DefaultMismatch2#i: 321 != 123" ) testFail[F, DefaultMismatch3](ProtobufType[DefaultMismatch3, SingularP3])( - "Default mismatch magnolify.protobuf.test.DefaultMismatch3#i: 321 != 0" + "Default mismatch magnolify.protobuf.DefaultMismatch3#i: 321 != 0" ) } } diff --git a/refined/src/test/scala/magnolify/refined/RefinedSuite.scala b/refined/src/test/scala/magnolify/refined/RefinedSuite.scala index 923a561a5..010370e7f 100644 --- a/refined/src/test/scala/magnolify/refined/RefinedSuite.scala +++ b/refined/src/test/scala/magnolify/refined/RefinedSuite.scala @@ -22,7 +22,7 @@ import eu.timepit.refined.auto._ import eu.timepit.refined.boolean._ import eu.timepit.refined.numeric._ import eu.timepit.refined.string._ -import magnolify.guava.test.BytesSink +import magnolify.guava.BytesSink import magnolify.test._ object RefinedSuite { @@ -154,9 +154,9 @@ class RefinedSuite extends MagnolifySuite { test("protobuf") { import magnolify.protobuf._ + import magnolify.protobuf.Proto3._ import magnolify.protobuf.unsafe.Proto3Option._ import magnolify.refined.protobuf._ - import magnolify.test.Proto3._ val tpe1 = ensureSerializable(ProtobufType[ProtoRequired, SingularP3]) val required = ProtoRequired(true, record.pct, refineV.unsafeFrom(record.uuid.value)) assertEquals(tpe1(tpe1(required)), required) diff --git a/scalacheck/src/test/scala-2.12/magnolify/scalacheck/test/MoreCollectionsBuildable.scala b/scalacheck/src/test/scala-2.12/magnolify/scalacheck/MoreCollectionsBuildable.scala similarity index 96% rename from scalacheck/src/test/scala-2.12/magnolify/scalacheck/test/MoreCollectionsBuildable.scala rename to scalacheck/src/test/scala-2.12/magnolify/scalacheck/MoreCollectionsBuildable.scala index 3cd0f9874..ed6334c13 100644 --- a/scalacheck/src/test/scala-2.12/magnolify/scalacheck/test/MoreCollectionsBuildable.scala +++ b/scalacheck/src/test/scala-2.12/magnolify/scalacheck/MoreCollectionsBuildable.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.scalacheck.test +package magnolify.scalacheck import magnolify.shims._ import org.scalacheck.util.Buildable diff --git a/scalacheck/src/test/scala-2.13/magnolify/scalacheck/test/MoreCollectionsBuildable.scala b/scalacheck/src/test/scala-2.13/magnolify/scalacheck/MoreCollectionsBuildable.scala similarity index 94% rename from scalacheck/src/test/scala-2.13/magnolify/scalacheck/test/MoreCollectionsBuildable.scala rename to scalacheck/src/test/scala-2.13/magnolify/scalacheck/MoreCollectionsBuildable.scala index 9d1d8f542..57404f0ba 100644 --- a/scalacheck/src/test/scala-2.13/magnolify/scalacheck/test/MoreCollectionsBuildable.scala +++ b/scalacheck/src/test/scala-2.13/magnolify/scalacheck/MoreCollectionsBuildable.scala @@ -14,6 +14,6 @@ * limitations under the License. */ -package magnolify.scalacheck.test +package magnolify.scalacheck object MoreCollectionsBuildable diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/test/ArbitraryDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala similarity index 90% rename from scalacheck/src/test/scala/magnolify/scalacheck/test/ArbitraryDerivationSuite.scala rename to scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala index e7ea4af9d..51667c0ef 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/test/ArbitraryDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala @@ -14,9 +14,12 @@ * limitations under the License. */ -package magnolify.scalacheck.test +package magnolify.scalacheck import magnolify.scalacheck.auto._ +import magnolify.scalacheck.MoreCollectionsBuildable._ // extra scala 2.12 Buildable +import magnolify.scalacheck.TestArbitrary.arbDuration +import magnolify.scalacheck.TestArbitrary.arbUri import magnolify.shims._ import magnolify.test.ADT._ import magnolify.test.Simple._ @@ -54,14 +57,9 @@ class ArbitraryDerivationSuite extends MagnolifySuite { test[Numbers] test[Required] test[Nullable] - - { - import MoreCollectionsBuildable._ // scala 2.12 does not find implicit Buildable for some collections - test[Repeated] - test((c: Collections) => (c.a.toList, c.l, c.v)) - test[MoreCollections] - } - + test[Repeated] + test((c: Collections) => (c.a.toList, c.l, c.v)) + test[MoreCollections] test[Nested] { @@ -74,10 +72,7 @@ class ArbitraryDerivationSuite extends MagnolifySuite { } } - { - import Custom._ - test[Custom] - } + test[Custom] { import magnolify.scalacheck.semiauto.ArbitraryDerivation.Fallback diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/test/CogenDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala similarity index 87% rename from scalacheck/src/test/scala/magnolify/scalacheck/test/CogenDerivationSuite.scala rename to scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala index 9023e02b2..4252f7e01 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/test/CogenDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.scalacheck.test +package magnolify.scalacheck import magnolify.scalacheck.auto._ import magnolify.test.ADT._ @@ -24,6 +24,7 @@ import org.scalacheck._ import org.scalacheck.rng.Seed import scala.reflect._ +import java.net.URI class CogenDerivationSuite extends MagnolifySuite { private def test[T: Arbitrary: ClassTag: Cogen]: Unit = @@ -45,18 +46,16 @@ class CogenDerivationSuite extends MagnolifySuite { } } + import magnolify.scalacheck.TestArbitrary._ + implicit val cogenUri: Cogen[URI] = Cogen(_.hashCode().toLong) + test[Numbers] test[Required] test[Nullable] - { - test[Repeated] - test((c: Collections) => (c.a.toList, c.l, c.v)) - } - + test[Repeated] + test((c: Collections) => (c.a.toList, c.l, c.v)) test[Nested] - - import Custom._ test[Custom] test[Node] diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/test/FunctionDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala similarity index 98% rename from scalacheck/src/test/scala/magnolify/scalacheck/test/FunctionDerivationSuite.scala rename to scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala index 1ed046341..7b18cc1b5 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/test/FunctionDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.scalacheck.test +package magnolify.scalacheck import magnolify.test.Simple._ import magnolify.test.ADT._ diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/test/ScopeTest.scala b/scalacheck/src/test/scala/magnolify/scalacheck/ScopeTest.scala similarity index 97% rename from scalacheck/src/test/scala/magnolify/scalacheck/test/ScopeTest.scala rename to scalacheck/src/test/scala/magnolify/scalacheck/ScopeTest.scala index 5aaa9bdea..df59d2e07 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/test/ScopeTest.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/ScopeTest.scala @@ -14,7 +14,7 @@ * limitations under the License. */ -package magnolify.scalacheck.test +package magnolify.scalacheck import magnolify.test.Simple._ import org.scalacheck._ diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/TestArbitrary.scala b/scalacheck/src/test/scala/magnolify/scalacheck/TestArbitrary.scala new file mode 100644 index 000000000..fe0edfd8e --- /dev/null +++ b/scalacheck/src/test/scala/magnolify/scalacheck/TestArbitrary.scala @@ -0,0 +1,85 @@ +/* + * Copyright 2022 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.scalacheck + +import magnolify.scalacheck.semiauto.ArbitraryDerivation +import magnolify.shared.UnsafeEnum +import magnolify.test.ADT._ +import magnolify.test.JavaEnums +import magnolify.test.Simple._ +import org.scalacheck._ + +import java.time._ +import java.net.URI + +object TestArbitrary { + // time + implicit lazy val arbInstant: Arbitrary[Instant] = + Arbitrary(Gen.posNum[Long].map(Instant.ofEpochMilli)) + implicit lazy val arbLocalDate: Arbitrary[LocalDate] = + Arbitrary(Gen.chooseNum(0L, 365L * 100).map(LocalDate.ofEpochDay)) + implicit lazy val arbLocalTime: Arbitrary[LocalTime] = + Arbitrary(arbInstant.arbitrary.map(_.atZone(ZoneOffset.UTC).toLocalTime)) + implicit lazy val arbLocalDateTime: Arbitrary[LocalDateTime] = + Arbitrary(arbInstant.arbitrary.map(_.atZone(ZoneOffset.UTC).toLocalDateTime)) + implicit lazy val arbOffsetTime: Arbitrary[OffsetTime] = + Arbitrary(arbInstant.arbitrary.map(_.atOffset(ZoneOffset.UTC).toOffsetTime)) + implicit lazy val arbDuration: Arbitrary[Duration] = + Arbitrary(Gen.posNum[Long].map(Duration.ofMillis)) + + // enum + implicit lazy val arbJavaEnum: Arbitrary[JavaEnums.Color] = Arbitrary( + Gen.oneOf(JavaEnums.Color.values.toSeq) + ) + implicit lazy val arbScalaEnums: Arbitrary[ScalaEnums.Color.Type] = Arbitrary( + Gen.oneOf(ScalaEnums.Color.values) + ) + implicit def arbUnsafeEnum[T](implicit arb: Arbitrary[T]): Arbitrary[UnsafeEnum[T]] = Arbitrary { + Gen.oneOf( + arb.arbitrary.map(UnsafeEnum.Known.apply), + Gen.alphaNumStr.suchThat(_.nonEmpty).map(UnsafeEnum.Unknown.apply) + ) + } + + // ADT + implicit lazy val arbNode: Arbitrary[Node] = ArbitraryDerivation[Node] + implicit lazy val arbGNode: Arbitrary[GNode[Int]] = ArbitraryDerivation[GNode[Int]] + implicit lazy val arbShape: Arbitrary[Shape] = ArbitraryDerivation[Shape] + implicit lazy val arbColor: Arbitrary[Color] = ArbitraryDerivation[Color] + implicit lazy val arbPerson: Arbitrary[Person] = ArbitraryDerivation[Person] + + // simple + implicit lazy val arbIntegers: Arbitrary[Integers] = ArbitraryDerivation[Integers] + implicit lazy val arbFloats: Arbitrary[Floats] = ArbitraryDerivation[Floats] + implicit lazy val arbNumbers: Arbitrary[Numbers] = ArbitraryDerivation[Numbers] + implicit lazy val arbRequired: Arbitrary[Required] = ArbitraryDerivation[Required] + implicit lazy val arbNullable: Arbitrary[Nullable] = ArbitraryDerivation[Nullable] + implicit lazy val arbRepeated: Arbitrary[Repeated] = ArbitraryDerivation[Repeated] + implicit lazy val arbNested: Arbitrary[Nested] = ArbitraryDerivation[Nested] + implicit lazy val arbCollections: Arbitrary[Collections] = ArbitraryDerivation[Collections] + implicit lazy val arbMoreCollections: Arbitrary[MoreCollections] = + ArbitraryDerivation[MoreCollections] + implicit lazy val arbEnums: Arbitrary[Enums] = ArbitraryDerivation[Enums] + implicit lazy val arbUnsafeEnums: Arbitrary[UnsafeEnums] = ArbitraryDerivation[UnsafeEnums] + implicit lazy val arbCustom: Arbitrary[Custom] = ArbitraryDerivation[Custom] + implicit lazy val arbLowerCamel: Arbitrary[LowerCamel] = ArbitraryDerivation[LowerCamel] + implicit lazy val arbLowerCamelInner: Arbitrary[LowerCamelInner] = + ArbitraryDerivation[LowerCamelInner] + + // other + implicit lazy val arbUri: Arbitrary[URI] = Arbitrary(Gen.alphaNumStr.map(URI.create)) +} diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala b/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala new file mode 100644 index 000000000..b32e59f8b --- /dev/null +++ b/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala @@ -0,0 +1,57 @@ +/* + * Copyright 2022 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.scalacheck + +import magnolify.scalacheck.semiauto.CogenDerivation +import magnolify.test.ADT._ +import magnolify.test.JavaEnums +import magnolify.test.Simple._ +import org.scalacheck.Cogen + +import java.net.URI + +object TestCogen { + // enum + implicit lazy val coJavaEnum: Cogen[JavaEnums.Color] = Cogen(_.ordinal().toLong) + implicit lazy val coScalaEnums: Cogen[ScalaEnums.Color.Type] = Cogen(_.id.toLong) + + // ADT + implicit lazy val coNode: Cogen[Node] = CogenDerivation[Node] + implicit lazy val coGNode: Cogen[GNode[Int]] = CogenDerivation[GNode[Int]] + implicit lazy val coShape: Cogen[Shape] = CogenDerivation[Shape] + implicit lazy val coColor: Cogen[Color] = CogenDerivation[Color] + implicit lazy val coPerson: Cogen[Person] = CogenDerivation[Person] + + // simple + implicit lazy val coIntegers: Cogen[Integers] = CogenDerivation[Integers] + implicit lazy val coFloats: Cogen[Floats] = CogenDerivation[Floats] + implicit lazy val coNumbers: Cogen[Numbers] = CogenDerivation[Numbers] + implicit lazy val coRequired: Cogen[Required] = CogenDerivation[Required] + implicit lazy val coNullable: Cogen[Nullable] = CogenDerivation[Nullable] + implicit lazy val coRepeated: Cogen[Repeated] = CogenDerivation[Repeated] + implicit lazy val coNested: Cogen[Nested] = CogenDerivation[Nested] + implicit lazy val coCollections: Cogen[Collections] = CogenDerivation[Collections] + // implicit lazy val coMoreCollections: Cogen[MoreCollections] = CogenDerivation[MoreCollections] + implicit lazy val coEnums: Cogen[Enums] = CogenDerivation[Enums] + implicit lazy val coUnsafeEnums: Cogen[UnsafeEnums] = CogenDerivation[UnsafeEnums] + implicit lazy val coCustom: Cogen[Custom] = CogenDerivation[Custom] + implicit lazy val coLowerCamel: Cogen[LowerCamel] = CogenDerivation[LowerCamel] + implicit lazy val coLowerCamelInner: Cogen[LowerCamelInner] = CogenDerivation[LowerCamelInner] + + // other + implicit lazy val coUri: Cogen[URI] = Cogen(_.hashCode().toLong) +} diff --git a/shared/src/main/scala/magnolify/shared/EnumType.scala b/shared/src/main/scala/magnolify/shared/EnumType.scala index 26fd7521b..d4f23489f 100644 --- a/shared/src/main/scala/magnolify/shared/EnumType.scala +++ b/shared/src/main/scala/magnolify/shared/EnumType.scala @@ -115,10 +115,11 @@ object EnumType { // //////////////////////////////////////////////// // Scala ADT - implicit def gen[T](implicit lp: shapeless.LowPriority): Typeclass[T] = macro lowPrioGen[T] + def adtEnumType[T]: EnumType[T] = macro Magnolia.gen[T] - @nowarn("msg=parameter value lp in method lowPrioGen is never used") - def lowPrioGen[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = Magnolia.gen[T](c) + implicit def gen[T](implicit lp: shapeless.LowPriority): EnumType[T] = macro genMacro[T] + @nowarn("msg=parameter value lp in method genMacro is never used") + def genMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = Magnolia.gen[T](c) type Typeclass[T] = EnumType[T] diff --git a/tensorflow/src/test/scala/magnolify/tensorflow/test/ExampleTypeSuite.scala b/tensorflow/src/test/scala/magnolify/tensorflow/ExampleTypeSuite.scala similarity index 87% rename from tensorflow/src/test/scala/magnolify/tensorflow/test/ExampleTypeSuite.scala rename to tensorflow/src/test/scala/magnolify/tensorflow/ExampleTypeSuite.scala index d8f171837..c8cbbc5bd 100644 --- a/tensorflow/src/test/scala/magnolify/tensorflow/test/ExampleTypeSuite.scala +++ b/tensorflow/src/test/scala/magnolify/tensorflow/ExampleTypeSuite.scala @@ -14,25 +14,31 @@ * limitations under the License. */ -package magnolify.tensorflow.test +package magnolify.tensorflow -import java.net.URI -import java.time.Duration import cats._ import com.google.protobuf.ByteString import magnolify.cats.auto._ +import magnolify.cats.TestEq._ import magnolify.scalacheck.auto._ +import magnolify.scalacheck.TestArbitrary.{arbFloats => _, _} import magnolify.shared.CaseMapper +import magnolify.shared.TestEnumType._ import magnolify.tensorflow._ import magnolify.tensorflow.unsafe._ import magnolify.test.Simple._ import magnolify.test._ import org.scalacheck._ +import org.tensorflow.metadata.v0.Annotation +import org.tensorflow.metadata.v0.Feature +import org.tensorflow.metadata.v0.FeatureType +import org.tensorflow.metadata.v0.Schema import org.tensorflow.proto.example.Example -import org.tensorflow.metadata.v0.{Annotation, Feature, FeatureType, Schema} -import scala.reflect._ +import java.net.URI +import java.time.Duration import scala.jdk.CollectionConverters._ +import scala.reflect._ class ExampleTypeSuite extends MagnolifySuite { private def test[T: Arbitrary: ClassTag](implicit t: ExampleType[T], eq: Eq[T]): Unit = { @@ -49,6 +55,15 @@ class ExampleTypeSuite extends MagnolifySuite { // workaround for Double to Float precision loss implicit val arbDouble: Arbitrary[Double] = Arbitrary(Arbitrary.arbFloat.arbitrary.map(_.toDouble)) + implicit val arbByteString: Arbitrary[ByteString] = + Arbitrary(Gen.alphaNumStr.map(ByteString.copyFromUtf8)) + implicit val eqByteString: Eq[ByteString] = Eq.instance(_ == _) + implicit val efUri: ExampleField.Primitive[URI] = + ExampleField.from[ByteString](x => URI.create(x.toStringUtf8))(x => + ByteString.copyFromUtf8(x.toString) + ) + implicit val efDuration: ExampleField.Primitive[Duration] = + ExampleField.from[Long](Duration.ofMillis)(_.toMillis) test[Integers] test[Floats] @@ -58,29 +73,15 @@ class ExampleTypeSuite extends MagnolifySuite { test[ExampleNested] test[Unsafe] - { - import Collections._ - test[Collections] - test[MoreCollections] - } + test[Collections] + test[MoreCollections] - { - import Enums._ - import UnsafeEnums._ - test[Enums] - test[UnsafeEnums] - } + test[Enums] + test[UnsafeEnums] - { - import Custom._ - implicit val efUri: ExampleField.Primitive[URI] = - ExampleField.from[ByteString](x => URI.create(x.toStringUtf8))(x => - ByteString.copyFromUtf8(x.toString) - ) - implicit val efDuration: ExampleField.Primitive[Duration] = - ExampleField.from[Long](Duration.ofMillis)(_.toMillis) - test[Custom] - } + test[Custom] + + test[ExampleTypes] test("AnyVal") { implicit val et: ExampleType[HasValueClass] = ExampleType[HasValueClass] @@ -96,14 +97,6 @@ class ExampleTypeSuite extends MagnolifySuite { assert(value.getBytesList.getValue(0).toStringUtf8 == "String") } - { - implicit val arbByteString: Arbitrary[ByteString] = - Arbitrary(Gen.alphaNumStr.map(ByteString.copyFromUtf8)) - implicit val eqByteString: Eq[ByteString] = Eq.instance(_ == _) - implicit val eqByteArray: Eq[Array[Byte]] = Eq.by(_.toList) - test[ExampleTypes] - } - test("DefaultInner") { val et = ensureSerializable(ExampleType[DefaultInner]) assertEquals(et(Example.getDefaultInstance), DefaultInner()) diff --git a/test/src/test/scala/magnolify/shared/TestEnumType.scala b/test/src/test/scala/magnolify/shared/TestEnumType.scala new file mode 100644 index 000000000..be86edf15 --- /dev/null +++ b/test/src/test/scala/magnolify/shared/TestEnumType.scala @@ -0,0 +1,31 @@ +/* + * Copyright 2022 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.shared + +import magnolify.test.ADT +import magnolify.test.JavaEnums +import magnolify.test.Simple.ScalaEnums +object TestEnumType { + + implicit val etJava: EnumType[JavaEnums.Color] = + EnumType.javaEnumType[JavaEnums.Color] + implicit val etScala: EnumType[ScalaEnums.Color.Type] = + EnumType.scalaEnumType[ScalaEnums.Color.Type] + implicit val etAdt: EnumType[ADT.Color] = + EnumType.adtEnumType[ADT.Color] + +} diff --git a/test/src/test/scala/magnolify/test/Simple.scala b/test/src/test/scala/magnolify/test/Simple.scala index 195ec7709..93cfab4d9 100644 --- a/test/src/test/scala/magnolify/test/Simple.scala +++ b/test/src/test/scala/magnolify/test/Simple.scala @@ -18,14 +18,24 @@ package magnolify.test import java.net.URI import java.time.Duration -import org.scalacheck._ -import cats._ + import magnolify.shared.UnsafeEnum import scala.annotation.StaticAnnotation import scala.collection.immutable.Seq object Simple { + class ScalaAnnotation(val value: String) extends StaticAnnotation with Serializable + + object ScalaEnums { + @JavaAnnotation("Java Annotation") + @ScalaAnnotation("Scala Annotation") + object Color extends Enumeration { + type Type = Value + val Red, Green, Blue = Value + } + } + case class Integers(i: Int, l: Long) case class Floats(f: Float, d: Double) case class Numbers(i: Int, l: Long, f: Float, d: Double, bi: BigInt, bd: BigDecimal) @@ -69,54 +79,6 @@ object Simple { case class LowerCamel(firstField: String, secondField: String, innerField: LowerCamelInner) case class LowerCamelInner(innerFirst: String) - object Collections { - implicit def eqIterable[T, C[_]](implicit eq: Eq[T], tt: C[T] => Iterable[T]): Eq[C[T]] = - Eq.instance { (x, y) => - val xs = x.toList - val ys = y.toList - xs.size == ys.size && (x.iterator zip y.iterator).forall((eq.eqv _).tupled) - } - } - - class ScalaAnnotation(val value: String) extends StaticAnnotation with Serializable - - object ScalaEnums { - @JavaAnnotation("Java Annotation") - @ScalaAnnotation("Scala Annotation") - object Color extends Enumeration { - type Type = Value - val Red, Green, Blue = Value - } - } - - object Enums { - implicit val arbScalaEnum: Arbitrary[ScalaEnums.Color.Type] = - Arbitrary(Gen.oneOf(ScalaEnums.Color.values)) - implicit val eqJavaEnum: Eq[JavaEnums.Color] = Eq.by(_.name()) - implicit val eqScalaEnum: Eq[ScalaEnums.Color.Type] = Eq.by(_.toString) - } - - object UnsafeEnums { - implicit def arbUnsafeEnum[T](implicit arb: Arbitrary[T]): Arbitrary[UnsafeEnum[T]] = - Arbitrary( - Gen.oneOf(arb.arbitrary.map(UnsafeEnum(_)), Gen.const(UnsafeEnum.Unknown("NOT_A_COLOR"))) - ) - } - - object Custom { - implicit val arbUri: Arbitrary[URI] = - Arbitrary(Gen.alphaNumStr.map(URI.create)) - implicit val arbDuration: Arbitrary[Duration] = - Arbitrary(Gen.chooseNum(0, Int.MaxValue).map(_.toLong).map(Duration.ofMillis)) - implicit val coUri: Cogen[URI] = Cogen(_.toString.hashCode.toLong) - implicit val coDuration: Cogen[Duration] = Cogen(_.toMillis) - implicit val hashUri: Hash[URI] = Hash.fromUniversalHashCode[URI] - implicit val hashDuration: Hash[Duration] = Hash.fromUniversalHashCode[Duration] - - implicit val showUri: Show[URI] = Show.fromToString - implicit val showDuration: Show[Duration] = Show.fromToString - } - object LowerCamel { val fields: Seq[String] = Seq("firstField", "secondField", "innerField") val default: LowerCamel = LowerCamel("first", "second", LowerCamelInner("inner.first")) diff --git a/test/src/test/scala/magnolify/test/Time.scala b/test/src/test/scala/magnolify/test/Time.scala deleted file mode 100644 index 4b3686fdf..000000000 --- a/test/src/test/scala/magnolify/test/Time.scala +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package magnolify.test - -import java.time._ - -import cats._ -import cats.instances.all._ -import org.scalacheck._ - -object Time { - implicit val arbInstant: Arbitrary[Instant] = - Arbitrary(Gen.chooseNum(0, Int.MaxValue).map(_.toLong).map(Instant.ofEpochMilli)) - implicit val arbLocalDate: Arbitrary[LocalDate] = - Arbitrary(Gen.chooseNum(0L, 365L * 100).map(LocalDate.ofEpochDay)) - implicit val arbLocalTime: Arbitrary[LocalTime] = - Arbitrary(arbInstant.arbitrary.map(_.atZone(ZoneOffset.UTC).toLocalTime)) - implicit val arbLocalDateTime: Arbitrary[LocalDateTime] = - Arbitrary(arbInstant.arbitrary.map(_.atZone(ZoneOffset.UTC).toLocalDateTime)) - implicit val arbOffsetTime: Arbitrary[OffsetTime] = - Arbitrary(arbInstant.arbitrary.map(_.atOffset(ZoneOffset.UTC).toOffsetTime)) - - implicit val eqInstant: Eq[Instant] = Eq.by(_.toEpochMilli) - implicit val eqLocalDate: Eq[LocalDate] = Eq.by(_.toEpochDay) - implicit val eqLocalTime: Eq[LocalTime] = Eq.by(_.toNanoOfDay) - implicit val eqLocalDateTime: Eq[LocalDateTime] = Eq.by(_.toEpochSecond(ZoneOffset.UTC)) - implicit val eqOffsetTime: Eq[OffsetTime] = Eq.by(_.toLocalTime.toNanoOfDay) -}