|
| 1 | +/* |
| 2 | + * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. |
| 3 | + */ |
| 4 | + |
| 5 | +package kotlinx.serialization.protobuf.conformance |
| 6 | + |
| 7 | +import com.google.protobuf_test_messages.proto3.* |
| 8 | +import io.kotlintest.properties.* |
| 9 | +import kotlinx.serialization.* |
| 10 | +import kotlinx.serialization.protobuf.* |
| 11 | +import kotlin.test.* |
| 12 | + |
| 13 | +@Serializable |
| 14 | +data class KTestMessagesProto3Map( |
| 15 | + @ProtoNumber(56) val mapInt32Int32: Map<Int, Int> = emptyMap(), |
| 16 | + @ProtoNumber(57) val mapInt64Int64: Map<Long, Long> = emptyMap(), |
| 17 | + @ProtoNumber(58) val mapUint32Uint32: Map<UInt, UInt> = emptyMap(), |
| 18 | + @ProtoNumber(59) val mapUint64Uint64: Map<ULong, ULong> = emptyMap(), |
| 19 | + @ProtoNumber(60) val mapSint32Sint32: Map<Int, Int> = emptyMap(), |
| 20 | + @ProtoNumber(61) val mapSint64Sint64: Map<Long, Long> = emptyMap(), |
| 21 | + @ProtoNumber(62) val mapFixed32Fixed32: Map<Int, Int> = emptyMap(), |
| 22 | + @ProtoNumber(63) val mapFixed64Fixed64: Map<Long, Long> = emptyMap(), |
| 23 | + @ProtoNumber(64) val mapSfixed32Sfixed32: Map<Int, Int> = emptyMap(), |
| 24 | + @ProtoNumber(65) val mapSfixed64Sfixed64: Map<Long, Long> = emptyMap(), |
| 25 | + @ProtoNumber(66) val mapInt32Float: Map<Int, Float> = emptyMap(), |
| 26 | + @ProtoNumber(67) val mapInt32Double: Map<Int, Double> = emptyMap(), |
| 27 | + @ProtoNumber(68) val mapBoolBool: Map<Boolean, Boolean> = emptyMap(), |
| 28 | + @ProtoNumber(69) val mapStringString: Map<String, String> = emptyMap(), |
| 29 | + @ProtoNumber(70) val mapStringBytes: Map<String, ByteArray> = emptyMap(), |
| 30 | + @ProtoNumber(71) val mapStringNestedMessage: Map<String, KTestMessagesProto3Message.KNestedMessage> = emptyMap(), |
| 31 | + @ProtoNumber(72) val mapStringForeignMessage: Map<String, KForeignMessage> = emptyMap(), |
| 32 | + @ProtoNumber(73) val mapStringNestedEnum: Map<String, KTestMessagesProto3Enum.KNestedEnum> = emptyMap(), |
| 33 | + @ProtoNumber(74) val mapStringForeignEnum: Map<String, KForeignEnum> = emptyMap(), |
| 34 | +) |
| 35 | + |
| 36 | +class Proto3MapTest { |
| 37 | + @Test |
| 38 | + fun default() { |
| 39 | + val message = KTestMessagesProto3Map( |
| 40 | + mapInt32Int32 = Gen.map(Gen.int(), Gen.int()).generate(), |
| 41 | + mapInt64Int64 = Gen.map(Gen.long(), Gen.long()).generate(), |
| 42 | + mapUint32Uint32 = Gen.map(Gen.int().map { it.toUInt() }, Gen.int().map { it.toUInt() }).generate(), |
| 43 | + mapUint64Uint64 = Gen.map(Gen.int().map { it.toULong() }, Gen.int().map { it.toULong() }).generate(), |
| 44 | + mapInt32Float = Gen.map(Gen.int(), Gen.float()).generate(), |
| 45 | + mapInt32Double = Gen.map(Gen.int(), Gen.double()).generate(), |
| 46 | + mapBoolBool = Gen.map(Gen.bool(), Gen.bool()).generate(), |
| 47 | + mapStringString = Gen.map(Gen.string(), Gen.string()).generate(), |
| 48 | + mapStringBytes = Gen.map(Gen.string(), Gen.string().map { it.toByteArray() }).generate(), |
| 49 | + mapStringNestedMessage = mapOf( |
| 50 | + "asd_1" to KTestMessagesProto3Message.KNestedMessage( |
| 51 | + 1, |
| 52 | + null |
| 53 | + ), |
| 54 | + "asi_#" to KTestMessagesProto3Message.KNestedMessage( |
| 55 | + 2, |
| 56 | + KTestMessagesProto3Message( |
| 57 | + KTestMessagesProto3Message.KNestedMessage(3, null), |
| 58 | + ) |
| 59 | + ) |
| 60 | + ), |
| 61 | + mapStringForeignMessage = mapOf( |
| 62 | + "" to KForeignMessage(1), |
| 63 | + "-2" to KForeignMessage(-12), |
| 64 | + ), |
| 65 | + mapStringNestedEnum = Gen.map( |
| 66 | + Gen.string(), Gen.oneOf( |
| 67 | + KTestMessagesProto3Enum.KNestedEnum.entries, |
| 68 | + ) |
| 69 | + ).generate(), |
| 70 | + mapStringForeignEnum = Gen.map( |
| 71 | + Gen.string(), Gen.oneOf( |
| 72 | + KForeignEnum.entries, |
| 73 | + ) |
| 74 | + ).generate(), |
| 75 | + ) |
| 76 | + |
| 77 | + val bytes = ProtoBuf.encodeToByteArray(message) |
| 78 | + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) |
| 79 | + |
| 80 | + |
| 81 | + assertEquals(message.mapInt32Int32, restored.mapInt32Int32Map) |
| 82 | + assertEquals(message.mapInt64Int64, restored.mapInt64Int64Map) |
| 83 | + assertEquals( |
| 84 | + message.mapUint32Uint32, |
| 85 | + restored.mapUint32Uint32Map.map { it.key.toUInt() to it.value.toUInt() }.toMap() |
| 86 | + ) |
| 87 | + assertEquals( |
| 88 | + message.mapUint64Uint64, |
| 89 | + restored.mapUint64Uint64Map.map { it.key.toULong() to it.value.toULong() }.toMap() |
| 90 | + ) |
| 91 | + assertEquals(message.mapInt32Float, restored.mapInt32FloatMap) |
| 92 | + assertEquals(message.mapInt32Double, restored.mapInt32DoubleMap) |
| 93 | + assertEquals(message.mapBoolBool, restored.mapBoolBoolMap) |
| 94 | + assertEquals(message.mapStringString, restored.mapStringStringMap) |
| 95 | + assertContentEquals( |
| 96 | + message.mapStringBytes.mapValues { it.value.toString(Charsets.UTF_32) }.entries.toList(), |
| 97 | + restored.mapStringBytesMap.mapValues { it.value.toByteArray().toString(Charsets.UTF_32) }.entries.toList() |
| 98 | + ) |
| 99 | + assertEquals( |
| 100 | + message.mapStringNestedMessage.mapValues { it.value.toProto() }, |
| 101 | + restored.mapStringNestedMessageMap |
| 102 | + ) |
| 103 | + assertEquals( |
| 104 | + message.mapStringForeignMessage.mapValues { it.value.toProto() }, |
| 105 | + restored.mapStringForeignMessageMap |
| 106 | + ) |
| 107 | + assertEquals( |
| 108 | + message.mapStringNestedEnum.mapValues { it.value.name }, |
| 109 | + restored.mapStringNestedEnumMap.mapValues { it.value.name }, |
| 110 | + ) |
| 111 | + assertEquals( |
| 112 | + message.mapStringForeignEnum.mapValues { it.value.name }, |
| 113 | + restored.mapStringForeignEnumMap.mapValues { it.value.name } |
| 114 | + ) |
| 115 | + |
| 116 | + val restoredMessage = ProtoBuf.decodeFromByteArray<KTestMessagesProto3Map>(restored.toByteArray()) |
| 117 | + assertEquals(message.copy(mapStringBytes = mapOf()), restoredMessage.copy(mapStringBytes = mapOf())) |
| 118 | + } |
| 119 | + |
| 120 | + @Test |
| 121 | + @Ignore |
| 122 | + // Issue: https://github.com/Kotlin/kotlinx.serialization/issues/2417 |
| 123 | + fun signedAndFixed() { |
| 124 | + val message = KTestMessagesProto3Map( |
| 125 | + mapSint32Sint32 = Gen.map(Gen.int(), Gen.int()).generate(), |
| 126 | + mapSint64Sint64 = Gen.map(Gen.long(), Gen.long()).generate(), |
| 127 | + mapFixed32Fixed32 = Gen.map(Gen.int(), Gen.int()).generate(), |
| 128 | + mapFixed64Fixed64 = Gen.map(Gen.long(), Gen.long()).generate(), |
| 129 | + mapSfixed32Sfixed32 = Gen.map(Gen.int(), Gen.int()).generate(), |
| 130 | + mapSfixed64Sfixed64 = Gen.map(Gen.long(), Gen.long()).generate(), |
| 131 | + ) |
| 132 | + |
| 133 | + val bytes = ProtoBuf.encodeToByteArray(message) |
| 134 | + val restored = TestMessagesProto3.TestAllTypesProto3.parseFrom(bytes) |
| 135 | + |
| 136 | + |
| 137 | + assertContentEquals(message.mapSint32Sint32.entries.toList(), restored.mapSint32Sint32Map.entries.toList()) |
| 138 | + assertContentEquals(message.mapSint64Sint64.entries.toList(), restored.mapSint64Sint64Map.entries.toList()) |
| 139 | + assertContentEquals(message.mapFixed32Fixed32.entries.toList(), restored.mapFixed32Fixed32Map.entries.toList()) |
| 140 | + assertContentEquals(message.mapFixed64Fixed64.entries.toList(), restored.mapFixed64Fixed64Map.entries.toList()) |
| 141 | + assertContentEquals( |
| 142 | + message.mapSfixed32Sfixed32.entries.toList(), |
| 143 | + restored.mapSfixed32Sfixed32Map.entries.toList() |
| 144 | + ) |
| 145 | + assertContentEquals( |
| 146 | + message.mapSfixed64Sfixed64.entries.toList(), |
| 147 | + restored.mapSfixed64Sfixed64Map.entries.toList() |
| 148 | + ) |
| 149 | + |
| 150 | + |
| 151 | + val restoredMessage = ProtoBuf.decodeFromByteArray<KTestMessagesProto3Map>(restored.toByteArray()) |
| 152 | + assertEquals(message, restoredMessage) |
| 153 | + } |
| 154 | +} |
0 commit comments