MessageSerializationTest.kt 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * Copyright 2019-2023 Mamoe Technologies and contributors.
  3. *
  4. * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
  5. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
  6. *
  7. * https://github.com/mamoe/mirai/blob/dev/LICENSE
  8. */
  9. package net.mamoe.mirai.mock.test.mock
  10. import kotlinx.serialization.*
  11. import kotlinx.serialization.json.Json
  12. import kotlinx.serialization.modules.EmptySerializersModule
  13. import kotlinx.serialization.modules.plus
  14. import net.mamoe.mirai.message.MessageSerializers
  15. import net.mamoe.mirai.message.data.*
  16. import net.mamoe.mirai.mock.test.MockBotTestBase
  17. import net.mamoe.mirai.mock.utils.randomImageContent
  18. import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
  19. import org.junit.jupiter.api.Assertions
  20. import org.junit.jupiter.api.Test
  21. import kotlin.test.assertEquals
  22. import kotlin.test.assertFalse
  23. internal class MessageSerializationTest : MockBotTestBase() {
  24. @Suppress("DEPRECATION_ERROR")
  25. private val module
  26. get() = MessageSerializers.serializersModule
  27. private val format
  28. get() = Json {
  29. serializersModule = module
  30. useArrayPolymorphism = false
  31. ignoreUnknownKeys = false
  32. }
  33. private inline fun <reified T : Any> T.serialize(serializer: KSerializer<T> = module.serializer()): String {
  34. return format.encodeToString(serializer, this)
  35. }
  36. private inline fun <reified T : Any> String.deserialize(serializer: KSerializer<T> = module.serializer()): T {
  37. return format.decodeFromString(serializer, this)
  38. }
  39. private inline fun <reified T : Any> testSerialization(t: T, serializer: KSerializer<T> = module.serializer()) {
  40. val deserialized = kotlin.runCatching {
  41. println("Testing ${t::class.simpleName} with serializer $serializer")
  42. val serialized = t.serialize(serializer)
  43. println("Result: ${serializer.descriptor.serialName} $serialized")
  44. serialized.deserialize(serializer)
  45. }.getOrElse {
  46. throw IllegalStateException("Failed to serialize $t", it)
  47. }
  48. val msg = "serialized string: ${t.serialize(serializer)}\ndeserialized string: ${
  49. deserialized.serialize(
  50. serializer
  51. )
  52. }\n"
  53. assert1(
  54. t,
  55. deserialized,
  56. msg
  57. )
  58. if (t is SingleMessage) {
  59. PolymorphicWrapperContent(t)
  60. .serialize(PolymorphicWrapperContent.serializer())
  61. .deserialize(PolymorphicWrapperContent.serializer())
  62. .let { assert1(t, it.message, msg) }
  63. }
  64. }
  65. private fun assert1(t: Any, deserialized: Any, msg: String) {
  66. if (deserialized is MessageSource && t is MessageSource) {
  67. assertSource(t, deserialized, msg)
  68. return
  69. }
  70. if (t is MessageChain && deserialized is MessageChain) {
  71. assertEquals(t.size, deserialized.size)
  72. val iter1 = t.iterator()
  73. val iter2 = deserialized.iterator()
  74. repeat(t.size) {
  75. assert1(iter1.next(), iter2.next(), msg)
  76. }
  77. assertFalse(iter1.hasNext(), msg)
  78. assertFalse(iter2.hasNext(), msg)
  79. return
  80. }
  81. assertEquals(t, deserialized, msg)
  82. }
  83. private fun assertSource(t: MessageSource, deserialized: MessageSource, msg: String) {
  84. assertEquals(t.kind, deserialized.kind, msg)
  85. assertEquals(t.botId, deserialized.botId, msg)
  86. assertEquals(t.fromId, deserialized.fromId, msg)
  87. assertEquals(t.targetId, deserialized.targetId, msg)
  88. assertEquals(t.time, deserialized.time, msg)
  89. Assertions.assertArrayEquals(t.ids, deserialized.ids, msg)
  90. Assertions.assertArrayEquals(t.internalIds, deserialized.internalIds, msg)
  91. assertEquals(t.originalMessage, deserialized.originalMessage, msg)
  92. }
  93. @Test
  94. fun testSerializersModulePlus() {
  95. MessageSerializers.serializersModule + EmptySerializersModule()
  96. }
  97. @Test
  98. fun testMockMessageSources() = runTest {
  99. testSerialization(bot.addFriend(1, "").says(""))
  100. testSerialization(bot.addStranger(2, "").says(""))
  101. bot.addGroup(3, "").let { group ->
  102. group.sendMessage("AWA").source.let { testSerialization(messageChainOf(it)) }
  103. group.addMember(6, "").says("A").let { testSerialization(it) }
  104. }
  105. }
  106. @Test
  107. fun testMockResources() = runTest {
  108. testSerialization(bot.uploadMockImage(Image.randomImageContent().toExternalResource().toAutoCloseable()))
  109. "1".toByteArray().toExternalResource().use { data0 ->
  110. testSerialization(bot.uploadOnlineAudio(data0))
  111. testSerialization(bot.asFriend.uploadAudio(data0))
  112. }
  113. }
  114. @Serializable
  115. data class PolymorphicWrapperImage(
  116. val message: @Polymorphic Image
  117. )
  118. @Serializable
  119. data class PolymorphicWrapperContent(
  120. val message: @Polymorphic SingleMessage
  121. )
  122. @Test
  123. @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "UNRESOLVED_REFERENCE")
  124. fun `test serialization for MockImage`() = runTest {
  125. val img = [email protected](
  126. Image.randomImageContent().toExternalResource().toAutoCloseable()
  127. )
  128. PolymorphicWrapperImage(img)
  129. .serialize(PolymorphicWrapperImage.serializer())
  130. .also { println(it) }
  131. .deserialize(PolymorphicWrapperImage.serializer())
  132. }
  133. // https://github.com/mamoe/mirai/pull/2414#issuecomment-1386253123
  134. @Test
  135. fun `test 2414-1386253123`() = runTest {
  136. // event
  137. val img = [email protected](
  138. Image.randomImageContent().toExternalResource().toAutoCloseable()
  139. )
  140. val msg = buildMessageChain {
  141. add("imgUploaded")
  142. add(img)
  143. }
  144. val s = format.encodeToString(msg)
  145. println(s)
  146. println(format.decodeFromString<MessageChain>(s))
  147. testSerialization(msg)
  148. }
  149. }