mirror of
https://github.com/mamoe/mirai.git
synced 2026-08-22 22:23:32 +08:00
Use kotlinx-coroutines-test
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -65,6 +65,7 @@ dependencies {
|
||||
|
||||
testApi(project(":mirai-core"))
|
||||
testApi(`kotlin-stdlib-jdk8`)
|
||||
testApi(`kotlinx-coroutines-test`)
|
||||
|
||||
"consoleRuntimeClasspath"(project)
|
||||
"consoleRuntimeClasspath"(project(":mirai-core-utils"))
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -51,6 +51,7 @@ kotlin {
|
||||
commonTest {
|
||||
dependencies {
|
||||
runtimeOnly(`log4j-core`)
|
||||
implementation(`kotlinx-coroutines-test`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ kotlin {
|
||||
val commonTest by getting {
|
||||
dependencies {
|
||||
api(yamlkt)
|
||||
implementation(`kotlinx-coroutines-test`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ kotlin {
|
||||
commonTest {
|
||||
dependencies {
|
||||
implementation(kotlin("script-runtime"))
|
||||
implementation(`kotlinx-coroutines-test`)
|
||||
api(yamlkt)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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) })
|
||||
}
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user