mirror of
https://github.com/mamoe/mirai.git
synced 2025-04-25 04:50:26 +08:00
Change tests to multiplatform
This commit is contained in:
parent
20704b89b4
commit
2396851b63
buildSrc/src/main/kotlin
mirai-core-api/src/commonMain/kotlin
mirai-core-utils/src
commonMain/kotlin
commonTest/kotlin/net/mamoe/mirai/utils
jvmBaseMain/kotlin
nativeMain/kotlin
mirai-core/src
commonMain/kotlin
commonTest/kotlin
event
message
network
AwaitStateTest.ktServerListTest.kt
component
framework
AbstractCommonNHTest.ktAbstractCommonNHTestWithSelector.ktAbstractNettyNHTest.ktAbstractRealNetworkHandlerTest.ktAbstractRealTimeActionTestUnit.ktITestNetworkHandler.ktTestNetworkHandler.ktsessionUtils.kt
handler
impl/common
notice/processors
AbstractNoticeProcessorTest.ktGroupTransferTest.ktMemberAdminChangeTest.ktMemberJoinTest.ktMemberQuitTest.ktMessageSyncTest.ktMessageTest.ktMuteTest.ktRecallTest.kt
test
utils/io/serialization/tars/internal
jvmBaseMain/kotlin/network/impl/netty
jvmBaseTest/kotlin
network
framework
impl/netty
test
testFramework
codegen
RemoveDefaultValuesVisitor.ktValueDescAnalyzer.kt
descriptors
ClassValueDesc.ktCollectionLikeValueDesc.ktCollectionValueDesc.ktMapValueDesc.ktObjectArrayValueDesc.ktPlainValueDesc.ktPrimitiveArrayValueDesc.ktValueDesc.kt
test
visitor
visitors
desensitizer
message/protocol
notice
test
utils
nativeTest/kotlin
@ -120,7 +120,7 @@ fun Project.configureHMPPJvm() {
|
||||
androidMain.dependsOn(jvmBaseMain)
|
||||
|
||||
jvmTest.dependsOn(jvmBaseTest)
|
||||
androidTest.dependsOn(commonTest)
|
||||
androidTest.dependsOn(jvmBaseTest)
|
||||
|
||||
nativeMain.dependsOn(commonMain)
|
||||
nativeTest.dependsOn(commonTest)
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("MessageUtils")
|
||||
@file:Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
package net.mamoe.mirai.message.data
|
||||
|
||||
|
@ -181,9 +181,7 @@ internal object DeviceInfoCommonImpl {
|
||||
@Suppress("DuplicatedCode")
|
||||
fun equalsImpl(deviceInfo: DeviceInfo, other: Any?): Boolean = deviceInfo.run {
|
||||
if (deviceInfo === other) return true
|
||||
if (other !is DeviceInfo) return false
|
||||
|
||||
other as DeviceInfo
|
||||
if (!isSameType(this, other)) return false
|
||||
|
||||
if (!display.contentEquals(other.display)) return false
|
||||
if (!product.contentEquals(other.product)) return false
|
||||
|
@ -69,5 +69,6 @@ public expect fun <E> ConcurrentSet(): MutableSet<E>
|
||||
@Deprecated("", ReplaceWith("getOrElse(key) { default }"))
|
||||
public fun <K, V : R, R> Map<K, V>.getOrDefault(key: K, default: R): R = getOrElse(key) { default }
|
||||
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") // JDK 1.8
|
||||
@Deprecated("", ReplaceWith("getOrPut(key) { value }"))
|
||||
public fun <K, V> MutableMap<K, V>.putIfAbsent(key: K, value: V): V = getOrPut(key) { value }
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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.utils
|
||||
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.atomicfu.locks.SynchronizedObject
|
||||
import kotlinx.atomicfu.locks.synchronized
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
public fun <T : Any> computeOnNullMutableProperty(initializer: () -> T): ComputeOnNullMutableProperty<T> =
|
||||
ComputeOnNullMutablePropertyImpl(initializer)
|
||||
|
||||
public interface ComputeOnNullMutableProperty<V : Any> {
|
||||
public fun get(): V
|
||||
public fun set(value: V?)
|
||||
|
||||
public operator fun getValue(thisRef: Any?, property: KProperty<*>): V = get()
|
||||
public operator fun setValue(thisRef: Any?, property: KProperty<*>, value: V?): Unit = set(value)
|
||||
}
|
||||
|
||||
|
||||
private class ComputeOnNullMutablePropertyImpl<T : Any>(
|
||||
private val initializer: () -> T
|
||||
) : ComputeOnNullMutableProperty<T> {
|
||||
private val value = atomic<T?>(null)
|
||||
private val lock = SynchronizedObject()
|
||||
|
||||
override tailrec fun get(): T {
|
||||
return when (val v = this.value.value) {
|
||||
null -> synchronized(lock) {
|
||||
if (this.value.value === null) {
|
||||
val value = this.initializer()
|
||||
// compiler inserts
|
||||
this.value.compareAndSet(null, value) // setValue prevails
|
||||
return get()
|
||||
} else this.value.value as T
|
||||
}
|
||||
else -> v
|
||||
}
|
||||
}
|
||||
|
||||
override fun set(value: T?) {
|
||||
this.value.value = value
|
||||
}
|
||||
}
|
@ -9,55 +9,76 @@
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
public interface File {
|
||||
import io.ktor.utils.io.core.*
|
||||
|
||||
/**
|
||||
* Multiplatform implementation of file operations.
|
||||
*/
|
||||
public expect interface MiraiFile {
|
||||
public val name: String
|
||||
public val path: String
|
||||
public val parent: MiraiFile?
|
||||
|
||||
public val absolutePath: String
|
||||
|
||||
public val length: Long
|
||||
|
||||
public val parent: File?
|
||||
|
||||
public val isFile: Boolean
|
||||
public val isDirectory: Boolean
|
||||
|
||||
public fun exists(): Boolean
|
||||
|
||||
public fun resolve(path: String): File
|
||||
public fun resolve(file: File): File
|
||||
public fun resolve(path: String): MiraiFile
|
||||
public fun resolve(file: MiraiFile): MiraiFile
|
||||
|
||||
public fun createNewFile()
|
||||
public fun delete()
|
||||
public fun mkdirs()
|
||||
public fun createNewFile(): Boolean
|
||||
public fun delete(): Boolean
|
||||
|
||||
public fun readText(): String
|
||||
public fun readBytes(): ByteArray
|
||||
public fun mkdir(): Boolean
|
||||
public fun mkdirs(): Boolean
|
||||
|
||||
public fun writeBytes(data: ByteArray)
|
||||
public fun writeText(text: String)
|
||||
public fun input(): Input
|
||||
public fun output(): Output
|
||||
|
||||
public companion object {
|
||||
public fun create(path: String): File {
|
||||
TODO("")
|
||||
}
|
||||
public fun create(absolutePath: String): MiraiFile
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public fun File.createFileIfNotExists() {
|
||||
public fun MiraiFile.writeBytes(data: ByteArray) {
|
||||
return output().use { it.writeFully(data) }
|
||||
}
|
||||
|
||||
public fun MiraiFile.writeText(text: String) {
|
||||
return output().use { it.writeText(text) }
|
||||
}
|
||||
|
||||
public fun MiraiFile.readText(): String {
|
||||
return input().use { it.readText() }
|
||||
}
|
||||
|
||||
public fun MiraiFile.readBytes(): ByteArray {
|
||||
return input().use { it.readBytes() }
|
||||
}
|
||||
|
||||
|
||||
public fun MiraiFile.createFileIfNotExists() {
|
||||
if (!this.exists()) {
|
||||
this.parent?.mkdirs()
|
||||
this.createNewFile()
|
||||
}
|
||||
}
|
||||
|
||||
public fun File.resolveCreateFile(relative: String): File = this.resolve(relative).apply { createFileIfNotExists() }
|
||||
public fun File.resolveCreateFile(relative: File): File = this.resolve(relative).apply { createFileIfNotExists() }
|
||||
public fun MiraiFile.resolveCreateFile(relative: String): MiraiFile =
|
||||
this.resolve(relative).apply { createFileIfNotExists() }
|
||||
|
||||
public fun File.resolveMkdir(relative: String): File = this.resolve(relative).apply { mkdirs() }
|
||||
public fun File.resolveMkdir(relative: File): File = this.resolve(relative).apply { mkdirs() }
|
||||
public fun MiraiFile.resolveCreateFile(relative: MiraiFile): MiraiFile =
|
||||
this.resolve(relative).apply { createFileIfNotExists() }
|
||||
|
||||
public fun File.touch(): File = apply {
|
||||
public fun MiraiFile.resolveMkdir(relative: String): MiraiFile = this.resolve(relative).apply { mkdirs() }
|
||||
public fun MiraiFile.resolveMkdir(relative: MiraiFile): MiraiFile = this.resolve(relative).apply { mkdirs() }
|
||||
|
||||
public fun MiraiFile.touch(): MiraiFile = apply {
|
||||
parent?.mkdirs()
|
||||
createNewFile()
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ public inline fun <T, R> KSerializer<T>.mapPrimitive(
|
||||
}
|
||||
|
||||
|
||||
public fun <T> File.loadNotBlankAs(
|
||||
public fun <T> MiraiFile.loadNotBlankAs(
|
||||
serializer: DeserializationStrategy<T>,
|
||||
stringFormat: StringFormat,
|
||||
): T? {
|
||||
@ -76,7 +76,7 @@ public fun <T> File.loadNotBlankAs(
|
||||
return stringFormat.decodeFromString(serializer, this.readText())
|
||||
}
|
||||
|
||||
public fun <T> File.loadNotBlankAs(
|
||||
public fun <T> MiraiFile.loadNotBlankAs(
|
||||
serializer: DeserializationStrategy<T>,
|
||||
binaryFormat: BinaryFormat,
|
||||
): T? {
|
||||
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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.utils
|
||||
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
internal class ComputeOnNullMutablePropertyTest {
|
||||
@Test
|
||||
fun `can initialize`() {
|
||||
val prop = computeOnNullMutableProperty { "ok" }
|
||||
assertEquals("ok", prop.get())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can override`() {
|
||||
val called = atomic(false)
|
||||
val prop = computeOnNullMutableProperty { "not ok".also { called.value = true } }
|
||||
prop.set("ok")
|
||||
assertEquals("ok", prop.get())
|
||||
assertFalse { called.value }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can reinitialize 1`() {
|
||||
val called = atomic(false)
|
||||
val prop = computeOnNullMutableProperty { "ok".also { called.value = true } }
|
||||
prop.set("not ok 2")
|
||||
prop.set(null)
|
||||
assertEquals("ok", prop.get())
|
||||
assertTrue { called.value }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can reinitialize 2`() {
|
||||
val prop = computeOnNullMutableProperty { "ok" }
|
||||
prop.get()
|
||||
prop.set(null)
|
||||
assertEquals("ok", prop.get())
|
||||
}
|
||||
}
|
@ -39,15 +39,15 @@ internal class LateinitMutablePropertyTest {
|
||||
@Test
|
||||
fun initializerCalledOnce() {
|
||||
val value = Symbol("expected")
|
||||
val counter = atomic(0)
|
||||
var counter = 0
|
||||
|
||||
val prop by lateinitMutableProperty {
|
||||
counter.incrementAndGet()
|
||||
counter++
|
||||
value
|
||||
}
|
||||
assertSame(value, prop)
|
||||
assertSame(value, prop)
|
||||
assertEquals(1, counter.value)
|
||||
assertEquals(1, counter)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
31
mirai-core-utils/src/jvmBaseMain/kotlin/Files.kt
Normal file
31
mirai-core-utils/src/jvmBaseMain/kotlin/Files.kt
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.utils
|
||||
|
||||
import java.io.File
|
||||
|
||||
|
||||
public fun File.createFileIfNotExists() {
|
||||
if (!this.exists()) {
|
||||
this.parentFile?.mkdirs()
|
||||
this.createNewFile()
|
||||
}
|
||||
}
|
||||
|
||||
public fun File.resolveCreateFile(relative: String): File = this.resolve(relative).apply { createFileIfNotExists() }
|
||||
public fun File.resolveCreateFile(relative: File): File = this.resolve(relative).apply { createFileIfNotExists() }
|
||||
|
||||
public fun File.resolveMkdir(relative: String): File = this.resolve(relative).apply { mkdirs() }
|
||||
public fun File.resolveMkdir(relative: File): File = this.resolve(relative).apply { mkdirs() }
|
||||
|
||||
public fun File.touch(): File = apply {
|
||||
parentFile?.mkdirs()
|
||||
createNewFile()
|
||||
}
|
77
mirai-core-utils/src/jvmBaseMain/kotlin/MiraiFile.kt
Normal file
77
mirai-core-utils/src/jvmBaseMain/kotlin/MiraiFile.kt
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.utils
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import io.ktor.utils.io.streams.*
|
||||
import java.io.File
|
||||
|
||||
public actual interface MiraiFile {
|
||||
public actual val name: String
|
||||
public actual val parent: MiraiFile?
|
||||
|
||||
public actual val absolutePath: String
|
||||
|
||||
public actual val length: Long
|
||||
|
||||
public actual val isFile: Boolean
|
||||
public actual val isDirectory: Boolean
|
||||
|
||||
public actual fun exists(): Boolean
|
||||
|
||||
public actual fun resolve(path: String): MiraiFile
|
||||
public actual fun resolve(file: MiraiFile): MiraiFile
|
||||
|
||||
public actual fun createNewFile(): Boolean
|
||||
public actual fun delete(): Boolean
|
||||
|
||||
public actual fun mkdir(): Boolean
|
||||
public actual fun mkdirs(): Boolean
|
||||
|
||||
public actual fun input(): Input
|
||||
public actual fun output(): Output
|
||||
|
||||
public actual companion object {
|
||||
public actual fun create(absolutePath: String): MiraiFile {
|
||||
return File(absolutePath).asMiraiFile()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun File.asMiraiFile(): MiraiFile {
|
||||
return JvmFileAsMiraiFile(this)
|
||||
}
|
||||
|
||||
public fun MiraiFile.toJvmFile(): File {
|
||||
if (this is JvmFileAsMiraiFile) {
|
||||
return jvmFile
|
||||
}
|
||||
return File(absolutePath)
|
||||
}
|
||||
|
||||
internal class JvmFileAsMiraiFile(
|
||||
internal val jvmFile: File
|
||||
) : MiraiFile {
|
||||
override val name: String get() = jvmFile.name
|
||||
override val parent: MiraiFile? get() = jvmFile.parentFile?.asMiraiFile()
|
||||
override val absolutePath: String get() = jvmFile.absolutePath
|
||||
override val length: Long get() = jvmFile.length()
|
||||
override val isFile: Boolean get() = jvmFile.isFile
|
||||
override val isDirectory: Boolean get() = jvmFile.isDirectory
|
||||
override fun exists(): Boolean = jvmFile.exists()
|
||||
override fun resolve(path: String): MiraiFile = jvmFile.resolve(path).asMiraiFile()
|
||||
override fun resolve(file: MiraiFile): MiraiFile = jvmFile.resolve(file.absolutePath).asMiraiFile()
|
||||
override fun createNewFile(): Boolean = jvmFile.createNewFile()
|
||||
override fun delete(): Boolean = jvmFile.delete()
|
||||
override fun mkdir(): Boolean = jvmFile.mkdir()
|
||||
override fun mkdirs(): Boolean = jvmFile.mkdirs()
|
||||
override fun input(): Input = jvmFile.inputStream().asInput()
|
||||
override fun output(): Output = jvmFile.outputStream().asOutput()
|
||||
}
|
39
mirai-core-utils/src/nativeMain/kotlin/MiraiFile.kt
Normal file
39
mirai-core-utils/src/nativeMain/kotlin/MiraiFile.kt
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.utils
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
|
||||
/**
|
||||
* Multiplatform implementation of file operations.
|
||||
*/
|
||||
public actual interface MiraiFile {
|
||||
public actual val name: String
|
||||
public actual val parent: MiraiFile?
|
||||
public actual val absolutePath: String
|
||||
public actual val length: Long
|
||||
public actual val isFile: Boolean
|
||||
public actual val isDirectory: Boolean
|
||||
public actual fun exists(): Boolean
|
||||
public actual fun resolve(path: String): MiraiFile
|
||||
public actual fun resolve(file: MiraiFile): MiraiFile
|
||||
public actual fun createNewFile(): Boolean
|
||||
public actual fun delete(): Boolean
|
||||
public actual fun mkdir(): Boolean
|
||||
public actual fun mkdirs(): Boolean
|
||||
public actual fun input(): Input
|
||||
public actual fun output(): Output
|
||||
|
||||
public actual companion object {
|
||||
public actual fun create(absolutePath: String): MiraiFile {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
}
|
@ -85,9 +85,9 @@ internal class GroupMemberListCaches(
|
||||
return ret
|
||||
}
|
||||
|
||||
private val cacheDir: File by lazy { bot.configuration.groupCacheDir() }
|
||||
private val cacheDir: MiraiFile by lazy { bot.configuration.groupCacheDir() }
|
||||
|
||||
private fun resolveCacheFile(groupCode: Long): File {
|
||||
private fun resolveCacheFile(groupCode: Long): MiraiFile {
|
||||
cacheDir.mkdirs()
|
||||
return cacheDir.resolve("$groupCode.json")
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ internal class MemoryAccountSecretsManager : AccountSecretsManager {
|
||||
|
||||
|
||||
internal class FileCacheAccountSecretsManager(
|
||||
val file: File,
|
||||
val file: MiraiFile,
|
||||
val logger: MiraiLogger,
|
||||
) : AccountSecretsManager {
|
||||
@Synchronized
|
||||
@ -214,7 +214,7 @@ internal class FileCacheAccountSecretsManager(
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun saveSecretsToFile(file: File, account: BotAccount, secrets: AccountSecrets) {
|
||||
fun saveSecretsToFile(file: MiraiFile, account: BotAccount, secrets: AccountSecrets) {
|
||||
file.writeBytes(
|
||||
TEA.encrypt(
|
||||
AccountSecretsImpl(secrets).toByteArray(AccountSecretsImpl.serializer()),
|
||||
|
@ -19,10 +19,7 @@ import net.mamoe.mirai.internal.network.ProtoBufForCache
|
||||
import net.mamoe.mirai.internal.network.component.ComponentKey
|
||||
import net.mamoe.mirai.internal.network.component.ComponentStorage
|
||||
import net.mamoe.mirai.internal.utils.actualCacheDir
|
||||
import net.mamoe.mirai.utils.BotConfiguration
|
||||
import net.mamoe.mirai.utils.ConcurrentSet
|
||||
import net.mamoe.mirai.utils.File
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.*
|
||||
import kotlin.jvm.Volatile
|
||||
|
||||
internal interface BdhSessionSyncer {
|
||||
@ -75,9 +72,9 @@ internal class BdhSessionSyncerImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private val sessionCacheFile: File
|
||||
private val sessionCacheFile: MiraiFile
|
||||
get() = configuration.actualCacheDir().resolve("session.bin")
|
||||
private val serverListCacheFile: File
|
||||
private val serverListCacheFile: MiraiFile
|
||||
get() = configuration.actualCacheDir().resolve("servers.json")
|
||||
|
||||
override fun loadServerListFromCache() {
|
||||
|
@ -148,7 +148,7 @@ internal class ServerListImpl(
|
||||
*/
|
||||
@Synchronized
|
||||
override fun pollCurrent(): ServerAddress? {
|
||||
return current.firstOrNull()?.also { address ->
|
||||
return current.removeFirstOrNull()?.also { address ->
|
||||
lastPolledAddress = address
|
||||
}
|
||||
}
|
||||
|
@ -83,9 +83,10 @@ internal abstract class CommonNetworkHandler<Conn>(
|
||||
*/
|
||||
protected abstract fun Conn.writeAndFlushOrCloseAsync(packet: OutgoingPacket)
|
||||
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
|
||||
protected abstract fun Conn.close()
|
||||
|
||||
protected inner class PacketDecodePipeline(parentContext: CoroutineContext) :
|
||||
internal inner class PacketDecodePipeline(parentContext: CoroutineContext) :
|
||||
CoroutineScope by parentContext.childScope() {
|
||||
private val packetCodec: PacketCodec by lazy { context[PacketCodec] }
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.internal.network.handler.selector
|
||||
|
||||
internal open class NetworkChannelException : NetworkException {
|
||||
constructor() : super(true)
|
||||
constructor(cause: Throwable?) : super(true, cause)
|
||||
constructor(message: String) : super(message, true)
|
||||
constructor(message: String, cause: Throwable?) : super(message, cause, true)
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
|
||||
package net.mamoe.mirai.internal.network.handler.selector
|
||||
|
||||
internal abstract class NetworkException : Exception {
|
||||
internal open class NetworkException : Exception {
|
||||
/**
|
||||
* If true, the selector may recover the network handler by some means.
|
||||
*/
|
||||
|
@ -12,7 +12,7 @@
|
||||
package net.mamoe.mirai.internal.utils
|
||||
|
||||
import net.mamoe.mirai.utils.BotConfiguration
|
||||
import net.mamoe.mirai.utils.File
|
||||
import net.mamoe.mirai.utils.MiraiFile
|
||||
import net.mamoe.mirai.utils.resolveCreateFile
|
||||
import net.mamoe.mirai.utils.resolveMkdir
|
||||
import kotlin.jvm.JvmName
|
||||
@ -22,9 +22,11 @@ internal expect val BotConfiguration.workingDirPath: String
|
||||
|
||||
internal expect val BotConfiguration.cacheDirPath: String
|
||||
|
||||
internal fun BotConfiguration.actualCacheDir(): File = File.create(workingDirPath).resolveMkdir(cacheDirPath)
|
||||
internal fun BotConfiguration.contactCacheDir(): File = actualCacheDir().resolveMkdir("contacts")
|
||||
internal fun BotConfiguration.friendCacheFile(): File = contactCacheDir().resolveCreateFile("friends.json")
|
||||
internal fun BotConfiguration.groupCacheDir(): File = contactCacheDir().resolveMkdir("groups")
|
||||
internal fun BotConfiguration.groupCacheFile(groupId: Long): File = groupCacheDir().resolveCreateFile("$groupId.json")
|
||||
internal fun BotConfiguration.accountSecretsFile(): File = actualCacheDir().resolve("account.secrets")
|
||||
internal fun BotConfiguration.actualCacheDir(): MiraiFile = MiraiFile.create(workingDirPath).resolveMkdir(cacheDirPath)
|
||||
internal fun BotConfiguration.contactCacheDir(): MiraiFile = actualCacheDir().resolveMkdir("contacts")
|
||||
internal fun BotConfiguration.friendCacheFile(): MiraiFile = contactCacheDir().resolveCreateFile("friends.json")
|
||||
internal fun BotConfiguration.groupCacheDir(): MiraiFile = contactCacheDir().resolveMkdir("groups")
|
||||
internal fun BotConfiguration.groupCacheFile(groupId: Long): MiraiFile =
|
||||
groupCacheDir().resolveCreateFile("$groupId.json")
|
||||
|
||||
internal fun BotConfiguration.accountSecretsFile(): MiraiFile = actualCacheDir().resolve("account.secrets")
|
@ -73,33 +73,32 @@ private fun <T : JceStruct> ByteArray.doLoadAs(
|
||||
Tars.UTF_8.load(deserializer, input)
|
||||
}
|
||||
} catch (originalException: Exception) {
|
||||
val log = BytePacketBuilder()
|
||||
val build by lazy { log.build() }
|
||||
try {
|
||||
val value = log.use { stream ->
|
||||
stream.appendLine("\nData: ")
|
||||
stream.appendLine(this.toUHexString(offset = offset, length = length))
|
||||
stream.appendLine("Trace:")
|
||||
BytePacketBuilder().use { log ->
|
||||
val build by lazy { log.build() }
|
||||
try {
|
||||
log.appendLine("\nData: ")
|
||||
log.appendLine(this.toUHexString(offset = offset, length = length))
|
||||
log.appendLine("Trace:")
|
||||
|
||||
this.toReadPacket(offset = offset, length = length).use { input ->
|
||||
Tars.UTF_8.load(deserializer, input, debugLogger = DebugLogger(stream))
|
||||
val value = this.toReadPacket(offset = offset, length = length).use { input ->
|
||||
Tars.UTF_8.load(deserializer, input, debugLogger = DebugLogger(log))
|
||||
}
|
||||
}
|
||||
return value.also {
|
||||
TarsDecoder.logger.warning(
|
||||
contextualBugReportException(
|
||||
"解析 " + deserializer.descriptor.serialName,
|
||||
"启用 debug 模式后解析正常: $value \n\n${build.readText()}",
|
||||
originalException
|
||||
return value.also {
|
||||
TarsDecoder.logger.warning(
|
||||
contextualBugReportException(
|
||||
"解析 " + deserializer.descriptor.serialName,
|
||||
"启用 debug 模式后解析正常: $value \n\n${build.readText()}",
|
||||
originalException
|
||||
)
|
||||
)
|
||||
}
|
||||
} catch (secondFailure: Exception) {
|
||||
throw contextualBugReportException(
|
||||
"解析 " + deserializer.descriptor.serialName,
|
||||
build.readText(),
|
||||
ExceptionCollector.compressExceptions(originalException, secondFailure)
|
||||
)
|
||||
}
|
||||
} catch (secondFailure: Exception) {
|
||||
throw contextualBugReportException(
|
||||
"解析 " + deserializer.descriptor.serialName,
|
||||
build.readText(),
|
||||
ExceptionCollector.compressExceptions(originalException, secondFailure)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -190,8 +190,7 @@ internal class EventTests : AbstractEventTest() {
|
||||
|
||||
private fun singleThreaded(step: StepUtil, invoke: suspend EventChannel<Event>.() -> Unit) {
|
||||
// runBlocking 会完全堵死, 没法退出
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val scope = CoroutineScope(newSingleThreadContext("EventTests singleThreaded worker"))
|
||||
val scope = CoroutineScope(borrowSingleThreadDispatcher())
|
||||
val job = scope.launch {
|
||||
invoke(scope.globalEventChannel())
|
||||
}
|
||||
|
@ -19,8 +19,7 @@ import kotlin.test.*
|
||||
|
||||
@JvmBlockingBridge
|
||||
internal class NextEventTest : AbstractEventTest() {
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
private val dispatcher: CoroutineDispatcher = newSingleThreadContext("NextEventTest")
|
||||
private val dispatcher: CoroutineDispatcher = borrowSingleThreadDispatcher()
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@AfterTest
|
||||
|
@ -14,8 +14,9 @@ import net.mamoe.mirai.internal.message.image.calculateImageInfo
|
||||
import net.mamoe.mirai.internal.test.AbstractTest
|
||||
import net.mamoe.mirai.message.data.ImageType
|
||||
import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
|
||||
import net.mamoe.mirai.utils.File
|
||||
import net.mamoe.mirai.utils.MiraiFile
|
||||
import net.mamoe.mirai.utils.hexToBytes
|
||||
import net.mamoe.mirai.utils.readBytes
|
||||
import net.mamoe.mirai.utils.withUse
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -66,9 +67,9 @@ internal class ImageReadingTest : AbstractTest() {
|
||||
"FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 78 00 78 00 00 FF D0 FF D1 FF D2 FF D3 FF D4 FF D5 FF D6 FF D7 FF E1 00 5A 45 78 69 66 00 00 4D 4D 00 2A 00 00 00 08 00 05 03 01 00 05 00 00 00 01 00 00 00 4A 03 03 00 01 00 00 00 01 00 00 00 00 51 10 00 01 00 00 00 01 01 00 00 00 51 11 00 04 00 00 00 01 00 00 12 74 51 12 00 04 00 00 00 01 00 00 12 74 00 00 00 00 00 01 86 A0 00 00 B1 8F FF DB 00 43 00 02 01 01 02 01 01 02 02 02 02 02 02 02 02 03 05 03 03 03 03 03 06 04 04 03 05 07 06 07 07 07 06 07 07 08 09 0B 09 08 08 0A 08 07 07 0A 0D 0A 0A 0B 0C 0C 0C 0C 07 09 0E 0F 0D 0C 0E 0B 0C 0C 0C FF DB 00 43 01 02 02 02 03 03 03 06 03 03 06 0C 08 07 08 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C FF C2 00 11 08 01 90 01 E0 03 01 22 00 02 11 01 03 11 01 FF DA".testMatch(
|
||||
ImageType.JPG
|
||||
)
|
||||
println("Current path: " + net.mamoe.mirai.utils.File.create(".").absolutePath)
|
||||
println("Current path: " + net.mamoe.mirai.utils.MiraiFile.create(".").absolutePath)
|
||||
//Issue 1610
|
||||
File.create("./src/commonTest/resources/image/jpeg-header-issue-1610.bin").readBytes().testRead(
|
||||
MiraiFile.create("./src/commonTest/resources/image/jpeg-header-issue-1610.bin").readBytes().testRead(
|
||||
ImageType.JPG
|
||||
)
|
||||
//Failed to find
|
||||
|
@ -19,7 +19,7 @@ import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
class TestMiraiCode : AbstractTest() {
|
||||
internal class TestMiraiCode : AbstractTest() {
|
||||
@Test
|
||||
fun testDynamicMiraiCodeParser() {
|
||||
fun runTest(args: Int, code: String, parse: (args: Array<String>) -> Unit) {
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
package net.mamoe.mirai.internal.network
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.consumeAsFlow
|
||||
import kotlinx.coroutines.selects.select
|
||||
@ -73,8 +72,7 @@ internal class AwaitStateTest : AbstractMockNetworkHandlerTest() {
|
||||
}
|
||||
|
||||
// single thread so we can use [yield] to transfer dispatch
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
private val singleThreadDispatcher: CoroutineDispatcher = newSingleThreadContext("AwaitStateTest")
|
||||
private val singleThreadDispatcher: CoroutineDispatcher = borrowSingleThreadDispatcher()
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@AfterTest
|
||||
|
@ -1,18 +1,21 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
||||
* 此源代码的使用受 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/master/LICENSE
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:OptIn(TestOnly::class)
|
||||
|
||||
package net.mamoe.mirai.internal.network
|
||||
|
||||
import net.mamoe.mirai.internal.network.components.ServerAddress
|
||||
import net.mamoe.mirai.internal.network.components.ServerList
|
||||
import net.mamoe.mirai.internal.network.components.ServerListImpl
|
||||
import net.mamoe.mirai.internal.test.AbstractTest
|
||||
import net.mamoe.mirai.utils.TestOnly
|
||||
import kotlin.test.*
|
||||
|
||||
internal class ServerListTest : AbstractTest() {
|
||||
@ -32,7 +35,7 @@ internal class ServerListTest : AbstractTest() {
|
||||
val instance = ServerListImpl()
|
||||
val old = instance.getLastPolledIP()
|
||||
assertNotNull(old)
|
||||
assert(old.isEmpty())
|
||||
assertTrue { old.isEmpty() }
|
||||
assertNotNull(instance.pollCurrent())
|
||||
val new = instance.getLastPolledIP()
|
||||
assertNotNull(new)
|
||||
|
@ -7,26 +7,29 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:OptIn(TestOnly::class)
|
||||
|
||||
package net.mamoe.mirai.internal.network.component
|
||||
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.isActive
|
||||
import net.mamoe.mirai.internal.contact.uin
|
||||
import net.mamoe.mirai.internal.network.components.BotInitProcessor
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTestWithSelector
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTestWithSelector
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushForceOffline
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacket
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcPushForceOffline
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.utils.TestOnly
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
internal class BotInitProcessorTest {
|
||||
class WithoutSelector : AbstractNettyNHTest() {
|
||||
class WithoutSelector : AbstractCommonNHTest() {
|
||||
@Test
|
||||
fun `BotInitProcessor halted`() = runBlockingUnit {
|
||||
val p = setComponent(BotInitProcessor, object : BotInitProcessor {
|
||||
@ -43,7 +46,7 @@ internal class BotInitProcessorTest {
|
||||
}
|
||||
})
|
||||
assertTrue { network.isActive }
|
||||
network.setStateLoading(channel)
|
||||
network.setStateLoading(conn)
|
||||
assertEquals(1, p.ranTimes)
|
||||
assertEquals(0, p.haltedTimes)
|
||||
assertState(NetworkHandler.State.LOADING)
|
||||
@ -61,7 +64,7 @@ internal class BotInitProcessorTest {
|
||||
}
|
||||
}
|
||||
|
||||
class WithSelector : AbstractNettyNHTestWithSelector() {
|
||||
class WithSelector : AbstractCommonNHTestWithSelector() {
|
||||
@Test
|
||||
fun `BotInitProcessor halted`() = runBlockingUnit {
|
||||
bot.configuration.autoReconnectOnForceOffline = true
|
||||
@ -79,7 +82,7 @@ internal class BotInitProcessorTest {
|
||||
}
|
||||
})
|
||||
assertTrue { network.isActive }
|
||||
network.setStateLoading(channel)
|
||||
network.setStateLoading(conn)
|
||||
assertEquals(1, p.ranTimes)
|
||||
assertEquals(0, p.haltedTimes)
|
||||
assertState(NetworkHandler.State.LOADING)
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.internal.network.framework
|
||||
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.network.handler.*
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.utils.ExceptionCollector
|
||||
|
||||
/**
|
||||
* You may need to override [createConnection]
|
||||
*/
|
||||
internal abstract class TestCommonNetworkHandler(
|
||||
override val bot: QQAndroidBot,
|
||||
context: NetworkHandlerContext,
|
||||
address: SocketAddress,
|
||||
) : CommonNetworkHandler<PlatformConn>(context, address), ITestNetworkHandler<PlatformConn> {
|
||||
override suspend fun createConnection(): PlatformConn {
|
||||
return PlatformConn()
|
||||
}
|
||||
|
||||
override fun PlatformConn.writeAndFlushOrCloseAsync(packet: OutgoingPacket) {
|
||||
}
|
||||
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
|
||||
override fun PlatformConn.close() {
|
||||
}
|
||||
|
||||
override fun setStateClosed(exception: Throwable?): NetworkHandlerSupport.BaseStateImpl? {
|
||||
return setState { StateClosed(exception) }
|
||||
}
|
||||
|
||||
override fun setStateConnecting(exception: Throwable?): NetworkHandlerSupport.BaseStateImpl? {
|
||||
return setState { StateConnecting(ExceptionCollector(exception)) }
|
||||
}
|
||||
|
||||
override fun setStateOK(conn: PlatformConn, exception: Throwable?): NetworkHandlerSupport.BaseStateImpl? {
|
||||
exception?.printStackTrace()
|
||||
return setState { StateOK(conn, CompletableDeferred(Unit)) }
|
||||
}
|
||||
|
||||
override fun setStateLoading(conn: PlatformConn): NetworkHandlerSupport.BaseStateImpl? {
|
||||
return setState { StateLoading(conn) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Without selector. When network is closed, it will not reconnect, so that you can check for its states.
|
||||
*
|
||||
* @see AbstractCommonNHTestWithSelector
|
||||
*/
|
||||
internal expect abstract class AbstractCommonNHTest() :
|
||||
AbstractRealNetworkHandlerTest<TestCommonNetworkHandler> {
|
||||
|
||||
val conn: PlatformConn
|
||||
|
||||
override val network: TestCommonNetworkHandler
|
||||
|
||||
override val factory: NetworkHandlerFactory<TestCommonNetworkHandler>
|
||||
|
||||
protected fun removeOutgoingPacketEncoder()
|
||||
}
|
||||
|
||||
internal expect class PlatformConn()
|
@ -1,17 +1,16 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
||||
* 此源代码的使用受 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/master/LICENSE
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
package net.mamoe.mirai.internal.network.framework
|
||||
|
||||
import io.netty.channel.Channel
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.network.components.BotOfflineEventMonitor
|
||||
import net.mamoe.mirai.internal.network.components.BotOfflineEventMonitorImpl
|
||||
@ -26,18 +25,20 @@ import net.mamoe.mirai.utils.cast
|
||||
* When network is closed, it will reconnect, so that you test for real environment,
|
||||
* but you cannot check for its states (it will never be CLOSED until some fatal error, just like in real).
|
||||
*/
|
||||
internal abstract class AbstractNettyNHTestWithSelector : AbstractRealNetworkHandlerTest<TestSelectorNetworkHandler>() {
|
||||
internal abstract class AbstractCommonNHTestWithSelector :
|
||||
AbstractRealNetworkHandlerTest<TestSelectorNetworkHandler>() {
|
||||
init {
|
||||
overrideComponents[BotOfflineEventMonitor] = BotOfflineEventMonitorImpl()
|
||||
}
|
||||
|
||||
val channel = AbstractNettyNHTest.NettyNHTestChannel(
|
||||
logger = lazy { bot.logger },
|
||||
)
|
||||
val conn = PlatformConn()
|
||||
|
||||
val selector = TestSelector<TestNettyNH> {
|
||||
object : TestNettyNH(bot, createContext(), createAddress()) {
|
||||
override suspend fun createConnection(decodePipeline: PacketDecodePipeline): Channel = channel
|
||||
val selector = TestSelector<TestCommonNetworkHandler> {
|
||||
object : TestCommonNetworkHandler(bot, createContext(), createAddress()) {
|
||||
// override suspend fun createConnection(decodePipeline: PacketDecodePipeline): PlatformConn = channel
|
||||
override suspend fun createConnection(): PlatformConn {
|
||||
return conn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,9 +49,9 @@ internal abstract class AbstractNettyNHTestWithSelector : AbstractRealNetworkHan
|
||||
}
|
||||
|
||||
internal class TestSelectorNetworkHandler(
|
||||
selector: NetworkHandlerSelector<TestNettyNH>, override val bot: QQAndroidBot,
|
||||
) : ITestNetworkHandler,
|
||||
SelectorNetworkHandler<TestNettyNH>(selector) {
|
||||
selector: NetworkHandlerSelector<TestCommonNetworkHandler>, override val bot: QQAndroidBot,
|
||||
) : ITestNetworkHandler<PlatformConn>,
|
||||
SelectorNetworkHandler<TestCommonNetworkHandler>(selector) {
|
||||
|
||||
fun currentInstance() = selector.getCurrentInstanceOrCreate()
|
||||
fun currentInstanceOrNull() = selector.getCurrentInstanceOrNull()
|
||||
@ -63,12 +64,12 @@ internal class TestSelectorNetworkHandler(
|
||||
return selector.getCurrentInstanceOrCreate().setStateConnecting(exception)
|
||||
}
|
||||
|
||||
override fun setStateOK(channel: Channel, exception: Throwable?): NetworkHandlerSupport.BaseStateImpl? {
|
||||
return selector.getCurrentInstanceOrCreate().setStateOK(channel, exception)
|
||||
override fun setStateOK(conn: PlatformConn, exception: Throwable?): NetworkHandlerSupport.BaseStateImpl? {
|
||||
return selector.getCurrentInstanceOrCreate().setStateOK(conn, exception)
|
||||
}
|
||||
|
||||
override fun setStateLoading(channel: Channel): NetworkHandlerSupport.BaseStateImpl? {
|
||||
return selector.getCurrentInstanceOrCreate().setStateLoading(channel)
|
||||
override fun setStateLoading(conn: PlatformConn): NetworkHandlerSupport.BaseStateImpl? {
|
||||
return selector.getCurrentInstanceOrCreate().setStateLoading(conn)
|
||||
}
|
||||
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
/*
|
||||
* 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.internal.network.framework
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import io.netty.channel.Channel
|
||||
import io.netty.channel.embedded.EmbeddedChannel
|
||||
import io.netty.util.ReferenceCountUtil
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.serialization.InternalSerializationApi
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.serializer
|
||||
import net.mamoe.mirai.internal.AbstractBot
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.network.components.BotOfflineEventMonitor
|
||||
import net.mamoe.mirai.internal.network.components.RawIncomingPacket
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandlerContext
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandlerFactory
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandlerSupport
|
||||
import net.mamoe.mirai.internal.network.handler.SocketAddress
|
||||
import net.mamoe.mirai.internal.network.impl.netty.NettyNetworkHandler
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.internal.utils.io.ProtoBuf
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
|
||||
import net.mamoe.mirai.utils.ExceptionCollector
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.cast
|
||||
import net.mamoe.mirai.utils.error
|
||||
import java.net.SocketAddress
|
||||
|
||||
/**
|
||||
* You may need to override [createConnection]
|
||||
*/
|
||||
internal abstract class TestNettyNH(
|
||||
override val bot: QQAndroidBot,
|
||||
context: NetworkHandlerContext,
|
||||
address: SocketAddress,
|
||||
) : NettyNetworkHandler(context, address), ITestNetworkHandler {
|
||||
|
||||
protected abstract suspend fun createConnection(decodePipeline: PacketDecodePipeline): Channel
|
||||
final override suspend fun createConnection(): Channel {
|
||||
return createConnection(createDummyDecodePipeline())
|
||||
}
|
||||
|
||||
override fun setStateClosed(exception: Throwable?): NetworkHandlerSupport.BaseStateImpl? {
|
||||
return setState { StateClosed(exception) }
|
||||
}
|
||||
|
||||
override fun setStateConnecting(exception: Throwable?): NetworkHandlerSupport.BaseStateImpl? {
|
||||
return setState { StateConnecting(ExceptionCollector(exception)) }
|
||||
}
|
||||
|
||||
override fun setStateOK(channel: Channel, exception: Throwable?): NetworkHandlerSupport.BaseStateImpl? {
|
||||
exception?.printStackTrace()
|
||||
return setState { StateOK(channel, CompletableDeferred(Unit)) }
|
||||
}
|
||||
|
||||
override fun setStateLoading(channel: Channel): NetworkHandlerSupport.BaseStateImpl? {
|
||||
return setState { StateLoading(channel) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Without selector. When network is closed, it will not reconnect, so that you can check for its states.
|
||||
*
|
||||
* @see AbstractNettyNHTestWithSelector
|
||||
*/
|
||||
internal abstract class AbstractNettyNHTest : AbstractRealNetworkHandlerTest<TestNettyNH>() {
|
||||
|
||||
init {
|
||||
overrideComponents[BotOfflineEventMonitor] = object : BotOfflineEventMonitor {
|
||||
override fun attachJob(bot: AbstractBot, scope: CoroutineScope) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NettyNHTestChannel(
|
||||
val logger: Lazy<MiraiLogger>,
|
||||
var fakeServer: (NettyNHTestChannel.(msg: Any?) -> Unit)? = null,
|
||||
) : EmbeddedChannel() {
|
||||
@OptIn(InternalSerializationApi::class)
|
||||
fun listen(listener: (OutgoingPacket) -> Any?) {
|
||||
fakeServer = { packet ->
|
||||
if (packet is OutgoingPacket) {
|
||||
val rsp0 = when (val rsp = listener(packet)) {
|
||||
null -> null
|
||||
is Unit -> null
|
||||
is ByteArray -> {
|
||||
RawIncomingPacket(
|
||||
commandName = packet.commandName,
|
||||
sequenceId = packet.sequenceId,
|
||||
body = rsp
|
||||
)
|
||||
}
|
||||
is RawIncomingPacket -> rsp
|
||||
is ProtoBuf -> {
|
||||
RawIncomingPacket(
|
||||
commandName = packet.commandName,
|
||||
sequenceId = packet.sequenceId,
|
||||
body = buildPacket {
|
||||
writeProtoBuf(
|
||||
rsp::class.serializer().cast<KSerializer<ProtoBuf>>(),
|
||||
rsp
|
||||
)
|
||||
}.readBytes()
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
logger.value.error { "Failed to respond $rsp" }
|
||||
null
|
||||
}
|
||||
}
|
||||
if (rsp0 != null) {
|
||||
pipeline().fireChannelRead(rsp0)
|
||||
}
|
||||
}
|
||||
ReferenceCountUtil.release(packet)
|
||||
}
|
||||
}
|
||||
|
||||
public /*internal*/ override fun doRegister() {
|
||||
super.doRegister() // Set channel state to ACTIVE
|
||||
// Drop old handlers
|
||||
pipeline().let { p ->
|
||||
while (p.first() != null) {
|
||||
p.removeFirst()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleInboundMessage(msg: Any?) {
|
||||
ReferenceCountUtil.release(msg) // Not handled, Drop
|
||||
}
|
||||
|
||||
override fun handleOutboundMessage(msg: Any?) {
|
||||
fakeServer?.invoke(this, msg) ?: ReferenceCountUtil.release(msg)
|
||||
}
|
||||
}
|
||||
|
||||
val channel = NettyNHTestChannel(
|
||||
logger = lazy { bot.logger },
|
||||
)
|
||||
|
||||
override val network: TestNettyNH get() = bot.network as TestNettyNH
|
||||
|
||||
override val factory: NetworkHandlerFactory<TestNettyNH> =
|
||||
NetworkHandlerFactory<TestNettyNH> { context, address ->
|
||||
object : TestNettyNH(bot, context, address) {
|
||||
override suspend fun createConnection(decodePipeline: PacketDecodePipeline): Channel =
|
||||
channel.apply {
|
||||
doRegister() // restart channel
|
||||
setupChannelPipeline(pipeline(), decodePipeline)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun removeOutgoingPacketEncoder() {
|
||||
kotlin.runCatching {
|
||||
channel.pipeline().remove("outgoing-packet-encoder")
|
||||
}
|
||||
}
|
||||
}
|
@ -11,11 +11,9 @@
|
||||
|
||||
package net.mamoe.mirai.internal.network.framework
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import net.mamoe.mirai.internal.BotAccount
|
||||
import net.mamoe.mirai.internal.MockAccount
|
||||
import net.mamoe.mirai.internal.MockConfiguration
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.*
|
||||
import net.mamoe.mirai.internal.network.component.ComponentKey
|
||||
import net.mamoe.mirai.internal.network.component.ConcurrentComponentStorage
|
||||
import net.mamoe.mirai.internal.network.component.setAll
|
||||
@ -37,9 +35,9 @@ import kotlin.test.assertEquals
|
||||
/**
|
||||
* With real factory and components as in [QQAndroidBot.components].
|
||||
*
|
||||
* Extend [AbstractNettyNHTestWithSelector] or [AbstractNettyNHTest].
|
||||
* Extend [AbstractCommonNHTestWithSelector] or [AbstractCommonNHTest].
|
||||
*/
|
||||
internal sealed class AbstractRealNetworkHandlerTest<H : NetworkHandler> : AbstractNetworkHandlerTest() {
|
||||
internal abstract class AbstractRealNetworkHandlerTest<H : NetworkHandler> : AbstractNetworkHandlerTest() {
|
||||
abstract val factory: NetworkHandlerFactory<H>
|
||||
abstract val network: H
|
||||
|
||||
@ -137,9 +135,15 @@ internal sealed class AbstractRealNetworkHandlerTest<H : NetworkHandler> : Abstr
|
||||
bot.logger.subLogger("TestEventDispatcherImpl")
|
||||
)
|
||||
)
|
||||
|
||||
set(BotOfflineEventMonitor, object : BotOfflineEventMonitor {
|
||||
override fun attachJob(bot: AbstractBot, scope: CoroutineScope) {
|
||||
}
|
||||
})
|
||||
// set(StateObserver, bot.run { stateObserverChain() })
|
||||
}
|
||||
|
||||
|
||||
fun <T : Any> setComponent(key: ComponentKey<in T>, instance: T): T {
|
||||
overrideComponents[key] = instance
|
||||
return instance
|
||||
|
@ -19,7 +19,7 @@ import net.mamoe.mirai.utils.EMPTY_BYTE_ARRAY
|
||||
import net.mamoe.mirai.utils.hexToBytes
|
||||
import kotlin.test.BeforeTest
|
||||
|
||||
internal abstract class AbstractRealTimeActionTestUnit : AbstractNettyNHTest(), GroupExtensions {
|
||||
internal abstract class AbstractRealTimeActionTestUnit : AbstractCommonNHTest(), GroupExtensions {
|
||||
@BeforeTest
|
||||
internal fun prepareEnv() {
|
||||
bot.client.wLoginSigInfoField = WLoginSigInfo(
|
||||
@ -67,7 +67,7 @@ internal abstract class AbstractRealTimeActionTestUnit : AbstractNettyNHTest(),
|
||||
deviceToken = "Winserver datacenter 2077".toByteArray(),
|
||||
)
|
||||
bot.client._bot = bot
|
||||
network.setStateOK(channel)
|
||||
network.setStateOK(conn)
|
||||
removeOutgoingPacketEncoder()
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,29 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
||||
* 此源代码的使用受 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/master/LICENSE
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.framework
|
||||
|
||||
import io.netty.channel.Channel
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.network.components.EventDispatcher
|
||||
import net.mamoe.mirai.internal.network.components.SsoProcessor
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandlerSupport
|
||||
|
||||
internal interface ITestNetworkHandler : NetworkHandler {
|
||||
internal interface ITestNetworkHandler<Conn> : NetworkHandler {
|
||||
val bot: QQAndroidBot
|
||||
|
||||
|
||||
fun setStateClosed(exception: Throwable? = null): NetworkHandlerSupport.BaseStateImpl?
|
||||
fun setStateConnecting(exception: Throwable? = null): NetworkHandlerSupport.BaseStateImpl?
|
||||
fun setStateOK(channel: Channel, exception: Throwable? = null): NetworkHandlerSupport.BaseStateImpl?
|
||||
fun setStateLoading(channel: Channel): NetworkHandlerSupport.BaseStateImpl?
|
||||
fun setStateOK(conn: Conn, exception: Throwable? = null): NetworkHandlerSupport.BaseStateImpl?
|
||||
fun setStateLoading(conn: Conn): NetworkHandlerSupport.BaseStateImpl?
|
||||
}
|
||||
|
||||
internal val ITestNetworkHandler.eventDispatcher get() = bot.components[EventDispatcher]
|
||||
internal val ITestNetworkHandler.ssoProcessor get() = bot.components[SsoProcessor]
|
||||
internal val ITestNetworkHandler<*>.eventDispatcher get() = bot.components[EventDispatcher]
|
||||
internal val ITestNetworkHandler<*>.ssoProcessor get() = bot.components[SsoProcessor]
|
||||
|
@ -1,15 +1,15 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
||||
* 此源代码的使用受 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/master/LICENSE
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.framework
|
||||
|
||||
import io.netty.channel.Channel
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
@ -19,9 +19,8 @@ import net.mamoe.mirai.internal.network.handler.NetworkHandlerContext
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandlerSupport
|
||||
import net.mamoe.mirai.internal.network.handler.logger
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.utils.ConcurrentLinkedQueue
|
||||
import net.mamoe.mirai.utils.TestOnly
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
/**
|
||||
* States are manually set.
|
||||
@ -29,13 +28,15 @@ import java.util.concurrent.atomic.AtomicInteger
|
||||
internal open class TestNetworkHandler(
|
||||
override val bot: QQAndroidBot,
|
||||
context: NetworkHandlerContext,
|
||||
) : NetworkHandlerSupport(context), ITestNetworkHandler {
|
||||
) : NetworkHandlerSupport(context), ITestNetworkHandler<TestNetworkHandler.Connection> {
|
||||
class Connection
|
||||
|
||||
@Suppress("EXPOSED_SUPER_CLASS")
|
||||
internal open inner class TestState(
|
||||
correspondingState: NetworkHandler.State
|
||||
) : BaseStateImpl(correspondingState) {
|
||||
val resumeDeferred = CompletableDeferred<Unit>()
|
||||
val resumeCount = AtomicInteger(0)
|
||||
val resumeCount = atomic(0)
|
||||
val onResume get() = resumeDeferred.onJoin
|
||||
private val mutex = Mutex()
|
||||
|
||||
@ -81,12 +82,12 @@ internal open class TestNetworkHandler(
|
||||
return setState(NetworkHandler.State.CONNECTING)
|
||||
}
|
||||
|
||||
override fun setStateOK(channel: Channel, exception: Throwable?): TestState? {
|
||||
override fun setStateOK(conn: Connection, exception: Throwable?): TestState? {
|
||||
exception?.printStackTrace()
|
||||
return setState(NetworkHandler.State.OK)
|
||||
}
|
||||
|
||||
override fun setStateLoading(channel: Channel): TestState? {
|
||||
override fun setStateLoading(conn: Connection): TestState? {
|
||||
return setState(NetworkHandler.State.LOADING)
|
||||
}
|
||||
}
|
@ -18,8 +18,9 @@ import net.mamoe.mirai.internal.network.components.AccountSecretsImpl
|
||||
import net.mamoe.mirai.internal.network.components.SsoSession
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
|
||||
import net.mamoe.mirai.utils.EMPTY_BYTE_ARRAY
|
||||
import net.mamoe.mirai.utils.File
|
||||
import net.mamoe.mirai.utils.MiraiFile
|
||||
import net.mamoe.mirai.utils.debug
|
||||
import net.mamoe.mirai.utils.writeBytes
|
||||
|
||||
|
||||
internal class TestSsoSession(
|
||||
@ -53,7 +54,7 @@ internal fun QQAndroidClient.dumpSessionSafe(): ByteArray {
|
||||
return secrets.toByteArray(AccountSecretsImpl.serializer())
|
||||
}
|
||||
|
||||
internal fun QQAndroidBot.scheduleSafeSessionDump(outputFile: File) {
|
||||
internal fun QQAndroidBot.scheduleSafeSessionDump(outputFile: MiraiFile) {
|
||||
this.eventChannel.subscribeAlways<BotOnlineEvent> {
|
||||
outputFile.writeBytes(client.dumpSessionSafe())
|
||||
bot.logger.debug { "Dumped safe session to " }
|
||||
|
@ -13,26 +13,28 @@ package net.mamoe.mirai.internal.network.handler
|
||||
|
||||
import net.mamoe.mirai.internal.network.components.FirstLoginResult
|
||||
import net.mamoe.mirai.internal.network.components.SsoProcessor
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.TestNettyNH
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.PlatformConn
|
||||
import net.mamoe.mirai.internal.network.framework.TestCommonNetworkHandler
|
||||
import net.mamoe.mirai.internal.network.handler.selector.MaxAttemptsReachedException
|
||||
import net.mamoe.mirai.internal.network.handler.selector.NetworkException
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.utils.TestOnly
|
||||
import kotlin.test.*
|
||||
|
||||
internal class KeepAliveNetworkHandlerSelectorRealTest : AbstractNettyNHTest() {
|
||||
internal class KeepAliveNetworkHandlerSelectorRealTest : AbstractCommonNHTest() {
|
||||
|
||||
internal class FakeFailOnCreatingConnection : AbstractNettyNHTest() {
|
||||
internal class FakeFailOnCreatingConnection : AbstractCommonNHTest() {
|
||||
private class MyException : Exception()
|
||||
|
||||
private lateinit var throwException: () -> Nothing
|
||||
|
||||
override val factory: NetworkHandlerFactory<TestNettyNH> =
|
||||
NetworkHandlerFactory<TestNettyNH> { context, address ->
|
||||
object : TestNettyNH(bot, context, address) {
|
||||
override suspend fun createConnection(decodePipeline: PacketDecodePipeline): Channel =
|
||||
override val factory: NetworkHandlerFactory<TestCommonNetworkHandler> =
|
||||
NetworkHandlerFactory<TestCommonNetworkHandler> { context, address ->
|
||||
object : TestCommonNetworkHandler(bot, context, address) {
|
||||
override suspend fun createConnection(): PlatformConn {
|
||||
throwException()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:OptIn(TestOnly::class)
|
||||
|
||||
package net.mamoe.mirai.internal.network.handler
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@ -14,26 +16,26 @@ import kotlinx.coroutines.Job
|
||||
import net.mamoe.mirai.internal.network.components.EventDispatcher
|
||||
import net.mamoe.mirai.internal.network.components.HeartbeatFailureHandler
|
||||
import net.mamoe.mirai.internal.network.components.HeartbeatScheduler
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTestWithSelector
|
||||
import net.mamoe.mirai.internal.network.impl.netty.HeartbeatFailedException
|
||||
import net.mamoe.mirai.internal.network.impl.netty.NettyChannelException
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTestWithSelector
|
||||
import net.mamoe.mirai.internal.network.handler.selector.NetworkException
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import kotlin.test.*
|
||||
import net.mamoe.mirai.utils.TestOnly
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertFails
|
||||
|
||||
/**
|
||||
* Test whether the selector can recover the connection after first successful login.
|
||||
*/
|
||||
internal class SelectorRecoveryTest : AbstractNettyNHTestWithSelector() {
|
||||
@BeforeTest
|
||||
fun beforeTest(info: TestInfo) {
|
||||
println("=".repeat(30) + "BEGIN: ${info.displayName}" + "=".repeat(30))
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
fun afterTest(info: TestInfo) {
|
||||
println("=".repeat(31) + "END: ${info.displayName}" + "=".repeat(31))
|
||||
}
|
||||
internal class SelectorRecoveryTest : AbstractCommonNHTestWithSelector() {
|
||||
// @BeforeTest
|
||||
// fun beforeTest(info: TestInfo) {
|
||||
// println("=".repeat(30) + "BEGIN: ${info.displayName}" + "=".repeat(30))
|
||||
// }
|
||||
//
|
||||
// @AfterTest
|
||||
// fun afterTest(info: TestInfo) {
|
||||
// println("=".repeat(31) + "END: ${info.displayName}" + "=".repeat(31))
|
||||
// }
|
||||
|
||||
@Test
|
||||
fun `stop on manual close`() = runBlockingUnit {
|
||||
@ -44,12 +46,11 @@ internal class SelectorRecoveryTest : AbstractNettyNHTestWithSelector() {
|
||||
|
||||
/**
|
||||
* Emulates system hibernation and network failure.
|
||||
* @see HeartbeatFailedException
|
||||
*/
|
||||
@Test
|
||||
fun `can recover on heartbeat failure with NettyChannelException`() = runBlockingUnit {
|
||||
// We allow NetworkException to cause a reconnect.
|
||||
testRecoverWhenHeartbeatFailWith { NettyChannelException("test IO ex") }
|
||||
testRecoverWhenHeartbeatFailWith { NetworkException("test IO ex", true) }
|
||||
|
||||
bot.components[EventDispatcher].joinBroadcast() // Wait our async connector to complete.
|
||||
|
||||
|
@ -7,21 +7,22 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.impl.netty
|
||||
package net.mamoe.mirai.internal.network.impl.common
|
||||
|
||||
import net.mamoe.mirai.internal.network.components.AccountSecretsImpl
|
||||
import net.mamoe.mirai.internal.network.components.AccountSecretsManager
|
||||
import net.mamoe.mirai.internal.network.components.FileCacheAccountSecretsManager
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTest
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.internal.utils.accountSecretsFile
|
||||
import net.mamoe.mirai.utils.DeviceInfo
|
||||
import net.mamoe.mirai.utils.getRandomByteArray
|
||||
import net.mamoe.mirai.utils.writeBytes
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class AccountSecretsTest : AbstractNettyNHTest() {
|
||||
internal class AccountSecretsTest : AbstractCommonNHTest() {
|
||||
@Test
|
||||
fun `can login with no secrets`() = runBlockingUnit {
|
||||
val file = bot.configuration.accountSecretsFile()
|
@ -7,7 +7,9 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.impl.netty
|
||||
@file:OptIn(TestOnly::class)
|
||||
|
||||
package net.mamoe.mirai.internal.network.impl.common
|
||||
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
@ -15,16 +17,17 @@ import kotlinx.coroutines.isActive
|
||||
import net.mamoe.mirai.internal.MockBot
|
||||
import net.mamoe.mirai.internal.network.components.EventDispatcher
|
||||
import net.mamoe.mirai.internal.network.components.SsoProcessor
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.components.TestSsoProcessor
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State.*
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacket
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.supervisorJob
|
||||
import net.mamoe.mirai.utils.TestOnly
|
||||
import kotlin.test.*
|
||||
|
||||
internal class NettyBotLifecycleTest : AbstractNettyNHTest() {
|
||||
internal class BotLifecycleTest : AbstractCommonNHTest() {
|
||||
|
||||
|
||||
// not allowed anymore
|
@ -7,25 +7,26 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.impl.netty
|
||||
package net.mamoe.mirai.internal.network.impl.common
|
||||
|
||||
import net.mamoe.mirai.internal.network.components.ServerList
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.TestNettyNH
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.TestCommonNetworkHandler
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
internal class NettyAddressChangedTest : AbstractNettyNHTest() {
|
||||
internal class CommonNHAddressChangedTest : AbstractCommonNHTest() {
|
||||
@Test
|
||||
fun `test login ip changes`() = runBlockingUnit {
|
||||
networkLogger.debug("before login, Assuming both ip is empty")
|
||||
val lastConnectedIpOld = bot.components[ServerList].lastConnectedIP
|
||||
val lastDisconnectedIpOld = bot.components[ServerList].lastDisconnectedIP
|
||||
assert(lastConnectedIpOld.isEmpty()) { "Assuming lastConnectedIp is empty" }
|
||||
assert(lastDisconnectedIpOld.isEmpty()) { "Assuming lastDisconnectedIp is empty" }
|
||||
assertTrue(lastConnectedIpOld.isEmpty(), "Assuming lastConnectedIp is empty")
|
||||
assertTrue(lastDisconnectedIpOld.isEmpty(), "Assuming lastDisconnectedIp is empty")
|
||||
|
||||
networkLogger.debug("Do login, Assuming lastConnectedIp is NOT empty")
|
||||
bot.login()
|
||||
@ -37,7 +38,7 @@ internal class NettyAddressChangedTest : AbstractNettyNHTest() {
|
||||
)
|
||||
|
||||
networkLogger.debug("Offline the bot, Assuming lastConnectedIp is equals lastDisconnectedIp")
|
||||
(bot.network as TestNettyNH).setStateClosed()
|
||||
(bot.network as TestCommonNetworkHandler).setStateClosed()
|
||||
assertState(NetworkHandler.State.CLOSED)
|
||||
assertEquals(
|
||||
bot.components[ServerList].lastConnectedIP,
|
@ -7,32 +7,32 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.impl.netty
|
||||
@file:OptIn(TestOnly::class)
|
||||
|
||||
package net.mamoe.mirai.internal.network.impl.common
|
||||
|
||||
import io.ktor.utils.io.errors.*
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import net.mamoe.mirai.internal.network.components.BotOfflineEventMonitor
|
||||
import net.mamoe.mirai.internal.network.components.BotOfflineEventMonitorImpl
|
||||
import net.mamoe.mirai.internal.network.components.FirstLoginResult
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.TestNettyNH
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.TestCommonNetworkHandler
|
||||
import net.mamoe.mirai.internal.network.framework.setSsoProcessor
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
||||
import net.mamoe.mirai.internal.network.handler.selector.KeepAliveNetworkHandlerSelector
|
||||
import net.mamoe.mirai.internal.network.handler.selector.NetworkChannelException
|
||||
import net.mamoe.mirai.internal.network.handler.selector.SelectorNetworkHandler
|
||||
import net.mamoe.mirai.internal.network.handler.selectorLogger
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.network.CustomLoginFailedException
|
||||
import net.mamoe.mirai.utils.TestOnly
|
||||
import net.mamoe.mirai.utils.cast
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import java.io.IOException
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.*
|
||||
|
||||
internal class NettyBotNormalLoginTest : AbstractNettyNHTest() {
|
||||
internal class CommonNHBotNormalLoginTest : AbstractCommonNHTest() {
|
||||
init {
|
||||
overrideComponents[BotOfflineEventMonitor] = BotOfflineEventMonitorImpl()
|
||||
}
|
||||
@ -41,7 +41,7 @@ internal class NettyBotNormalLoginTest : AbstractNettyNHTest() {
|
||||
super.factory.create(createContext(), createAddress())
|
||||
}
|
||||
|
||||
override val network: TestNettyNH
|
||||
override val network: TestCommonNetworkHandler
|
||||
get() = bot.network.cast<SelectorNetworkHandler<*>>().selector.getCurrentInstanceOrCreate().cast()
|
||||
|
||||
override fun createHandler(): NetworkHandler {
|
||||
@ -50,7 +50,7 @@ internal class NettyBotNormalLoginTest : AbstractNettyNHTest() {
|
||||
|
||||
class CusLoginException(message: String?) : CustomLoginFailedException(true, message)
|
||||
|
||||
@AfterEach
|
||||
@AfterTest
|
||||
fun `close bot`() = runBlockingUnit {
|
||||
bot.logger.info("[TEST UNIT] Releasing bot....")
|
||||
bot.closeAndJoin()
|
||||
@ -74,8 +74,8 @@ internal class NettyBotNormalLoginTest : AbstractNettyNHTest() {
|
||||
// #1963
|
||||
@Test
|
||||
fun `test first login failure with internally handled exceptions2`() = runBlockingUnit {
|
||||
setSsoProcessor { throw NettyChannelException("test Connection reset by peer") }
|
||||
assertFailsWith<NettyChannelException>("test Connection reset by peer") { bot.login() }
|
||||
setSsoProcessor { throw NetworkChannelException("test Connection reset by peer") }
|
||||
assertFailsWith<NetworkChannelException>("test Connection reset by peer") { bot.login() }
|
||||
assertState(NetworkHandler.State.CLOSED)
|
||||
}
|
||||
|
@ -7,8 +7,11 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.impl.netty
|
||||
@file:OptIn(TestOnly::class)
|
||||
|
||||
package net.mamoe.mirai.internal.network.impl.common
|
||||
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.isActive
|
||||
import net.mamoe.mirai.event.Event
|
||||
@ -17,7 +20,7 @@ import net.mamoe.mirai.event.events.BotOnlineEvent
|
||||
import net.mamoe.mirai.event.events.BotReloginEvent
|
||||
import net.mamoe.mirai.internal.network.components.FirstLoginResult
|
||||
import net.mamoe.mirai.internal.network.components.SsoProcessor
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.eventDispatcher
|
||||
import net.mamoe.mirai.internal.network.framework.setSsoProcessor
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State.*
|
||||
@ -25,15 +28,13 @@ import net.mamoe.mirai.internal.test.assertEventBroadcasts
|
||||
import net.mamoe.mirai.internal.test.assertEventNotBroadcast
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.supervisorJob
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import net.mamoe.mirai.utils.TestOnly
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.TestInstance
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
|
||||
internal class NettyHandlerEventTest : AbstractNettyNHTest() {
|
||||
internal class CommonNHEventTest : AbstractCommonNHTest() {
|
||||
@Test
|
||||
fun `BotOnlineEvent after successful logon`() = runBlockingUnit {
|
||||
assertEventBroadcasts<BotOnlineEvent> {
|
||||
@ -94,24 +95,24 @@ internal class NettyHandlerEventTest : AbstractNettyNHTest() {
|
||||
|
||||
@Test
|
||||
fun `from CONNECTING TO OK the second time`() = runBlockingUnit {
|
||||
val ok = AtomicReference(CompletableDeferred<Unit>())
|
||||
val ok = atomic(CompletableDeferred<Unit>())
|
||||
setSsoProcessor {
|
||||
ok.get().join()
|
||||
ok.value.join()
|
||||
}
|
||||
|
||||
assertState(INITIALIZED)
|
||||
|
||||
network.setStateConnecting()
|
||||
ok.get().complete(Unit)
|
||||
ok.value.complete(Unit)
|
||||
network.resumeConnection()
|
||||
assertState(OK)
|
||||
|
||||
ok.set(CompletableDeferred())
|
||||
ok.value = CompletableDeferred()
|
||||
network.setStateConnecting()
|
||||
eventDispatcher.joinBroadcast()
|
||||
println("Starting receiving events")
|
||||
assertEventBroadcasts<Event>(2) {
|
||||
ok.get().complete(Unit)
|
||||
ok.value.complete(Unit)
|
||||
network.resumeConnection()
|
||||
eventDispatcher.joinBroadcast()
|
||||
}.let { event ->
|
@ -10,13 +10,13 @@
|
||||
package net.mamoe.mirai.internal.network.impl.netty
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTest
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
internal class NettyResumeConnectionTest : AbstractNettyNHTest() {
|
||||
internal class ResumeConnectionTest : AbstractCommonNHTest() {
|
||||
|
||||
private val packet = OutgoingPacket("", "", 1, ByteReadPacket.Empty)
|
||||
|
||||
@ -43,7 +43,7 @@ internal class NettyResumeConnectionTest : AbstractNettyNHTest() {
|
||||
|
||||
@Test
|
||||
fun `resumeConnection switches a state that can send packet on LOADING`() = runBlockingUnit {
|
||||
network.setStateLoading(channel)
|
||||
network.setStateLoading(conn)
|
||||
network.resumeConnection()
|
||||
network.sendWithoutExpect(packet)
|
||||
}
|
@ -7,44 +7,25 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.impl.netty
|
||||
package net.mamoe.mirai.internal.network.impl.common
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import io.netty.channel.Channel
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.yield
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.TestNettyNH
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandlerContext
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandlerFactory
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTest
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacket
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import java.net.SocketAddress
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
internal class NettySendPacketTest : AbstractNettyNHTest() {
|
||||
override val factory: NetworkHandlerFactory<TestNettyNH> = object : NetworkHandlerFactory<TestNettyNH> {
|
||||
override fun create(context: NetworkHandlerContext, address: SocketAddress): TestNettyNH {
|
||||
return object : TestNettyNH(bot, context, address) {
|
||||
override suspend fun createConnection(decodePipeline: PacketDecodePipeline): Channel =
|
||||
channel.apply {
|
||||
doRegister() // restart channel
|
||||
setupChannelPipeline(pipeline(), decodePipeline)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class SendPacketTest : AbstractCommonNHTest() {
|
||||
// single thread so we can use [yield] to transfer dispatch
|
||||
private val singleThreadDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
|
||||
private val singleThreadDispatcher = borrowSingleThreadDispatcher()
|
||||
|
||||
@Test
|
||||
fun `sendPacketImpl suspends until a valid state`() = runBlockingUnit(singleThreadDispatcher) {
|
||||
@ -55,7 +36,7 @@ internal class NettySendPacketTest : AbstractNettyNHTest() {
|
||||
assertNotNull(network.sendAndExpect(OutgoingPacket("name", "cmd", 1, ByteReadPacket.Empty)))
|
||||
assertTrue { expectStop.value }
|
||||
}
|
||||
network.setStateOK(channel) // then we can send packet.
|
||||
network.setStateOK(conn) // then we can send packet.
|
||||
yield() // yields the thread to run `sendAndExpect`
|
||||
|
||||
// when we got thread here again, `sendAndExpect` is suspending for response [Packet].
|
||||
@ -66,7 +47,7 @@ internal class NettySendPacketTest : AbstractNettyNHTest() {
|
||||
|
||||
@Test
|
||||
fun `sendPacketImpl does not suspend if state is valid`() = runBlockingUnit(singleThreadDispatcher) {
|
||||
network.setStateOK(channel) // then we can send packet.
|
||||
network.setStateOK(conn) // then we can send packet.
|
||||
val expectStop = atomic(false)
|
||||
|
||||
val job = launch(singleThreadDispatcher, start = CoroutineStart.UNDISPATCHED) {
|
@ -7,20 +7,23 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.impl.netty
|
||||
@file:OptIn(TestOnly::class)
|
||||
|
||||
package net.mamoe.mirai.internal.network.impl.common
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.event.Event
|
||||
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||
import net.mamoe.mirai.internal.AbstractBot
|
||||
import net.mamoe.mirai.internal.network.components.BotOfflineEventMonitor
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTest
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State.*
|
||||
import net.mamoe.mirai.internal.test.assertEventBroadcasts
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.utils.TestOnly
|
||||
import kotlin.test.*
|
||||
|
||||
internal class SetStateTest : AbstractNettyNHTest() {
|
||||
internal class SetStateTest : AbstractCommonNHTest() {
|
||||
@Test
|
||||
fun `setState should ignore duplications INITIALIZED to CLOSED to CLOSED`() {
|
||||
assertState(INITIALIZED)
|
||||
@ -32,7 +35,7 @@ internal class SetStateTest : AbstractNettyNHTest() {
|
||||
|
||||
@Test
|
||||
fun `setState should ignore duplications OK to CLOSED to CLOSED`() {
|
||||
assertNotNull(network.setStateOK(channel))
|
||||
assertNotNull(network.setStateOK(conn))
|
||||
assertState(OK)
|
||||
assertNotNull(network.setStateClosed(IllegalStateException("1")))
|
||||
assertState(CLOSED)
|
||||
@ -46,7 +49,7 @@ internal class SetStateTest : AbstractNettyNHTest() {
|
||||
override fun attachJob(bot: AbstractBot, scope: CoroutineScope) {
|
||||
}
|
||||
}
|
||||
assertNotNull(network.setStateOK(channel))
|
||||
assertNotNull(network.setStateOK(conn))
|
||||
assertState(OK)
|
||||
assertEventBroadcasts<Event> {
|
||||
assertNotNull(network.setStateClosed(IllegalStateException("1")))
|
||||
@ -62,7 +65,7 @@ internal class SetStateTest : AbstractNettyNHTest() {
|
||||
|
||||
@Test
|
||||
fun `Precondition - setState should ignore duplications 2 OK to CLOSED to CLOSED`() = runBlockingUnit {
|
||||
assertNotNull(network.setStateOK(channel))
|
||||
assertNotNull(network.setStateOK(conn))
|
||||
assertState(OK)
|
||||
assertEventBroadcasts<Event> {
|
||||
assertNotNull(network.setStateClosed(IllegalStateException("1")))
|
@ -27,7 +27,7 @@ import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.components.*
|
||||
import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.noticeProcessorPipeline
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractNettyNHTest
|
||||
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTest
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacket
|
||||
import net.mamoe.mirai.internal.utils.io.JceStruct
|
||||
import net.mamoe.mirai.internal.utils.io.ProtocolStruct
|
||||
@ -38,7 +38,7 @@ import net.mamoe.mirai.utils.*
|
||||
/**
|
||||
* To add breakpoint, see [NoticeProcessorPipelineImpl.process]
|
||||
*/
|
||||
internal abstract class AbstractNoticeProcessorTest : AbstractNettyNHTest(), GroupExtensions {
|
||||
internal abstract class AbstractNoticeProcessorTest : AbstractCommonNHTest(), GroupExtensions {
|
||||
init {
|
||||
setSystemProp("mirai.network.notice.pipeline.log.full", "true")
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.event.events.BotGroupPermissionChangeEvent
|
||||
import net.mamoe.mirai.event.events.MemberPermissionChangeEvent
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertIs
|
||||
@ -22,7 +23,7 @@ import kotlin.test.assertIs
|
||||
internal class GroupTransferTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
@Test
|
||||
suspend fun `owner transfers group to other member`() {
|
||||
fun `owner transfers group to other member`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans.PbMsgInfo(
|
||||
fromUin = 2230203,
|
||||
@ -63,7 +64,7 @@ internal class GroupTransferTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `owner transfers group to bot`() {
|
||||
fun `owner transfers group to bot`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans.PbMsgInfo(
|
||||
fromUin = 2230203,
|
||||
|
@ -15,6 +15,8 @@ import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.event.events.BotGroupPermissionChangeEvent
|
||||
import net.mamoe.mirai.event.events.MemberPermissionChangeEvent
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertIs
|
||||
@ -26,9 +28,9 @@ import kotlin.test.assertIs
|
||||
internal class MemberAdminChangeTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
@Test
|
||||
suspend fun `bot member to admin`() {
|
||||
fun `bot member to admin`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans.PbMsgInfo(
|
||||
OnlinePushTrans.PbMsgInfo(
|
||||
fromUin = 2230203,
|
||||
toUin = 1230003,
|
||||
msgType = 44,
|
||||
@ -74,7 +76,7 @@ internal class MemberAdminChangeTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `bot admin to member`() {
|
||||
fun `bot admin to member`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans.PbMsgInfo(
|
||||
fromUin = 2230203,
|
||||
@ -119,7 +121,7 @@ internal class MemberAdminChangeTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `member member to admin`() {
|
||||
fun `member member to admin`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans.PbMsgInfo(
|
||||
fromUin = 2230203,
|
||||
@ -168,7 +170,7 @@ internal class MemberAdminChangeTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `member admin to member`() {
|
||||
fun `member admin to member`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans.PbMsgInfo(
|
||||
fromUin = 2230203,
|
||||
|
@ -15,20 +15,22 @@ import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.event.events.MemberJoinEvent
|
||||
import net.mamoe.mirai.event.events.MemberJoinRequestEvent
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import kotlin.test.*
|
||||
|
||||
internal class MemberJoinTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
@Test
|
||||
suspend fun `member actively request join`() {
|
||||
fun `member actively request join`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg.StructMsg(
|
||||
Structmsg.StructMsg(
|
||||
version = 1,
|
||||
msgType = 2,
|
||||
msgSeq = 16300,
|
||||
msgTime = 1630,
|
||||
reqUin = 1230001,
|
||||
msg = net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg.SystemMsg(
|
||||
msg = Structmsg.SystemMsg(
|
||||
subType = 1,
|
||||
msgTitle = "加群申请",
|
||||
msgDescribe = "申请加入 %group_name%",
|
||||
@ -36,26 +38,26 @@ internal class MemberJoinTest : AbstractNoticeProcessorTest() {
|
||||
srcId = 1,
|
||||
subSrcId = 5,
|
||||
actions = mutableListOf(
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg.SystemMsgAction(
|
||||
Structmsg.SystemMsgAction(
|
||||
name = "拒绝",
|
||||
result = "已拒绝",
|
||||
actionInfo = net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg.SystemMsgActionInfo(
|
||||
actionInfo = Structmsg.SystemMsgActionInfo(
|
||||
type = 12,
|
||||
groupCode = 2230203,
|
||||
),
|
||||
detailName = "拒绝",
|
||||
), net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg.SystemMsgAction(
|
||||
), Structmsg.SystemMsgAction(
|
||||
name = "同意",
|
||||
result = "已同意",
|
||||
actionInfo = net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg.SystemMsgActionInfo(
|
||||
actionInfo = Structmsg.SystemMsgActionInfo(
|
||||
type = 11,
|
||||
groupCode = 2230203,
|
||||
),
|
||||
detailName = "同意",
|
||||
), net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg.SystemMsgAction(
|
||||
), Structmsg.SystemMsgAction(
|
||||
name = "忽略",
|
||||
result = "已忽略",
|
||||
actionInfo = net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg.SystemMsgActionInfo(
|
||||
actionInfo = Structmsg.SystemMsgActionInfo(
|
||||
type = 14,
|
||||
groupCode = 2230203,
|
||||
),
|
||||
@ -64,7 +66,7 @@ internal class MemberJoinTest : AbstractNoticeProcessorTest() {
|
||||
),
|
||||
groupCode = 2230203,
|
||||
groupMsgType = 1,
|
||||
groupInfo = net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg.GroupInfo(
|
||||
groupInfo = Structmsg.GroupInfo(
|
||||
appPrivilegeFlag = 67698880,
|
||||
),
|
||||
groupFlagext3 = 128,
|
||||
@ -96,7 +98,7 @@ internal class MemberJoinTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `member request accepted by other admin`() {
|
||||
fun `member request accepted by other admin`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.Msg(
|
||||
msgHead = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.MsgHead(
|
||||
@ -143,7 +145,7 @@ internal class MemberJoinTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `member request accepted by bot as admin`() {
|
||||
fun `member request accepted by bot as admin`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.Msg(
|
||||
msgHead = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.MsgHead(
|
||||
@ -191,7 +193,7 @@ internal class MemberJoinTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
|
||||
@Test
|
||||
suspend fun `member joins directly when group allows anyone`() {
|
||||
fun `member joins directly when group allows anyone`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.Msg(
|
||||
msgHead = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.MsgHead(
|
||||
|
@ -14,6 +14,8 @@ package net.mamoe.mirai.internal.notice.processors
|
||||
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.event.events.MemberLeaveEvent
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertIs
|
||||
@ -21,9 +23,9 @@ import kotlin.test.assertIs
|
||||
internal class MemberQuitTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
@Test
|
||||
suspend fun `member active quit`() {
|
||||
fun `member active quit`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans.PbMsgInfo(
|
||||
OnlinePushTrans.PbMsgInfo(
|
||||
fromUin = 2230203,
|
||||
toUin = 1230003,
|
||||
msgType = 34,
|
||||
@ -33,7 +35,7 @@ internal class MemberQuitTest : AbstractNoticeProcessorTest() {
|
||||
realMsgTime = 1629,
|
||||
msgData = "00 22 07 BB 01 00 12 C4 B1 02 00 30 39 41 36 36 41 32 31 32 33 35 37 32 43 39 35 38 42 42 36 38 45 32 36 44 34 34 32 38 45 32 32 37 32 36 44 39 44 45 41 31 34 41 44 37 30 31 46 31".hexToBytes(),
|
||||
svrIp = 618,
|
||||
extGroupKeyInfo = net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans.ExtGroupKeyInfo(
|
||||
extGroupKeyInfo = OnlinePushTrans.ExtGroupKeyInfo(
|
||||
curMaxSeq = 1626,
|
||||
curTime = 16298,
|
||||
),
|
||||
@ -58,7 +60,7 @@ internal class MemberQuitTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `member kick`() {
|
||||
fun `member kick`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans.PbMsgInfo(
|
||||
fromUin = 2230203,
|
||||
|
@ -9,11 +9,16 @@
|
||||
|
||||
package net.mamoe.mirai.internal.notice.processors
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.event.events.FriendMessageSyncEvent
|
||||
import net.mamoe.mirai.event.events.GroupMessageSyncEvent
|
||||
import net.mamoe.mirai.internal.network.components.NoticePipelineContext.Companion.KEY_FROM_SYNC
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.message.data.content
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -23,18 +28,18 @@ import kotlin.test.assertIs
|
||||
internal class MessageSyncTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
@Test
|
||||
suspend fun `can receive group sync from macOS client`() {
|
||||
fun `can receive group sync from macOS client`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush.PbPushMsg(
|
||||
msg = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.Msg(
|
||||
msgHead = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.MsgHead(
|
||||
MsgOnlinePush.PbPushMsg(
|
||||
msg = MsgComm.Msg(
|
||||
msgHead = MsgComm.MsgHead(
|
||||
fromUin = 1230002,
|
||||
toUin = 1230002,
|
||||
msgType = 82,
|
||||
msgSeq = 1772,
|
||||
msgTime = 1640029614,
|
||||
msgUid = 144115188088832082,
|
||||
groupInfo = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.GroupInfo(
|
||||
groupInfo = MsgComm.GroupInfo(
|
||||
groupCode = 2230203,
|
||||
groupType = 1,
|
||||
groupInfoSeq = 657,
|
||||
@ -47,9 +52,9 @@ internal class MessageSyncTest : AbstractNoticeProcessorTest() {
|
||||
fromInstid = 537067835,
|
||||
userActive = 1,
|
||||
),
|
||||
msgBody = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.MsgBody(
|
||||
richText = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.RichText(
|
||||
attr = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Attr(
|
||||
msgBody = ImMsgBody.MsgBody(
|
||||
richText = ImMsgBody.RichText(
|
||||
attr = ImMsgBody.Attr(
|
||||
codePage = 0,
|
||||
time = 1640029614,
|
||||
random = 25984994,
|
||||
@ -60,23 +65,23 @@ internal class MessageSyncTest : AbstractNoticeProcessorTest() {
|
||||
fontName = "Helvetica",
|
||||
),
|
||||
elems = mutableListOf(
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
|
||||
text = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Text(
|
||||
ImMsgBody.Elem(
|
||||
text = ImMsgBody.Text(
|
||||
str = "s",
|
||||
),
|
||||
),
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
|
||||
elemFlags2 = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.ElemFlags2(
|
||||
ImMsgBody.Elem(
|
||||
elemFlags2 = ImMsgBody.ElemFlags2(
|
||||
msgRptCnt = 1,
|
||||
),
|
||||
),
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
|
||||
generalFlags = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.GeneralFlags(
|
||||
ImMsgBody.Elem(
|
||||
generalFlags = ImMsgBody.GeneralFlags(
|
||||
pbReserve = "".hexToBytes(),
|
||||
),
|
||||
),
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
|
||||
extraInfo = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.ExtraInfo(
|
||||
ImMsgBody.Elem(
|
||||
extraInfo = ImMsgBody.ExtraInfo(
|
||||
nick = "user2",
|
||||
level = 1,
|
||||
groupMask = 1,
|
||||
@ -112,7 +117,7 @@ internal class MessageSyncTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
|
||||
@Test
|
||||
suspend fun `can receive friend sync from macOS client`() {
|
||||
fun `can receive friend sync from macOS client`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
attributes[KEY_FROM_SYNC] = true
|
||||
|
||||
|
@ -11,12 +11,14 @@
|
||||
|
||||
package net.mamoe.mirai.internal.notice.processors
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.event.events.FriendMessageEvent
|
||||
import net.mamoe.mirai.event.events.GroupMessageEvent
|
||||
import net.mamoe.mirai.event.events.GroupTempMessageEvent
|
||||
import net.mamoe.mirai.internal.network.components.NoticePipelineContext.Companion.KEY_FROM_SYNC
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.message.data.MessageSource
|
||||
import net.mamoe.mirai.message.data.OnlineMessageSource
|
||||
import net.mamoe.mirai.message.data.PlainText
|
||||
@ -29,7 +31,7 @@ import kotlin.test.assertIs
|
||||
internal class MessageTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
@Test
|
||||
suspend fun `group message test`() {
|
||||
fun `group message test`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush.PbPushMsg(
|
||||
msg = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.Msg(
|
||||
@ -132,7 +134,7 @@ internal class MessageTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
|
||||
@Test
|
||||
suspend fun `friend message test`() {
|
||||
fun `friend message test`() = runBlockingUnit {
|
||||
suspend fun runTest() = use(KEY_FROM_SYNC to false) {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.Msg(
|
||||
msgHead = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.MsgHead(
|
||||
@ -212,7 +214,7 @@ internal class MessageTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `group temp message test`() {
|
||||
fun `group temp message test`() = runBlockingUnit {
|
||||
suspend fun runTest() = use(KEY_FROM_SYNC to false) {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.Msg(
|
||||
msgHead = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.MsgHead(
|
||||
@ -306,7 +308,7 @@ internal class MessageTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
// for #1410
|
||||
@Test
|
||||
suspend fun `group temp message test for issue 1410`() {
|
||||
fun `group temp message test for issue 1410`() = runBlockingUnit {
|
||||
suspend fun runTest() = use(KEY_FROM_SYNC to false) {
|
||||
net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.Msg(
|
||||
msgHead = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.MsgHead(
|
||||
|
@ -20,6 +20,7 @@ import net.mamoe.mirai.event.events.MemberUnmuteEvent
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.MsgInfo
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.OnlinePushPack
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.ShareData
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -28,7 +29,7 @@ import kotlin.test.assertIs
|
||||
|
||||
internal class MuteTest : AbstractNoticeProcessorTest() {
|
||||
@Test
|
||||
suspend fun `bot mute`() {
|
||||
fun `bot mute`() = runBlockingUnit {
|
||||
suspend fun MuteTest.runTest() = use {
|
||||
OnlinePushPack.SvcReqPushMsg(
|
||||
uin = 1230001,
|
||||
@ -79,7 +80,7 @@ internal class MuteTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `bot unmute`() {
|
||||
fun `bot unmute`() = runBlockingUnit {
|
||||
suspend fun MuteTest.runTest() = use {
|
||||
OnlinePushPack.SvcReqPushMsg(
|
||||
uin = 1230001,
|
||||
@ -146,7 +147,7 @@ internal class MuteTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `member mute`() {
|
||||
fun `member mute`() = runBlockingUnit {
|
||||
suspend fun MuteTest.runTest() = use {
|
||||
OnlinePushPack.SvcReqPushMsg(
|
||||
uin = 1230001,
|
||||
@ -198,7 +199,7 @@ internal class MuteTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
|
||||
@Test
|
||||
suspend fun `member unmute`() {
|
||||
fun `member unmute`() = runBlockingUnit {
|
||||
suspend fun MuteTest.runTest() = use {
|
||||
OnlinePushPack.SvcReqPushMsg(
|
||||
uin = 1230001,
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
package net.mamoe.mirai.internal.notice.processors
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.Mirai
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
@ -16,10 +17,11 @@ import net.mamoe.mirai.contact.PermissionDeniedException
|
||||
import net.mamoe.mirai.internal.message.source.OnlineMessageSourceFromGroupImpl
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.message.data.OnlineMessageSource
|
||||
import net.mamoe.mirai.utils.hexToBytes
|
||||
import org.junit.jupiter.api.assertFailsWith
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
internal class RecallTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
@ -91,7 +93,7 @@ internal class RecallTest : AbstractNoticeProcessorTest() {
|
||||
)
|
||||
|
||||
@Test
|
||||
suspend fun `recall member message without permission`() {
|
||||
fun `recall member message without permission`() = runBlockingUnit {
|
||||
val bot = setBot(2)
|
||||
val group = bot.addGroup(5, 3, MemberPermission.MEMBER).apply {
|
||||
// owner
|
||||
@ -105,7 +107,7 @@ internal class RecallTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `recall member message`() {
|
||||
fun `recall member message`() = runBlockingUnit {
|
||||
val bot = setBot(2)
|
||||
val group = bot.addGroup(5, 3, MemberPermission.ADMINISTRATOR).apply {
|
||||
// owner
|
||||
@ -117,7 +119,7 @@ internal class RecallTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `recall administrator message`() {
|
||||
fun `recall administrator message`() = runBlockingUnit {
|
||||
val bot = setBot(2)
|
||||
val group = bot.addGroup(5, 3, MemberPermission.ADMINISTRATOR).apply {
|
||||
// owner
|
||||
@ -129,9 +131,9 @@ internal class RecallTest : AbstractNoticeProcessorTest() {
|
||||
Mirai.recallMessage(bot, source(bot, 1, group.id, group.botPermission))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
suspend fun `recall administrator message as owner`() {
|
||||
fun `recall administrator message as owner`() = runBlockingUnit {
|
||||
val bot = setBot(2)
|
||||
val group = bot.addGroup(5, 2, MemberPermission.OWNER).apply {
|
||||
// sender
|
||||
@ -141,7 +143,7 @@ internal class RecallTest : AbstractNoticeProcessorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
suspend fun `recall owner message`() {
|
||||
fun `recall owner message`() = runBlockingUnit {
|
||||
val bot = setBot(2)
|
||||
val group = bot.addGroup(5, 1, MemberPermission.ADMINISTRATOR).apply {
|
||||
// sender
|
||||
|
@ -12,8 +12,8 @@ package net.mamoe.mirai.internal.test
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import net.mamoe.mirai.event.Event
|
||||
import net.mamoe.mirai.event.GlobalEventChannel
|
||||
import net.mamoe.mirai.utils.ConcurrentLinkedQueue
|
||||
import net.mamoe.mirai.utils.cast
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.test.assertEquals
|
||||
|
@ -9,48 +9,36 @@
|
||||
|
||||
package net.mamoe.mirai.internal.test
|
||||
|
||||
import net.mamoe.mirai.IMirai
|
||||
import net.mamoe.mirai.internal.network.framework.SynchronizedStdoutLogger
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Timeout
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlinx.coroutines.*
|
||||
import kotlin.test.AfterTest
|
||||
import kotlin.test.Test
|
||||
|
||||
internal expect fun initPlatform()
|
||||
|
||||
|
||||
@Suppress("UnnecessaryOptInAnnotation") // on JVM
|
||||
@OptIn(ExperimentalCoroutinesApi::class, DelicateCoroutinesApi::class)
|
||||
internal abstract class CommonAbstractTest {
|
||||
private val dispatchers = mutableListOf<CloseableCoroutineDispatcher>()
|
||||
|
||||
fun borrowSingleThreadDispatcher(): CoroutineDispatcher {
|
||||
return newSingleThreadContext(this::class.simpleName ?: "CommonAbstractTest")
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
fun closeAllDispatchers() {
|
||||
for (dispatcher in dispatchers) {
|
||||
dispatcher.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All test classes should inherit from [AbstractTest]
|
||||
*/
|
||||
@Timeout(value = 7, unit = TimeUnit.MINUTES)
|
||||
abstract class AbstractTest {
|
||||
init {
|
||||
initPlatform()
|
||||
internal expect abstract class AbstractTest() : CommonAbstractTest {
|
||||
|
||||
restoreLoggerFactory()
|
||||
|
||||
System.setProperty("mirai.network.packet.logger", "true")
|
||||
System.setProperty("mirai.network.state.observer.logging", "true")
|
||||
System.setProperty("mirai.network.show.all.components", "true")
|
||||
System.setProperty("mirai.network.show.components.creation.stacktrace", "true")
|
||||
System.setProperty("mirai.network.handle.selector.logging", "true")
|
||||
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
protected fun restoreLoggerFactory() {
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
MiraiLogger.setDefaultLoggerCreator {
|
||||
SynchronizedStdoutLogger(it)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
init {
|
||||
Exception() // create a exception to load relevant classes to estimate invocation time of test cases more accurately.
|
||||
IMirai::class.simpleName // similarly, load classes.
|
||||
}
|
||||
}
|
||||
companion object
|
||||
}
|
||||
|
||||
internal expect class PlatformInitializationTest() : AbstractTest {
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
package net.mamoe.mirai.internal.utils.io.serialization.tars.internal
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.internal.test.AbstractTest
|
||||
import net.mamoe.mirai.internal.utils.io.JceStruct
|
||||
@ -18,13 +19,11 @@ import net.mamoe.mirai.internal.utils.io.serialization.tars.TarsId
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
|
||||
import net.mamoe.mirai.utils.toReadPacket
|
||||
import net.mamoe.mirai.utils.toUHexString
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.PrintStream
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFails
|
||||
|
||||
class DebugLoggerTest : AbstractTest() {
|
||||
internal class DebugLoggerTest : AbstractTest() {
|
||||
|
||||
fun String.uniteLine(): String = replace("\r\n", "\n").replace("\r", "\n")
|
||||
|
||||
@ -36,8 +35,8 @@ class DebugLoggerTest : AbstractTest() {
|
||||
|
||||
@Test
|
||||
fun `can log`() {
|
||||
val out = ByteArrayOutputStream()
|
||||
val logger = DebugLogger(PrintStream(out))
|
||||
val out = BytePacketBuilder()
|
||||
val logger = DebugLogger(out)
|
||||
val original = Struct("string", 1)
|
||||
val bytes = original.toByteArray(Struct.serializer())
|
||||
val value = bytes.toReadPacket().use { Tars.UTF_8.load(Struct.serializer(), it, logger) }
|
||||
@ -51,7 +50,7 @@ class DebugLoggerTest : AbstractTest() {
|
||||
name=int
|
||||
decodeElementIndex: currentHead == null
|
||||
endStructure: net.mamoe.mirai.internal.utils.io.serialization.tars.internal.DebugLoggerTest.Struct, null, null
|
||||
""".trimIndent(), out.toByteArray().decodeToString().trim().uniteLine()
|
||||
""".trimIndent(), out.build().readBytes().decodeToString().trim().uniteLine()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -9,9 +9,9 @@
|
||||
|
||||
package net.mamoe.mirai.internal.network.impl.netty
|
||||
|
||||
import net.mamoe.mirai.internal.network.handler.selector.NetworkException
|
||||
import net.mamoe.mirai.internal.network.handler.selector.NetworkChannelException
|
||||
|
||||
internal data class NettyChannelException(
|
||||
override val message: String? = null,
|
||||
override val cause: Throwable? = null,
|
||||
) : NetworkException(true)
|
||||
) : NetworkChannelException()
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.internal.network.framework
|
||||
|
||||
import kotlinx.coroutines.ExecutorCoroutineDispatcher
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandlerFactory
|
||||
import kotlin.test.AfterTest
|
||||
|
||||
/**
|
||||
* Without selector. When network is closed, it will not reconnect, so that you can check for its states.
|
||||
*
|
||||
* @see AbstractCommonNHTestWithSelector
|
||||
*/
|
||||
internal actual abstract class AbstractCommonNHTest actual constructor() :
|
||||
AbstractRealNetworkHandlerTest<TestCommonNetworkHandler>() {
|
||||
actual override val network: TestCommonNetworkHandler by lazy {
|
||||
factory.create(createContext(), createAddress())
|
||||
}
|
||||
|
||||
private val startedDispatchers = mutableListOf<ExecutorCoroutineDispatcher>()
|
||||
|
||||
@AfterTest
|
||||
fun cleanupDispatchers() {
|
||||
startedDispatchers.forEach { it.close() }
|
||||
}
|
||||
|
||||
actual override val factory: NetworkHandlerFactory<TestCommonNetworkHandler> =
|
||||
NetworkHandlerFactory<TestCommonNetworkHandler> { context, address ->
|
||||
object : TestCommonNetworkHandler(bot, context, address) {
|
||||
override suspend fun createConnection(): PlatformConn {
|
||||
return conn.apply {
|
||||
doRegister() // restart channel
|
||||
// setupChannelPipeline(
|
||||
// pipeline(), PacketDecodePipeline(
|
||||
// coroutineContext.plus(
|
||||
// NioEventLoopGroup().asCoroutineDispatcher().also { startedDispatchers.add(it) })
|
||||
// )
|
||||
// )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected actual fun removeOutgoingPacketEncoder() {
|
||||
kotlin.runCatching {
|
||||
conn.pipeline().remove("outgoing-packet-encoder")
|
||||
}
|
||||
}
|
||||
|
||||
actual val conn: PlatformConn = NettyNHTestChannel()
|
||||
}
|
||||
|
||||
internal actual typealias PlatformConn = NettyNHTestChannel
|
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* 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.internal.network.framework
|
||||
|
||||
internal abstract class AbstractNettyNHTest : AbstractCommonNHTest() {
|
||||
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.internal.network.framework
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import io.netty.channel.embedded.EmbeddedChannel
|
||||
import io.netty.util.ReferenceCountUtil
|
||||
import kotlinx.serialization.InternalSerializationApi
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.serializer
|
||||
import net.mamoe.mirai.internal.network.components.RawIncomingPacket
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.internal.utils.io.ProtoBuf
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.cast
|
||||
import net.mamoe.mirai.utils.error
|
||||
|
||||
internal class NettyNHTestChannel(
|
||||
var fakeServer: (NettyNHTestChannel.(msg: Any?) -> Unit)?,
|
||||
) : EmbeddedChannel() {
|
||||
constructor() : this(null)
|
||||
|
||||
@OptIn(InternalSerializationApi::class)
|
||||
fun listen(listener: (OutgoingPacket) -> Any?) {
|
||||
fakeServer = { packet ->
|
||||
if (packet is OutgoingPacket) {
|
||||
val rsp0 = when (val rsp = listener(packet)) {
|
||||
null -> null
|
||||
is Unit -> null
|
||||
is ByteArray -> {
|
||||
RawIncomingPacket(
|
||||
commandName = packet.commandName,
|
||||
sequenceId = packet.sequenceId,
|
||||
body = rsp
|
||||
)
|
||||
}
|
||||
is RawIncomingPacket -> rsp
|
||||
is ProtoBuf -> {
|
||||
RawIncomingPacket(
|
||||
commandName = packet.commandName,
|
||||
sequenceId = packet.sequenceId,
|
||||
body = buildPacket {
|
||||
writeProtoBuf(
|
||||
rsp::class.serializer().cast<KSerializer<ProtoBuf>>(),
|
||||
rsp
|
||||
)
|
||||
}.readBytes()
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
logger.error { "Failed to respond $rsp" }
|
||||
null
|
||||
}
|
||||
}
|
||||
if (rsp0 != null) {
|
||||
pipeline().fireChannelRead(rsp0)
|
||||
}
|
||||
}
|
||||
ReferenceCountUtil.release(packet)
|
||||
}
|
||||
}
|
||||
|
||||
public /*internal*/ override fun doRegister() {
|
||||
super.doRegister() // Set channel state to ACTIVE
|
||||
// Drop old handlers
|
||||
pipeline().let { p ->
|
||||
while (p.first() != null) {
|
||||
p.removeFirst()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleInboundMessage(msg: Any?) {
|
||||
ReferenceCountUtil.release(msg) // Not handled, Drop
|
||||
}
|
||||
|
||||
override fun handleOutboundMessage(msg: Any?) {
|
||||
fakeServer?.invoke(this, msg) ?: ReferenceCountUtil.release(msg)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val logger by lazy {
|
||||
MiraiLogger.Factory.create(NettyNHTestChannel::class)
|
||||
}
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@ import kotlin.time.Duration.Companion.seconds
|
||||
/**
|
||||
* @see awaitKt
|
||||
*/
|
||||
internal class NettyUtilsTest : AbstractTest() {
|
||||
internal class CommonNHUtilsTest : AbstractTest() {
|
||||
companion object {
|
||||
private val channel = EmbeddedChannel()
|
||||
|
40
mirai-core/src/jvmBaseTest/kotlin/test/AbstractTest.kt
Normal file
40
mirai-core/src/jvmBaseTest/kotlin/test/AbstractTest.kt
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.internal.test
|
||||
|
||||
import net.mamoe.mirai.IMirai
|
||||
import net.mamoe.mirai.internal.network.framework.SynchronizedStdoutLogger
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.setSystemProp
|
||||
import org.junit.jupiter.api.Timeout
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@Timeout(value = 7, unit = TimeUnit.MINUTES)
|
||||
internal actual abstract class AbstractTest actual constructor() : CommonAbstractTest() {
|
||||
actual companion object {
|
||||
init {
|
||||
initPlatform()
|
||||
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
MiraiLogger.setDefaultLoggerCreator {
|
||||
SynchronizedStdoutLogger(it)
|
||||
}
|
||||
|
||||
setSystemProp("mirai.network.packet.logger", "true")
|
||||
setSystemProp("mirai.network.state.observer.logging", "true")
|
||||
setSystemProp("mirai.network.show.all.components", "true")
|
||||
setSystemProp("mirai.network.show.components.creation.stacktrace", "true")
|
||||
setSystemProp("mirai.network.handle.selector.logging", "true")
|
||||
|
||||
Exception() // create a exception to load relevant classes to estimate invocation time of test cases more accurately.
|
||||
IMirai::class.simpleName // similarly, load classes.
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -25,7 +25,11 @@ import net.mamoe.mirai.internal.utils.io.ProtocolStruct
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import net.mamoe.yamlkt.YamlBuilder
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.full.createInstance
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
private val logger: MiraiLogger by lazy { MiraiLogger.Factory.create(Desensitizer::class) }
|
||||
@ -91,7 +95,6 @@ internal class Desensitizer private constructor(
|
||||
.renderToString()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
inline fun <reified T> ValueDescAnalyzer.generateAndDesensitize(
|
||||
value: T,
|
||||
desensitizer: Desensitizer = instance,
|
||||
@ -116,7 +119,6 @@ internal class Desensitizer private constructor(
|
||||
}
|
||||
else -> {
|
||||
map.getOrPut(value.toByteArray().toUHexString()) { replacement.toByteArray().toUHexString() }
|
||||
map.getOrDefault()
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
||||
@ -7,13 +7,13 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.notice.test
|
||||
package net.mamoe.mirai.internal.testFramework.test
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.protobuf.ProtoNumber
|
||||
import net.mamoe.mirai.internal.testFramework.desensitizer.Desensitizer
|
||||
import net.mamoe.mirai.internal.test.AbstractTest
|
||||
import net.mamoe.mirai.internal.testFramework.desensitizer.Desensitizer
|
||||
import net.mamoe.mirai.internal.utils.io.ProtocolStruct
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import net.mamoe.yamlkt.YamlBuilder
|
@ -12,9 +12,12 @@ package net.mamoe.mirai.internal.utils
|
||||
import kotlinx.serialization.Transient
|
||||
import net.mamoe.mirai.internal.testFramework.desensitizer.Desensitizer
|
||||
import net.mamoe.mirai.utils.toUHexString
|
||||
import java.lang.reflect.Modifier
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.full.hasAnnotation
|
||||
import kotlin.reflect.jvm.javaField
|
||||
|
||||
internal class StructureToStringTransformerLegacy : StructureToStringTransformer {
|
||||
override fun transform(any: Any?): String = any._miraiContentToString()
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.internal.network.framework
|
||||
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandlerFactory
|
||||
|
||||
/**
|
||||
* Without selector. When network is closed, it will not reconnect, so that you can check for its states.
|
||||
*
|
||||
* @see AbstractCommonNHTestWithSelector
|
||||
*/
|
||||
internal actual abstract class AbstractCommonNHTest actual constructor() :
|
||||
AbstractRealNetworkHandlerTest<TestCommonNetworkHandler>() {
|
||||
|
||||
actual override val network: TestCommonNetworkHandler
|
||||
get() = TODO("Not yet implemented")
|
||||
actual override val factory: NetworkHandlerFactory<TestCommonNetworkHandler>
|
||||
get() = TODO("Not yet implemented")
|
||||
|
||||
protected actual fun removeOutgoingPacketEncoder() {
|
||||
}
|
||||
|
||||
actual val conn: PlatformConn
|
||||
get() = TODO("Not yet implemented")
|
||||
|
||||
}
|
||||
|
||||
internal actual class PlatformConn
|
10
mirai-core/src/nativeTest/kotlin/package.kt
Normal file
10
mirai-core/src/nativeTest/kotlin/package.kt
Normal file
@ -0,0 +1,10 @@
|
||||
/*
|
||||
* 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.internal
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.internal.test
|
||||
|
||||
import net.mamoe.mirai.IMirai
|
||||
import net.mamoe.mirai.internal.network.framework.SynchronizedStdoutLogger
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.setSystemProp
|
||||
import kotlin.test.Test
|
||||
|
||||
|
||||
internal actual fun initPlatform() {
|
||||
}
|
||||
|
||||
internal actual class PlatformInitializationTest actual constructor() : AbstractTest() {
|
||||
@Test
|
||||
actual fun test() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All test classes should inherit from [AbstractTest]
|
||||
*/
|
||||
internal actual abstract class AbstractTest actual constructor() : CommonAbstractTest() {
|
||||
|
||||
actual companion object {
|
||||
init {
|
||||
initPlatform()
|
||||
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
MiraiLogger.setDefaultLoggerCreator {
|
||||
SynchronizedStdoutLogger(it)
|
||||
}
|
||||
|
||||
setSystemProp("mirai.network.packet.logger", "true")
|
||||
setSystemProp("mirai.network.state.observer.logging", "true")
|
||||
setSystemProp("mirai.network.show.all.components", "true")
|
||||
setSystemProp("mirai.network.show.components.creation.stacktrace", "true")
|
||||
setSystemProp("mirai.network.handle.selector.logging", "true")
|
||||
|
||||
Exception() // create a exception to load relevant classes to estimate invocation time of test cases more accurately.
|
||||
IMirai::class.simpleName // similarly, load classes.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user