mirror of
https://github.com/mamoe/mirai.git
synced 2024-12-27 00:50:11 +08:00
[mock] Fix serialization
This commit is contained in:
parent
a8e90c6e89
commit
1ea68d82a7
@ -31,11 +31,18 @@ import net.mamoe.mirai.mock.internal.contact.AQQ_RECALL_FAILED_MESSAGE
|
||||
import net.mamoe.mirai.mock.internal.contact.MockFriendImpl
|
||||
import net.mamoe.mirai.mock.internal.contact.MockImage
|
||||
import net.mamoe.mirai.mock.internal.contact.MockStrangerImpl
|
||||
import net.mamoe.mirai.mock.internal.msgsrc.registerMockMsgSerializers
|
||||
import net.mamoe.mirai.mock.utils.mock
|
||||
import net.mamoe.mirai.mock.utils.simpleMemberInfo
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
|
||||
internal class MockMiraiImpl : MiraiImpl() {
|
||||
companion object {
|
||||
init {
|
||||
registerMockMsgSerializers()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun solveBotInvitedJoinGroupRequestEvent(
|
||||
bot: Bot,
|
||||
eventId: Long,
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
package net.mamoe.mirai.mock.internal.contact
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
@ -95,6 +96,8 @@ internal suspend fun ExternalResource.mockImplUploadAudioAsOnline(bot: MockBot):
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
|
||||
@Serializable(MockImage.Serializer::class)
|
||||
internal class MockImage(
|
||||
override val imageId: String,
|
||||
private val urlPath: String,
|
||||
@ -112,6 +115,8 @@ internal class MockImage(
|
||||
}
|
||||
}
|
||||
|
||||
object Serializer : Image.FallbackSerializer("MockImage")
|
||||
|
||||
private val _stringValue: String? by lazy(LazyThreadSafetyMode.NONE) { "[mirai:image:$imageId]" }
|
||||
|
||||
override fun getUrl(bot: Bot): String {
|
||||
|
@ -7,16 +7,98 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
|
||||
package net.mamoe.mirai.mock.internal.msgsrc
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.data.MessageSourceKind
|
||||
import net.mamoe.mirai.message.data.OnlineMessageSource
|
||||
import net.mamoe.mirai.internal.message.MessageSourceSerializerImpl
|
||||
import net.mamoe.mirai.internal.message.protocol.MessageProtocolFacadeImpl
|
||||
import net.mamoe.mirai.internal.message.protocol.serialization.MessageSerializer
|
||||
import net.mamoe.mirai.message.MessageSerializers
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.mock.internal.contact.AbstractMockContact
|
||||
import net.mamoe.mirai.mock.internal.contact.MockImage
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
|
||||
internal fun registerMockMsgSerializers() {
|
||||
val serializers = mutableListOf<MessageSerializer<*>>()
|
||||
|
||||
MessageSerializer.superclassesScope(Image::class, MessageContent::class, SingleMessage::class) {
|
||||
serializers.add(
|
||||
MessageSerializer(
|
||||
MockImage::class,
|
||||
MockImage.serializer()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
MessageSerializer.superclassesScope(MessageSource::class, MessageMetadata::class, SingleMessage::class) {
|
||||
|
||||
serializers.add(
|
||||
MessageSerializer(
|
||||
OnlineMsgSrcToGroup::class,
|
||||
OnlineMsgSrcToGroup.serializer()
|
||||
)
|
||||
)
|
||||
serializers.add(
|
||||
MessageSerializer(
|
||||
OnlineMsgSrcToFriend::class,
|
||||
OnlineMsgSrcToFriend.serializer()
|
||||
)
|
||||
)
|
||||
serializers.add(
|
||||
MessageSerializer(
|
||||
OnlineMsgSrcToStranger::class,
|
||||
OnlineMsgSrcToStranger.serializer()
|
||||
)
|
||||
)
|
||||
serializers.add(
|
||||
MessageSerializer(
|
||||
OnlineMsgSrcToTemp::class,
|
||||
OnlineMsgSrcToTemp.serializer()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
serializers.add(
|
||||
MessageSerializer(
|
||||
OnlineMsgSrcFromGroup::class,
|
||||
OnlineMsgSrcFromGroup.serializer()
|
||||
)
|
||||
)
|
||||
serializers.add(
|
||||
MessageSerializer(
|
||||
OnlineMsgSrcFromFriend::class,
|
||||
OnlineMsgSrcFromFriend.serializer()
|
||||
)
|
||||
)
|
||||
serializers.add(
|
||||
MessageSerializer(
|
||||
OnlineMsgSrcFromStranger::class,
|
||||
OnlineMsgSrcFromStranger.serializer()
|
||||
)
|
||||
)
|
||||
serializers.add(
|
||||
MessageSerializer(
|
||||
OnlineMsgSrcFromTemp::class,
|
||||
OnlineMsgSrcFromTemp.serializer()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val module = MessageProtocolFacadeImpl(listOf(), "").also {
|
||||
it.serializers.addAll(serializers)
|
||||
}.createSerializersModule()
|
||||
|
||||
MessageSerializers.registerSerializers(module)
|
||||
}
|
||||
|
||||
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
|
||||
@Serializable(OnlineMsgSrcToGroup.Serializer::class)
|
||||
internal class OnlineMsgSrcToGroup(
|
||||
override val ids: IntArray,
|
||||
override val internalIds: IntArray,
|
||||
@ -27,8 +109,13 @@ internal class OnlineMsgSrcToGroup(
|
||||
override val target: Group
|
||||
) : OnlineMessageSource.Outgoing.ToGroup() {
|
||||
override val isOriginalMessageInitialized: Boolean get() = true
|
||||
|
||||
object Serializer : KSerializer<MessageSource> by MessageSourceSerializerImpl("OnlineMessageSourceToGroup")
|
||||
|
||||
}
|
||||
|
||||
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
|
||||
@Serializable(OnlineMsgSrcToFriend.Serializer::class)
|
||||
internal class OnlineMsgSrcToFriend(
|
||||
override val ids: IntArray,
|
||||
override val internalIds: IntArray,
|
||||
@ -39,8 +126,14 @@ internal class OnlineMsgSrcToFriend(
|
||||
override val target: Friend
|
||||
) : OnlineMessageSource.Outgoing.ToFriend() {
|
||||
override val isOriginalMessageInitialized: Boolean get() = true
|
||||
|
||||
object Serializer : KSerializer<MessageSource> by MessageSourceSerializerImpl("OnlineMessageSourceToFriend")
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
|
||||
@Serializable(OnlineMsgSrcToStranger.Serializer::class)
|
||||
internal class OnlineMsgSrcToStranger(
|
||||
override val ids: IntArray,
|
||||
override val internalIds: IntArray,
|
||||
@ -51,8 +144,12 @@ internal class OnlineMsgSrcToStranger(
|
||||
override val target: Stranger
|
||||
) : OnlineMessageSource.Outgoing.ToStranger() {
|
||||
override val isOriginalMessageInitialized: Boolean get() = true
|
||||
|
||||
object Serializer : KSerializer<MessageSource> by MessageSourceSerializerImpl("OnlineMessageSourceToStranger")
|
||||
}
|
||||
|
||||
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
|
||||
@Serializable(OnlineMsgSrcToTemp.Serializer::class)
|
||||
internal class OnlineMsgSrcToTemp(
|
||||
override val ids: IntArray,
|
||||
override val internalIds: IntArray,
|
||||
@ -63,19 +160,13 @@ internal class OnlineMsgSrcToTemp(
|
||||
override val target: Member
|
||||
) : OnlineMessageSource.Outgoing.ToTemp() {
|
||||
override val isOriginalMessageInitialized: Boolean get() = true
|
||||
|
||||
object Serializer : KSerializer<MessageSource> by MessageSourceSerializerImpl("OnlineMessageSourceToTemp")
|
||||
}
|
||||
|
||||
internal class OnlineMsgFromGroup(
|
||||
override val ids: IntArray,
|
||||
override val internalIds: IntArray,
|
||||
override val time: Int,
|
||||
override val originalMessage: MessageChain,
|
||||
override val bot: Bot,
|
||||
override val sender: Member
|
||||
) : OnlineMessageSource.Incoming.FromGroup() {
|
||||
override val isOriginalMessageInitialized: Boolean get() = true
|
||||
}
|
||||
|
||||
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
|
||||
@Serializable(OnlineMsgSrcFromFriend.Serializer::class)
|
||||
internal class OnlineMsgSrcFromFriend(
|
||||
override val ids: IntArray,
|
||||
override val internalIds: IntArray,
|
||||
@ -85,8 +176,12 @@ internal class OnlineMsgSrcFromFriend(
|
||||
override val sender: Friend
|
||||
) : OnlineMessageSource.Incoming.FromFriend() {
|
||||
override val isOriginalMessageInitialized: Boolean get() = true
|
||||
|
||||
object Serializer : KSerializer<MessageSource> by MessageSourceSerializerImpl("OnlineMessageSourceFromFriend")
|
||||
}
|
||||
|
||||
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
|
||||
@Serializable(OnlineMsgSrcFromStranger.Serializer::class)
|
||||
internal class OnlineMsgSrcFromStranger(
|
||||
override val ids: IntArray,
|
||||
override val internalIds: IntArray,
|
||||
@ -96,8 +191,12 @@ internal class OnlineMsgSrcFromStranger(
|
||||
override val sender: Stranger
|
||||
) : OnlineMessageSource.Incoming.FromStranger() {
|
||||
override val isOriginalMessageInitialized: Boolean get() = true
|
||||
|
||||
object Serializer : KSerializer<MessageSource> by MessageSourceSerializerImpl("OnlineMessageSourceFromStranger")
|
||||
}
|
||||
|
||||
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
|
||||
@Serializable(OnlineMsgSrcFromTemp.Serializer::class)
|
||||
internal class OnlineMsgSrcFromTemp(
|
||||
override val ids: IntArray,
|
||||
override val internalIds: IntArray,
|
||||
@ -107,8 +206,13 @@ internal class OnlineMsgSrcFromTemp(
|
||||
override val sender: Member
|
||||
) : OnlineMessageSource.Incoming.FromTemp() {
|
||||
override val isOriginalMessageInitialized: Boolean get() = true
|
||||
|
||||
object Serializer : KSerializer<MessageSource> by MessageSourceSerializerImpl("OnlineMessageSourceFromTemp")
|
||||
|
||||
}
|
||||
|
||||
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
|
||||
@Serializable(OnlineMsgSrcFromGroup.Serializer::class)
|
||||
internal class OnlineMsgSrcFromGroup(
|
||||
override val ids: IntArray,
|
||||
override val internalIds: IntArray,
|
||||
@ -118,6 +222,9 @@ internal class OnlineMsgSrcFromGroup(
|
||||
override val sender: Member
|
||||
) : OnlineMessageSource.Incoming.FromGroup() {
|
||||
override val isOriginalMessageInitialized: Boolean get() = true
|
||||
|
||||
object Serializer : KSerializer<MessageSource> by MessageSourceSerializerImpl("OnlineMessageSourceFromGroup")
|
||||
|
||||
}
|
||||
|
||||
internal typealias MsgSrcConstructor<R> = (
|
||||
@ -141,6 +248,7 @@ internal inline fun <R> AbstractMockContact.newMsgSrc(
|
||||
is Stranger,
|
||||
is Friend,
|
||||
-> this.id
|
||||
|
||||
else -> error("Invalid contact: $this")
|
||||
},
|
||||
kind = when (this) {
|
||||
|
123
mirai-core-mock/test/mock/MessageSerializationTest.kt
Normal file
123
mirai-core-mock/test/mock/MessageSerializationTest.kt
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.mock.test.mock
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.serializer
|
||||
import net.mamoe.mirai.message.MessageSerializers
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.mock.test.MockBotTestBase
|
||||
import net.mamoe.mirai.mock.utils.randomImageContent
|
||||
import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
|
||||
internal class MessageSerializationTest : MockBotTestBase() {
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
private val module
|
||||
get() = MessageSerializers.serializersModule
|
||||
private val format
|
||||
get() = Json {
|
||||
serializersModule = module
|
||||
useArrayPolymorphism = false
|
||||
ignoreUnknownKeys = true
|
||||
}
|
||||
|
||||
private inline fun <reified T : Any> T.serialize(serializer: KSerializer<T> = module.serializer()): String {
|
||||
return format.encodeToString(serializer, this)
|
||||
}
|
||||
|
||||
private inline fun <reified T : Any> String.deserialize(serializer: KSerializer<T> = module.serializer()): T {
|
||||
return format.decodeFromString(serializer, this)
|
||||
}
|
||||
|
||||
private inline fun <reified T : Any> testSerialization(t: T, serializer: KSerializer<T> = module.serializer()) {
|
||||
val deserialized = kotlin.runCatching {
|
||||
println("Testing ${t::class.simpleName} with serializer $serializer")
|
||||
val serialized = t.serialize(serializer)
|
||||
println("Result: ${serializer.descriptor.serialName} $serialized")
|
||||
serialized.deserialize(serializer)
|
||||
}.getOrElse {
|
||||
throw IllegalStateException("Failed to serialize $t", it)
|
||||
}
|
||||
|
||||
val msg = "serialized string: ${t.serialize(serializer)}\ndeserialized string: ${
|
||||
deserialized.serialize(
|
||||
serializer
|
||||
)
|
||||
}\n"
|
||||
|
||||
|
||||
|
||||
assert1(
|
||||
t,
|
||||
deserialized,
|
||||
msg
|
||||
)
|
||||
}
|
||||
|
||||
private fun assert1(t: Any, deserialized: Any, msg: String) {
|
||||
if (deserialized is MessageSource && t is MessageSource) {
|
||||
assertSource(t, deserialized, msg)
|
||||
return
|
||||
}
|
||||
|
||||
if (t is MessageChain && deserialized is MessageChain) {
|
||||
assertEquals(t.size, deserialized.size)
|
||||
val iter1 = t.iterator()
|
||||
val iter2 = deserialized.iterator()
|
||||
|
||||
repeat(t.size) {
|
||||
assert1(iter1.next(), iter2.next(), msg)
|
||||
}
|
||||
assertFalse(iter1.hasNext(), msg)
|
||||
assertFalse(iter2.hasNext(), msg)
|
||||
return
|
||||
}
|
||||
|
||||
assertEquals(t, deserialized, msg)
|
||||
}
|
||||
|
||||
private fun assertSource(t: MessageSource, deserialized: MessageSource, msg: String) {
|
||||
assertEquals(t.kind, deserialized.kind, msg)
|
||||
assertEquals(t.botId, deserialized.botId, msg)
|
||||
assertEquals(t.fromId, deserialized.fromId, msg)
|
||||
assertEquals(t.targetId, deserialized.targetId, msg)
|
||||
assertEquals(t.time, deserialized.time, msg)
|
||||
Assertions.assertArrayEquals(t.ids, deserialized.ids, msg)
|
||||
Assertions.assertArrayEquals(t.internalIds, deserialized.internalIds, msg)
|
||||
assertEquals(t.originalMessage, deserialized.originalMessage, msg)
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testMockMessageSources() = runTest {
|
||||
testSerialization(bot.addFriend(1, "").says(""))
|
||||
testSerialization(bot.addStranger(2, "").says(""))
|
||||
bot.addGroup(3, "").let { group ->
|
||||
group.sendMessage("AWA").source.let { testSerialization(messageChainOf(it)) }
|
||||
group.addMember(6, "").says("A").let { testSerialization(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMockResources() = runTest {
|
||||
testSerialization(bot.uploadMockImage(Image.randomImageContent().toExternalResource().toAutoCloseable()))
|
||||
|
||||
"1".toByteArray().toExternalResource().use { data0 ->
|
||||
testSerialization(bot.uploadOnlineAudio(data0))
|
||||
testSerialization(bot.asFriend.uploadAudio(data0))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user