NettyTestUnit

This commit is contained in:
Karlatemp 2021-04-15 23:59:35 +08:00 committed by Him188
parent e293195391
commit 5f0b432220
3 changed files with 92 additions and 5 deletions

View File

@ -208,13 +208,17 @@ internal class NettyNetworkHandler(
override fun initialState(): BaseStateImpl = StateInitialized()
}
private suspend fun ChannelFuture.awaitKt(): ChannelFuture {
internal suspend fun ChannelFuture.awaitKt(): ChannelFuture {
suspendCancellableCoroutine<Unit> { cont ->
cont.invokeOnCancellation {
channel().close()
}
addListener {
cont.resumeWith(Result.success(Unit))
addListener { f ->
if (f.isSuccess) {
cont.resumeWith(Result.success(Unit))
} else {
cont.resumeWith(Result.failure(f.cause()))
}
}
}
return this

View File

@ -0,0 +1,69 @@
/*
* 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
import io.netty.channel.DefaultChannelPromise
import io.netty.channel.embedded.EmbeddedChannel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.mamoe.mirai.internal.network.net.impl.netty.awaitKt
import net.mamoe.mirai.internal.test.runBlockingUnit
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.Test
import kotlin.test.assertFailsWith
import kotlin.test.assertTrue
import kotlin.time.seconds
internal class NettyTestUnit {
companion object {
private val channel = EmbeddedChannel()
@JvmStatic
@AfterAll
fun afterAll() {
channel.close()
}
}
@Test
fun canAwait() = runBlockingUnit(timeout = 5.seconds) {
val future = DefaultChannelPromise(channel)
launch {
delay(2000)
future.setSuccess()
}
future.awaitKt()
}
@Test
fun returnsImmediatelyIfCompleted() = runBlockingUnit(timeout = 5.seconds) {
val future = DefaultChannelPromise(channel)
future.setSuccess()
future.awaitKt()
}
@Test
fun testAwait() {
class MyError : AssertionError("My") // coroutine debugger will modify the exception if inside coroutine
runBlockingUnit(timeout = 5.seconds) {
val future = DefaultChannelPromise(channel)
launch {
delay(2000)
future.setFailure(MyError())
}
assertFailsWith<AssertionError> {
future.awaitKt()
}.let { actual ->
assertTrue { actual is MyError }
}
}
}
}

View File

@ -12,12 +12,26 @@ package net.mamoe.mirai.internal.test
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.time.Duration
internal fun runBlockingUnit(
fun runBlockingUnit(
context: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.() -> Unit
): Unit {
) {
return runBlocking(context, block)
}
fun runBlockingUnit(
context: CoroutineContext = EmptyCoroutineContext,
timeout: Duration,
block: suspend CoroutineScope.() -> Unit
) {
runBlockingUnit(context) {
withTimeout(timeout) {
block()
}
}
}