From 32aedd423a871bfe5cb828ab70614583c36c78bf Mon Sep 17 00:00:00 2001 From: Davide Angelocola Date: Sat, 20 Jun 2026 07:47:56 +0200 Subject: [PATCH] test(reader): cover For/ZigZag Int materialize, Sparse Short/Bool, DateTimePartsArrays - LazyForIntArray / LazyZigZagIntArray: add the missing materialize() bulk-decode - LazySparseShortArray: getShort patch/fill/null + getInt/fold null-patches path - LazySparseBoolArray: getBoolean patch/fill + forEachBoolean (was untested) - DateTimePartsArrays: new test covering readLong for every integer type, masked valid/null cells, and the unsupported-type default All five at 100% line + branch. Co-Authored-By: Claude Opus 4.8 --- .../reader/array/DateTimePartsArraysTest.java | 56 +++++++++++++++++++ .../reader/array/LazyForIntArrayTest.java | 16 ++++++ .../reader/array/LazySparseArrayTest.java | 52 +++++++++++++++++ .../reader/array/LazyZigZagIntArrayTest.java | 16 ++++++ 4 files changed, 140 insertions(+) create mode 100644 reader/src/test/java/io/github/dfa1/vortex/reader/array/DateTimePartsArraysTest.java diff --git a/reader/src/test/java/io/github/dfa1/vortex/reader/array/DateTimePartsArraysTest.java b/reader/src/test/java/io/github/dfa1/vortex/reader/array/DateTimePartsArraysTest.java new file mode 100644 index 00000000..591e62a9 --- /dev/null +++ b/reader/src/test/java/io/github/dfa1/vortex/reader/array/DateTimePartsArraysTest.java @@ -0,0 +1,56 @@ +package io.github.dfa1.vortex.reader.array; + +import io.github.dfa1.vortex.core.VortexException; +import org.junit.jupiter.api.Test; + +import static io.github.dfa1.vortex.reader.array.TestArrays.bools; +import static io.github.dfa1.vortex.reader.array.TestArrays.bytes; +import static io.github.dfa1.vortex.reader.array.TestArrays.doubles; +import static io.github.dfa1.vortex.reader.array.TestArrays.ints; +import static io.github.dfa1.vortex.reader.array.TestArrays.longs; +import static io.github.dfa1.vortex.reader.array.TestArrays.shorts; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class DateTimePartsArraysTest { + + @Test + void readLong_dispatchesEveryIntegerArrayType() { + // Given / When / Then — each narrow integer type widens to signed long + assertThat(DateTimePartsArrays.readLong(bytes((byte) -7), 0)).isEqualTo(-7L); + assertThat(DateTimePartsArrays.readLong(shorts((short) 300), 0)).isEqualTo(300L); + assertThat(DateTimePartsArrays.readLong(ints(70000), 0)).isEqualTo(70000L); + assertThat(DateTimePartsArrays.readLong(longs(5_000_000_000L), 0)).isEqualTo(5_000_000_000L); + } + + @Test + void readLong_recursesThroughValidMaskedCell() { + // Given — a masked array whose cell is valid + MaskedArray masked = new MaskedArray(longs(42L, 43L), bools(true, true)); + + // When / Then — unwraps to the inner value + assertThat(DateTimePartsArrays.readLong(masked, 1)).isEqualTo(43L); + } + + @Test + void readLong_nullMaskedCell_throws() { + // Given — a masked array whose cell is null + MaskedArray masked = new MaskedArray(longs(42L, 43L), bools(true, false)); + + // When / Then + assertThatThrownBy(() -> DateTimePartsArrays.readLong(masked, 1)) + .isInstanceOf(VortexException.class) + .hasMessageContaining("null cell"); + } + + @Test + void readLong_unsupportedArrayType_throws() { + // Given — a DoubleArray is not a valid date-time part child + DoubleArray bad = doubles(1.0); + + // When / Then + assertThatThrownBy(() -> DateTimePartsArrays.readLong(bad, 0)) + .isInstanceOf(VortexException.class) + .hasMessageContaining("unsupported child array type"); + } +} diff --git a/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyForIntArrayTest.java b/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyForIntArrayTest.java index ec5742a7..205672e3 100644 --- a/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyForIntArrayTest.java +++ b/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyForIntArrayTest.java @@ -63,4 +63,20 @@ void foldSumApplies() { // Then assertThat(sum).isEqualTo(36); } + + @Test + void materializeDecodesAllRows() { + // Given + LazyForIntArray sut = of(1000, 1, 2, 3); + + // When + try (Arena arena = Arena.ofConfined()) { + MemorySegment seg = sut.materialize(arena); + + // Then — materialized rows match the lazy getter + for (int i = 0; i < 3; i++) { + assertThat(seg.getAtIndex(LE_INT, i)).as("row %d", i).isEqualTo(sut.getInt(i)); + } + } + } } diff --git a/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazySparseArrayTest.java b/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazySparseArrayTest.java index 5bbf364a..a3bfd021 100644 --- a/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazySparseArrayTest.java +++ b/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazySparseArrayTest.java @@ -8,6 +8,7 @@ import java.lang.foreign.ValueLayout; import java.util.ArrayList; +import static io.github.dfa1.vortex.encoding.DTypes.BOOL; import static io.github.dfa1.vortex.encoding.DTypes.F32; import static io.github.dfa1.vortex.encoding.DTypes.F64; import static io.github.dfa1.vortex.encoding.DTypes.I16; @@ -16,6 +17,7 @@ import static io.github.dfa1.vortex.encoding.DTypes.I8; import static io.github.dfa1.vortex.encoding.DTypes.U16; import static io.github.dfa1.vortex.encoding.DTypes.U8; +import static io.github.dfa1.vortex.reader.array.TestArrays.bools; import static io.github.dfa1.vortex.reader.array.TestArrays.bytes; import static io.github.dfa1.vortex.reader.array.TestArrays.doubles; import static io.github.dfa1.vortex.reader.array.TestArrays.floats; @@ -211,6 +213,56 @@ void shortGetIntWidensUnsigned() { // When / Then assertThat(sut.getInt(0)).isEqualTo(65535); } + + @Test + void shortGetShortPatchFillAndNullPatches() { + // Given — fill 1, patches at 1->100, 3->200 + ShortArray values = shorts((short) 100, (short) 200); + Array indices = ints(1, 3); + var sut = new LazySparseShortArray(I16, 5, (short) 1, 1, values, indices, 0L); + + // When / Then — getShort hits both patch (p>=0) and fill (p<0) + assertThat(sut.getShort(0)).isEqualTo((short) 1); + assertThat(sut.getShort(1)).isEqualTo((short) 100); + assertThat(sut.getShort(3)).isEqualTo((short) 200); + + // null patches → every position returns the fill (getShort, getInt and fold paths) + var nf = new LazySparseShortArray(I16, 3, (short) 7, 7, null, null, 0L); + assertThat(nf.getShort(0)).isEqualTo((short) 7); + assertThat(nf.getInt(0)).isEqualTo(7); + assertThat(nf.fold(0L, java.lang.Long::sum)).isEqualTo(21L); + } + } + + @Nested + class Bool { + + @Test + void getBooleanPatchAndFill() { + // Given — fill false, single patch true at index 2 + BoolArray values = bools(true); + Array indices = ints(2); + var sut = new LazySparseBoolArray(BOOL, 4, false, values, indices, 0L); + + // When / Then + assertThat(sut.getBoolean(0)).isFalse(); // fill (p<0) + assertThat(sut.getBoolean(2)).isTrue(); // patch + } + + @Test + void forEachBooleanEmitsFillAndPatches() { + // Given + BoolArray values = bools(true); + Array indices = ints(2); + var sut = new LazySparseBoolArray(BOOL, 4, false, values, indices, 0L); + + // When + var seen = new ArrayList(); + sut.forEachBoolean(seen::add); + + // Then + assertThat(seen).containsExactly(false, false, true, false); + } } @Nested diff --git a/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyZigZagIntArrayTest.java b/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyZigZagIntArrayTest.java index 3d57d8e6..31f8f976 100644 --- a/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyZigZagIntArrayTest.java +++ b/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyZigZagIntArrayTest.java @@ -65,4 +65,20 @@ void foldSumApplies() { // Then assertThat(sum).isZero(); } + + @Test + void materializeDecodesAllRows() { + // Given + LazyZigZagIntArray sut = of(0, 1, 2, 3, 4); + + // When + try (Arena arena = Arena.ofConfined()) { + MemorySegment seg = sut.materialize(arena); + + // Then — materialized rows match the lazy getter + for (int i = 0; i < 5; i++) { + assertThat(seg.getAtIndex(LE_INT, i)).as("row %d", i).isEqualTo(sut.getInt(i)); + } + } + } }