Skip to content

Commit

Permalink
Improve enum test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
Chuckame committed Sep 25, 2024
1 parent f7e72fe commit 9348a8d
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 3 deletions.
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ ij_editorconfig_spaces_around_assignment_operators = true

[{*.kt,*.kts}]
ktlint_standard_filename = disabled
ktlint_standard_class-signature = disabled
ktlint_standard_function-signature = disabled
ktlint_standard_chain-method-continuation = disabled
ktlint_standard_function-expression-body = disabled
ij_kotlin_align_in_columns_case_branch = false
ij_kotlin_align_multiline_binary_operation = false
ij_kotlin_align_multiline_extends_list = false
Expand Down
61 changes: 59 additions & 2 deletions src/test/kotlin/com/github/avrokotlin/avro4k/AvroAssertions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -221,49 +221,106 @@ fun encodeToBytesUsingApacheLib(

internal inline fun <reified T> StringSpecRootScope.basicScalarEncodeDecodeTests(value: T, schema: Schema, apacheCompatibleValue: Any? = value) {
"support scalar type ${schema.type} serialization" {
Avro.schema<T>() shouldBe schema
testEncodeDecode(schema, value, apacheCompatibleValue = apacheCompatibleValue)
Avro.schema<TestGenericValueClass<T>>() shouldBe schema
testEncodeDecode(schema, TestGenericValueClass(value), apacheCompatibleValue = apacheCompatibleValue)

Avro.schema<T?>() shouldBe schema.nullable
testEncodeDecode<T?>(schema.nullable, value, apacheCompatibleValue = apacheCompatibleValue)
testEncodeDecode<T?>(schema.nullable, null)

Avro.schema<TestGenericValueClass<T?>>() shouldBe schema.nullable
testEncodeDecode(schema.nullable, TestGenericValueClass<T?>(value), apacheCompatibleValue = apacheCompatibleValue)
testEncodeDecode(schema.nullable, TestGenericValueClass<T?>(null), apacheCompatibleValue = null)
Avro.schema<TestGenericValueClass<T?>?>() shouldBe schema.nullable
testEncodeDecode<TestGenericValueClass<T?>?>(schema.nullable, null)
Avro.schema<TestGenericValueClass<T>?>() shouldBe schema.nullable
testEncodeDecode<TestGenericValueClass<T>?>(schema.nullable, null)
}
"scalar type ${schema.type} in record" {
val record =
SchemaBuilder.record("theRecord").fields()
.name("field").type(schema).noDefault()
.endRecord()

Avro.schema<TestGenericRecord<T>>() shouldBe record
Avro.schema<TestGenericRecord<TestGenericValueClass<T>>>() shouldBe record
testEncodeDecode(record, TestGenericRecord(value), apacheCompatibleValue = GenericData.Record(record).also { it.put(0, apacheCompatibleValue) })
testEncodeDecode(record, TestGenericRecord(TestGenericValueClass(value)), apacheCompatibleValue = GenericData.Record(record).also { it.put(0, apacheCompatibleValue) })

val expectedRecordSchemaNullable =
SchemaBuilder.record("theRecord").fields()
.name("field").type(schema.nullable).withDefault(null)
.endRecord()
Avro.schema<TestGenericRecord<T?>>() shouldBe expectedRecordSchemaNullable
Avro.schema<TestGenericRecord<TestGenericValueClass<T?>>>() shouldBe expectedRecordSchemaNullable
Avro.schema<TestGenericRecord<TestGenericValueClass<T?>?>>() shouldBe expectedRecordSchemaNullable
Avro.schema<TestGenericRecord<TestGenericValueClass<T>?>>() shouldBe expectedRecordSchemaNullable

val recordNullable =
SchemaBuilder.record("theRecord").fields()
.name("field").type(schema.nullable).noDefault()
.endRecord()
testEncodeDecode(recordNullable, TestGenericRecord<T?>(value), apacheCompatibleValue = GenericData.Record(recordNullable).also { it.put(0, apacheCompatibleValue) })
testEncodeDecode(recordNullable, TestGenericRecord<T?>(null), apacheCompatibleValue = GenericData.Record(recordNullable).also { it.put(0, null) })
testEncodeDecode(recordNullable, TestGenericRecord(TestGenericValueClass<T?>(value)), apacheCompatibleValue = GenericData.Record(recordNullable).also { it.put(0, apacheCompatibleValue) })
testEncodeDecode(
recordNullable,
TestGenericRecord(TestGenericValueClass<T?>(value)),
apacheCompatibleValue = GenericData.Record(recordNullable).also { it.put(0, apacheCompatibleValue) }
)
testEncodeDecode(recordNullable, TestGenericRecord(TestGenericValueClass<T?>(null)), apacheCompatibleValue = GenericData.Record(recordNullable).also { it.put(0, null) })
}
"scalar type ${schema.type} in map" {
val map = SchemaBuilder.map().values(schema)
Avro.schema<Map<String, T>>() shouldBe map
Avro.schema<Map<String, TestGenericValueClass<T>>>() shouldBe map
Avro.schema<Map<T, TestGenericValueClass<T>>>() shouldBe map
Avro.schema<Map<TestGenericValueClass<T>, TestGenericValueClass<T>>>() shouldBe map
Avro.schema<Map<T, T>>() shouldBe map
Avro.schema<Map<TestGenericValueClass<T>, T>>() shouldBe map
testEncodeDecode(map, mapOf("key" to value), apacheCompatibleValue = mapOf("key" to apacheCompatibleValue))
testEncodeDecode(map, mapOf("key" to TestGenericValueClass(value)), apacheCompatibleValue = mapOf("key" to apacheCompatibleValue))

val mapNullable = SchemaBuilder.map().values(schema.nullable)
Avro.schema<Map<String, T?>>() shouldBe mapNullable
Avro.schema<Map<String, TestGenericValueClass<T?>>>() shouldBe mapNullable
Avro.schema<Map<String, TestGenericValueClass<T?>?>>() shouldBe mapNullable
Avro.schema<Map<String, TestGenericValueClass<T>?>>() shouldBe mapNullable
Avro.schema<Map<T, TestGenericValueClass<T?>>>() shouldBe mapNullable
Avro.schema<Map<T, TestGenericValueClass<T?>?>>() shouldBe mapNullable
Avro.schema<Map<T, TestGenericValueClass<T>?>>() shouldBe mapNullable
Avro.schema<Map<TestGenericValueClass<T>, TestGenericValueClass<T?>>>() shouldBe mapNullable
Avro.schema<Map<TestGenericValueClass<T>, TestGenericValueClass<T?>?>>() shouldBe mapNullable
Avro.schema<Map<TestGenericValueClass<T>, TestGenericValueClass<T>?>>() shouldBe mapNullable
Avro.schema<Map<T, T?>>() shouldBe mapNullable
Avro.schema<Map<TestGenericValueClass<T>, T?>>() shouldBe mapNullable
testEncodeDecode(mapNullable, mapOf("key" to TestGenericValueClass<T?>(value)), apacheCompatibleValue = mapOf("key" to apacheCompatibleValue))
testEncodeDecode(mapNullable, mapOf("key" to TestGenericValueClass<T?>(null)), apacheCompatibleValue = mapOf("key" to null))
}
"scalar type ${schema.type} in array" {
val array = SchemaBuilder.array().items(schema)
Avro.schema<List<T>>() shouldBe array
Avro.schema<List<TestGenericValueClass<T>>>() shouldBe array
Avro.schema<Set<T>>() shouldBe array
Avro.schema<Set<TestGenericValueClass<T>>>() shouldBe array
Avro.schema<Array<T>>() shouldBe array
Avro.schema<Array<TestGenericValueClass<T>>>() shouldBe array
testEncodeDecode(array, listOf(value), apacheCompatibleValue = listOf(apacheCompatibleValue))
testEncodeDecode(array, listOf(TestGenericValueClass(value)), apacheCompatibleValue = listOf(apacheCompatibleValue))

val arrayNullable = SchemaBuilder.array().items(schema.nullable)
Avro.schema<List<T?>>() shouldBe arrayNullable
Avro.schema<List<TestGenericValueClass<T?>>>() shouldBe arrayNullable
Avro.schema<List<TestGenericValueClass<T?>?>>() shouldBe arrayNullable
Avro.schema<List<TestGenericValueClass<T>?>>() shouldBe arrayNullable
Avro.schema<Set<T?>>() shouldBe arrayNullable
Avro.schema<Set<TestGenericValueClass<T>?>>() shouldBe arrayNullable
Avro.schema<Set<TestGenericValueClass<T?>?>>() shouldBe arrayNullable
Avro.schema<Set<TestGenericValueClass<T>?>>() shouldBe arrayNullable
Avro.schema<Array<T?>>() shouldBe arrayNullable
Avro.schema<Array<TestGenericValueClass<T>?>>() shouldBe arrayNullable
Avro.schema<Array<TestGenericValueClass<T?>?>>() shouldBe arrayNullable
Avro.schema<Array<TestGenericValueClass<T>?>>() shouldBe arrayNullable
testEncodeDecode(arrayNullable, listOf(TestGenericValueClass<T?>(value)), apacheCompatibleValue = listOf(apacheCompatibleValue))
testEncodeDecode(arrayNullable, listOf(TestGenericValueClass<T?>(null)), apacheCompatibleValue = listOf(null))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.github.avrokotlin.avro4k.schema
import com.github.avrokotlin.avro4k.serializer.UUIDSerializer
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
Expand All @@ -21,10 +22,21 @@ import org.apache.avro.SchemaBuilder
import org.apache.avro.generic.GenericData

internal class EnumEncodingTest : StringSpec({
val expectedEnumSchema = SchemaBuilder.enumeration(Cream::class.qualifiedName).symbols("Bruce", "Baker", "Clapton")
basicScalarEncodeDecodeTests<Cream>(Cream.Bruce, expectedEnumSchema, apacheCompatibleValue = GenericData.EnumSymbol(expectedEnumSchema, "Bruce"))

basicScalarEncodeDecodeTests(Cream.Bruce, Avro.schema<Cream>(), apacheCompatibleValue = GenericData.EnumSymbol(Avro.schema<Cream>(), "Bruce"))
"Only allow 1 @AvroEnumDefault at max" {
shouldThrow<UnsupportedOperationException> {
Avro.schema<BadEnumWithManyDefaults>()
}
}

"Decoding enum with an unknown symbol uses @AvroEnumDefault value" {
Avro.schema<EnumV2>() shouldBe
SchemaBuilder.enumeration("Enum")
.defaultSymbol("UNKNOWN")
.symbols("UNKNOWN", "A", "B")

AvroAssertions.assertThat(EnumV2WrapperRecord(EnumV2.B))
.isEncodedAs(record(GenericData.EnumSymbol(Avro.schema<EnumV2>(), "B")))
.isDecodedAs(EnumV1WrapperRecord(EnumV1.UNKNOWN))
Expand Down Expand Up @@ -71,6 +83,15 @@ internal class EnumEncodingTest : StringSpec({
A,
}

@Serializable
private enum class BadEnumWithManyDefaults {
@AvroEnumDefault
DEF1,

@AvroEnumDefault
DEF2,
}

@Serializable
@SerialName("Enum")
private enum class EnumV1WithoutDefault {
Expand Down

0 comments on commit 9348a8d

Please sign in to comment.