Skip to content

Commit 11287da

Browse files
dfa1claude
andcommitted
test(reader): direct coverage for Offset* views + RleArrays
OffsetBool/Int/Long/Double were only covered incidentally through the RLE decode path; add direct slice tests alongside the existing Byte/Short/Float ones. Add RleArraysTest for chunkValueCount (middle-chunk, last-chunk, and firstOffset-subtraction branches). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 4caaa8e commit 11287da

2 files changed

Lines changed: 143 additions & 0 deletions

File tree

reader/src/test/java/io/github/dfa1/vortex/reader/array/OffsetArrayTest.java

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,107 @@ void foldReducesSlicedRange() {
140140
}
141141
}
142142

143+
@Nested
144+
class Bool {
145+
@Test
146+
void getBooleanShiftsByOffset() {
147+
try (Arena arena = Arena.ofConfined()) {
148+
// Given — packed bits [F, T, T, F]
149+
BoolArray inner = boolArray(arena, false, true, true, false);
150+
var sut = new OffsetBoolArray(new DType.Bool(false), 2, inner, 1L);
151+
152+
// When / Then
153+
assertThat(sut.getBoolean(0)).isTrue(); // inner[1]
154+
assertThat(sut.getBoolean(1)).isTrue(); // inner[2]
155+
assertThat(sut.length()).isEqualTo(2);
156+
}
157+
}
158+
}
159+
160+
@Nested
161+
class Int {
162+
@Test
163+
void getIntShiftsByOffset() {
164+
try (Arena arena = Arena.ofConfined()) {
165+
// Given
166+
IntArray inner = intArray(arena, 10, 20, 30, 40);
167+
var sut = new OffsetIntArray(new DType.Primitive(PType.I32, false), 2, inner, 2L);
168+
169+
// When / Then
170+
assertThat(sut.getInt(0)).isEqualTo(30);
171+
assertThat(sut.getInt(1)).isEqualTo(40);
172+
}
173+
}
174+
}
175+
176+
@Nested
177+
class Long {
178+
@Test
179+
void getLongShiftsByOffset() {
180+
try (Arena arena = Arena.ofConfined()) {
181+
// Given
182+
LongArray inner = longArray(arena, 5L, 6L, 7L, 8L);
183+
var sut = new OffsetLongArray(new DType.Primitive(PType.I64, false), 2, inner, 1L);
184+
185+
// When / Then
186+
assertThat(sut.getLong(0)).isEqualTo(6L);
187+
assertThat(sut.getLong(1)).isEqualTo(7L);
188+
}
189+
}
190+
}
191+
192+
@Nested
193+
class Double {
194+
@Test
195+
void getDoubleShiftsByOffset() {
196+
try (Arena arena = Arena.ofConfined()) {
197+
// Given
198+
DoubleArray inner = doubleArray(arena, 1.5, 2.5, 3.5);
199+
var sut = new OffsetDoubleArray(new DType.Primitive(PType.F64, false), 2, inner, 1L);
200+
201+
// When / Then
202+
assertThat(sut.getDouble(0)).isEqualTo(2.5);
203+
assertThat(sut.getDouble(1)).isEqualTo(3.5);
204+
}
205+
}
206+
}
207+
208+
private static BoolArray boolArray(Arena arena, boolean... vs) {
209+
MemorySegment seg = arena.allocate((vs.length + 7) / 8);
210+
for (int i = 0; i < vs.length; i++) {
211+
if (vs[i]) {
212+
long bi = i >>> 3;
213+
byte b = seg.get(ValueLayout.JAVA_BYTE, bi);
214+
seg.set(ValueLayout.JAVA_BYTE, bi, (byte) ((b & 0xff) | (1 << (i & 7))));
215+
}
216+
}
217+
return new MaterializedBoolArray(new DType.Bool(false), vs.length, seg.asReadOnly());
218+
}
219+
220+
private static IntArray intArray(Arena arena, int... vs) {
221+
MemorySegment seg = arena.allocate(vs.length * 4L, 4);
222+
for (int i = 0; i < vs.length; i++) {
223+
seg.setAtIndex(ValueLayout.JAVA_INT, i, vs[i]);
224+
}
225+
return new MaterializedIntArray(new DType.Primitive(PType.I32, false), vs.length, seg.asReadOnly());
226+
}
227+
228+
private static LongArray longArray(Arena arena, long... vs) {
229+
MemorySegment seg = arena.allocate(vs.length * 8L, 8);
230+
for (int i = 0; i < vs.length; i++) {
231+
seg.setAtIndex(ValueLayout.JAVA_LONG, i, vs[i]);
232+
}
233+
return new MaterializedLongArray(new DType.Primitive(PType.I64, false), vs.length, seg.asReadOnly());
234+
}
235+
236+
private static DoubleArray doubleArray(Arena arena, double... vs) {
237+
MemorySegment seg = arena.allocate(vs.length * 8L, 8);
238+
for (int i = 0; i < vs.length; i++) {
239+
seg.setAtIndex(ValueLayout.JAVA_DOUBLE, i, vs[i]);
240+
}
241+
return new MaterializedDoubleArray(new DType.Primitive(PType.F64, false), vs.length, seg.asReadOnly());
242+
}
243+
143244
private static ByteArray byteArray(Arena arena, byte... vs) {
144245
MemorySegment seg = arena.allocate(vs.length, 1);
145246
for (int i = 0; i < vs.length; i++) {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package io.github.dfa1.vortex.reader.array;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.assertj.core.api.Assertions.assertThat;
6+
7+
class RleArraysTest {
8+
9+
@Test
10+
void chunkValueCount_middleChunk_usesNextOffset() {
11+
// Given — two chunks, pool [0,3,5); firstOffset 0
12+
long[] offsets = {0, 3};
13+
14+
// When
15+
int count = RleArrays.chunkValueCount(0, 2, offsets, 0L, 5L);
16+
17+
// Then — offsets[1] - offsets[0] = 3
18+
assertThat(count).isEqualTo(3);
19+
}
20+
21+
@Test
22+
void chunkValueCount_lastChunk_usesValuesLen() {
23+
// Given — last chunk falls back to the total pool length
24+
long[] offsets = {0, 3};
25+
26+
// When
27+
int count = RleArrays.chunkValueCount(1, 2, offsets, 0L, 5L);
28+
29+
// Then — valuesLen(5) - offsets[1](3) = 2
30+
assertThat(count).isEqualTo(2);
31+
}
32+
33+
@Test
34+
void chunkValueCount_subtractsFirstOffset() {
35+
// Given — pool origin shifted by firstOffset 10
36+
long[] offsets = {10, 13};
37+
38+
// When / Then — both branches still measure the local span
39+
assertThat(RleArrays.chunkValueCount(0, 2, offsets, 10L, 5L)).isEqualTo(3);
40+
assertThat(RleArrays.chunkValueCount(1, 2, offsets, 10L, 5L)).isEqualTo(2);
41+
}
42+
}

0 commit comments

Comments
 (0)