diff --git a/src/test/java/com/mythlane/gravityflip/command/DefineValidationTest.java b/src/test/java/com/mythlane/gravityflip/command/DefineValidationTest.java new file mode 100644 index 0000000..d39128b --- /dev/null +++ b/src/test/java/com/mythlane/gravityflip/command/DefineValidationTest.java @@ -0,0 +1,93 @@ +package com.mythlane.gravityflip.command; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Pure-data tests for {@link DefineValidation} — no Hytale runtime dependency. + * + *

Covers : + *

+ */ +class DefineValidationTest { + + // ---------- name regex ---------- + + @Test + void validName_acceptsAlnumUnderscoreDash() { + assertTrue(DefineValidation.isValidName("abc")); + assertTrue(DefineValidation.isValidName("my-zone_1")); + assertTrue(DefineValidation.isValidName("Z")); + assertTrue(DefineValidation.isValidName("a".repeat(32))); + assertTrue(DefineValidation.isValidName("ABC_123-xyz")); + } + + @Test + void validName_rejectsNullEmptyBlankAndInvalidChars() { + assertFalse(DefineValidation.isValidName(null)); + assertFalse(DefineValidation.isValidName("")); + assertFalse(DefineValidation.isValidName(" ")); + assertFalse(DefineValidation.isValidName("my zone")); + assertFalse(DefineValidation.isValidName("a".repeat(33))); + assertFalse(DefineValidation.isValidName("name!")); + assertFalse(DefineValidation.isValidName("名前")); + assertFalse(DefineValidation.isValidName("../etc/passwd")); + assertFalse(DefineValidation.isValidName("has.dot")); + } + + // ---------- componentwise min/max ---------- + + @Test + void componentwiseMin_returnsSmallestPerAxis() { + int[] a = {5, 10, -3}; + int[] b = {1, 20, -7}; + assertArrayEquals(new int[]{1, 10, -7}, DefineValidation.componentwiseMin(a, b)); + } + + @Test + void componentwiseMax_returnsLargestPerAxis() { + int[] a = {5, 10, -3}; + int[] b = {1, 20, -7}; + assertArrayEquals(new int[]{5, 20, -3}, DefineValidation.componentwiseMax(a, b)); + } + + @Test + void componentwise_orderIndependent() { + int[] a = {1, 2, 3}; + int[] b = {4, 5, 6}; + assertArrayEquals( + DefineValidation.componentwiseMin(a, b), + DefineValidation.componentwiseMin(b, a)); + assertArrayEquals( + DefineValidation.componentwiseMax(a, b), + DefineValidation.componentwiseMax(b, a)); + } + + // ---------- inflate-max convention (block inclusion) ---------- + + /** + * A block occupies the cube between (x,y,z) and (x+1,y+1,z+1). If an AABB's max is the + * raw block coord (maxBlockX, maxBlockY, maxBlockZ), a player standing on top of that + * block is OUTSIDE the AABB. We therefore inflate max by +1 per axis. + */ + @Test + void boxFromCorners_inflateMax_includesMaxBlock() { + int[] mn = {0, 64, 0}; + int[] mx = {10, 70, 10}; + // Player feet at (10.5, 70.5, 10.5) — standing in the maxBlock cube. + double px = 10.5, py = 70.5, pz = 10.5; + // Without inflate: max = (10,70,10) — player OUT. + assertFalse(px < mx[0] && py < mx[1] && pz < mx[2]); + // With inflate: max = (11,71,11) — player IN. + int[] mxInflated = {mx[0] + 1, mx[1] + 1, mx[2] + 1}; + assertTrue(px < mxInflated[0] && py < mxInflated[1] && pz < mxInflated[2]); + } +}