Compare commits

...
10 Commits
Author SHA1 Message Date
Andreas Troelsen f07df6a556 Add compatibility note in README.
build / build (push) Failing after 2m7s
2022-07-26 17:35:01 +02:00
Andreas Troelsen 9e92094501 Ignore leave events for spectators.
Spectators produce leave events, but they won't have a join event that
matches the leave event they produce. This is because spectators either
joined _as_ spectators (spectating doesn't produce join events), or they
_transitioned_ into the spectator state after _dying_ in the session (in
which case they already produced a death event that "cements" the player
session).

This fixes an edge case problem that occurs when a spectator produces a
leave event while exactly one player is currently in the lobby. In this
case, the leave event triggers a session deletion, since the leave event
logic "thinks" the leave event is triggered by the player in the lobby.
It would be possible to prevent that problem with additional checks in
the leave event logic, but the underlying problem really is that leave
events produced by spectators shouldn't be recorded or reacted to in any
way, shape, or form, as they are not relevant to the stats (leave times
are only really relevant if the leave event happens _during_ a session,
which this change does not affect).
2022-07-25 17:30:19 +02:00
Andreas Troelsen 85df0066f1 Remove player entries on leave/death prior to session start.
While we do want to keep track of join and ready times, we really don't
care about those stats for players who join the lobby _and leave_ prior
to the arena actually starting.

Coincidentally, _not_ storing stats for players that don't actually pick
a class means we don't end up trying to insert a `null` value into the
class name column, which should solve the error thrown when trying to do
just that as a result of the auto-start timer kicking players or players
themselves leaving prior to starting.

Fixes #16
2022-07-03 20:58:42 +02:00
Andreas Troelsen ffc6c89eac Fix references to repo in README.
The project has been migrated to the MobArena org, so let's make sure
the links make sense :)
2022-06-21 20:39:09 +02:00
Andreas Troelsen 4ab74b06cb Upgrade MySQL connector to 8.0.28.
Apparently there's a security issue <= 8.0.27. It doesn't really matter
all that much here since we're in the `provided` scope, but better safe
than sorry.
2022-06-21 20:32:20 +02:00
Andreas Troelsen 2745af3d0d Switch to Spigot API and bump version to 1.17.
This brings the repository up to the same Spigot API version as the core
plugin for essentially the same reasons, plus consistency.
2022-05-27 22:47:04 +02:00
Andreas Troelsen 72bb017834 Fix maven-compiler-plugin configuration.
Apparently the whole `<release>` tag shebang doesn't work on jitpack.
Not sure where it comes from.
2021-12-05 13:57:20 +01:00
Andreas Troelsen 57bf8c6472 Add tests for delete session command.
This is just a single sunshine scenario test because that's all the
command supports right now. Issues #2 and #3 highlight some of the
problems with this command, and when those issues are tackled, tests
should be introduced along with the fixes.
2021-08-06 22:13:14 +02:00
Andreas Troelsen 066a15c2af Add query command tests.
Not a lot of variation in these commands, but the output is a little
difficult to write robust tests for because it's all stringly typed.
These tests will break pretty hard (or require lots of adapting) if we
introduce i18n.

