Skip to content

Commit 2ac1ea7

Browse files
committed
Zero excessive bits in readBooleanList
1 parent 9a5df24 commit 2ac1ea7

File tree

2 files changed

+51
-4
lines changed

2 files changed

+51
-4
lines changed

src/main/java/com/github/shyiko/mysql/binlog/event/deserialization/TableMapEventMetadataDeserializer.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ public TableMapEventMetadata deserialize(BinaryLogEventDataReader eventDataReade
252252
return result;
253253
}
254254

255-
256-
private static BitSet readBooleanList(ByteArrayInputStream inputStream, int length) throws IOException {
255+
// The method is visible for testing purposes.
256+
public static BitSet readBooleanList(ByteArrayInputStream inputStream, int length) throws IOException {
257257
BitSet result = new BitSet();
258258
// according to MySQL internals the amount of storage required for N columns is INT((N+7)/8) bytes
259259
byte[] bytes = inputStream.read((length + 7) >> 3);
@@ -265,7 +265,8 @@ private static BitSet readBooleanList(ByteArrayInputStream inputStream, int leng
265265
return result;
266266
}
267267

268-
private static BitSet readBooleanList(BinaryLogEventDataReader eventDataReader, int length) {
268+
// The method is visible for testing purposes.
269+
public static BitSet readBooleanList(BinaryLogEventDataReader eventDataReader, int length) {
269270
byte[] bytes = eventDataReader.readBytes((length + 7) >> 3);
270271

271272
// Bit reversion is taken from Hacker's Delight 2nd Edition 7-1.
@@ -276,6 +277,8 @@ private static BitSet readBooleanList(BinaryLogEventDataReader eventDataReader,
276277
b = (byte)(((b & 0x0f) << 4) | ((b >>> 4) & 0x0f));
277278
bytes[i] = b;
278279
}
280+
byte mask = (byte)(0xff >> (bytes.length * 8 - length));
281+
bytes[bytes.length - 1] = (byte)(bytes[bytes.length - 1] & mask);
279282

280283
return BitSet.valueOf(bytes);
281284
}

src/test/java/com/github/shyiko/mysql/binlog/event/deserialization/TableMapEventMetadataDeserializerTest.java

+45-1
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
import org.junit.Test;
66

77
import java.io.IOException;
8+
import java.nio.ByteBuffer;
89
import java.util.BitSet;
910
import java.util.stream.IntStream;
10-
import java.util.stream.Stream;
1111

1212
import org.junit.Assert;
1313

14+
import static junit.framework.Assert.assertEquals;
15+
1416
public class TableMapEventMetadataDeserializerTest {
1517
private static final byte[] DATA = {
1618
(byte)0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x74, 0x70, 0x63, 0x63, 0x32, 0x00, 0x09,
@@ -38,6 +40,48 @@ public void deserialize_shouldProperlyDeserializeData_withBinaryReader() throws
3840
assertEventData(actual);
3941
}
4042

43+
@Test
44+
public void readBooleanList_shouldConsistentlyDeserializeBitSet() throws IOException{
45+
ReadBooleanListTestData[] testData = {
46+
// 01100101 -> 01100xxx -> {1, 2}
47+
new ReadBooleanListTestData(new byte[]{0x65}, 5, new int[]{1, 2}),
48+
// 01100101 -> 01100101 -> {1, 2, 5, 7}
49+
new ReadBooleanListTestData(new byte[]{0x65}, 8, new int[]{1, 2, 5, 7}),
50+
// 01011101 00010001 -> 01011101 000xxxxx -> {1, 3, 4, 5, 7}
51+
new ReadBooleanListTestData(new byte[]{0x5d, 0x11}, 11, new int[]{1, 3, 4, 5, 7}),
52+
// 01001000 11111111 -> 01001000 1111111x -> {1, 4, 8, 9, 10, 11, 12, 13, 14}
53+
new ReadBooleanListTestData(new byte[]{0x48, (byte)0xff}, 15, new int[]{1, 4, 8, 9, 10, 11, 12, 13, 14}),
54+
// 01010101 01101100 01000011 -> 10111010 10001000 0100001x -> {1, 3, 5, 7, 9, 10, 12, 13, 17, 22}
55+
new ReadBooleanListTestData(new byte[]{0x55, 0x6c, 0x43}, 23, new int[]{1, 3, 5, 7, 9, 10, 12, 13, 17, 22}),
56+
};
57+
58+
for (int i = 0; i < testData.length; i++) {
59+
ReadBooleanListTestData currentTest = testData[i];
60+
BinaryLogEventDataReader reader = new BinaryLogEventDataReader(ByteBuffer.wrap(currentTest.data));
61+
ByteArrayInputStream inputStream = new ByteArrayInputStream(currentTest.data);
62+
63+
BitSet readerBitSet = TableMapEventMetadataDeserializer.readBooleanList(reader, currentTest.length);
64+
BitSet streamBitSet = TableMapEventMetadataDeserializer.readBooleanList(inputStream, currentTest.length);
65+
66+
BitSet expectedBitSet = IntStream.of(currentTest.expectedBitsSet).collect(BitSet::new, BitSet::set, BitSet::or);
67+
68+
assertEquals(String.format("Unexpected bits set in case %d", i), expectedBitSet, readerBitSet);
69+
assertEquals(String.format("Reader and stream results don't match in case %d", i), streamBitSet, readerBitSet);
70+
}
71+
}
72+
73+
public static class ReadBooleanListTestData {
74+
public final byte[] data;
75+
public final int length;
76+
public final int[] expectedBitsSet;
77+
78+
public ReadBooleanListTestData(byte[] data, int length, int[] expectedBitsSet) {
79+
this.data = data;
80+
this.length = length;
81+
this.expectedBitsSet = expectedBitsSet;
82+
}
83+
}
84+
4185
private static void assertEventData(TableMapEventData actual) {
4286
Assert.assertEquals(134L, actual.getTableId());
4387
Assert.assertEquals("tpcc2", actual.getDatabase());

0 commit comments

Comments
 (0)