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 @@ -102,6 +102,45 @@ public Optional<TestSetting> fromString(@NotNull String setting) {
}
}

private enum AnotherTestSetting implements PlayerSetting {
ENABLED,
DISABLED;

private static final NamespacedKey KEY = new NamespacedKey("mccore", "another_test_setting");

@Override
@NotNull
public NamespacedKey getSettingKey() {
return KEY;
}

@Override
@NotNull
public LinkedNode<AnotherTestSetting> getFirstSetting() {
return new LinkedNode<>(ENABLED, new LinkedNode<>(DISABLED, null));
}

@Override
@NotNull
public LinkedNode<AnotherTestSetting> getNextSetting() {
return this == ENABLED ? new LinkedNode<>(DISABLED, null) : new LinkedNode<>(ENABLED, null);
}

@Override
public void onSettingChange(@NotNull CorePlayer player, @NotNull Optional<PlayerSetting> oldSetting) {
}

@Override
@NotNull
public Optional<AnotherTestSetting> fromString(@NotNull String setting) {
try {
return Optional.of(AnotherTestSetting.valueOf(setting));
} catch (IllegalArgumentException e) {
return Optional.empty();
}
}
}

@Nested
@DisplayName("attemptCreateTable")
class AttemptCreateTable {
Expand Down Expand Up @@ -273,6 +312,25 @@ void getPlayerSettings_returnsPartialResults_whenSqlExceptionOccurs() throws SQL
assertNotNull(settings);
assertTrue(settings.isEmpty());
}

@Test
@DisplayName("Given multiple settings registered, when getPlayerSettings is called, then returns one result per registered setting")
void getPlayerSettings_returnsAllSettings_whenMultipleRegistered() throws SQLException {
PlayerSettingRegistry registry = RegistryAccess.registryAccess().registry(RegistryKey.PLAYER_SETTING);
registry.register(AnotherTestSetting.ENABLED);

when(mockConnection.prepareStatement(anyString())).thenReturn(mockStatement);
// Both settings default (no saved values) - iteration order doesn't matter
when(mockStatement.executeQuery()).thenReturn(mockResultSet);
when(mockResultSet.next()).thenReturn(false);

Set<PlayerSetting> settings = PlayerSettingDAO.getPlayerSettings(mockConnection, TEST_UUID);

assertEquals(2, settings.size());
// Both should return their defaults: ON for TestSetting, ENABLED for AnotherTestSetting
assertTrue(settings.stream().anyMatch(s -> s.name().equals("ON")));
assertTrue(settings.stream().anyMatch(s -> s.name().equals("ENABLED")));
}
}

@Nested
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,62 @@ void emptyBrackets_returnsEmptySet() {
Set<String> result = PlayerStatisticDAO.deserializeStringSet("[]");
assertTrue(result.isEmpty());
}

@DisplayName("Given unquoted elements, when deserializing, then parses them correctly")
@Test
void unquotedElements_parsedCorrectly() {
Set<String> result = PlayerStatisticDAO.deserializeStringSet("[hello,world]");
assertEquals(2, result.size());
assertTrue(result.contains("hello"));
assertTrue(result.contains("world"));
}

@DisplayName("Given single unquoted element, when deserializing, then parses it correctly")
@Test
void singleUnquotedElement_parsedCorrectly() {
Set<String> result = PlayerStatisticDAO.deserializeStringSet("[hello]");
assertEquals(1, result.size());
assertTrue(result.contains("hello"));
}

@DisplayName("Given backslash followed by non-special character, when deserializing, then preserves both characters")
@Test
void unknownEscapeSequence_preservesBothCharacters() {
Set<String> result = PlayerStatisticDAO.deserializeStringSet("[\"hello\\nworld\"]");
assertEquals(1, result.size());
assertTrue(result.contains("hello\\nworld"));
}

@DisplayName("Given elements with leading whitespace, when deserializing, then trims whitespace")
@Test
void elementsWithWhitespace_trimmedCorrectly() {
Set<String> result = PlayerStatisticDAO.deserializeStringSet("[\"alpha\", \"beta\"]");
assertEquals(2, result.size());
assertTrue(result.contains("alpha"));
assertTrue(result.contains("beta"));
}

@DisplayName("Given brackets with only whitespace, when deserializing, then returns empty set")
@Test
void bracketsWithWhitespace_returnsEmptySet() {
Set<String> result = PlayerStatisticDAO.deserializeStringSet("[ ]");
assertTrue(result.isEmpty());
}

@DisplayName("Given unquoted elements with whitespace, when deserializing, then trims values")
@Test
void unquotedElementsWithWhitespace_trimmed() {
Set<String> result = PlayerStatisticDAO.deserializeStringSet("[ alpha , beta ]");
assertEquals(2, result.size());
assertTrue(result.contains("alpha"));
assertTrue(result.contains("beta"));
}