The tests don't cover tab completion. That will have to come later.
2021-08-06 22:13:14 +02:00
Andreas Troelsen f96c69bb42 Add import/export command tests.
These are pretty much whitebox tests, so they don't really provide any
improvements to the architecture, but they do add a level of confidence
in terms of refactoring the somewhat unorthodox import/export structure.
2021-08-06 22:13:14 +02:00
12 changed files with 545 additions and 9 deletions
+4 -2
View File
@@ -1,14 +1,16 @@
# MobArenaStats [![Build Status](https://github.com/garbagemule/MobArenaStats/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/garbagemule/MobArenaStats/actions/workflows/build.yml)
# MobArenaStats [![Build Status](https://github.com/mobarena/MobArenaStats/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/mobarena/MobArenaStats/actions/workflows/build.yml)
MobArenaStats is a _plugin extension_ for [MobArena](https://github.com/garbagemule/MobArena).
The extension collects stats from MobArena sessions into persistent storage such as MySQL, MariaDB, and SQLite databases.
It hooks into MobArena's command handler to provide commands for querying and managing the stats.
**Note:** This extension requires MobArena 0.107 or later to work.
## Getting Started
Download a copy of the latest MobArenaStats build and place it in your server's `plugins` folder.
You can grab a build from the _Artifacts_ section of the latest run of the [build workflow](https://github.com/garbagemule/MobArenaStats/actions/workflows/build.yml) in GitHub Actions, or you can join the MobArena Discord server and grab one from the `#test-builds` channel.
You can grab a build from the _Artifacts_ section of the latest run of the [build workflow](https://github.com/mobarena/MobArenaStats/actions/workflows/build.yml) in GitHub Actions, or you can join the MobArena Discord server and grab one from the `#test-builds` channel.
Start your server and let the plugin load.
It will generate a default `config.yml` file and set up a default SQLite data store.
+8 -7
View File
@@ -34,11 +34,11 @@
<version>2.2.1</version>
</dependency>
<!-- https://hub.spigotmc.org/nexus/content/groups/public/org/bukkit/bukkit/ -->
<!-- https://hub.spigotmc.org/nexus/content/groups/public/org/spigotmc/spigot-api/ -->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.13-R0.1-SNAPSHOT</version>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.17-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@@ -54,7 +54,7 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
<version>8.0.28</version>
<scope>provided</scope>
</dependency>
@@ -134,7 +134,7 @@
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
@@ -157,7 +157,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>11</release>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
@@ -47,6 +47,11 @@ public class Session {
public void playerLeave(Arena arena, Player player) {
UUID playerId = player.getUniqueId();
if (sessionStats.startTime == null) {
playerStats.remove(playerId);
return;
}
PlayerSessionStats stats = playerStats.get(playerId);
if (stats == null) {
return;
@@ -63,6 +68,11 @@ public class Session {
public void playerDeath(Arena arena, Player player) {
UUID playerId = player.getUniqueId();
if (sessionStats.startTime == null) {
playerStats.remove(playerId);
return;
}
PlayerSessionStats stats = playerStats.get(playerId);
if (stats == null) {
return;
@@ -88,6 +88,10 @@ public class SessionListener implements Listener {
Arena arena = event.getArena();
Player player = event.getPlayer();
if (arena.inSpec(player)) {
return;
}
Session session = sessionStore.getByArena(arena);
if (session == null) {
log.warning("Unexpected leave event for non-existent session of arena " + arena.getSlug());
@@ -0,0 +1,61 @@
package org.mobarena.stats.command;
import com.garbagemule.MobArena.Messenger;
import com.garbagemule.MobArena.framework.ArenaMaster;
import org.bukkit.command.CommandSender;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mobarena.stats.MobArenaStats;
import org.mobarena.stats.store.ArenaStats;
import org.mobarena.stats.store.StatsStore;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class ArenaStatsCommandTest {
MobArenaStats plugin;
ArenaStatsCommand subject;
@BeforeEach
void setup() {
plugin = mock(MobArenaStats.class);
subject = new ArenaStatsCommand(plugin);
}
@Test
void noArgumentsReturnsFalse() {
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {};
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(false));
}
@Test
void success() {
String slug = "castle";
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {slug};
Messenger messenger = mock(Messenger.class);
StatsStore store = mock(StatsStore.class);
ArenaStats stats = new ArenaStats(1, 2, 3, 4, 5, 6, 7);
when(am.getGlobalMessenger()).thenReturn(messenger);
when(plugin.getStatsStore()).thenReturn(store);
when(plugin.getAsyncExecutor()).thenReturn(Runnable::run);
when(store.getArenaStats(slug)).thenReturn(stats);
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(true));
verify(messenger).tell(eq(sender), contains(slug));
}
}
@@ -0,0 +1,50 @@
package org.mobarena.stats.command;
import com.garbagemule.MobArena.Messenger;
import com.garbagemule.MobArena.framework.ArenaMaster;
import org.bukkit.command.CommandSender;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mobarena.stats.MobArenaStats;
import org.mobarena.stats.store.StatsStore;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.UUID;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class DeleteSessionStatsCommandTest {
MobArenaStats plugin;
DeleteSessionStatsCommand subject;
@BeforeEach
void setup() {
plugin = mock(MobArenaStats.class);
subject = new DeleteSessionStatsCommand(plugin);
}
@Test
void success() {
String id = "cafebabe-ea75-dead-beef-deadcafebabe";
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {id};
Messenger messenger = mock(Messenger.class);
StatsStore store = mock(StatsStore.class);
when(am.getGlobalMessenger()).thenReturn(messenger);
when(plugin.getStatsStore()).thenReturn(store);
when(plugin.getAsyncExecutor()).thenReturn(Runnable::run);
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(true));
verify(store).delete(UUID.fromString(id));
verify(messenger).tell(eq(sender), contains("deleted"));
}
}
@@ -0,0 +1,79 @@
package org.mobarena.stats.command;
import com.garbagemule.MobArena.Messenger;
import com.garbagemule.MobArena.framework.ArenaMaster;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mobarena.stats.MobArenaStats;
import org.mobarena.stats.store.StatsStore;
import org.mobarena.stats.store.StatsStoreRegistry;
import org.mockito.ArgumentMatchers;
import org.mockito.junit.jupiter.MockitoExtension;
import java.io.IOException;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class ExportCommandTest {
MobArenaStats plugin;
ExportCommand subject;
@BeforeEach
void setup() {
plugin = mock(MobArenaStats.class);
subject = new ExportCommand(plugin);
}
@Test
void failure() throws Exception {
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {};
Messenger messenger = mock(Messenger.class);
StatsStore source = mock(StatsStore.class);
StatsStore target = mock(StatsStore.class);
StatsStoreRegistry registry = mock(StatsStoreRegistry.class);
when(am.getGlobalMessenger()).thenReturn(messenger);
when(plugin.getStatsStore()).thenReturn(source);
when(plugin.getStatsStoreRegistry()).thenReturn(registry);
when(plugin.getAsyncExecutor()).thenReturn(Runnable::run);
when(registry.create(ArgumentMatchers.any(ConfigurationSection.class))).thenReturn(target);
doThrow(IOException.class).when(source).export(target);
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(true));
verify(messenger).tell(eq(sender), contains("Exporting stats"));
verify(messenger).tell(eq(sender), contains("failed"));
}
@Test
void success() throws Exception {
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {};
Messenger messenger = mock(Messenger.class);
StatsStore source = mock(StatsStore.class);
StatsStore target = mock(StatsStore.class);
StatsStoreRegistry registry = mock(StatsStoreRegistry.class);
when(am.getGlobalMessenger()).thenReturn(messenger);
when(plugin.getStatsStore()).thenReturn(source);
when(plugin.getStatsStoreRegistry()).thenReturn(registry);
when(plugin.getAsyncExecutor()).thenReturn(Runnable::run);
when(registry.create(ArgumentMatchers.any(ConfigurationSection.class))).thenReturn(target);
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(true));
verify(messenger).tell(eq(sender), contains("Exporting stats"));
verify(messenger).tell(eq(sender), contains("complete"));
}
}
@@ -0,0 +1,49 @@
package org.mobarena.stats.command;
import com.garbagemule.MobArena.Messenger;
import com.garbagemule.MobArena.framework.ArenaMaster;
import org.bukkit.command.CommandSender;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mobarena.stats.MobArenaStats;
import org.mobarena.stats.store.GlobalStats;
import org.mobarena.stats.store.StatsStore;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class GlobalStatsCommandTest {
MobArenaStats plugin;
GlobalStatsCommand subject;
@BeforeEach
void setup() {
plugin = mock(MobArenaStats.class);
subject = new GlobalStatsCommand(plugin);
}
@Test
void success() {
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {};
Messenger messenger = mock(Messenger.class);
StatsStore store = mock(StatsStore.class);
GlobalStats stats = new GlobalStats(1, 2, 3, 4);
when(am.getGlobalMessenger()).thenReturn(messenger);
when(plugin.getStatsStore()).thenReturn(store);
when(plugin.getAsyncExecutor()).thenReturn(Runnable::run);
when(store.getGlobalStats()).thenReturn(stats);
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(true));
verify(messenger).tell(eq(sender), contains("Global stats"));
}
}
@@ -0,0 +1,147 @@
package org.mobarena.stats.command;
import com.garbagemule.MobArena.Messenger;
import com.garbagemule.MobArena.framework.ArenaMaster;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.mobarena.stats.MobArenaStats;
import org.mobarena.stats.store.StatsStore;
import org.mobarena.stats.store.StatsStoreRegistry;
import org.mockito.ArgumentMatchers;
import org.mockito.junit.jupiter.MockitoExtension;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class ImportCommandTest {
@TempDir
File data;
MobArenaStats plugin;
ImportCommand subject;
@BeforeEach
void setup() {
plugin = mock(MobArenaStats.class);
subject = new ImportCommand(plugin);
}
@Test
void noArgumentsReturnsFalse() {
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {};
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(false));
}
@Test
void nonExistentSourceFileNoImport() {
String filename = "stats.export-321.db";
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {filename};
when(plugin.getDataFolder()).thenReturn(data);
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(false));
verify(sender).sendMessage(contains("not found"));
}
@Test
void wrongFilenamePrefixNoImport() throws Exception {
String filename = "stats.db";
Files.createFile(data.toPath().resolve(filename));
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {filename};
when(plugin.getDataFolder()).thenReturn(data);
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(true));
verify(sender).sendMessage(contains("filename must start with"));
}
@Test
void wrongFilenameSuffixNoImport() throws Exception {
String filename = "stats.export-123.sql";
Files.createFile(data.toPath().resolve(filename));
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {filename};
when(plugin.getDataFolder()).thenReturn(data);
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(true));
verify(sender).sendMessage(contains("filename must end with"));
}
@Test
void failure() throws Exception {
String filename = "stats.export-123.db";
Files.createFile(data.toPath().resolve(filename));
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {filename};
Messenger messenger = mock(Messenger.class);
StatsStore source = mock(StatsStore.class);
StatsStore target = mock(StatsStore.class);
StatsStoreRegistry registry = mock(StatsStoreRegistry.class);
when(am.getGlobalMessenger()).thenReturn(messenger);
when(plugin.getDataFolder()).thenReturn(data);
when(plugin.getStatsStore()).thenReturn(target);
when(plugin.getStatsStoreRegistry()).thenReturn(registry);
when(plugin.getAsyncExecutor()).thenReturn(Runnable::run);
when(registry.create(ArgumentMatchers.any(ConfigurationSection.class))).thenReturn(source);
doThrow(IOException.class).when(source).export(target);
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(true));
verify(messenger).tell(eq(sender), contains("Importing stats"));
verify(messenger).tell(eq(sender), contains("failed"));
}
@Test
void success() throws Exception {
String filename = "stats.export-123.db";
Files.createFile(data.toPath().resolve(filename));
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {filename};
Messenger messenger = mock(Messenger.class);
StatsStore source = mock(StatsStore.class);
StatsStore target = mock(StatsStore.class);
StatsStoreRegistry registry = mock(StatsStoreRegistry.class);
when(am.getGlobalMessenger()).thenReturn(messenger);
when(plugin.getDataFolder()).thenReturn(data);
when(plugin.getStatsStore()).thenReturn(target);
when(plugin.getStatsStoreRegistry()).thenReturn(registry);
when(plugin.getAsyncExecutor()).thenReturn(Runnable::run);
when(registry.create(ArgumentMatchers.any(ConfigurationSection.class))).thenReturn(source);
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(true));
verify(messenger).tell(eq(sender), contains("Importing stats"));
verify(source).export(target);
verify(messenger).tell(eq(sender), contains("complete"));
}
}
@@ -0,0 +1,83 @@
package org.mobarena.stats.command;
import com.garbagemule.MobArena.Messenger;
import com.garbagemule.MobArena.framework.ArenaMaster;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mobarena.stats.MobArenaStats;
import org.mobarena.stats.store.PlayerStats;
import org.mobarena.stats.store.StatsStore;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class PlayerStatsCommandTest {
MobArenaStats plugin;
PlayerStatsCommand subject;
@BeforeEach
void setup() {
plugin = mock(MobArenaStats.class);
subject = new PlayerStatsCommand(plugin);
}
@Test
void noArgumentsReturnsFalseForConsole() {
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {};
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(false));
}
@Test
void noArgumentsUsesSenderNameForPlayers() {
String name = "alice";
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(Player.class);
String[] args = {};
Messenger messenger = mock(Messenger.class);
StatsStore store = mock(StatsStore.class);
PlayerStats stats = new PlayerStats(1, 2, 3, 4);
when(sender.getName()).thenReturn(name);
when(am.getGlobalMessenger()).thenReturn(messenger);
when(plugin.getStatsStore()).thenReturn(store);
when(plugin.getAsyncExecutor()).thenReturn(Runnable::run);
when(store.getPlayerStats(name)).thenReturn(stats);
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(true));
verify(messenger).tell(eq(sender), contains(name));
}
@Test
void success() {
String name = "garbagemule";
ArenaMaster am = mock(ArenaMaster.class);
CommandSender sender = mock(CommandSender.class);
String[] args = {name};
Messenger messenger = mock(Messenger.class);
StatsStore store = mock(StatsStore.class);
PlayerStats stats = new PlayerStats(1, 2, 3, 4);
when(am.getGlobalMessenger()).thenReturn(messenger);
when(plugin.getStatsStore()).thenReturn(store);
when(plugin.getAsyncExecutor()).thenReturn(Runnable::run);
when(store.getPlayerStats(name)).thenReturn(stats);
boolean result = subject.execute(am, sender, args);
assertThat(result, equalTo(true));
verify(messenger).tell(eq(sender), contains(name));
}
}
@@ -110,10 +110,23 @@ class SessionListenerTest {
verify(session).playerReady(player, className);
}
@Test
void ignoresPlayerLeaveForSpectators() {
Player player = mock(Player.class);
Arena arena = mock(Arena.class);
when(arena.inSpec(player)).thenReturn(true);
ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(player, arena);
subject.on(event);
verifyNoInteractions(sessionStore);
}
@Test
void logsWarningIfPlayerLeavesInNonExistentSession() {
Player player = mock(Player.class);
Arena arena = mock(Arena.class);
when(arena.inSpec(player)).thenReturn(false);
when(sessionStore.getByArena(arena)).thenReturn(null);
ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(player, arena);
@@ -127,6 +140,7 @@ class SessionListenerTest {
Player player = mock(Player.class);
Arena arena = mock(Arena.class);
Session session = mock(Session.class);
when(arena.inSpec(player)).thenReturn(false);
when(arena.isRunning()).thenReturn(false);
when(arena.getPlayersInLobby()).thenReturn(Collections.singleton(player));
when(sessionStore.getByArena(arena)).thenReturn(session);
@@ -142,6 +156,7 @@ class SessionListenerTest {
Player player = mock(Player.class);
Arena arena = mock(Arena.class);
Session session = mock(Session.class);
when(arena.inSpec(player)).thenReturn(false);
when(arena.isRunning()).thenReturn(false);
when(arena.getPlayersInLobby()).thenReturn(Collections.singleton(player));
when(sessionStore.getByArena(arena)).thenReturn(session);
@@ -158,6 +173,7 @@ class SessionListenerTest {
Player other = mock(Player.class);
Arena arena = mock(Arena.class);
Session session = mock(Session.class);
when(arena.inSpec(player)).thenReturn(false);
when(arena.isRunning()).thenReturn(false);
when(arena.getPlayersInLobby()).thenReturn(new HashSet<>(Arrays.asList(player, other)));
when(sessionStore.getByArena(arena)).thenReturn(session);
@@ -173,6 +189,7 @@ class SessionListenerTest {
Player player = mock(Player.class);
Arena arena = mock(Arena.class);
Session session = mock(Session.class);
when(arena.inSpec(player)).thenReturn(false);
when(arena.isRunning()).thenReturn(true);
when(sessionStore.getByArena(arena)).thenReturn(session);
ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(player, arena);
@@ -95,6 +95,19 @@ class SessionTest {
assertThat(actual.className, equalTo(className));
}
@Test
void removeFromSessionOnLeaveBeforeStart() {
UUID playerId = UUID.fromString("cafebabe-ea75-dead-beef-deadcafebabe");
Player player = Mocks.player(playerId, "garbagemule");
Arena arena = mock(Arena.class);
subject.playerJoin(player);
subject.playerLeave(arena, player);
PlayerSessionStats actual = subject.getPlayerStats(playerId);
assertThat(actual, nullValue());
}
@Test
void setLeaveTimeOnLeave() {
UUID playerId = UUID.fromString("cafebabe-ea75-dead-beef-deadcafebabe");
@@ -103,6 +116,7 @@ class SessionTest {
ArenaPlayer ap = mock(ArenaPlayer.class);
when(arena.getArenaPlayer(player)).thenReturn(ap);
subject.playerJoin(player);
subject.start();
subject.playerLeave(arena, player);
@@ -118,6 +132,7 @@ class SessionTest {
ArenaPlayer ap = mock(ArenaPlayer.class);
when(arena.getArenaPlayer(player)).thenReturn(ap);
subject.playerJoin(player);
subject.start();
subject.playerLeave(arena, player);
@@ -133,6 +148,7 @@ class SessionTest {
ArenaPlayer ap = mock(ArenaPlayer.class);
when(arena.getArenaPlayer(player)).thenReturn(ap);
subject.playerJoin(player);
subject.start();
subject.getPlayerStats(playerId).conclusion = PlayerConclusion.VICTORY;
subject.playerLeave(arena, player);
@@ -141,6 +157,19 @@ class SessionTest {
assertThat(actual.conclusion, not(equalTo(PlayerConclusion.RETREAT)));
}
@Test
void removeFromSessionOnDeathBeforeStart() {
UUID playerId = UUID.fromString("cafebabe-ea75-dead-beef-deadcafebabe");
Player player = Mocks.player(playerId, "garbagemule");
Arena arena = mock(Arena.class);
subject.playerJoin(player);
subject.playerDeath(arena, player);
PlayerSessionStats actual = subject.getPlayerStats(playerId);
assertThat(actual, nullValue());
}
@Test
void setDeathTimeOnDeath() {
UUID playerId = UUID.fromString("cafebabe-ea75-dead-beef-deadcafebabe");
@@ -149,6 +178,7 @@ class SessionTest {
ArenaPlayer ap = mock(ArenaPlayer.class);
when(arena.getArenaPlayer(player)).thenReturn(ap);
subject.playerJoin(player);
subject.start();
subject.playerDeath(arena, player);
@@ -164,6 +194,7 @@ class SessionTest {
ArenaPlayer ap = mock(ArenaPlayer.class);
when(arena.getArenaPlayer(player)).thenReturn(ap);
subject.playerJoin(player);
subject.start();
subject.playerDeath(arena, player);
@@ -179,6 +210,7 @@ class SessionTest {
ArenaPlayer ap = mock(ArenaPlayer.class);
when(arena.getArenaPlayer(player)).thenReturn(ap);
subject.playerJoin(player);
subject.start();
subject.getPlayerStats(playerId).conclusion = PlayerConclusion.VICTORY;
subject.playerDeath(arena, player);
@@ -246,6 +278,7 @@ class SessionTest {
when(arena.getArenaPlayer(corpse)).thenReturn(ap);
subject.playerJoin(corpse);
subject.playerJoin(survivor);
subject.start();
subject.playerDeath(arena, corpse);
subject.complete();