mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-08-03 20:16:16 -04:00
test command exection, fix execution bugs
This commit is contained in:
parent
deed2949a3
commit
574c71f359
8
doc/CLI.md
Normal file
8
doc/CLI.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# CLI ToDo
|
||||||
|
|
||||||
|
- [ ] set default root node to `null`
|
||||||
|
- [ ] all parsers
|
||||||
|
- [ ] better suggestions
|
||||||
|
- [ ] gui suggestions
|
||||||
|
- [ ] improved entity parser
|
||||||
|
- [ ] some cli commands
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.commands.errors
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.commands.util.CommandReader
|
||||||
|
|
||||||
|
class DeadEndError(
|
||||||
|
reader: CommandReader,
|
||||||
|
) : ReaderError(reader, reader.pointer, reader.pointer)
|
@ -35,9 +35,13 @@ abstract class CommandNode(
|
|||||||
open fun execute(reader: CommandReader, stack: CommandStack) {
|
open fun execute(reader: CommandReader, stack: CommandStack) {
|
||||||
val pointer = reader.pointer
|
val pointer = reader.pointer
|
||||||
val stackSize = stack.size
|
val stackSize = stack.size
|
||||||
var lastError: Throwable? = null
|
|
||||||
var highestStack = 0
|
var childError: Throwable? = null
|
||||||
|
var errorStack = -1
|
||||||
|
|
||||||
for (child in children) {
|
for (child in children) {
|
||||||
|
reader.pointer = pointer
|
||||||
|
stack.reset(stackSize)
|
||||||
try {
|
try {
|
||||||
executeChild(child, reader, stack)
|
executeChild(child, reader, stack)
|
||||||
if (reader.canPeek()) {
|
if (reader.canPeek()) {
|
||||||
@ -45,18 +49,13 @@ abstract class CommandNode(
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
} catch (error: Throwable) {
|
} catch (error: Throwable) {
|
||||||
val size = stack.size
|
if (stack.size > errorStack) {
|
||||||
if (size >= highestStack) {
|
errorStack = stack.size
|
||||||
highestStack = size
|
childError = error
|
||||||
lastError = error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reader.pointer = pointer
|
|
||||||
|
|
||||||
stack.reset(stackSize)
|
|
||||||
}
|
}
|
||||||
|
throw childError ?: return
|
||||||
throw lastError ?: if (reader.canPeek()) throw TrailingTextArgument(reader) else return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.commands.nodes
|
package de.bixilon.minosoft.commands.nodes
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.commands.errors.DeadEndError
|
||||||
import de.bixilon.minosoft.commands.errors.ExpectedArgumentError
|
import de.bixilon.minosoft.commands.errors.ExpectedArgumentError
|
||||||
import de.bixilon.minosoft.commands.stack.CommandExecutor
|
import de.bixilon.minosoft.commands.stack.CommandExecutor
|
||||||
import de.bixilon.minosoft.commands.stack.CommandStack
|
import de.bixilon.minosoft.commands.stack.CommandStack
|
||||||
@ -38,11 +39,12 @@ abstract class ExecutableNode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun execute(reader: CommandReader, stack: CommandStack) {
|
override fun execute(reader: CommandReader, stack: CommandStack) {
|
||||||
reader.skipWhitespaces()
|
|
||||||
if (!reader.canPeekNext()) {
|
if (!reader.canPeekNext()) {
|
||||||
// empty string
|
// empty string
|
||||||
if (executable) {
|
if (executable) {
|
||||||
return execute(stack)
|
return execute(stack)
|
||||||
|
} else if (children.isEmpty()) {
|
||||||
|
throw DeadEndError(reader)
|
||||||
} else {
|
} else {
|
||||||
throw ExpectedArgumentError(reader)
|
throw ExpectedArgumentError(reader)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.commands.nodes
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.commands.errors.DeadEndError
|
||||||
|
import de.bixilon.minosoft.commands.errors.ExpectedArgumentError
|
||||||
|
import de.bixilon.minosoft.commands.errors.literal.ExpectedLiteralArgument
|
||||||
|
import de.bixilon.minosoft.commands.errors.literal.InvalidLiteralArgumentError
|
||||||
|
import de.bixilon.minosoft.commands.errors.literal.TrailingTextArgument
|
||||||
|
import de.bixilon.minosoft.commands.parser.brigadier.string.StringParseError
|
||||||
|
import de.bixilon.minosoft.commands.parser.brigadier.string.StringParser
|
||||||
|
import de.bixilon.minosoft.commands.stack.CommandStack
|
||||||
|
import de.bixilon.minosoft.commands.util.CommandReader
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.assertDoesNotThrow
|
||||||
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertNotNull
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
|
||||||
|
internal class ExecutionChildReadingTest {
|
||||||
|
|
||||||
|
private fun createCommand(): CommandNode {
|
||||||
|
return RootNode()
|
||||||
|
.addChild(LiteralNode("0_literal"))
|
||||||
|
.addChild(
|
||||||
|
LiteralNode("1_literal")
|
||||||
|
.addChild(LiteralNode("1_literal_2"))
|
||||||
|
.addChild(LiteralNode("2_literal_2", executable = true))
|
||||||
|
)
|
||||||
|
.addChild(LiteralNode("2_literal", executable = true))
|
||||||
|
.addChild(
|
||||||
|
LiteralNode("1_execute")
|
||||||
|
.addChild(ArgumentNode("args", StringParser(StringParser.StringModes.GREEDY), executable = true))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCreation() {
|
||||||
|
assertTrue(createCommand() is RootNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testValid() {
|
||||||
|
val stack = CommandStack()
|
||||||
|
assertDoesNotThrow { (createCommand().execute(CommandReader("1_execute test"), stack)) }
|
||||||
|
assertNotNull(stack["1_execute"])
|
||||||
|
assertEquals(stack["args"], "test")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testValid2() {
|
||||||
|
val stack = CommandStack()
|
||||||
|
assertDoesNotThrow { (createCommand().execute(CommandReader("1_execute this is a really long valid greedy read string..."), stack)) }
|
||||||
|
assertNotNull(stack["1_execute"])
|
||||||
|
assertEquals(stack["args"], "this is a really long valid greedy read string...")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInvalidLiteralValid() {
|
||||||
|
assertThrows<InvalidLiteralArgumentError> { (createCommand().execute(CommandReader("3_404_not_found"), CommandStack())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testBlankStringArgument() {
|
||||||
|
assertThrows<StringParseError> { (createCommand().execute(CommandReader("1_execute "), CommandStack())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNoStringArgument() {
|
||||||
|
assertThrows<ExpectedArgumentError> { (createCommand().execute(CommandReader("1_execute"), CommandStack())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDeadEnd() {
|
||||||
|
assertThrows<DeadEndError> { (createCommand().execute(CommandReader("0_literal"), CommandStack())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTrailingData() {
|
||||||
|
assertThrows<TrailingTextArgument> { (createCommand().execute(CommandReader("0_literal test"), CommandStack())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testEmpty() {
|
||||||
|
assertThrows<ExpectedLiteralArgument> { (createCommand().execute(CommandReader(""), CommandStack())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTrailingWhitespace() {
|
||||||
|
assertDoesNotThrow { createCommand().execute(CommandReader("2_literal "), CommandStack()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test2TrailingWhitespace() {
|
||||||
|
assertDoesNotThrow { createCommand().execute(CommandReader("1_literal 2_literal_2 "), CommandStack()) }
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@
|
|||||||
package de.bixilon.minosoft.commands.nodes
|
package de.bixilon.minosoft.commands.nodes
|
||||||
|
|
||||||
import de.bixilon.minosoft.commands.errors.literal.InvalidLiteralArgumentError
|
import de.bixilon.minosoft.commands.errors.literal.InvalidLiteralArgumentError
|
||||||
|
import de.bixilon.minosoft.commands.errors.literal.TrailingTextArgument
|
||||||
import de.bixilon.minosoft.commands.errors.reader.ExpectedWhitespaceError
|
import de.bixilon.minosoft.commands.errors.reader.ExpectedWhitespaceError
|
||||||
import de.bixilon.minosoft.commands.parser.brigadier.string.StringParseError
|
import de.bixilon.minosoft.commands.parser.brigadier.string.StringParseError
|
||||||
import de.bixilon.minosoft.commands.parser.brigadier.string.StringParser
|
import de.bixilon.minosoft.commands.parser.brigadier.string.StringParser
|
||||||
@ -29,7 +30,11 @@ internal class SuggestionChildReadingTest {
|
|||||||
|
|
||||||
private fun createCommand(): CommandNode {
|
private fun createCommand(): CommandNode {
|
||||||
return RootNode()
|
return RootNode()
|
||||||
.addChild(LiteralNode("1_literal"))
|
.addChild(
|
||||||
|
LiteralNode("1_literal")
|
||||||
|
.addChild(LiteralNode("1_literal_2"))
|
||||||
|
.addChild(LiteralNode("2_literal_2"))
|
||||||
|
)
|
||||||
.addChild(LiteralNode("2_literal"))
|
.addChild(LiteralNode("2_literal"))
|
||||||
.addChild(
|
.addChild(
|
||||||
LiteralNode("1_execute")
|
LiteralNode("1_execute")
|
||||||
@ -76,4 +81,34 @@ internal class SuggestionChildReadingTest {
|
|||||||
fun testEmptySuggestions() {
|
fun testEmptySuggestions() {
|
||||||
assertEquals(createCommand().getSuggestions(CommandReader(""), CommandStack()), listOf("1_literal", "2_literal", "1_execute"))
|
assertEquals(createCommand().getSuggestions(CommandReader(""), CommandStack()), listOf("1_literal", "2_literal", "1_execute"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTrailingData() {
|
||||||
|
assertThrows<TrailingTextArgument> { (createCommand().getSuggestions(CommandReader("2_literal test"), CommandStack())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test2InvalidLiteral() {
|
||||||
|
assertThrows<InvalidLiteralArgumentError> { (createCommand().getSuggestions(CommandReader("1_literal test"), CommandStack())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test2EmptyLevelSuggestions() {
|
||||||
|
assertEquals(createCommand().getSuggestions(CommandReader("1_literal"), CommandStack()), listOf("1_literal_2", "2_literal_2"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test2TrailingData() {
|
||||||
|
assertThrows<TrailingTextArgument> { (createCommand().getSuggestions(CommandReader("2_literal 1_literal_2 test"), CommandStack())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTrailingWhitespace() {
|
||||||
|
assertEquals(createCommand().getSuggestions(CommandReader("2_literal "), CommandStack()), emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test2TrailingWhitespace() {
|
||||||
|
assertEquals(createCommand().getSuggestions(CommandReader("1_literal 1_literal_2 "), CommandStack()), emptyList())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user