diff --git a/core/src/test/java/co/aikar/commands/CommandManagerTests.java b/core/src/test/java/co/aikar/commands/CommandManagerTests.java new file mode 100644 index 00000000..c620dd70 --- /dev/null +++ b/core/src/test/java/co/aikar/commands/CommandManagerTests.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License + * + * 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 co.aikar.commands; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +public class CommandManagerTests { + + @Spy + private TestCommandSender sender; + + private TestCommandManager manager; + + @BeforeEach + public void initEach() { + manager = new TestCommandManager(); + manager.registerCommand(new EchoCommand()); + } + + @Test + public void echoCommandSendsMessageArgument() { + manager.dispatchCommand(sender, "echo this is a test"); + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(String.class); + verify(sender).sendMessage(argumentCaptor.capture()); + assertEquals("this is a test", argumentCaptor.getValue()); + } +} diff --git a/core/src/test/java/co/aikar/commands/EchoCommand.java b/core/src/test/java/co/aikar/commands/EchoCommand.java new file mode 100644 index 00000000..87d851b9 --- /dev/null +++ b/core/src/test/java/co/aikar/commands/EchoCommand.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License + * + * 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 co.aikar.commands; + +import co.aikar.commands.annotation.CommandAlias; +import co.aikar.commands.annotation.Default; + +@CommandAlias("echo") +public class EchoCommand extends BaseCommand { + + @Default + public void onCommand(TestCommandSender sender, String message) { + sender.sendMessage(message); + } +} diff --git a/core/src/test/java/co/aikar/commands/TestCommandContexts.java b/core/src/test/java/co/aikar/commands/TestCommandContexts.java new file mode 100644 index 00000000..00e7a4cf --- /dev/null +++ b/core/src/test/java/co/aikar/commands/TestCommandContexts.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License + * + * 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 co.aikar.commands; + +public class TestCommandContexts extends CommandContexts { + + public TestCommandContexts(CommandManager manager) { + super(manager); + registerIssuerOnlyContext(TestCommandSender.class, c -> c.getIssuer().getIssuer()); + } +} diff --git a/core/src/test/java/co/aikar/commands/TestCommandExecutionContext.java b/core/src/test/java/co/aikar/commands/TestCommandExecutionContext.java new file mode 100644 index 00000000..f75a5984 --- /dev/null +++ b/core/src/test/java/co/aikar/commands/TestCommandExecutionContext.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License + * + * 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 co.aikar.commands; + +import java.util.List; +import java.util.Map; + +public class TestCommandExecutionContext extends CommandExecutionContext { + + public TestCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, TestCommandIssuer sender, List args, int index, Map passedArgs) { + super(cmd, param, sender, args, index, passedArgs); + } +} diff --git a/core/src/test/java/co/aikar/commands/TestCommandIssuer.java b/core/src/test/java/co/aikar/commands/TestCommandIssuer.java new file mode 100644 index 00000000..fc466138 --- /dev/null +++ b/core/src/test/java/co/aikar/commands/TestCommandIssuer.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License + * + * 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 co.aikar.commands; + +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class TestCommandIssuer implements CommandIssuer { + + private final TestCommandManager manager; + private final TestCommandSender issuer; + + public TestCommandIssuer(TestCommandManager manager, TestCommandSender issuer) { + this.manager = manager; + this.issuer = issuer; + } + + @Override + public TestCommandSender getIssuer() { + return issuer; + } + + @Override + public TestCommandManager getManager() { + return manager; + } + + @Override + public boolean isPlayer() { + return false; + } + + @Override + public @NotNull UUID getUniqueId() { + return issuer.getUuid(); + } + + @Override + public boolean hasPermission(String permission) { + return issuer.hasPermission(permission); + } + + @Override + public void sendMessageInternal(String message) { + issuer.sendMessage(message); + } +} diff --git a/core/src/test/java/co/aikar/commands/TestCommandManager.java b/core/src/test/java/co/aikar/commands/TestCommandManager.java new file mode 100644 index 00000000..98f8dee5 --- /dev/null +++ b/core/src/test/java/co/aikar/commands/TestCommandManager.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License + * + * 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 co.aikar.commands; + +import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class TestCommandManager extends CommandManager< + TestCommandSender, + TestCommandIssuer, + String, + MessageFormatter, + TestCommandExecutionContext, + TestConditionContext> { + + private final Logger logger = Logger.getLogger(this.getClass().getSimpleName()); + private final Map commands = new HashMap<>(); + private final CommandCompletions> completions = new CommandCompletions<>(this); + + protected TestCommandContexts contexts; + protected Locales locales; + + @Override + public CommandContexts getCommandContexts() { + if (contexts == null) { + contexts = new TestCommandContexts(this); + } + return contexts; + } + + @Override + public CommandCompletions getCommandCompletions() { + return completions; + } + + @Override + public void registerCommand(BaseCommand command) { + command.onRegister(this); + for (Map.Entry entry : command.registeredCommands.entrySet()) { + String commandName = entry.getKey().toLowerCase(); + TestRootCommand cmd = (TestRootCommand) entry.getValue(); + if (!cmd.isRegistered) { + cmd.isRegistered = true; + commands.put(commandName, cmd); + } + } + } + + public void unregisterCommand(BaseCommand command) { + for (Map.Entry entry : command.registeredCommands.entrySet()) { + String jdaCommandName = entry.getKey().toLowerCase(); + TestRootCommand jdaCommand = (TestRootCommand) entry.getValue(); + jdaCommand.getSubCommands().values().removeAll(command.subCommands.values()); + if (jdaCommand.isRegistered && jdaCommand.getSubCommands().isEmpty()) { + jdaCommand.isRegistered = false; + commands.remove(jdaCommandName); + } + } + } + + @Override + public boolean hasRegisteredCommands() { + return !commands.isEmpty(); + } + + @Override + public boolean isCommandIssuer(Class type) { + return TestCommandIssuer.class.isAssignableFrom(type); + } + + @Override + public TestCommandIssuer getCommandIssuer(Object issuer) { + if (!(issuer instanceof TestCommandSender)) { + throw new IllegalArgumentException(issuer.getClass().getName() + " is not a TestCommandSender."); + } + return new TestCommandIssuer(this, (TestCommandSender) issuer); + } + + @Override + public RootCommand createRootCommand(String cmd) { + return new TestRootCommand(this, cmd); + } + + @Override + public Locales getLocales() { + if (locales == null) { + locales = new Locales(this); + locales.loadLanguages(); + } + return locales; + } + + @Override + public CommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { + return new TestCommandExecutionContext(command, parameter, (TestCommandIssuer) sender, args, i, passedArgs); + } + + @Override + public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) { + return new CommandCompletionContext(command, sender, input, config, args); + } + + @Override + public void log(LogLevel level, String message, Throwable throwable) { + Level logLevel = level == LogLevel.INFO ? Level.INFO : Level.SEVERE; + logger.log(logLevel, LogLevel.LOG_PREFIX + message); + if (throwable != null) { + for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) { + logger.log(logLevel, LogLevel.LOG_PREFIX + line); + } + } + } + + @Override + public Collection getRegisteredRootCommands() { + return Collections.unmodifiableCollection(commands.values()); + } + + public void dispatchCommand(TestCommandSender sender, String command) { + String[] args = ACFPatterns.SPACE.split(command, -1); + if (args.length == 0) { + return; + } + String cmd = args[0].toLowerCase(); + TestRootCommand rootCommand = commands.get(cmd); + if (rootCommand == null) { + return; + } + if (args.length > 1) { + args = Arrays.copyOfRange(args, 1, args.length); + } else { + args = new String[0]; + } + rootCommand.execute(this.getCommandIssuer(sender), cmd, args); + } +} diff --git a/core/src/test/java/co/aikar/commands/TestCommandSender.java b/core/src/test/java/co/aikar/commands/TestCommandSender.java new file mode 100644 index 00000000..e180f971 --- /dev/null +++ b/core/src/test/java/co/aikar/commands/TestCommandSender.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License + * + * 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 co.aikar.commands; + +import java.util.UUID; + +/** + * Simple command sender. Use with {@link org.mockito.Mockito#spy(Object)} or {@link org.mockito.Spy}. + */ +public class TestCommandSender { + + private final UUID uuid = UUID.randomUUID(); + + UUID getUuid() { + return uuid; + } + + public boolean hasPermission(String permission) { + return false; + } + + public void sendMessage(String message) { + } +} diff --git a/core/src/test/java/co/aikar/commands/TestConditionContext.java b/core/src/test/java/co/aikar/commands/TestConditionContext.java new file mode 100644 index 00000000..aa72e7b9 --- /dev/null +++ b/core/src/test/java/co/aikar/commands/TestConditionContext.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License + * + * 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 co.aikar.commands; + +public class TestConditionContext extends ConditionContext { + public TestConditionContext(TestCommandIssuer issuer, String config) { + super(issuer, config); + } +} diff --git a/core/src/test/java/co/aikar/commands/TestRootCommand.java b/core/src/test/java/co/aikar/commands/TestRootCommand.java new file mode 100644 index 00000000..5167dd38 --- /dev/null +++ b/core/src/test/java/co/aikar/commands/TestRootCommand.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License + * + * 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 co.aikar.commands; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.SetMultimap; + +import java.util.ArrayList; +import java.util.List; + +public class TestRootCommand implements RootCommand { + + private final String name; + boolean isRegistered = false; + private TestCommandManager manager; + private BaseCommand defCommand; + private SetMultimap subCommands = HashMultimap.create(); + private List children = new ArrayList<>(); + + TestRootCommand(TestCommandManager manager, String name) { + this.manager = manager; + this.name = name; + } + + @Override + + public void addChild(BaseCommand command) { + if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) { + this.defCommand = command; + } + addChildShared(this.children, this.subCommands, command); + } + + @Override + public CommandManager getManager() { + return this.manager; + } + + @Override + public SetMultimap getSubCommands() { + return this.subCommands; + } + + @Override + public List getChildren() { + return this.children; + } + + @Override + public String getCommandName() { + return this.name; + } + + @Override + public BaseCommand getDefCommand() { + return defCommand; + } +} diff --git a/pom.xml b/pom.xml index bb14d5e9..be8fa889 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,9 @@ UTF-8 + 5.4.0 + 1.4.0 + 2.25.1 @@ -71,6 +74,10 @@ + + maven-surefire-plugin + 2.22.1 + org.apache.maven.plugins maven-source-plugin @@ -139,6 +146,37 @@ 15.0 provided + + + org.junit.jupiter + junit-jupiter-api + ${junit.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit.version} + test + + + org.junit.jupiter + junit-jupiter-params + ${junit.version} + test + + + org.mockito + mockito-core + ${mockito.version} + test + + + org.mockito + mockito-junit-jupiter + ${mockito.version} + test +