Test: NettyEndlessReconnectionTest

This commit is contained in:
Him188 2021-04-25 13:58:13 +08:00
parent 29cb81ad64
commit 062492c546
3 changed files with 69 additions and 3 deletions

View File

@ -169,6 +169,10 @@ public fun systemProp(name: String, default: Boolean): Boolean =
System.getProperty(name, default.toString())?.toBoolean() ?: default
public fun systemProp(name: String, default: Long): Long =
System.getProperty(name, default.toString())?.toLongOrNull() ?: default
public fun Throwable.getRootCause(maxDepth: Int = 20): Throwable {
var depth = 0
var rootCause: Throwable? = this

View File

@ -32,6 +32,7 @@ import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.utils.ExceptionCollector
import net.mamoe.mirai.utils.childScope
import net.mamoe.mirai.utils.debug
import net.mamoe.mirai.utils.systemProp
import java.net.SocketAddress
import kotlin.coroutines.CoroutineContext
import io.netty.channel.Channel as NettyChannel
@ -206,9 +207,7 @@ internal open class NettyNetworkHandler(
wait: Boolean = false
) : NettyState(State.CONNECTING) {
private val connection = async {
if (wait) {
delay(5000)
}
if (wait) delay(RECONNECT_DELAY)
createConnection(decodePipeline)
}
@ -346,4 +345,12 @@ internal open class NettyNetworkHandler(
}
override fun initialState(): BaseStateImpl = StateInitialized()
companion object {
/**
* millis
*/
@JvmField
var RECONNECT_DELAY = systemProp("mirai.network.reconnect.delay", 5000)
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2019-2021 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/master/LICENSE
*/
package net.mamoe.mirai.internal.network.impl.netty
import io.netty.channel.Channel
import kotlinx.coroutines.delay
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.test.runBlockingUnit
import java.net.SocketAddress
import kotlin.reflect.jvm.javaGetter
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* When offline, handler will try endlessly to re-establish a connection. Exceptions are preserved as suppressed exceptions however, duplicates must be dropped to save memory.
*/
internal class NettyEndlessReconnectionTest : AbstractNettyNHTest() {
override val factory: NetworkHandlerFactory<TestNettyNH> = object : NetworkHandlerFactory<TestNettyNH> {
override fun create(context: NetworkHandlerContext, address: SocketAddress): TestNettyNH {
return object : TestNettyNH(context, address) {
override suspend fun createConnection(decodePipeline: PacketDecodePipeline): Channel =
error("fail")
}
}
}
@Test
fun `massive reconnection`() = runBlockingUnit {
val r = NettyNetworkHandler.Companion.RECONNECT_DELAY
NettyNetworkHandler.Companion.RECONNECT_DELAY = 0
network.setStateConnecting() // will connect endlessly and create a massive amount of exceptions
delay(10000) // if exceptions are ignored by ExceptionCollector, memory usage will not exceed limitation.
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
val state = network::_state.javaGetter!!.apply { isAccessible = true }
.invoke(network) as NetworkHandlerSupport.BaseStateImpl
assertTrue { state.getCause()!!.suppressed.size <= 1 } // might be zero if just created since at this time network is still running.
// size <= 1 means duplicates are dropped.
network.close(null)
NettyNetworkHandler.Companion.RECONNECT_DELAY = r
}
}