/* * Copyright 2019-2020 Mamoe Technologies and contributors. * * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. * Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link. * * https://github.com/mamoe/mirai/blob/master/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.logging.LoggerController import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader import net.mamoe.mirai.console.plugin.loader.PluginLoader import net.mamoe.mirai.console.util.ConsoleExperimentalApi 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.* import java.nio.file.Path import kotlin.coroutines.Continuation import kotlin.coroutines.CoroutineContext import kotlin.coroutines.resume import kotlin.test.assertNotNull @OptIn(ConsoleInternalApi::class) fun initTestEnvironment() { object : MiraiConsoleImplementation { override val rootPath: Path = createTempDir().toPath() @ConsoleExperimentalApi 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) } }