package openmods.utils.io;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;
public class BitStreamsTest {
public static final byte b00001010 = (byte)0x0A;
public static final byte b00000000 = (byte)0x00;
public static final byte b01010101 = (byte)0x55;
public static final byte b10000000 = (byte)0x80;
public static final byte b00000001 = (byte)0x01;
public static final byte b10101010 = (byte)0xAA;
public static final byte b11111111 = (byte)0xFF;
public static final byte b10100000 = (byte)0xA0;
private static final byte b01000000 = (byte)0x40;
public static void checkInputStream(InputBitStream stream, boolean... bits) throws IOException {
int bitCount = 0;
for (boolean bit : bits) {
Assert.assertEquals("Bit " + bitCount, bit, stream.readBit());
bitCount++;
}
}
public static void writeBits(OutputBitStream stream, boolean... bits) throws IOException {
for (boolean bit : bits)
stream.writeBit(bit);
}
public static InputBitStream createInputStream(byte[] bytes) {
ByteArrayInputStream input = new ByteArrayInputStream(bytes);
return InputBitStream.create(input);
}
public static void checkInputOutput(int size, boolean[] bits) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
OutputBitStream outputStream = OutputBitStream.create(output);
for (boolean bit : bits)
outputStream.writeBit(bit);
outputStream.flush();
final byte[] bytes = output.toByteArray();
Assert.assertEquals(size, bytes.length);
ByteArrayInputStream input = new ByteArrayInputStream(bytes);
InputBitStream inputStream = InputBitStream.create(input);
checkInputStream(inputStream, bits);
}
@Test
public void testInputStreamOneByteAllZeros() throws IOException {
InputBitStream inputStream = createInputStream(new byte[] { 0 });
checkInputStream(inputStream, false, false, false, false, false, false, false, false);
}
@Test
public void testInputStreamTwoBytesAllZeros() throws IOException {
InputBitStream inputStream = createInputStream(new byte[] { 0, 0 });
checkInputStream(inputStream,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false);
}
@Test
public void testInputStreamOneByteAllOnes() throws IOException {
InputBitStream inputStream = createInputStream(new byte[] { b11111111 });
checkInputStream(inputStream,
true, true, true, true, true, true, true, true);
}
@Test
public void testInputStreamTwoBytesAllOnes() throws IOException {
InputBitStream inputStream = createInputStream(new byte[] { b11111111, b11111111 });
checkInputStream(inputStream,
true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true);
}
@Test
public void testInputStreamOneByteToggling() throws IOException {
InputBitStream inputStream = createInputStream(new byte[] { b01010101 });
checkInputStream(inputStream,
false, true, false, true, false, true, false, true);
}
@Test
public void testInputStreamTwoBytesToggling() throws IOException {
InputBitStream inputStream = createInputStream(new byte[] { b01010101, b10101010 });
checkInputStream(inputStream,
false, true, false, true, false, true, false, true,
true, false, true, false, true, false, true, false);
}
@Test
public void testInputStreamOneByteFirstOne() throws IOException {
InputBitStream inputStream = createInputStream(new byte[] { b10000000 });
checkInputStream(inputStream,
true, false, false, false, false, false, false, false);
}
@Test
public void testInputStreamOneByteLastOne() throws IOException {
InputBitStream inputStream = createInputStream(new byte[] { b00000001 });
checkInputStream(inputStream,
false, false, false, false, false, false, false, true);
}
@Test
public void testInputStreamByteCount() throws IOException {
InputBitStream inputStream = createInputStream(new byte[] { b11111111, b00000000 });
Assert.assertEquals(0, inputStream.bytesRead());
for (int i = 0; i < 8; i++) {
Assert.assertTrue(inputStream.readBit());
Assert.assertEquals(1, inputStream.bytesRead());
}
for (int i = 0; i < 8; i++) {
Assert.assertFalse(inputStream.readBit());
Assert.assertEquals(2, inputStream.bytesRead());
}
}
@Test
public void testOutputEmptyFlush() throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
OutputBitStream stream = OutputBitStream.create(output);
Assert.assertEquals(0, stream.bytesWritten());
Assert.assertArrayEquals(new byte[0], output.toByteArray());
stream.flush();
Assert.assertEquals(0, stream.bytesWritten());
Assert.assertArrayEquals(new byte[0], output.toByteArray());
}
@Test
public void testOutputBasicOperations() throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
OutputBitStream stream = OutputBitStream.create(output);
for (int i = 0; i < 8; i++) {
Assert.assertEquals(0, stream.bytesWritten());
Assert.assertEquals(0, output.toByteArray().length);
stream.writeBit(true);
Assert.assertEquals(0, stream.bytesWritten());
Assert.assertEquals(0, output.toByteArray().length);
}
stream.writeBit(true);
Assert.assertEquals(1, stream.bytesWritten());
Assert.assertArrayEquals(new byte[] { b11111111 }, output.toByteArray());
stream.flush();
Assert.assertEquals(2, stream.bytesWritten());
Assert.assertArrayEquals(new byte[] { b11111111, b10000000 }, output.toByteArray());
stream.flush();
Assert.assertEquals(2, stream.bytesWritten());
Assert.assertArrayEquals(new byte[] { b11111111, b10000000 }, output.toByteArray());
stream.writeBit(false);
stream.flush();
Assert.assertEquals(3, stream.bytesWritten());
Assert.assertArrayEquals(new byte[] { b11111111, b10000000, b00000000 }, output.toByteArray());
}
@Test
public void testOutputSingleBitFlush() throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
OutputBitStream stream = OutputBitStream.create(output);
Assert.assertEquals(0, stream.bytesWritten());
Assert.assertEquals(0, output.toByteArray().length);
stream.writeBit(true);
Assert.assertEquals(0, stream.bytesWritten());
Assert.assertEquals(0, output.toByteArray().length);
stream.flush();
Assert.assertEquals(1, stream.bytesWritten());
Assert.assertArrayEquals(new byte[] { b10000000 }, output.toByteArray());
}
@Test
public void testOutputTwoBitFlush() throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
OutputBitStream stream = OutputBitStream.create(output);
Assert.assertEquals(0, stream.bytesWritten());
Assert.assertEquals(0, output.toByteArray().length);
stream.writeBit(false);
stream.writeBit(true);
Assert.assertEquals(0, stream.bytesWritten());
Assert.assertEquals(0, output.toByteArray().length);
stream.flush();
Assert.assertEquals(1, stream.bytesWritten());
Assert.assertArrayEquals(new byte[] { b01000000 }, output.toByteArray());
}
@Test
public void testOutputFourAlternatingBits() throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
OutputBitStream stream = OutputBitStream.create(output);
writeBits(stream, true, false, true, false);
stream.flush();
Assert.assertEquals(1, stream.bytesWritten());
Assert.assertArrayEquals(new byte[] { b10100000 }, output.toByteArray());
stream.flush();
Assert.assertEquals(1, stream.bytesWritten());
Assert.assertArrayEquals(new byte[] { b10100000 }, output.toByteArray());
}
@Test
public void testInputOutput() throws IOException {
checkInputOutput(0, new boolean[0]);
checkInputOutput(1, new boolean[] { false });
checkInputOutput(1, new boolean[] { true });
checkInputOutput(1, new boolean[] { false, true });
checkInputOutput(1, new boolean[] { true, false });
checkInputOutput(1, new boolean[] { true, true, true, true, true, true, true, true });
checkInputOutput(2, new boolean[] { true, true, true, true, true, true, true, true, true });
checkInputOutput(1, new boolean[] { false, false, false, false, false, false, false, false });
checkInputOutput(2, new boolean[] { false, false, false, false, false, false, false, false, false });
checkInputOutput(1, new boolean[] { true, false, false, false });
checkInputOutput(1, new boolean[] { false, false, false, true });
checkInputOutput(2, new boolean[] {
true, false, false, false, false, false, false, false,
false, false, false, false });
checkInputOutput(2, new boolean[] {
false, false, false, false, false, false, false, false,
false, false, false, true });
checkInputOutput(2, new boolean[] {
true, false, true, false, true, false, true, false,
false, true, false, true });
checkInputOutput(2, new boolean[] {
true, true, true, true, true, true, true, true,
false, false, false, false, false, false, false, false });
}
}