Use kotlinx-coroutines-test

This commit is contained in:
Him188
2022-06-14 12:43:43 +01:00
parent ede060004b
commit 21c4a5ba04
20 changed files with 156 additions and 181 deletions

View File

@@ -16,7 +16,10 @@ import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.testing.Test
import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
@@ -61,11 +64,12 @@ fun Project.preConfigureJvmTarget() {
fun Project.configureJvmTarget() {
val defaultVer = jvmVersion()
tasks.withType(KotlinCompile::class)
.filter { it.name.contains("test", ignoreCase = true) }
.forEach { task ->
task.kotlinOptions.freeCompilerArgs += "-opt-in=net.mamoe.mirai.utils.TestOnly"
configure(kotlinSourceSets.orEmpty()) {
languageSettings {
optIn("net.mamoe.mirai.utils.TestOnly")
optIn("kotlinx.coroutines.ExperimentalCoroutinesApi")
}
}
extensions.findByType(JavaPluginExtension::class.java)?.run {
sourceCompatibility = defaultVer

View File

@@ -73,6 +73,7 @@ fun kotlinx(id: String, version: String) = "org.jetbrains.kotlinx:kotlinx-$id:$v
fun ktor(id: String, version: String = Versions.ktor) = "io.ktor:ktor-$id:$version"
val `kotlinx-coroutines-core` = kotlinx("coroutines-core", Versions.coroutines)
val `kotlinx-coroutines-test` = kotlinx("coroutines-test", Versions.coroutines)
val `kotlinx-coroutines-jdk8` = kotlinx("coroutines-jdk8", Versions.coroutines)
val `kotlinx-coroutines-swing` = kotlinx("coroutines-swing", Versions.coroutines)
val `kotlinx-coroutines-debug` = kotlinx("coroutines-debug", Versions.coroutines)

View File

@@ -65,6 +65,7 @@ dependencies {
testApi(project(":mirai-core"))
testApi(`kotlin-stdlib-jdk8`)
testApi(`kotlinx-coroutines-test`)
"consoleRuntimeClasspath"(project)
"consoleRuntimeClasspath"(project(":mirai-core-utils"))

View File

@@ -12,6 +12,7 @@
package net.mamoe.mirai.console.command
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import net.mamoe.mirai.console.MiraiConsoleImplementation
import net.mamoe.mirai.console.Testing
import net.mamoe.mirai.console.Testing.withTesting
@@ -191,7 +192,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleExecute() = runBlocking {
fun testSimpleExecute() = runTest {
simpleCommand.withRegistration {
assertEquals("test", withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, "test"))
@@ -200,7 +201,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun `test raw command`() = runBlocking {
fun `test raw command`() = runTest {
rawCommand.withRegistration {
val result = withTesting<MessageChain> {
assertSuccess(rawCommand.execute(sender, PlainText("a1"), PlainText("a2"), PlainText("a3")))
@@ -221,7 +222,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun `test enum argument`() = runBlocking {
fun `test enum argument`() = runTest {
val enum = TestEnumArgCommand()
enum.withRegistration {
@@ -291,7 +292,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun `test temporal argument`() = runBlocking {
fun `test temporal argument`() = runTest {
val command = TestTemporalArgCommand()
command.withRegistration {
val temporal: List<KClass<out TemporalAccessor>> = listOf(
@@ -322,7 +323,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsSplitting() = runBlocking {
fun testSimpleArgsSplitting() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test", "ttt", "tt").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test ttt tt")))
@@ -331,7 +332,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsEscape() = runBlocking {
fun testSimpleArgsEscape() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test", "esc ape").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test esc\\ ape")))
@@ -340,7 +341,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsQuote() = runBlocking {
fun testSimpleArgsQuote() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test", "esc ape").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test \"esc ape\"")))
@@ -349,7 +350,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsQuoteReject() = runBlocking {
fun testSimpleArgsQuoteReject() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test", "es\"c", "ape\"").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test es\"c ape\"")))
@@ -358,7 +359,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsQuoteEscape() = runBlocking {
fun testSimpleArgsQuoteEscape() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test", "\"esc", "ape\"").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test \\\"esc ape\"")))
@@ -367,7 +368,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsMultipleQuotes() = runBlocking {
fun testSimpleArgsMultipleQuotes() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test", "esc ape", "1 2").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test \"esc ape\" \"1 2\"")))
@@ -376,7 +377,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsMisplacedQuote() = runBlocking {
fun testSimpleArgsMisplacedQuote() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test", "esc ape", "1\"", "\"2").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test \"esc ape\" 1\" \"2 ")))
@@ -385,7 +386,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsQuoteSpaceEscape() = runBlocking {
fun testSimpleArgsQuoteSpaceEscape() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test \"esc", "ape\"").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test\\ \"esc ape\"")))
@@ -394,7 +395,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsStopParse() = runBlocking {
fun testSimpleArgsStopParse() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test", "esc ape ").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test -- esc ape ")))
@@ -403,7 +404,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsStopParse2() = runBlocking {
fun testSimpleArgsStopParse2() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test", "esc ape test\\12\"\"3").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test -- esc ape test\\12\"\"3")))
@@ -412,7 +413,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsStopParseReject() = runBlocking {
fun testSimpleArgsStopParseReject() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test--", "esc", "ape").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test-- esc ape ")))
@@ -421,7 +422,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsStopParseEscape() = runBlocking {
fun testSimpleArgsStopParseEscape() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test", "--", "esc", "ape").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test \\-- esc ape")))
@@ -430,7 +431,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsStopParseEscape2() = runBlocking {
fun testSimpleArgsStopParseEscape2() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test", " --", "esc", "ape").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test \\ -- esc ape")))
@@ -439,7 +440,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun testSimpleArgsStopParseQuote() = runBlocking {
fun testSimpleArgsStopParseQuote() = runTest {
simpleCommand.withRegistration {
assertEquals(arrayOf("test", "--", "esc", "ape").joinToString(), withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, PlainText("test \"--\" esc ape")))
@@ -450,7 +451,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
val image = Image("/f8f1ab55-bf8e-4236-b55e-955848d7069f")
@Test
fun `PlainText and Image args splitting`() = runBlocking {
fun `PlainText and Image args splitting`() = runTest {
simpleCommand.withRegistration {
val result = withTesting<MessageChain> {
assertSuccess(simpleCommand.execute(sender, buildMessageChain {
@@ -472,7 +473,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun `executing command by string command`() = runBlocking {
fun `executing command by string command`() = runTest {
compositeCommand.withRegistration {
val result = withTesting<Int> {
assertSuccess(sender.executeCommand("/testComposite mute 1"))
@@ -490,7 +491,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun `composite command executing`() = runBlocking {
fun `composite command executing`() = runTest {
compositeCommand.withRegistration {
assertEquals(1, withTesting {
assertSuccess(compositeCommand.execute(sender, "mute 1"))
@@ -499,7 +500,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
}
@Test
fun `test first param command sender`() = runBlocking {
fun `test first param command sender`() = runTest {
object : CompositeCommand(owner, "cmd") {
@SubCommand
fun handle(sender: CommandSender, arg: String) {

View File

@@ -12,8 +12,7 @@
package net.mamoe.mirai.console.command
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.runBlocking
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import kotlinx.coroutines.test.runTest
import net.mamoe.mirai.Bot
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
@@ -29,15 +28,14 @@ import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
@OptIn(ExperimentalCommandDescriptors::class)
@JvmBlockingBridge
internal class LoginCommandTest : AbstractCommandTest() {
@Test
fun `login with provided password`() = runBlocking {
fun `login with provided password`() = runTest {
val myId = 123L
val myPwd = "password001"
val bot = awaitDeferred<QQAndroidBot> { cont ->
val bot = awaitDeferred { cont ->
val command = object : LoginCommandImpl() {
override suspend fun doLogin(bot: Bot) {
cont.complete(bot as QQAndroidBot)
@@ -53,7 +51,7 @@ internal class LoginCommandTest : AbstractCommandTest() {
}
@Test
fun `login with saved plain password`() = runBlocking {
fun `login with saved plain password`() = runTest {
val myId = 123L
val myPwd = "password001"
@@ -66,7 +64,7 @@ internal class LoginCommandTest : AbstractCommandTest() {
)
})
val bot = awaitDeferred<QQAndroidBot> { cont ->
val bot = awaitDeferred { cont ->
val command = object : LoginCommandImpl() {
override suspend fun doLogin(bot: Bot) {
cont.complete(bot as QQAndroidBot)
@@ -82,7 +80,7 @@ internal class LoginCommandTest : AbstractCommandTest() {
}
@Test
fun `login with saved md5 password`() = runBlocking {
fun `login with saved md5 password`() = runTest {
val myId = 123L
val myPwd = "password001"

View File

@@ -23,7 +23,7 @@ internal class TestCoroutineUtils {
// TODO TestCoroutineUtils disabled manually: on CI real time measurement is not precise causing tests to fail.
// @Test
// fun `test launchTimedTask 0 time`() = runBlocking {
// fun `test launchTimedTask 0 time`() = runTest {
// val scope = CoroutineScope(SupervisorJob())
//
// val result = withTimeoutOrNull(6000) {
@@ -39,7 +39,7 @@ internal class TestCoroutineUtils {
// }
//
// @Test
// fun `test launchTimedTask finishes 1 time`() = runBlocking {
// fun `test launchTimedTask finishes 1 time`() = runTest {
// val scope = CoroutineScope(SupervisorJob())
//
// withTimeout(4000) {
@@ -55,7 +55,7 @@ internal class TestCoroutineUtils {
// }
//
// @Test
// fun `test launchTimedTask finishes multiple times`() = runBlocking {
// fun `test launchTimedTask finishes multiple times`() = runTest {
// val scope = CoroutineScope(SupervisorJob())
//
// val resumedTimes = AtomicInteger(0)
@@ -77,7 +77,7 @@ internal class TestCoroutineUtils {
// }
//
// @Test
// fun `test launchTimedTask interval less than delay`() = runBlocking {
// fun `test launchTimedTask interval less than delay`() = runTest {
// val scope = CoroutineScope(SupervisorJob())
//
// withTimeout(5000) {

View File

@@ -51,6 +51,7 @@ kotlin {
commonTest {
dependencies {
runtimeOnly(`log4j-core`)
implementation(`kotlinx-coroutines-test`)
}
}

View File

@@ -9,7 +9,7 @@
package net.mamoe.mirai.message.data
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
@@ -26,7 +26,7 @@ internal class MessageUtilsTest {
}
@Test
fun `flow toMessageChain`(): Unit = runBlocking {
fun `flow toMessageChain`() = runTest {
assertEquals(messageChainOf(PlainText("1")), flowOf(PlainText("1")).toMessageChain())
}
}

View File

@@ -43,6 +43,7 @@ kotlin {
val commonTest by getting {
dependencies {
api(yamlkt)
implementation(`kotlinx-coroutines-test`)
}
}

View File

@@ -12,6 +12,7 @@ package net.mamoe.mirai.utils
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.yield
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -50,7 +51,7 @@ internal class LateinitMutablePropertyTest {
}
@Test
fun setValuePrevailsOnCompetitionWithInitializer() = runBlocking {
fun setValuePrevailsOnCompetitionWithInitializer() = runTest {
val verySlowInitializer = CompletableDeferred<Unit>()
val override = Symbol("override")
val initializer = Symbol("initializer")

View File

@@ -11,6 +11,7 @@ package net.mamoe.mirai.utils
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.yield
import org.junit.jupiter.api.Test
import java.util.concurrent.CompletableFuture
@@ -20,7 +21,7 @@ import kotlin.test.assertSame
internal class LateinitMutablePropertyTestJvm {
@Test
fun `initializer called once if requested by multiple threads`() = runBlocking {
fun `initializer called once if requested by multiple threads`() = runTest {
val value = Symbol("expected")
var counter = 0

View File

@@ -50,6 +50,7 @@ kotlin {
commonTest {
dependencies {
implementation(kotlin("script-runtime"))
implementation(`kotlinx-coroutines-test`)
api(yamlkt)
}
}

View File

@@ -11,7 +11,9 @@ package net.mamoe.mirai.internal.event
import kotlinx.atomicfu.atomic
import kotlinx.coroutines.*
import kotlinx.coroutines.test.runTest
import net.mamoe.mirai.event.*
import net.mamoe.mirai.utils.childScope
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.test.AfterTest
import kotlin.test.Test
@@ -112,7 +114,7 @@ internal class EventTests : AbstractEventTest() {
}
@Test
fun `test concurrent listening 2`() = runBlocking {
fun `test concurrent listening 2`() = runTest {
resetEventListeners()
val registered = atomic(0)
val called = atomic(0)
@@ -190,15 +192,11 @@ internal class EventTests : AbstractEventTest() {
open class PriorityTestEvent : AbstractEvent()
private fun singleThreaded(step: StepUtil, invoke: suspend EventChannel<Event>.() -> Unit) {
// runBlocking 会完全堵死, 没法退出
val scope = CoroutineScope(borrowSingleThreadDispatcher())
val job = scope.launch {
runTest(borrowSingleThreadDispatcher()) {
val scope = this.childScope()
invoke(scope.globalEventChannel())
scope.cancel()
}
runBlocking {
job.join()
}
scope.cancel()
step.throws()
}

View File

@@ -19,15 +19,6 @@ import kotlin.test.*
@JvmBlockingBridge
internal class NextEventTest : AbstractEventTest() {
private val dispatcher: CoroutineDispatcher = borrowSingleThreadDispatcher()
@OptIn(ExperimentalCoroutinesApi::class)
@AfterTest
fun stopDispatcher() {
(dispatcher as CloseableCoroutineDispatcher).close()
}
data class TE(
val x: Int
) : AbstractEvent()
@@ -44,66 +35,58 @@ internal class NextEventTest : AbstractEventTest() {
fun `nextEvent can receive`() = runBlockingUnit {
val channel = GlobalEventChannel
withContext(dispatcher) {
val deferred = async(start = CoroutineStart.UNDISPATCHED) {
channel.nextEvent<TE>()
}
TE(1).broadcast()
yield()
assertTrue { deferred.isCompleted }
assertEquals(TE(1), deferred.await())
val deferred = async(start = CoroutineStart.UNDISPATCHED) {
channel.nextEvent<TE>()
}
TE(1).broadcast()
yield()
assertTrue { deferred.isCompleted }
assertEquals(TE(1), deferred.await())
}
@Test
fun `nextEvent can filter type`() = runBlockingUnit {
val channel = GlobalEventChannel
withContext(dispatcher) {
val deferred = async(start = CoroutineStart.UNDISPATCHED) {
channel.nextEvent<TE>()
}
TE2(1).broadcast()
yield()
assertFalse { deferred.isCompleted }
TE(1).broadcast()
yield()
assertTrue { deferred.isCompleted }
assertEquals(TE(1), deferred.await())
val deferred = async(start = CoroutineStart.UNDISPATCHED) {
channel.nextEvent<TE>()
}
TE2(1).broadcast()
yield()
assertFalse { deferred.isCompleted }
TE(1).broadcast()
yield()
assertTrue { deferred.isCompleted }
assertEquals(TE(1), deferred.await())
}
@Test
fun `nextEvent can filter by filter`() = runBlockingUnit {
val channel = GlobalEventChannel
withContext(dispatcher) {
val deferred = async(start = CoroutineStart.UNDISPATCHED) {
channel.nextEvent<TE> { it.x == 2 }
}
TE(1).broadcast()
yield()
assertFalse { deferred.isCompleted }
TE(2).broadcast()
yield()
assertTrue { deferred.isCompleted }
assertEquals(TE(2), deferred.await())
val deferred = async(start = CoroutineStart.UNDISPATCHED) {
channel.nextEvent<TE> { it.x == 2 }
}
TE(1).broadcast()
yield()
assertFalse { deferred.isCompleted }
TE(2).broadcast()
yield()
assertTrue { deferred.isCompleted }
assertEquals(TE(2), deferred.await())
}
@Test
fun `nextEvent can timeout`() = runBlockingUnit {
val channel = GlobalEventChannel
withContext(dispatcher) {
assertFailsWith<TimeoutCancellationException> {
withTimeout(timeMillis = 1) { channel.nextEvent<TE>(EventPriority.MONITOR) }
}
assertFailsWith<TimeoutCancellationException> {
withTimeout(timeMillis = 1) { channel.nextEvent<TE>(EventPriority.MONITOR) }
}
}
@@ -111,18 +94,16 @@ internal class NextEventTest : AbstractEventTest() {
fun `nextEvent can cancel`() = runBlockingUnit {
val channel = GlobalEventChannel
withContext(dispatcher) {
coroutineScope {
val job = launch {
val result = kotlin.runCatching { channel.nextEvent<TE>(EventPriority.MONITOR) }
assertTrue { result.isFailure }
assertIs<CancellationException>(result.exceptionOrNull())
throw result.exceptionOrNull()!!
}
assertTrue { job.isActive }
job.cancelAndJoin()
assertTrue { job.isCancelled }
coroutineScope {
val job = launch {
val result = kotlin.runCatching { channel.nextEvent<TE>(EventPriority.MONITOR) }
assertTrue { result.isFailure }
assertIs<CancellationException>(result.exceptionOrNull())
throw result.exceptionOrNull()!!
}
assertTrue { job.isActive }
job.cancelAndJoin()
assertTrue { job.isCancelled }
}
}
@@ -132,59 +113,51 @@ internal class NextEventTest : AbstractEventTest() {
@Test
fun `nextEventOrNull can receive`() = runBlockingUnit {
withContext(dispatcher) {
val deferred = async(start = CoroutineStart.UNDISPATCHED) {
withTimeoutOrNull<TE>(5000) { globalEventChannel().nextEvent(EventPriority.MONITOR) }
}
TE(1).broadcast()
yield()
assertTrue { deferred.isCompleted }
assertEquals(TE(1), deferred.await())
val deferred = async(start = CoroutineStart.UNDISPATCHED) {
withTimeoutOrNull<TE>(5000) { globalEventChannel().nextEvent(EventPriority.MONITOR) }
}
TE(1).broadcast()
yield()
assertTrue { deferred.isCompleted }
assertEquals(TE(1), deferred.await())
}
@Test
fun `nextEventOrNull can filter type`() = runBlockingUnit {
withContext(dispatcher) {
val deferred = async(start = CoroutineStart.UNDISPATCHED) {
withTimeoutOrNull<TE>(5000) { globalEventChannel().nextEvent(EventPriority.MONITOR) }
}
TE2(1).broadcast()
yield()
assertFalse { deferred.isCompleted }
TE(1).broadcast()
yield()
assertTrue { deferred.isCompleted }
assertEquals(TE(1), deferred.await())
val deferred = async(start = CoroutineStart.UNDISPATCHED) {
withTimeoutOrNull<TE>(5000) { globalEventChannel().nextEvent(EventPriority.MONITOR) }
}
TE2(1).broadcast()
yield()
assertFalse { deferred.isCompleted }
TE(1).broadcast()
yield()
assertTrue { deferred.isCompleted }
assertEquals(TE(1), deferred.await())
}
@Test
fun `nextEventOrNull can filter by filter`() = runBlockingUnit {
withContext(dispatcher) {
val deferred = async(start = CoroutineStart.UNDISPATCHED) {
withTimeoutOrNull<TE>(5000) { globalEventChannel().nextEvent(EventPriority.MONITOR) { it.x == 2 } }
}
TE(1).broadcast()
yield()
assertFalse { deferred.isCompleted }
TE(2).broadcast()
yield()
assertTrue { deferred.isCompleted }
assertEquals(TE(2), deferred.await())
val deferred = async(start = CoroutineStart.UNDISPATCHED) {
withTimeoutOrNull<TE>(5000) { globalEventChannel().nextEvent(EventPriority.MONITOR) { it.x == 2 } }
}
TE(1).broadcast()
yield()
assertFalse { deferred.isCompleted }
TE(2).broadcast()
yield()
assertTrue { deferred.isCompleted }
assertEquals(TE(2), deferred.await())
}
@Test
fun `nextEventOrNull can timeout`() = runBlockingUnit {
withContext(dispatcher) {
assertEquals(null,
withTimeoutOrNull<TE>(timeMillis = 1) { globalEventChannel().nextEvent(EventPriority.MONITOR) })
}
assertEquals(null,
withTimeoutOrNull<TE>(timeMillis = 1) { globalEventChannel().nextEvent(EventPriority.MONITOR) })
}
}

View File

@@ -98,7 +98,7 @@ internal class ForwardMessageProtocolTest : AbstractMessageProtocolTest() {
// // TODO: 2022/5/23 test for download ForwardMessage
// @Test
// fun `can receive and download ForwardMessage`() {
// val message = runBlocking {
// val message = runTest {
// runWithFacade {
// net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.Msg(
// msgHead = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.MsgHead(

View File

@@ -73,13 +73,6 @@ internal class AwaitStateTest : AbstractMockNetworkHandlerTest() {
// single thread so we can use [yield] to transfer dispatch
private val singleThreadDispatcher: CoroutineDispatcher = borrowSingleThreadDispatcher()
@OptIn(ExperimentalCoroutinesApi::class)
@AfterTest
fun after() {
(singleThreadDispatcher as CloseableCoroutineDispatcher).close()
}
@Test
fun `test whileSelect onStateChanged drop if not listening`() = runBlockingUnit(singleThreadDispatcher + Job()) {
createNetworkHandler().run {

View File

@@ -13,6 +13,7 @@ package net.mamoe.mirai.internal.network.component
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.isActive
import kotlinx.coroutines.test.runTest
import net.mamoe.mirai.internal.contact.uin
import net.mamoe.mirai.internal.network.components.BotInitProcessor
import net.mamoe.mirai.internal.network.framework.AbstractCommonNHTest
@@ -31,7 +32,7 @@ import kotlin.test.assertTrue
internal class BotInitProcessorTest {
class WithoutSelector : AbstractCommonNHTest() {
@Test
fun `BotInitProcessor halted`() = runBlockingUnit {
fun `BotInitProcessor halted`() = runTest {
val p = setComponent(BotInitProcessor, object : BotInitProcessor {
var ranTimes = 0
var haltedTimes = 0

View File

@@ -9,7 +9,11 @@
package net.mamoe.mirai.internal.test
import kotlinx.coroutines.*
import kotlinx.coroutines.CloseableCoroutineDispatcher
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlin.test.AfterTest
import kotlin.test.Test
@@ -22,7 +26,7 @@ internal abstract class CommonAbstractTest {
private val dispatchers = mutableListOf<CloseableCoroutineDispatcher>()
fun borrowSingleThreadDispatcher(): CoroutineDispatcher {
return newSingleThreadContext(this::class.simpleName ?: "CommonAbstractTest")
return StandardTestDispatcher()
}
@AfterTest

View File

@@ -1,40 +1,33 @@
/*
* 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.test
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.withTimeout
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
fun runBlockingUnit(
context: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.() -> Unit
) {
return runBlocking(context) {
withTimeout(60.seconds) { // always checks for infinite runs.
block()
}
}
}
block: suspend TestScope.() -> Unit
) = runTest(context) { block() }
fun runBlockingUnit(
context: CoroutineContext = EmptyCoroutineContext,
timeout: Duration,
block: suspend CoroutineScope.() -> Unit
block: suspend TestScope.() -> Unit
) {
runBlockingUnit(context) {
runTest(context, dispatchTimeoutMs = timeout.inWholeMilliseconds) {
withTimeout(timeout) {
block()
}

View File

@@ -10,8 +10,9 @@
package net.mamoe.mirai.internal.event
import kotlinx.coroutines.cancel
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import net.mamoe.mirai.event.*
import net.mamoe.mirai.utils.childScope
import java.util.concurrent.atomic.AtomicInteger
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -20,12 +21,14 @@ internal class JvmMethodEventsTestJava : AbstractEventTest() {
private val called = AtomicInteger(0)
@Test
fun test() = runBlocking {
fun test() = runTest {
val host = TestHost(called)
globalEventChannel().registerListenerHost(host)
runBlocking { TestEvent().broadcast() }
val scope = this.childScope()
scope.globalEventChannel().registerListenerHost(host)
TestEvent().broadcast()
assertEquals(3, called.get(), null)
host.cancel() // reset listeners
scope.cancel()
}
}