diff --git a/build.gradle b/build.gradle index e57a16f..728c907 100644 --- a/build.gradle +++ b/build.gradle @@ -3,3 +3,7 @@ plugins { id 'com.gtnewhorizons.gtnhconvention' } + +tasks.test { + useJUnitPlatform() +} diff --git a/dependencies.gradle b/dependencies.gradle index 9a1a671..f723ced 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,6 +1,13 @@ // Add your dependencies here dependencies { + api('com.github.GTNewHorizons:GTNHLib:0.11.37:dev') + + testImplementation(platform("org.junit:junit-bom:5.11.4")) + testImplementation("org.junit.jupiter:junit-jupiter") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") + implementation("com.github.GTNewHorizons:CodeChickenCore:1.4.12:dev") compileOnly("com.github.GTNewHorizons:Angelica:2.1.19:dev") compileOnly("com.github.GTNewHorizons:Postea:1.2.5:dev") {transitive = false} diff --git a/src/test/java/codechicken/multipart/IDWriterCharacterizationTest.java b/src/test/java/codechicken/multipart/IDWriterCharacterizationTest.java new file mode 100644 index 0000000..b28bf45 --- /dev/null +++ b/src/test/java/codechicken/multipart/IDWriterCharacterizationTest.java @@ -0,0 +1,74 @@ +package codechicken.multipart; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.lang.reflect.Proxy; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import codechicken.lib.data.MCDataInput; +import codechicken.lib.data.MCDataOutput; +import codechicken.lib.data.MCDataOutputWrapper; + +class IDWriterCharacterizationTest { + + @ParameterizedTest(name = "max {0} encodes {1} as {2}") + @CsvSource({ "0, 305419896, '78', 120", "255, 305419896, '78', 120", + "256, 305419896, '56 78', 22136", "65535, 305419896, '56 78', 22136", + "65536, 305419896, '12 34 56 78', 305419896", "2147483647, 305419896, '12 34 56 78', 305419896", + "-2147483648, 305419896, '78', 120", "-1, 305419896, '78', 120", }) + void selectsCarrierFromMaximum(int maximum, int value, String encodedHex, int decodedValue) throws Exception { + IDWriter writer = new IDWriter(); + writer.setMax(maximum); + + byte[] encoded = encode(writer, value); + + assertArrayEquals(hex(encodedHex), encoded); + assertEquals(decodedValue, decode(writer, encoded)); + } + + private static byte[] encode(IDWriter writer, int value) { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + MCDataOutput output = new MCDataOutputWrapper(new DataOutputStream(bytes)); + writer.write().apply(output, value); + return bytes.toByteArray(); + } + + private static int decode(IDWriter writer, byte[] bytes) throws Exception { + DataInputStream data = new DataInputStream(new ByteArrayInputStream(bytes)); + MCDataInput input = (MCDataInput) Proxy.newProxyInstance( + MCDataInput.class.getClassLoader(), + new Class[] { MCDataInput.class }, + (proxy, method, arguments) -> { + switch (method.getName()) { + case "readUByte": + return (short) data.readUnsignedByte(); + case "readUShort": + return data.readUnsignedShort(); + case "readInt": + return data.readInt(); + default: + throw new AssertionError("Unexpected read method: " + method.getName()); + } + }); + + int value = (Integer) writer.read().apply(input); + assertEquals(0, data.available(), "The selected reader must consume its whole carrier"); + return value; + } + + private static byte[] hex(String value) { + String[] octets = value.split(" "); + byte[] bytes = new byte[octets.length]; + for (int i = 0; i < octets.length; i++) { + bytes[i] = (byte) Integer.parseInt(octets[i], 16); + } + return bytes; + } +}