Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,44 @@ void createTables_completesSuccessfully_whenTablesExist() throws Exception {
assertTrue(result.isDone());
assertFalse(result.isCompletedExceptionally());
}

@Test
@DisplayName("Given a valid database, when createTables completes, then connection is closed")
void createTables_closesConnection_whenComplete() throws Exception {
Database mockDatabase = mock(Database.class);
Connection mockConnection = mock(Connection.class);

when(mockDatabase.getDatabaseExecutorService()).thenReturn(executor);
when(mockDatabase.getConnection()).thenReturn(mockConnection);
when(mockDatabase.tableExists(eq(mockConnection), any(String.class))).thenReturn(true);

CreateTableFunction function = CreateCoreTablesFunction.getCreateCoreTablesFunction();

CompletableFuture<Void> result = function.createTables(mockDatabase);
result.get(5, TimeUnit.SECONDS);

org.mockito.Mockito.verify(mockConnection).close();
}

@Test
@DisplayName("Given tables do not exist, when createTables is called, then creates tables and completes successfully")
void createTables_createsTables_whenTablesDoNotExist() throws Exception {
Database mockDatabase = mock(Database.class);
Connection mockConnection = mock(Connection.class);
java.sql.PreparedStatement mockStatement = mock(java.sql.PreparedStatement.class);

when(mockDatabase.getDatabaseExecutorService()).thenReturn(executor);
when(mockDatabase.getConnection()).thenReturn(mockConnection);
when(mockDatabase.tableExists(eq(mockConnection), any(String.class))).thenReturn(false);
when(mockConnection.prepareStatement(any(String.class))).thenReturn(mockStatement);

CreateTableFunction function = CreateCoreTablesFunction.getCreateCoreTablesFunction();

CompletableFuture<Void> result = function.createTables(mockDatabase);
assertNotNull(result);

result.get(5, TimeUnit.SECONDS);
assertTrue(result.isDone());
assertFalse(result.isCompletedExceptionally());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

class UpdateCoreTablesFunctionTest {
Expand Down Expand Up @@ -89,4 +90,27 @@ void updateTables_completesSuccessfully_whenDatabaseIsValid() throws Exception {
assertTrue(result.isDone());
assertFalse(result.isCompletedExceptionally());
}

@Test
@DisplayName("Given a valid database, when updateTables completes, then connection is closed")
void updateTables_closesConnection_whenComplete() throws Exception {
Database mockDatabase = mock(Database.class);
Connection mockConnection = mock(Connection.class);
PreparedStatement mockStatement = mock(PreparedStatement.class);
ResultSet mockResultSet = mock(ResultSet.class);

when(mockDatabase.getDatabaseExecutorService()).thenReturn(executor);
when(mockDatabase.getConnection()).thenReturn(mockConnection);
when(mockConnection.prepareStatement(any(String.class))).thenReturn(mockStatement);
when(mockStatement.executeQuery()).thenReturn(mockResultSet);
when(mockStatement.executeUpdate()).thenReturn(1);
when(mockResultSet.next()).thenReturn(false);

UpdateTableFunction function = UpdateCoreTablesFunction.getUpdateCoreTablesFunction();

CompletableFuture<Void> result = function.updateTables(mockDatabase);
result.get(5, TimeUnit.SECONDS);

verify(mockConnection).close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package com.diamonddagger590.mccore.statistic;

import com.diamonddagger590.mccore.player.CorePlayer;
import com.diamonddagger590.mccore.registry.RegistryAccess;
import com.diamonddagger590.mccore.registry.RegistryKey;
import com.diamonddagger590.mccore.testing.RegistryResetExtension;
import org.bukkit.NamespacedKey;
import org.bukkit.event.Event;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

class PlayerStatisticDataSetCoverageTest {

private static final UUID PLAYER_UUID = UUID.randomUUID();

@SuppressWarnings("deprecation")
private static NamespacedKey key(String namespace, String key) {
return new NamespacedKey(namespace, key);
}

private static final NamespacedKey UNLIMITED_SET_KEY = key("test", "unlimited_set");
private static final NamespacedKey INT_KEY = key("test", "int_stat");

private final List<Event> firedEvents = Collections.synchronizedList(new ArrayList<>());
private CorePlayer mockPlayer;
private PlayerStatisticData data;

@BeforeEach
void setUp() {
RegistryResetExtension.setupRegistry();
StatisticRegistry registry = RegistryAccess.registryAccess().registry(RegistryKey.STATISTIC);

registry.register(new SimpleStatistic(UNLIMITED_SET_KEY, StatisticType.SET_STRING,
new LinkedHashSet<String>(), "Unlimited Set", "Set with no size limit"));
registry.register(new SimpleStatistic(INT_KEY, StatisticType.INT, 0, "Int", "Int stat"));

mockPlayer = new TestCorePlayer(PLAYER_UUID);
firedEvents.clear();
data = new PlayerStatisticData(
PLAYER_UUID,
event -> firedEvents.add(event),
id -> mockPlayer
);
}

@AfterEach
void tearDown() {
RegistryResetExtension.resetRegistry();
}

@Nested
@DisplayName("addToSet with unlimited max size")
class AddToSetUnlimitedTests {

@Test
@DisplayName("Given a set statistic with unlimited max size, when adding elements, then no eviction occurs")
void addToSet_doesNotEvict_whenMaxSizeIsUnlimited() {
for (int i = 0; i < 10; i++) {
assertTrue(data.addToSet(UNLIMITED_SET_KEY, "element_" + i));
}
Set<String> result = data.getSetValue(UNLIMITED_SET_KEY).get();
assertEquals(10, result.size());
for (int i = 0; i < 10; i++) {
assertTrue(result.contains("element_" + i));
}
}

@Test
@DisplayName("Given a set statistic with unlimited max size, when adding a duplicate, then returns false")
void addToSet_returnsFalse_whenDuplicateAndUnlimited() {
data.addToSet(UNLIMITED_SET_KEY, "element");
firedEvents.clear();
assertFalse(data.addToSet(UNLIMITED_SET_KEY, "element"));
assertTrue(firedEvents.isEmpty());
}

@Test
@DisplayName("Given a set statistic with unlimited max size, when adding many elements, then all are preserved")
void addToSet_preservesAllElements_whenUnlimitedAndLargeSet() {
for (int i = 0; i < 50; i++) {
data.addToSet(UNLIMITED_SET_KEY, "item_" + i);
}
Set<String> result = data.getSetValue(UNLIMITED_SET_KEY).get();
assertEquals(50, result.size());
}
}

@Nested
@DisplayName("getModifiedEntries edge cases")
class GetModifiedEntriesEdgeCases {

@Test
@DisplayName("Given a dirty key with non-null value whose statistic was unregistered, when getting modified entries, then excludes the key")
void getModifiedEntries_excludesKey_whenValuePresentButStatisticUnregistered() {
data.setValue(INT_KEY, 42);
assertTrue(data.isDirty());

RegistryResetExtension.resetRegistry();
RegistryResetExtension.setupRegistry();

Map<NamespacedKey, StatisticEntry> modified = data.getModifiedEntries();
assertTrue(modified.isEmpty());
}

@Test
@DisplayName("Given dirty keys with mixed registration status, when getting modified entries, then includes only registered keys")
void getModifiedEntries_includesOnlyRegistered_whenMixedRegistration() {
NamespacedKey tempKey = key("test", "temp_stat");
StatisticRegistry registry = RegistryAccess.registryAccess().registry(RegistryKey.STATISTIC);
registry.register(new SimpleStatistic(tempKey, StatisticType.INT, 0, "Temp", "Temp stat"));

data.setValue(INT_KEY, 10);
data.setValue(tempKey, 20);
assertTrue(data.isDirty());

RegistryResetExtension.resetRegistry();
RegistryResetExtension.setupRegistry();
StatisticRegistry newRegistry = RegistryAccess.registryAccess().registry(RegistryKey.STATISTIC);
newRegistry.register(new SimpleStatistic(INT_KEY, StatisticType.INT, 0, "Int", "Int stat"));

Map<NamespacedKey, StatisticEntry> modified = data.getModifiedEntries();
assertEquals(1, modified.size());
assertTrue(modified.containsKey(INT_KEY));
assertFalse(modified.containsKey(tempKey));
}
}

private static class TestCorePlayer extends CorePlayer {

TestCorePlayer(UUID uuid) {
super(uuid, null);
}

@Override
public boolean useMutex() {
return false;
}
}
}
Loading