diff --git a/briar-core/src/org/briarproject/serial/ReaderImpl.java b/briar-core/src/org/briarproject/serial/ReaderImpl.java index 6a644bff6e187b2d66d791b1b4865ba3f942df6b..b8710776f6c712bf77a0211156670d620e9f8fae 100644 --- a/briar-core/src/org/briarproject/serial/ReaderImpl.java +++ b/briar-core/src/org/briarproject/serial/ReaderImpl.java @@ -1,14 +1,21 @@ package org.briarproject.serial; -import static org.briarproject.serial.Tag.BYTES; +import static org.briarproject.serial.Tag.BYTES_16; +import static org.briarproject.serial.Tag.BYTES_32; +import static org.briarproject.serial.Tag.BYTES_8; import static org.briarproject.serial.Tag.END; import static org.briarproject.serial.Tag.FALSE; import static org.briarproject.serial.Tag.FLOAT; -import static org.briarproject.serial.Tag.INTEGER; +import static org.briarproject.serial.Tag.INTEGER_16; +import static org.briarproject.serial.Tag.INTEGER_32; +import static org.briarproject.serial.Tag.INTEGER_64; +import static org.briarproject.serial.Tag.INTEGER_8; import static org.briarproject.serial.Tag.LIST; import static org.briarproject.serial.Tag.MAP; import static org.briarproject.serial.Tag.NULL; -import static org.briarproject.serial.Tag.STRING; +import static org.briarproject.serial.Tag.STRING_16; +import static org.briarproject.serial.Tag.STRING_32; +import static org.briarproject.serial.Tag.STRING_8; import static org.briarproject.serial.Tag.STRUCT; import static org.briarproject.serial.Tag.TRUE; @@ -82,20 +89,6 @@ class ReaderImpl implements Reader { readIntoBuffer(buf, length, consume); } - private int readInt32(boolean consume) throws IOException { - readIntoBuffer(4, consume); - int value = 0; - for(int i = 0; i < 4; i++) value |= (buf[i] & 0xFF) << (24 - i * 8); - return value; - } - - private long readInt64(boolean consume) throws IOException { - readIntoBuffer(8, consume); - long value = 0; - for(int i = 0; i < 8; i++) value |= (buf[i] & 0xFFL) << (56 - i * 8); - return value; - } - private void skip(int length) throws IOException { while(length > 0) { int read = in.read(buf, 0, Math.min(length, buf.length)); @@ -154,18 +147,56 @@ class ReaderImpl implements Reader { public boolean hasInteger() throws IOException { if(!hasLookahead) readLookahead(); if(eof) return false; - return next == INTEGER; + return next == INTEGER_8 || next == INTEGER_16 || next == INTEGER_32 || + next == INTEGER_64; } public long readInteger() throws IOException { if(!hasInteger()) throw new FormatException(); consumeLookahead(); + if(next == INTEGER_8) return readInt8(true); + if(next == INTEGER_16) return readInt16(true); + if(next == INTEGER_32) return readInt32(true); return readInt64(true); } + private int readInt8(boolean consume) throws IOException { + readIntoBuffer(1, consume); + return buf[0]; + } + + private short readInt16(boolean consume) throws IOException { + readIntoBuffer(2, consume); + short value = (short) (((buf[0] & 0xFF) << 8) + (buf[1] & 0xFF)); + if(value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) + throw new FormatException(); + return value; + } + + private int readInt32(boolean consume) throws IOException { + readIntoBuffer(4, consume); + int value = 0; + for(int i = 0; i < 4; i++) value |= (buf[i] & 0xFF) << (24 - i * 8); + if(value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) + throw new FormatException(); + return value; + } + + private long readInt64(boolean consume) throws IOException { + readIntoBuffer(8, consume); + long value = 0; + for(int i = 0; i < 8; i++) value |= (buf[i] & 0xFFL) << (56 - i * 8); + if(value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) + throw new FormatException(); + return value; + } + public void skipInteger() throws IOException { if(!hasInteger()) throw new FormatException(); - skip(8); + if(next == INTEGER_8) skip(1); + else if(next == INTEGER_16) skip(2); + else if(next == INTEGER_32) skip(4); + else skip(8); hasLookahead = false; } @@ -178,7 +209,10 @@ class ReaderImpl implements Reader { public double readFloat() throws IOException { if(!hasFloat()) throw new FormatException(); consumeLookahead(); - return Double.longBitsToDouble(readInt64(true)); + readIntoBuffer(8, true); + long value = 0; + for(int i = 0; i < 8; i++) value |= (buf[i] & 0xFFL) << (56 - i * 8); + return Double.longBitsToDouble(value); } public void skipFloat() throws IOException { @@ -190,22 +224,29 @@ class ReaderImpl implements Reader { public boolean hasString() throws IOException { if(!hasLookahead) readLookahead(); if(eof) return false; - return next == STRING; + return next == STRING_8 || next == STRING_16 || next == STRING_32; } public String readString(int maxLength) throws IOException { if(!hasString()) throw new FormatException(); consumeLookahead(); - int length = readInt32(true); + int length = readStringLength(true); if(length < 0 || length > maxLength) throw new FormatException(); if(length == 0) return ""; readIntoBuffer(length, true); return new String(buf, 0, length, "UTF-8"); } + private int readStringLength(boolean consume) throws IOException { + if(next == STRING_8) return readInt8(consume); + if(next == STRING_16) return readInt16(consume); + if(next == STRING_32) return readInt32(consume); + throw new FormatException(); + } + public void skipString(int maxLength) throws IOException { if(!hasString()) throw new FormatException(); - int length = readInt32(false); + int length = readStringLength(false); if(length < 0 || length > maxLength) throw new FormatException(); skip(length); hasLookahead = false; @@ -214,13 +255,13 @@ class ReaderImpl implements Reader { public boolean hasBytes() throws IOException { if(!hasLookahead) readLookahead(); if(eof) return false; - return next == BYTES; + return next == BYTES_8 || next == BYTES_16 || next == BYTES_32; } public byte[] readBytes(int maxLength) throws IOException { if(!hasBytes()) throw new FormatException(); consumeLookahead(); - int length = readInt32(true); + int length = readBytesLength(true); if(length < 0 || length > maxLength) throw new FormatException(); if(length == 0) return EMPTY_BUFFER; byte[] b = new byte[length]; @@ -228,9 +269,16 @@ class ReaderImpl implements Reader { return b; } + private int readBytesLength(boolean consume) throws IOException { + if(next == BYTES_8) return readInt8(consume); + if(next == BYTES_16) return readInt16(consume); + if(next == BYTES_32) return readInt32(consume); + throw new FormatException(); + } + public void skipBytes(int maxLength) throws IOException { if(!hasBytes()) throw new FormatException(); - int length = readInt32(false); + int length = readBytesLength(false); if(length < 0 || length > maxLength) throw new FormatException(); skip(length); hasLookahead = false; diff --git a/briar-core/src/org/briarproject/serial/SerialComponentImpl.java b/briar-core/src/org/briarproject/serial/SerialComponentImpl.java index f94aeabbce7c57ad9d22014c52a0e470ad4ec2df..8a7a42ab1f2aa4805e1c1f7133cdc1418fd4231c 100644 --- a/briar-core/src/org/briarproject/serial/SerialComponentImpl.java +++ b/briar-core/src/org/briarproject/serial/SerialComponentImpl.java @@ -26,7 +26,13 @@ class SerialComponentImpl implements SerialComponent { } public int getSerialisedUniqueIdLength() { - // BYTES tag, 32-bit length, bytes - return 5 + UniqueId.LENGTH; + // BYTES_8, BYTES_16 or BYTES_32 tag, length, bytes + return 1 + getLengthBytes(UniqueId.LENGTH) + UniqueId.LENGTH; + } + + private int getLengthBytes(int length) { + if(length <= Byte.MAX_VALUE) return 1; + if(length <= Short.MAX_VALUE) return 2; + return 4; } } diff --git a/briar-core/src/org/briarproject/serial/Tag.java b/briar-core/src/org/briarproject/serial/Tag.java index af7056186eee92717d4178daeaf60fa18fa79e71..9fe385dfaccf29371e318de45bebc1fa92e83dc1 100644 --- a/briar-core/src/org/briarproject/serial/Tag.java +++ b/briar-core/src/org/briarproject/serial/Tag.java @@ -2,15 +2,22 @@ package org.briarproject.serial; interface Tag { - byte FALSE = 0; - byte TRUE = 1; - byte INTEGER = 2; - byte FLOAT = 3; - byte STRING = 4; - byte BYTES = 5; - byte LIST = 6; - byte MAP = 7; - byte STRUCT = 8; - byte END = 9; - byte NULL = 10; + byte FALSE = 0x00; + byte TRUE = 0x01; + byte INTEGER_8 = 0x02; + byte INTEGER_16 = 0x03; + byte INTEGER_32 = 0x04; + byte INTEGER_64 = 0x05; + byte FLOAT = 0x06; + byte STRING_8 = 0x07; + byte STRING_16 = 0x08; + byte STRING_32 = 0x09; + byte BYTES_8 = 0x0A; + byte BYTES_16 = 0x0B; + byte BYTES_32 = 0x0C; + byte LIST = 0x0D; + byte MAP = 0x0E; + byte STRUCT = 0x0F; + byte END = 0x10; + byte NULL = 0x11; } diff --git a/briar-core/src/org/briarproject/serial/WriterImpl.java b/briar-core/src/org/briarproject/serial/WriterImpl.java index 9e8ffe76603968f0950f1c974221dcb121d7e667..45995cdb0ef07697806671c69434b6debc5d084b 100644 --- a/briar-core/src/org/briarproject/serial/WriterImpl.java +++ b/briar-core/src/org/briarproject/serial/WriterImpl.java @@ -1,9 +1,17 @@ package org.briarproject.serial; +import static org.briarproject.serial.Tag.BYTES_16; +import static org.briarproject.serial.Tag.BYTES_32; +import static org.briarproject.serial.Tag.BYTES_8; import static org.briarproject.serial.Tag.FALSE; import static org.briarproject.serial.Tag.FLOAT; -import static org.briarproject.serial.Tag.INTEGER; -import static org.briarproject.serial.Tag.STRING; +import static org.briarproject.serial.Tag.INTEGER_16; +import static org.briarproject.serial.Tag.INTEGER_32; +import static org.briarproject.serial.Tag.INTEGER_64; +import static org.briarproject.serial.Tag.INTEGER_8; +import static org.briarproject.serial.Tag.STRING_16; +import static org.briarproject.serial.Tag.STRING_32; +import static org.briarproject.serial.Tag.STRING_8; import static org.briarproject.serial.Tag.TRUE; import java.io.IOException; @@ -49,20 +57,43 @@ class WriterImpl implements Writer { else write(FALSE); } - public void writeInteger(long l) throws IOException { - write(INTEGER); - writeInt64(l); + public void writeInteger(long i) throws IOException { + if(i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE) { + write(INTEGER_8); + write((byte) i); + } else if(i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) { + write(INTEGER_16); + writeInt16((short) i); + } else if(i >= Integer.MIN_VALUE && i <= Integer.MAX_VALUE) { + write(INTEGER_32); + writeInt32((int) i); + } else { + write(INTEGER_64); + writeInt64(i); + } + } + + private void writeInt16(short i) throws IOException { + write((byte) (i >> 8)); + write((byte) ((i << 8) >> 8)); + } + + private void writeInt32(int i) throws IOException { + write((byte) (i >> 24)); + write((byte) ((i << 8) >> 24)); + write((byte) ((i << 16) >> 24)); + write((byte) ((i << 24) >> 24)); } - private void writeInt64(long l) throws IOException { - write((byte) (l >> 56)); - write((byte) ((l << 8) >> 56)); - write((byte) ((l << 16) >> 56)); - write((byte) ((l << 24) >> 56)); - write((byte) ((l << 32) >> 56)); - write((byte) ((l << 40) >> 56)); - write((byte) ((l << 48) >> 56)); - write((byte) ((l << 56) >> 56)); + private void writeInt64(long i) throws IOException { + write((byte) (i >> 56)); + write((byte) ((i << 8) >> 56)); + write((byte) ((i << 16) >> 56)); + write((byte) ((i << 24) >> 56)); + write((byte) ((i << 32) >> 56)); + write((byte) ((i << 40) >> 56)); + write((byte) ((i << 48) >> 56)); + write((byte) ((i << 56) >> 56)); } public void writeFloat(double d) throws IOException { @@ -72,22 +103,30 @@ class WriterImpl implements Writer { public void writeString(String s) throws IOException { byte[] b = s.getBytes("UTF-8"); - write(STRING); - writeLength(b.length); + if(b.length <= Byte.MAX_VALUE) { + write(STRING_8); + write((byte) b.length); + } else if(b.length <= Short.MAX_VALUE) { + write(STRING_16); + writeInt16((short) b.length); + } else { + write(STRING_32); + writeInt32(b.length); + } write(b); } - private void writeLength(int i) throws IOException { - assert i >= 0; - write((byte) (i >> 24)); - write((byte) ((i << 8) >> 24)); - write((byte) ((i << 16) >> 24)); - write((byte) ((i << 24) >> 24)); - } - public void writeBytes(byte[] b) throws IOException { - write(Tag.BYTES); - writeLength(b.length); + if(b.length <= Byte.MAX_VALUE) { + write(BYTES_8); + write((byte) b.length); + } else if(b.length <= Short.MAX_VALUE) { + write(BYTES_16); + writeInt16((short) b.length); + } else { + write(BYTES_32); + writeInt32(b.length); + } write(b); } diff --git a/briar-tests/build.xml b/briar-tests/build.xml index f5d288ba6ef8328500fb9393bf14c3b4e3ee6c8b..a7d749821fb4d3e272201eee473219800329c834 100644 --- a/briar-tests/build.xml +++ b/briar-tests/build.xml @@ -76,11 +76,10 @@ </javac> </target> <target name='test' depends='compile'> - <junit printsummary='on' fork='yes' forkmode='once' haltonfailure='yes' showoutput='true'> + <junit printsummary='on' fork='yes' forkmode='once' haltonfailure='yes'> <assertions> <enable/> </assertions> - <formatter type="plain" usefile="false"/> <classpath> <fileset refid='test-jars'/> <fileset refid='desktop-jars'/> diff --git a/briar-tests/src/org/briarproject/TestUtils.java b/briar-tests/src/org/briarproject/TestUtils.java index 4c39dec2a236a22479550d7ec96dedf09d5f6d20..40618408cf470249870233f6a0e939ef6361a6be 100644 --- a/briar-tests/src/org/briarproject/TestUtils.java +++ b/briar-tests/src/org/briarproject/TestUtils.java @@ -12,7 +12,7 @@ import org.briarproject.api.UniqueId; public class TestUtils { private static final AtomicInteger nextTestDir = - new AtomicInteger((int) (Math.random() * 1000 * 1000)); + new AtomicInteger((int) (Math.random() * 1000 * 1000)); private static final Random random = new Random(); public static void delete(File f) { @@ -45,10 +45,10 @@ public class TestUtils { return b; } - public static String createRandomString(int length) throws Exception { - StringBuilder s = new StringBuilder(length); + public static String createRandomString(int length) { + char[] c = new char[length]; for(int i = 0; i < length; i++) - s.append((char) ('a' + random.nextInt(26))); - return s.toString(); + c[i] = (char) ('a' + random.nextInt(26)); + return new String(c); } } diff --git a/briar-tests/src/org/briarproject/serial/ReaderImplTest.java b/briar-tests/src/org/briarproject/serial/ReaderImplTest.java index 30c4eb1e4fafa590e933487317f35686b68a4449..54210b540ac084c638294fa7a7243ac638bfca50 100644 --- a/briar-tests/src/org/briarproject/serial/ReaderImplTest.java +++ b/briar-tests/src/org/briarproject/serial/ReaderImplTest.java @@ -5,6 +5,7 @@ import static org.junit.Assert.assertArrayEquals; import java.io.ByteArrayInputStream; import org.briarproject.BriarTestCase; +import org.briarproject.TestUtils; import org.briarproject.api.FormatException; import org.briarproject.util.StringUtils; import org.junit.Test; @@ -31,31 +32,128 @@ public class ReaderImplTest extends BriarTestCase { } @Test - public void testReadInteger() throws Exception { - setContents("02" + "0000000000000000" + "02" + "FFFFFFFFFFFFFFFF" - + "02" + "7FFFFFFFFFFFFFFF" + "02" + "8000000000000000"); + public void testReadInt8() throws Exception { + setContents("02" + "00" + "02" + "FF" + + "02" + "7F" + "02" + "80"); assertEquals(0, r.readInteger()); assertEquals(-1, r.readInteger()); + assertEquals(Byte.MAX_VALUE, r.readInteger()); + assertEquals(Byte.MIN_VALUE, r.readInteger()); + assertTrue(r.eof()); + } + + @Test + public void testSkipInt8() throws Exception { + setContents("02" + "00"); + r.skipInteger(); + assertTrue(r.eof()); + } + + @Test + public void testReadInt16() throws Exception { + setContents("03" + "0080" + "03" + "FF7F" + + "03" + "7FFF" + "03" + "8000"); + assertEquals(Byte.MAX_VALUE + 1, r.readInteger()); + assertEquals(Byte.MIN_VALUE - 1, r.readInteger()); + assertEquals(Short.MAX_VALUE, r.readInteger()); + assertEquals(Short.MIN_VALUE, r.readInteger()); + assertTrue(r.eof()); + } + + @Test + public void testSkipInt16() throws Exception { + setContents("03" + "0080"); + r.skipInteger(); + assertTrue(r.eof()); + } + + @Test + public void testReadInt32() throws Exception { + setContents("04" + "00008000" + "04" + "FFFF7FFF" + + "04" + "7FFFFFFF" + "04" + "80000000"); + assertEquals(Short.MAX_VALUE + 1, r.readInteger()); + assertEquals(Short.MIN_VALUE - 1, r.readInteger()); + assertEquals(Integer.MAX_VALUE, r.readInteger()); + assertEquals(Integer.MIN_VALUE, r.readInteger()); + assertTrue(r.eof()); + } + + @Test + public void testSkipInt32() throws Exception { + setContents("04" + "00008000"); + r.skipInteger(); + assertTrue(r.eof()); + } + + @Test + public void testReadInt64() throws Exception { + setContents("05" + "0000000080000000" + "05" + "FFFFFFFF7FFFFFFF" + + "05" + "7FFFFFFFFFFFFFFF" + "05" + "8000000000000000"); + assertEquals(Integer.MAX_VALUE + 1L, r.readInteger()); + assertEquals(Integer.MIN_VALUE - 1L, r.readInteger()); assertEquals(Long.MAX_VALUE, r.readInteger()); assertEquals(Long.MIN_VALUE, r.readInteger()); assertTrue(r.eof()); } @Test - public void testSkipInteger() throws Exception { - setContents("02" + "0000000000000000"); + public void testSkipInt64() throws Exception { + setContents("05" + "0000000080000000"); r.skipInteger(); assertTrue(r.eof()); } + @Test + public void testIntegersMustHaveMinimalLength() throws Exception { + // INTEGER_16 could be encoded as INTEGER_8 + setContents("02" + "7F" + "03" + "007F"); + assertEquals(Byte.MAX_VALUE, r.readInteger()); + try { + r.readInteger(); + fail(); + } catch(FormatException expected) {} + setContents("02" + "80" + "03" + "FF80"); + assertEquals(Byte.MIN_VALUE, r.readInteger()); + try { + r.readInteger(); + fail(); + } catch(FormatException expected) {} + // INTEGER_32 could be encoded as INTEGER_16 + setContents("03" + "7FFF" + "04" + "00007FFF"); + assertEquals(Short.MAX_VALUE, r.readInteger()); + try { + r.readInteger(); + fail(); + } catch(FormatException expected) {} + setContents("03" + "8000" + "04" + "FFFF8000"); + assertEquals(Short.MIN_VALUE, r.readInteger()); + try { + r.readInteger(); + fail(); + } catch(FormatException expected) {} + // INTEGER_64 could be encoded as INTEGER_32 + setContents("04" + "7FFFFFFF" + "05" + "000000007FFFFFFF"); + assertEquals(Integer.MAX_VALUE, r.readInteger()); + try { + r.readInteger(); + fail(); + } catch(FormatException expected) {} + setContents("04" + "80000000" + "05" + "FFFFFFFF80000000"); + assertEquals(Integer.MIN_VALUE, r.readInteger()); + try { + r.readInteger(); + fail(); + } catch(FormatException expected) {} + } + @Test public void testReadFloat() throws Exception { // http://babbage.cs.qc.edu/IEEE-754/Decimal.html // http://steve.hollasch.net/cgindex/coding/ieeefloat.html - setContents("03" + "0000000000000000" + "03" + "3FF0000000000000" - + "03" + "4000000000000000" + "03" + "BFF0000000000000" - + "03" + "8000000000000000" + "03" + "FFF0000000000000" - + "03" + "7FF0000000000000" + "03" + "7FF8000000000000"); + setContents("06" + "0000000000000000" + "06" + "3FF0000000000000" + + "06" + "4000000000000000" + "06" + "BFF0000000000000" + + "06" + "8000000000000000" + "06" + "FFF0000000000000" + + "06" + "7FF0000000000000" + "06" + "7FF8000000000000"); assertEquals(0.0, r.readFloat()); assertEquals(1.0, r.readFloat()); assertEquals(2.0, r.readFloat()); @@ -69,25 +167,28 @@ public class ReaderImplTest extends BriarTestCase { @Test public void testSkipFloat() throws Exception { - setContents("03" + "0000000000000000"); + setContents("06" + "0000000000000000"); r.skipFloat(); assertTrue(r.eof()); } @Test - public void testReadString() throws Exception { - // "foo" and the empty string - setContents("04" + "00000003" + "666F6F" + "04" + "00000000"); + public void testReadString8() throws Exception { + String longest = TestUtils.createRandomString(Byte.MAX_VALUE); + String longHex = StringUtils.toHexString(longest.getBytes("UTF-8")); + // "foo", the empty string, and 127 random letters + setContents("07" + "03" + "666F6F" + "07" + "00" + + "07" + "7F" + longHex); assertEquals("foo", r.readString(Integer.MAX_VALUE)); assertEquals("", r.readString(Integer.MAX_VALUE)); + assertEquals(longest, r.readString(Integer.MAX_VALUE)); assertTrue(r.eof()); } @Test - public void testReadStringMaxLength() throws Exception { + public void testReadString8ChecksMaxLength() throws Exception { // "foo" twice - setContents("04" + "00000003" + "666F6F" + - "04" + "00000003" + "666F6F"); + setContents("07" + "03" + "666F6F" + "07" + "03" + "666F6F"); assertEquals("foo", r.readString(3)); assertTrue(r.hasString()); try { @@ -97,19 +198,22 @@ public class ReaderImplTest extends BriarTestCase { } @Test - public void testSkipString() throws Exception { - // "foo" and the empty string - setContents("04" + "00000003" + "666F6F" + "04" + "00000000"); + public void testSkipString8() throws Exception { + String longest = TestUtils.createRandomString(Byte.MAX_VALUE); + String longHex = StringUtils.toHexString(longest.getBytes("UTF-8")); + // "foo", the empty string, and 127 random letters + setContents("07" + "03" + "666F6F" + "07" + "00" + + "07" + "7F" + longHex); + r.skipString(Integer.MAX_VALUE); r.skipString(Integer.MAX_VALUE); r.skipString(Integer.MAX_VALUE); assertTrue(r.eof()); } @Test - public void testSkipStringMaxLength() throws Exception { + public void testSkipString8ChecksMaxLength() throws Exception { // "foo" twice - setContents("04" + "00000003" + "666F6F" + - "04" + "00000003" + "666F6F"); + setContents("07" + "03" + "666F6F" + "07" + "03" + "666F6F"); r.skipString(3); assertTrue(r.hasString()); try { @@ -119,19 +223,150 @@ public class ReaderImplTest extends BriarTestCase { } @Test - public void testReadBytes() throws Exception { - // {1, 2, 3} and {} - setContents("05" + "00000003" + "010203" + "05" + "00000000"); + public void testReadString16() throws Exception { + String shortest = TestUtils.createRandomString(Byte.MAX_VALUE + 1); + String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8")); + String longest = TestUtils.createRandomString(Short.MAX_VALUE); + String longHex = StringUtils.toHexString(longest.getBytes("UTF-8")); + // 128 random letters and 2^15 -1 random letters + setContents("08" + "0080" + shortHex + "08" + "7FFF" + longHex); + assertEquals(shortest, r.readString(Integer.MAX_VALUE)); + assertEquals(longest, r.readString(Integer.MAX_VALUE)); + assertTrue(r.eof()); + } + + @Test + public void testReadString16ChecksMaxLength() throws Exception { + String shortest = TestUtils.createRandomString(Byte.MAX_VALUE + 1); + String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8")); + // 128 random letters, twice + setContents("08" + "0080" + shortHex + "08" + "0080" + shortHex); + assertEquals(shortest, r.readString(Byte.MAX_VALUE + 1)); + assertTrue(r.hasString()); + try { + r.readString(Byte.MAX_VALUE); + fail(); + } catch(FormatException expected) {} + } + + @Test + public void testSkipString16() throws Exception { + String shortest = TestUtils.createRandomString(Byte.MAX_VALUE + 1); + String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8")); + String longest = TestUtils.createRandomString(Short.MAX_VALUE); + String longHex = StringUtils.toHexString(longest.getBytes("UTF-8")); + // 128 random letters and 2^15 - 1 random letters + setContents("08" + "0080" + shortHex + "08" + "7FFF" + longHex); + r.skipString(Integer.MAX_VALUE); + r.skipString(Integer.MAX_VALUE); + assertTrue(r.eof()); + } + + @Test + public void testSkipString16ChecksMaxLength() throws Exception { + String shortest = TestUtils.createRandomString(Byte.MAX_VALUE + 1); + String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8")); + // 128 random letters, twice + setContents("08" + "0080" + shortHex + "08" + "0080" + shortHex); + r.skipString(Byte.MAX_VALUE + 1); + assertTrue(r.hasString()); + try { + r.skipString(Byte.MAX_VALUE); + fail(); + } catch(FormatException expected) {} + } + + @Test + public void testReadString32() throws Exception { + String shortest = TestUtils.createRandomString(Short.MAX_VALUE + 1); + String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8")); + // 2^15 random letters + setContents("09" + "00008000" + shortHex); + assertEquals(shortest, r.readString(Integer.MAX_VALUE)); + assertTrue(r.eof()); + } + + @Test + public void testReadString32ChecksMaxLength() throws Exception { + String shortest = TestUtils.createRandomString(Short.MAX_VALUE + 1); + String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8")); + // 2^15 random letters, twice + setContents("09" + "00008000" + shortHex + + "09" + "00008000" + shortHex); + assertEquals(shortest, r.readString(Short.MAX_VALUE + 1)); + assertTrue(r.hasString()); + try { + r.readString(Short.MAX_VALUE); + fail(); + } catch(FormatException expected) {} + } + + @Test + public void testSkipString32() throws Exception { + String shortest = TestUtils.createRandomString(Short.MAX_VALUE + 1); + String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8")); + // 2^15 random letters, twice + setContents("09" + "00008000" + shortHex + + "09" + "00008000" + shortHex); + r.skipString(Integer.MAX_VALUE); + r.skipString(Integer.MAX_VALUE); + assertTrue(r.eof()); + } + + @Test + public void testSkipString32ChecksMaxLength() throws Exception { + String shortest = TestUtils.createRandomString(Short.MAX_VALUE + 1); + String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8")); + // 2^15 random letters, twice + setContents("09" + "00008000" + shortHex + + "09" + "00008000" + shortHex); + r.skipString(Short.MAX_VALUE + 1); + assertTrue(r.hasString()); + try { + r.skipString(Short.MAX_VALUE); + fail(); + } catch(FormatException expected) {} + } + + @Test + public void testStringsMustHaveMinimalLength() throws Exception { + // STRING_16 could be encoded as STRING_8 + String longest8 = TestUtils.createRandomString(Byte.MAX_VALUE); + String long8Hex = StringUtils.toHexString(longest8.getBytes("UTF-8")); + setContents("07" + "7F" + long8Hex + "08" + "007F" + long8Hex); + assertEquals(longest8, r.readString(Integer.MAX_VALUE)); + try { + r.readString(Integer.MAX_VALUE); + fail(); + } catch(FormatException expected) {} + // STRING_32 could be encoded as STRING_16 + String longest16 = TestUtils.createRandomString(Short.MAX_VALUE); + String long16Hex = StringUtils.toHexString(longest16.getBytes("UTF-8")); + setContents("08" + "7FFF" + long16Hex + "09" + "00007FFF" + long16Hex); + assertEquals(longest16, r.readString(Integer.MAX_VALUE)); + try { + r.readString(Integer.MAX_VALUE); + fail(); + } catch(FormatException expected) {} + } + + @Test + public void testReadBytes8() throws Exception { + byte[] longest = new byte[Byte.MAX_VALUE]; + String longHex = StringUtils.toHexString(longest); + // {1, 2, 3}, {}, and 127 zero bytes + setContents("0A" + "03" + "010203" + "0A" + "00" + + "0A" + "7F" + longHex); assertArrayEquals(new byte[] {1, 2, 3}, r.readBytes(Integer.MAX_VALUE)); - assertArrayEquals(new byte[] {}, r.readBytes(Integer.MAX_VALUE)); + assertArrayEquals(new byte[0], r.readBytes(Integer.MAX_VALUE)); + assertArrayEquals(longest, r.readBytes(Integer.MAX_VALUE)); assertTrue(r.eof()); } @Test - public void testReadBytesMaxLength() throws Exception { + public void testReadBytes8ChecksMaxLength() throws Exception { // {1, 2, 3} twice - setContents("05" + "00000003" + "010203" + - "05" + "00000003" + "010203"); + setContents("0A" + "03" + "010203" + "0A" + "03" + "010203"); assertArrayEquals(new byte[] {1, 2, 3}, r.readBytes(3)); assertTrue(r.hasBytes()); try { @@ -141,19 +376,22 @@ public class ReaderImplTest extends BriarTestCase { } @Test - public void testSkipBytes() throws Exception { - // {1, 2, 3} and {} - setContents("05" + "00000003" + "010203" + "05" + "00000000"); + public void testSkipBytes8() throws Exception { + byte[] longest = new byte[Byte.MAX_VALUE]; + String longHex = StringUtils.toHexString(longest); + // {1, 2, 3}, {}, and 127 zero bytes + setContents("0A" + "03" + "010203" + "0A" + "00" + + "0A" + "7F" + longHex); + r.skipBytes(Integer.MAX_VALUE); r.skipBytes(Integer.MAX_VALUE); r.skipBytes(Integer.MAX_VALUE); assertTrue(r.eof()); } @Test - public void testSkipBytesMaxLength() throws Exception { + public void testSkipBytes8ChecksMaxLength() throws Exception { // {1, 2, 3} twice - setContents("05" + "00000003" + "010203" + - "05" + "00000003" + "010203"); + setContents("0A" + "03" + "010203" + "0A" + "03" + "010203"); r.skipBytes(3); assertTrue(r.hasBytes()); try { @@ -162,12 +400,140 @@ public class ReaderImplTest extends BriarTestCase { } catch(FormatException expected) {} } + @Test + public void testReadBytes16() throws Exception { + byte[] shortest = new byte[Byte.MAX_VALUE + 1]; + String shortHex = StringUtils.toHexString(shortest); + byte[] longest = new byte[Short.MAX_VALUE]; + String longHex = StringUtils.toHexString(longest); + // 128 zero bytes and 2^15 - 1 zero bytes + setContents("0B" + "0080" + shortHex + "0B" + "7FFF" + longHex); + assertArrayEquals(shortest, r.readBytes(Integer.MAX_VALUE)); + assertArrayEquals(longest, r.readBytes(Integer.MAX_VALUE)); + assertTrue(r.eof()); + } + + @Test + public void testReadBytes16ChecksMaxLength() throws Exception { + byte[] shortest = new byte[Byte.MAX_VALUE + 1]; + String shortHex = StringUtils.toHexString(shortest); + // 128 zero bytes, twice + setContents("0B" + "0080" + shortHex + "0B" + "0080" + shortHex); + assertArrayEquals(shortest, r.readBytes(Byte.MAX_VALUE + 1)); + assertTrue(r.hasBytes()); + try { + r.readBytes(Byte.MAX_VALUE); + fail(); + } catch(FormatException expected) {} + } + + @Test + public void testSkipBytes16() throws Exception { + byte[] shortest = new byte[Byte.MAX_VALUE + 1]; + String shortHex = StringUtils.toHexString(shortest); + byte[] longest = new byte[Short.MAX_VALUE]; + String longHex = StringUtils.toHexString(longest); + // 128 zero bytes and 2^15 - 1 zero bytes + setContents("0B" + "0080" + shortHex + "0B" + "7FFF" + longHex); + r.skipBytes(Integer.MAX_VALUE); + r.skipBytes(Integer.MAX_VALUE); + assertTrue(r.eof()); + } + + @Test + public void testSkipBytes16ChecksMaxLength() throws Exception { + byte[] shortest = new byte[Byte.MAX_VALUE + 1]; + String shortHex = StringUtils.toHexString(shortest); + // 128 zero bytes, twice + setContents("0B" + "0080" + shortHex + "0B" + "0080" + shortHex); + r.skipBytes(Byte.MAX_VALUE + 1); + assertTrue(r.hasBytes()); + try { + r.skipBytes(Byte.MAX_VALUE); + fail(); + } catch(FormatException expected) {} + } + + @Test + public void testReadBytes32() throws Exception { + byte[] shortest = new byte[Short.MAX_VALUE + 1]; + String shortHex = StringUtils.toHexString(shortest); + // 2^15 zero bytes + setContents("0C" + "00008000" + shortHex); + assertArrayEquals(shortest, r.readBytes(Integer.MAX_VALUE)); + assertTrue(r.eof()); + } + + @Test + public void testReadBytes32ChecksMaxLength() throws Exception { + byte[] shortest = new byte[Short.MAX_VALUE + 1]; + String shortHex = StringUtils.toHexString(shortest); + // 2^15 zero bytes, twice + setContents("0C" + "00008000" + shortHex + + "0C" + "00008000" + shortHex); + assertArrayEquals(shortest, r.readBytes(Short.MAX_VALUE + 1)); + assertTrue(r.hasBytes()); + try { + r.readBytes(Short.MAX_VALUE); + fail(); + } catch(FormatException expected) {} + } + + @Test + public void testSkipBytes32() throws Exception { + byte[] shortest = new byte[Short.MAX_VALUE + 1]; + String shortHex = StringUtils.toHexString(shortest); + // 2^15 zero bytes, twice + setContents("0C" + "00008000" + shortHex + + "0C" + "00008000" + shortHex); + r.skipBytes(Integer.MAX_VALUE); + r.skipBytes(Integer.MAX_VALUE); + assertTrue(r.eof()); + } + + @Test + public void testSkipBytes32ChecksMaxLength() throws Exception { + byte[] shortest = new byte[Short.MAX_VALUE + 1]; + String shortHex = StringUtils.toHexString(shortest); + // 2^15 zero bytes, twice + setContents("0C" + "00008000" + shortHex + + "0C" + "00008000" + shortHex); + r.skipBytes(Short.MAX_VALUE + 1); + assertTrue(r.hasBytes()); + try { + r.skipBytes(Short.MAX_VALUE); + fail(); + } catch(FormatException expected) {} + } + + @Test + public void testBytesMustHaveMinimalLength() throws Exception { + // BYTES_16 could be encoded as BYTES_8 + byte[] longest8 = new byte[Byte.MAX_VALUE]; + String long8Hex = StringUtils.toHexString(longest8); + setContents("0A" + "7F" + long8Hex + "0B" + "007F" + long8Hex); + assertArrayEquals(longest8, r.readBytes(Integer.MAX_VALUE)); + try { + r.readBytes(Integer.MAX_VALUE); + fail(); + } catch(FormatException expected) {} + // BYTES_32 could be encoded as BYTES_16 + byte[] longest16 = new byte[Short.MAX_VALUE]; + String long16Hex = StringUtils.toHexString(longest16); + setContents("0B" + "7FFF" + long16Hex + "0C" + "00007FFF" + long16Hex); + assertArrayEquals(longest16, r.readBytes(Integer.MAX_VALUE)); + try { + r.readBytes(Integer.MAX_VALUE); + fail(); + } catch(FormatException expected) {} + } + @Test public void testReadList() throws Exception { - // A list containing 2, "foo", and 128 - setContents("06" + "02" + "0000000000000001" + - "04" + "00000003" + "666F6F" + - "02" + "0000000000000080" + "09"); + // A list containing 1, "foo", and 128 + setContents("0D" + "02" + "01" + + "07" + "03" + "666F6F" + + "03" + "0080" + "10"); r.readListStart(); assertFalse(r.hasListEnd()); assertEquals(1, r.readInteger()); @@ -182,26 +548,26 @@ public class ReaderImplTest extends BriarTestCase { @Test public void testSkipList() throws Exception { - // A list containing 2, "foo", and 128 - setContents("06" + "02" + "0000000000000001" + - "04" + "00000003" + "666F6F" + - "02" + "0000000000000080" + "09"); + // A list containing 1, "foo", and 128 + setContents("0D" + "02" + "01" + + "07" + "03" + "666F6F" + + "03" + "0080" + "10"); r.skipList(); assertTrue(r.eof()); } @Test public void testReadMap() throws Exception { - // A map containing "foo" -> 123 and {} -> null - setContents("07" + "04" + "00000003" + "666F6F" + - "02" + "000000000000007B" + "05" + "00000000" + "0A" + "09"); + // A map containing "foo" -> 123 and byte[0] -> null + setContents("0E" + "07" + "03" + "666F6F" + "02" + "7B" + + "0A" + "00" + "11" + "10"); r.readMapStart(); assertFalse(r.hasMapEnd()); assertEquals("foo", r.readString(1000)); assertFalse(r.hasMapEnd()); assertEquals(123, r.readInteger()); assertFalse(r.hasMapEnd()); - assertArrayEquals(new byte[] {}, r.readBytes(1000)); + assertArrayEquals(new byte[0], r.readBytes(1000)); assertFalse(r.hasMapEnd()); assertTrue(r.hasNull()); r.readNull(); @@ -212,9 +578,9 @@ public class ReaderImplTest extends BriarTestCase { @Test public void testSkipMap() throws Exception { - // A map containing "foo" -> 123 and {} -> null - setContents("07" + "04" + "00000003" + "666F6F" + - "02" + "000000000000007B" + "05" + "00000000" + "0A" + "09"); + // A map containing "foo" -> 123 and byte[0] -> null + setContents("0E" + "07" + "03" + "666F6F" + "02" + "7B" + + "0A" + "00" + "11" + "10"); r.skipMap(); assertTrue(r.eof()); } @@ -222,7 +588,7 @@ public class ReaderImplTest extends BriarTestCase { @Test public void testReadStruct() throws Exception { // Two empty structs with IDs 0 and 255 - setContents("0800" + "09" + "08FF" + "09"); + setContents("0F00" + "10" + "0FFF" + "10"); r.readStructStart(0); r.readStructEnd(); r.readStructStart(255); @@ -233,7 +599,7 @@ public class ReaderImplTest extends BriarTestCase { @Test public void testSkipStruct() throws Exception { // Two empty structs with IDs 0 and 255 - setContents("0800" + "09" + "08FF" + "09"); + setContents("0F00" + "10" + "0FFF" + "10"); r.skipStruct(); r.skipStruct(); assertTrue(r.eof()); @@ -242,21 +608,21 @@ public class ReaderImplTest extends BriarTestCase { @Test public void testSkipNestedStructMapAndList() throws Exception { // A struct containing a map containing two empty lists - setContents("0800" + "07" + "06" + "09" + "06" + "09" + "09" + "09"); + setContents("0F00" + "0E" + "0D" + "10" + "0D" + "10" + "10" + "10"); r.skipStruct(); assertTrue(r.eof()); } @Test public void testReadNull() throws Exception { - setContents("0A"); + setContents("11"); r.readNull(); assertTrue(r.eof()); } @Test public void testSkipNull() throws Exception { - setContents("0A"); + setContents("11"); r.skipNull(); assertTrue(r.eof()); } diff --git a/briar-tests/src/org/briarproject/serial/WriterImplTest.java b/briar-tests/src/org/briarproject/serial/WriterImplTest.java index f21da475a15697cb6b2cd879f701eebd796c7e92..6535bd2cbb83fc8001898461f88f462f60a22616 100644 --- a/briar-tests/src/org/briarproject/serial/WriterImplTest.java +++ b/briar-tests/src/org/briarproject/serial/WriterImplTest.java @@ -9,6 +9,7 @@ import java.util.List; import java.util.Map; import org.briarproject.BriarTestCase; +import org.briarproject.TestUtils; import org.briarproject.util.StringUtils; import org.junit.Before; import org.junit.Test; @@ -36,11 +37,20 @@ public class WriterImplTest extends BriarTestCase { public void testWriteInteger() throws IOException { w.writeInteger(0); w.writeInteger(-1); - w.writeInteger(Long.MIN_VALUE); + w.writeInteger(Byte.MAX_VALUE); + w.writeInteger(Byte.MIN_VALUE); + w.writeInteger(Short.MAX_VALUE); + w.writeInteger(Short.MIN_VALUE); + w.writeInteger(Integer.MAX_VALUE); + w.writeInteger(Integer.MIN_VALUE); w.writeInteger(Long.MAX_VALUE); - // INTEGER tag, 0, INTEGER tag, -1, etc - checkContents("02" + "0000000000000000" + "02" + "FFFFFFFFFFFFFFFF" - + "02" + "8000000000000000" + "02" + "7FFFFFFFFFFFFFFF"); + w.writeInteger(Long.MIN_VALUE); + // INTEGER_8 tag, 0, INTEGER_8 tag, -1, etc + checkContents("02" + "00" + "02" + "FF" + + "02" + "7F" + "02" + "80" + + "03" + "7FFF" + "03" + "8000" + + "04" + "7FFFFFFF" + "04" + "80000000" + + "05" + "7FFFFFFFFFFFFFFF" + "05" + "8000000000000000"); } @Test @@ -55,26 +65,75 @@ public class WriterImplTest extends BriarTestCase { w.writeFloat(Double.NEGATIVE_INFINITY); // 1 2047 0 -> 0xFFF00000... w.writeFloat(Double.POSITIVE_INFINITY); // 0 2047 0 -> 0x7FF00000... w.writeFloat(Double.NaN); // 0 2047 1 -> 0x7FF8000000000000 - checkContents("03" + "0000000000000000" + "03" + "3FF0000000000000" - + "03" + "4000000000000000" + "03" + "BFF0000000000000" - + "03" + "8000000000000000" + "03" + "FFF0000000000000" - + "03" + "7FF0000000000000" + "03" + "7FF8000000000000"); + checkContents("06" + "0000000000000000" + "06" + "3FF0000000000000" + + "06" + "4000000000000000" + "06" + "BFF0000000000000" + + "06" + "8000000000000000" + "06" + "FFF0000000000000" + + "06" + "7FF0000000000000" + "06" + "7FF8000000000000"); } @Test - public void testWriteString() throws IOException { + public void testWriteString8() throws IOException { + String longest = TestUtils.createRandomString(Byte.MAX_VALUE); + String longHex = StringUtils.toHexString(longest.getBytes("UTF-8")); w.writeString("foo bar baz bam "); - // STRING tag, length 16, UTF-8 bytes - checkContents("04" + "00000010" + "666F6F206261722062617A2062616D20"); + w.writeString(longest); + // STRING_8 tag, length 16, UTF-8 bytes, STRING_8 tag, length 127, + // UTF-8 bytes + checkContents("07" + "10" + "666F6F206261722062617A2062616D20" + + "07" + "7F" + longHex); + } + + @Test + public void testWriteString16() throws IOException { + String shortest = TestUtils.createRandomString(Byte.MAX_VALUE + 1); + String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8")); + String longest = TestUtils.createRandomString(Short.MAX_VALUE); + String longHex = StringUtils.toHexString(longest.getBytes("UTF-8")); + w.writeString(shortest); + w.writeString(longest); + // STRING_16 tag, length 128, UTF-8 bytes, STRING_16 tag, + // length 2^15 - 1, UTF-8 bytes + checkContents("08" + "0080" + shortHex + "08" + "7FFF" + longHex); + } + + @Test + public void testWriteString32() throws IOException { + String shortest = TestUtils.createRandomString(Short.MAX_VALUE + 1); + String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8")); + w.writeString(shortest); + // STRING_32 tag, length 2^15, UTF-8 bytes + checkContents("09" + "00008000" + shortHex); + } + + @Test + public void testWriteBytes8() throws IOException { + byte[] longest = new byte[Byte.MAX_VALUE]; + String longHex = StringUtils.toHexString(longest); + w.writeBytes(new byte[] {1, 2, 3}); + w.writeBytes(longest); + // BYTES_8 tag, length 3, bytes, BYTES_8 tag, length 127, bytes + checkContents("0A" + "03" + "010203" + "0A" + "7F" + longHex); + } + + @Test + public void testWriteBytes16() throws IOException { + byte[] shortest = new byte[Byte.MAX_VALUE + 1]; + String shortHex = StringUtils.toHexString(shortest); + byte[] longest = new byte[Short.MAX_VALUE]; + String longHex = StringUtils.toHexString(longest); + w.writeBytes(shortest); + w.writeBytes(longest); + // BYTES_16 tag, length 128, bytes, BYTES_16 tag, length 2^15 - 1, bytes + checkContents("0B" + "0080" + shortHex + "0B" + "7FFF" + longHex); } @Test - public void testWriteBytes() throws IOException { - w.writeBytes(new byte[] { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - }); - // BYTES tag, length 16, bytes - checkContents("05" + "00000010" + "000102030405060708090A0B0C0D0E0F"); + public void testWriteBytes32() throws IOException { + byte[] shortest = new byte[Short.MAX_VALUE + 1]; + String shortHex = StringUtils.toHexString(shortest); + w.writeBytes(shortest); + // BYTES_32 tag, length 2^15, bytes + checkContents("0C" + "00008000" + shortHex); } @Test @@ -83,8 +142,7 @@ public class WriterImplTest extends BriarTestCase { for(int i = 0; i < 3; i++) l.add(i); w.writeList(l); // LIST tag, elements as integers, END tag - checkContents("06" + "02" + "0000000000000000" + - "02" + "0000000000000001" + "02" + "0000000000000002" + "09"); + checkContents("0D" + "02" + "00" + "02" + "01" + "02" + "02" + "10"); } @Test @@ -95,8 +153,7 @@ public class WriterImplTest extends BriarTestCase { l.add(2); w.writeList(l); // LIST tag, 1 as integer, NULL tag, 2 as integer, END tag - checkContents("06" + "02" + "0000000000000001" + "0A" + - "02" + "0000000000000002" + "09"); + checkContents("0D" + "02" + "01" + "11" + "02" + "02" + "10"); } @Test @@ -106,11 +163,10 @@ public class WriterImplTest extends BriarTestCase { for(int i = 0; i < 4; i++) m.put(i, i + 1); w.writeMap(m); // MAP tag, entries as integers, END tag - checkContents("07" + "02" + "0000000000000000" + - "02" + "0000000000000001" + "02" + "0000000000000001" + - "02" + "0000000000000002" + "02" + "0000000000000002" + - "02" + "0000000000000003" + "02" + "0000000000000003" + - "02" + "0000000000000004" + "09"); + checkContents("0E" + "02" + "00" + "02" + "01" + + "02" + "01" + "02" + "02" + + "02" + "02" + "02" + "03" + + "02" + "03" + "02" + "04" + "10"); } @Test @@ -121,9 +177,9 @@ public class WriterImplTest extends BriarTestCase { w.writeInteger(128); w.writeListEnd(); // LIST tag, 1 as integer, "foo" as string, 128 as integer, END tag - checkContents("06" + "02" + "0000000000000001" + - "04" + "00000003" + "666F6F" + - "02" + "0000000000000080" + "09"); + checkContents("0D" + "02" + "01" + + "07" + "03" + "666F6F" + + "03" + "0080" + "10"); } @Test @@ -136,8 +192,8 @@ public class WriterImplTest extends BriarTestCase { w.writeMapEnd(); // MAP tag, "foo" as string, 123 as integer, {} as bytes, NULL tag, // END tag - checkContents("07" + "04" + "00000003" + "666F6F" + - "02" + "000000000000007B" + "05" + "00000000" + "0A" + "09"); + checkContents("0E" + "07" + "03" + "666F6F" + + "02" + "7B" + "0A" + "00" + "11" + "10"); } @Test @@ -151,9 +207,8 @@ public class WriterImplTest extends BriarTestCase { w.writeMap(m1); // MAP tag, MAP tag, "foo" as string, 123 as integer, END tag, // LIST tag, 1 as integer, END tag, END tag - checkContents("07" + "07" + "04" + "00000003" + "666F6F" + - "02" + "000000000000007B" + "09" + "06" + - "02" + "0000000000000001" + "09" + "09"); + checkContents("0E" + "0E" + "07" + "03" + "666F6F" + + "02" + "7B" + "10" + "0D" + "02" + "01" + "10" + "10"); } @Test @@ -161,13 +216,13 @@ public class WriterImplTest extends BriarTestCase { w.writeStructStart(123); w.writeStructEnd(); // STRUCT tag, 123 as struct ID, END tag - checkContents("08" + "7B" + "09"); + checkContents("0F" + "7B" + "10"); } @Test public void testWriteNull() throws IOException { w.writeNull(); - checkContents("0A"); + checkContents("11"); } private void checkContents(String hex) throws IOException {