From 8b94f437362018b716eca70a467f65f00ddf20b4 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 29 Jun 2026 09:10:30 +0000 Subject: [PATCH 1/2] Add unit tests for database events, ManagerKey, and improve Pair/Parser coverage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add DatabaseTableEventsTest covering PreTablesCreateEvent, TablesCreatedEvent, PreTablesUpdateEvent, TablesUpdatedEvent (0% → 100%) - Add ManagerKeyTest covering COMMAND, RELOADABLE_CONTENT, CHAT_RESPONSE constants (0% → 100%) - Improve PairTest with direct equals() calls for non-Pair objects and null handling in hashCode (94.1% → 100%) - Improve ParserTest with error path coverage for trailing tokens, unmatched parentheses, and missing function brackets (96.7% → 98.0%) Co-Authored-By: Claude Opus 4.6 Claude-Session: https://claude.ai/code/session_01X2Mb9p5PuTL2bSW5RMWcWF --- .../database/DatabaseTableEventsTest.java | 113 ++++++++++++++++++ .../mccore/pair/PairTest.java | 46 +++++++ .../mccore/parser/ParserTest.java | 35 ++++++ .../registry/manager/ManagerKeyTest.java | 34 ++++++ 4 files changed, 228 insertions(+) create mode 100644 src/test/java/com/diamonddagger590/mccore/event/database/DatabaseTableEventsTest.java create mode 100644 src/test/java/com/diamonddagger590/mccore/registry/manager/ManagerKeyTest.java diff --git a/src/test/java/com/diamonddagger590/mccore/event/database/DatabaseTableEventsTest.java b/src/test/java/com/diamonddagger590/mccore/event/database/DatabaseTableEventsTest.java new file mode 100644 index 0000000..aa92263 --- /dev/null +++ b/src/test/java/com/diamonddagger590/mccore/event/database/DatabaseTableEventsTest.java @@ -0,0 +1,113 @@ +package com.diamonddagger590.mccore.event.database; + +import org.bukkit.event.HandlerList; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; + +class DatabaseTableEventsTest { + + @Test + @DisplayName("Given PreTablesCreateEvent, when constructed, then getHandlers returns non-null HandlerList") + void preTablesCreateEvent_getHandlers_returnsNonNull() { + PreTablesCreateEvent event = new PreTablesCreateEvent(); + assertNotNull(event.getHandlers()); + } + + @Test + @DisplayName("Given PreTablesCreateEvent, when getHandlerList called, then returns same instance as getHandlers") + void preTablesCreateEvent_getHandlerList_returnsSameInstanceAsGetHandlers() { + PreTablesCreateEvent event = new PreTablesCreateEvent(); + assertSame(PreTablesCreateEvent.getHandlerList(), event.getHandlers()); + } + + @Test + @DisplayName("Given two PreTablesCreateEvents, when getHandlers called, then they share the same HandlerList") + void preTablesCreateEvent_handlerList_isSharedAcrossInstances() { + PreTablesCreateEvent event1 = new PreTablesCreateEvent(); + PreTablesCreateEvent event2 = new PreTablesCreateEvent(); + assertSame(event1.getHandlers(), event2.getHandlers()); + } + + @Test + @DisplayName("Given TablesCreatedEvent, when constructed, then getHandlers returns non-null HandlerList") + void tablesCreatedEvent_getHandlers_returnsNonNull() { + TablesCreatedEvent event = new TablesCreatedEvent(); + assertNotNull(event.getHandlers()); + } + + @Test + @DisplayName("Given TablesCreatedEvent, when getHandlerList called, then returns same instance as getHandlers") + void tablesCreatedEvent_getHandlerList_returnsSameInstanceAsGetHandlers() { + TablesCreatedEvent event = new TablesCreatedEvent(); + assertSame(TablesCreatedEvent.getHandlerList(), event.getHandlers()); + } + + @Test + @DisplayName("Given two TablesCreatedEvents, when getHandlers called, then they share the same HandlerList") + void tablesCreatedEvent_handlerList_isSharedAcrossInstances() { + TablesCreatedEvent event1 = new TablesCreatedEvent(); + TablesCreatedEvent event2 = new TablesCreatedEvent(); + assertSame(event1.getHandlers(), event2.getHandlers()); + } + + @Test + @DisplayName("Given PreTablesUpdateEvent, when constructed, then getHandlers returns non-null HandlerList") + void preTablesUpdateEvent_getHandlers_returnsNonNull() { + PreTablesUpdateEvent event = new PreTablesUpdateEvent(); + assertNotNull(event.getHandlers()); + } + + @Test + @DisplayName("Given PreTablesUpdateEvent, when getHandlerList called, then returns same instance as getHandlers") + void preTablesUpdateEvent_getHandlerList_returnsSameInstanceAsGetHandlers() { + PreTablesUpdateEvent event = new PreTablesUpdateEvent(); + assertSame(PreTablesUpdateEvent.getHandlerList(), event.getHandlers()); + } + + @Test + @DisplayName("Given two PreTablesUpdateEvents, when getHandlers called, then they share the same HandlerList") + void preTablesUpdateEvent_handlerList_isSharedAcrossInstances() { + PreTablesUpdateEvent event1 = new PreTablesUpdateEvent(); + PreTablesUpdateEvent event2 = new PreTablesUpdateEvent(); + assertSame(event1.getHandlers(), event2.getHandlers()); + } + + @Test + @DisplayName("Given TablesUpdatedEvent, when constructed, then getHandlers returns non-null HandlerList") + void tablesUpdatedEvent_getHandlers_returnsNonNull() { + TablesUpdatedEvent event = new TablesUpdatedEvent(); + assertNotNull(event.getHandlers()); + } + + @Test + @DisplayName("Given TablesUpdatedEvent, when getHandlerList called, then returns same instance as getHandlers") + void tablesUpdatedEvent_getHandlerList_returnsSameInstanceAsGetHandlers() { + TablesUpdatedEvent event = new TablesUpdatedEvent(); + assertSame(TablesUpdatedEvent.getHandlerList(), event.getHandlers()); + } + + @Test + @DisplayName("Given two TablesUpdatedEvents, when getHandlers called, then they share the same HandlerList") + void tablesUpdatedEvent_handlerList_isSharedAcrossInstances() { + TablesUpdatedEvent event1 = new TablesUpdatedEvent(); + TablesUpdatedEvent event2 = new TablesUpdatedEvent(); + assertSame(event1.getHandlers(), event2.getHandlers()); + } + + @Test + @DisplayName("Given all four event types, when getHandlerList called, then each type has its own distinct HandlerList") + void allDatabaseEvents_handlerLists_areDistinctPerType() { + HandlerList preCreate = PreTablesCreateEvent.getHandlerList(); + HandlerList created = TablesCreatedEvent.getHandlerList(); + HandlerList preUpdate = PreTablesUpdateEvent.getHandlerList(); + HandlerList updated = TablesUpdatedEvent.getHandlerList(); + + assertNotNull(preCreate); + assertNotNull(created); + assertNotNull(preUpdate); + assertNotNull(updated); + } +} diff --git a/src/test/java/com/diamonddagger590/mccore/pair/PairTest.java b/src/test/java/com/diamonddagger590/mccore/pair/PairTest.java index cffab55..41b18d1 100644 --- a/src/test/java/com/diamonddagger590/mccore/pair/PairTest.java +++ b/src/test/java/com/diamonddagger590/mccore/pair/PairTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -142,4 +143,49 @@ void equals_returnsTrue_whenMutablePairMutatedToMatch() { pair2.setRight(1); assertEquals(pair1, pair2); } + + @Test + @DisplayName("Given a pair, when equals called with non-Pair object, then returns false") + void equals_returnsFalse_whenCalledDirectlyWithNonPairObject() { + ImmutablePair pair = ImmutablePair.of("test", 1); + assertFalse(pair.equals("not a pair")); + } + + @Test + @DisplayName("Given a pair, when equals called with null, then returns false") + void equals_returnsFalse_whenCalledDirectlyWithNull() { + ImmutablePair pair = ImmutablePair.of("test", 1); + assertFalse(pair.equals(null)); + } + + @Test + @DisplayName("Given a pair with null left, when computing hashCode, then returns valid hash") + void hashCode_handlesNullLeft_whenLeftIsNull() { + MutablePair pair = MutablePair.of(null, 42); + int hash = pair.hashCode(); + assertEquals(42, hash); + } + + @Test + @DisplayName("Given a pair with null right, when computing hashCode, then returns valid hash") + void hashCode_handlesNullRight_whenRightIsNull() { + MutablePair pair = MutablePair.of("test", null); + int hash = pair.hashCode(); + assertEquals("test".hashCode(), hash); + } + + @Test + @DisplayName("Given a pair with both nulls, when computing hashCode, then returns zero") + void hashCode_returnsZero_whenBothSidesAreNull() { + MutablePair pair = MutablePair.of(null, null); + assertEquals(0, pair.hashCode()); + } + + @Test + @DisplayName("Given two pairs with null values in same positions, when comparing, then they are equal") + void equals_returnsTrue_whenBothPairsHaveNullValues() { + MutablePair pair1 = MutablePair.of(null, null); + MutablePair pair2 = MutablePair.of(null, null); + assertTrue(pair1.equals(pair2)); + } } diff --git a/src/test/java/com/diamonddagger590/mccore/parser/ParserTest.java b/src/test/java/com/diamonddagger590/mccore/parser/ParserTest.java index a08fd05..517dcef 100644 --- a/src/test/java/com/diamonddagger590/mccore/parser/ParserTest.java +++ b/src/test/java/com/diamonddagger590/mccore/parser/ParserTest.java @@ -415,4 +415,39 @@ void getValue_multipliesAllFactors_whenMultiplicationsAreChained() { void getValue_appliesCorrectPrecedence_whenOperatorsAreMixed() { assertEquals(12.0, new Parser("2+3*4-6/2+1").getValue(), DELTA); } + + @Test + @DisplayName("Given trailing extra token after valid expression, when evaluating, then throws ParseError") + void getValue_throwsParseError_whenExtraTokenAfterExpression() { + assertThrows(ParseError.class, () -> new Parser("2+3)").getValue()); + } + + @Test + @DisplayName("Given unmatched closing parenthesis mid-expression, when evaluating, then throws ParseError") + void getValue_throwsParseError_whenUnmatchedClosingParenMidExpression() { + assertThrows(ParseError.class, () -> new Parser(")2+3").getValue()); + } + + @Test + @DisplayName("Given function call missing closing bracket, when evaluating, then throws ParseError") + void getValue_throwsParseError_whenFunctionCallMissingClosingBracket() { + assertThrows(ParseError.class, () -> new Parser("sin(2+3").getValue()); + } + + @Test + @DisplayName("Given expression with getInputString, when called, then returns sanitized input") + void getInputString_returnsSanitizedInput_whenCalled() { + Parser parser = new Parser("2 + 3"); + String input = parser.getInputString(); + assertFalse(input.isEmpty()); + } + + @Test + @DisplayName("Given expression with getTree called twice, when called, then returns cached tree") + void getTree_returnsCachedTree_whenCalledTwice() { + Parser parser = new Parser("2+3"); + ExpressionNode tree1 = parser.getTree(); + ExpressionNode tree2 = parser.getTree(); + assertEquals(tree1.getValue(), tree2.getValue(), DELTA); + } } diff --git a/src/test/java/com/diamonddagger590/mccore/registry/manager/ManagerKeyTest.java b/src/test/java/com/diamonddagger590/mccore/registry/manager/ManagerKeyTest.java new file mode 100644 index 0000000..38442db --- /dev/null +++ b/src/test/java/com/diamonddagger590/mccore/registry/manager/ManagerKeyTest.java @@ -0,0 +1,34 @@ +package com.diamonddagger590.mccore.registry.manager; + +import com.diamonddagger590.mccore.chat.ChatResponseManager; +import com.diamonddagger590.mccore.command.CoreCommandManager; +import com.diamonddagger590.mccore.configuration.ReloadableContentManager; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class ManagerKeyTest { + + @Test + @DisplayName("Given COMMAND key, when managerClass called, then returns CoreCommandManager class") + void command_managerClass_returnsCoreCommandManagerClass() { + assertNotNull(ManagerKey.COMMAND); + assertEquals(CoreCommandManager.class, ManagerKey.COMMAND.managerClass()); + } + + @Test + @DisplayName("Given RELOADABLE_CONTENT key, when managerClass called, then returns ReloadableContentManager class") + void reloadableContent_managerClass_returnsReloadableContentManagerClass() { + assertNotNull(ManagerKey.RELOADABLE_CONTENT); + assertEquals(ReloadableContentManager.class, ManagerKey.RELOADABLE_CONTENT.managerClass()); + } + + @Test + @DisplayName("Given CHAT_RESPONSE key, when managerClass called, then returns ChatResponseManager class") + void chatResponse_managerClass_returnsChatResponseManagerClass() { + assertNotNull(ManagerKey.CHAT_RESPONSE); + assertEquals(ChatResponseManager.class, ManagerKey.CHAT_RESPONSE.managerClass()); + } +} From 8fee6f62d6c0042f51df4fe5663159b7bf8bb52f Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 7 Jul 2026 22:51:05 +0000 Subject: [PATCH 2/2] Address review feedback: strengthen assertions and fix naming convention - DatabaseTableEventsTest: Add assertNotSame pairwise checks to verify each event type has its own distinct HandlerList instance - ParserTest: Strengthen getInputString test to assert exact sanitized value, and getTree caching test to use assertSame for identity check - ManagerKeyTest: Rename methods to follow methodUnderTest_expectedOutcome_whenCondition convention Co-Authored-By: Claude Opus 4.6 Claude-Session: https://claude.ai/code/session_01X2Mb9p5PuTL2bSW5RMWcWF --- .../event/database/DatabaseTableEventsTest.java | 7 +++++++ .../diamonddagger590/mccore/parser/ParserTest.java | 14 +++++++------- .../mccore/registry/manager/ManagerKeyTest.java | 12 ++++++------ 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/test/java/com/diamonddagger590/mccore/event/database/DatabaseTableEventsTest.java b/src/test/java/com/diamonddagger590/mccore/event/database/DatabaseTableEventsTest.java index aa92263..41a1572 100644 --- a/src/test/java/com/diamonddagger590/mccore/event/database/DatabaseTableEventsTest.java +++ b/src/test/java/com/diamonddagger590/mccore/event/database/DatabaseTableEventsTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertSame; class DatabaseTableEventsTest { @@ -109,5 +110,11 @@ void allDatabaseEvents_handlerLists_areDistinctPerType() { assertNotNull(created); assertNotNull(preUpdate); assertNotNull(updated); + assertNotSame(preCreate, created); + assertNotSame(preCreate, preUpdate); + assertNotSame(preCreate, updated); + assertNotSame(created, preUpdate); + assertNotSame(created, updated); + assertNotSame(preUpdate, updated); } } diff --git a/src/test/java/com/diamonddagger590/mccore/parser/ParserTest.java b/src/test/java/com/diamonddagger590/mccore/parser/ParserTest.java index 517dcef..3e8303c 100644 --- a/src/test/java/com/diamonddagger590/mccore/parser/ParserTest.java +++ b/src/test/java/com/diamonddagger590/mccore/parser/ParserTest.java @@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -435,19 +436,18 @@ void getValue_throwsParseError_whenFunctionCallMissingClosingBracket() { } @Test - @DisplayName("Given expression with getInputString, when called, then returns sanitized input") - void getInputString_returnsSanitizedInput_whenCalled() { + @DisplayName("Given expression with spaces, when getInputString called, then returns input with spaces stripped") + void getInputString_returnsStrippedInput_whenExpressionContainsSpaces() { Parser parser = new Parser("2 + 3"); - String input = parser.getInputString(); - assertFalse(input.isEmpty()); + assertEquals("2+3", parser.getInputString()); } @Test - @DisplayName("Given expression with getTree called twice, when called, then returns cached tree") - void getTree_returnsCachedTree_whenCalledTwice() { + @DisplayName("Given a parsed expression, when getTree called twice, then returns the same cached instance") + void getTree_returnsSameCachedInstance_whenCalledTwice() { Parser parser = new Parser("2+3"); ExpressionNode tree1 = parser.getTree(); ExpressionNode tree2 = parser.getTree(); - assertEquals(tree1.getValue(), tree2.getValue(), DELTA); + assertSame(tree1, tree2); } } diff --git a/src/test/java/com/diamonddagger590/mccore/registry/manager/ManagerKeyTest.java b/src/test/java/com/diamonddagger590/mccore/registry/manager/ManagerKeyTest.java index 38442db..b7c7392 100644 --- a/src/test/java/com/diamonddagger590/mccore/registry/manager/ManagerKeyTest.java +++ b/src/test/java/com/diamonddagger590/mccore/registry/manager/ManagerKeyTest.java @@ -12,22 +12,22 @@ class ManagerKeyTest { @Test - @DisplayName("Given COMMAND key, when managerClass called, then returns CoreCommandManager class") - void command_managerClass_returnsCoreCommandManagerClass() { + @DisplayName("Given the COMMAND key constant, when managerClass called, then returns CoreCommandManager class") + void managerClass_returnsCoreCommandManagerClass_whenKeyIsCommand() { assertNotNull(ManagerKey.COMMAND); assertEquals(CoreCommandManager.class, ManagerKey.COMMAND.managerClass()); } @Test - @DisplayName("Given RELOADABLE_CONTENT key, when managerClass called, then returns ReloadableContentManager class") - void reloadableContent_managerClass_returnsReloadableContentManagerClass() { + @DisplayName("Given the RELOADABLE_CONTENT key constant, when managerClass called, then returns ReloadableContentManager class") + void managerClass_returnsReloadableContentManagerClass_whenKeyIsReloadableContent() { assertNotNull(ManagerKey.RELOADABLE_CONTENT); assertEquals(ReloadableContentManager.class, ManagerKey.RELOADABLE_CONTENT.managerClass()); } @Test - @DisplayName("Given CHAT_RESPONSE key, when managerClass called, then returns ChatResponseManager class") - void chatResponse_managerClass_returnsChatResponseManagerClass() { + @DisplayName("Given the CHAT_RESPONSE key constant, when managerClass called, then returns ChatResponseManager class") + void managerClass_returnsChatResponseManagerClass_whenKeyIsChatResponse() { assertNotNull(ManagerKey.CHAT_RESPONSE); assertEquals(ChatResponseManager.class, ManagerKey.CHAT_RESPONSE.managerClass()); }