diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/TablePlayer.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/TablePlayer.java index 660e60f31..b84b3905a 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/TablePlayer.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/TablePlayer.java @@ -119,6 +119,21 @@ public class TablePlayer implements Comparable { return Objects.hash(name, activityIndex, playtime, sessionCount, registered, lastSeen, geolocation); } + @Override + public String toString() { + return "TablePlayer{" + + "uuid=" + uuid + + ", name='" + name + '\'' + + ", activityIndex=" + activityIndex + + ", playtime=" + playtime + + ", sessionCount=" + sessionCount + + ", registered=" + registered + + ", lastSeen=" + lastSeen + + ", geolocation='" + geolocation + '\'' + + ", banned=" + banned + + '}'; + } + public static class Builder { private final TablePlayer player; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/Session.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/Session.java index b6e0528e4..c4b9fcf74 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/Session.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/Session.java @@ -19,6 +19,7 @@ package com.djrapitops.plan.gathering.domain; import com.djrapitops.plan.delivery.domain.DateHolder; import com.djrapitops.plan.delivery.domain.container.DynamicDataContainer; import com.djrapitops.plan.delivery.domain.keys.SessionKeys; +import com.djrapitops.plan.utilities.comparators.DateHolderRecentComparator; import java.util.ArrayList; import java.util.List; @@ -183,7 +184,7 @@ public class Session extends DynamicDataContainer implements DateHolder { getValue(SessionKeys.END).orElse(-1L).equals(session.getValue(SessionKeys.END).orElse(-1L)) && mobKills == session.mobKills && deaths == session.deaths && - Objects.equals(playerKills, session.playerKills) && + Objects.equals(getPlayerKills(), session.getPlayerKills()) && Objects.equals(worldTimes, session.worldTimes); } @@ -210,6 +211,7 @@ public class Session extends DynamicDataContainer implements DateHolder { } public List getPlayerKills() { + playerKills.sort(new DateHolderRecentComparator()); return playerKills; } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/H2DB.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/H2DB.java index 226f48983..35b2a5b9b 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/H2DB.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/H2DB.java @@ -143,6 +143,8 @@ public class H2DB extends SQLDB { logger.debug("H2 Connection close prompted by: " + ThrowableUtils.findCallerAfterClass(Thread.currentThread().getStackTrace(), H2DB.class)); logger.debug("H2 " + dbName + ": Closed Connection"); MiscUtils.close(connection); + } else { + logger.debug("H2 " + dbName + ": Connection was null when closing"); } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/SessionQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/SessionQueries.java index 40a488e40..50bd18035 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/SessionQueries.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/SessionQueries.java @@ -155,7 +155,7 @@ public class SessionQueries { // Utilities String[] gms = GMTimes.getGMKeyArray(); - Comparator dateColderRecentComparator = new DateHolderRecentComparator(); + Comparator mostRecentFirst = new DateHolderRecentComparator(); Comparator longRecentComparator = (one, two) -> Long.compare(two, one); // Descending order, most recent first. while (set.next()) { @@ -197,8 +197,10 @@ public class SessionQueries { long date = set.getLong(KillsTable.DATE); String weapon = set.getString(KillsTable.WEAPON); List playerKills = session.getPlayerKills(); - playerKills.add(new PlayerKill(victim, weapon, date, victimName)); - playerKills.sort(dateColderRecentComparator); + PlayerKill newKill = new PlayerKill(victim, weapon, date, victimName); + if (!playerKills.contains(newKill)) { + playerKills.add(newKill); + } } session.putRawData(SessionKeys.NAME, set.getString("name")); @@ -214,7 +216,7 @@ public class SessionQueries { .flatMap(Collection::stream) .map(SortedMap::values) .flatMap(Collection::stream) - .sorted(dateColderRecentComparator) // Disorder arises + .sorted(mostRecentFirst) // Disorder arises .collect(Collectors.toList()); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/sql/tables/KillsTable.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/sql/tables/KillsTable.java index 07675dc81..611f5417f 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/sql/tables/KillsTable.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/sql/tables/KillsTable.java @@ -53,6 +53,8 @@ public class KillsTable { public static final String WEAPON = "weapon"; public static final String DATE = "date"; + public static final int WEAPON_COLUMN_LENGTH = 30; + public static final String INSERT_STATEMENT = "INSERT INTO " + TABLE_NAME + " (" + SESSION_ID + ',' + KILLER_UUID + ',' @@ -72,7 +74,7 @@ public class KillsTable { .column(KILLER_UUID, Sql.varchar(36)).notNull() .column(VICTIM_UUID, Sql.varchar(36)).notNull() .column(SERVER_UUID, Sql.varchar(36)).notNull() - .column(WEAPON, Sql.varchar(30)).notNull() + .column(WEAPON, Sql.varchar(WEAPON_COLUMN_LENGTH)).notNull() .column(DATE, Sql.LONG).notNull() .column(SESSION_ID, Sql.INT).notNull() .foreignKey(SESSION_ID, SessionsTable.TABLE_NAME, SessionsTable.ID) @@ -95,7 +97,7 @@ public class KillsTable { statement.setString(6, kill.getVictim().toString()); statement.setString(7, serverUUID.toString()); statement.setLong(8, kill.getDate()); - statement.setString(9, StringUtils.truncate(kill.getWeapon(), 30)); + statement.setString(9, StringUtils.truncate(kill.getWeapon(), WEAPON_COLUMN_LENGTH)); statement.addBatch(); } } diff --git a/Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/JSErrorRegressionTest.java b/Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/JSErrorRegressionTest.java index a56b13029..7502166f4 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/JSErrorRegressionTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/JSErrorRegressionTest.java @@ -77,7 +77,7 @@ class JSErrorRegressionTest { DBSystem dbSystem = bukkitSystem.getDatabaseSystem(); Database database = dbSystem.getDatabase(); UUID uuid = TestConstants.PLAYER_ONE_UUID; - database.executeTransaction(new PlayerRegisterTransaction(uuid, () -> 1000L, "name")); + database.executeTransaction(new PlayerRegisterTransaction(uuid, RandomData::randomTime, "name")); Session session = new Session(uuid, serverUUID, 1000L, "world", "SURVIVAL"); session.endSession(11000L); database.executeTransaction(new WorldNameStoreTransaction(serverUUID, "world")); diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/DatabaseTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/DatabaseTest.java index ed581b4f7..dd54c27fe 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/DatabaseTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/DatabaseTest.java @@ -26,7 +26,6 @@ import com.djrapitops.plan.delivery.domain.keys.Key; import com.djrapitops.plan.delivery.domain.keys.PlayerKeys; import com.djrapitops.plan.delivery.domain.keys.ServerKeys; import com.djrapitops.plan.delivery.domain.keys.SessionKeys; -import com.djrapitops.plan.delivery.domain.mutators.SessionsMutator; import com.djrapitops.plan.gathering.domain.*; import com.djrapitops.plan.identification.Server; import com.djrapitops.plan.query.QuerySvc; @@ -187,80 +186,12 @@ public interface DatabaseTest extends DatabaseTestPreparer { return kills; } - @Test - default void testSessionPlaytimeSaving() { - saveTwoWorlds(); - saveUserOne(); - saveUserTwo(); - Session session = new Session(playerUUID, serverUUID(), 12345L, worlds[0], "SURVIVAL"); - session.endSession(22345L); - session.setWorldTimes(createWorldTimes()); - session.setPlayerKills(createKills()); - - long expectedLength = 10000L; - assertEquals(expectedLength, session.getLength()); - assertEquals(expectedLength, session.getUnsafe(SessionKeys.WORLD_TIMES).getTotal()); - - execute(DataStoreQueries.storeSession(session)); - - forcePersistenceCheck(); - - Map> sessions = db().query(SessionQueries.fetchSessionsOfPlayer(playerUUID)); - assertTrue(sessions.containsKey(serverUUID())); - - SessionsMutator sessionsMutator = new SessionsMutator(sessions.get(serverUUID())); - SessionsMutator afterTimeSessionsMutator = sessionsMutator.filterSessionsBetween(30000, System.currentTimeMillis()); - - assertEquals(expectedLength, sessionsMutator.toPlaytime()); - assertEquals(0L, afterTimeSessionsMutator.toPlaytime()); - - assertEquals(1, sessionsMutator.count()); - assertEquals(0, afterTimeSessionsMutator.count()); - } - - @Test - default void sessionsAreStoredWithAllData() { - saveUserOne(); - saveUserTwo(); - - Session session = new Session(playerUUID, serverUUID(), 12345L, worlds[0], "SURVIVAL"); - session.endSession(22345L); - session.setWorldTimes(createWorldTimes()); - session.setPlayerKills(createKills()); - - execute(DataStoreQueries.storeSession(session)); - - forcePersistenceCheck(); - - Map> sessions = db().query(SessionQueries.fetchSessionsOfPlayer(playerUUID)); - List savedSessions = sessions.get(serverUUID()); - - assertNotNull(savedSessions); - assertEquals(1, savedSessions.size()); - - assertEquals(session, savedSessions.get(0)); - } - - @Test - default void mostRecentSessionsCanBeQueried() { - sessionsAreStoredWithAllData(); - - Session session = new Session(playerUUID, serverUUID(), 12345L, worlds[0], "SURVIVAL"); - session.endSession(22345L); - session.setWorldTimes(createWorldTimes()); - session.setPlayerKills(createKills()); - - List expected = Collections.singletonList(session); - List result = db().query(SessionQueries.fetchLatestSessionsOfServer(serverUUID(), 1)); - assertEquals(expected, result); - } - @Test default void userInfoTableStoresCorrectUserInformation() { saveUserOne(); List userInfo = db().query(UserInfoQueries.fetchUserInformationOfUser(playerUUID)); - List expected = Collections.singletonList(new UserInfo(playerUUID, serverUUID(), 1000L, false, false)); + List expected = Collections.singletonList(new UserInfo(playerUUID, serverUUID(), TestConstants.REGISTER_TIME, false, false)); assertEquals(expected, userInfo); } @@ -272,7 +203,7 @@ public interface DatabaseTest extends DatabaseTestPreparer { db().executeTransaction(new BanStatusTransaction(playerUUID, () -> true)); List userInfo = db().query(UserInfoQueries.fetchUserInformationOfUser(playerUUID)); - List expected = Collections.singletonList(new UserInfo(playerUUID, serverUUID(), 1000L, false, true)); + List expected = Collections.singletonList(new UserInfo(playerUUID, serverUUID(), TestConstants.REGISTER_TIME, false, true)); assertEquals(expected, userInfo); } @@ -284,7 +215,7 @@ public interface DatabaseTest extends DatabaseTestPreparer { db().executeTransaction(new OperatorStatusTransaction(playerUUID, true)); List userInfo = db().query(UserInfoQueries.fetchUserInformationOfUser(playerUUID)); - List expected = Collections.singletonList(new UserInfo(playerUUID, serverUUID(), 1000L, true, false)); + List expected = Collections.singletonList(new UserInfo(playerUUID, serverUUID(), TestConstants.REGISTER_TIME, true, false)); assertEquals(expected, userInfo); } @@ -296,7 +227,7 @@ public interface DatabaseTest extends DatabaseTestPreparer { OptionalAssert.equals(playerUUID, db().query(UserIdentifierQueries.fetchPlayerUUIDOf(TestConstants.PLAYER_ONE_NAME))); // Updates the name - db().executeTransaction(new PlayerRegisterTransaction(playerUUID, () -> 0, "NewName")); + db().executeTransaction(new PlayerRegisterTransaction(playerUUID, RandomData::randomTime, "NewName")); forcePersistenceCheck(); assertFalse(db().query(UserIdentifierQueries.fetchPlayerUUIDOf(TestConstants.PLAYER_ONE_NAME)).isPresent()); @@ -606,75 +537,10 @@ public interface DatabaseTest extends DatabaseTestPreparer { assertEquals(worldTimes, savedSession.getUnsafe(SessionKeys.WORLD_TIMES)); } - @Test - default void worldTimesAreSavedWithAllSessionSave() { - saveTwoWorlds(); - saveUserOne(); - - WorldTimes worldTimes = createWorldTimes(); - - Session session = createSession(); - session.setWorldTimes(worldTimes); - List sessions = new ArrayList<>(); - sessions.add(session); - db().executeTransaction(new Transaction() { - @Override - protected void performOperations() { - execute(LargeStoreQueries.storeAllSessionsWithKillAndWorldData(sessions)); - } - }); - - Map saved = db().query(WorldTimesQueries.fetchPlayerWorldTimesOnServers(playerUUID)); - WorldTimes savedWorldTimes = saved.get(serverUUID()); - assertEquals(worldTimes, savedWorldTimes); - } - - @Test - default void worldTimesAreSavedWithSession() { - saveTwoWorlds(); - saveUserOne(); - - WorldTimes worldTimes = createWorldTimes(); - Session session = createSession(); - session.setWorldTimes(worldTimes); - List sessions = new ArrayList<>(); - sessions.add(session); - db().executeTransaction(new Transaction() { - @Override - protected void performOperations() { - execute(LargeStoreQueries.storeAllSessionsWithKillAndWorldData(sessions)); - } - }); - - List allSessions = db().query(SessionQueries.fetchAllSessions()); - - assertEquals(worldTimes, allSessions.get(0).getUnsafe(SessionKeys.WORLD_TIMES)); - } - - @Test - default void playersWorldTimesMatchTotal() { - worldTimesAreSavedWithSession(); - WorldTimes worldTimesOfUser = db().query(WorldTimesQueries.fetchPlayerTotalWorldTimes(playerUUID)); - assertEquals(createWorldTimes(), worldTimesOfUser); - } - - @Test - default void serverWorldTimesMatchTotal() { - worldTimesAreSavedWithSession(); - WorldTimes worldTimesOfServer = db().query(WorldTimesQueries.fetchServerTotalWorldTimes(serverUUID())); - assertEquals(createWorldTimes(), worldTimesOfServer); - } - - @Test - default void emptyServerWorldTimesIsEmpty() { - WorldTimes worldTimesOfServer = db().query(WorldTimesQueries.fetchServerTotalWorldTimes(serverUUID())); - assertEquals(new WorldTimes(), worldTimesOfServer); - } - @Test default void playerIsRegisteredToUsersTable() { assertFalse(db().query(PlayerFetchQueries.isPlayerRegistered(playerUUID))); - db().executeTransaction(new PlayerRegisterTransaction(playerUUID, () -> 1000L, TestConstants.PLAYER_ONE_NAME)); + db().executeTransaction(new PlayerRegisterTransaction(playerUUID, RandomData::randomTime, TestConstants.PLAYER_ONE_NAME)); assertTrue(db().query(PlayerFetchQueries.isPlayerRegistered(playerUUID))); assertFalse(db().query(PlayerFetchQueries.isPlayerRegisteredOnServer(playerUUID, serverUUID()))); } @@ -683,7 +549,7 @@ public interface DatabaseTest extends DatabaseTestPreparer { default void playerIsRegisteredToBothTables() { assertFalse(db().query(PlayerFetchQueries.isPlayerRegistered(playerUUID))); assertFalse(db().query(PlayerFetchQueries.isPlayerRegisteredOnServer(playerUUID, serverUUID()))); - db().executeTransaction(new PlayerServerRegisterTransaction(playerUUID, () -> 1000L, TestConstants.PLAYER_ONE_NAME, serverUUID())); + db().executeTransaction(new PlayerServerRegisterTransaction(playerUUID, () -> TestConstants.REGISTER_TIME, TestConstants.PLAYER_ONE_NAME, serverUUID())); assertTrue(db().query(PlayerFetchQueries.isPlayerRegistered(playerUUID))); assertTrue(db().query(PlayerFetchQueries.isPlayerRegisteredOnServer(playerUUID, serverUUID()))); } @@ -726,7 +592,7 @@ public interface DatabaseTest extends DatabaseTestPreparer { assertFalse(end - start > TimeUnit.SECONDS.toNanos(1L), () -> "Took too long: " + ((end - start) / 1000000.0) + "ms"); OptionalAssert.equals(playerUUID, container.getValue(PlayerKeys.UUID)); - OptionalAssert.equals(1000L, container.getValue(PlayerKeys.REGISTERED)); + OptionalAssert.equals(TestConstants.REGISTER_TIME, container.getValue(PlayerKeys.REGISTERED)); OptionalAssert.equals(TestConstants.PLAYER_ONE_NAME, container.getValue(PlayerKeys.NAME)); OptionalAssert.equals(1, container.getValue(PlayerKeys.KICK_COUNT)); @@ -749,7 +615,7 @@ public interface DatabaseTest extends DatabaseTestPreparer { PlayerContainer playerContainer = db().query(ContainerFetchQueries.fetchPlayerContainer(playerUUID)); // Active sessions are added after fetching - playerContainer.putRawData(PlayerKeys.ACTIVE_SESSION, RandomData.randomSession()); + playerContainer.putRawData(PlayerKeys.ACTIVE_SESSION, RandomData.randomSession(serverUUID(), worlds, playerUUID)); List unsupported = new ArrayList<>(); List keys = FieldFetcher.getPublicStaticFields(PlayerKeys.class, Key.class); @@ -1026,29 +892,26 @@ public interface DatabaseTest extends DatabaseTestPreparer { @Test default void serverTablePlayersQueryQueriesAtLeastOnePlayer() { - sessionsAreStoredWithAllData(); + db().executeTransaction(new WorldNameStoreTransaction(serverUUID(), worlds[0])); + db().executeTransaction(new WorldNameStoreTransaction(serverUUID(), worlds[1])); + db().executeTransaction(new PlayerServerRegisterTransaction(playerUUID, RandomData::randomTime, TestConstants.PLAYER_ONE_NAME, serverUUID())); + db().executeTransaction(new PlayerServerRegisterTransaction(player2UUID, RandomData::randomTime, TestConstants.PLAYER_TWO_NAME, serverUUID())); + db().executeTransaction(new SessionEndTransaction(RandomData.randomSession(serverUUID(), worlds, playerUUID, player2UUID))); List result = db().query(new ServerTablePlayersQuery(serverUUID(), System.currentTimeMillis(), 10L, 1)); + assertEquals(1, result.size(), () -> "Incorrect query result: " + result); assertNotEquals(Collections.emptyList(), result); } @Test default void networkTablePlayersQueryQueriesAtLeastOnePlayer() { - sessionsAreStoredWithAllData(); + db().executeTransaction(new WorldNameStoreTransaction(serverUUID(), worlds[0])); + db().executeTransaction(new WorldNameStoreTransaction(serverUUID(), worlds[1])); + db().executeTransaction(new PlayerServerRegisterTransaction(playerUUID, RandomData::randomTime, TestConstants.PLAYER_ONE_NAME, serverUUID())); + db().executeTransaction(new PlayerServerRegisterTransaction(player2UUID, RandomData::randomTime, TestConstants.PLAYER_TWO_NAME, serverUUID())); + db().executeTransaction(new SessionEndTransaction(RandomData.randomSession(serverUUID(), worlds, playerUUID, player2UUID))); List result = db().query(new NetworkTablePlayersQuery(System.currentTimeMillis(), 10L, 1)); - assertNotEquals(Collections.emptyList(), result); - } - - @Test - default void kdrCastAsDoubleDoesNotCauseExceptions() { - sessionsAreStoredWithAllData(); - db().executeTransaction(new PlayerServerRegisterTransaction(player2UUID, () -> 123456789L, "Test", serverUUID())); - - Long killCount = db().query(KillQueries.playerKillCount(0L, System.currentTimeMillis(), serverUUID())); - assertEquals(2, killCount); // Ensure the kills were saved - - Double result = db().query(KillQueries.averageKDR(0L, System.currentTimeMillis(), serverUUID())); - assertEquals(1.0, result, 0.1); + assertEquals(1, result.size(), () -> "Incorrect query result: " + result); } } diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/H2Test.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/H2Test.java index 6f434d0d6..d7cdc79fb 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/H2Test.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/H2Test.java @@ -19,6 +19,7 @@ package com.djrapitops.plan.storage.database; import com.djrapitops.plan.PlanSystem; import com.djrapitops.plan.storage.database.queries.ActivityIndexQueriesTest; import com.djrapitops.plan.storage.database.queries.GeolocationQueriesTest; +import com.djrapitops.plan.storage.database.queries.SessionQueriesTest; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.extension.ExtendWith; @@ -42,7 +43,8 @@ import java.util.UUID; public class H2Test implements DatabaseTest, ExtensionsDatabaseTest, ActivityIndexQueriesTest, - GeolocationQueriesTest { + GeolocationQueriesTest, + SessionQueriesTest { private static final int TEST_PORT_NUMBER = RandomData.randomInt(9005, 9500); @@ -58,7 +60,10 @@ public class H2Test implements DatabaseTest, @AfterAll static void disableSystem() { - if (database != null) database.close(); + if (database != null) { + database.close(); + System.out.println("Database state after close: " + database.getState().name()); + } system.disable(); } diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/MySQLTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/MySQLTest.java index cd4ce91eb..d7a3cf35d 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/MySQLTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/MySQLTest.java @@ -19,6 +19,7 @@ package com.djrapitops.plan.storage.database; import com.djrapitops.plan.PlanSystem; import com.djrapitops.plan.storage.database.queries.ActivityIndexQueriesTest; import com.djrapitops.plan.storage.database.queries.GeolocationQueriesTest; +import com.djrapitops.plan.storage.database.queries.SessionQueriesTest; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; @@ -48,7 +49,8 @@ import java.util.UUID; class MySQLTest implements DatabaseTest, ExtensionsDatabaseTest, ActivityIndexQueriesTest, - GeolocationQueriesTest { + GeolocationQueriesTest, + SessionQueriesTest { private static final int TEST_PORT_NUMBER = RandomData.randomInt(9005, 9500); diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/SQLiteTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/SQLiteTest.java index c93c0097c..7aca1c181 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/SQLiteTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/SQLiteTest.java @@ -19,6 +19,7 @@ package com.djrapitops.plan.storage.database; import com.djrapitops.plan.PlanSystem; import com.djrapitops.plan.storage.database.queries.ActivityIndexQueriesTest; import com.djrapitops.plan.storage.database.queries.GeolocationQueriesTest; +import com.djrapitops.plan.storage.database.queries.SessionQueriesTest; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.extension.ExtendWith; @@ -42,7 +43,8 @@ import java.util.UUID; public class SQLiteTest implements DatabaseTest, ExtensionsDatabaseTest, ActivityIndexQueriesTest, - GeolocationQueriesTest { + GeolocationQueriesTest, + SessionQueriesTest { private static final int TEST_PORT_NUMBER = RandomData.randomInt(9005, 9500); diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ActivityIndexQueriesTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ActivityIndexQueriesTest.java index 26c4fdba8..299282713 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ActivityIndexQueriesTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ActivityIndexQueriesTest.java @@ -1,3 +1,19 @@ +/* + * 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 . + */ package com.djrapitops.plan.storage.database.queries; import com.djrapitops.plan.delivery.domain.TablePlayer; @@ -11,6 +27,7 @@ import com.djrapitops.plan.storage.database.queries.objects.SessionQueries; import com.djrapitops.plan.storage.database.transactions.events.PlayerServerRegisterTransaction; import com.djrapitops.plan.storage.database.transactions.events.WorldNameStoreTransaction; import org.junit.jupiter.api.Test; +import utilities.RandomData; import utilities.TestConstants; import java.util.*; @@ -22,7 +39,7 @@ import static org.junit.jupiter.api.Assertions.*; public interface ActivityIndexQueriesTest extends DatabaseTestPreparer { default void storeSessions() { - db().executeTransaction(new PlayerServerRegisterTransaction(playerUUID, () -> 1000L, TestConstants.PLAYER_ONE_NAME, serverUUID())); + db().executeTransaction(new PlayerServerRegisterTransaction(playerUUID, RandomData::randomTime, TestConstants.PLAYER_ONE_NAME, serverUUID())); db().executeTransaction(new WorldNameStoreTransaction(serverUUID(), worlds[0])); Session session = new Session(playerUUID, serverUUID(), 12345L, worlds[0], "SURVIVAL"); diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/GeolocationQueriesTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/GeolocationQueriesTest.java index 0c934b81a..e2739e985 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/GeolocationQueriesTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/GeolocationQueriesTest.java @@ -1,3 +1,19 @@ +/* + * 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 . + */ package com.djrapitops.plan.storage.database.queries; import com.djrapitops.plan.delivery.domain.DateObj; @@ -22,7 +38,7 @@ public interface GeolocationQueriesTest extends DatabaseTestPreparer { @Test default void geoInformationIsStored() { - db().executeTransaction(new PlayerServerRegisterTransaction(playerUUID, () -> 1000L, TestConstants.PLAYER_ONE_NAME, serverUUID())); + db().executeTransaction(new PlayerServerRegisterTransaction(playerUUID, RandomData::randomTime, TestConstants.PLAYER_ONE_NAME, serverUUID())); List expected = RandomData.randomGeoInfo(); for (GeoInfo geoInfo : expected) { diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/SessionQueriesTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/SessionQueriesTest.java new file mode 100644 index 000000000..8d7418759 --- /dev/null +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/SessionQueriesTest.java @@ -0,0 +1,163 @@ +/* + * 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 . + */ +package com.djrapitops.plan.storage.database.queries; + +import com.djrapitops.plan.delivery.domain.keys.SessionKeys; +import com.djrapitops.plan.delivery.domain.mutators.SessionsMutator; +import com.djrapitops.plan.gathering.domain.Session; +import com.djrapitops.plan.gathering.domain.WorldTimes; +import com.djrapitops.plan.storage.database.DatabaseTestPreparer; +import com.djrapitops.plan.storage.database.queries.objects.SessionQueries; +import com.djrapitops.plan.storage.database.queries.objects.WorldTimesQueries; +import com.djrapitops.plan.storage.database.transactions.Transaction; +import com.djrapitops.plan.storage.database.transactions.events.PlayerServerRegisterTransaction; +import com.djrapitops.plan.storage.database.transactions.events.WorldNameStoreTransaction; +import org.junit.jupiter.api.Test; +import utilities.RandomData; +import utilities.TestConstants; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; + +public interface SessionQueriesTest extends DatabaseTestPreparer { + + @Test + default void sessionPlaytimeIsCalculatedCorrectlyAfterStorage() { + prepareForSessionSave(); + + Session session = RandomData.randomSession(serverUUID(), worlds, playerUUID, player2UUID); + long expectedLength = session.getLength(); + long sessionEnd = session.getValue(SessionKeys.END).orElseThrow(AssertionError::new); + + execute(DataStoreQueries.storeSession(session)); + + forcePersistenceCheck(); + + Map> sessions = db().query(SessionQueries.fetchSessionsOfPlayer(playerUUID)); + assertTrue(sessions.containsKey(serverUUID())); + + SessionsMutator sessionsMutator = new SessionsMutator(sessions.get(serverUUID())); + assertEquals(expectedLength, sessionsMutator.toPlaytime()); + assertEquals(1, sessionsMutator.count()); + + SessionsMutator afterTimeSessionsMutator = sessionsMutator.filterSessionsBetween(sessionEnd + 1L, System.currentTimeMillis()); + assertEquals(0L, afterTimeSessionsMutator.toPlaytime()); + assertEquals(0, afterTimeSessionsMutator.count()); + } + + default void prepareForSessionSave() { + db().executeTransaction(new WorldNameStoreTransaction(serverUUID(), worlds[0])); + db().executeTransaction(new WorldNameStoreTransaction(serverUUID(), worlds[1])); + db().executeTransaction(new PlayerServerRegisterTransaction(playerUUID, RandomData::randomTime, TestConstants.PLAYER_ONE_NAME, serverUUID())); + db().executeTransaction(new PlayerServerRegisterTransaction(player2UUID, RandomData::randomTime, TestConstants.PLAYER_TWO_NAME, serverUUID())); + } + + @Test + default void sessionsAreStoredWithAllData() { + prepareForSessionSave(); + Session session = RandomData.randomSession(serverUUID(), worlds, playerUUID, player2UUID); + execute(DataStoreQueries.storeSession(session)); + + forcePersistenceCheck(); + + Map> sessions = db().query(SessionQueries.fetchSessionsOfPlayer(playerUUID)); + List savedSessions = sessions.get(serverUUID()); + + assertNotNull(savedSessions); + assertEquals(1, savedSessions.size()); + + assertEquals(session, savedSessions.get(0)); + } + + @Test + default void mostRecentSessionsCanBeQueried() { + prepareForSessionSave(); + Session session = RandomData.randomSession(serverUUID(), worlds, playerUUID, player2UUID); + execute(DataStoreQueries.storeSession(session)); + + List expected = Collections.singletonList(session); + List result = db().query(SessionQueries.fetchLatestSessionsOfServer(serverUUID(), 1)); + assertEquals(expected, result); + } + + @Test + default void worldTimesAreSavedWithAllSessionSave() { + prepareForSessionSave(); + + WorldTimes worldTimes = RandomData.randomWorldTimes(worlds); + Session session = RandomData.randomSession(serverUUID(), worlds, playerUUID); + session.setWorldTimes(worldTimes); + List sessions = Collections.singletonList(session); + db().executeTransaction(new Transaction() { + @Override + protected void performOperations() { + execute(LargeStoreQueries.storeAllSessionsWithKillAndWorldData(sessions)); + } + }); + + Map saved = db().query(WorldTimesQueries.fetchPlayerWorldTimesOnServers(playerUUID)); + WorldTimes savedWorldTimes = saved.get(serverUUID()); + assertEquals(worldTimes, savedWorldTimes); + } + + @Test + default void worldTimesAreSavedWithSession() { + prepareForSessionSave(); + + WorldTimes worldTimes = RandomData.randomWorldTimes(worlds); + Session session = RandomData.randomSession(serverUUID(), worlds, playerUUID); + session.setWorldTimes(worldTimes); + List sessions = new ArrayList<>(); + sessions.add(session); + db().executeTransaction(new Transaction() { + @Override + protected void performOperations() { + execute(LargeStoreQueries.storeAllSessionsWithKillAndWorldData(sessions)); + } + }); + + List allSessions = db().query(SessionQueries.fetchAllSessions()); + + assertEquals(worldTimes, allSessions.get(0).getUnsafe(SessionKeys.WORLD_TIMES)); + } + + @Test + default void playersWorldTimesMatchTotal() { + worldTimesAreSavedWithSession(); + Session session = db().query(SessionQueries.fetchSessionsOfPlayer(playerUUID)).get(serverUUID()).get(0); + WorldTimes expected = session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes()); + WorldTimes worldTimesOfUser = db().query(WorldTimesQueries.fetchPlayerTotalWorldTimes(playerUUID)); + assertEquals(expected, worldTimesOfUser); + } + + @Test + default void serverWorldTimesMatchTotal() { + worldTimesAreSavedWithSession(); + Session session = db().query(SessionQueries.fetchSessionsOfPlayer(playerUUID)).get(serverUUID()).get(0); + WorldTimes expected = session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes()); + WorldTimes worldTimesOfServer = db().query(WorldTimesQueries.fetchServerTotalWorldTimes(serverUUID())); + assertEquals(expected, worldTimesOfServer); + } + + @Test + default void emptyServerWorldTimesIsEmpty() { + WorldTimes worldTimesOfServer = db().query(WorldTimesQueries.fetchServerTotalWorldTimes(serverUUID())); + assertEquals(new WorldTimes(), worldTimesOfServer); + } + +} diff --git a/Plan/common/src/test/java/utilities/RandomData.java b/Plan/common/src/test/java/utilities/RandomData.java index 3fe94e433..5bfd5d43d 100644 --- a/Plan/common/src/test/java/utilities/RandomData.java +++ b/Plan/common/src/test/java/utilities/RandomData.java @@ -19,12 +19,14 @@ package utilities; import com.djrapitops.plan.delivery.domain.WebUser; import com.djrapitops.plan.delivery.rendering.json.graphs.line.Point; import com.djrapitops.plan.gathering.domain.*; +import com.djrapitops.plan.storage.database.sql.tables.KillsTable; import com.djrapitops.plan.utilities.PassEncryptUtil; import org.apache.commons.lang3.RandomStringUtils; import java.util.*; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; public class RandomData { @@ -38,6 +40,14 @@ public class RandomData { return ThreadLocalRandom.current().nextInt(rangeStart, rangeEnd); } + public static long randomTime() { + return randomTimeAfter(0); + } + + public static long randomTimeAfter(long after) { + return randomLong(after, System.currentTimeMillis()); + } + public static long randomLong(long rangeStart, long rangeEnd) { return ThreadLocalRandom.current().nextLong(rangeStart, rangeEnd); } @@ -65,15 +75,39 @@ public class RandomData { } public static List randomSessions() { - List test = new ArrayList<>(); - for (int i = 0; i < 20; i++) { - test.add(randomSession()); - } - return test; + return pickMultiple(randomInt(15, 30), + () -> randomSession( + TestConstants.SERVER_UUID, + pickMultiple(4, () -> randomString(5)).toArray(new String[0]), + pickMultiple(5, UUID::randomUUID).toArray(new UUID[0]) + ) + ); } - public static Session randomSession() { - return new Session(1, TestConstants.PLAYER_ONE_UUID, TestConstants.SERVER_UUID, r.nextLong(), r.nextLong(), 0, 0, 0); + public static String randomGameMode() { + return pickAtRandom(GMTimes.getGMKeyArray()); + } + + public static T pickAtRandom(T[] from) { + return from[randomInt(0, from.length)]; + } + + public static List pickMultiple(int howMany, Supplier supplier) { + List picked = new ArrayList<>(); + for (int i = 0; i < howMany; i++) { + picked.add(supplier.get()); + } + return picked; + } + + public static Session randomSession(UUID serverUUID, String[] worlds, UUID... uuids) { + Session session = new Session(uuids[0], serverUUID, RandomData.randomTime(), pickAtRandom(worlds), randomGameMode()); + session.endSession(RandomData.randomTimeAfter(session.getDate())); + session.setWorldTimes(RandomData.randomWorldTimes(worlds)); + if (uuids.length >= 2) { + session.setPlayerKills(RandomData.randomKills(pickAtRandom(Arrays.copyOfRange(uuids, 1, uuids.length)))); + } + return session; } public static List randomPoints() { @@ -85,15 +119,10 @@ public class RandomData { } public static List randomGeoInfo() { - List test = new ArrayList<>(); - for (int i = 0; i < 20; i++) { - GeoInfo geoInfo = new GeoInfo(randomString(10), r.nextLong()); - test.add(geoInfo); - } - return test; + return pickMultiple(randomInt(15, 30), () -> new GeoInfo(randomString(10), randomTime())); } - public static WorldTimes randomWorldTimes(String[] worlds) { + public static WorldTimes randomWorldTimes(String... worlds) { Map times = new HashMap<>(); for (String world : worlds) { Map gmTimes = new HashMap<>(); @@ -104,4 +133,14 @@ public class RandomData { } return new WorldTimes(times); } + + public static List randomKills(UUID... victimUUIDs) { + if (victimUUIDs == null || victimUUIDs.length == 1 && victimUUIDs[0] == null) return Collections.emptyList(); + + return pickMultiple(randomInt(3, 15), () -> new PlayerKill( + pickAtRandom(victimUUIDs), + randomString(randomInt(10, KillsTable.WEAPON_COLUMN_LENGTH)), + randomTime() + )); + } } diff --git a/Plan/common/src/test/java/utilities/TestConstants.java b/Plan/common/src/test/java/utilities/TestConstants.java index 7babc1370..61f554499 100644 --- a/Plan/common/src/test/java/utilities/TestConstants.java +++ b/Plan/common/src/test/java/utilities/TestConstants.java @@ -38,6 +38,7 @@ public class TestConstants { public static final String PLAYER_TWO_NAME = "Test_Player_two"; public static final String WORLD_ONE_NAME = "World One"; + public static final Long REGISTER_TIME = RandomData.randomTime(); public static final int SERVER_MAX_PLAYERS = 20; public static final int BUNGEE_MAX_PLAYERS = 100;