From 8f73a693ccd29d4b6458e7fd20422fed69ee812a Mon Sep 17 00:00:00 2001 From: Algent Date: Sat, 15 Aug 2026 19:42:06 +0200 Subject: [PATCH] test: characterize ControlKeyModifer Plain-JVM coverage is structural: the Java-facing isControlDown(EntityPlayer) static that the reference scaladoc calls out as existing for Java callers, and the typo in the class name, which is the published name. Forge server coverage for the behavior. isControlDown branches on whether the player's world is remote, so it needs a real player; a Forge FakePlayer on a dedicated server world takes the server branch and reads the map the client keeps in sync through packet 1. Unknown players default to not holding, the map reflects the last recorded value, and clearing resets it. The client branch reads isClientPressing instead and no harness has a client. 120 plain-JVM tests, 21 Forge server tests. --- .../test/ControlKeyModiferFunctionalTest.java | 76 +++++++++++++++++++ ...ControlKeyModiferCharacterizationTest.java | 35 +++++++++ 2 files changed, 111 insertions(+) create mode 100644 src/functionalTest/java/codechicken/multipart/test/ControlKeyModiferFunctionalTest.java create mode 100644 src/test/java/codechicken/multipart/ControlKeyModiferCharacterizationTest.java diff --git a/src/functionalTest/java/codechicken/multipart/test/ControlKeyModiferFunctionalTest.java b/src/functionalTest/java/codechicken/multipart/test/ControlKeyModiferFunctionalTest.java new file mode 100644 index 0000000..bd9d795 --- /dev/null +++ b/src/functionalTest/java/codechicken/multipart/test/ControlKeyModiferFunctionalTest.java @@ -0,0 +1,76 @@ +package codechicken.multipart.test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.util.FakePlayerFactory; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import codechicken.multipart.ControlKeyModifer; + +/** + * isControlDown needs a player with a world to pick its branch. On a dedicated server the world is never remote, so + * these cover the server half: the map the client keeps in sync through packet 1. The client half reads + * isClientPressing instead and no test harness has a client. + */ +class ControlKeyModiferFunctionalTest { + + @BeforeEach + @AfterEach + void clearRecordedPlayers() { + clearAll(); + } + + @Test + void aPlayerTheServerHasNotHeardFromIsNotHoldingTheKey() { + assertFalse(ControlKeyModifer.isControlDown(player())); + } + + @Test + void reflectsWhatTheServerLastRecordedForThePlayer() { + EntityPlayer player = player(); + + record(player, true); + assertTrue(ControlKeyModifer.isControlDown(player)); + + record(player, false); + assertFalse(ControlKeyModifer.isControlDown(player)); + } + + /** Server stop clears the map, so a player must not carry a held key into the next run. */ + @Test + void clearingResetsThePlayerToNotHolding() { + EntityPlayer player = player(); + record(player, true); + + clearAll(); + + assertFalse(ControlKeyModifer.isControlDown(player)); + } + + // The two adapters below are the only places the map's collection type is named. + + private static void record(EntityPlayer player, boolean pressed) { + ControlKeyModifer.map().put(player, pressed); + } + + private static void clearAll() { + ControlKeyModifer.map().clear(); + } + + private static EntityPlayer player() { + WorldServer world = MinecraftServer.getServer().worldServers[0]; + assertNotNull(world); + EntityPlayer player = FakePlayerFactory.getMinecraft(world); + assertNotNull(player); + assertFalse(player.worldObj.isRemote, "A dedicated server world is never remote"); + return player; + } +} diff --git a/src/test/java/codechicken/multipart/ControlKeyModiferCharacterizationTest.java b/src/test/java/codechicken/multipart/ControlKeyModiferCharacterizationTest.java new file mode 100644 index 0000000..4da0461 --- /dev/null +++ b/src/test/java/codechicken/multipart/ControlKeyModiferCharacterizationTest.java @@ -0,0 +1,35 @@ +package codechicken.multipart; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import net.minecraft.entity.player.EntityPlayer; + +import org.junit.jupiter.api.Test; + +/** + * Every branch of isControlDown needs a player with a world, so the behavior is covered by the Forge server suite + * against a FakePlayer. What is pinned here is the Java-facing entry point, which the reference scaladoc calls out as + * existing for Java callers rather than for the Scala implicit. + */ +class ControlKeyModiferCharacterizationTest { + + /** The class name carries a typo in the reference. It is the published name, so the port keeps it. */ + @Test + void theTypoInTheClassNameIsPreserved() { + assertEquals("codechicken.multipart.ControlKeyModifer", ControlKeyModifer.class.getName()); + } + + @Test + void theJavaFacingQueryIsAPublicStaticTakingAPlayer() throws Exception { + Method isControlDown = ControlKeyModifer.class.getDeclaredMethod("isControlDown", EntityPlayer.class); + + assertSame(boolean.class, isControlDown.getReturnType()); + assertTrue(Modifier.isPublic(isControlDown.getModifiers())); + assertTrue(Modifier.isStatic(isControlDown.getModifiers())); + } +}