From 6c8c53b6f503c134d878ccebca209159cf719a99 Mon Sep 17 00:00:00 2001 From: Kellen Dye Date: Fri, 23 Aug 2024 15:34:36 -0400 Subject: [PATCH] coverage --- .../magnolify/beam/logical/package.scala | 17 +++++---- .../magnolify/beam/BeamSchemaTypeSuite.scala | 36 +++++++++++-------- .../test/scala/magnolify/cats/TestEq.scala | 14 ++++---- docs/mapping.md | 2 +- .../magnolify/parquet/ParquetTypeSuite.scala | 27 ++++++++------ 5 files changed, 53 insertions(+), 43 deletions(-) diff --git a/beam/src/main/scala/magnolify/beam/logical/package.scala b/beam/src/main/scala/magnolify/beam/logical/package.scala index f7d4c472..fcd93ff1 100644 --- a/beam/src/main/scala/magnolify/beam/logical/package.scala +++ b/beam/src/main/scala/magnolify/beam/logical/package.scala @@ -20,6 +20,7 @@ import org.apache.beam.sdk.schemas.logicaltypes import org.apache.beam.sdk.schemas.Schema.FieldType import org.apache.beam.sdk.schemas.logicaltypes.SqlTypes import org.joda.time as joda +import org.joda.time.chrono.ISOChronology import java.time as jt import java.time.temporal.ChronoField @@ -33,21 +34,19 @@ package object logical { private lazy val EpochJodaDate = new joda.LocalDate(1970, 1, 1) implicit val bsfJodaLocalDate: BeamSchemaField[joda.LocalDate] = BeamSchemaField.from[jt.LocalDate](jtld => - EpochJodaDate.plusDays(jtld.get(ChronoField.EPOCH_DAY)) + EpochJodaDate.plusDays(jtld.getLong(ChronoField.EPOCH_DAY).toInt) )(d => jt.LocalDate.ofEpochDay(joda.Days.daysBetween(EpochJodaDate, d).getDays.toLong)) } object millis { - implicit val bsfInstantMillis: BeamSchemaField[jt.Instant] = - BeamSchemaField.id[jt.Instant](_ => FieldType.DATETIME) - implicit val bsfJodaInstantMillis: BeamSchemaField[joda.Instant] = - BeamSchemaField.from[jt.Instant](i => millisToJodaInstant(millisFromInstant(i)))(i => - millisToInstant(millisFromJodaInstant(i)) + implicit lazy val bsfInstantMillis: BeamSchemaField[jt.Instant] = + BeamSchemaField.from[joda.Instant](i => millisToInstant(millisFromJodaInstant(i)))(i => + millisToJodaInstant(millisFromInstant(i)) ) + implicit val bsfJodaInstantMillis: BeamSchemaField[joda.Instant] = + BeamSchemaField.id[joda.Instant](_ => FieldType.DATETIME) implicit val bsfJodaDateTimeMillis: BeamSchemaField[joda.DateTime] = - BeamSchemaField.from[jt.Instant](i => millisToJodaDateTime(millisFromInstant(i)))(dt => - millisToInstant(millisFromJodaDateTime(dt)) - ) + BeamSchemaField.from[joda.Instant](_.toDateTime(ISOChronology.getInstanceUTC))(_.toInstant) implicit val bsfLocalTimeMillis: BeamSchemaField[jt.LocalTime] = BeamSchemaField.from[Int](millisToLocalTime)(millisFromLocalTime) diff --git a/beam/src/test/scala/magnolify/beam/BeamSchemaTypeSuite.scala b/beam/src/test/scala/magnolify/beam/BeamSchemaTypeSuite.scala index 297a8d89..d2764cfa 100644 --- a/beam/src/test/scala/magnolify/beam/BeamSchemaTypeSuite.scala +++ b/beam/src/test/scala/magnolify/beam/BeamSchemaTypeSuite.scala @@ -39,12 +39,17 @@ class BeamSchemaTypeSuite extends MagnolifySuite { private def test[T: Arbitrary: ClassTag](implicit bst: BeamSchemaType[T], eq: Eq[T] + ): Unit = testNamed[T](className[T]) + + private def testNamed[T: Arbitrary](name: String)(implicit + bst: BeamSchemaType[T], + eq: Eq[T] ): Unit = { // Ensure serializable even after evaluation of `schema` bst.schema: Unit ensureSerializable(bst) - property(className[T]) { + property(name) { Prop.forAll { (t: T) => val converted = bst.apply(t) val roundtripped = bst.apply(converted) @@ -68,6 +73,7 @@ class BeamSchemaTypeSuite extends MagnolifySuite { test[Collections] test[MoreCollections] + test[Empty] test[Others] test[Maps] test[Logical] @@ -80,28 +86,28 @@ class BeamSchemaTypeSuite extends MagnolifySuite { test[UnsafeEnums] } - property("Date") { + { import magnolify.beam.logical.date.* test[JavaDate] test[JodaDate] } - property("Millis") { + { import magnolify.beam.logical.millis.* - test[JavaTime] - test[JodaTime] + testNamed[JavaTime]("JavaMillis") + testNamed[JodaTime]("JodaMillis") } - property("Micros") { + { import magnolify.beam.logical.micros.* - test[JavaTime] - test[JodaTime] + testNamed[JavaTime]("JavaMicros") + testNamed[JodaTime]("JodaMicros") } - property("Nanos") { + { import magnolify.beam.logical.nanos.* - test[JavaTime] - test[JodaTime] + testNamed[JavaTime]("JavaNanos") + testNamed[JodaTime]("JodaNanos") } { @@ -109,9 +115,8 @@ class BeamSchemaTypeSuite extends MagnolifySuite { BeamSchemaType[LowerCamel](CaseMapper(_.toUpperCase)) test[LowerCamel] - test("LowerCamel mapping") { + { val schema = bst.schema - val fields = LowerCamel.fields.map(_.toUpperCase) assertEquals(schema.getFields.asScala.map(_.getName()).toSeq, fields) assertEquals( @@ -121,7 +126,7 @@ class BeamSchemaTypeSuite extends MagnolifySuite { } } - test("ValueClass") { + { // value classes should act only as fields intercept[IllegalArgumentException] { BeamSchemaType[ValueClass] @@ -135,12 +140,13 @@ class BeamSchemaTypeSuite extends MagnolifySuite { assert(record.getValue[String]("vc").equals("String")) } - property("Sql") { + { import magnolify.beam.logical.sql.* test[Sql] } } +case class Empty() case class Others(bs: ByteString, cs: CharSequence, bb: ByteBuffer, c: Char) case class Decimal(bd: BigDecimal, bdo: Option[BigDecimal]) case class Logical( diff --git a/cats/src/test/scala/magnolify/cats/TestEq.scala b/cats/src/test/scala/magnolify/cats/TestEq.scala index 22ecb023..db0c76ce 100644 --- a/cats/src/test/scala/magnolify/cats/TestEq.scala +++ b/cats/src/test/scala/magnolify/cats/TestEq.scala @@ -45,7 +45,7 @@ object TestEq { // Can only be used as a key value list m.map { case (k, v) => k.toString -> v } } - implicit val eqByteBuffer: Eq[ByteBuffer] = Eq.by(_.array()) + implicit lazy val eqByteBuffer: Eq[ByteBuffer] = Eq.by(_.array()) // java-time implicit lazy val eqInstant: Eq[Instant] = Eq.fromUniversalEquals @@ -56,12 +56,12 @@ object TestEq { implicit lazy val eqDuration: Eq[Duration] = Eq.fromUniversalEquals // joda-time - implicit val eqJodaDate: Eq[joda.LocalDate] = Eq.fromUniversalEquals - implicit val eqJodaDateTime: Eq[joda.DateTime] = Eq.fromUniversalEquals - implicit val eqJodaLocalTime: Eq[joda.LocalTime] = Eq.fromUniversalEquals - implicit val eqJodaLocalDateTime: Eq[joda.LocalDateTime] = Eq.fromUniversalEquals - implicit val eqJodaDuration: Eq[joda.Duration] = Eq.fromUniversalEquals - implicit val eqJodaInstant: Eq[joda.Instant] = Eq.fromUniversalEquals + implicit lazy val eqJodaDate: Eq[joda.LocalDate] = Eq.fromUniversalEquals + implicit lazy val eqJodaDateTime: Eq[joda.DateTime] = Eq.fromUniversalEquals + implicit lazy val eqJodaLocalTime: Eq[joda.LocalTime] = Eq.fromUniversalEquals + implicit lazy val eqJodaLocalDateTime: Eq[joda.LocalDateTime] = Eq.fromUniversalEquals + implicit lazy val eqJodaDuration: Eq[joda.Duration] = Eq.fromUniversalEquals + implicit lazy val eqJodaInstant: Eq[joda.Instant] = Eq.fromUniversalEquals // enum implicit lazy val eqJavaEnum: Eq[JavaEnums.Color] = Eq.fromUniversalEquals diff --git a/docs/mapping.md b/docs/mapping.md index c86db47e..cb5284b9 100644 --- a/docs/mapping.md +++ b/docs/mapping.md @@ -60,5 +60,5 @@ one of: `magnolify.parquet.ParquetField.{decimal32, decimal64, decimalFixed, decimalBinary}`. 15. Map key type in avro is fixed to string. Scala Map key type must be either `String` or `CharSequence`. 16. Beam logical [Enumeration type](https://beam.apache.org/documentation/programming-guide/#enumerationtype) -17. See [beam.md][protobuf.md](https://github.com/spotify/magnolify/blob/master/docs/beam.md) for details +17. See [beam.md](https://github.com/spotify/magnolify/blob/master/docs/beam.md) for details 18. Beam logical [UUID type](https://beam.apache.org/releases/javadoc/2.58.1/org/apache/beam/sdk/schemas/logicaltypes/UuidLogicalType.html) diff --git a/parquet/src/test/scala/magnolify/parquet/ParquetTypeSuite.scala b/parquet/src/test/scala/magnolify/parquet/ParquetTypeSuite.scala index 6d1b8c89..53357fb8 100644 --- a/parquet/src/test/scala/magnolify/parquet/ParquetTypeSuite.scala +++ b/parquet/src/test/scala/magnolify/parquet/ParquetTypeSuite.scala @@ -43,12 +43,17 @@ class ParquetTypeSuite extends MagnolifySuite { private def test[T: Arbitrary: ClassTag](implicit t: ParquetType[T], eq: Eq[T] + ): Unit = testNamed[T](className[T]) + + private def testNamed[T: Arbitrary](name: String)(implicit + t: ParquetType[T], + eq: Eq[T] ): Unit = { // Ensure serializable even after evaluation of `schema` t.schema: Unit val tpe = ensureSerializable(t) - property(className[T]) { + property(name) { Prop.forAll { (t: T) => val out = new TestOutputFile val writer = tpe.writeBuilder(out).build() @@ -162,43 +167,43 @@ class ParquetTypeSuite extends MagnolifySuite { { implicit val arbBigDecimal: Arbitrary[BigDecimal] = decimal(9) implicit val pfBigDecimal: ParquetField[BigDecimal] = ParquetField.decimal32(9, 0) - test[Decimal] + testNamed[Decimal]("Decimal32") } { implicit val arbBigDecimal: Arbitrary[BigDecimal] = decimal(18) implicit val pfBigDecimal: ParquetField[BigDecimal] = ParquetField.decimal64(18, 0) - test[Decimal] + testNamed[Decimal]("Decimal64") } { implicit val arbBigDecimal: Arbitrary[BigDecimal] = decimal(18) // math.floor(math.log10(math.pow(2, 8*8-1) - 1)) = 18 digits implicit val pfBigDecimal: ParquetField[BigDecimal] = ParquetField.decimalFixed(8, 18, 0) - test[Decimal] + testNamed[Decimal]("DecimalFixed") } { implicit val arbBigDecimal: Arbitrary[BigDecimal] = decimal(20) implicit val pfBigDecimal: ParquetField[BigDecimal] = ParquetField.decimalBinary(20, 0) - test[Decimal] + testNamed[Decimal]("DecimalBinary") } test[Logical] - property("Millis") { + { import magnolify.parquet.logical.millis._ - test[Time] + testNamed[Time]("TimeMillis") } - property("Micros") { + { import magnolify.parquet.logical.micros._ - test[Time] + testNamed[Time]("TimeMicros") } - property("Nanos") { + { import magnolify.parquet.logical.nanos._ - test[Time] + testNamed[Time]("TimeNanos") } {