-
Notifications
You must be signed in to change notification settings - Fork 620
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add protobuf conformance tests (#2404)
Add conformance tests using test_messages_proto3 construct google provides
- Loading branch information
Showing
9 changed files
with
1,122 additions
and
0 deletions.
There are no files selected for viewing
90 changes: 90 additions & 0 deletions
90
formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3EnumTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* 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.NEG, | ||
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<KTestMessagesProto3Enum>(restored.toByteArray()) | ||
assertEquals(message, restoredMessage) | ||
} | ||
} |
154 changes: 154 additions & 0 deletions
154
formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MapTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
/* | ||
* 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<Int, Int> = emptyMap(), | ||
@ProtoNumber(57) val mapInt64Int64: Map<Long, Long> = emptyMap(), | ||
@ProtoNumber(58) val mapUint32Uint32: Map<UInt, UInt> = emptyMap(), | ||
@ProtoNumber(59) val mapUint64Uint64: Map<ULong, ULong> = emptyMap(), | ||
@ProtoNumber(60) val mapSint32Sint32: Map<Int, Int> = emptyMap(), | ||
@ProtoNumber(61) val mapSint64Sint64: Map<Long, Long> = emptyMap(), | ||
@ProtoNumber(62) val mapFixed32Fixed32: Map<Int, Int> = emptyMap(), | ||
@ProtoNumber(63) val mapFixed64Fixed64: Map<Long, Long> = emptyMap(), | ||
@ProtoNumber(64) val mapSfixed32Sfixed32: Map<Int, Int> = emptyMap(), | ||
@ProtoNumber(65) val mapSfixed64Sfixed64: Map<Long, Long> = emptyMap(), | ||
@ProtoNumber(66) val mapInt32Float: Map<Int, Float> = emptyMap(), | ||
@ProtoNumber(67) val mapInt32Double: Map<Int, Double> = emptyMap(), | ||
@ProtoNumber(68) val mapBoolBool: Map<Boolean, Boolean> = emptyMap(), | ||
@ProtoNumber(69) val mapStringString: Map<String, String> = emptyMap(), | ||
@ProtoNumber(70) val mapStringBytes: Map<String, ByteArray> = emptyMap(), | ||
@ProtoNumber(71) val mapStringNestedMessage: Map<String, KTestMessagesProto3Message.KNestedMessage> = emptyMap(), | ||
@ProtoNumber(72) val mapStringForeignMessage: Map<String, KForeignMessage> = emptyMap(), | ||
@ProtoNumber(73) val mapStringNestedEnum: Map<String, KTestMessagesProto3Enum.KNestedEnum> = emptyMap(), | ||
@ProtoNumber(74) val mapStringForeignEnum: Map<String, KForeignEnum> = 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(), | ||
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.string().map { it.toByteArray() }).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.mapInt32Float, restored.mapInt32FloatMap) | ||
assertEquals(message.mapInt32Double, restored.mapInt32DoubleMap) | ||
assertEquals(message.mapBoolBool, restored.mapBoolBoolMap) | ||
assertEquals(message.mapStringString, restored.mapStringStringMap) | ||
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 | ||
) | ||
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<KTestMessagesProto3Map>(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<KTestMessagesProto3Map>(restored.toByteArray()) | ||
assertEquals(message, restoredMessage) | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/conformance/Proto3MessageTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
} |
Oops, something went wrong.