From f05305cb0a94efb4502935d3792edfc501cdc1f3 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Fri, 21 Jul 2023 01:01:32 +0200 Subject: [PATCH] Add command test and fix command path handling - It feels so good to be able to debug this code --- ButtonProcessor/pom.xml | 2 +- Chroma-Core/pom.xml | 6 ++ .../java/buttondevteam/lib/chat/Command2.kt | 9 ++- .../java/buttondevteam/lib/chat/ICommand2.kt | 41 +++++------ .../lib/chat/test/Command2MCTest.kt | 73 +++++++++++++++++++ Chroma-Core/src/test/resources/commands.yml | 18 +++++ pom.xml | 29 ++++---- 7 files changed, 141 insertions(+), 37 deletions(-) create mode 100644 Chroma-Core/src/test/kotlin/buttondevteam/lib/chat/test/Command2MCTest.kt create mode 100644 Chroma-Core/src/test/resources/commands.yml diff --git a/ButtonProcessor/pom.xml b/ButtonProcessor/pom.xml index dfbfe2b..ed36791 100644 --- a/ButtonProcessor/pom.xml +++ b/ButtonProcessor/pom.xml @@ -37,7 +37,7 @@ maven-compiler-plugin 3.8.1 - -proc:none + none 17 17 diff --git a/Chroma-Core/pom.xml b/Chroma-Core/pom.xml index baa48ce..a5ea55a 100755 --- a/Chroma-Core/pom.xml +++ b/Chroma-Core/pom.xml @@ -249,6 +249,12 @@ mccoroutine-bukkit-core 2.11.0 + + com.github.seeseemelk + MockBukkit-v1.19 + 2.29.0 + test + TBMCPlugins diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.kt index e8da066..e62b3ce 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.kt @@ -90,8 +90,14 @@ abstract class Command2, TP : Command2Sender>( paramConverters[cl] = ParamConverter(converter, errormsg, allSupplier) } + /** + * Handle the given command line as sent by the sender. + * + * @param sender The sender who sent the command + * @param commandline The command line, including the leading command char + */ open fun handleCommand(sender: TP, commandline: String): Boolean { - val results = dispatcher.parse(commandline, sender) + val results = dispatcher.parse(commandline.removePrefix("/"), sender) if (results.reader.canRead()) { return false // Unknown command } @@ -138,6 +144,7 @@ abstract class Command2, TP : Command2Sender>( for (meth in command.javaClass.methods) { val ann = meth.getAnnotation(Subcommand::class.java) ?: continue val fullPath = command.commandPath + CommandUtils.getCommandPath(meth.name, ' ') + assert(fullPath.isNotBlank()) { "No path found for command class ${command.javaClass.name} and method ${meth.name}" } val (lastNode, mainNode, remainingPath) = registerNodeFromPath(fullPath) lastNode.addChild(getExecutableNode(meth, command, ann, remainingPath, CommandArgumentHelpManager(command), fullPath)) if (mainCommandNode == null) mainCommandNode = mainNode diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/ICommand2.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/ICommand2.kt index 6a122c3..b8d724a 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/ICommand2.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/ICommand2.kt @@ -74,32 +74,31 @@ abstract class ICommand2(val manager: Command2<*, TP>) { get() = EMPTY_PATHS // TODO: Deal with this (used for channel IDs) private fun getcmdpath(): String { - if (!javaClass.isAnnotationPresent(CommandClass::class.java)) throw RuntimeException( - "No @CommandClass annotation on command class " + javaClass.simpleName + "!" - ) + if (!javaClass.isAnnotationPresent(CommandClass::class.java)) + throw RuntimeException("No @CommandClass annotation on command class ${javaClass.simpleName}!") val getFromClass = Function { cl: Class<*> -> cl.simpleName.lowercase(Locale.getDefault()).replace("commandbase", "") // <-- ... .replace("command", "") } - var path = javaClass.getAnnotation(CommandClass::class.java).path - var prevpath = if (path.isEmpty()) getFromClass.apply(javaClass) else path.also { path = it } - var cl: Class<*>? = javaClass.superclass - while (cl != null && cl.getPackage().name != ICommand2MC::class.java.getPackage().name) { - // - var newpath: String - val ccann: CommandClass? = cl.getAnnotation(CommandClass::class.java) - if (ccann?.path.isNullOrEmpty() || ccann?.path == prevpath) { - if (ccann?.excludeFromPath ?: Modifier.isAbstract(cl.modifiers)) { - cl = cl.superclass - continue - } - newpath = getFromClass.apply(cl) - } else newpath = ccann!!.path - path = "$newpath $path" - prevpath = newpath - cl = cl.superclass + val classList = mutableListOf>(javaClass) + while (true) { + val superClass = classList.last().superclass + if (superClass != null && superClass.getPackage().name != ICommand2MC::class.java.getPackage().name) { + classList.add(superClass) + } else { + break + } } - return path + return classList.reversed().associateWith { it.getAnnotation(CommandClass::class.java) } + .mapNotNull { + if (it.value?.path.isNullOrEmpty()) + if (it.value?.excludeFromPath ?: Modifier.isAbstract(it.key.modifiers)) + null + else + it.key.simpleName.lowercase().removeSuffix("commandbase").removeSuffix("command") + else + it.value.path + }.joinToString(" ") } companion object { diff --git a/Chroma-Core/src/test/kotlin/buttondevteam/lib/chat/test/Command2MCTest.kt b/Chroma-Core/src/test/kotlin/buttondevteam/lib/chat/test/Command2MCTest.kt new file mode 100644 index 0000000..b4c3db6 --- /dev/null +++ b/Chroma-Core/src/test/kotlin/buttondevteam/lib/chat/test/Command2MCTest.kt @@ -0,0 +1,73 @@ +package buttondevteam.lib.chat.test + +import be.seeseemelk.mockbukkit.MockBukkit +import buttondevteam.core.MainPlugin +import buttondevteam.core.component.channel.Channel +import buttondevteam.lib.architecture.ButtonPlugin +import buttondevteam.lib.chat.Command2 +import buttondevteam.lib.chat.Command2MCSender +import buttondevteam.lib.chat.CommandClass +import buttondevteam.lib.chat.ICommand2MC +import buttondevteam.lib.player.ChromaGamerBase +import buttondevteam.lib.player.TBMCPlayer +import org.junit.jupiter.api.MethodOrderer +import org.junit.jupiter.api.Order +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestMethodOrder +import java.util.* + +@TestMethodOrder(MethodOrderer.OrderAnnotation::class) +class Command2MCTest { + + init { + if (!initialized) { + try { + MockBukkit.mock() + } catch (e: IllegalStateException) { + throw RuntimeException("Failed to init tests! Something in here fails to initialize. Check the first test case.", e) + } + MockBukkit.load(MainPlugin::class.java, true) + ButtonPlugin.command2MC.unregisterCommands(MainPlugin.instance) // FIXME should have the init code separate of the plugin init code + initialized = true + } + } + + @Test + @Order(1) + fun testRegisterCommand() { + MainPlugin.instance.registerCommand(TestCommand) + assert(ButtonPlugin.command2MC.commandNodes.size == 1) + assert(ButtonPlugin.command2MC.commandNodes.first().literal == "test") + } + + @Test + fun testHasPermission() { + } + + @Test + fun testAddParamConverter() { + } + + @Test + fun testUnregisterCommands() { + } + + @Test + @Order(2) + fun testHandleCommand() { + val user = ChromaGamerBase.getUser(UUID.randomUUID().toString(), TBMCPlayer::class.java) + assert(ButtonPlugin.command2MC.handleCommand(Command2MCSender(user, Channel.globalChat, user), "/test hmm")) + } + + @CommandClass + object TestCommand : ICommand2MC() { + @Command2.Subcommand + fun def(sender: Command2MCSender, test: String) { + println(test) + } + } + + companion object { + private var initialized = false + } +} \ No newline at end of file diff --git a/Chroma-Core/src/test/resources/commands.yml b/Chroma-Core/src/test/resources/commands.yml new file mode 100644 index 0000000..4d3ff60 --- /dev/null +++ b/Chroma-Core/src/test/resources/commands.yml @@ -0,0 +1,18 @@ +buttondevteam: + lib: + chat: + test: + Command2MCTest: + TestCommand: + def: + method: def() + params: '' + core: + ComponentCommand: + def: + method: def() + params: '' + ChromaCommand: + def: + method: def() + params: '' diff --git a/pom.xml b/pom.xml index af71e1c..ecae72f 100644 --- a/pom.xml +++ b/pom.xml @@ -41,18 +41,19 @@ - - junit - junit - 4.13.1 - test - - - - org.projectlombok - lombok - ${lombok.version} - provided - - + + + org.junit.jupiter + junit-jupiter-api + 5.9.3 + test + + + + org.projectlombok + lombok + ${lombok.version} + provided + + \ No newline at end of file