Skip to main content
Hytale uses codecs (encode/decode pairs) extensively for component serialization, network packets, and data persistence. HRTK’s CodecAssert class lets you verify that your codecs correctly round-trip data and gracefully handle malformed input.

CodecAssert Methods

MethodDescription
assertRoundTrip(codec, value)Encode then decode; assert result equals original
assertRoundTrip(codec, value, equalityCheck)Round-trip with custom equality predicate
assertDecodeEquals(codec, bsonValue, expected)Decode and assert result equals expected
assertDecodeThrows(codec, malformedBson)Assert decoding throws an exception

Round-Trip Testing

The most common codec test: encode a value, decode it back, and verify the result matches the original.
import com.frotty27.hrtk.api.assert_.CodecAssert;

@HytaleTest
void testTransformRoundTrip() {
    TransformComponent transform = new TransformComponent();
    CodecAssert.assertRoundTrip(TransformComponent.CODEC, transform);
}
Under the hood, assertRoundTrip calls codec.encode(value) and then codec.decode(encoded), comparing the results with Objects.equals().

Custom equality

If your type does not implement equals() correctly (or you want partial comparison), provide a custom BiPredicate:
@HytaleTest
void testRoundTripCustomEquality() {
    MyComponent original = new MyComponent(42, "test");
    CodecAssert.assertRoundTrip(MyComponent.CODEC, original, (a, b) -> {
        return a.getId() == b.getId() && a.getName().equals(b.getName());
    });
}

Decode Verification

Test that decoding a specific BSON value produces the expected result:
@HytaleTest
void testDecodeSpecificValue() {
    BsonDocument doc = new BsonDocument("x", new BsonInt32(10));
    CodecAssert.assertDecodeEquals(PositionCodec.INSTANCE, doc, new Position(10, 0, 0));
}

Malformed Input

Verify that your codec rejects invalid data instead of silently producing garbage:
@HytaleTest
void testDecodeThrowsOnNull() {
    CodecAssert.assertDecodeThrows(TransformComponent.CODEC, null);
}

@HytaleTest
void testDecodeThrowsOnInvalidType() {
    CodecAssert.assertDecodeThrows(TransformComponent.CODEC, "not-a-bson-value");
}
If assertDecodeThrows does NOT get an exception, the test fails with “Expected decode to throw but it succeeded”. This catches codecs that silently accept invalid input, which could cause data corruption.

Complete Example Suite

@HytaleSuite("Codec Tests")
@Tag("codec")
public class CodecTests {

    @HytaleTest
    @Order(1)
    void roundTripPreservesData() {
        TransformComponent transform = new TransformComponent();
        CodecAssert.assertRoundTrip(TransformComponent.CODEC, transform);
    }

    @HytaleTest
    @Order(2)
    void roundTripWithCustomCheck() {
        TransformComponent transform = new TransformComponent();
        CodecAssert.assertRoundTrip(TransformComponent.CODEC, transform,
            (a, b) -> a != null && b != null
        );
    }

    @HytaleTest
    @Order(3)
    void rejectsNullInput() {
        CodecAssert.assertDecodeThrows(TransformComponent.CODEC, null);
    }

    @HytaleTest
    @Order(4)
    void rejectsInvalidBson() {
        CodecAssert.assertDecodeThrows(TransformComponent.CODEC, "invalid");
    }

    @HytaleTest
    @Order(5)
    void codecExists() {
        HytaleAssert.assertNotNull(TransformComponent.CODEC);
    }
}

How It Works Internally

CodecAssert uses reflection to find and invoke encode() and decode() methods on the codec object. This means it works with any codec that follows the standard Hytale pattern — no compile-time coupling required.
The codec parameter is typed as Object in the API to avoid depending on HytaleServer.jar classes. At runtime, it should be a Hytale Codec<T> instance.

Next Steps