From 16b56c18bf363d05b5c974ff2ac4818e8b3074d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fa=C3=A7=20Eldenk?= Date: Mon, 7 Aug 2023 20:47:36 +0300 Subject: [PATCH 1/3] add conformance tests using test_messages_proto3 construct google provides --- .../protobuf/conformance/Proto3EnumTest.kt | 89 ++++++ .../protobuf/conformance/Proto3MapTest.kt | 128 ++++++++ .../protobuf/conformance/Proto3MessageTest.kt | 65 ++++ .../protobuf/conformance/Proto3OneofTest.kt | 75 +++++ .../protobuf/conformance/Proto3PackedTest.kt | 69 +++++ .../conformance/Proto3PrimitiveTest.kt | 74 +++++ .../conformance/Proto3RepeatedTest.kt | 95 ++++++ .../conformance/Proto3UnpackedTest.kt | 69 +++++ .../testProto/test_messages_proto3.proto | 289 ++++++++++++++++++ 9 files changed, 953 insertions(+) create mode 100644 formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3EnumTest.kt create mode 100644 formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MapTest.kt create mode 100644 formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MessageTest.kt create mode 100644 formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3OneofTest.kt create mode 100644 formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PackedTest.kt create mode 100644 formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PrimitiveTest.kt create mode 100644 formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3RepeatedTest.kt create mode 100644 formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3UnpackedTest.kt create mode 100644 formats/protobuf/testProto/test_messages_proto3.proto diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3EnumTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3EnumTest.kt new file mode 100644 index 000000000..2512b5eee --- /dev/null +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3EnumTest.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.protobuf.conformance + +import com.google.protobuf_test_messages.proto3.* +import kotlinx.serialization.* +import kotlinx.serialization.protobuf.* +import kotlin.test.* + +@Serializable +data class KTestMessagesProto3Enum( + @ProtoNumber(21) val optionalNestedEnum: KNestedEnum = KNestedEnum.FOO, + @ProtoNumber(22) val optionalForeignEnum: KForeignEnum = KForeignEnum.FOREIGN_FOO, + @ProtoNumber(23) val optionalAliasedEnum: KAliasedEnum = KAliasedEnum.ALIAS_FOO, +) { + enum class KNestedEnum { + @ProtoNumber(0) + FOO, + + @ProtoNumber(1) + BAR, + + @ProtoNumber(2) + BAZ; +// @ProtoNumber(-1) +// NEG; + + fun toProto() = TestMessagesProto3.TestAllTypesProto3.NestedEnum.valueOf(this.name) + } + + + enum class KAliasedEnum { + @ProtoNumber(0) + ALIAS_FOO, + + @ProtoNumber(1) + ALIAS_BAR, + + @ProtoNumber(2) + ALIAS_BAZ, + + @ProtoNumber(2) + MOO, + + @ProtoNumber(2) + moo, + + @ProtoNumber(2) + bAz; + + fun toProto() = TestMessagesProto3.TestAllTypesProto3.AliasedEnum.valueOf(this.name) + } +} + +enum class KForeignEnum { + @ProtoNumber(0) + FOREIGN_FOO, + + @ProtoNumber(1) + FOREIGN_BAR, + + @ProtoNumber(2) + FOREIGN_BAZ; + + fun toProto() = TestMessagesProto3.ForeignEnum.valueOf(this.name) +} + +class Proto3EnumTest { + @Test + fun default() { + val message = KTestMessagesProto3Enum( + optionalNestedEnum = KTestMessagesProto3Enum.KNestedEnum.BAR, + optionalForeignEnum = KForeignEnum.FOREIGN_BAR, + optionalAliasedEnum = KTestMessagesProto3Enum.KAliasedEnum.ALIAS_BAR + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + assertEquals(message.optionalNestedEnum.toProto(), restored.optionalNestedEnum) + assertEquals(message.optionalForeignEnum.toProto(), restored.optionalForeignEnum) + assertEquals(message.optionalAliasedEnum.toProto(), restored.optionalAliasedEnum) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message, restoredMessage) + } +} diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MapTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MapTest.kt new file mode 100644 index 000000000..b2b9832e2 --- /dev/null +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MapTest.kt @@ -0,0 +1,128 @@ +/* + * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.protobuf.conformance + +import com.google.protobuf_test_messages.proto3.* +import io.kotlintest.properties.* +import kotlinx.serialization.* +import kotlinx.serialization.protobuf.* +import kotlin.test.* + +@Serializable +data class KTestMessagesProto3Map( + @ProtoNumber(56) val mapInt32Int32: Map = emptyMap(), + @ProtoNumber(57) val mapInt64Int64: Map = emptyMap(), + @ProtoNumber(58) val mapUint32Uint32: Map = emptyMap(), + @ProtoNumber(59) val mapUint64Uint64: Map = emptyMap(), + @ProtoNumber(60) val mapSint32Sint32: Map = emptyMap(), + @ProtoNumber(61) val mapSint64Sint64: Map = emptyMap(), +// @ProtoNumber(62) val mapFixed32Fixed32: Map = emptyMap(), +// @ProtoNumber(63) val mapFixed64Fixed64: Map = emptyMap(), +// @ProtoNumber(64) val mapSfixed32Sfixed32: Map = emptyMap(), +// @ProtoNumber(65) val mapSfixed64Sfixed64: Map = emptyMap(), + @ProtoNumber(66) val mapInt32Float: Map = emptyMap(), + @ProtoNumber(67) val mapInt32Double: Map = emptyMap(), + @ProtoNumber(68) val mapBoolBool: Map = emptyMap(), + @ProtoNumber(69) val mapStringString: Map = emptyMap(), +// @ProtoNumber(70) val mapStringBytes: Map = emptyMap(), + @ProtoNumber(71) val mapStringNestedMessage: Map = emptyMap(), + @ProtoNumber(72) val mapStringForeignMessage: Map = emptyMap(), + @ProtoNumber(73) val mapStringNestedEnum: Map = emptyMap(), + @ProtoNumber(74) val mapStringForeignEnum: Map = emptyMap(), +) + +class Proto3MapTest { + @Test + fun default() { + val message = KTestMessagesProto3Map( + mapInt32Int32 = Gen.map(Gen.int(), Gen.int()).generate(), + mapInt64Int64 = Gen.map(Gen.long(), Gen.long()).generate(), + mapUint32Uint32 = Gen.map(Gen.int().map { it.toUInt() }, Gen.int().map { it.toUInt() }).generate(), + mapUint64Uint64 = Gen.map(Gen.int().map { it.toULong() }, Gen.int().map { it.toULong() }).generate(), +// mapSint32Sint32 = Gen.map(Gen.int(), Gen.int()).generate(), +// mapSint64Sint64 = Gen.map(Gen.long(), Gen.long()).generate(), +// mapFixed32Fixed32 = Gen.map(Gen.int(), Gen.int()).generate(), +// mapFixed64Fixed64 = Gen.map(Gen.long(), Gen.long()).generate(), +// mapSfixed32Sfixed32 = Gen.map(Gen.int(), Gen.int()).generate(), +// mapSfixed64Sfixed64 = Gen.map(Gen.long(), Gen.long()).generate(), + mapInt32Float = Gen.map(Gen.int(), Gen.float()).generate(), + mapInt32Double = Gen.map(Gen.int(), Gen.double()).generate(), + mapBoolBool = Gen.map(Gen.bool(), Gen.bool()).generate(), + mapStringString = Gen.map(Gen.string(), Gen.string()).generate(), +// mapStringBytes = Gen.map(Gen.string(), Gen.byteArray()).generate(), + mapStringNestedMessage = mapOf( + "asd_1" to KTestMessagesProto3Message.KNestedMessage( + 1, + null + ), + "asi_#" to KTestMessagesProto3Message.KNestedMessage( + 2, + KTestMessagesProto3Message( + KTestMessagesProto3Message.KNestedMessage(3, null), + ) + ) + ), + mapStringForeignMessage = mapOf( + "" to KForeignMessage(1), + "-2" to KForeignMessage(-12), + ), + mapStringNestedEnum = Gen.map( + Gen.string(), Gen.oneOf( + KTestMessagesProto3Enum.KNestedEnum.entries, + ) + ).generate(), + mapStringForeignEnum = Gen.map( + Gen.string(), Gen.oneOf( + KForeignEnum.entries, + ) + ).generate(), + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + + assertEquals(message.mapInt32Int32, restored.mapInt32Int32Map) + assertEquals(message.mapInt64Int64, restored.mapInt64Int64Map) + assertEquals( + message.mapUint32Uint32, + restored.mapUint32Uint32Map.map { it.key.toUInt() to it.value.toUInt() }.toMap() + ) + assertEquals( + message.mapUint64Uint64, + restored.mapUint64Uint64Map.map { it.key.toULong() to it.value.toULong() }.toMap() + ) +// assertEquals(message.mapSint32Sint32, restored.mapSint32Sint32Map) +// assertEquals(message.mapSint64Sint64, restored.mapSint64Sint64Map) +// assertEquals(message.mapFixed32Fixed32, restored.mapFixed32Fixed32Map) +// assertEquals(message.mapFixed64Fixed64, restored.mapFixed64Fixed64Map) +// assertEquals(message.mapSfixed32Sfixed32, restored.mapSfixed32Sfixed32Map) +// assertEquals(message.mapSfixed64Sfixed64, restored.mapSfixed64Sfixed64Map) + assertEquals(message.mapInt32Float, restored.mapInt32FloatMap) + assertEquals(message.mapInt32Double, restored.mapInt32DoubleMap) + assertEquals(message.mapBoolBool, restored.mapBoolBoolMap) + assertEquals(message.mapStringString, restored.mapStringStringMap) +// assertEquals(message.mapStringBytes, restored.mapStringBytesMap) + assertEquals( + message.mapStringNestedMessage.mapValues { it.value.toProto() }, + restored.mapStringNestedMessageMap + ) + assertEquals( + message.mapStringForeignMessage.mapValues { it.value.toProto() }, + restored.mapStringForeignMessageMap + ) + assertEquals( + message.mapStringNestedEnum.mapValues { it.value.name }, + restored.mapStringNestedEnumMap.mapValues { it.value.name }, + ) + assertEquals( + message.mapStringForeignEnum.mapValues { it.value.name }, + restored.mapStringForeignEnumMap.mapValues { it.value.name } + ) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message, restoredMessage) + } +} diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MessageTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MessageTest.kt new file mode 100644 index 000000000..c369d6ebb --- /dev/null +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MessageTest.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.protobuf.conformance + +import com.google.protobuf_test_messages.proto3.* +import kotlinx.serialization.* +import kotlinx.serialization.protobuf.* +import kotlin.test.* + +@Serializable +data class KTestMessagesProto3Message( + @ProtoNumber(18) val optionalNestedMessage: KNestedMessage? = null, + @ProtoNumber(19) val optionalForeignMessage: KForeignMessage? = null, +) { + @Serializable + data class KNestedMessage( + @ProtoNumber(1) val a: Int = 0, + @ProtoNumber(2) val corecursive: KTestMessagesProto3Message? = null, + ) { + fun toProto(): TestMessagesProto3.TestAllTypesProto3.NestedMessage = + TestMessagesProto3.TestAllTypesProto3.NestedMessage.parseFrom( + ProtoBuf.encodeToByteArray(this) + ) + } +} + +@Serializable +data class KForeignMessage( + @ProtoNumber(1) val c: Int = 0, +) { + fun toProto(): TestMessagesProto3.ForeignMessage = + TestMessagesProto3.ForeignMessage.parseFrom( + ProtoBuf.encodeToByteArray(this) + ) +} + +class Proto3MessageTest { + @Test + fun default() { + val message = KTestMessagesProto3Message( + optionalNestedMessage = KTestMessagesProto3Message.KNestedMessage( + a = 150, + corecursive = KTestMessagesProto3Message( + optionalNestedMessage = KTestMessagesProto3Message.KNestedMessage( + a = 42, + ) + ) + ), + optionalForeignMessage = KForeignMessage( + c = 150, + ) + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + assertEquals(message.optionalNestedMessage?.a, restored.optionalNestedMessage.a) + assertEquals( + message.optionalNestedMessage?.corecursive?.optionalNestedMessage?.a, + restored.optionalNestedMessage.corecursive.optionalNestedMessage.a + ) + assertEquals(message.optionalForeignMessage?.c, restored.optionalForeignMessage.c) + } +} diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3OneofTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3OneofTest.kt new file mode 100644 index 000000000..1a473085d --- /dev/null +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3OneofTest.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.protobuf.conformance + +import com.google.protobuf_test_messages.proto3.* +import kotlinx.serialization.* +import kotlinx.serialization.protobuf.* +import kotlin.test.* + +@Serializable +data class KTestMessageProto3Oneof( + @ProtoNumber(111) val oneofUint32: UInt? = null, + @ProtoNumber(112) val oneofNestedMessage: KTestMessagesProto3Message.KNestedMessage? = null, + @ProtoNumber(113) val oneofString: String? = null, + @ProtoNumber(114) val oneofBytes: ByteArray? = null, + @ProtoNumber(115) val oneofBool: Boolean? = null, + @ProtoNumber(116) val oneofUint64: ULong? = null, + @ProtoNumber(117) val oneofFloat: Float? = null, + @ProtoNumber(118) val oneofDouble: Double? = null, + @ProtoNumber(119) val oneofEnum: KTestMessagesProto3Enum.KNestedEnum? = null, +) { + init { + require( + listOf( + oneofUint32, + oneofNestedMessage, + oneofString, + oneofBytes, + oneofBool, + oneofUint64, + oneofFloat, + oneofDouble, + oneofEnum, + ).count { it != null } == 1 + ) + } +} + +class Proto3OneofTest { + @Test + fun default() { + listOf( + KTestMessageProto3Oneof(oneofUint32 = 150u), + KTestMessageProto3Oneof(oneofNestedMessage = KTestMessagesProto3Message.KNestedMessage(a = 150)), + KTestMessageProto3Oneof(oneofString = "150"), + KTestMessageProto3Oneof(oneofBytes = "150".toByteArray()), + KTestMessageProto3Oneof(oneofBool = true), + KTestMessageProto3Oneof(oneofUint64 = 150uL), + KTestMessageProto3Oneof(oneofFloat = 150f), + KTestMessageProto3Oneof(oneofDouble = 150.0), + KTestMessageProto3Oneof(oneofEnum = KTestMessagesProto3Enum.KNestedEnum.BAR), + ).forEach { message -> + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + if (restored.hasOneofUint32()) assertEquals(message.oneofUint32, restored.oneofUint32.toUInt()) + if (restored.hasOneofNestedMessage()) assertEquals( + message.oneofNestedMessage?.a, + restored.oneofNestedMessage?.a + ) + if (restored.hasOneofString()) assertEquals(message.oneofString, restored.oneofString) + if (restored.hasOneofBytes()) assertContentEquals(message.oneofBytes, restored.oneofBytes.toByteArray()) + if (restored.hasOneofBool()) assertEquals(message.oneofBool, restored.oneofBool) + if (restored.hasOneofUint64()) assertEquals(message.oneofUint64, restored.oneofUint64.toULong()) + if (restored.hasOneofFloat()) assertEquals(message.oneofFloat, restored.oneofFloat) + if (restored.hasOneofDouble()) assertEquals(message.oneofDouble, restored.oneofDouble) + if (restored.hasOneofEnum()) assertEquals(message.oneofEnum?.name, restored.oneofEnum?.name) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message, restoredMessage.copy(oneofBytes = message.oneofBytes)) + assertContentEquals(message.oneofBytes, restoredMessage.oneofBytes) + } + } +} diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PackedTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PackedTest.kt new file mode 100644 index 000000000..5031f1be4 --- /dev/null +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PackedTest.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.protobuf.conformance + +import com.google.protobuf_test_messages.proto3.* +import io.kotlintest.properties.* +import kotlinx.serialization.* +import kotlinx.serialization.protobuf.* +import kotlin.test.* + +@Serializable +data class KTestMessagesProto3Packed( + @ProtoNumber(75) @ProtoPacked val packedInt32: List = emptyList(), + @ProtoNumber(76) @ProtoPacked val packedInt64: List = emptyList(), +// @ProtoNumber(77) @ProtoPacked val packedUint32: List = emptyList(), +// @ProtoNumber(78) @ProtoPacked val packedUint64: List = emptyList(), + @ProtoNumber(79) @ProtoPacked val packedSint32: List = emptyList(), + @ProtoNumber(80) @ProtoPacked val packedSint64: List = emptyList(), +// @ProtoNumber(81) @ProtoPacked val packedFixed32: List = emptyList(), +// @ProtoNumber(82) @ProtoPacked val packedFixed64: List = emptyList(), +// @ProtoNumber(83) @ProtoPacked val packedSfixed32: List = emptyList(), +// @ProtoNumber(84) @ProtoPacked val packedSfixed64: List = emptyList(), + @ProtoNumber(85) @ProtoPacked val packedFloat: List = emptyList(), + @ProtoNumber(86) @ProtoPacked val packedDouble: List = emptyList(), + @ProtoNumber(87) @ProtoPacked val packedBool: List = emptyList(), +) + +class Proto3PackedTest { + @Test + fun default() { + val message = KTestMessagesProto3Packed( + packedInt32 = Gen.list(Gen.int()).generate(), + packedInt64 = Gen.list(Gen.long()).generate(), +// packedUint32 = Gen.list(Gen.int().map { it.toUInt() }).generate(), +// packedUint64 = Gen.list(Gen.long().map { it.toULong() }).generate(), + packedSint32 = Gen.list(Gen.int()).generate(), + packedSint64 = Gen.list(Gen.long()).generate(), +// packedFixed32 = Gen.list(Gen.int()).generate(), +// packedFixed64 = Gen.list(Gen.long()).generate(), +// packedSfixed32 = Gen.list(Gen.int()).generate(), +// packedSfixed64 = Gen.list(Gen.long()).generate(), + packedFloat = Gen.list(Gen.float()).generate(), + packedDouble = Gen.list(Gen.double()).generate(), + packedBool = Gen.list(Gen.bool()).generate(), + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + assertEquals(message.packedInt32, restored.packedInt32List) + assertEquals(message.packedInt64, restored.packedInt64List) +// assertEquals(message.packedUint32, restored.packedUint32List.map { it.toUInt() }) +// assertEquals(message.packedUint64, restored.packedUint64List.map { it.toULong() }) +// assertEquals(message.packedSint32, restored.packedSint32List) +// assertEquals(message.packedSint64, restored.packedSint64List) +// assertEquals(message.packedFixed32, restored.packedFixed32List) +// assertEquals(message.packedFixed64, restored.packedFixed64List) +// assertEquals(message.packedSfixed32, restored.packedSfixed32List) +// assertEquals(message.packedSfixed64, restored.packedSfixed64List) + assertEquals(message.packedFloat, restored.packedFloatList) + assertEquals(message.packedDouble, restored.packedDoubleList) + assertEquals(message.packedBool, restored.packedBoolList) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message, restoredMessage) + } +} diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PrimitiveTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PrimitiveTest.kt new file mode 100644 index 000000000..93f87c3c3 --- /dev/null +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PrimitiveTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.protobuf.conformance + +import com.google.protobuf_test_messages.proto3.* +import kotlinx.serialization.* +import kotlinx.serialization.protobuf.* +import kotlin.test.* + +@Serializable +data class KTestMessagesProto3Primitive( + @ProtoNumber(1) val optionalInt32: Int = 0, + @ProtoNumber(2) val optionalInt64: Long = 0, + @ProtoNumber(3) val optionalUint32: UInt = 0U, + @ProtoNumber(4) val optionalUint64: ULong = 0UL, + @ProtoNumber(5) @ProtoType(ProtoIntegerType.SIGNED) val optionalSint32: Int = 0, + @ProtoNumber(6) @ProtoType(ProtoIntegerType.SIGNED) val optionalSint64: Long = 0, + @ProtoNumber(7) @ProtoType(ProtoIntegerType.FIXED) val optionalFixed32: Int = 0, + @ProtoNumber(8) @ProtoType(ProtoIntegerType.FIXED) val optionalFixed64: Long = 0, + @ProtoNumber(9) @ProtoType(ProtoIntegerType.FIXED) val optionalSfixed32: Int = 0, + @ProtoNumber(10) @ProtoType(ProtoIntegerType.FIXED) val optionalSfixed64: Long = 0, + @ProtoNumber(11) val optionalFloat: Float = 0.0f, + @ProtoNumber(12) val optionalDouble: Double = 0.0, + @ProtoNumber(13) val optionalBool: Boolean = false, + @ProtoNumber(14) val optionalString: String = "", + @ProtoNumber(15) val optionalBytes: ByteArray = byteArrayOf(), +) + +class Proto3PrimitiveTest { + @Test + fun default() { + val message = KTestMessagesProto3Primitive( + optionalInt32 = Int.MAX_VALUE, + optionalInt64 = Long.MAX_VALUE, + optionalUint32 = UInt.MAX_VALUE, + optionalUint64 = ULong.MAX_VALUE, + optionalSint32 = Int.MAX_VALUE, + optionalSint64 = Long.MAX_VALUE, + optionalFixed32 = Int.MAX_VALUE, + optionalFixed64 = Long.MAX_VALUE, + optionalSfixed32 = Int.MAX_VALUE, + optionalSfixed64 = Long.MAX_VALUE, + optionalFloat = Float.MAX_VALUE, + optionalDouble = Double.MAX_VALUE, + optionalBool = true, + optionalString = "string", + optionalBytes = byteArrayOf(1, 2, 3, 4, 5) + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + assertEquals(message.optionalInt32, restored.optionalInt32) + assertEquals(message.optionalInt64, restored.optionalInt64) + assertEquals(message.optionalUint32, restored.optionalUint32.toUInt()) + assertEquals(message.optionalUint64, restored.optionalUint64.toULong()) + assertEquals(message.optionalSint32, restored.optionalSint32) + assertEquals(message.optionalSint64, restored.optionalSint64) + assertEquals(message.optionalFixed32, restored.optionalFixed32) + assertEquals(message.optionalFixed64, restored.optionalFixed64) + assertEquals(message.optionalSfixed32, restored.optionalSfixed32) + assertEquals(message.optionalSfixed64, restored.optionalSfixed64) + assertEquals(message.optionalFloat, restored.optionalFloat) + assertEquals(message.optionalDouble, restored.optionalDouble) + assertEquals(message.optionalBool, restored.optionalBool) + assertEquals(message.optionalString, restored.optionalString) + assertContentEquals(message.optionalBytes, restored.optionalBytes.toByteArray()) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message, restoredMessage.copy(optionalBytes = message.optionalBytes)) + } +} diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3RepeatedTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3RepeatedTest.kt new file mode 100644 index 000000000..88a11fe0f --- /dev/null +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3RepeatedTest.kt @@ -0,0 +1,95 @@ +/* + * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.protobuf.conformance + +import com.google.protobuf_test_messages.proto3.* +import io.kotlintest.properties.* +import kotlinx.serialization.* +import kotlinx.serialization.protobuf.* +import kotlin.test.* + +@Serializable +data class KTestMessagesProto3Repeated( + @ProtoNumber(31) @ProtoPacked val repeatedInt32: List = emptyList(), + @ProtoNumber(32) @ProtoPacked val repeatedInt64: List = emptyList(), +// @ProtoNumber(33) @ProtoPacked val repeatedUint32: List = emptyList(), +// @ProtoNumber(34) @ProtoPacked val repeatedUint64: List = emptyList(), +// @ProtoNumber(35) @ProtoPacked val repeatedSint32: List = emptyList(), +// @ProtoNumber(36) @ProtoPacked val repeatedSint64: List = emptyList(), +// @ProtoNumber(37) @ProtoPacked val repeatedFixed32: List = emptyList(), +// @ProtoNumber(38) @ProtoPacked val repeatedFixed64: List = emptyList(), +// @ProtoNumber(39) @ProtoPacked val repeatedSfixed32: List = emptyList(), +// @ProtoNumber(40) @ProtoPacked val repeatedSfixed64: List = emptyList(), + @ProtoNumber(41) @ProtoPacked val repeatedFloat: List = emptyList(), + @ProtoNumber(42) @ProtoPacked val repeatedDouble: List = emptyList(), + @ProtoNumber(43) @ProtoPacked val repeatedBool: List = emptyList(), + @ProtoNumber(44) val repeatedString: List = emptyList(), +// @ProtoNumber(45) val repeatedBytes: List = emptyList(), + @ProtoNumber(48) val repeatedNestedMessages: List = emptyList(), + @ProtoNumber(49) val repeatedForeignMessages: List = emptyList(), +) + +class Proto3RepeatedTest { + @Test + fun default() { + val message = KTestMessagesProto3Repeated( + repeatedInt32 = Gen.list(Gen.int()).generate(), + repeatedInt64 = Gen.list(Gen.long()).generate(), +// repeatedUint32 = Gen.list(Gen.int().map { it.toUInt() }).generate(), +// repeatedUint64 = Gen.list(Gen.long().map { it.toULong() }).generate(), +// repeatedSint32 = Gen.list(Gen.int()).generate(), +// repeatedSint64 = Gen.list(Gen.long()).generate(), +// repeatedFixed32 = Gen.list(Gen.int()).generate(), +// repeatedFixed64 = Gen.list(Gen.long()).generate(), +// repeatedSfixed32 = Gen.list(Gen.int()).generate(), +// repeatedSfixed64 = Gen.list(Gen.long()).generate(), + repeatedFloat = Gen.list(Gen.float()).generate(), + repeatedDouble = Gen.list(Gen.double()).generate(), + repeatedBool = Gen.list(Gen.bool()).generate(), + repeatedString = Gen.list(Gen.string()).generate(), +// repeatedBytes = Gen.list(Gen.string().map { it.toByteArray() }).generate(), + repeatedNestedMessages = listOf( + KTestMessagesProto3Message.KNestedMessage( + 1, + null + ), + KTestMessagesProto3Message.KNestedMessage( + 2, + KTestMessagesProto3Message( + KTestMessagesProto3Message.KNestedMessage(3, null), + ) + ) + ), + repeatedForeignMessages = listOf( + KForeignMessage(1), + KForeignMessage(-12), + ) + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + assertEquals(message.repeatedInt32, restored.repeatedInt32List) + assertEquals(message.repeatedInt64, restored.repeatedInt64List) +// assertEquals(message.repeatedUint32, restored.repeatedUint32List.map { it.toUInt() }) +// assertEquals(message.repeatedUint64, restored.repeatedUint64List.map { it.toULong() }) +// assertEquals(message.repeatedSint32, restored.repeatedSint32List) +// assertEquals(message.repeatedSint64, restored.repeatedSint64List) +// assertEquals(message.repeatedFixed32, restored.repeatedFixed32List) +// assertEquals(message.repeatedFixed64, restored.repeatedFixed64List) +// assertEquals(message.repeatedSfixed32, restored.repeatedSfixed32List) +// assertEquals(message.repeatedSfixed64, restored.repeatedSfixed64List) + assertEquals(message.repeatedFloat, restored.repeatedFloatList) + assertEquals(message.repeatedDouble, restored.repeatedDoubleList) + assertEquals(message.repeatedBool, restored.repeatedBoolList) + assertEquals(message.repeatedString, restored.repeatedStringList) +// assertEquals(message.repeatedBytes.map { it.toList() }, restored.repeatedBytesList.map { it.toList() }) + assertEquals(message.repeatedNestedMessages.map { it.toProto() }, restored.repeatedNestedMessageList) + assertEquals(message.repeatedForeignMessages.map { it.toProto() }, restored.repeatedForeignMessageList) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message, restoredMessage) + } +} diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3UnpackedTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3UnpackedTest.kt new file mode 100644 index 000000000..b4477a9d1 --- /dev/null +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3UnpackedTest.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.protobuf.conformance + +import com.google.protobuf_test_messages.proto3.* +import io.kotlintest.properties.* +import kotlinx.serialization.* +import kotlinx.serialization.protobuf.* +import kotlin.test.* + +@Serializable +data class KTestMessagesProto3Unpacked( + @ProtoNumber(89) val unpackedInt32: List = emptyList(), + @ProtoNumber(90) val unpackedInt64: List = emptyList(), + @ProtoNumber(91) val unpackedUint32: List = emptyList(), + @ProtoNumber(92) val unpackedUint64: List = emptyList(), + @ProtoNumber(93) val unpackedSint32: List = emptyList(), + @ProtoNumber(94) val unpackedSint64: List = emptyList(), + @ProtoNumber(95) val unpackedFixed32: List = emptyList(), + @ProtoNumber(96) val unpackedFixed64: List = emptyList(), + @ProtoNumber(97) val unpackedSfixed32: List = emptyList(), + @ProtoNumber(98) val unpackedSfixed64: List = emptyList(), + @ProtoNumber(99) val unpackedFloat: List = emptyList(), + @ProtoNumber(100) val unpackedDouble: List = emptyList(), + @ProtoNumber(101) val unpackedBool: List = emptyList(), +) + +class Proto3UnpackedTest { + @Test + fun default() { + val message = KTestMessagesProto3Unpacked( + unpackedInt32 = Gen.list(Gen.int()).generate(), + unpackedInt64 = Gen.list(Gen.long()).generate(), + unpackedUint32 = Gen.list(Gen.int().map { it.toUInt() }).generate(), + unpackedUint64 = Gen.list(Gen.long().map { it.toULong() }).generate(), + unpackedSint32 = Gen.list(Gen.int()).generate(), + unpackedSint64 = Gen.list(Gen.long()).generate(), + unpackedFixed32 = Gen.list(Gen.int()).generate(), + unpackedFixed64 = Gen.list(Gen.long()).generate(), + unpackedSfixed32 = Gen.list(Gen.int()).generate(), + unpackedSfixed64 = Gen.list(Gen.long()).generate(), + unpackedFloat = Gen.list(Gen.float()).generate(), + unpackedDouble = Gen.list(Gen.double()).generate(), + unpackedBool = Gen.list(Gen.bool()).generate(), + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + assertEquals(message.unpackedInt32, restored.unpackedInt32List) + assertEquals(message.unpackedInt64, restored.unpackedInt64List) + assertEquals(message.unpackedUint32, restored.unpackedUint32List.map { it.toUInt() }) + assertEquals(message.unpackedUint64, restored.unpackedUint64List.map { it.toULong() }) + //assertEquals(message.unpackedSint32, restored.unpackedSint32List) + //assertEquals(message.unpackedSint64, restored.unpackedSint64List) + //assertEquals(message.unpackedFixed32, restored.unpackedFixed32List) + //assertEquals(message.unpackedFixed64, restored.unpackedFixed64List) + //assertEquals(message.unpackedSfixed32, restored.unpackedSfixed32List) + //assertEquals(message.unpackedSfixed64, restored.unpackedSfixed64List) + assertEquals(message.unpackedFloat, restored.unpackedFloatList) + assertEquals(message.unpackedDouble, restored.unpackedDoubleList) + assertEquals(message.unpackedBool, restored.unpackedBoolList) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message, restoredMessage) + } +} diff --git a/formats/protobuf/testProto/test_messages_proto3.proto b/formats/protobuf/testProto/test_messages_proto3.proto new file mode 100644 index 000000000..6b2799571 --- /dev/null +++ b/formats/protobuf/testProto/test_messages_proto3.proto @@ -0,0 +1,289 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Test schema for proto3 messages. This test schema is used by: +// +// - benchmarks +// - fuzz tests +// - conformance tests +// +// https://github.com/protocolbuffers/protobuf/blob/5e03386555544e39c21236dca0097123edec8769/src/google/protobuf/test_messages_proto3.proto + +syntax = "proto3"; + +package protobuf_test_messages.proto3; + +option java_package = "com.google.protobuf_test_messages.proto3"; +option objc_class_prefix = "Proto3"; + +// This is the default, but we specify it here explicitly. +option optimize_for = SPEED; + +import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; + +option cc_enable_arenas = true; + +// This proto includes every type of field in both singular and repeated +// forms. +// +// Also, crucially, all messages and enums in this file are eventually +// submessages of this message. So for example, a fuzz test of TestAllTypes +// could trigger bugs that occur in any message type in this file. We verify +// this stays true in a unit test. +message TestAllTypesProto3 { + message NestedMessage { + int32 a = 1; + TestAllTypesProto3 corecursive = 2; + } + + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + NEG = -1; // Intentionally negative. + } + + enum AliasedEnum { + option allow_alias = true; + + ALIAS_FOO = 0; + ALIAS_BAR = 1; + ALIAS_BAZ = 2; + MOO = 2; + moo = 2; + bAz = 2; + } + + // Singular + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; + + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; + AliasedEnum optional_aliased_enum = 23; + + string optional_string_piece = 24 [ctype = STRING_PIECE]; + string optional_cord = 25 [ctype = CORD]; + + TestAllTypesProto3 recursive_message = 27; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + + repeated string repeated_string_piece = 54 [ctype = STRING_PIECE]; + repeated string repeated_cord = 55 [ctype = CORD]; + + // Packed + repeated int32 packed_int32 = 75 [packed = true]; + repeated int64 packed_int64 = 76 [packed = true]; + repeated uint32 packed_uint32 = 77 [packed = true]; + repeated uint64 packed_uint64 = 78 [packed = true]; + repeated sint32 packed_sint32 = 79 [packed = true]; + repeated sint64 packed_sint64 = 80 [packed = true]; + repeated fixed32 packed_fixed32 = 81 [packed = true]; + repeated fixed64 packed_fixed64 = 82 [packed = true]; + repeated sfixed32 packed_sfixed32 = 83 [packed = true]; + repeated sfixed64 packed_sfixed64 = 84 [packed = true]; + repeated float packed_float = 85 [packed = true]; + repeated double packed_double = 86 [packed = true]; + repeated bool packed_bool = 87 [packed = true]; + repeated NestedEnum packed_nested_enum = 88 [packed = true]; + + // Unpacked + repeated int32 unpacked_int32 = 89 [packed = false]; + repeated int64 unpacked_int64 = 90 [packed = false]; + repeated uint32 unpacked_uint32 = 91 [packed = false]; + repeated uint64 unpacked_uint64 = 92 [packed = false]; + repeated sint32 unpacked_sint32 = 93 [packed = false]; + repeated sint64 unpacked_sint64 = 94 [packed = false]; + repeated fixed32 unpacked_fixed32 = 95 [packed = false]; + repeated fixed64 unpacked_fixed64 = 96 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 97 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 98 [packed = false]; + repeated float unpacked_float = 99 [packed = false]; + repeated double unpacked_double = 100 [packed = false]; + repeated bool unpacked_bool = 101 [packed = false]; + repeated NestedEnum unpacked_nested_enum = 102 [packed = false]; + + // Map + map map_int32_int32 = 56; + map map_int64_int64 = 57; + map map_uint32_uint32 = 58; + map map_uint64_uint64 = 59; + map map_sint32_sint32 = 60; + map map_sint64_sint64 = 61; + map map_fixed32_fixed32 = 62; + map map_fixed64_fixed64 = 63; + map map_sfixed32_sfixed32 = 64; + map map_sfixed64_sfixed64 = 65; + map map_int32_float = 66; + map map_int32_double = 67; + map map_bool_bool = 68; + map map_string_string = 69; + map map_string_bytes = 70; + map map_string_nested_message = 71; + map map_string_foreign_message = 72; + map map_string_nested_enum = 73; + map map_string_foreign_enum = 74; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + bool oneof_bool = 115; + uint64 oneof_uint64 = 116; + float oneof_float = 117; + double oneof_double = 118; + NestedEnum oneof_enum = 119; + google.protobuf.NullValue oneof_null_value = 120; + } + + // Well-known types + google.protobuf.BoolValue optional_bool_wrapper = 201; + google.protobuf.Int32Value optional_int32_wrapper = 202; + google.protobuf.Int64Value optional_int64_wrapper = 203; + google.protobuf.UInt32Value optional_uint32_wrapper = 204; + google.protobuf.UInt64Value optional_uint64_wrapper = 205; + google.protobuf.FloatValue optional_float_wrapper = 206; + google.protobuf.DoubleValue optional_double_wrapper = 207; + google.protobuf.StringValue optional_string_wrapper = 208; + google.protobuf.BytesValue optional_bytes_wrapper = 209; + + repeated google.protobuf.BoolValue repeated_bool_wrapper = 211; + repeated google.protobuf.Int32Value repeated_int32_wrapper = 212; + repeated google.protobuf.Int64Value repeated_int64_wrapper = 213; + repeated google.protobuf.UInt32Value repeated_uint32_wrapper = 214; + repeated google.protobuf.UInt64Value repeated_uint64_wrapper = 215; + repeated google.protobuf.FloatValue repeated_float_wrapper = 216; + repeated google.protobuf.DoubleValue repeated_double_wrapper = 217; + repeated google.protobuf.StringValue repeated_string_wrapper = 218; + repeated google.protobuf.BytesValue repeated_bytes_wrapper = 219; + + google.protobuf.Duration optional_duration = 301; + google.protobuf.Timestamp optional_timestamp = 302; + google.protobuf.FieldMask optional_field_mask = 303; + google.protobuf.Struct optional_struct = 304; + google.protobuf.Any optional_any = 305; + google.protobuf.Value optional_value = 306; + google.protobuf.NullValue optional_null_value = 307; + + repeated google.protobuf.Duration repeated_duration = 311; + repeated google.protobuf.Timestamp repeated_timestamp = 312; + repeated google.protobuf.FieldMask repeated_fieldmask = 313; + repeated google.protobuf.Struct repeated_struct = 324; + repeated google.protobuf.Any repeated_any = 315; + repeated google.protobuf.Value repeated_value = 316; + repeated google.protobuf.ListValue repeated_list_value = 317; + + // Test field-name-to-JSON-name convention. + // (protobuf says names can be any valid C/C++ identifier.) + int32 fieldname1 = 401; + int32 field_name2 = 402; + int32 _field_name3 = 403; + int32 field__name4_ = 404; + int32 field0name5 = 405; + int32 field_0_name6 = 406; + int32 fieldName7 = 407; + int32 FieldName8 = 408; + int32 field_Name9 = 409; + int32 Field_Name10 = 410; + int32 FIELD_NAME11 = 411; + int32 FIELD_name12 = 412; + int32 __field_name13 = 413; + int32 __Field_name14 = 414; + int32 field__name15 = 415; + int32 field__Name16 = 416; + int32 field_name17__ = 417; + int32 Field_name18__ = 418; + + // Reserved for testing unknown fields + reserved 501 to 510; +} + +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_FOO = 0; + FOREIGN_BAR = 1; + FOREIGN_BAZ = 2; +} + +message NullHypothesisProto3 {} + +message EnumOnlyProto3 { + enum Bool { + kFalse = 0; + kTrue = 1; + } +} From 8a89a962a36d1df4f035f1a4f87fd4547588a85b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fa=C3=A7=20Eldenk?= Date: Wed, 23 Aug 2023 15:53:25 -0500 Subject: [PATCH 2/3] update tests and descriptions --- .../protobuf/conformance/Proto3EnumTest.kt | 9 +- .../protobuf/conformance/Proto3MapTest.kt | 64 ++++++++++---- .../protobuf/conformance/Proto3OneofTest.kt | 20 ++--- .../protobuf/conformance/Proto3PackedTest.kt | 74 +++++++++++----- .../conformance/Proto3RepeatedTest.kt | 87 +++++++++++++------ .../conformance/Proto3UnpackedTest.kt | 39 ++++++--- 6 files changed, 199 insertions(+), 94 deletions(-) diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3EnumTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3EnumTest.kt index 2512b5eee..7b2dda22a 100644 --- a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3EnumTest.kt +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3EnumTest.kt @@ -23,9 +23,10 @@ data class KTestMessagesProto3Enum( BAR, @ProtoNumber(2) - BAZ; -// @ProtoNumber(-1) -// NEG; + BAZ, + + @ProtoNumber(-1) + NEG; fun toProto() = TestMessagesProto3.TestAllTypesProto3.NestedEnum.valueOf(this.name) } @@ -71,7 +72,7 @@ class Proto3EnumTest { @Test fun default() { val message = KTestMessagesProto3Enum( - optionalNestedEnum = KTestMessagesProto3Enum.KNestedEnum.BAR, + optionalNestedEnum = KTestMessagesProto3Enum.KNestedEnum.NEG, optionalForeignEnum = KForeignEnum.FOREIGN_BAR, optionalAliasedEnum = KTestMessagesProto3Enum.KAliasedEnum.ALIAS_BAR ) diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MapTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MapTest.kt index b2b9832e2..a96142492 100644 --- a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MapTest.kt +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MapTest.kt @@ -18,15 +18,15 @@ data class KTestMessagesProto3Map( @ProtoNumber(59) val mapUint64Uint64: Map = emptyMap(), @ProtoNumber(60) val mapSint32Sint32: Map = emptyMap(), @ProtoNumber(61) val mapSint64Sint64: Map = emptyMap(), -// @ProtoNumber(62) val mapFixed32Fixed32: Map = emptyMap(), -// @ProtoNumber(63) val mapFixed64Fixed64: Map = emptyMap(), -// @ProtoNumber(64) val mapSfixed32Sfixed32: Map = emptyMap(), -// @ProtoNumber(65) val mapSfixed64Sfixed64: Map = emptyMap(), + @ProtoNumber(62) val mapFixed32Fixed32: Map = emptyMap(), + @ProtoNumber(63) val mapFixed64Fixed64: Map = emptyMap(), + @ProtoNumber(64) val mapSfixed32Sfixed32: Map = emptyMap(), + @ProtoNumber(65) val mapSfixed64Sfixed64: Map = emptyMap(), @ProtoNumber(66) val mapInt32Float: Map = emptyMap(), @ProtoNumber(67) val mapInt32Double: Map = emptyMap(), @ProtoNumber(68) val mapBoolBool: Map = emptyMap(), @ProtoNumber(69) val mapStringString: Map = emptyMap(), -// @ProtoNumber(70) val mapStringBytes: Map = emptyMap(), + @ProtoNumber(70) val mapStringBytes: Map = emptyMap(), @ProtoNumber(71) val mapStringNestedMessage: Map = emptyMap(), @ProtoNumber(72) val mapStringForeignMessage: Map = emptyMap(), @ProtoNumber(73) val mapStringNestedEnum: Map = emptyMap(), @@ -41,17 +41,11 @@ class Proto3MapTest { mapInt64Int64 = Gen.map(Gen.long(), Gen.long()).generate(), mapUint32Uint32 = Gen.map(Gen.int().map { it.toUInt() }, Gen.int().map { it.toUInt() }).generate(), mapUint64Uint64 = Gen.map(Gen.int().map { it.toULong() }, Gen.int().map { it.toULong() }).generate(), -// mapSint32Sint32 = Gen.map(Gen.int(), Gen.int()).generate(), -// mapSint64Sint64 = Gen.map(Gen.long(), Gen.long()).generate(), -// mapFixed32Fixed32 = Gen.map(Gen.int(), Gen.int()).generate(), -// mapFixed64Fixed64 = Gen.map(Gen.long(), Gen.long()).generate(), -// mapSfixed32Sfixed32 = Gen.map(Gen.int(), Gen.int()).generate(), -// mapSfixed64Sfixed64 = Gen.map(Gen.long(), Gen.long()).generate(), mapInt32Float = Gen.map(Gen.int(), Gen.float()).generate(), mapInt32Double = Gen.map(Gen.int(), Gen.double()).generate(), mapBoolBool = Gen.map(Gen.bool(), Gen.bool()).generate(), mapStringString = Gen.map(Gen.string(), Gen.string()).generate(), -// mapStringBytes = Gen.map(Gen.string(), Gen.byteArray()).generate(), + mapStringBytes = Gen.map(Gen.string(), Gen.string().map { it.toByteArray() }).generate(), mapStringNestedMessage = mapOf( "asd_1" to KTestMessagesProto3Message.KNestedMessage( 1, @@ -94,17 +88,14 @@ class Proto3MapTest { message.mapUint64Uint64, restored.mapUint64Uint64Map.map { it.key.toULong() to it.value.toULong() }.toMap() ) -// assertEquals(message.mapSint32Sint32, restored.mapSint32Sint32Map) -// assertEquals(message.mapSint64Sint64, restored.mapSint64Sint64Map) -// assertEquals(message.mapFixed32Fixed32, restored.mapFixed32Fixed32Map) -// assertEquals(message.mapFixed64Fixed64, restored.mapFixed64Fixed64Map) -// assertEquals(message.mapSfixed32Sfixed32, restored.mapSfixed32Sfixed32Map) -// assertEquals(message.mapSfixed64Sfixed64, restored.mapSfixed64Sfixed64Map) assertEquals(message.mapInt32Float, restored.mapInt32FloatMap) assertEquals(message.mapInt32Double, restored.mapInt32DoubleMap) assertEquals(message.mapBoolBool, restored.mapBoolBoolMap) assertEquals(message.mapStringString, restored.mapStringStringMap) -// assertEquals(message.mapStringBytes, restored.mapStringBytesMap) + assertContentEquals( + message.mapStringBytes.mapValues { it.value.toString(Charsets.UTF_32) }.entries.toList(), + restored.mapStringBytesMap.mapValues { it.value.toByteArray().toString(Charsets.UTF_32) }.entries.toList() + ) assertEquals( message.mapStringNestedMessage.mapValues { it.value.toProto() }, restored.mapStringNestedMessageMap @@ -122,6 +113,41 @@ class Proto3MapTest { restored.mapStringForeignEnumMap.mapValues { it.value.name } ) + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message.copy(mapStringBytes = mapOf()), restoredMessage.copy(mapStringBytes = mapOf())) + } + + @Test + @Ignore + // Issue: https://github.com/Kotlin/kotlinx.serialization/issues/2417 + fun signedAndFixed() { + val message = KTestMessagesProto3Map( + mapSint32Sint32 = Gen.map(Gen.int(), Gen.int()).generate(), + mapSint64Sint64 = Gen.map(Gen.long(), Gen.long()).generate(), + mapFixed32Fixed32 = Gen.map(Gen.int(), Gen.int()).generate(), + mapFixed64Fixed64 = Gen.map(Gen.long(), Gen.long()).generate(), + mapSfixed32Sfixed32 = Gen.map(Gen.int(), Gen.int()).generate(), + mapSfixed64Sfixed64 = Gen.map(Gen.long(), Gen.long()).generate(), + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + + assertContentEquals(message.mapSint32Sint32.entries.toList(), restored.mapSint32Sint32Map.entries.toList()) + assertContentEquals(message.mapSint64Sint64.entries.toList(), restored.mapSint64Sint64Map.entries.toList()) + assertContentEquals(message.mapFixed32Fixed32.entries.toList(), restored.mapFixed32Fixed32Map.entries.toList()) + assertContentEquals(message.mapFixed64Fixed64.entries.toList(), restored.mapFixed64Fixed64Map.entries.toList()) + assertContentEquals( + message.mapSfixed32Sfixed32.entries.toList(), + restored.mapSfixed32Sfixed32Map.entries.toList() + ) + assertContentEquals( + message.mapSfixed64Sfixed64.entries.toList(), + restored.mapSfixed64Sfixed64Map.entries.toList() + ) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) assertEquals(message, restoredMessage) } diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3OneofTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3OneofTest.kt index 1a473085d..bcf1dc060 100644 --- a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3OneofTest.kt +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3OneofTest.kt @@ -54,18 +54,18 @@ class Proto3OneofTest { ).forEach { message -> val bytes = ProtoBuf.encodeToByteArray(message) val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) - if (restored.hasOneofUint32()) assertEquals(message.oneofUint32, restored.oneofUint32.toUInt()) - if (restored.hasOneofNestedMessage()) assertEquals( - message.oneofNestedMessage?.a, + if (message.oneofUint32 != null) assertEquals(message.oneofUint32, restored.oneofUint32.toUInt()) + if (message.oneofNestedMessage != null) assertEquals( + message.oneofNestedMessage.a, restored.oneofNestedMessage?.a ) - if (restored.hasOneofString()) assertEquals(message.oneofString, restored.oneofString) - if (restored.hasOneofBytes()) assertContentEquals(message.oneofBytes, restored.oneofBytes.toByteArray()) - if (restored.hasOneofBool()) assertEquals(message.oneofBool, restored.oneofBool) - if (restored.hasOneofUint64()) assertEquals(message.oneofUint64, restored.oneofUint64.toULong()) - if (restored.hasOneofFloat()) assertEquals(message.oneofFloat, restored.oneofFloat) - if (restored.hasOneofDouble()) assertEquals(message.oneofDouble, restored.oneofDouble) - if (restored.hasOneofEnum()) assertEquals(message.oneofEnum?.name, restored.oneofEnum?.name) + if (message.oneofString != null) assertEquals(message.oneofString, restored.oneofString) + if (message.oneofBytes != null) assertContentEquals(message.oneofBytes, restored.oneofBytes.toByteArray()) + if (message.oneofBool != null) assertEquals(message.oneofBool, restored.oneofBool) + if (message.oneofUint64 != null) assertEquals(message.oneofUint64, restored.oneofUint64.toULong()) + if (message.oneofFloat != null) assertEquals(message.oneofFloat, restored.oneofFloat) + if (message.oneofDouble != null) assertEquals(message.oneofDouble, restored.oneofDouble) + if (message.oneofEnum != null) assertEquals(message.oneofEnum.name, restored.oneofEnum?.name) val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) assertEquals(message, restoredMessage.copy(oneofBytes = message.oneofBytes)) diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PackedTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PackedTest.kt index 5031f1be4..e0da0bb8f 100644 --- a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PackedTest.kt +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PackedTest.kt @@ -14,14 +14,14 @@ import kotlin.test.* data class KTestMessagesProto3Packed( @ProtoNumber(75) @ProtoPacked val packedInt32: List = emptyList(), @ProtoNumber(76) @ProtoPacked val packedInt64: List = emptyList(), -// @ProtoNumber(77) @ProtoPacked val packedUint32: List = emptyList(), -// @ProtoNumber(78) @ProtoPacked val packedUint64: List = emptyList(), + @ProtoNumber(77) @ProtoPacked val packedUint32: List = emptyList(), + @ProtoNumber(78) @ProtoPacked val packedUint64: List = emptyList(), @ProtoNumber(79) @ProtoPacked val packedSint32: List = emptyList(), @ProtoNumber(80) @ProtoPacked val packedSint64: List = emptyList(), -// @ProtoNumber(81) @ProtoPacked val packedFixed32: List = emptyList(), -// @ProtoNumber(82) @ProtoPacked val packedFixed64: List = emptyList(), -// @ProtoNumber(83) @ProtoPacked val packedSfixed32: List = emptyList(), -// @ProtoNumber(84) @ProtoPacked val packedSfixed64: List = emptyList(), + @ProtoNumber(81) @ProtoPacked val packedFixed32: List = emptyList(), + @ProtoNumber(82) @ProtoPacked val packedFixed64: List = emptyList(), + @ProtoNumber(83) @ProtoPacked val packedSfixed32: List = emptyList(), + @ProtoNumber(84) @ProtoPacked val packedSfixed64: List = emptyList(), @ProtoNumber(85) @ProtoPacked val packedFloat: List = emptyList(), @ProtoNumber(86) @ProtoPacked val packedDouble: List = emptyList(), @ProtoNumber(87) @ProtoPacked val packedBool: List = emptyList(), @@ -33,14 +33,6 @@ class Proto3PackedTest { val message = KTestMessagesProto3Packed( packedInt32 = Gen.list(Gen.int()).generate(), packedInt64 = Gen.list(Gen.long()).generate(), -// packedUint32 = Gen.list(Gen.int().map { it.toUInt() }).generate(), -// packedUint64 = Gen.list(Gen.long().map { it.toULong() }).generate(), - packedSint32 = Gen.list(Gen.int()).generate(), - packedSint64 = Gen.list(Gen.long()).generate(), -// packedFixed32 = Gen.list(Gen.int()).generate(), -// packedFixed64 = Gen.list(Gen.long()).generate(), -// packedSfixed32 = Gen.list(Gen.int()).generate(), -// packedSfixed64 = Gen.list(Gen.long()).generate(), packedFloat = Gen.list(Gen.float()).generate(), packedDouble = Gen.list(Gen.double()).generate(), packedBool = Gen.list(Gen.bool()).generate(), @@ -51,14 +43,6 @@ class Proto3PackedTest { assertEquals(message.packedInt32, restored.packedInt32List) assertEquals(message.packedInt64, restored.packedInt64List) -// assertEquals(message.packedUint32, restored.packedUint32List.map { it.toUInt() }) -// assertEquals(message.packedUint64, restored.packedUint64List.map { it.toULong() }) -// assertEquals(message.packedSint32, restored.packedSint32List) -// assertEquals(message.packedSint64, restored.packedSint64List) -// assertEquals(message.packedFixed32, restored.packedFixed32List) -// assertEquals(message.packedFixed64, restored.packedFixed64List) -// assertEquals(message.packedSfixed32, restored.packedSfixed32List) -// assertEquals(message.packedSfixed64, restored.packedSfixed64List) assertEquals(message.packedFloat, restored.packedFloatList) assertEquals(message.packedDouble, restored.packedDoubleList) assertEquals(message.packedBool, restored.packedBoolList) @@ -66,4 +50,50 @@ class Proto3PackedTest { val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) assertEquals(message, restoredMessage) } + + @Test + @Ignore + // Issue: https://github.com/Kotlin/kotlinx.serialization/issues/2419 + fun signedAndFixed() { + val message = KTestMessagesProto3Packed( + packedSint32 = Gen.list(Gen.int()).generate(), + packedSint64 = Gen.list(Gen.long()).generate(), + packedFixed32 = Gen.list(Gen.int()).generate(), + packedFixed64 = Gen.list(Gen.long()).generate(), + packedSfixed32 = Gen.list(Gen.int()).generate(), + packedSfixed64 = Gen.list(Gen.long()).generate(), + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + assertEquals(message.packedSint32, restored.packedSint32List) + assertEquals(message.packedSint64, restored.packedSint64List) + assertEquals(message.packedFixed32, restored.packedFixed32List) + assertEquals(message.packedFixed64, restored.packedFixed64List) + assertEquals(message.packedSfixed32, restored.packedSfixed32List) + assertEquals(message.packedSfixed64, restored.packedSfixed64List) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message, restoredMessage) + } + + @Test + @Ignore + // Issue: https://github.com/Kotlin/kotlinx.serialization/issues/2418 + fun unsigned() { + val message = KTestMessagesProto3Packed( + packedUint32 = Gen.list(Gen.int().map { it.toUInt() }).generate(), + packedUint64 = Gen.list(Gen.long().map { it.toULong() }).generate(), + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + assertEquals(message.packedUint32, restored.packedUint32List.map { it.toUInt() }) + assertEquals(message.packedUint64, restored.packedUint64List.map { it.toULong() }) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message, restoredMessage) + } } diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3RepeatedTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3RepeatedTest.kt index 88a11fe0f..1479f439d 100644 --- a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3RepeatedTest.kt +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3RepeatedTest.kt @@ -14,19 +14,19 @@ import kotlin.test.* data class KTestMessagesProto3Repeated( @ProtoNumber(31) @ProtoPacked val repeatedInt32: List = emptyList(), @ProtoNumber(32) @ProtoPacked val repeatedInt64: List = emptyList(), -// @ProtoNumber(33) @ProtoPacked val repeatedUint32: List = emptyList(), -// @ProtoNumber(34) @ProtoPacked val repeatedUint64: List = emptyList(), -// @ProtoNumber(35) @ProtoPacked val repeatedSint32: List = emptyList(), -// @ProtoNumber(36) @ProtoPacked val repeatedSint64: List = emptyList(), -// @ProtoNumber(37) @ProtoPacked val repeatedFixed32: List = emptyList(), -// @ProtoNumber(38) @ProtoPacked val repeatedFixed64: List = emptyList(), -// @ProtoNumber(39) @ProtoPacked val repeatedSfixed32: List = emptyList(), -// @ProtoNumber(40) @ProtoPacked val repeatedSfixed64: List = emptyList(), + @ProtoNumber(33) @ProtoPacked val repeatedUint32: List = emptyList(), + @ProtoNumber(34) @ProtoPacked val repeatedUint64: List = emptyList(), + @ProtoNumber(35) @ProtoPacked val repeatedSint32: List = emptyList(), + @ProtoNumber(36) @ProtoPacked val repeatedSint64: List = emptyList(), + @ProtoNumber(37) @ProtoPacked val repeatedFixed32: List = emptyList(), + @ProtoNumber(38) @ProtoPacked val repeatedFixed64: List = emptyList(), + @ProtoNumber(39) @ProtoPacked val repeatedSfixed32: List = emptyList(), + @ProtoNumber(40) @ProtoPacked val repeatedSfixed64: List = emptyList(), @ProtoNumber(41) @ProtoPacked val repeatedFloat: List = emptyList(), @ProtoNumber(42) @ProtoPacked val repeatedDouble: List = emptyList(), @ProtoNumber(43) @ProtoPacked val repeatedBool: List = emptyList(), @ProtoNumber(44) val repeatedString: List = emptyList(), -// @ProtoNumber(45) val repeatedBytes: List = emptyList(), + @ProtoNumber(45) val repeatedBytes: List = emptyList(), @ProtoNumber(48) val repeatedNestedMessages: List = emptyList(), @ProtoNumber(49) val repeatedForeignMessages: List = emptyList(), ) @@ -37,19 +37,11 @@ class Proto3RepeatedTest { val message = KTestMessagesProto3Repeated( repeatedInt32 = Gen.list(Gen.int()).generate(), repeatedInt64 = Gen.list(Gen.long()).generate(), -// repeatedUint32 = Gen.list(Gen.int().map { it.toUInt() }).generate(), -// repeatedUint64 = Gen.list(Gen.long().map { it.toULong() }).generate(), -// repeatedSint32 = Gen.list(Gen.int()).generate(), -// repeatedSint64 = Gen.list(Gen.long()).generate(), -// repeatedFixed32 = Gen.list(Gen.int()).generate(), -// repeatedFixed64 = Gen.list(Gen.long()).generate(), -// repeatedSfixed32 = Gen.list(Gen.int()).generate(), -// repeatedSfixed64 = Gen.list(Gen.long()).generate(), repeatedFloat = Gen.list(Gen.float()).generate(), repeatedDouble = Gen.list(Gen.double()).generate(), repeatedBool = Gen.list(Gen.bool()).generate(), repeatedString = Gen.list(Gen.string()).generate(), -// repeatedBytes = Gen.list(Gen.string().map { it.toByteArray() }).generate(), + repeatedBytes = Gen.list(Gen.string().map { it.toByteArray() }).generate(), repeatedNestedMessages = listOf( KTestMessagesProto3Message.KNestedMessage( 1, @@ -73,21 +65,62 @@ class Proto3RepeatedTest { assertEquals(message.repeatedInt32, restored.repeatedInt32List) assertEquals(message.repeatedInt64, restored.repeatedInt64List) -// assertEquals(message.repeatedUint32, restored.repeatedUint32List.map { it.toUInt() }) -// assertEquals(message.repeatedUint64, restored.repeatedUint64List.map { it.toULong() }) -// assertEquals(message.repeatedSint32, restored.repeatedSint32List) -// assertEquals(message.repeatedSint64, restored.repeatedSint64List) -// assertEquals(message.repeatedFixed32, restored.repeatedFixed32List) -// assertEquals(message.repeatedFixed64, restored.repeatedFixed64List) -// assertEquals(message.repeatedSfixed32, restored.repeatedSfixed32List) -// assertEquals(message.repeatedSfixed64, restored.repeatedSfixed64List) assertEquals(message.repeatedFloat, restored.repeatedFloatList) assertEquals(message.repeatedDouble, restored.repeatedDoubleList) assertEquals(message.repeatedBool, restored.repeatedBoolList) assertEquals(message.repeatedString, restored.repeatedStringList) -// assertEquals(message.repeatedBytes.map { it.toList() }, restored.repeatedBytesList.map { it.toList() }) assertEquals(message.repeatedNestedMessages.map { it.toProto() }, restored.repeatedNestedMessageList) assertEquals(message.repeatedForeignMessages.map { it.toProto() }, restored.repeatedForeignMessageList) + assertEquals(message.repeatedBytes.map { it.toList() }, restored.repeatedBytesList.map { it.toList() }) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message, restoredMessage.copy(repeatedBytes = message.repeatedBytes)) + } + + @Test + @Ignore + // Issue: https://github.com/Kotlin/kotlinx.serialization/issues/2419 + fun signedAndFixed() { + val message = KTestMessagesProto3Repeated( + repeatedSint32 = Gen.list(Gen.int()).generate(), + repeatedSint64 = Gen.list(Gen.long()).generate(), + repeatedFixed32 = Gen.list(Gen.int()).generate(), + repeatedFixed64 = Gen.list(Gen.long()).generate(), + repeatedSfixed32 = Gen.list(Gen.int()).generate(), + repeatedSfixed64 = Gen.list(Gen.long()).generate(), + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + assertEquals(message.repeatedUint32, restored.repeatedUint32List.map { it.toUInt() }) + assertEquals(message.repeatedUint64, restored.repeatedUint64List.map { it.toULong() }) + assertEquals(message.repeatedSint32, restored.repeatedSint32List) + assertEquals(message.repeatedSint64, restored.repeatedSint64List) + assertEquals(message.repeatedFixed32, restored.repeatedFixed32List) + assertEquals(message.repeatedFixed64, restored.repeatedFixed64List) + assertEquals(message.repeatedSfixed32, restored.repeatedSfixed32List) + assertEquals(message.repeatedSfixed64, restored.repeatedSfixed64List) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message, restoredMessage) + } + + + @Test + @Ignore + // Issue: https://github.com/Kotlin/kotlinx.serialization/issues/2418 + fun unsigned() { + val message = KTestMessagesProto3Repeated( + repeatedUint32 = Gen.list(Gen.int().map { it.toUInt() }).generate(), + repeatedUint64 = Gen.list(Gen.long().map { it.toULong() }).generate(), + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + assertEquals(message.repeatedUint32, restored.repeatedUint32List.map { it.toUInt() }) + assertEquals(message.repeatedUint64, restored.repeatedUint64List.map { it.toULong() }) val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) assertEquals(message, restoredMessage) diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3UnpackedTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3UnpackedTest.kt index b4477a9d1..dad773d9e 100644 --- a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3UnpackedTest.kt +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3UnpackedTest.kt @@ -35,12 +35,6 @@ class Proto3UnpackedTest { unpackedInt64 = Gen.list(Gen.long()).generate(), unpackedUint32 = Gen.list(Gen.int().map { it.toUInt() }).generate(), unpackedUint64 = Gen.list(Gen.long().map { it.toULong() }).generate(), - unpackedSint32 = Gen.list(Gen.int()).generate(), - unpackedSint64 = Gen.list(Gen.long()).generate(), - unpackedFixed32 = Gen.list(Gen.int()).generate(), - unpackedFixed64 = Gen.list(Gen.long()).generate(), - unpackedSfixed32 = Gen.list(Gen.int()).generate(), - unpackedSfixed64 = Gen.list(Gen.long()).generate(), unpackedFloat = Gen.list(Gen.float()).generate(), unpackedDouble = Gen.list(Gen.double()).generate(), unpackedBool = Gen.list(Gen.bool()).generate(), @@ -53,12 +47,6 @@ class Proto3UnpackedTest { assertEquals(message.unpackedInt64, restored.unpackedInt64List) assertEquals(message.unpackedUint32, restored.unpackedUint32List.map { it.toUInt() }) assertEquals(message.unpackedUint64, restored.unpackedUint64List.map { it.toULong() }) - //assertEquals(message.unpackedSint32, restored.unpackedSint32List) - //assertEquals(message.unpackedSint64, restored.unpackedSint64List) - //assertEquals(message.unpackedFixed32, restored.unpackedFixed32List) - //assertEquals(message.unpackedFixed64, restored.unpackedFixed64List) - //assertEquals(message.unpackedSfixed32, restored.unpackedSfixed32List) - //assertEquals(message.unpackedSfixed64, restored.unpackedSfixed64List) assertEquals(message.unpackedFloat, restored.unpackedFloatList) assertEquals(message.unpackedDouble, restored.unpackedDoubleList) assertEquals(message.unpackedBool, restored.unpackedBoolList) @@ -66,4 +54,31 @@ class Proto3UnpackedTest { val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) assertEquals(message, restoredMessage) } + + @Test + @Ignore + // Issue: https://github.com/Kotlin/kotlinx.serialization/issues/2419 + fun signedAndFixed() { + val message = KTestMessagesProto3Unpacked( + unpackedSint32 = Gen.list(Gen.int()).generate(), + unpackedSint64 = Gen.list(Gen.long()).generate(), + unpackedFixed32 = Gen.list(Gen.int()).generate(), + unpackedFixed64 = Gen.list(Gen.long()).generate(), + unpackedSfixed32 = Gen.list(Gen.int()).generate(), + unpackedSfixed64 = Gen.list(Gen.long()).generate(), + ) + + val bytes = ProtoBuf.encodeToByteArray(message) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + assertEquals(message.unpackedSint32, restored.unpackedSint32List) + assertEquals(message.unpackedSint64, restored.unpackedSint64List) + assertEquals(message.unpackedFixed32, restored.unpackedFixed32List) + assertEquals(message.unpackedFixed64, restored.unpackedFixed64List) + assertEquals(message.unpackedSfixed32, restored.unpackedSfixed32List) + assertEquals(message.unpackedSfixed64, restored.unpackedSfixed64List) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + assertEquals(message, restoredMessage) + } } From 85e8f678ee0454d91298bab249a393a71747a36d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fa=C3=A7=20Eldenk?= Date: Sat, 23 Sep 2023 15:08:10 +0300 Subject: [PATCH 3/3] refactor tests slightly --- .../protobuf/conformance/Proto3OneofTest.kt | 116 +++++++++++++----- .../conformance/Proto3PrimitiveTest.kt | 3 + .../conformance/Proto3RepeatedTest.kt | 5 + 3 files changed, 94 insertions(+), 30 deletions(-) diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3OneofTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3OneofTest.kt index bcf1dc060..fda811eac 100644 --- a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3OneofTest.kt +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3OneofTest.kt @@ -39,37 +39,93 @@ data class KTestMessageProto3Oneof( } class Proto3OneofTest { + + /** + * Verify that the given [KTestMessageProto3Oneof] is correctly encoded and decoded as + * [TestMessagesProto3.TestAllTypesProto3] by running the [verificationFunction]. This + * method also verifies that the encoded and decoded message is equal to the original message. + * + * @param verificationFunction a function that verifies the encoded and decoded message. First parameter + * is the original message and the second parameter is the decoded protobuf library message. + * @receiver the [KTestMessageProto3Oneof] to verify + */ + private fun KTestMessageProto3Oneof.verify( + verificationFunction: (KTestMessageProto3Oneof, TestMessagesProto3.TestAllTypesProto3) -> Unit, + ) { + val bytes = ProtoBuf.encodeToByteArray(this) + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) + + verificationFunction.invoke(this, restored) + + val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + + // [equals] method is not implemented for [ByteArray] so we need to compare it separately. + assertEquals(this, restoredMessage.copy(oneofBytes = this.oneofBytes)) + assertContentEquals(this.oneofBytes, restoredMessage.oneofBytes) + } + + @Test + fun uint32() { + KTestMessageProto3Oneof(oneofUint32 = 150u).verify { self, restored -> + assertEquals(self.oneofUint32, restored.oneofUint32.toUInt()) + } + } + + @Test + fun nestedMessage() { + KTestMessageProto3Oneof( + oneofNestedMessage = KTestMessagesProto3Message.KNestedMessage(a = 150), + ).verify { self, restored -> + assertEquals(self.oneofNestedMessage?.a, restored.oneofNestedMessage.a) + } + } + + @Test + fun string() { + KTestMessageProto3Oneof(oneofString = "150").verify { self, restored -> + assertEquals(self.oneofString, restored.oneofString) + } + } + + @Test + fun bytes() { + KTestMessageProto3Oneof(oneofBytes = "150".toByteArray()).verify { self, restored -> + assertContentEquals(self.oneofBytes, restored.oneofBytes.toByteArray()) + } + } + + @Test + fun bool() { + KTestMessageProto3Oneof(oneofBool = true).verify { self, restored -> + assertEquals(self.oneofBool, restored.oneofBool) + } + } + + @Test + fun uint64() { + KTestMessageProto3Oneof(oneofUint64 = 150uL).verify { self, restored -> + assertEquals(self.oneofUint64, restored.oneofUint64.toULong()) + } + } + + @Test + fun float() { + KTestMessageProto3Oneof(oneofFloat = 150f).verify { self, restored -> + assertEquals(self.oneofFloat, restored.oneofFloat) + } + } + + @Test + fun double() { + KTestMessageProto3Oneof(oneofDouble = 150.0).verify { self, restored -> + assertEquals(self.oneofDouble, restored.oneofDouble) + } + } + @Test - fun default() { - listOf( - KTestMessageProto3Oneof(oneofUint32 = 150u), - KTestMessageProto3Oneof(oneofNestedMessage = KTestMessagesProto3Message.KNestedMessage(a = 150)), - KTestMessageProto3Oneof(oneofString = "150"), - KTestMessageProto3Oneof(oneofBytes = "150".toByteArray()), - KTestMessageProto3Oneof(oneofBool = true), - KTestMessageProto3Oneof(oneofUint64 = 150uL), - KTestMessageProto3Oneof(oneofFloat = 150f), - KTestMessageProto3Oneof(oneofDouble = 150.0), - KTestMessageProto3Oneof(oneofEnum = KTestMessagesProto3Enum.KNestedEnum.BAR), - ).forEach { message -> - val bytes = ProtoBuf.encodeToByteArray(message) - val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) - if (message.oneofUint32 != null) assertEquals(message.oneofUint32, restored.oneofUint32.toUInt()) - if (message.oneofNestedMessage != null) assertEquals( - message.oneofNestedMessage.a, - restored.oneofNestedMessage?.a - ) - if (message.oneofString != null) assertEquals(message.oneofString, restored.oneofString) - if (message.oneofBytes != null) assertContentEquals(message.oneofBytes, restored.oneofBytes.toByteArray()) - if (message.oneofBool != null) assertEquals(message.oneofBool, restored.oneofBool) - if (message.oneofUint64 != null) assertEquals(message.oneofUint64, restored.oneofUint64.toULong()) - if (message.oneofFloat != null) assertEquals(message.oneofFloat, restored.oneofFloat) - if (message.oneofDouble != null) assertEquals(message.oneofDouble, restored.oneofDouble) - if (message.oneofEnum != null) assertEquals(message.oneofEnum.name, restored.oneofEnum?.name) - - val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) - assertEquals(message, restoredMessage.copy(oneofBytes = message.oneofBytes)) - assertContentEquals(message.oneofBytes, restoredMessage.oneofBytes) + fun enum() { + KTestMessageProto3Oneof(oneofEnum = KTestMessagesProto3Enum.KNestedEnum.BAR).verify { self, restored -> + assertEquals(self.oneofEnum?.name, restored.oneofEnum.name) } } } diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PrimitiveTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PrimitiveTest.kt index 93f87c3c3..a7363f8f8 100644 --- a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PrimitiveTest.kt +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3PrimitiveTest.kt @@ -69,6 +69,9 @@ class Proto3PrimitiveTest { assertContentEquals(message.optionalBytes, restored.optionalBytes.toByteArray()) val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + + // [equals] method is not implemented for [ByteArray] so we need to compare it separately. assertEquals(message, restoredMessage.copy(optionalBytes = message.optionalBytes)) + assertContentEquals(message.optionalBytes, restoredMessage.optionalBytes) } } diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3RepeatedTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3RepeatedTest.kt index 1479f439d..b3dab8c7a 100644 --- a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3RepeatedTest.kt +++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3RepeatedTest.kt @@ -74,7 +74,12 @@ class Proto3RepeatedTest { assertEquals(message.repeatedBytes.map { it.toList() }, restored.repeatedBytesList.map { it.toList() }) val restoredMessage = ProtoBuf.decodeFromByteArray(restored.toByteArray()) + // [equals] method is not implemented for [ByteArray] so we need to compare it separately. assertEquals(message, restoredMessage.copy(repeatedBytes = message.repeatedBytes)) + assertContentEquals( + message.repeatedBytes.flatMap { it.toList() }, + restoredMessage.repeatedBytes.flatMap { it.toList() }, + ) } @Test