Plan/Plan/common/src/test/java/com/djrapitops/plan/gathering/events/PlayerLeaveEventConsumerTes...

268 lines
12 KiB
Java

/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.gathering.events;
import com.djrapitops.plan.PlanSystem;
import com.djrapitops.plan.extension.DataExtension;
import com.djrapitops.plan.extension.ExtensionService;
import com.djrapitops.plan.extension.annotation.NumberProvider;
import com.djrapitops.plan.extension.annotation.PluginInfo;
import com.djrapitops.plan.gathering.cache.SessionCache;
import com.djrapitops.plan.gathering.domain.*;
import com.djrapitops.plan.gathering.domain.event.JoinAddress;
import com.djrapitops.plan.gathering.domain.event.PlayerLeave;
import com.djrapitops.plan.identification.Server;
import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
import com.djrapitops.plan.settings.config.paths.ExportSettings;
import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.SQLDB;
import com.djrapitops.plan.storage.database.queries.objects.JoinAddressQueries;
import com.djrapitops.plan.storage.database.queries.objects.SessionQueries;
import com.djrapitops.plan.storage.database.queries.objects.UserInfoQueries;
import com.djrapitops.plan.storage.database.sql.tables.JoinAddressTable;
import com.djrapitops.plan.storage.database.transactions.StoreServerInformationTransaction;
import com.djrapitops.plan.storage.database.transactions.commands.RemoveEverythingTransaction;
import com.djrapitops.plan.storage.database.transactions.events.StoreJoinAddressTransaction;
import com.djrapitops.plan.storage.database.transactions.events.StoreServerPlayerTransaction;
import com.djrapitops.plan.storage.database.transactions.events.StoreWorldNameTransaction;
import extension.FullSystemExtension;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testcontainers.shaded.org.awaitility.Awaitility;
import utilities.TestConstants;
import utilities.dagger.PlanPluginComponent;
import utilities.mocks.objects.TestPlayerData;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ExtendWith(FullSystemExtension.class)
class PlayerLeaveEventConsumerTest {
private static Server server;
private static PlayerLeaveEventConsumer underTest;
@BeforeAll
static void beforeAll(PlanConfig config, PlanSystem system, PlanPluginComponent component) {
config.set(DataGatheringSettings.GEOLOCATIONS, true);
config.set(DataGatheringSettings.ACCEPT_GEOLITE2_EULA, true);
system.enable();
server = system.getServerInfo().getServer();
underTest = component.leaveConsumer();
}
@AfterAll
static void afterAll(PlanSystem system, Database database) throws ExecutionException, InterruptedException {
database.executeTransaction(new RemoveEverythingTransaction()).get();
system.disable();
SessionCache.clear();
}
@BeforeEach
void resetSystem(PlanConfig config, Database database, ServerUUID serverUUID) {
SessionCache.clear();
config.set(ExportSettings.PLAYER_PAGES, false);
config.set(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE, false);
config.set(DataGatheringSettings.PRESERVE_JOIN_ADDRESS_CASE, false);
database.executeTransaction(new RemoveEverythingTransaction());
database.executeTransaction(new StoreServerInformationTransaction(new Server(serverUUID, TestConstants.SERVER_NAME, "", TestConstants.VERSION)));
}
private void waitUntilDatabaseIsDone(Database database) {
Awaitility.await()
.atMost(2, TimeUnit.SECONDS)
.until(() -> ((SQLDB) database).getTransactionQueueSize() < 1);
}
PlayerLeave createPlayerLeave(PlatformPlayerData player) {
return PlayerLeave.builder()
.time(System.currentTimeMillis())
.server(server)
.player(player)
.build();
}
private TestPlayerData createTestPlayer() {
return new TestPlayerData(TestConstants.PLAYER_ONE_UUID, TestConstants.PLAYER_ONE_NAME);
}
@Test
void leavingGameServerSavesSession(PlanSystem system, Database database, ServerUUID serverUUID) {
SessionCache sessionCache = system.getCacheSystem().getSessionCache();
long sessionStart = System.currentTimeMillis();
sessionCache.cacheSession(TestConstants.PLAYER_ONE_UUID, new ActiveSession(TestConstants.PLAYER_ONE_UUID, serverUUID, sessionStart, "World", GMTimes.SURVIVAL));
database.executeTransaction(new StoreWorldNameTransaction(serverUUID, "World"));
PlayerLeave leave = createPlayerLeave(createTestPlayer());
underTest.onLeaveGameServer(leave);
waitUntilDatabaseIsDone(database);
DataMap extraData = new DataMap();
GMTimes gmTimes = new GMTimes(Map.of(
GMTimes.SURVIVAL, leave.getTime() - sessionStart,
GMTimes.CREATIVE, 0L,
GMTimes.SPECTATOR, 0L,
GMTimes.ADVENTURE, 0L
));
extraData.put(WorldTimes.class, new WorldTimes(Map.of("World", gmTimes)));
extraData.put(PlayerKills.class, new PlayerKills());
extraData.put(MobKillCounter.class, new MobKillCounter());
extraData.put(DeathCounter.class, new DeathCounter());
extraData.put(JoinAddress.class, new JoinAddress(JoinAddressTable.DEFAULT_VALUE_FOR_LOOKUP));
List<FinishedSession> expected = List.of(new FinishedSession(
TestConstants.PLAYER_ONE_UUID,
serverUUID,
sessionStart,
leave.getTime(),
0L,
extraData
));
List<FinishedSession> result = database.query(SessionQueries.fetchAllSessions());
assertEquals(expected, result);
}
@Test
void leavingGameServerSavesBanStatus(PlanSystem system, Database database, ServerUUID serverUUID) {
SessionCache sessionCache = system.getCacheSystem().getSessionCache();
long sessionStart = System.currentTimeMillis();
sessionCache.cacheSession(TestConstants.PLAYER_ONE_UUID, new ActiveSession(TestConstants.PLAYER_ONE_UUID, serverUUID, sessionStart, "World", GMTimes.SURVIVAL));
registerPlayer(database, serverUUID);
PlayerLeave leave = createPlayerLeave(createTestPlayer()
.setBanned(true));
underTest.onLeaveGameServer(leave);
waitUntilDatabaseIsDone(database);
Set<Integer> result = database.query(UserInfoQueries.userIdsOfBanned());
assertEquals(1, result.size());
result = database.query(UserInfoQueries.userIdsOfNotBanned());
assertEquals(0, result.size());
}
@Test
void leavingGameServerExportsPlayerPage(PlanConfig config, Database database, ServerUUID serverUUID) {
registerPlayer(database, serverUUID);
config.set(ExportSettings.PLAYER_PAGES, true);
config.set(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE, true);
PlayerLeave leave = createPlayerLeave(createTestPlayer());
underTest.onLeaveGameServer(leave);
File playerExportDir = config.getPageExportPath().resolve("player/" + TestConstants.PLAYER_ONE_UUID).toFile();
Awaitility.await()
.atMost(2, TimeUnit.SECONDS)
.until(playerExportDir::exists);
assertTrue(playerExportDir.exists());
assertTrue(playerExportDir.isDirectory());
}
@Test
void leavingProxyServerExportsPlayerPage(PlanConfig config, Database database, ServerUUID serverUUID) {
registerPlayer(database, serverUUID);
config.set(ExportSettings.PLAYER_PAGES, true);
config.set(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE, true);
PlayerLeave leave = createPlayerLeave(createTestPlayer());
underTest.onLeaveProxyServer(leave);
File playerExportDir = config.getPageExportPath().resolve("player/" + TestConstants.PLAYER_ONE_UUID).toFile();
Awaitility.await()
.atMost(2, TimeUnit.SECONDS)
.until(playerExportDir::exists);
assertTrue(playerExportDir.exists());
assertTrue(playerExportDir.isDirectory());
}
private void registerPlayer(Database database, ServerUUID serverUUID) {
database.executeTransaction(new StoreServerPlayerTransaction(TestConstants.PLAYER_ONE_UUID, System::currentTimeMillis, TestConstants.PLAYER_ONE_NAME, serverUUID, () -> null))
.join(); // Wait until complete
}
@Test
void extensionDataIsUpdatedBeforeLeave() {
AtomicBoolean called = new AtomicBoolean(false);
@PluginInfo(name = "Extension")
class Extension implements DataExtension {
@NumberProvider(text = "Value")
public long value(UUID playerUUID) {
called.set(true);
return 0L;
}
}
Extension extension = new Extension();
try {
ExtensionService.getInstance().register(extension);
underTest.beforeLeave(createPlayerLeave(createTestPlayer()));
Awaitility.await()
.atMost(2, TimeUnit.SECONDS)
.until(called::get);
assertTrue(called.get());
} finally {
ExtensionService.getInstance().unregister(extension);
}
}
@Test
void joinAddressCaseIsPreserved(PlanSystem system, PlanConfig config, Database database, ServerUUID serverUUID) {
config.set(DataGatheringSettings.PRESERVE_JOIN_ADDRESS_CASE, true);
SessionCache sessionCache = system.getCacheSystem().getSessionCache();
long sessionStart = System.currentTimeMillis();
ActiveSession activeSession = new ActiveSession(TestConstants.PLAYER_ONE_UUID, serverUUID, sessionStart, "World", GMTimes.SURVIVAL);
activeSession.getExtraData().put(JoinAddress.class, new JoinAddress("PLAY.UPPERCASE.COM"));
sessionCache.cacheSession(TestConstants.PLAYER_ONE_UUID, activeSession);
database.executeTransaction(new StoreJoinAddressTransaction("play.uppercase.com")); // The wrong address
database.executeTransaction(new StoreWorldNameTransaction(serverUUID, "World"));
PlayerLeave leave = createPlayerLeave(createTestPlayer()
.setJoinAddress("PLAY.UPPERCASE.COM"));
underTest.onLeaveGameServer(leave);
waitUntilDatabaseIsDone(database);
List<String> expected = List.of("PLAY.UPPERCASE.COM", "play.uppercase.com", JoinAddressTable.DEFAULT_VALUE_FOR_LOOKUP);
List<String> result = database.query(JoinAddressQueries.allJoinAddresses());
assertEquals(expected, result);
}
}