mirai/backend/mirai-console/test/command/TestCommand.kt

365 lines
12 KiB
Kotlin
Raw Normal View History

/*
2020-08-16 23:36:24 +08:00
* Copyright 2019-2020 Mamoe Technologies and contributors.
*
2020-08-23 17:46:51 +08:00
* 此源代码的使用受 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
*/
@file:Suppress("unused")
package net.mamoe.mirai.console.command
2020-08-01 23:13:49 +08:00
import kotlinx.coroutines.cancel
import kotlinx.coroutines.runBlocking
import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.Testing
2020-08-01 23:13:49 +08:00
import net.mamoe.mirai.console.Testing.withTesting
2020-10-24 21:19:50 +08:00
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.getRegisteredCommands
2020-08-16 23:21:11 +08:00
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
2020-10-24 21:19:50 +08:00
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.registerCommand
2020-08-16 23:21:11 +08:00
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregisterAllCommands
2020-10-24 21:19:50 +08:00
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregisterCommand
2020-10-09 12:35:16 +08:00
import net.mamoe.mirai.console.command.descriptor.CommandValueArgumentParser
2020-10-20 13:27:13 +08:00
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
import net.mamoe.mirai.console.command.descriptor.buildCommandArgumentContext
2020-08-01 23:13:49 +08:00
import net.mamoe.mirai.console.initTestEnvironment
import net.mamoe.mirai.console.internal.command.CommandManagerImpl
2020-08-16 23:21:11 +08:00
import net.mamoe.mirai.console.internal.command.flattenCommandComponents
2020-09-04 10:57:32 +08:00
import net.mamoe.mirai.message.data.*
2020-08-01 23:13:49 +08:00
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
2020-10-24 13:14:25 +08:00
import kotlin.test.*
object TestCompositeCommand : CompositeCommand(
2020-11-29 18:07:02 +08:00
owner,
"testComposite", "tsC"
) {
@SubCommand
2020-10-24 11:35:10 +08:00
fun mute(seconds: Int = 60) {
Testing.ok(seconds)
}
@SubCommand
fun mute(target: Long, seconds: Int) {
Testing.ok(seconds)
}
}
2020-11-10 08:55:54 +08:00
object TestRawCommand : RawCommand(
2020-11-29 18:07:02 +08:00
owner,
2020-11-10 08:55:54 +08:00
"testRaw"
) {
override suspend fun CommandSender.onCommand(args: MessageChain) {
Testing.ok(args)
}
}
object TestSimpleCommand : RawCommand(owner, "testSimple", "tsS") {
2020-09-04 10:57:32 +08:00
override suspend fun CommandSender.onCommand(args: MessageChain) {
Testing.ok(args)
}
}
internal val sender by lazy { ConsoleCommandSender }
2020-11-29 18:07:02 +08:00
internal object TestUnitCommandOwner : CommandOwner by ConsoleCommandOwner
internal val owner by lazy { TestUnitCommandOwner }
2020-08-01 23:13:49 +08:00
2020-10-24 11:35:10 +08:00
@OptIn(ExperimentalCommandDescriptors::class)
internal class TestCommand {
companion object {
@JvmStatic
@BeforeAll
fun init() {
initTestEnvironment()
}
2020-08-01 23:05:03 +08:00
@AfterAll
@JvmStatic
fun destroy() {
2020-08-01 23:13:49 +08:00
MiraiConsole.cancel()
2020-08-01 23:05:03 +08:00
}
}
@Test
fun testRegister() {
try {
2020-10-24 21:19:50 +08:00
unregisterAllCommands(ConsoleCommandOwner) // builtins
2020-11-29 18:07:02 +08:00
unregisterAllCommands(owner) // testing unit
2020-10-24 21:19:50 +08:00
unregisterCommand(TestSimpleCommand)
2020-08-01 23:05:03 +08:00
assertTrue(TestCompositeCommand.register())
assertFalse(TestCompositeCommand.register())
2020-11-29 18:07:02 +08:00
assertEquals(1, getRegisteredCommands(owner).size)
2020-09-18 23:26:16 +08:00
assertEquals(1, CommandManagerImpl._registeredCommands.size)
2020-10-23 13:40:16 +08:00
assertEquals(2,
CommandManagerImpl.requiredPrefixCommandMap.size,
CommandManagerImpl.requiredPrefixCommandMap.entries.joinToString { it.toString() })
} finally {
2020-10-24 21:19:50 +08:00
unregisterCommand(TestCompositeCommand)
}
}
@Test
fun testSimpleExecute() = runBlocking {
2020-10-20 13:27:13 +08:00
TestSimpleCommand.withRegistration {
assertEquals("test", withTesting<MessageChain> {
assertSuccess(TestSimpleCommand.execute(sender, "test"))
}.contentToString())
}
}
2020-11-10 08:55:54 +08:00
@Test
fun `test raw command`() = runBlocking {
TestRawCommand.withRegistration {
val result = withTesting<MessageChain> {
assertSuccess(TestRawCommand.execute(sender, PlainText("a1"), PlainText("a2"), PlainText("a3")))
}
assertEquals(3, result.size)
assertEquals("a1, a2, a3", result.joinToString())
}
}
@Test
fun `test flattenCommandArgs`() {
val result = arrayOf("test", image).flattenCommandComponents().toTypedArray()
2020-09-04 10:57:32 +08:00
assertEquals("test", result[0].content)
assertSame(image, result[1])
assertEquals(2, result.size)
}
@Test
fun testSimpleArgsSplitting() = runBlocking {
2020-10-23 13:40:16 +08:00
TestSimpleCommand.withRegistration {
assertEquals(arrayOf("test", "ttt", "tt").joinToString(), withTesting<MessageChain> {
assertSuccess(TestSimpleCommand.execute(sender, PlainText("test ttt tt")))
}.joinToString())
}
}
val image = Image("/f8f1ab55-bf8e-4236-b55e-955848d7069f")
@Test
fun `PlainText and Image args splitting`() = runBlocking {
2020-10-23 13:40:16 +08:00
TestSimpleCommand.withRegistration {
val result = withTesting<MessageChain> {
assertSuccess(TestSimpleCommand.execute(sender, buildMessageChain {
+"test"
+image
+"tt"
}))
}
assertEquals<Any>(arrayOf("test", image, "tt").joinToString(), result.toTypedArray().joinToString())
assertSame(image, result[1])
}
}
@Test
fun `test throw Exception`() {
runBlocking {
assertTrue(sender.executeCommand("").isFailure())
}
}
@Test
fun `executing command by string command`() = runBlocking {
TestCompositeCommand.withRegistration {
val result = withTesting<Int> {
assertSuccess(sender.executeCommand("/testComposite mute 1"))
}
assertEquals(1, result)
}
}
2020-10-24 11:35:10 +08:00
@Test
fun `composite command descriptors`() {
val overloads = TestCompositeCommand.overloads
assertEquals("CommandSignature(<mute>, seconds: Int = ...)", overloads[0].toString())
assertEquals("CommandSignature(<mute>, target: Long, seconds: Int)", overloads[1].toString())
2020-10-24 11:35:10 +08:00
}
@Test
fun `composite command executing`() = runBlocking {
2020-10-23 13:40:16 +08:00
TestCompositeCommand.withRegistration {
assertEquals(1, withTesting {
assertSuccess(TestCompositeCommand.execute(sender, "mute 1"))
})
}
}
@Test
fun `composite sub command resolution conflict`() {
runBlocking {
val composite = object : CompositeCommand(
2020-11-29 18:07:02 +08:00
owner,
"tr"
) {
@Suppress("UNUSED_PARAMETER")
@SubCommand
fun mute(seconds: Int) {
Testing.ok(1)
}
@Suppress("UNUSED_PARAMETER")
@SubCommand
2020-10-24 11:35:10 +08:00
fun mute(seconds: Int, arg2: Int = 1) {
Testing.ok(2)
}
}
2020-10-24 21:19:50 +08:00
registerCommand(composite)
2020-10-24 11:35:10 +08:00
println(composite.overloads.joinToString())
composite.withRegistration {
2020-10-24 11:35:10 +08:00
assertEquals(1, withTesting { assertSuccess(composite.execute(sender, "mute 123")) }) // one arg, resolves to mute(Int)
assertEquals(2, withTesting { assertSuccess(composite.execute(sender, "mute 123 1")) }) // two arg, resolved to mute(Int, Int)
}
}
}
@Test
fun `composite sub command parsing`() {
runBlocking {
class MyClass(
2020-10-23 13:40:16 +08:00
val value: Int,
)
val composite = object : CompositeCommand(
2020-11-29 18:07:02 +08:00
owner,
2020-09-09 22:49:48 +08:00
"test22",
overrideContext = buildCommandArgumentContext {
2020-10-09 12:35:16 +08:00
add(object : CommandValueArgumentParser<MyClass> {
override fun parse(raw: String, sender: CommandSender): MyClass {
return MyClass(raw.toInt())
}
override fun parse(raw: MessageContent, sender: CommandSender): MyClass {
2020-10-24 12:00:56 +08:00
if (raw is PlainText) return parse(raw.content, sender)
assertSame(image, raw)
return MyClass(2)
}
})
}
) {
@SubCommand
fun mute(seconds: MyClass) {
Testing.ok(seconds)
}
}
composite.withRegistration {
2020-10-24 12:00:56 +08:00
assertEquals(333, withTesting<MyClass> { assertSuccess(execute(sender, "mute 333")) }.value)
assertEquals(2, withTesting<MyClass> {
2020-10-23 13:40:16 +08:00
assertSuccess(
execute(sender, buildMessageChain {
+"mute"
+image
})
)
}.value)
}
}
}
2020-06-28 11:46:06 +08:00
@Test
fun `test simple command`() {
runBlocking {
val simple = object : SimpleCommand(owner, "test") {
@Handler
fun onCommand(string: String) {
Testing.ok(string)
}
}
simple.withRegistration {
2020-09-04 18:56:42 +08:00
// assertEquals("xxx", withTesting { simple.execute(sender, "xxx") })
2020-09-09 22:49:48 +08:00
assertEquals("xxx", withTesting { assertSuccess(sender.executeCommand("/test xxx")) })
2020-06-28 11:46:06 +08:00
}
}
}
@Test
fun `test optional argument command`() {
runBlocking {
val optionCommand = object : CompositeCommand(
2020-11-29 18:07:02 +08:00
owner,
"testOptional"
) {
@SubCommand
fun optional(arg1: String, arg2: String = "Here is optional", arg3: String? = null) {
println(arg1)
println(arg2)
println(arg3)
// println(arg3)
Testing.ok(Unit)
}
}
optionCommand.withRegistration {
withTesting<Unit> {
assertSuccess(sender.executeCommand("/testOptional optional 1"))
}
}
}
}
2020-10-24 13:14:25 +08:00
@Test
fun `test vararg`() {
runBlocking {
val optionCommand = object : CompositeCommand(
2020-11-29 18:07:02 +08:00
owner,
2020-10-24 13:14:25 +08:00
"test"
) {
@SubCommand
fun vararg(arg1: Int, vararg x: String) {
assertEquals(1, arg1)
Testing.ok(x)
}
}
optionCommand.withRegistration {
assertArrayEquals(
emptyArray<String>(),
withTesting {
assertSuccess(sender.executeCommand("/test vararg 1"))
}
)
assertArrayEquals(
arrayOf("s"),
withTesting<Array<String>> {
assertSuccess(sender.executeCommand("/test vararg 1 s"))
}
)
assertArrayEquals(
arrayOf("s", "s", "s"),
withTesting {
assertSuccess(sender.executeCommand("/test vararg 1 s s s"))
}
)
}
}
}
}
fun <T> assertArrayEquals(expected: Array<out T>, actual: Array<out T>, message: String? = null) {
asserter.assertEquals(message, expected.contentToString(), actual.contentToString())
2020-08-01 23:05:03 +08:00
}
2020-10-20 13:27:13 +08:00
@OptIn(ExperimentalCommandDescriptors::class)
internal fun assertSuccess(result: CommandExecuteResult) {
if (result.isFailure()) {
throw result.exception ?: AssertionError(result.toString())
}
2020-10-27 21:58:57 +08:00
}