ByteArrayBitStreamTest.java
package zserio.runtime.io;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.IOException;
import java.lang.reflect.*;
import java.math.BigInteger;
import org.junit.jupiter.api.Test;
public class ByteArrayBitStreamTest
{
@Test
public void unsignedBits() throws Exception
{
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeBits", long.class, int.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readBits", int.class);
// all possible numBits (up to 63! bits - unsigned long doesn't exists in Java)
for (int numBits = 1; numBits <= 63; ++numBits)
{
// max value and some smaller values
final long maxValue = (1L << numBits) - 1;
final Long data[] = {
maxValue,
maxValue >> 1,
maxValue >> 2,
1L,
0L,
1L,
maxValue >> 2,
maxValue >> 1,
maxValue,
};
testBitsImpl(writeMethod, readMethod, data, numBits);
}
}
@Test
public void signedBits() throws Exception
{
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeSignedBits", long.class, int.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readSignedBits", int.class);
// all possible numBits (up to 64 bits)
for (int numBits = 1; numBits <= 64; ++numBits)
{
// min and max values and some smaller values
final long minValue = -1L << (numBits - 1);
final long maxValue = (1L << (numBits - 1)) - 1;
final Long data[] = {
minValue,
maxValue,
minValue >> 1,
maxValue >> 1,
minValue >> 2,
maxValue >> 2,
0L,
maxValue >> 2,
minValue >> 2,
maxValue >> 1,
minValue >> 1,
maxValue,
minValue,
};
testBitsImpl(writeMethod, readMethod, data, numBits);
}
}
@Test
public void unsignedInt() throws Exception
{
long maxValue = (1L << 32) - 1;
Long values[] = {
maxValue,
maxValue >> 8,
maxValue >> 16,
maxValue >> 24,
1L,
0L,
1L,
maxValue >> 24,
maxValue >> 16,
maxValue >> 8,
maxValue,
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeUnsignedInt", long.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readUnsignedInt");
testImpl(writeMethod, readMethod, values, 31);
}
@Test
public void signedInt() throws Exception
{
int minValue = Integer.MIN_VALUE;
int maxValue = Integer.MAX_VALUE;
Integer values[] = {
minValue,
maxValue,
minValue >> 8,
maxValue >> 8,
minValue >> 16,
maxValue >> 16,
minValue >> 24,
maxValue >> 24,
-1,
1,
0,
1,
-1,
maxValue >> 24,
minValue >> 24,
maxValue >> 16,
minValue >> 16,
maxValue >> 8,
minValue >> 8,
maxValue,
minValue,
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeInt", int.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readInt");
testImpl(writeMethod, readMethod, values, 31);
}
@Test
public void unsignedShort() throws Exception
{
int maxValue = (1 << 16) - 1;
Integer values[] = {
maxValue,
maxValue >> 8,
1,
0,
1,
maxValue >> 8,
maxValue,
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeUnsignedShort", int.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readUnsignedShort");
testImpl(writeMethod, readMethod, values, 15);
}
@Test
public void signedShort() throws Exception
{
short minValue = Short.MIN_VALUE;
short maxValue = Short.MAX_VALUE;
Short values[] = {
minValue,
maxValue,
(short)(minValue >> 8),
(short)(maxValue >> 8),
-1,
1,
0,
1,
-1,
(short)(maxValue >> 8),
(short)(minValue >> 8),
maxValue,
minValue,
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeShort", short.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readShort");
testImpl(writeMethod, readMethod, values, 15);
}
@Test
public void unsignedByte() throws Exception
{
short maxValue = (1 << 8) - 1;
Short values[] = {
maxValue,
(short)(maxValue >> 4),
1,
0,
1,
(short)(maxValue >> 4),
maxValue,
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeUnsignedByte", short.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readUnsignedByte");
testImpl(writeMethod, readMethod, values, 7);
}
@Test
public void signedByte() throws Exception
{
byte minValue = Byte.MIN_VALUE;
byte maxValue = Byte.MAX_VALUE;
Byte values[] = {
minValue,
maxValue,
(byte)(minValue >> 4),
(byte)(maxValue >> 4),
-1,
1,
0,
1,
-1,
(byte)(maxValue >> 4),
(byte)(minValue >> 4),
maxValue,
minValue,
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeByte", byte.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readByte");
testImpl(writeMethod, readMethod, values, 7);
}
@Test
public void bigInteger() throws Exception
{
// single method for both signed and unsigned writing
Method writeMethod =
ByteArrayBitStreamWriter.class.getMethod("writeBigInteger", BigInteger.class, int.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readBigInteger", int.class);
// all possible numBits
for (int numBits = 1; numBits < 65; ++numBits)
{
BigInteger maxValue = BigInteger.ONE.shiftLeft(numBits).subtract(BigInteger.ONE);
BigInteger values[] = {
maxValue,
maxValue.shiftRight(8),
maxValue.shiftRight(16),
maxValue.shiftRight(24),
maxValue.shiftRight(32),
maxValue.shiftRight(40),
maxValue.shiftRight(48),
maxValue.shiftRight(56),
BigInteger.ONE,
BigInteger.ZERO,
BigInteger.ONE,
maxValue.shiftRight(56),
maxValue.shiftRight(48),
maxValue.shiftRight(40),
maxValue.shiftRight(32),
maxValue.shiftRight(24),
maxValue.shiftRight(16),
maxValue.shiftRight(8),
};
testBitsImpl(writeMethod, readMethod, values, numBits);
}
}
@Test
public void signedBigInteger() throws Exception
{
// single method for both signed and unsigned writing
Method writeMethod =
ByteArrayBitStreamWriter.class.getMethod("writeBigInteger", BigInteger.class, int.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readSignedBigInteger", int.class);
// all possible numBits
for (int numBits = 1; numBits < 65; ++numBits)
{
BigInteger maxValue = BigInteger.ONE.shiftLeft(numBits - 1).subtract(BigInteger.ONE);
BigInteger minValue = maxValue.negate();
BigInteger values[] = {
minValue,
maxValue,
minValue.shiftRight(8),
maxValue.shiftRight(8),
minValue.shiftRight(16),
maxValue.shiftRight(16),
minValue.shiftRight(24),
maxValue.shiftRight(24),
minValue.shiftRight(32),
maxValue.shiftRight(32),
minValue.shiftRight(40),
maxValue.shiftRight(40),
minValue.shiftRight(48),
maxValue.shiftRight(48),
minValue.shiftRight(56),
maxValue.shiftRight(56),
BigInteger.ZERO,
maxValue.shiftRight(56),
minValue.shiftRight(56),
maxValue.shiftRight(48),
minValue.shiftRight(48),
maxValue.shiftRight(40),
minValue.shiftRight(40),
maxValue.shiftRight(32),
minValue.shiftRight(32),
maxValue.shiftRight(24),
minValue.shiftRight(24),
maxValue.shiftRight(16),
minValue.shiftRight(16),
maxValue.shiftRight(8),
minValue.shiftRight(8),
};
testBitsImpl(writeMethod, readMethod, values, numBits);
}
}
@Test
public void float16() throws Exception
{
Float values[] = {
-42.5f,
-2.0f,
0.0f,
0.6171875f,
0.875f,
2.0f,
9.875f,
42.5f,
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeFloat16", float.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readFloat16");
testImpl(writeMethod, readMethod, values, 15);
}
@Test
public void float32() throws Exception
{
Float values[] = {
-42.5f,
-2.0f,
0.0f,
0.6171875f,
0.875f,
2.0f,
9.875f,
42.5f,
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeFloat32", float.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readFloat32");
testImpl(writeMethod, readMethod, values, 31);
}
@Test
public void float64() throws Exception
{
Double values[] = {
-42.5,
-2.0,
0.0,
0.6171875,
0.875,
2.0,
9.875,
42.5,
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeFloat64", double.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readFloat64");
testImpl(writeMethod, readMethod, values, 63);
}
@Test
public void bitBuffer() throws Exception
{
BitBuffer values[] = {
new BitBuffer(new byte[] {(byte)0xAB, (byte)0x07}, 11),
new BitBuffer(new byte[] {(byte)0xAB, (byte)0xCD, (byte)0x7F}, 23),
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeBitBuffer", BitBuffer.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readBitBuffer");
testImpl(writeMethod, readMethod, values, 7);
}
@Test
public void string() throws Exception
{
String values[] = {
"Hello World",
"\n\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\"\'Hello World2\0nonWrittenPart",
"Price: " + new String(new byte[] {(byte)0xE2, (byte)0x82, (byte)0x93}, "UTF-8") +
" 3 what's this? -> " + new String(new byte[] {(byte)0xC2, (byte)0xA2}, "UTF-8"),
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeString", String.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readString");
testImpl(writeMethod, readMethod, values, 7);
}
@Test
public void bytes() throws Exception
{
byte values[][] = {
{(byte)0, (byte)255},
{(byte)1, (byte)127, (byte)128, (byte)254},
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeBytes", byte[].class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readBytes");
testImpl(writeMethod, readMethod, values, 7);
}
@Test
public void bool() throws Exception
{
Boolean values[] = {
false,
true,
true,
false,
false,
true,
false,
true,
false,
false,
true,
true,
false,
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeBool", boolean.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readBool");
testImpl(writeMethod, readMethod, values, 1);
}
@Test
public void varInt16() throws Exception
{
Short values[] = {
// 1 byte
(short)0,
-(short)1,
+(short)1,
-(short)((1 << (6)) - 1),
+(short)((1 << (6)) - 1),
// 2 bytes
-(short)((1 << (6))),
+(short)((1 << (6))),
-(short)((1 << (6 + 8)) - 1),
+(short)((1 << (6 + 8)) - 1),
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeVarInt16", short.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readVarInt16");
testImpl(writeMethod, readMethod, values, 15);
}
@Test
public void varInt32() throws Exception
{
Integer values[] = {
// 1 byte
0,
-((1)),
+((1)),
-((1 << (6)) - 1),
+((1 << (6)) - 1),
// 2 bytes
-((1 << (6))),
+((1 << (6))),
-((1 << (6 + 7)) - 1),
+((1 << (6 + 7)) - 1),
// 3 bytes
-((1 << (6 + 7))),
+((1 << (6 + 7))),
-((1 << (6 + 7 + 7)) - 1),
+((1 << (6 + 7 + 7)) - 1),
// 4 bytes
-((1 << (6 + 7 + 7))),
+((1 << (6 + 7 + 7))),
-((1 << (6 + 7 + 7 + 8)) - 1),
+((1 << (6 + 7 + 7 + 8)) - 1),
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeVarInt32", int.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readVarInt32");
testImpl(writeMethod, readMethod, values, 31);
}
@Test
public void varInt64() throws Exception
{
Long values[] = {
// 1 byte
0L,
-((1L)),
+((1L)),
-((1L << (6)) - 1),
+((1L << (6)) - 1),
// 2 bytes
-((1L << (6))),
+((1L << (6))),
-((1L << (6 + 7)) - 1),
+((1L << (6 + 7)) - 1),
// 3 bytes
-((1L << (6 + 7))),
+((1L << (6 + 7))),
-((1L << (6 + 7 + 7)) - 1),
+((1L << (6 + 7 + 7)) - 1),
// 4 bytes
-((1L << (6 + 7 + 7))),
+((1L << (6 + 7 + 7))),
-((1L << (6 + 7 + 7 + 8)) - 1),
+((1L << (6 + 7 + 7 + 8)) - 1)
// 5 bytes
- ((1L << (6 + 7 + 7 + 7))),
+((1L << (6 + 7 + 7 + 7))),
-((1L << (6 + 7 + 7 + 7 + 7)) - 1),
+((1L << (6 + 7 + 7 + 7 + 7)) - 1),
// 6 bytes
-((1L << (6 + 7 + 7 + 7 + 7))),
+((1L << (6 + 7 + 7 + 7 + 7))),
-((1L << (6 + 7 + 7 + 7 + 7 + 7)) - 1),
+((1L << (6 + 7 + 7 + 7 + 7 + 7)) - 1),
// 7 bytes
-((1L << (6 + 7 + 7 + 7 + 7 + 7))),
+((1L << (6 + 7 + 7 + 7 + 7 + 7))),
-((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7)) - 1),
+((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7)) - 1),
// 8 bytes
-((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7))),
+((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7))),
-((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7 + 8)) - 1),
+((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7 + 8)) - 1),
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeVarInt64", long.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readVarInt64");
testImpl(writeMethod, readMethod, values, 63);
}
@Test
public void varUInt16() throws Exception
{
Short values[] = {
// 1 byte
(short)0,
(short)1,
(short)((1 << (7)) - 1),
// 2 bytes
(short)((1 << (7))),
(short)((1 << (7 + 8)) - 1),
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeVarUInt16", short.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readVarUInt16");
testImpl(writeMethod, readMethod, values, 15);
}
@Test
public void varUInt32() throws Exception
{
Integer values[] = {
// 1 byte
((0)),
((1)),
((1 << (7)) - 1),
// 2 bytes
((1 << (7))),
((1 << (7 + 7)) - 1),
// 3 bytes
((1 << (7 + 7))),
((1 << (7 + 7 + 7)) - 1),
// 4 bytes
((1 << (7 + 7 + 7))),
((1 << (7 + 7 + 7 + 8)) - 1),
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeVarUInt32", int.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readVarUInt32");
testImpl(writeMethod, readMethod, values, 31);
}
@Test
public void varUInt64() throws Exception
{
Long values[] = {
// 1 byte
((0L)),
((1L)),
((1L << (7)) - 1),
// 2 bytes
((1L << (7))),
((1L << (7 + 7)) - 1),
// 3 bytes
((1L << (7 + 7))),
((1L << (7 + 7 + 7)) - 1),
// 4 bytes
((1L << (7 + 7 + 7))),
((1L << (7 + 7 + 7 + 8)) - 1),
// 5 bytes
((1L << (7 + 7 + 7 + 7))),
((1L << (7 + 7 + 7 + 7 + 7)) - 1),
// 6 bytes
((1L << (7 + 7 + 7 + 7 + 7))),
((1L << (7 + 7 + 7 + 7 + 7 + 7)) - 1),
// 7 bytes
((1L << (7 + 7 + 7 + 7 + 7 + 7))),
((1L << (7 + 7 + 7 + 7 + 7 + 7 + 7)) - 1),
// 8 bytes
((1L << (7 + 7 + 7 + 7 + 7 + 7 + 7))),
((1L << (7 + 7 + 7 + 7 + 7 + 7 + 7 + 8)) - 1),
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeVarUInt64", long.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readVarUInt64");
testImpl(writeMethod, readMethod, values, 63);
}
@Test
public void varInt() throws Exception
{
Long values[] = {
// 1 byte
0L, -((1L)), +((1L)), -((1L << (6)) - 1), +((1L << (6)) - 1),
// 2 bytes
-((1L << (6))), +((1L << (6))), -((1L << (6 + 7)) - 1), +((1L << (6 + 7)) - 1),
// 3 bytes
-((1L << (6 + 7))), +((1L << (6 + 7))), -((1L << (6 + 7 + 7)) - 1), +((1L << (6 + 7 + 7)) - 1),
// 4 bytes
-((1L << (6 + 7 + 7))), +((1L << (6 + 7 + 7))), -((1L << (6 + 7 + 7 + 8)) - 1),
+((1L << (6 + 7 + 7 + 8)) - 1)
// 5 bytes
- ((1L << (6 + 7 + 7 + 7))),
+((1L << (6 + 7 + 7 + 7))), -((1L << (6 + 7 + 7 + 7 + 7)) - 1),
+((1L << (6 + 7 + 7 + 7 + 7)) - 1),
// 6 bytes
-((1L << (6 + 7 + 7 + 7 + 7))), +((1L << (6 + 7 + 7 + 7 + 7))),
-((1L << (6 + 7 + 7 + 7 + 7 + 7)) - 1), +((1L << (6 + 7 + 7 + 7 + 7 + 7)) - 1),
// 7 bytes
-((1L << (6 + 7 + 7 + 7 + 7 + 7))), +((1L << (6 + 7 + 7 + 7 + 7 + 7))),
-((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7)) - 1), +((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7)) - 1),
// 8 bytes
-((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7))), +((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7))),
-((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7 + 7)) - 1), +((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7 + 7)) - 1),
// 9 bytes
-((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7 + 7))), +((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7 + 7))),
-((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7 + 7 + 8)) - 1),
+((1L << (6 + 7 + 7 + 7 + 7 + 7 + 7 + 7 + 8)) - 1),
// 1 byte
Long.MIN_VALUE, // special case, encoded as -0
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeVarInt", long.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readVarInt");
testImpl(writeMethod, readMethod, values, 63);
}
@Test
public void varUInt() throws Exception
{
BigInteger values[] = {
// 1 byte
BigInteger.ZERO,
BigInteger.ONE,
BigInteger.ONE.shiftLeft(7).subtract(BigInteger.ONE),
// 2 bytes
BigInteger.ONE.shiftLeft(7),
BigInteger.ONE.shiftLeft(7 + 7).subtract(BigInteger.ONE),
// 3 bytes
BigInteger.ONE.shiftLeft(7 + 7),
BigInteger.ONE.shiftLeft(7 + 7 + 7).subtract(BigInteger.ONE),
// 4 bytes
BigInteger.ONE.shiftLeft(7 + 7 + 7),
BigInteger.ONE.shiftLeft(7 + 7 + 7 + 7).subtract(BigInteger.ONE),
// 5 bytes
BigInteger.ONE.shiftLeft(7 + 7 + 7 + 7),
BigInteger.ONE.shiftLeft(7 + 7 + 7 + 7 + 7).subtract(BigInteger.ONE),
// 6 bytes
BigInteger.ONE.shiftLeft(7 + 7 + 7 + 7 + 7),
BigInteger.ONE.shiftLeft(7 + 7 + 7 + 7 + 7 + 7).subtract(BigInteger.ONE),
// 7 bytes
BigInteger.ONE.shiftLeft(7 + 7 + 7 + 7 + 7 + 7),
BigInteger.ONE.shiftLeft(7 + 7 + 7 + 7 + 7 + 7 + 7).subtract(BigInteger.ONE),
// 8 bytes
BigInteger.ONE.shiftLeft(7 + 7 + 7 + 7 + 7 + 7 + 7),
BigInteger.ONE.shiftLeft(7 + 7 + 7 + 7 + 7 + 7 + 7 + 7).subtract(BigInteger.ONE),
// 9 bytes
BigInteger.ONE.shiftLeft(7 + 7 + 7 + 7 + 7 + 7 + 7 + 7),
BigInteger.ONE.shiftLeft(7 + 7 + 7 + 7 + 7 + 7 + 7 + 7 + 8).subtract(BigInteger.ONE),
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeVarUInt", BigInteger.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readVarUInt");
testImpl(writeMethod, readMethod, values, 63);
}
@Test
public void varSize() throws Exception
{
Integer values[] = {
// 1 byte
((0)),
((1)),
((1 << (7)) - 1),
// 2 bytes
((1 << (7))),
((1 << (7 + 7)) - 1),
// 3 bytes
((1 << (7 + 7))),
((1 << (7 + 7 + 7)) - 1),
// 4 bytes
((1 << (7 + 7 + 7))),
((1 << (7 + 7 + 7 + 7)) - 1),
// 5 bytes
((1 << (7 + 7 + 7 + 7))),
((1 << (2 + 7 + 7 + 7 + 8)) - 1),
};
Method writeMethod = ByteArrayBitStreamWriter.class.getMethod("writeVarSize", int.class);
Method readMethod = ByteArrayBitStreamReader.class.getMethod("readVarSize");
testImpl(writeMethod, readMethod, values, 31);
}
@Test
public void bitPosition() throws IOException
{
try (final ByteArrayBitStreamWriter writer = new ByteArrayBitStreamWriter())
{
writer.writeBits(0xaaaa, 16);
assertEquals(16, writer.getBitPosition());
writer.setBitPosition(8);
assertEquals(8, writer.getBitPosition());
writer.writeBits(0xff, 8);
assertEquals(16, writer.getBitPosition());
writer.setBitPosition(13);
assertEquals(13, writer.getBitPosition());
writer.writeBits(0, 2);
assertEquals(15, writer.getBitPosition());
writer.setBitPosition(16);
assertEquals(16, writer.getBitPosition());
final byte[] buffer = writer.toByteArray();
try (final ByteArrayBitStreamReader reader = new ByteArrayBitStreamReader(buffer))
{
assertEquals(0xaaf9, reader.readBits(16));
assertEquals(16, reader.getBitPosition());
reader.setBitPosition(8);
assertEquals(8, reader.getBitPosition());
assertEquals(0xf9, reader.readBits(8));
assertEquals(16, reader.getBitPosition());
reader.setBitPosition(13);
assertEquals(13, reader.getBitPosition());
assertEquals(0, reader.readBits(2));
assertEquals(15, reader.getBitPosition());
assertEquals(1, reader.readBits(1));
assertEquals(16, reader.getBitPosition());
}
}
}
@Test
public void alignTo() throws IOException
{
try (final ByteArrayBitStreamWriter writer = new ByteArrayBitStreamWriter())
{
writer.writeBits(5, 3);
writer.alignTo(8);
assertEquals(8, writer.getBitPosition());
writer.writeBits(0, 1);
writer.alignTo(16);
assertEquals(16, writer.getBitPosition());
writer.writeBits(0xAA, 9);
writer.alignTo(32);
assertEquals(32, writer.getBitPosition());
writer.writeBits(0xACA, 13);
writer.alignTo(64);
assertEquals(64, writer.getBitPosition());
writer.writeBits(0xCAFE, 16);
final byte[] buffer = writer.toByteArray();
try (final ByteArrayBitStreamReader reader = new ByteArrayBitStreamReader(buffer))
{
assertEquals(5, reader.readBits(3));
reader.alignTo(8);
assertEquals(8, reader.getBitPosition());
assertEquals(0, reader.readBits(1));
reader.alignTo(16);
assertEquals(16, reader.getBitPosition());
assertEquals(0xAA, reader.readBits(9));
reader.alignTo(32);
assertEquals(32, reader.getBitPosition());
assertEquals(0xACA, reader.readBits(13));
reader.alignTo(64);
assertEquals(64, reader.getBitPosition());
assertEquals(0xCAFE, reader.readBits(16));
}
}
}
private void testImpl(Method writeMethod, Method readMethod, Object[] values, int maxStartBitPos)
throws Exception
{
try
{
// all possible start bit positions
for (int bitPos = 0; bitPos <= maxStartBitPos; ++bitPos)
{
try (final ByteArrayBitStreamWriter writer = new ByteArrayBitStreamWriter())
{
if (bitPos > 0)
writer.writeBits(0, bitPos);
for (int i = 0; i < values.length; ++i)
{
writeMethod.invoke(writer, values[i]);
}
final byte[] buffer = writer.toByteArray();
try (final ByteArrayBitStreamReader reader = new ByteArrayBitStreamReader(buffer))
{
if (bitPos > 0)
reader.readBits(bitPos);
for (int i = 0; i < values.length; ++i)
{
if (values instanceof byte[][])
assertArrayEquals((byte[])values[i], (byte[])readMethod.invoke(reader));
else
assertEquals(values[i], readMethod.invoke(reader));
}
}
}
catch (AssertionError e)
{
throw new AssertionError("[bitPos=" + bitPos + "]: " + e.getMessage());
}
}
}
catch (InvocationTargetException e)
{
fail(e.getTargetException().toString());
}
}
private void testBitsImpl(Method writeMethod, Method readMethod, Object[] values, int numBits)
throws Exception
{
try
{
// all possible start bit positions
for (int bitPos = 0; bitPos < numBits; ++bitPos)
{
try (final ByteArrayBitStreamWriter writer = new ByteArrayBitStreamWriter())
{
if (bitPos > 0)
writer.writeBits(0, bitPos);
for (int i = 0; i < values.length; ++i)
writeMethod.invoke(writer, values[i], numBits);
final byte[] buffer = writer.toByteArray();
try (final ByteArrayBitStreamReader reader = new ByteArrayBitStreamReader(buffer))
{
if (bitPos > 0)
reader.readBits(bitPos);
for (int i = 0; i < values.length; ++i)
assertEquals(values[i], readMethod.invoke(reader, numBits));
}
}
catch (AssertionError e)
{
throw new AssertionError(
"[numBits=" + numBits + ", bitPos=" + bitPos + "]: " + e.getMessage());
}
}
}
catch (InvocationTargetException e)
{
fail(e.getTargetException().toString());
}
}
}