Compare commits
10
Commits
7e08fde493
..
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f07df6a556 | ||
|
|
9e92094501 | ||
|
|
85df0066f1 | ||
|
|
ffc6c89eac | ||
|
|
4ab74b06cb | ||
|
|
2745af3d0d | ||
|
|
72bb017834 | ||
|
|
57bf8c6472 | ||
|
|
066a15c2af | ||
|
|
f96c69bb42 |
@@ -1,14 +1,16 @@
|
|||||||
# MobArenaStats [](https://github.com/garbagemule/MobArenaStats/actions/workflows/build.yml)
|
# MobArenaStats [](https://github.com/mobarena/MobArenaStats/actions/workflows/build.yml)
|
||||||
|
|
||||||
MobArenaStats is a _plugin extension_ for [MobArena](https://github.com/garbagemule/MobArena).
|
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.
|
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.
|
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
|
## Getting Started
|
||||||
|
|
||||||
Download a copy of the latest MobArenaStats build and place it in your server's `plugins` folder.
|
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.
|
Start your server and let the plugin load.
|
||||||
It will generate a default `config.yml` file and set up a default SQLite data store.
|
It will generate a default `config.yml` file and set up a default SQLite data store.
|
||||||
|
|||||||
@@ -34,11 +34,11 @@
|
|||||||
<version>2.2.1</version>
|
<version>2.2.1</version>
|
||||||
</dependency>
|
</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>
|
<dependency>
|
||||||
<groupId>org.bukkit</groupId>
|
<groupId>org.spigotmc</groupId>
|
||||||
<artifactId>bukkit</artifactId>
|
<artifactId>spigot-api</artifactId>
|
||||||
<version>1.13-R0.1-SNAPSHOT</version>
|
<version>1.17-R0.1-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
<version>8.0.25</version>
|
<version>8.0.28</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>spigot-repo</id>
|
<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>
|
||||||
|
|
||||||
<repository>
|
<repository>
|
||||||
@@ -157,7 +157,8 @@
|
|||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.8.1</version>
|
<version>3.8.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<release>11</release>
|
<source>11</source>
|
||||||
|
<target>11</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,11 @@ public class Session {
|
|||||||
|
|
||||||
public void playerLeave(Arena arena, Player player) {
|
public void playerLeave(Arena arena, Player player) {
|
||||||
UUID playerId = player.getUniqueId();
|
UUID playerId = player.getUniqueId();
|
||||||
|
if (sessionStats.startTime == null) {
|
||||||
|
playerStats.remove(playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PlayerSessionStats stats = playerStats.get(playerId);
|
PlayerSessionStats stats = playerStats.get(playerId);
|
||||||
if (stats == null) {
|
if (stats == null) {
|
||||||
return;
|
return;
|
||||||
@@ -63,6 +68,11 @@ public class Session {
|
|||||||
|
|
||||||
public void playerDeath(Arena arena, Player player) {
|
public void playerDeath(Arena arena, Player player) {
|
||||||
UUID playerId = player.getUniqueId();
|
UUID playerId = player.getUniqueId();
|
||||||
|
if (sessionStats.startTime == null) {
|
||||||
|
playerStats.remove(playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PlayerSessionStats stats = playerStats.get(playerId);
|
PlayerSessionStats stats = playerStats.get(playerId);
|
||||||
if (stats == null) {
|
if (stats == null) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ public class SessionListener implements Listener {
|
|||||||
Arena arena = event.getArena();
|
Arena arena = event.getArena();
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
|
|
||||||
|
if (arena.inSpec(player)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Session session = sessionStore.getByArena(arena);
|
Session session = sessionStore.getByArena(arena);
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
log.warning("Unexpected leave event for non-existent session of arena " + arena.getSlug());
|
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);
|
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
|
@Test
|
||||||
void logsWarningIfPlayerLeavesInNonExistentSession() {
|
void logsWarningIfPlayerLeavesInNonExistentSession() {
|
||||||
Player player = mock(Player.class);
|
Player player = mock(Player.class);
|
||||||
Arena arena = mock(Arena.class);
|
Arena arena = mock(Arena.class);
|
||||||
|
when(arena.inSpec(player)).thenReturn(false);
|
||||||
when(sessionStore.getByArena(arena)).thenReturn(null);
|
when(sessionStore.getByArena(arena)).thenReturn(null);
|
||||||
ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(player, arena);
|
ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(player, arena);
|
||||||
|
|
||||||
@@ -127,6 +140,7 @@ class SessionListenerTest {
|
|||||||
Player player = mock(Player.class);
|
Player player = mock(Player.class);
|
||||||
Arena arena = mock(Arena.class);
|
Arena arena = mock(Arena.class);
|
||||||
Session session = mock(Session.class);
|
Session session = mock(Session.class);
|
||||||
|
when(arena.inSpec(player)).thenReturn(false);
|
||||||
when(arena.isRunning()).thenReturn(false);
|
when(arena.isRunning()).thenReturn(false);
|
||||||
when(arena.getPlayersInLobby()).thenReturn(Collections.singleton(player));
|
when(arena.getPlayersInLobby()).thenReturn(Collections.singleton(player));
|
||||||
when(sessionStore.getByArena(arena)).thenReturn(session);
|
when(sessionStore.getByArena(arena)).thenReturn(session);
|
||||||
@@ -142,6 +156,7 @@ class SessionListenerTest {
|
|||||||
Player player = mock(Player.class);
|
Player player = mock(Player.class);
|
||||||
Arena arena = mock(Arena.class);
|
Arena arena = mock(Arena.class);
|
||||||
Session session = mock(Session.class);
|
Session session = mock(Session.class);
|
||||||
|
when(arena.inSpec(player)).thenReturn(false);
|
||||||
when(arena.isRunning()).thenReturn(false);
|
when(arena.isRunning()).thenReturn(false);
|
||||||
when(arena.getPlayersInLobby()).thenReturn(Collections.singleton(player));
|
when(arena.getPlayersInLobby()).thenReturn(Collections.singleton(player));
|
||||||
when(sessionStore.getByArena(arena)).thenReturn(session);
|
when(sessionStore.getByArena(arena)).thenReturn(session);
|
||||||
@@ -158,6 +173,7 @@ class SessionListenerTest {
|
|||||||
Player other = mock(Player.class);
|
Player other = mock(Player.class);
|
||||||
Arena arena = mock(Arena.class);
|
Arena arena = mock(Arena.class);
|
||||||
Session session = mock(Session.class);
|
Session session = mock(Session.class);
|
||||||
|
when(arena.inSpec(player)).thenReturn(false);
|
||||||
when(arena.isRunning()).thenReturn(false);
|
when(arena.isRunning()).thenReturn(false);
|
||||||
when(arena.getPlayersInLobby()).thenReturn(new HashSet<>(Arrays.asList(player, other)));
|
when(arena.getPlayersInLobby()).thenReturn(new HashSet<>(Arrays.asList(player, other)));
|
||||||
when(sessionStore.getByArena(arena)).thenReturn(session);
|
when(sessionStore.getByArena(arena)).thenReturn(session);
|
||||||
@@ -173,6 +189,7 @@ class SessionListenerTest {
|
|||||||
Player player = mock(Player.class);
|
Player player = mock(Player.class);
|
||||||
Arena arena = mock(Arena.class);
|
Arena arena = mock(Arena.class);
|
||||||
Session session = mock(Session.class);
|
Session session = mock(Session.class);
|
||||||
|
when(arena.inSpec(player)).thenReturn(false);
|
||||||
when(arena.isRunning()).thenReturn(true);
|
when(arena.isRunning()).thenReturn(true);
|
||||||
when(sessionStore.getByArena(arena)).thenReturn(session);
|
when(sessionStore.getByArena(arena)).thenReturn(session);
|
||||||
ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(player, arena);
|
ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(player, arena);
|
||||||
|
|||||||
@@ -95,6 +95,19 @@ class SessionTest {
|
|||||||
assertThat(actual.className, equalTo(className));
|
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
|
@Test
|
||||||
void setLeaveTimeOnLeave() {
|
void setLeaveTimeOnLeave() {
|
||||||
UUID playerId = UUID.fromString("cafebabe-ea75-dead-beef-deadcafebabe");
|
UUID playerId = UUID.fromString("cafebabe-ea75-dead-beef-deadcafebabe");
|
||||||
@@ -103,6 +116,7 @@ class SessionTest {
|
|||||||
ArenaPlayer ap = mock(ArenaPlayer.class);
|
ArenaPlayer ap = mock(ArenaPlayer.class);
|
||||||
when(arena.getArenaPlayer(player)).thenReturn(ap);
|
when(arena.getArenaPlayer(player)).thenReturn(ap);
|
||||||
subject.playerJoin(player);
|
subject.playerJoin(player);
|
||||||
|
subject.start();
|
||||||
|
|
||||||
subject.playerLeave(arena, player);
|
subject.playerLeave(arena, player);
|
||||||
|
|
||||||
@@ -118,6 +132,7 @@ class SessionTest {
|
|||||||
ArenaPlayer ap = mock(ArenaPlayer.class);
|
ArenaPlayer ap = mock(ArenaPlayer.class);
|
||||||
when(arena.getArenaPlayer(player)).thenReturn(ap);
|
when(arena.getArenaPlayer(player)).thenReturn(ap);
|
||||||
subject.playerJoin(player);
|
subject.playerJoin(player);
|
||||||
|
subject.start();
|
||||||
|
|
||||||
subject.playerLeave(arena, player);
|
subject.playerLeave(arena, player);
|
||||||
|
|
||||||
@@ -133,6 +148,7 @@ class SessionTest {
|
|||||||
ArenaPlayer ap = mock(ArenaPlayer.class);
|
ArenaPlayer ap = mock(ArenaPlayer.class);
|
||||||
when(arena.getArenaPlayer(player)).thenReturn(ap);
|
when(arena.getArenaPlayer(player)).thenReturn(ap);
|
||||||
subject.playerJoin(player);
|
subject.playerJoin(player);
|
||||||
|
subject.start();
|
||||||
subject.getPlayerStats(playerId).conclusion = PlayerConclusion.VICTORY;
|
subject.getPlayerStats(playerId).conclusion = PlayerConclusion.VICTORY;
|
||||||
|
|
||||||
subject.playerLeave(arena, player);
|
subject.playerLeave(arena, player);
|
||||||
@@ -141,6 +157,19 @@ class SessionTest {
|
|||||||
assertThat(actual.conclusion, not(equalTo(PlayerConclusion.RETREAT)));
|
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
|
@Test
|
||||||
void setDeathTimeOnDeath() {
|
void setDeathTimeOnDeath() {
|
||||||
UUID playerId = UUID.fromString("cafebabe-ea75-dead-beef-deadcafebabe");
|
UUID playerId = UUID.fromString("cafebabe-ea75-dead-beef-deadcafebabe");
|
||||||
@@ -149,6 +178,7 @@ class SessionTest {
|
|||||||
ArenaPlayer ap = mock(ArenaPlayer.class);
|
ArenaPlayer ap = mock(ArenaPlayer.class);
|
||||||
when(arena.getArenaPlayer(player)).thenReturn(ap);
|
when(arena.getArenaPlayer(player)).thenReturn(ap);
|
||||||
subject.playerJoin(player);
|
subject.playerJoin(player);
|
||||||
|
subject.start();
|
||||||
|
|
||||||
subject.playerDeath(arena, player);
|
subject.playerDeath(arena, player);
|
||||||
|
|
||||||
@@ -164,6 +194,7 @@ class SessionTest {
|
|||||||
ArenaPlayer ap = mock(ArenaPlayer.class);
|
ArenaPlayer ap = mock(ArenaPlayer.class);
|
||||||
when(arena.getArenaPlayer(player)).thenReturn(ap);
|
when(arena.getArenaPlayer(player)).thenReturn(ap);
|
||||||
subject.playerJoin(player);
|
subject.playerJoin(player);
|
||||||
|
subject.start();
|
||||||
|
|
||||||
subject.playerDeath(arena, player);
|
subject.playerDeath(arena, player);
|
||||||
|
|
||||||
@@ -179,6 +210,7 @@ class SessionTest {
|
|||||||
ArenaPlayer ap = mock(ArenaPlayer.class);
|
ArenaPlayer ap = mock(ArenaPlayer.class);
|
||||||
when(arena.getArenaPlayer(player)).thenReturn(ap);
|
when(arena.getArenaPlayer(player)).thenReturn(ap);
|
||||||
subject.playerJoin(player);
|
subject.playerJoin(player);
|
||||||
|
subject.start();
|
||||||
subject.getPlayerStats(playerId).conclusion = PlayerConclusion.VICTORY;
|
subject.getPlayerStats(playerId).conclusion = PlayerConclusion.VICTORY;
|
||||||
|
|
||||||
subject.playerDeath(arena, player);
|
subject.playerDeath(arena, player);
|
||||||
@@ -246,6 +278,7 @@ class SessionTest {
|
|||||||
when(arena.getArenaPlayer(corpse)).thenReturn(ap);
|
when(arena.getArenaPlayer(corpse)).thenReturn(ap);
|
||||||
subject.playerJoin(corpse);
|
subject.playerJoin(corpse);
|
||||||
subject.playerJoin(survivor);
|
subject.playerJoin(survivor);
|
||||||
|
subject.start();
|
||||||
subject.playerDeath(arena, corpse);
|
subject.playerDeath(arena, corpse);
|
||||||
|
|
||||||
subject.complete();
|
subject.complete();
|
||||||
|
|||||||
Reference in New Issue
Block a user