Skip to content

Commit

Permalink
coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
kellen committed Aug 23, 2024
1 parent ec120eb commit 6c8c53b
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 43 deletions.
17 changes: 8 additions & 9 deletions beam/src/main/scala/magnolify/beam/logical/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
36 changes: 21 additions & 15 deletions beam/src/test/scala/magnolify/beam/BeamSchemaTypeSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -68,6 +73,7 @@ class BeamSchemaTypeSuite extends MagnolifySuite {
test[Collections]
test[MoreCollections]

test[Empty]
test[Others]
test[Maps]
test[Logical]
Expand All @@ -80,38 +86,37 @@ 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")
}

{
implicit val bst: BeamSchemaType[LowerCamel] =
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(
Expand All @@ -121,7 +126,7 @@ class BeamSchemaTypeSuite extends MagnolifySuite {
}
}

test("ValueClass") {
{
// value classes should act only as fields
intercept[IllegalArgumentException] {
BeamSchemaType[ValueClass]
Expand All @@ -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(
Expand Down
14 changes: 7 additions & 7 deletions cats/src/test/scala/magnolify/cats/TestEq.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion docs/mapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
27 changes: 16 additions & 11 deletions parquet/src/test/scala/magnolify/parquet/ParquetTypeSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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")
}

{
Expand Down

0 comments on commit 6c8c53b

Please sign in to comment.