From 55a0edac9634b8f8c769873e9d47ace54b21b61a Mon Sep 17 00:00:00 2001 From: Davide Angelocola Date: Fri, 19 Jun 2026 21:49:45 +0200 Subject: [PATCH] test(reader): full coverage for Lazy ALP array families Cover the gaps in the lazy ALP arrays to 100% line + branch: - LazyAlpFloatArray / LazyAlpDoubleArray: materialize() bulk-decode path - LazyAlpRdDoubleArray: forEachDouble + fold - LazyAlpRdFloatArray: fold + the patch-override lookup path Co-Authored-By: Claude Opus 4.8 --- .../reader/array/LazyAlpDoubleArrayTest.java | 23 +++++++ .../reader/array/LazyAlpFloatArrayTest.java | 19 ++++++ .../reader/array/LazyAlpRdArrayTest.java | 61 +++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyAlpDoubleArrayTest.java b/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyAlpDoubleArrayTest.java index 9d22cf0b..7c1051f9 100644 --- a/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyAlpDoubleArrayTest.java +++ b/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyAlpDoubleArrayTest.java @@ -112,6 +112,29 @@ void emptyReturnsIdentity() { } } + @Nested + class Materialize { + + @Test + void decodesAllRows() { + // Given + LazyAlpDoubleArray sut = of(0.01, 123L, 456L, 789L); + ValueLayout.OfDouble leDouble = + ValueLayout.JAVA_DOUBLE_UNALIGNED.withOrder(ByteOrder.LITTLE_ENDIAN); + + // When + try (Arena arena = Arena.ofConfined()) { + MemorySegment seg = sut.materialize(arena); + + // Then — each materialized row matches the lazy getter + for (int i = 0; i < 3; i++) { + assertThat(seg.getAtIndex(leDouble, i)).as("row %d", i) + .isCloseTo(sut.getDouble(i), offset(1e-12)); + } + } + } + } + @Nested class Metadata { diff --git a/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyAlpFloatArrayTest.java b/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyAlpFloatArrayTest.java index b7fc61c9..f7dfadd7 100644 --- a/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyAlpFloatArrayTest.java +++ b/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyAlpFloatArrayTest.java @@ -50,6 +50,25 @@ void foldSumApplies() { assertThat(sum).isCloseTo(10.0, offset(1e-9)); } + @Test + void materializeDecodesAllRows() { + // Given + LazyAlpFloatArray sut = of(0.01f, 123, 456, 789); + ValueLayout.OfFloat leFloat = + ValueLayout.JAVA_FLOAT_UNALIGNED.withOrder(ByteOrder.LITTLE_ENDIAN); + + // When + try (Arena arena = Arena.ofConfined()) { + MemorySegment seg = sut.materialize(arena); + + // Then — each materialized row matches the lazy getter + for (int i = 0; i < 3; i++) { + assertThat(seg.getAtIndex(leFloat, i)).as("row %d", i) + .isCloseTo(sut.getFloat(i), offset(1e-6f)); + } + } + } + @Test void metadataExposed() { // Given diff --git a/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyAlpRdArrayTest.java b/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyAlpRdArrayTest.java index b36aead6..5f0fa70c 100644 --- a/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyAlpRdArrayTest.java +++ b/reader/src/test/java/io/github/dfa1/vortex/reader/array/LazyAlpRdArrayTest.java @@ -8,6 +8,8 @@ import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; +import java.util.ArrayList; +import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -81,6 +83,35 @@ void patchOverridesDictAtPatchedIndex() { assertThat(sut.getDouble(2)).isEqualTo(base); } } + + @Test + void forEachAndFoldVisitAllRows() { + // Given — three values reconstructed dict-only + try (Arena arena = Arena.ofConfined()) { + int rightBitWidth = 48; + double[] sample = {1.0, 2.0, 4.0}; + short[] dict = new short[sample.length]; + long[] rights = new long[sample.length]; + long rightMask = (1L << rightBitWidth) - 1; + short[] codes = new short[sample.length]; + for (int i = 0; i < sample.length; i++) { + long bits = Double.doubleToRawLongBits(sample[i]); + dict[i] = (short) ((bits >>> rightBitWidth) & 0xFFFF); + rights[i] = bits & rightMask; + codes[i] = (short) i; + } + var sut = new LazyAlpRdDoubleArray(F64, sample.length, dict, rightBitWidth, + shortArray(arena, codes), longArray(arena, rights), null, new short[0], 0L); + + // When + List seen = new ArrayList<>(); + sut.forEachDouble(seen::add); + + // Then + assertThat(seen).containsExactly(1.0, 2.0, 4.0); + assertThat(sut.fold(0.0, Double::sum)).isEqualTo(7.0); + } + } } @Nested @@ -109,6 +140,36 @@ void reconstructsBitsViaDict() { assertThat(sut.getFloat(1)).isEqualTo(-2.25f); } } + + @Test + void patchOverridesDictAndFoldSums() { + // Given — row 1 patched, rows 0/2 dict; also exercises fold + the non-patch lookup + try (Arena arena = Arena.ofConfined()) { + int rightBitWidth = 16; + float base = 1.5f; + float patched = -3.0f; + int baseBits = Float.floatToRawIntBits(base); + int patchedBits = Float.floatToRawIntBits(patched); + int rightMask = (1 << rightBitWidth) - 1; + + short[] dict = {(short) ((baseBits >>> rightBitWidth) & 0xFFFF)}; + ShortArray leftArr = shortArray(arena, (short) 0, (short) 0, (short) 0); + IntArray rightArr = intArray(arena, + baseBits & rightMask, patchedBits & rightMask, baseBits & rightMask); + Array patchIdx = intArray(arena, 1); + short[] patchLeft = {(short) ((patchedBits >>> rightBitWidth) & 0xFFFF)}; + + var sut = new LazyAlpRdFloatArray(F32, 3, dict, rightBitWidth, + leftArr, rightArr, patchIdx, patchLeft, 0L); + + // Then + assertThat(sut.getFloat(0)).isEqualTo(base); + assertThat(sut.getFloat(1)).isEqualTo(patched); + assertThat(sut.getFloat(2)).isEqualTo(base); + assertThat(sut.fold(0.0, Double::sum)) + .isEqualTo((double) base + patched + base); + } + } } private static ShortArray shortArray(Arena arena, short... vs) {