@DisplayName("Given backslash at end of quoted element, when deserializing, then treats as literal backslash")
@Test
void backslashAtEndOfQuotedElement_treatedAsLiteralEnd() {
Set<String> result = PlayerStatisticDAO.deserializeStringSet("[\"test\\\\\"]");
assertEquals(1, result.size());
assertTrue(result.contains("test\\"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,125 @@ void returnsStatistic_whenExists() throws SQLException {
assertEquals(77, result.get().value());
}

@Test
@DisplayName("Given LONG statistic exists, when getPlayerStatistic, then returns long value")
void returnsLongStatistic_whenExists() throws SQLException {
when(connection.prepareStatement(anyString())).thenReturn(statement);
when(statement.executeQuery()).thenReturn(resultSet);
when(resultSet.next()).thenReturn(true);
when(resultSet.getString("stat_type")).thenReturn("LONG");
when(resultSet.getLong("long_value")).thenReturn(123456789L);

Optional<StatisticEntry> result = PlayerStatisticDAO.getPlayerStatistic(connection, playerUUID, key);

assertTrue(result.isPresent());
assertEquals(StatisticType.LONG, result.get().type());
assertEquals(123456789L, result.get().value());
}

@Test
@DisplayName("Given DOUBLE statistic exists, when getPlayerStatistic, then returns double value")
void returnsDoubleStatistic_whenExists() throws SQLException {
when(connection.prepareStatement(anyString())).thenReturn(statement);
when(statement.executeQuery()).thenReturn(resultSet);
when(resultSet.next()).thenReturn(true);
when(resultSet.getString("stat_type")).thenReturn("DOUBLE");
when(resultSet.getDouble("double_value")).thenReturn(2.718);

Optional<StatisticEntry> result = PlayerStatisticDAO.getPlayerStatistic(connection, playerUUID, key);

assertTrue(result.isPresent());
assertEquals(StatisticType.DOUBLE, result.get().type());
assertEquals(2.718, result.get().value());
}

@Test
@DisplayName("Given STRING statistic exists, when getPlayerStatistic, then returns string value")
void returnsStringStatistic_whenExists() throws SQLException {
when(connection.prepareStatement(anyString())).thenReturn(statement);
when(statement.executeQuery()).thenReturn(resultSet);
when(resultSet.next()).thenReturn(true);
when(resultSet.getString("stat_type")).thenReturn("STRING");
when(resultSet.getString("string_value")).thenReturn("test_value");

Optional<StatisticEntry> result = PlayerStatisticDAO.getPlayerStatistic(connection, playerUUID, key);

assertTrue(result.isPresent());
assertEquals(StatisticType.STRING, result.get().type());
assertEquals("test_value", result.get().value());
}

@Test
@DisplayName("Given STRING statistic with null value, when getPlayerStatistic, then returns empty string")
void returnsEmptyString_whenStringValueIsNull() throws SQLException {
when(connection.prepareStatement(anyString())).thenReturn(statement);
when(statement.executeQuery()).thenReturn(resultSet);
when(resultSet.next()).thenReturn(true);
when(resultSet.getString("stat_type")).thenReturn("STRING");
when(resultSet.getString("string_value")).thenReturn(null);

Optional<StatisticEntry> result = PlayerStatisticDAO.getPlayerStatistic(connection, playerUUID, key);

assertTrue(result.isPresent());
assertEquals(StatisticType.STRING, result.get().type());
assertEquals("", result.get().value());
}

@Test
@DisplayName("Given TIMESTAMP statistic exists, when getPlayerStatistic, then returns Instant value")
void returnsTimestampStatistic_whenExists() throws SQLException {
long epochMillis = 1718000000000L;
when(connection.prepareStatement(anyString())).thenReturn(statement);
when(statement.executeQuery()).thenReturn(resultSet);
when(resultSet.next()).thenReturn(true);
when(resultSet.getString("stat_type")).thenReturn("TIMESTAMP");
when(resultSet.getLong("timestamp_value")).thenReturn(epochMillis);

Optional<StatisticEntry> result = PlayerStatisticDAO.getPlayerStatistic(connection, playerUUID, key);

assertTrue(result.isPresent());
assertEquals(StatisticType.TIMESTAMP, result.get().type());
assertEquals(Instant.ofEpochMilli(epochMillis), result.get().value());
}

@Test
@DisplayName("Given SET_STRING statistic exists, when getPlayerStatistic, then returns deserialized set")
void returnsSetStringStatistic_whenExists() throws SQLException {
when(connection.prepareStatement(anyString())).thenReturn(statement);
when(statement.executeQuery()).thenReturn(resultSet);
when(resultSet.next()).thenReturn(true);
when(resultSet.getString("stat_type")).thenReturn("SET_STRING");
when(resultSet.getString("string_value")).thenReturn("[\"one\",\"two\"]");

Optional<StatisticEntry> result = PlayerStatisticDAO.getPlayerStatistic(connection, playerUUID, key);

assertTrue(result.isPresent());
assertEquals(StatisticType.SET_STRING, result.get().type());
@SuppressWarnings("unchecked")
Set<String> set = (Set<String>) result.get().value();
assertEquals(2, set.size());
assertTrue(set.contains("one"));
assertTrue(set.contains("two"));
}

@Test
@DisplayName("Given SET_STRING statistic with null value, when getPlayerStatistic, then returns empty set")
void returnsEmptySet_whenSetStringValueIsNull() throws SQLException {
when(connection.prepareStatement(anyString())).thenReturn(statement);
when(statement.executeQuery()).thenReturn(resultSet);
when(resultSet.next()).thenReturn(true);
when(resultSet.getString("stat_type")).thenReturn("SET_STRING");
when(resultSet.getString("string_value")).thenReturn(null);

Optional<StatisticEntry> result = PlayerStatisticDAO.getPlayerStatistic(connection, playerUUID, key);

assertTrue(result.isPresent());
assertEquals(StatisticType.SET_STRING, result.get().type());
@SuppressWarnings("unchecked")
Set<String> set = (Set<String>) result.get().value();
assertTrue(set.isEmpty());
}

@Test
@DisplayName("Given statistic does not exist, when getPlayerStatistic, then returns empty")
void returnsEmpty_whenNotExists() throws SQLException {
Expand Down
Loading