MarginaliaSearch/code/libraries/coded-sequence/test/nu/marginalia/sequence/BitReaderTest.java
Viktor Lofgren ae87e41cec (index) Fix rare BitReader.takeWhileZero bug
Fix rare bug where the takeWhileZero method would fail to repopulate the underlying buffer.  This caused intermittent de-compression errors if takeWhileZero happened at a 64 bit boundary while the underlying buffer was empty.

The change also alters how sequence-lengths are encoded, to more consistently use the getGamma method instead of adding special significance to a zero first byte.

Finally, assertions are added checking the invariants of the gamma and delta coding logic as well as UrlIdCodec to earlier detect issues.
2024-07-16 11:03:56 +02:00

139 lines
3.5 KiB
Java

package nu.marginalia.sequence;
import nu.marginalia.sequence.io.BitReader;
import nu.marginalia.sequence.io.BitWriter;
import org.junit.jupiter.api.Test;
import java.nio.ByteBuffer;
import static org.junit.jupiter.api.Assertions.*;
class BitReaderTest {
@Test
void getBit() {
var writer = new BitWriter(ByteBuffer.allocate(1024));
writer.putBit(true);
writer.putBit(false);
writer.putBits(0, 32);
writer.putBit(true);
writer.putBit(false);
var buffer = writer.finish();
var reader = new BitReader(buffer);
assertTrue(reader.getBit());
assertFalse(reader.getBit());
for (int i = 0; i < 32; i++) {
assertFalse(reader.getBit());
}
assertTrue(reader.getBit());
assertFalse(reader.getBit());
}
@Test
void getInByte() {
var writer = new BitWriter(ByteBuffer.allocate(1024));
writer.putBit(true);
writer.putBit(false);
var buffer = writer.finish();
var reader = new BitReader(buffer);
int val = reader.get(2);
assertEquals(0b10, val);
}
@Test
void get() {
var writer = new BitWriter(ByteBuffer.allocate(1024));
writer.putBit(true);
writer.putBit(false);
writer.putBits(0, 32);
writer.putBit(true);
writer.putBit(false);
var buffer = writer.finish();
var reader = new BitReader(buffer);
int val = reader.get(4);
assertEquals(0b1000, val);
val = reader.get(30);
assertEquals(0b000, val);
val = reader.get(2);
assertEquals(0b10, val);
}
@Test
void getSevens() {
// Fuzz test that probes int32 misalignments
var writer = new BitWriter(ByteBuffer.allocate(1024));
for (int i = 0; i < 729; i++) {
writer.putBit(true);
writer.putBit(false);
writer.putBit(false);
writer.putBit(true);
writer.putBit(false);
writer.putBit(false);
writer.putBit(true);
}
var buffer = writer.finish();
var reader = new BitReader(buffer);
for (int i = 0; i < 729; i++) {
int val = reader.get(7);
assertEquals(0b1001001, val);
}
}
@Test
void getSevens2() {
// Fuzz test that probes int32 misalignments
var writer = new BitWriter(ByteBuffer.allocate(1024));
for (int i = 0; i < 729; i++) {
writer.putBits(73, 7);
}
var buffer = writer.finish();
var reader = new BitReader(buffer);
for (int i = 0; i < 729; i++) {
int val = reader.get(7);
assertEquals(0b1001001, val);
}
}
@Test
public void testTakeWhileZero() {
var writer = new BitWriter(ByteBuffer.allocate(1024));
writer.putBits(0, 4);
writer.putBit(true);
var buffer = writer.finish();
var reader = new BitReader(buffer);
int val = reader.takeWhileZero();
assertEquals(4, val);
assertTrue(reader.getBit());
}
@Test
public void testTakeWhileZeroOverInt64() {
var writer = new BitWriter(ByteBuffer.allocate(1024));
writer.putBits(0, 32);
writer.putBits(0, 32);
writer.putBits(0, 2);
writer.putBit(true);
var buffer = writer.finish();
var reader = new BitReader(buffer);
int val = reader.takeWhileZero();
assertEquals(66, val);
assertTrue(reader.getBit());
}
}