Commit ca216bc4 authored by Him188's avatar Him188

Fix `syncFromEvent`, add Tests

parent 422e8a9b
......@@ -15,7 +15,6 @@ import kotlinx.coroutines.*
import net.mamoe.mirai.utils.SinceMirai
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.suspendCoroutine
import kotlin.jvm.JvmSynthetic
import kotlin.reflect.KClass
......@@ -37,7 +36,16 @@ suspend inline fun <reified E : Event, R : Any> syncFromEvent(
noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常
): R {
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
return syncFromEventOrNull(timeoutMillis, mapper) ?: error("timeout $timeoutMillis ms asyncFromEvent")
return if (timeoutMillis == -1L) {
coroutineScope {
syncFromEventImpl<E, R>(E::class, this, mapper)
}
} else {
withTimeout(timeoutMillis) {
syncFromEventImpl<E, R>(E::class, this, mapper)
}
}
}
/**
......@@ -54,19 +62,13 @@ suspend inline fun <reified E : Event, R : Any> syncFromEvent(
@JvmSynthetic
@SinceMirai("0.38.0")
suspend inline fun <reified E : Event, R : Any> syncFromEventOrNull(
timeoutMillis: Long = -1,
timeoutMillis: Long,
noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常
): R? {
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
require(timeoutMillis > 0) { "timeoutMillis must be > 0" }
return if (timeoutMillis == -1L) {
coroutineScope {
syncFromEventOrNullImpl<E, R>(E::class, this, mapper)
}
} else {
withTimeoutOrNull(timeoutMillis) {
syncFromEventOrNullImpl<E, R>(E::class, this, mapper)
}
return withTimeoutOrNull(timeoutMillis) {
syncFromEventImpl<E, R>(E::class, this, mapper)
}
}
......@@ -83,7 +85,7 @@ suspend inline fun <reified E : Event, R : Any> syncFromEventOrNull(
@Suppress("DeferredIsResult")
@SinceMirai("0.38.0")
inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEventOrNull(
timeoutMillis: Long = -1,
timeoutMillis: Long,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常
): Deferred<R?> {
......@@ -123,11 +125,11 @@ inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEvent(
//////////////
@PublishedApi
internal suspend fun <E : Event, R> syncFromEventOrNullImpl(
internal suspend fun <E : Event, R> syncFromEventImpl(
eventClass: KClass<E>,
coroutineScope: CoroutineScope,
mapper: suspend E.(E) -> R?
): R? = suspendCoroutine { cont ->
): R = suspendCancellableCoroutine { cont ->
coroutineScope.subscribe(eventClass) {
cont.resumeWith(kotlin.runCatching {
mapper.invoke(this, it) ?: return@subscribe ListeningStatus.LISTENING
......
/*
* Copyright 2020 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.message
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
import net.mamoe.mirai.event.TestEvent
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.syncFromEvent
import net.mamoe.mirai.test.runBlocking
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import kotlin.test.Test
import kotlin.test.assertFailsWith
internal class SubscribingGetTest {
@Test
fun testSyncFromEvent(): Unit = runBlocking {
withTimeout(500) {
suspendCoroutine<Unit> { cont ->
launch {
syncFromEvent(5000) { _: TestEvent ->
cont.resume(Unit)
}
}
launch {
TestEvent().broadcast()
}
}
}
}
@Test
fun testSyncFromEventTimeout() {
runBlockingWithTimeout(500) {
assertFailsWith<TimeoutCancellationException> {
syncFromEvent(100) { _: TestEvent -> }
}
}
}
}
internal fun <R> runBlockingWithTimeout(
millis: Long,
context: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.() -> R
): R = runBlocking(context) {
withTimeout(millis, block)
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment