From 89c70ff447fb0a08290221418bc7a0f76afc1eb8 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sun, 29 Jan 2017 13:54:37 +0100 Subject: [PATCH] #1026 Add more tags for forced commands (lazily replaced) (#214) * #1026 Add more tags for forced commands (lazily replaced) - Extract lazy replacement of tags to its own class - Implement wrapper to replace a String property within an object - Use wrapper in command manager and add new tags * Make argument type generic in lazy tags util --- .../settings/WelcomeMessageConfiguration.java | 59 +----- .../commandconfig/CommandManager.java | 43 +++- .../{PlayerTag.java => DependentTag.java} | 16 +- .../xephi/authme/util/lazytags/SimpleTag.java | 10 +- .../fr/xephi/authme/util/lazytags/Tag.java | 14 +- .../authme/util/lazytags/TagBuilder.java | 10 +- .../authme/util/lazytags/TagReplacer.java | 102 ++++++++++ .../util/lazytags/WrappedTagReplacer.java | 61 ++++++ .../commandconfig/CommandManagerTest.java | 188 +++++++++--------- .../filegeneration/GenerateCommandsYml.java | 9 +- .../commandconfig/commands.complete.yml | 4 +- .../commandconfig/commands.incomplete.yml | 2 +- 12 files changed, 329 insertions(+), 189 deletions(-) rename src/main/java/fr/xephi/authme/util/lazytags/{PlayerTag.java => DependentTag.java} (56%) create mode 100644 src/main/java/fr/xephi/authme/util/lazytags/TagReplacer.java create mode 100644 src/main/java/fr/xephi/authme/util/lazytags/WrappedTagReplacer.java diff --git a/src/main/java/fr/xephi/authme/settings/WelcomeMessageConfiguration.java b/src/main/java/fr/xephi/authme/settings/WelcomeMessageConfiguration.java index 8fcb2163..60666f7a 100644 --- a/src/main/java/fr/xephi/authme/settings/WelcomeMessageConfiguration.java +++ b/src/main/java/fr/xephi/authme/settings/WelcomeMessageConfiguration.java @@ -8,6 +8,7 @@ import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.service.GeoIpService; import fr.xephi.authme.util.PlayerUtils; import fr.xephi.authme.util.lazytags.Tag; +import fr.xephi.authme.util.lazytags.TagReplacer; import org.bukkit.Server; import org.bukkit.entity.Player; @@ -19,9 +20,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Arrays; import java.util.Collections; -import java.util.LinkedList; import java.util.List; -import java.util.stream.Collectors; import static fr.xephi.authme.util.FileUtils.copyFileFromResource; import static fr.xephi.authme.util.lazytags.TagBuilder.createTag; @@ -48,7 +47,7 @@ public class WelcomeMessageConfiguration implements Reloadable { private PlayerCache playerCache; /** List of all supported tags for the welcome message. */ - private final List availableTags = Arrays.asList( + private final List> availableTags = Arrays.asList( createTag("&", () -> "\u00a7"), createTag("{PLAYER}", pl -> pl.getName()), createTag("{ONLINE}", () -> Integer.toString(bukkitService.getOnlinePlayers().size())), @@ -60,16 +59,13 @@ public class WelcomeMessageConfiguration implements Reloadable { createTag("{VERSION}", () -> server.getBukkitVersion()), createTag("{COUNTRY}", pl -> geoIpService.getCountryName(PlayerUtils.getPlayerIp(pl)))); - /** Welcome message, by lines. */ - private List welcomeMessage; - /** Tags used in the welcome message. */ - private List usedTags; + private TagReplacer messageSupplier; @PostConstruct @Override public void reload() { - welcomeMessage = readWelcomeFile(); - usedTags = determineUsedTags(welcomeMessage); + List welcomeMessage = readWelcomeFile(); + messageSupplier = TagReplacer.newReplacer(availableTags, welcomeMessage); } /** @@ -79,22 +75,7 @@ public class WelcomeMessageConfiguration implements Reloadable { * @return the welcome message */ public List getWelcomeMessage(Player player) { - // Note ljacqu 20170121: Using a Map might seem more natural here but we avoid doing so for performance - // Although the performance gain here is probably minimal... - List tagValues = new LinkedList<>(); - for (Tag tag : usedTags) { - tagValues.add(new TagValue(tag.getName(), tag.getValue(player))); - } - - List adaptedMessages = new LinkedList<>(); - for (String line : welcomeMessage) { - String adaptedLine = line; - for (TagValue tagValue : tagValues) { - adaptedLine = adaptedLine.replace(tagValue.tag, tagValue.value); - } - adaptedMessages.add(adaptedLine); - } - return adaptedMessages; + return messageSupplier.getAdaptedMessages(player); } /** @@ -113,32 +94,4 @@ public class WelcomeMessageConfiguration implements Reloadable { } return Collections.emptyList(); } - - /** - * Determines which tags are used in the message. - * - * @param welcomeMessage the lines of the welcome message - * @return the tags - */ - private List determineUsedTags(List welcomeMessage) { - return availableTags.stream() - .filter(tag -> welcomeMessage.stream().anyMatch(msg -> msg.contains(tag.getName()))) - .collect(Collectors.toList()); - } - - private static final class TagValue { - - private final String tag; - private final String value; - - TagValue(String tag, String value) { - this.tag = tag; - this.value = value; - } - - @Override - public String toString() { - return "TagValue[tag='" + tag + "', value='" + value + "']"; - } - } } diff --git a/src/main/java/fr/xephi/authme/settings/commandconfig/CommandManager.java b/src/main/java/fr/xephi/authme/settings/commandconfig/CommandManager.java index bc0abf38..d87ebd5e 100644 --- a/src/main/java/fr/xephi/authme/settings/commandconfig/CommandManager.java +++ b/src/main/java/fr/xephi/authme/settings/commandconfig/CommandManager.java @@ -5,13 +5,21 @@ import ch.jalu.configme.resource.YamlFileResource; import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.Reloadable; import fr.xephi.authme.service.BukkitService; +import fr.xephi.authme.service.GeoIpService; import fr.xephi.authme.util.FileUtils; +import fr.xephi.authme.util.PlayerUtils; +import fr.xephi.authme.util.lazytags.Tag; +import fr.xephi.authme.util.lazytags.WrappedTagReplacer; import org.bukkit.entity.Player; import javax.inject.Inject; import java.io.File; +import java.util.Arrays; +import java.util.List; import java.util.Map; +import static fr.xephi.authme.util.lazytags.TagBuilder.createTag; + /** * Manages configurable commands to be run when various events occur. */ @@ -19,15 +27,20 @@ public class CommandManager implements Reloadable { private final File dataFolder; private final BukkitService bukkitService; + private final GeoIpService geoIpService; private final CommandMigrationService commandMigrationService; + private final List> availableTags = buildAvailableTags(); - private CommandConfig commandConfig; + private WrappedTagReplacer onJoinCommands; + private WrappedTagReplacer onLoginCommands; + private WrappedTagReplacer onRegisterCommands; @Inject - CommandManager(@DataFolder File dataFolder, BukkitService bukkitService, + CommandManager(@DataFolder File dataFolder, BukkitService bukkitService, GeoIpService geoIpService, CommandMigrationService commandMigrationService) { this.dataFolder = dataFolder; this.bukkitService = bukkitService; + this.geoIpService = geoIpService; this.commandMigrationService = commandMigrationService; reload(); } @@ -38,7 +51,7 @@ public class CommandManager implements Reloadable { * @param player the joining player */ public void runCommandsOnJoin(Player player) { - executeCommands(player, commandConfig.getOnJoin()); + executeCommands(player, onJoinCommands.getAdaptedItems(player)); } /** @@ -47,7 +60,7 @@ public class CommandManager implements Reloadable { * @param player the player who has registered */ public void runCommandsOnRegister(Player player) { - executeCommands(player, commandConfig.getOnRegister()); + executeCommands(player, onRegisterCommands.getAdaptedItems(player)); } /** @@ -56,11 +69,11 @@ public class CommandManager implements Reloadable { * @param player the player that logged in */ public void runCommandsOnLogin(Player player) { - executeCommands(player, commandConfig.getOnLogin()); + executeCommands(player, onLoginCommands.getAdaptedItems(player)); } - private void executeCommands(Player player, Map commands) { - for (Command command : commands.values()) { + private void executeCommands(Player player, List commands) { + for (Command command : commands) { final String execution = command.getCommand().replace("%p", player.getName()); if (Executor.CONSOLE.equals(command.getExecutor())) { bukkitService.dispatchConsoleCommand(execution); @@ -77,8 +90,22 @@ public class CommandManager implements Reloadable { SettingsManager settingsManager = new SettingsManager( new YamlFileResource(file), commandMigrationService, CommandSettingsHolder.class); - commandConfig = settingsManager.getProperty(CommandSettingsHolder.COMMANDS); + CommandConfig commandConfig = settingsManager.getProperty(CommandSettingsHolder.COMMANDS); + onJoinCommands = newReplacer(commandConfig.getOnJoin()); + onLoginCommands = newReplacer(commandConfig.getOnLogin()); + onRegisterCommands = newReplacer(commandConfig.getOnRegister()); } + private WrappedTagReplacer newReplacer(Map commands) { + return new WrappedTagReplacer<>(availableTags, commands.values(), Command::getCommand, + (cmd, text) -> new Command(text, cmd.getExecutor())); + } + private List> buildAvailableTags() { + return Arrays.asList( + createTag("%p", pl -> pl.getName()), + createTag("%nick", pl -> pl.getDisplayName()), + createTag("%ip", pl -> PlayerUtils.getPlayerIp(pl)), + createTag("%country", pl -> geoIpService.getCountryName(PlayerUtils.getPlayerIp(pl)))); + } } diff --git a/src/main/java/fr/xephi/authme/util/lazytags/PlayerTag.java b/src/main/java/fr/xephi/authme/util/lazytags/DependentTag.java similarity index 56% rename from src/main/java/fr/xephi/authme/util/lazytags/PlayerTag.java rename to src/main/java/fr/xephi/authme/util/lazytags/DependentTag.java index 3c476237..5fb0cd3d 100644 --- a/src/main/java/fr/xephi/authme/util/lazytags/PlayerTag.java +++ b/src/main/java/fr/xephi/authme/util/lazytags/DependentTag.java @@ -1,16 +1,16 @@ package fr.xephi.authme.util.lazytags; -import org.bukkit.entity.Player; - import java.util.function.Function; /** - * Replaceable tag whose value depends on the player. + * Replaceable tag whose value depends on an argument. + * + * @param the argument type */ -public class PlayerTag implements Tag { +public class DependentTag implements Tag { private final String name; - private final Function replacementFunction; + private final Function replacementFunction; /** * Constructor. @@ -18,7 +18,7 @@ public class PlayerTag implements Tag { * @param name the tag (placeholder) that will be replaced * @param replacementFunction the function producing the replacement */ - public PlayerTag(String name, Function replacementFunction) { + public DependentTag(String name, Function replacementFunction) { this.name = name; this.replacementFunction = replacementFunction; } @@ -29,7 +29,7 @@ public class PlayerTag implements Tag { } @Override - public String getValue(Player player) { - return replacementFunction.apply(player); + public String getValue(A argument) { + return replacementFunction.apply(argument); } } diff --git a/src/main/java/fr/xephi/authme/util/lazytags/SimpleTag.java b/src/main/java/fr/xephi/authme/util/lazytags/SimpleTag.java index 08ece1c3..a5bb58a2 100644 --- a/src/main/java/fr/xephi/authme/util/lazytags/SimpleTag.java +++ b/src/main/java/fr/xephi/authme/util/lazytags/SimpleTag.java @@ -1,13 +1,13 @@ package fr.xephi.authme.util.lazytags; -import org.bukkit.entity.Player; - import java.util.function.Supplier; /** - * Tag to be replaced that does not depend on the player. + * Tag to be replaced that does not depend on an argument. + * + * @param type of the argument (not used in this implementation) */ -public class SimpleTag implements Tag { +public class SimpleTag implements Tag { private final String name; private final Supplier replacementFunction; @@ -23,7 +23,7 @@ public class SimpleTag implements Tag { } @Override - public String getValue(Player player) { + public String getValue(A argument) { return replacementFunction.get(); } } diff --git a/src/main/java/fr/xephi/authme/util/lazytags/Tag.java b/src/main/java/fr/xephi/authme/util/lazytags/Tag.java index 5129777d..2c7c6ba5 100644 --- a/src/main/java/fr/xephi/authme/util/lazytags/Tag.java +++ b/src/main/java/fr/xephi/authme/util/lazytags/Tag.java @@ -1,11 +1,11 @@ package fr.xephi.authme.util.lazytags; -import org.bukkit.entity.Player; - /** - * Represents a tag in a text to be replaced with a value (which may depend on the Player). + * Represents a tag in a text to be replaced with a value (which may depend on some argument). + * + * @param argument type the replacement may depend on */ -public interface Tag { +public interface Tag { /** * @return the tag to replace @@ -13,10 +13,10 @@ public interface Tag { String getName(); /** - * Returns the value to replace the tag with for the given player. + * Returns the value to replace the tag with for the given argument. * - * @param player the player to evaluate the replacement for + * @param argument the argument to evaluate the replacement for * @return the replacement */ - String getValue(Player player); + String getValue(A argument); } diff --git a/src/main/java/fr/xephi/authme/util/lazytags/TagBuilder.java b/src/main/java/fr/xephi/authme/util/lazytags/TagBuilder.java index dc8eaef9..677b30e2 100644 --- a/src/main/java/fr/xephi/authme/util/lazytags/TagBuilder.java +++ b/src/main/java/fr/xephi/authme/util/lazytags/TagBuilder.java @@ -1,7 +1,5 @@ package fr.xephi.authme.util.lazytags; -import org.bukkit.entity.Player; - import java.util.function.Function; import java.util.function.Supplier; @@ -13,11 +11,11 @@ public final class TagBuilder { private TagBuilder() { } - public static Tag createTag(String name, Function replacementFunction) { - return new PlayerTag(name, replacementFunction); + public static Tag createTag(String name, Function replacementFunction) { + return new DependentTag<>(name, replacementFunction); } - public static Tag createTag(String name, Supplier replacementFunction) { - return new SimpleTag(name, replacementFunction); + public static Tag createTag(String name, Supplier replacementFunction) { + return new SimpleTag<>(name, replacementFunction); } } diff --git a/src/main/java/fr/xephi/authme/util/lazytags/TagReplacer.java b/src/main/java/fr/xephi/authme/util/lazytags/TagReplacer.java new file mode 100644 index 00000000..660132fb --- /dev/null +++ b/src/main/java/fr/xephi/authme/util/lazytags/TagReplacer.java @@ -0,0 +1,102 @@ +package fr.xephi.authme.util.lazytags; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Replaces tags lazily by first determining which tags are being used + * and only applying those replacements afterwards. + * + * @param the argument type + */ +public class TagReplacer { + + private final List> tags; + private final Collection messages; + + /** + * Private constructor. Use {@link #newReplacer(Collection, Collection)}. + * + * @param tags the tags that are being used in the messages + * @param messages the messages + */ + private TagReplacer(List> tags, Collection messages) { + this.tags = tags; + this.messages = messages; + } + + /** + * Creates a new instance of this class, which will provide the given + * messages adapted with the provided tags. + * + * @param allTags all available tags + * @param messages the messages to use + * @param the argument type + * @return new tag replacer instance + */ + public static TagReplacer newReplacer(Collection> allTags, Collection messages) { + List> usedTags = determineUsedTags(allTags, messages); + return new TagReplacer<>(usedTags, messages); + } + + /** + * Returns the messages with the tags applied for the given argument. + * + * @param argument the argument to get the messages for + * @return the adapted messages + */ + public List getAdaptedMessages(A argument) { + // Note ljacqu 20170121: Using a Map might seem more natural here but we avoid doing so for performance + // Although the performance gain here is probably minimal... + List tagValues = new LinkedList<>(); + for (Tag tag : tags) { + tagValues.add(new TagValue(tag.getName(), tag.getValue(argument))); + } + + List adaptedMessages = new LinkedList<>(); + for (String line : messages) { + String adaptedLine = line; + for (TagValue tagValue : tagValues) { + adaptedLine = adaptedLine.replace(tagValue.tag, tagValue.value); + } + adaptedMessages.add(adaptedLine); + } + return adaptedMessages; + } + + /** + * Determines which tags are used somewhere in the given list of messages. + * + * @param allTags all available tags + * @param messages the messages + * @param argument type + * @return tags used at least once + */ + private static List> determineUsedTags(Collection> allTags, Collection messages) { + return allTags.stream() + .filter(tag -> messages.stream().anyMatch(msg -> msg.contains(tag.getName()))) + .collect(Collectors.toList()); + } + + /** (Tag, value) pair. */ + private static final class TagValue { + + /** The tag to replace. */ + private final String tag; + /** The value to replace with. */ + private final String value; + + TagValue(String tag, String value) { + this.tag = tag; + this.value = value; + } + + @Override + public String toString() { + return "TagValue[tag='" + tag + "', value='" + value + "']"; + } + } + +} diff --git a/src/main/java/fr/xephi/authme/util/lazytags/WrappedTagReplacer.java b/src/main/java/fr/xephi/authme/util/lazytags/WrappedTagReplacer.java new file mode 100644 index 00000000..92c3f70d --- /dev/null +++ b/src/main/java/fr/xephi/authme/util/lazytags/WrappedTagReplacer.java @@ -0,0 +1,61 @@ +package fr.xephi.authme.util.lazytags; + +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Applies tags lazily to the String property of an item. This class wraps + * a {@link TagReplacer} with the extraction of the String property and + * the creation of new items with the adapted string property. + * + * @param the item type + * @param the argument type to evaluate the replacements + */ +public class WrappedTagReplacer { + + private final Collection items; + private final BiFunction itemCreator; + private final TagReplacer tagReplacer; + + /** + * Constructor. + * + * @param allTags all available tags + * @param items the items to apply the replacements on + * @param stringGetter getter of the String property to adapt on the items + * @param itemCreator a function of signature (T, String) -> T: the original item and the adapted String are passed + */ + public WrappedTagReplacer(Collection> allTags, + Collection items, + Function stringGetter, + BiFunction itemCreator) { + this.items = items; + this.itemCreator = itemCreator; + + List stringItems = items.stream().map(stringGetter).collect(Collectors.toList()); + tagReplacer = TagReplacer.newReplacer(allTags, stringItems); + } + + /** + * Creates adapted items for the given argument. + * + * @param argument the argument to adapt the items for + * @return the adapted items + */ + public List getAdaptedItems(A argument) { + List adaptedStrings = tagReplacer.getAdaptedMessages(argument); + List adaptedItems = new LinkedList<>(); + + Iterator originalItemsIter = items.iterator(); + Iterator newStringsIter = adaptedStrings.iterator(); + while (originalItemsIter.hasNext() && newStringsIter.hasNext()) { + adaptedItems.add(itemCreator.apply(originalItemsIter.next(), newStringsIter.next())); + } + return adaptedItems; + } +} diff --git a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java index fb8e4e40..3ec3b447 100644 --- a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java +++ b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java @@ -1,9 +1,9 @@ package fr.xephi.authme.settings.commandconfig; import com.google.common.io.Files; -import fr.xephi.authme.ReflectionTestUtils; import fr.xephi.authme.TestHelper; import fr.xephi.authme.service.BukkitService; +import fr.xephi.authme.service.GeoIpService; import fr.xephi.authme.settings.SettingsMigrationService; import org.bukkit.entity.Player; import org.junit.Before; @@ -17,13 +17,7 @@ import org.mockito.junit.MockitoJUnitRunner; import java.io.File; import java.io.IOException; -import java.util.function.BiConsumer; -import static fr.xephi.authme.settings.commandconfig.CommandConfigTestHelper.isCommand; -import static java.lang.String.format; -import static org.hamcrest.Matchers.anEmptyMap; -import static org.hamcrest.Matchers.contains; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; @@ -31,6 +25,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.only; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; /** * Test for {@link CommandManager}. @@ -41,104 +36,116 @@ public class CommandManagerTest { private static final String TEST_FILES_FOLDER = "/fr/xephi/authme/settings/commandconfig/"; private CommandManager manager; + private Player player; + @InjectMocks private CommandMigrationService commandMigrationService; - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - @Mock private BukkitService bukkitService; @Mock + private GeoIpService geoIpService; + @Mock private SettingsMigrationService settingsMigrationService; + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + private File testFolder; @Before public void setup() throws IOException { testFolder = temporaryFolder.newFolder(); - } - - @Test - @SuppressWarnings("unchecked") - public void shouldLoadCompleteFile() { - // given - copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.complete.yml"); - - // when - initManager(); - - // then - CommandConfig commandConfig = ReflectionTestUtils.getFieldValue(CommandManager.class, manager, "commandConfig"); - assertThat(commandConfig.getOnJoin().keySet(), contains("broadcast")); - assertThat(commandConfig.getOnJoin().values(), contains(isCommand("broadcast %p has joined", Executor.CONSOLE))); - assertThat(commandConfig.getOnRegister().keySet(), contains("announce", "notify")); - assertThat(commandConfig.getOnRegister().values(), contains( - isCommand("me I just registered", Executor.PLAYER), - isCommand("log %p registered", Executor.CONSOLE))); - assertThat(commandConfig.getOnLogin().keySet(), contains("welcome", "show_motd", "display_list")); - assertThat(commandConfig.getOnLogin().values(), contains( - isCommand("msg %p Welcome back", Executor.CONSOLE), - isCommand("motd", Executor.PLAYER), - isCommand("list", Executor.PLAYER))); - } - - @Test - public void shouldLoadIncompleteFile() { - // given - copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.incomplete.yml"); - - // when - initManager(); - - // then - CommandConfig commandConfig = ReflectionTestUtils.getFieldValue(CommandManager.class, manager, "commandConfig"); - assertThat(commandConfig.getOnJoin().values(), contains(isCommand("broadcast %p has joined", Executor.CONSOLE))); - assertThat(commandConfig.getOnLogin().values(), contains( - isCommand("msg %p Welcome back", Executor.CONSOLE), - isCommand("list", Executor.PLAYER))); - assertThat(commandConfig.getOnRegister(), anEmptyMap()); - } - - @Test - public void shouldExecuteCommandsOnJoin() { - // given - String name = "Bobby1"; - - // when - testCommandExecution(name, CommandManager::runCommandsOnJoin); - - // then - verify(bukkitService, only()).dispatchConsoleCommand(format("broadcast %s has joined", name)); - } - - @Test - public void shouldExecuteCommandsOnRegister() { - // given - String name = "luis"; - - // when - testCommandExecution(name, CommandManager::runCommandsOnRegister); - - // then - verify(bukkitService).dispatchCommand(any(Player.class), eq("me I just registered")); - verify(bukkitService).dispatchConsoleCommand(format("log %s registered", name)); - verifyNoMoreInteractions(bukkitService); + player = mockPlayer(); } @Test public void shouldExecuteCommandsOnLogin() { // given - String name = "plaYer01"; + copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.complete.yml"); + initManager(); // when - testCommandExecution(name, CommandManager::runCommandsOnLogin); + manager.runCommandsOnLogin(player); // then - verify(bukkitService).dispatchConsoleCommand(format("msg %s Welcome back", name)); + verify(bukkitService).dispatchConsoleCommand("msg Bobby Welcome back"); verify(bukkitService).dispatchCommand(any(Player.class), eq("motd")); verify(bukkitService).dispatchCommand(any(Player.class), eq("list")); verifyNoMoreInteractions(bukkitService); + verifyZeroInteractions(geoIpService); + } + + @Test + public void shouldExecuteCommandsOnLoginWithIncompleteConfig() { + // given + copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.incomplete.yml"); + initManager(); + + // when + manager.runCommandsOnLogin(player); + + // then + verify(bukkitService).dispatchConsoleCommand("msg Bobby Welcome back, bob"); + verify(bukkitService).dispatchCommand(any(Player.class), eq("list")); + verifyNoMoreInteractions(bukkitService); + verifyZeroInteractions(geoIpService); + } + + @Test + public void shouldExecuteCommandsOnJoin() { + // given + copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.complete.yml"); + initManager(); + + // when + manager.runCommandsOnJoin(player); + + // then + verify(bukkitService, only()).dispatchConsoleCommand("broadcast bob has joined"); + verifyZeroInteractions(geoIpService); + } + + @Test + public void shouldExecuteCommandsOnJoinWithIncompleteConfig() { + // given + copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.incomplete.yml"); + initManager(); + + // when + manager.runCommandsOnJoin(player); + + // then + verify(bukkitService, only()).dispatchConsoleCommand("broadcast Bobby has joined"); + verifyZeroInteractions(geoIpService); + } + + @Test + public void shouldExecuteCommandsOnRegister() { + // given + copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.complete.yml"); + initManager(); + + // when + manager.runCommandsOnRegister(player); + + // then + verify(bukkitService).dispatchCommand(any(Player.class), eq("me I just registered")); + verify(bukkitService).dispatchConsoleCommand("log Bobby (127.0.0.3, Syldavia) registered"); + verifyNoMoreInteractions(bukkitService); + } + + @Test + public void shouldExecuteCommandsOnRegisterWithIncompleteConfig() { + // given + copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.incomplete.yml"); + initManager(); + + // when + manager.runCommandsOnRegister(player); + + // then + verifyZeroInteractions(bukkitService, geoIpService); } @Test @@ -147,18 +154,8 @@ public class CommandManagerTest { TestHelper.validateHasOnlyPrivateEmptyConstructor(CommandSettingsHolder.class); } - - private void testCommandExecution(String playerName, BiConsumer testMethod) { - copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.complete.yml"); - initManager(); - Player player = mock(Player.class); - given(player.getName()).willReturn(playerName); - - testMethod.accept(manager, player); - } - private void initManager() { - manager = new CommandManager(testFolder, bukkitService, commandMigrationService); + manager = new CommandManager(testFolder, bukkitService, geoIpService, commandMigrationService); } private void copyJarFileAsCommandsYml(String path) { @@ -171,4 +168,13 @@ public class CommandManagerTest { } } + private Player mockPlayer() { + Player player = mock(Player.class); + given(player.getName()).willReturn("Bobby"); + given(player.getDisplayName()).willReturn("bob"); + String ip = "127.0.0.3"; + TestHelper.mockPlayerIp(player, ip); + given(geoIpService.getCountryName(ip)).willReturn("Syldavia"); + return player; + } } diff --git a/src/test/java/tools/filegeneration/GenerateCommandsYml.java b/src/test/java/tools/filegeneration/GenerateCommandsYml.java index 73113ccc..b99eef52 100644 --- a/src/test/java/tools/filegeneration/GenerateCommandsYml.java +++ b/src/test/java/tools/filegeneration/GenerateCommandsYml.java @@ -26,7 +26,7 @@ public class GenerateCommandsYml implements AutoToolTask { // Get default and add sample entry CommandConfig commandConfig = CommandSettingsHolder.COMMANDS.getDefaultValue(); commandConfig.setOnLogin( - ImmutableMap.of("welcome", newCommand("msg %p Welcome back!", Executor.PLAYER))); + ImmutableMap.of("welcome", new Command("msg %p Welcome back!", Executor.PLAYER))); // Export the value to the file SettingsManager settingsManager = new SettingsManager( @@ -41,11 +41,4 @@ public class GenerateCommandsYml implements AutoToolTask { public String getTaskName() { return "generateCommandsYml"; } - - private static Command newCommand(String commandLine, Executor executor) { - Command command = new Command(); - command.setCommand(commandLine); - command.setExecutor(executor); - return command; - } } diff --git a/src/test/resources/fr/xephi/authme/settings/commandconfig/commands.complete.yml b/src/test/resources/fr/xephi/authme/settings/commandconfig/commands.complete.yml index 8c6bf79d..757f09ca 100644 --- a/src/test/resources/fr/xephi/authme/settings/commandconfig/commands.complete.yml +++ b/src/test/resources/fr/xephi/authme/settings/commandconfig/commands.complete.yml @@ -2,14 +2,14 @@ onJoin: broadcast: - command: 'broadcast %p has joined' + command: 'broadcast %nick has joined' executor: CONSOLE onRegister: announce: command: 'me I just registered' executor: PLAYER notify: - command: 'log %p registered' + command: 'log %p (%ip, %country) registered' executor: CONSOLE onLogin: welcome: diff --git a/src/test/resources/fr/xephi/authme/settings/commandconfig/commands.incomplete.yml b/src/test/resources/fr/xephi/authme/settings/commandconfig/commands.incomplete.yml index 2eef86b0..a1e9060f 100644 --- a/src/test/resources/fr/xephi/authme/settings/commandconfig/commands.incomplete.yml +++ b/src/test/resources/fr/xephi/authme/settings/commandconfig/commands.incomplete.yml @@ -6,7 +6,7 @@ onJoin: executor: CONSOLE onLogin: welcome: - command: 'msg %p Welcome back' + command: 'msg %p Welcome back, %nick' executor: CONSOLE show_motd: # command: 'motd' <-- mandatory property, so entry should be ignored