From a66d2b54d537385ac00332a6f113248dde11c09d Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Sun, 5 Jul 2026 16:11:04 +0200 Subject: [PATCH] test: add CapsFilter, CharacterFilter, SpamFilter unit tests --- .../lochat/core/filter/CapsFilterTest.java | 76 +++++++++++ .../core/filter/CharacterFilterTest.java | 79 +++++++++++ .../lochat/core/filter/SpamFilterTest.java | 124 ++++++++++++++++++ 3 files changed, 279 insertions(+) create mode 100644 src/test/java/com/loki/lochat/core/filter/CapsFilterTest.java create mode 100644 src/test/java/com/loki/lochat/core/filter/CharacterFilterTest.java create mode 100644 src/test/java/com/loki/lochat/core/filter/SpamFilterTest.java diff --git a/src/test/java/com/loki/lochat/core/filter/CapsFilterTest.java b/src/test/java/com/loki/lochat/core/filter/CapsFilterTest.java new file mode 100644 index 0000000..c73881f --- /dev/null +++ b/src/test/java/com/loki/lochat/core/filter/CapsFilterTest.java @@ -0,0 +1,76 @@ +package com.loki.lochat.core.filter; + +import org.bukkit.entity.Player; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class CapsFilterTest { + + @Test + void filter_noCapsReturnsSame() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.caps")).thenReturn(false); + CapsFilter filter = new CapsFilter(70, 5, true, false); + assertEquals("hello world", filter.filter(player, "hello world")); + } + + @Test + void filter_allCapsAutoLower() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.caps")).thenReturn(false); + CapsFilter filter = new CapsFilter(50, 3, true, false); + String result = filter.filter(player, "HELLO WORLD"); + assertNotNull(result); + assertTrue(result.startsWith("H") && result.substring(1).equals("ello world")); + } + + @Test + void filter_allCapsBlocked() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.caps")).thenReturn(false); + CapsFilter filter = new CapsFilter(50, 3, false, true); + assertNull(filter.filter(player, "HELLO WORLD")); + } + + @Test + void filter_shortMessageIgnored() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.caps")).thenReturn(false); + CapsFilter filter = new CapsFilter(70, 10, false, true); + assertEquals("HI", filter.filter(player, "HI")); + } + + @Test + void filter_bypassPermission() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.caps")).thenReturn(true); + CapsFilter filter = new CapsFilter(50, 3, false, true); + assertEquals("HELLO", filter.filter(player, "HELLO")); + } + + @Test + void filter_mixedCapsWithinLimit() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.caps")).thenReturn(false); + CapsFilter filter = new CapsFilter(70, 5, true, false); + assertEquals("Hello World", filter.filter(player, "Hello World")); + } + + @Test + void filter_onlySpecialChars() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.caps")).thenReturn(false); + CapsFilter filter = new CapsFilter(50, 3, true, false); + assertEquals("123!@#", filter.filter(player, "123!@#")); + } + + @Test + void filter_emptyString() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.caps")).thenReturn(false); + CapsFilter filter = new CapsFilter(50, 5, true, false); + assertEquals("", filter.filter(player, "")); + } +} diff --git a/src/test/java/com/loki/lochat/core/filter/CharacterFilterTest.java b/src/test/java/com/loki/lochat/core/filter/CharacterFilterTest.java new file mode 100644 index 0000000..c6537f2 --- /dev/null +++ b/src/test/java/com/loki/lochat/core/filter/CharacterFilterTest.java @@ -0,0 +1,79 @@ +package com.loki.lochat.core.filter; + +import com.loki.lochat.core.filter.filters.CharacterFilter; + +import org.bukkit.configuration.file.YamlConfiguration; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class CharacterFilterTest { + + @Test + void filter_limitsRepeatingChars() { + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.repeating-chars.enabled", true); + config.set("filters.repeating-chars.max", 3); + CharacterFilter filter = new CharacterFilter(config); + assertEquals("привееет", filter.filter("привеееееет")); + } + + @Test + void filter_noChangeWhenUnderLimit() { + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.repeating-chars.enabled", true); + config.set("filters.repeating-chars.max", 3); + CharacterFilter filter = new CharacterFilter(config); + assertEquals("привет", filter.filter("привет")); + } + + @Test + void filter_shortRepeatsAllowed() { + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.repeating-chars.enabled", true); + config.set("filters.repeating-chars.max", 3); + CharacterFilter filter = new CharacterFilter(config); + assertEquals("ууупс", filter.filter("ууупс")); + } + + @Test + void filter_disabledReturnsOriginal() { + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.repeating-chars.enabled", false); + CharacterFilter filter = new CharacterFilter(config); + assertEquals("мноооого букв", filter.filter("мноооого букв")); + } + + @Test + void filter_zeroMaxDisabled() { + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.repeating-chars.enabled", true); + config.set("filters.repeating-chars.max", 0); + CharacterFilter filter = new CharacterFilter(config); + assertEquals("теееекст", filter.filter("теееекст")); + } + + @Test + void filter_defaultConfig() { + CharacterFilter filter = new CharacterFilter(new YamlConfiguration()); + assertEquals("тееест", filter.filter("теееест")); + } + + @Test + void filter_differentMax() { + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.repeating-chars.enabled", true); + config.set("filters.repeating-chars.max", 1); + CharacterFilter filter = new CharacterFilter(config); + assertEquals("ап", filter.filter("ааап")); + } + + @Test + void filter_multiplePatterns() { + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.repeating-chars.enabled", true); + config.set("filters.repeating-chars.max", 2); + CharacterFilter filter = new CharacterFilter(config); + assertEquals("aa bb", filter.filter("aaa bbb")); + } +} diff --git a/src/test/java/com/loki/lochat/core/filter/SpamFilterTest.java b/src/test/java/com/loki/lochat/core/filter/SpamFilterTest.java new file mode 100644 index 0000000..e568722 --- /dev/null +++ b/src/test/java/com/loki/lochat/core/filter/SpamFilterTest.java @@ -0,0 +1,124 @@ +package com.loki.lochat.core.filter; + +import com.loki.lochat.core.filter.filters.SpamFilter; + +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class SpamFilterTest { + + @Test + void filter_firstMessageAllowed() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.spam")).thenReturn(false); + when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID()); + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.spam.max-similar-messages", 3); + config.set("filters.spam.similarity-threshold", 80); + SpamFilter filter = new SpamFilter(config); + FilterResult result = filter.filter(player, "hello"); + assertTrue(result.allowed()); + } + + @Test + void filter_sameMessageRepeated() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.spam")).thenReturn(false); + when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID()); + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.spam.max-similar-messages", 2); + config.set("filters.spam.similarity-threshold", 80); + config.set("filters.spam.block-message", "no spam"); + SpamFilter filter = new SpamFilter(config); + filter.filter(player, "hello"); + filter.filter(player, "hello"); + FilterResult result = filter.filter(player, "hello"); + assertFalse(result.allowed()); + assertEquals("no spam", result.blockReason()); + } + + @Test + void filter_differentMessagesAllowed() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.spam")).thenReturn(false); + when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID()); + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.spam.max-similar-messages", 2); + config.set("filters.spam.similarity-threshold", 80); + SpamFilter filter = new SpamFilter(config); + filter.filter(player, "hello"); + filter.filter(player, "world"); + FilterResult result = filter.filter(player, "foo"); + assertTrue(result.allowed()); + } + + @Test + void filter_bypassPermission() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.spam")).thenReturn(true); + when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID()); + YamlConfiguration config = new YamlConfiguration(); + SpamFilter filter = new SpamFilter(config); + FilterResult result = filter.filter(player, "spam"); + assertTrue(result.allowed()); + } + + @Test + void filter_historyLimit() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.spam")).thenReturn(false); + when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID()); + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.spam.max-similar-messages", 2); + config.set("filters.spam.similarity-threshold", 100); + config.set("filters.spam.block-message", "no spam"); + SpamFilter filter = new SpamFilter(config); + // Send 12 different messages to fill and rotate history + for (int i = 0; i < 12; i++) { + filter.filter(player, "msg" + i); + } + // Send "hello" twice more to trigger spam detection + filter.filter(player, "hello"); + filter.filter(player, "hello"); + FilterResult result = filter.filter(player, "hello"); + assertFalse(result.allowed()); + } + + @Test + void filter_similarButNotExact() { + Player player = mock(Player.class); + when(player.hasPermission("lochat.bypass.spam")).thenReturn(false); + when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID()); + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.spam.max-similar-messages", 2); + config.set("filters.spam.similarity-threshold", 90); + config.set("filters.spam.block-message", "no spam"); + SpamFilter filter = new SpamFilter(config); + filter.filter(player, "hello world"); + filter.filter(player, "hello world"); + FilterResult result = filter.filter(player, "hello world!"); + // 91% similarity (11/12 chars match), should be blocked + assertFalse(result.allowed()); + } + + @Test + void clearPlayer_removesData() { + Player player = mock(Player.class); + java.util.UUID uuid = java.util.UUID.randomUUID(); + when(player.hasPermission("lochat.bypass.spam")).thenReturn(false); + when(player.getUniqueId()).thenReturn(uuid); + YamlConfiguration config = new YamlConfiguration(); + config.set("filters.spam.max-similar-messages", 2); + config.set("filters.spam.similarity-threshold", 100); + SpamFilter filter = new SpamFilter(config); + filter.filter(player, "hello"); + filter.clearPlayer(uuid); + filter.filter(player, "hello"); + FilterResult result = filter.filter(player, "hello"); + assertTrue(result.allowed()); + } +}