/* * 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/dev/LICENSE */ package net.mamoe.mirai.console import kotlinx.coroutines.* import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.data.MemoryPluginDataStorage import net.mamoe.mirai.console.data.PluginDataStorage import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader import net.mamoe.mirai.console.plugin.loader.PluginLoader import net.mamoe.mirai.console.util.ConsoleInput import net.mamoe.mirai.console.util.ConsoleInternalApi import net.mamoe.mirai.console.util.SemVersion import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.LoginSolver import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.PlatformLogger import java.nio.file.Path import kotlin.coroutines.Continuation import kotlin.coroutines.CoroutineContext import kotlin.coroutines.resume import kotlin.io.path.createTempDirectory import kotlin.test.assertNotNull @OptIn(ConsoleInternalApi::class, kotlin.io.path.ExperimentalPathApi::class) fun initTestEnvironment() { object : MiraiConsoleImplementation { override val rootPath: Path = createTempDirectory() override val frontEndDescription: MiraiConsoleFrontEndDescription get() = object : MiraiConsoleFrontEndDescription { override val name: String get() = "Test" override val vendor: String get() = "Test" override val version: SemVersion get() = SemVersion("1.0.0") } override val builtInPluginLoaders: List>> = listOf(lazy { JvmPluginLoader }) override val consoleCommandSender: MiraiConsoleImplementation.ConsoleCommandSenderImpl = object : MiraiConsoleImplementation.ConsoleCommandSenderImpl { override suspend fun sendMessage(message: Message) { println(message) } override suspend fun sendMessage(message: String) { println(message) } } override val dataStorageForJvmPluginLoader: PluginDataStorage = MemoryPluginDataStorage() override val configStorageForJvmPluginLoader: PluginDataStorage = MemoryPluginDataStorage() override val dataStorageForBuiltIns: PluginDataStorage = MemoryPluginDataStorage() override val configStorageForBuiltIns: PluginDataStorage = MemoryPluginDataStorage() override val consoleInput: ConsoleInput = object : ConsoleInput { override suspend fun requestInput(hint: String): String { println(hint) return readLine() ?: error("No stdin") } } override fun createLoginSolver(requesterBot: Long, configuration: BotConfiguration): LoginSolver = LoginSolver.Default!! override fun createLogger(identity: String?): MiraiLogger { return PlatformLogger(identity) } override val coroutineContext: CoroutineContext = SupervisorJob() + CoroutineExceptionHandler { _, throwable -> throwable.printStackTrace() } }.start() CommandManager } internal object Testing { @Volatile internal var cont: Continuation? = null @Suppress("UNCHECKED_CAST") suspend fun withTesting(timeout: Long = 50000L, block: suspend () -> Unit): R { @Suppress("RemoveExplicitTypeArguments") // bug return if (timeout != -1L) { withTimeout(timeout) { suspendCancellableCoroutine { ct -> this@Testing.cont = ct as Continuation runBlocking { block() } } } } else { suspendCancellableCoroutine { ct -> this.cont = ct as Continuation runBlocking { block() } } } } fun ok(result: Any? = Unit) { val cont = cont assertNotNull(cont) cont.resume(result) } }