Split Session related queries to own test class:

- Added a lot of new utility methods to RandomData
- Fixed a bug where duplicate PlayerKills were queried
  This bug was discovered by accident when PlayerKill saving was randomized
  for the tests.
- Testing constant REGISTER_TIME extracted
- String truncation constant extracted for KillsTable
  This was causing some Session equals issues due to truncated weapon names
- Session now sorts PlayerKill list as this was assumed in some places.
This commit is contained in:
Risto Lahtela 2020-03-11 23:10:17 +02:00
parent b49baa1275
commit fd6877dcad
15 changed files with 316 additions and 185 deletions

View File

@ -119,6 +119,21 @@ public class TablePlayer implements Comparable<TablePlayer> {
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;

View File

@ -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<PlayerKill> getPlayerKills() {
playerKills.sort(new DateHolderRecentComparator());
return playerKills;
}

View File

@ -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");
}
}

View File

@ -155,7 +155,7 @@ public class SessionQueries {
// Utilities
String[] gms = GMTimes.getGMKeyArray();
Comparator<DateHolder> dateColderRecentComparator = new DateHolderRecentComparator();
Comparator<DateHolder> mostRecentFirst = new DateHolderRecentComparator();
Comparator<Long> 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<PlayerKill> 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());
}

View File

@ -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();
}
}

View File

@ -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"));

View File

@ -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<UUID, List<Session>> 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<UUID, List<Session>> sessions = db().query(SessionQueries.fetchSessionsOfPlayer(playerUUID));
List<Session> 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<Session> expected = Collections.singletonList(session);
List<Session> result = db().query(SessionQueries.fetchLatestSessionsOfServer(serverUUID(), 1));
assertEquals(expected, result);
}
@Test
default void userInfoTableStoresCorrectUserInformation() {
saveUserOne();
List<UserInfo> userInfo = db().query(UserInfoQueries.fetchUserInformationOfUser(playerUUID));
List<UserInfo> expected = Collections.singletonList(new UserInfo(playerUUID, serverUUID(), 1000L, false, false));
List<UserInfo> 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> userInfo = db().query(UserInfoQueries.fetchUserInformationOfUser(playerUUID));
List<UserInfo> expected = Collections.singletonList(new UserInfo(playerUUID, serverUUID(), 1000L, false, true));
List<UserInfo> 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> userInfo = db().query(UserInfoQueries.fetchUserInformationOfUser(playerUUID));
List<UserInfo> expected = Collections.singletonList(new UserInfo(playerUUID, serverUUID(), 1000L, true, false));
List<UserInfo> 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<Session> sessions = new ArrayList<>();
sessions.add(session);
db().executeTransaction(new Transaction() {
@Override
protected void performOperations() {
execute(LargeStoreQueries.storeAllSessionsWithKillAndWorldData(sessions));
}
});
Map<UUID, WorldTimes> 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<Session> sessions = new ArrayList<>();
sessions.add(session);
db().executeTransaction(new Transaction() {
@Override
protected void performOperations() {
execute(LargeStoreQueries.storeAllSessionsWithKillAndWorldData(sessions));
}
});
List<Session> 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<String> unsupported = new ArrayList<>();
List<Key> 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<TablePlayer> 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<TablePlayer> 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);
}
}

View File

@ -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();
}

View File

@ -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);

View File

@ -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);

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
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");

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
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<GeoInfo> expected = RandomData.randomGeoInfo();
for (GeoInfo geoInfo : expected) {

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
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<UUID, List<Session>> 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<UUID, List<Session>> sessions = db().query(SessionQueries.fetchSessionsOfPlayer(playerUUID));
List<Session> 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<Session> expected = Collections.singletonList(session);
List<Session> 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<Session> sessions = Collections.singletonList(session);
db().executeTransaction(new Transaction() {
@Override
protected void performOperations() {
execute(LargeStoreQueries.storeAllSessionsWithKillAndWorldData(sessions));
}
});
Map<UUID, WorldTimes> 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<Session> sessions = new ArrayList<>();
sessions.add(session);
db().executeTransaction(new Transaction() {
@Override
protected void performOperations() {
execute(LargeStoreQueries.storeAllSessionsWithKillAndWorldData(sessions));
}
});
List<Session> 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);
}
}

View File

@ -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<Session> randomSessions() {
List<Session> 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> T pickAtRandom(T[] from) {
return from[randomInt(0, from.length)];
}
public static <T> List<T> pickMultiple(int howMany, Supplier<T> supplier) {
List<T> 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<Point> randomPoints() {
@ -85,15 +119,10 @@ public class RandomData {
}
public static List<GeoInfo> randomGeoInfo() {
List<GeoInfo> 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<String, GMTimes> times = new HashMap<>();
for (String world : worlds) {
Map<String, Long> gmTimes = new HashMap<>();
@ -104,4 +133,14 @@ public class RandomData {
}
return new WorldTimes(times);
}
public static List<PlayerKill> 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()
));
}
}

View File

@ -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;