From c5498e26b990d2052c06dd2284bfabf3c5de748b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Mon, 7 Sep 2020 20:59:58 +0200 Subject: [PATCH] Add some tests and make the permission check work properly --- .../intellectualsites/commands/Command.java | 3 + .../commands/CommandManager.java | 10 +++ .../commands/CommandTree.java | 23 +++--- .../exceptions/NoPermissionException.java | 1 - .../commands/CommandTest.java | 46 +++++++++++ .../commands/CommandTreeTest.java | 78 +++++++++++++++++++ .../commands/TestCommandManager.java | 37 +++++++++ .../commands/TestCommandSender.java | 40 ++++++++++ 8 files changed, 228 insertions(+), 10 deletions(-) create mode 100644 commands-core/src/test/java/com/intellectualsites/commands/CommandTest.java create mode 100644 commands-core/src/test/java/com/intellectualsites/commands/CommandTreeTest.java create mode 100644 commands-core/src/test/java/com/intellectualsites/commands/TestCommandManager.java create mode 100644 commands-core/src/test/java/com/intellectualsites/commands/TestCommandSender.java diff --git a/commands-core/src/main/java/com/intellectualsites/commands/Command.java b/commands-core/src/main/java/com/intellectualsites/commands/Command.java index 6af472e4..1dceb880 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/Command.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/Command.java @@ -60,6 +60,9 @@ public class Command { // Enforce ordering of command components boolean foundOptional = false; for (final CommandComponent component : this.components) { + if (component.getName().isEmpty()) { + throw new IllegalArgumentException("Component names may not be empty"); + } if (foundOptional && component.isRequired()) { throw new IllegalArgumentException( String.format("Command component '%s' cannot be placed after an optional component", diff --git a/commands-core/src/main/java/com/intellectualsites/commands/CommandManager.java b/commands-core/src/main/java/com/intellectualsites/commands/CommandManager.java index 086271fd..05a8e800 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/CommandManager.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/CommandManager.java @@ -147,4 +147,14 @@ public abstract class CommandManager { return Command.newBuilder(name); } + /** + * Get the internal command tree. This should not be accessed unless you know what you + * are doing + * + * @return Command tree + */ + @Nonnull CommandTree getCommandTree() { + return this.commandTree; + } + } diff --git a/commands-core/src/main/java/com/intellectualsites/commands/CommandTree.java b/commands-core/src/main/java/com/intellectualsites/commands/CommandTree.java index 1589b6d1..8d485889 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/CommandTree.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/CommandTree.java @@ -310,8 +310,8 @@ public class CommandTree { return sender.hasPermission(permission) ? null : permission; } if (node.isLeaf()) { - // noinspection all - return sender.hasPermission(node.value.getOwningCommand().getCommandPermission()) + return sender.hasPermission(Objects.requireNonNull(Objects.requireNonNull(node.value, "node.value").getOwningCommand(), + "owning command").getCommandPermission()) ? null : node.value.getOwningCommand().getCommandPermission(); } /* @@ -351,6 +351,7 @@ public class CommandTree { this.commandRegistrationHandler.registerCommand(leaf.getOwningCommand()); } }); + // Register command permissions this.getLeavesRaw(this.internalTree).forEach(node -> { /* All leaves must necessarily have an owning command */ @@ -362,11 +363,12 @@ public class CommandTree { chain = chain.subList(1, chain.size()); // Go through all nodes from the tail upwards until a collision occurs for (final Node> commandComponentNode : chain) { - if (commandComponentNode.nodeMeta.containsKey("permission")) { - commandComponentNode.nodeMeta.remove("permission"); - break; + if (commandComponentNode.nodeMeta.containsKey("permission") && !commandComponentNode.nodeMeta.get("permission") + .equalsIgnoreCase(node.nodeMeta.get("permission"))) { + commandComponentNode.nodeMeta.put("permission", ""); + } else { + commandComponentNode.nodeMeta.put("permission", node.nodeMeta.get("permission")); } - commandComponentNode.nodeMeta.put("permission", node.nodeMeta.get("permission")); } }); /* TODO: Figure out a way to register all combinations along a command component path */ @@ -477,13 +479,12 @@ public class CommandTree { return false; } final Node node = (Node) o; - return Objects.equals(getChildren(), node.getChildren()) && - Objects.equals(getValue(), node.getValue()); + return Objects.equals(getValue(), node.getValue()); } @Override public int hashCode() { - return Objects.hash(getChildren(), getValue()); + return Objects.hash(getValue()); } @Nullable @@ -495,6 +496,10 @@ public class CommandTree { this.parent = parent; } + @Override + public String toString() { + return "Node{value=" + value + '}'; + } } } diff --git a/commands-core/src/main/java/com/intellectualsites/commands/exceptions/NoPermissionException.java b/commands-core/src/main/java/com/intellectualsites/commands/exceptions/NoPermissionException.java index f655ad0c..3024dfc3 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/exceptions/NoPermissionException.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/exceptions/NoPermissionException.java @@ -54,5 +54,4 @@ public class NoPermissionException extends CommandParseException { return this.missingPermission; } - } diff --git a/commands-core/src/test/java/com/intellectualsites/commands/CommandTest.java b/commands-core/src/test/java/com/intellectualsites/commands/CommandTest.java new file mode 100644 index 00000000..19855fa0 --- /dev/null +++ b/commands-core/src/test/java/com/intellectualsites/commands/CommandTest.java @@ -0,0 +1,46 @@ +// +// MIT License +// +// Copyright (c) 2020 IntellectualSites +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package com.intellectualsites.commands; + +import com.intellectualsites.commands.components.StaticComponent; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class CommandTest { + + @Test() + void noComponents() { + Assertions.assertEquals(1, Command.newBuilder("test").build().getComponents().size()); + } + + @Test + void ensureOrdering() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + Command.newBuilder("test").withComponent(StaticComponent.optional("something")) + .withComponent(StaticComponent.required("somethingelse")).build()); + } + +} diff --git a/commands-core/src/test/java/com/intellectualsites/commands/CommandTreeTest.java b/commands-core/src/test/java/com/intellectualsites/commands/CommandTreeTest.java new file mode 100644 index 00000000..7b66835c --- /dev/null +++ b/commands-core/src/test/java/com/intellectualsites/commands/CommandTreeTest.java @@ -0,0 +1,78 @@ +// +// MIT License +// +// Copyright (c) 2020 IntellectualSites +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package com.intellectualsites.commands; + +import com.intellectualsites.commands.components.StaticComponent; +import com.intellectualsites.commands.context.CommandContext; +import com.intellectualsites.commands.exceptions.NoPermissionException; +import com.intellectualsites.commands.sender.CommandSender; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; + +class CommandTreeTest { + + private static CommandManager commandManager; + + @BeforeAll + static void newTree() { + commandManager = new TestCommandManager(); + commandManager.registerCommand(commandManager.commandBuilder("test") + .withComponent(StaticComponent.required("one")).build()) + .registerCommand(commandManager.commandBuilder("test") + .withComponent(StaticComponent.required("two")).withPermission("no").build()); + } + + @Test + void parse() { + final Optional> command = commandManager.getCommandTree().parse(new CommandContext<>(new TestCommandSender()), new LinkedList<>( + Arrays.asList("test", "one"))); + Assertions.assertTrue(command.isPresent()); + Assertions.assertThrows(NoPermissionException.class, () -> commandManager.getCommandTree().parse(new CommandContext<>(new TestCommandSender()), new LinkedList<>( + Arrays.asList("test", "two")))); + } + + @Test + void getSuggestions() { + } + + @Test + void testGetSuggestions() { + } + + @Test + void insertCommand() { + } + + @Test + void verifyAndRegister() { + } + +} diff --git a/commands-core/src/test/java/com/intellectualsites/commands/TestCommandManager.java b/commands-core/src/test/java/com/intellectualsites/commands/TestCommandManager.java new file mode 100644 index 00000000..3a12e15a --- /dev/null +++ b/commands-core/src/test/java/com/intellectualsites/commands/TestCommandManager.java @@ -0,0 +1,37 @@ +// +// MIT License +// +// Copyright (c) 2020 IntellectualSites +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package com.intellectualsites.commands; + +import com.intellectualsites.commands.execution.CommandExecutionCoordinator; +import com.intellectualsites.commands.internal.CommandRegistrationHandler; +import com.intellectualsites.commands.sender.CommandSender; + +public class TestCommandManager extends CommandManager { + + protected TestCommandManager() { + super(CommandExecutionCoordinator.simpleCoordinator(), CommandRegistrationHandler.NULL_COMMAND_REGISTRATION_HANDLER); + } + +} + diff --git a/commands-core/src/test/java/com/intellectualsites/commands/TestCommandSender.java b/commands-core/src/test/java/com/intellectualsites/commands/TestCommandSender.java new file mode 100644 index 00000000..9d42d069 --- /dev/null +++ b/commands-core/src/test/java/com/intellectualsites/commands/TestCommandSender.java @@ -0,0 +1,40 @@ +// +// MIT License +// +// Copyright (c) 2020 IntellectualSites +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package com.intellectualsites.commands; + +import com.intellectualsites.commands.sender.CommandSender; + +import javax.annotation.Nonnull; + +public class TestCommandSender implements CommandSender { + + @Override + public boolean hasPermission(@Nonnull final String permission) { + if (permission.equalsIgnoreCase("no")) { + return false; + } + return true; + } + +}