diff --git a/src/main/java/bentobox/addon/limits/listeners/JoinListener.java b/src/main/java/bentobox/addon/limits/listeners/JoinListener.java index 6bb8d1d..c6ca053 100644 --- a/src/main/java/bentobox/addon/limits/listeners/JoinListener.java +++ b/src/main/java/bentobox/addon/limits/listeners/JoinListener.java @@ -38,33 +38,32 @@ public class JoinListener implements Listener { private void checkPerms(Player player, String permissionPrefix, String islandId, String gameMode) { IslandBlockCount ibc = addon.getBlockLimitListener().getIsland(islandId); for (PermissionAttachmentInfo perms : player.getEffectivePermissions()) { - int limit = -1; if (perms.getPermission().startsWith(permissionPrefix)) { + // No wildcards + if (perms.getPermission().contains(permissionPrefix + "*")) { + logError(player.getName(), perms.getPermission(), "wildcards are not allowed."); + return; + } // Get the Material String[] split = perms.getPermission().split("\\."); if (split.length != 5) { - logError(player.getName(), perms.getPermission(), "format must be " + permissionPrefix + "MATERIAL.NUMBER"); + logError(player.getName(), perms.getPermission(), "format must be '" + permissionPrefix + "MATERIAL.NUMBER'"); return; } Material m = Material.getMaterial(split[3].toUpperCase(Locale.ENGLISH)); if (m == null) { - logError(player.getName(), perms.getPermission(), split[3].toUpperCase(Locale.ENGLISH) + " is not a valid material"); + logError(player.getName(), perms.getPermission(), split[3].toUpperCase(Locale.ENGLISH) + " is not a valid material."); return; } // Get the max value should there be more than one - if (perms.getPermission().contains(permissionPrefix + ".*")) { - logError(player.getName(), perms.getPermission(), "wildcards are not allowed"); - return; - } if (!NumberUtils.isDigits(split[4])) { logError(player.getName(), perms.getPermission(), "the last part MUST be a number!"); } else { - limit = Math.max(limit, Integer.valueOf(split[4])); // Set the limit if (ibc == null) { ibc = new IslandBlockCount(islandId, gameMode); } - ibc.setBlockLimit(m, limit); + ibc.setBlockLimit(m, Math.max(ibc.getBlockLimit(m), Integer.valueOf(split[4]))); } } } @@ -76,7 +75,7 @@ public class JoinListener implements Listener { } private void logError(String name, String perm, String error) { - addon.logError("Player " + name + " has permission: '" + perm + " but " + error + " Ignoring..."); + addon.logError("Player " + name + " has permission: '" + perm + "' but " + error + " Ignoring..."); } /* diff --git a/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java b/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java new file mode 100644 index 0000000..4ce9696 --- /dev/null +++ b/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java @@ -0,0 +1,439 @@ +/** + * + */ +package bentobox.addon.limits.listeners; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.eq; + + +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.permissions.PermissionAttachmentInfo; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import bentobox.addon.limits.Limits; +import bentobox.addon.limits.objects.IslandBlockCount; +import world.bentobox.bentobox.api.addons.AddonDescription; +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.api.events.island.IslandEvent; +import world.bentobox.bentobox.api.events.team.TeamEvent.TeamSetownerEvent; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.IslandsManager; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest( {Bukkit.class} ) +public class JoinListenerTest { + + @Mock + private Limits addon; + @Mock + private GameModeAddon bskyblock; + @Mock + private Player player; + + private JoinListener jl; + @Mock + private IslandsManager im; + @Mock + private BlockLimitsListener bll; + @Mock + private IslandBlockCount ibc; + @Mock + private OfflinePlayer owner; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + jl = new JoinListener(addon); + // Setup addon + when(addon.getGameModes()).thenReturn(Collections.singletonList(bskyblock)); + when(addon.getGameModeName(any())).thenReturn("bskyblock"); + when(addon.getGameModePermPrefix(any())).thenReturn("bskyblock."); + // Island Manager + when(im.hasIsland(any(), any(UUID.class))).thenReturn(true); + Island island = mock(Island.class); + when(island.getUniqueId()).thenReturn("unique_id"); + when(im.getIsland(any(), any(UUID.class))).thenReturn(island); + // Default is that player has island + when(addon.getIslands()).thenReturn(im); + // Player + when(player.getUniqueId()).thenReturn(UUID.randomUUID()); + when(player.getName()).thenReturn("tastybento"); + // No permissions by default + when(player.getEffectivePermissions()).thenReturn(Collections.emptySet()); + // bsKyBlock + when(bskyblock.getPermissionPrefix()).thenReturn("bskyblock."); + AddonDescription desc = new AddonDescription.Builder("main", "BSkyBlock", "1.0").build(); + when(bskyblock.getDescription()).thenReturn(desc); + + // Block limit listener + when(addon.getBlockLimitListener()).thenReturn(bll); + when(bll.getIsland(anyString())).thenReturn(ibc); + + // bukkit + PowerMockito.mockStatic(Bukkit.class); + // default is that owner is online + when(owner.isOnline()).thenReturn(true); + when(owner.getPlayer()).thenReturn(player); + when(Bukkit.getOfflinePlayer(any(UUID.class))).thenReturn(owner); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onNewIsland(world.bentobox.bentobox.api.events.island.IslandEvent)}. + */ + @Test + public void testOnNewIslandWrongReason() { + Island island = mock(Island.class); + IslandEvent e = new IslandEvent(island, null, false, null, IslandEvent.Reason.BAN); + jl.onNewIsland(e); + verify(island, never()).getWorld(); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onNewIsland(world.bentobox.bentobox.api.events.island.IslandEvent)}. + */ + @Test + public void testOnNewIslandRegistered() { + Island island = mock(Island.class); + IslandEvent e = new IslandEvent(island, null, false, null, IslandEvent.Reason.REGISTERED); + jl.onNewIsland(e); + verify(island).getWorld(); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onNewIsland(world.bentobox.bentobox.api.events.island.IslandEvent)}. + */ + @Test + public void testOnNewIslandResetted() { + Island island = mock(Island.class); + IslandEvent e = new IslandEvent(island, null, false, null, IslandEvent.Reason.RESETTED); + jl.onNewIsland(e); + verify(island).getWorld(); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onNewIsland(world.bentobox.bentobox.api.events.island.IslandEvent)}. + */ + @Test + public void testOnNewIslandCreated() { + when(addon.inGameModeWorld(any())).thenReturn(true); + Island island = mock(Island.class); + IslandEvent e = new IslandEvent(island, null, false, null, IslandEvent.Reason.CREATED); + jl.onNewIsland(e); + verify(island).getWorld(); + verify(owner).getPlayer(); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onNewIsland(world.bentobox.bentobox.api.events.island.IslandEvent)}. + */ + @Test + public void testOnNewIslandCreatedOffline() { + when(owner.isOnline()).thenReturn(false); + when(addon.inGameModeWorld(any())).thenReturn(true); + Island island = mock(Island.class); + IslandEvent e = new IslandEvent(island, null, false, null, IslandEvent.Reason.CREATED); + jl.onNewIsland(e); + verify(island).getWorld(); + verify(owner, never()).getPlayer(); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onNewIsland(world.bentobox.bentobox.api.events.island.IslandEvent)}. + */ + @Test + public void testOnNewIslandCreatedNoNameOrPermPrefix() { + when(addon.getGameModeName(any())).thenReturn(""); + when(addon.getGameModePermPrefix(any())).thenReturn("bskyblock."); + when(addon.inGameModeWorld(any())).thenReturn(true); + Island island = mock(Island.class); + IslandEvent e = new IslandEvent(island, null, false, null, IslandEvent.Reason.CREATED); + jl.onNewIsland(e); + when(addon.getGameModeName(any())).thenReturn("bskyblock"); + when(addon.getGameModePermPrefix(any())).thenReturn(""); + jl.onNewIsland(e); + verify(owner, never()).getPlayer(); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onOwnerChange(world.bentobox.bentobox.api.events.team.TeamEvent.TeamSetownerEvent)}. + */ + @Test + public void testOnOwnerChange() { + Island island = mock(Island.class); + TeamSetownerEvent e = mock(TeamSetownerEvent.class); + when(e.getIsland()).thenReturn(island); + when(e.getNewOwner()).thenReturn(UUID.randomUUID()); + jl.onOwnerChange(e); + verify(e, Mockito.times(2)).getIsland(); + verify(e).getNewOwner(); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent)}. + */ + @Test + public void testOnPlayerJoin() { + PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); + jl.onPlayerJoin(e); + verify(addon).getGameModes(); + verify(bll).setIsland("unique_id", ibc); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent)}. + */ + @Test + public void testOnPlayerJoinIBCNull() { + ibc = null; + PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); + jl.onPlayerJoin(e); + verify(addon).getGameModes(); + verify(bll, never()).setIsland("unique_id", ibc); + } + + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent)}. + */ + @Test + public void testOnPlayerJoinWithPermNotLimits() { + Set perms = new HashSet<>(); + PermissionAttachmentInfo permAtt = mock(PermissionAttachmentInfo.class); + when(permAtt.getPermission()).thenReturn("bskyblock.my.perm.for.game"); + perms.add(permAtt); + when(player.getEffectivePermissions()).thenReturn(perms); + PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); + jl.onPlayerJoin(e); + verify(addon).getGameModes(); + verify(bll).setIsland("unique_id", ibc); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent)}. + */ + @Test + public void testOnPlayerJoinWithPermLimitsWrongSize() { + Set perms = new HashSet<>(); + PermissionAttachmentInfo permAtt = mock(PermissionAttachmentInfo.class); + when(permAtt.getPermission()).thenReturn("bskyblock.island.limit.my.perm.for.game"); + perms.add(permAtt); + when(player.getEffectivePermissions()).thenReturn(perms); + PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); + jl.onPlayerJoin(e); + verify(addon).logError("Player tastybento has permission: 'bskyblock.island.limit.my.perm.for.game' but format must be 'bskyblock.island.limit.MATERIAL.NUMBER' Ignoring..."); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent)}. + */ + @Test + public void testOnPlayerJoinWithPermLimitsInvalidMaterial() { + Set perms = new HashSet<>(); + PermissionAttachmentInfo permAtt = mock(PermissionAttachmentInfo.class); + when(permAtt.getPermission()).thenReturn("bskyblock.island.limit.mumbo.34"); + perms.add(permAtt); + when(player.getEffectivePermissions()).thenReturn(perms); + PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); + jl.onPlayerJoin(e); + verify(addon).logError("Player tastybento has permission: 'bskyblock.island.limit.mumbo.34' but MUMBO is not a valid material. Ignoring..."); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent)}. + */ + @Test + public void testOnPlayerJoinWithPermLimitsWildcard() { + Set perms = new HashSet<>(); + PermissionAttachmentInfo permAtt = mock(PermissionAttachmentInfo.class); + when(permAtt.getPermission()).thenReturn("bskyblock.island.limit.*"); + perms.add(permAtt); + when(player.getEffectivePermissions()).thenReturn(perms); + PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); + jl.onPlayerJoin(e); + verify(addon).logError("Player tastybento has permission: 'bskyblock.island.limit.*' but wildcards are not allowed. Ignoring..."); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent)}. + */ + @Test + public void testOnPlayerJoinWithPermLimitsNotNumber() { + Set perms = new HashSet<>(); + PermissionAttachmentInfo permAtt = mock(PermissionAttachmentInfo.class); + when(permAtt.getPermission()).thenReturn("bskyblock.island.limit.STONE.abc"); + perms.add(permAtt); + when(player.getEffectivePermissions()).thenReturn(perms); + PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); + jl.onPlayerJoin(e); + verify(addon).logError("Player tastybento has permission: 'bskyblock.island.limit.STONE.abc' but the last part MUST be a number! Ignoring..."); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent)}. + */ + @Test + public void testOnPlayerJoinWithPermLimitsSuccess() { + Set perms = new HashSet<>(); + PermissionAttachmentInfo permAtt = mock(PermissionAttachmentInfo.class); + when(permAtt.getPermission()).thenReturn("bskyblock.island.limit.STONE.24"); + perms.add(permAtt); + when(player.getEffectivePermissions()).thenReturn(perms); + PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); + jl.onPlayerJoin(e); + verify(addon, never()).logError(anyString()); + verify(ibc).setBlockLimit(eq(Material.STONE), eq(24)); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent)}. + */ + @Test + public void testOnPlayerJoinWithPermLimitsMultiPerms() { + Set perms = new HashSet<>(); + PermissionAttachmentInfo permAtt = mock(PermissionAttachmentInfo.class); + when(permAtt.getPermission()).thenReturn("bskyblock.island.limit.STONE.24"); + perms.add(permAtt); + PermissionAttachmentInfo permAtt2 = mock(PermissionAttachmentInfo.class); + when(permAtt2.getPermission()).thenReturn("bskyblock.island.limit.grass.14"); + perms.add(permAtt2); + PermissionAttachmentInfo permAtt3 = mock(PermissionAttachmentInfo.class); + when(permAtt3.getPermission()).thenReturn("bskyblock.island.limit.dirt.34"); + perms.add(permAtt3); + when(player.getEffectivePermissions()).thenReturn(perms); + PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); + jl.onPlayerJoin(e); + verify(addon, never()).logError(anyString()); + verify(ibc).setBlockLimit(eq(Material.STONE), eq(24)); + verify(ibc).setBlockLimit(eq(Material.GRASS), eq(14)); + verify(ibc).setBlockLimit(eq(Material.DIRT), eq(34)); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent)}. + */ + @Test + public void testOnPlayerJoinWithPermLimitsMultiPermsSameMaterial() { + // IBC - set the block limit for STONE to be 25 already + when(ibc.getBlockLimit(any())).thenReturn(25); + Set perms = new HashSet<>(); + PermissionAttachmentInfo permAtt = mock(PermissionAttachmentInfo.class); + when(permAtt.getPermission()).thenReturn("bskyblock.island.limit.STONE.24"); + perms.add(permAtt); + PermissionAttachmentInfo permAtt2 = mock(PermissionAttachmentInfo.class); + when(permAtt2.getPermission()).thenReturn("bskyblock.island.limit.STONE.14"); + perms.add(permAtt2); + PermissionAttachmentInfo permAtt3 = mock(PermissionAttachmentInfo.class); + when(permAtt3.getPermission()).thenReturn("bskyblock.island.limit.STONE.34"); + perms.add(permAtt3); + when(player.getEffectivePermissions()).thenReturn(perms); + PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); + jl.onPlayerJoin(e); + verify(addon, never()).logError(anyString()); + // Only the limit over 25 should be set + verify(ibc, never()).setBlockLimit(eq(Material.STONE), eq(24)); + verify(ibc, never()).setBlockLimit(eq(Material.STONE), eq(14)); + verify(ibc).setBlockLimit(eq(Material.STONE), eq(34)); + } + + + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onUnregisterIsland(world.bentobox.bentobox.api.events.island.IslandEvent)}. + */ + @Test + public void testOnUnregisterIslandNotUnregistered() { + Island island = mock(Island.class); + IslandEvent e = new IslandEvent(island, null, false, null, IslandEvent.Reason.BAN); + jl.onUnregisterIsland(e); + verify(island, never()).getWorld(); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onUnregisterIsland(world.bentobox.bentobox.api.events.island.IslandEvent)}. + */ + @Test + public void testOnUnregisterIslandNotInWorld() { + Island island = mock(Island.class); + IslandEvent e = new IslandEvent(island, null, false, null, IslandEvent.Reason.UNREGISTERED); + jl.onUnregisterIsland(e); + verify(island).getWorld(); + verify(addon, never()).getBlockLimitListener(); + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onUnregisterIsland(world.bentobox.bentobox.api.events.island.IslandEvent)}. + */ + @Test + public void testOnUnregisterIslandInWorld() { + @SuppressWarnings("unchecked") + Map map = mock(Map.class); + when(ibc.getBlockLimits()).thenReturn(map); + when(addon.inGameModeWorld(any())).thenReturn(true); + Island island = mock(Island.class); + IslandEvent e = new IslandEvent(island, null, false, null, IslandEvent.Reason.UNREGISTERED); + jl.onUnregisterIsland(e); + verify(island).getWorld(); + verify(addon).getBlockLimitListener(); + verify(map).clear(); + + } + + /** + * Test method for {@link bentobox.addon.limits.listeners.JoinListener#onUnregisterIsland(world.bentobox.bentobox.api.events.island.IslandEvent)}. + */ + @Test + public void testOnUnregisterIslandInWorldNullIBC() { + when(bll.getIsland(anyString())).thenReturn(null); + @SuppressWarnings("unchecked") + Map map = mock(Map.class); + when(ibc.getBlockLimits()).thenReturn(map); + when(addon.inGameModeWorld(any())).thenReturn(true); + Island island = mock(Island.class); + IslandEvent e = new IslandEvent(island, null, false, null, IslandEvent.Reason.UNREGISTERED); + jl.onUnregisterIsland(e); + verify(island).getWorld(); + verify(addon).getBlockLimitListener(); + verify(map, never()).clear(); + + } + + + +}