mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Compact encodings for integers, strings and byte arrays.
This adds complexity but will save a lot of bandwidth, as most of the strings and byte arrays we want to send are less than 128 bytes. The extra complexity isn't exposed outside of the serial component.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 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 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 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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'/>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
assertArrayEquals(new byte[] {1, 2, 3}, r.readBytes(Integer.MAX_VALUE));
|
||||
assertArrayEquals(new byte[] {}, r.readBytes(Integer.MAX_VALUE));
|
||||
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 testReadBytesMaxLength() throws Exception {
|
||||
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[0], r.readBytes(Integer.MAX_VALUE));
|
||||
assertArrayEquals(longest, r.readBytes(Integer.MAX_VALUE));
|
||||
assertTrue(r.eof());
|
||||
}
|
||||
|
||||
@Test
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -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 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 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 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 {
|
||||
|
||||
Reference in New Issue
Block a user