- Using e.g. Factory<Converter> instead of the injector directly makes its purpose more specific and disallows any future abuse of the injector's functions
303 lines
14 KiB
Java
303 lines
14 KiB
Java
package fr.xephi.authme.command;
|
|
|
|
import ch.jalu.injector.Injector;
|
|
import com.google.common.collect.Sets;
|
|
import fr.xephi.authme.command.TestCommandsUtil.TestLoginCommand;
|
|
import fr.xephi.authme.command.TestCommandsUtil.TestRegisterCommand;
|
|
import fr.xephi.authme.command.TestCommandsUtil.TestUnregisterCommand;
|
|
import fr.xephi.authme.command.help.HelpProvider;
|
|
import fr.xephi.authme.initialization.factory.Factory;
|
|
import fr.xephi.authme.message.MessageKey;
|
|
import fr.xephi.authme.message.Messages;
|
|
import fr.xephi.authme.permission.PermissionsManager;
|
|
import org.bukkit.command.CommandSender;
|
|
import org.junit.Before;
|
|
import org.junit.Test;
|
|
import org.junit.runner.RunWith;
|
|
import org.mockito.ArgumentCaptor;
|
|
import org.mockito.Mock;
|
|
import org.mockito.invocation.InvocationOnMock;
|
|
import org.mockito.junit.MockitoJUnitRunner;
|
|
import org.mockito.stubbing.Answer;
|
|
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
import static fr.xephi.authme.command.FoundResultStatus.INCORRECT_ARGUMENTS;
|
|
import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND;
|
|
import static fr.xephi.authme.command.FoundResultStatus.NO_PERMISSION;
|
|
import static fr.xephi.authme.command.FoundResultStatus.SUCCESS;
|
|
import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL;
|
|
import static java.util.Arrays.asList;
|
|
import static org.hamcrest.Matchers.containsString;
|
|
import static org.junit.Assert.assertThat;
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.ArgumentMatchers.anyList;
|
|
import static org.mockito.ArgumentMatchers.anyString;
|
|
import static org.mockito.ArgumentMatchers.eq;
|
|
import static org.mockito.BDDMockito.given;
|
|
import static org.mockito.Mockito.atLeastOnce;
|
|
import static org.mockito.Mockito.doReturn;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.never;
|
|
import static org.mockito.Mockito.times;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.hamcrest.MockitoHamcrest.argThat;
|
|
|
|
/**
|
|
* Test for {@link CommandHandler}.
|
|
*/
|
|
// Justification: It's more readable to use asList() everywhere in the test when we often generated two lists where one
|
|
// often consists of only one element, e.g. myMethod(asList("authme"), asList("my", "args"), ...)
|
|
@SuppressWarnings("ArraysAsListWithZeroOrOneArgument")
|
|
@RunWith(MockitoJUnitRunner.class)
|
|
public class CommandHandlerTest {
|
|
|
|
private CommandHandler handler;
|
|
|
|
@Mock
|
|
private Factory<ExecutableCommand> commandFactory;
|
|
@Mock
|
|
private CommandMapper commandMapper;
|
|
@Mock
|
|
private PermissionsManager permissionsManager;
|
|
@Mock
|
|
private Messages messages;
|
|
@Mock
|
|
private HelpProvider helpProvider;
|
|
|
|
private Map<Class<? extends ExecutableCommand>, ExecutableCommand> mockedCommands = new HashMap<>();
|
|
|
|
@Before
|
|
@SuppressWarnings("unchecked")
|
|
public void initializeCommandMapper() {
|
|
given(commandMapper.getCommandClasses()).willReturn(Sets.newHashSet(
|
|
ExecutableCommand.class, TestLoginCommand.class, TestRegisterCommand.class, TestUnregisterCommand.class));
|
|
setInjectorToMockExecutableCommandClasses();
|
|
|
|
handler = new CommandHandler(commandFactory, commandMapper, permissionsManager, messages, helpProvider);
|
|
}
|
|
|
|
/**
|
|
* Makes the injector return a mock when {@link Injector#newInstance(Class)} is invoked
|
|
* with (a child of) ExecutableCommand.class. The mocks the injector creates are stored in {@link #mockedCommands}.
|
|
* <p>
|
|
* The {@link CommandMapper} is mocked in {@link #initializeCommandMapper()} to return certain test classes.
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
private void setInjectorToMockExecutableCommandClasses() {
|
|
given(commandFactory.newInstance(any(Class.class))).willAnswer(new Answer<Object>() {
|
|
@Override
|
|
public Object answer(InvocationOnMock invocation) throws Throwable {
|
|
Class<?> clazz = invocation.getArgument(0);
|
|
if (ExecutableCommand.class.isAssignableFrom(clazz)) {
|
|
Class<? extends ExecutableCommand> commandClass = (Class<? extends ExecutableCommand>) clazz;
|
|
ExecutableCommand mock = mock(commandClass);
|
|
mockedCommands.put(commandClass, mock);
|
|
return mock;
|
|
}
|
|
throw new IllegalStateException("Unexpected class '" + clazz.getName()
|
|
+ "': Not a child of ExecutableCommand");
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
@Test
|
|
public void shouldCallMappedCommandWithArgs() {
|
|
// given
|
|
String bukkitLabel = "Authme";
|
|
String[] bukkitArgs = {"Login", "myPass"};
|
|
|
|
CommandSender sender = mock(CommandSender.class);
|
|
CommandDescription command = mock(CommandDescription.class);
|
|
doReturn(TestLoginCommand.class).when(command).getExecutableCommand();
|
|
given(commandMapper.mapPartsToCommand(any(CommandSender.class), anyList()))
|
|
.willReturn(new FoundCommandResult(command, asList("Authme", "Login"), asList("myPass"), 0.0, SUCCESS));
|
|
|
|
// when
|
|
handler.processCommand(sender, bukkitLabel, bukkitArgs);
|
|
|
|
// then
|
|
ExecutableCommand executableCommand = mockedCommands.get(TestLoginCommand.class);
|
|
verify(commandMapper).mapPartsToCommand(sender, asList("Authme", "Login", "myPass"));
|
|
verify(executableCommand).executeCommand(sender, asList("myPass"));
|
|
// Ensure that no error message was issued to the command sender
|
|
verify(sender, never()).sendMessage(anyString());
|
|
}
|
|
|
|
@Test
|
|
public void shouldNotCallExecutableCommandIfNoPermission() {
|
|
// given
|
|
String bukkitLabel = "unreg";
|
|
String[] bukkitArgs = {"testPlayer"};
|
|
CommandSender sender = mock(CommandSender.class);
|
|
CommandDescription command = mock(CommandDescription.class);
|
|
given(commandMapper.mapPartsToCommand(any(CommandSender.class), anyList()))
|
|
.willReturn(new FoundCommandResult(command, asList("unreg"), asList("testPlayer"), 0.0, NO_PERMISSION));
|
|
|
|
// when
|
|
handler.processCommand(sender, bukkitLabel, bukkitArgs);
|
|
|
|
// then
|
|
verify(commandMapper).mapPartsToCommand(sender, asList("unreg", "testPlayer"));
|
|
verify(command, never()).getExecutableCommand();
|
|
verify(messages).send(sender, MessageKey.NO_PERMISSION);
|
|
}
|
|
|
|
@Test
|
|
public void shouldNotCallExecutableForWrongArguments() {
|
|
// given
|
|
String bukkitLabel = "unreg";
|
|
String[] bukkitArgs = {"testPlayer"};
|
|
CommandSender sender = mock(CommandSender.class);
|
|
CommandDescription command = mock(CommandDescription.class);
|
|
given(command.getExecutableCommand()).willReturn((Class) TestUnregisterCommand.class);
|
|
given(commandMapper.mapPartsToCommand(any(CommandSender.class), anyList())).willReturn(
|
|
new FoundCommandResult(command, asList("unreg"), asList("testPlayer"), 0.0, INCORRECT_ARGUMENTS));
|
|
given(permissionsManager.hasPermission(sender, command.getPermission())).willReturn(true);
|
|
|
|
// when
|
|
handler.processCommand(sender, bukkitLabel, bukkitArgs);
|
|
|
|
// then
|
|
verify(commandMapper).mapPartsToCommand(sender, asList("unreg", "testPlayer"));
|
|
verify(sender, atLeastOnce()).sendMessage(argThat(containsString("Incorrect command arguments")));
|
|
}
|
|
|
|
@Test
|
|
public void shouldUseCustomMessageUponArgumentMismatch() {
|
|
// given
|
|
String bukkitLabel = "unreg";
|
|
String[] bukkitArgs = {"testPlayer"};
|
|
CommandSender sender = mock(CommandSender.class);
|
|
CommandDescription command = mock(CommandDescription.class);
|
|
given(command.getExecutableCommand()).willReturn((Class) TestUnregisterCommand.class);
|
|
given(mockedCommands.get(TestUnregisterCommand.class).getArgumentsMismatchMessage())
|
|
.willReturn(MessageKey.USAGE_RECOVER_EMAIL);
|
|
given(commandMapper.mapPartsToCommand(any(CommandSender.class), anyList())).willReturn(
|
|
new FoundCommandResult(command, asList("unreg"), asList("testPlayer"), 0.0, INCORRECT_ARGUMENTS));
|
|
given(permissionsManager.hasPermission(sender, command.getPermission())).willReturn(true);
|
|
|
|
// when
|
|
handler.processCommand(sender, bukkitLabel, bukkitArgs);
|
|
|
|
// then
|
|
verify(commandMapper).mapPartsToCommand(sender, asList("unreg", "testPlayer"));
|
|
verify(messages).send(sender, MessageKey.USAGE_RECOVER_EMAIL);
|
|
verify(sender, never()).sendMessage(anyString());
|
|
}
|
|
|
|
@Test
|
|
public void shouldNotCallExecutableForWrongArgumentsAndPermissionDenied() {
|
|
// given
|
|
String bukkitLabel = "unreg";
|
|
String[] bukkitArgs = {"testPlayer"};
|
|
CommandSender sender = mock(CommandSender.class);
|
|
CommandDescription command = mock(CommandDescription.class);
|
|
given(commandMapper.mapPartsToCommand(any(CommandSender.class), anyList())).willReturn(
|
|
new FoundCommandResult(command, asList("unreg"), asList("testPlayer"), 0.0, INCORRECT_ARGUMENTS));
|
|
given(permissionsManager.hasPermission(sender, command.getPermission())).willReturn(false);
|
|
|
|
// when
|
|
handler.processCommand(sender, bukkitLabel, bukkitArgs);
|
|
|
|
// then
|
|
verify(commandMapper).mapPartsToCommand(sender, asList("unreg", "testPlayer"));
|
|
verify(command, never()).getExecutableCommand();
|
|
verify(messages).send(sender, MessageKey.NO_PERMISSION);
|
|
}
|
|
|
|
@Test
|
|
public void shouldNotCallExecutableForFailedParsing() {
|
|
// given
|
|
String bukkitLabel = "unreg";
|
|
String[] bukkitArgs = {"testPlayer"};
|
|
CommandSender sender = mock(CommandSender.class);
|
|
CommandDescription command = mock(CommandDescription.class);
|
|
given(commandMapper.mapPartsToCommand(any(CommandSender.class), anyList())).willReturn(
|
|
new FoundCommandResult(command, asList("unreg"), asList("testPlayer"), 0.0, MISSING_BASE_COMMAND));
|
|
|
|
// when
|
|
handler.processCommand(sender, bukkitLabel, bukkitArgs);
|
|
|
|
// then
|
|
verify(commandMapper).mapPartsToCommand(sender, asList("unreg", "testPlayer"));
|
|
verify(command, never()).getExecutableCommand();
|
|
verify(sender).sendMessage(argThat(containsString("Failed to parse")));
|
|
}
|
|
|
|
@Test
|
|
public void shouldNotCallExecutableForUnknownLabelAndHaveSuggestion() {
|
|
// given
|
|
String bukkitLabel = "unreg";
|
|
String[] bukkitArgs = {"testPlayer"};
|
|
CommandSender sender = mock(CommandSender.class);
|
|
CommandDescription command = mock(CommandDescription.class);
|
|
given(command.getLabels()).willReturn(Collections.singletonList("test_cmd"));
|
|
given(commandMapper.mapPartsToCommand(any(CommandSender.class), anyList())).willReturn(
|
|
new FoundCommandResult(command, asList("unreg"), asList("testPlayer"), 0.01, UNKNOWN_LABEL));
|
|
|
|
// when
|
|
handler.processCommand(sender, bukkitLabel, bukkitArgs);
|
|
|
|
// then
|
|
verify(commandMapper).mapPartsToCommand(sender, asList("unreg", "testPlayer"));
|
|
verify(command, never()).getExecutableCommand();
|
|
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
|
verify(sender, times(3)).sendMessage(captor.capture());
|
|
assertThat(captor.getAllValues().get(0), containsString("Unknown command"));
|
|
assertThat(captor.getAllValues().get(1), containsString("Did you mean"));
|
|
assertThat(captor.getAllValues().get(1), containsString("/test_cmd"));
|
|
assertThat(captor.getAllValues().get(2), containsString("Use the command"));
|
|
assertThat(captor.getAllValues().get(2), containsString("to view help"));
|
|
}
|
|
|
|
@Test
|
|
public void shouldNotCallExecutableForUnknownLabelAndNotSuggestCommand() {
|
|
// given
|
|
String bukkitLabel = "unreg";
|
|
String[] bukkitArgs = {"testPlayer"};
|
|
CommandSender sender = mock(CommandSender.class);
|
|
CommandDescription command = mock(CommandDescription.class);
|
|
given(commandMapper.mapPartsToCommand(any(CommandSender.class), anyList())).willReturn(
|
|
new FoundCommandResult(command, asList("unreg"), asList("testPlayer"), 1.0, UNKNOWN_LABEL));
|
|
|
|
// when
|
|
handler.processCommand(sender, bukkitLabel, bukkitArgs);
|
|
|
|
// then
|
|
verify(commandMapper).mapPartsToCommand(sender, asList("unreg", "testPlayer"));
|
|
verify(command, never()).getExecutableCommand();
|
|
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
|
verify(sender, times(2)).sendMessage(captor.capture());
|
|
assertThat(captor.getAllValues().get(0), containsString("Unknown command"));
|
|
assertThat(captor.getAllValues().get(1), containsString("Use the command"));
|
|
assertThat(captor.getAllValues().get(1), containsString("to view help"));
|
|
}
|
|
|
|
@Test
|
|
public void shouldStripWhitespace() {
|
|
// given
|
|
String bukkitLabel = "AuthMe";
|
|
String[] bukkitArgs = {" ", "", "REGISTER", " ", "testArg", " "};
|
|
CommandSender sender = mock(CommandSender.class);
|
|
|
|
CommandDescription command = mock(CommandDescription.class);
|
|
doReturn(TestRegisterCommand.class).when(command).getExecutableCommand();
|
|
given(commandMapper.mapPartsToCommand(eq(sender), anyList()))
|
|
.willReturn(new FoundCommandResult(command, asList("AuthMe", "REGISTER"), asList("testArg"), 0.0, SUCCESS));
|
|
|
|
// when
|
|
handler.processCommand(sender, bukkitLabel, bukkitArgs);
|
|
|
|
// then
|
|
ExecutableCommand executableCommand = mockedCommands.get(TestRegisterCommand.class);
|
|
verify(commandMapper).mapPartsToCommand(sender, asList("AuthMe", "REGISTER", "testArg"));
|
|
verify(executableCommand).executeCommand(sender, asList("testArg"));
|
|
verify(sender, never()).sendMessage(anyString());
|
|
}
|
|
|
|
}
|