Request reader and unit test.

This commit is contained in:
akwizgran
2011-07-27 11:06:54 +01:00
parent 0933092295
commit b161e5ed1d
20 changed files with 305 additions and 48 deletions

View File

@@ -752,7 +752,7 @@ public abstract class DatabaseComponentTest extends TestCase {
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
// Get the acked batches
oneOf(ack).getBatches();
oneOf(ack).getBatchIds();
will(returnValue(Collections.singletonList(batchId)));
oneOf(database).removeAckedBatch(txn, contactId, batchId);
}});
@@ -940,7 +940,7 @@ public abstract class DatabaseComponentTest extends TestCase {
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
// Get the offered messages
oneOf(offer).getMessages();
oneOf(offer).getMessageIds();
will(returnValue(offered));
oneOf(database).setStatusSeenIfVisible(txn, contactId, messageId);
will(returnValue(false)); // Not visible - request message # 0

View File

@@ -97,7 +97,7 @@ public class AckReaderTest extends TestCase {
}
private byte[] createAck(boolean tooBig) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream(Ack.MAX_SIZE);
ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer w = writerFactory.createWriter(out);
w.writeUserDefinedTag(Tags.ACK);
w.writeListStart();

View File

@@ -6,6 +6,7 @@ import java.io.FileOutputStream;
import java.security.KeyPair;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
@@ -24,6 +25,7 @@ import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageEncoder;
import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.Subscriptions;
import net.sf.briar.api.protocol.Tags;
import net.sf.briar.api.protocol.Transports;
@@ -32,6 +34,7 @@ import net.sf.briar.api.protocol.writers.AckWriter;
import net.sf.briar.api.protocol.writers.BatchWriter;
import net.sf.briar.api.protocol.writers.OfferWriter;
import net.sf.briar.api.protocol.writers.PacketWriterFactory;
import net.sf.briar.api.protocol.writers.RequestWriter;
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
import net.sf.briar.api.protocol.writers.TransportWriter;
import net.sf.briar.api.serial.Reader;
@@ -61,6 +64,7 @@ public class FileReadWriteTest extends TestCase {
private final AckReader ackReader;
private final BatchReader batchReader;
private final OfferReader offerReader;
private final RequestReader requestReader;
private final SubscriptionReader subscriptionReader;
private final TransportReader transportReader;
private final Author author;
@@ -82,6 +86,7 @@ public class FileReadWriteTest extends TestCase {
ackReader = i.getInstance(AckReader.class);
batchReader = i.getInstance(BatchReader.class);
offerReader = i.getInstance(OfferReader.class);
requestReader = i.getInstance(RequestReader.class);
subscriptionReader = i.getInstance(SubscriptionReader.class);
transportReader = i.getInstance(TransportReader.class);
// Create two groups: one restricted, one unrestricted
@@ -135,6 +140,12 @@ public class FileReadWriteTest extends TestCase {
assertTrue(o.writeMessageId(message3.getId()));
o.finish();
RequestWriter r = packetWriterFactory.createRequestWriter(out);
BitSet requested = new BitSet(4);
requested.set(1);
requested.set(3);
r.writeBitmap(requested, 4);
SubscriptionWriter s =
packetWriterFactory.createSubscriptionWriter(out);
Collection<Group> subs = new ArrayList<Group>();
@@ -160,35 +171,47 @@ public class FileReadWriteTest extends TestCase {
reader.addObjectReader(Tags.ACK, ackReader);
reader.addObjectReader(Tags.BATCH, batchReader);
reader.addObjectReader(Tags.OFFER, offerReader);
reader.addObjectReader(Tags.REQUEST, requestReader);
reader.addObjectReader(Tags.SUBSCRIPTIONS, subscriptionReader);
reader.addObjectReader(Tags.TRANSPORTS, transportReader);
// Read the ack
assertTrue(reader.hasUserDefined(Tags.ACK));
Ack a = reader.readUserDefined(Tags.ACK, Ack.class);
assertEquals(Collections.singletonList(ack), a.getBatches());
assertEquals(Collections.singletonList(ack), a.getBatchIds());
// Read the batch
assertTrue(reader.hasUserDefined(Tags.BATCH));
Batch b = reader.readUserDefined(Tags.BATCH, Batch.class);
Collection<Message> messages = b.getMessages();
assertEquals(4, messages.size());
Iterator<Message> i = messages.iterator();
checkMessageEquality(message, i.next());
checkMessageEquality(message1, i.next());
checkMessageEquality(message2, i.next());
checkMessageEquality(message3, i.next());
Iterator<Message> it = messages.iterator();
checkMessageEquality(message, it.next());
checkMessageEquality(message1, it.next());
checkMessageEquality(message2, it.next());
checkMessageEquality(message3, it.next());
// Read the offer
assertTrue(reader.hasUserDefined(Tags.OFFER));
Offer o = reader.readUserDefined(Tags.OFFER, Offer.class);
Collection<MessageId> ids = o.getMessages();
assertEquals(4, ids.size());
Iterator<MessageId> i1 = ids.iterator();
assertEquals(message.getId(), i1.next());
assertEquals(message1.getId(), i1.next());
assertEquals(message2.getId(), i1.next());
assertEquals(message3.getId(), i1.next());
Collection<MessageId> offered = o.getMessageIds();
assertEquals(4, offered.size());
Iterator<MessageId> it1 = offered.iterator();
assertEquals(message.getId(), it1.next());
assertEquals(message1.getId(), it1.next());
assertEquals(message2.getId(), it1.next());
assertEquals(message3.getId(), it1.next());
// Read the request
assertTrue(reader.hasUserDefined(Tags.REQUEST));
Request r = reader.readUserDefined(Tags.REQUEST, Request.class);
BitSet requested = r.getBitmap();
assertFalse(requested.get(0));
assertTrue(requested.get(1));
assertFalse(requested.get(2));
assertTrue(requested.get(3));
// If there are any padding bits, they should all be zero
for(int i = 4; i < requested.size(); i++) assertFalse(requested.get(i));
// Read the subscriptions update
assertTrue(reader.hasUserDefined(Tags.SUBSCRIPTIONS));
@@ -196,9 +219,9 @@ public class FileReadWriteTest extends TestCase {
Subscriptions.class);
Collection<Group> subs = s.getSubscriptions();
assertEquals(2, subs.size());
Iterator<Group> i2 = subs.iterator();
checkGroupEquality(group, i2.next());
checkGroupEquality(group1, i2.next());
Iterator<Group> it2 = subs.iterator();
checkGroupEquality(group, it2.next());
checkGroupEquality(group1, it2.next());
assertTrue(s.getTimestamp() > start);
assertTrue(s.getTimestamp() <= System.currentTimeMillis());

View File

@@ -0,0 +1,133 @@
package net.sf.briar.protocol;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.BitSet;
import junit.framework.TestCase;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.Tags;
import net.sf.briar.api.serial.FormatException;
import net.sf.briar.api.serial.Reader;
import net.sf.briar.api.serial.ReaderFactory;
import net.sf.briar.api.serial.Writer;
import net.sf.briar.api.serial.WriterFactory;
import net.sf.briar.serial.SerialModule;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class RequestReaderTest extends TestCase {
private final ReaderFactory readerFactory;
private final WriterFactory writerFactory;
private final Mockery context;
public RequestReaderTest() throws Exception {
super();
Injector i = Guice.createInjector(new SerialModule());
readerFactory = i.getInstance(ReaderFactory.class);
writerFactory = i.getInstance(WriterFactory.class);
context = new Mockery();
}
@Test
public void testFormatExceptionIfRequestIsTooLarge() throws Exception {
RequestFactory requestFactory = context.mock(RequestFactory.class);
RequestReader requestReader = new RequestReader(requestFactory);
byte[] b = createRequest(true);
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addObjectReader(Tags.REQUEST, requestReader);
try {
reader.readUserDefined(Tags.REQUEST, Request.class);
assertTrue(false);
} catch(FormatException expected) {}
context.assertIsSatisfied();
}
@Test
public void testNoFormatExceptionIfRequestIsMaximumSize() throws Exception {
final RequestFactory requestFactory =
context.mock(RequestFactory.class);
RequestReader requestReader = new RequestReader(requestFactory);
final Request request = context.mock(Request.class);
context.checking(new Expectations() {{
oneOf(requestFactory).createRequest(with(any(BitSet.class)));
will(returnValue(request));
}});
byte[] b = createRequest(false);
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addObjectReader(Tags.REQUEST, requestReader);
assertEquals(request, reader.readUserDefined(Tags.REQUEST,
Request.class));
context.assertIsSatisfied();
}
@Test
public void testBitmapDecoding() throws Exception {
// Test sizes from 0 to 1000 bits
for(int i = 0; i < 1000; i++) {
// Create a BitSet of size i with one in ten bits set (on average)
BitSet requested = new BitSet(i);
for(int j = 0; j < i; j++) if(Math.random() < 0.1) requested.set(j);
// Encode the BitSet as a bitmap
int bytes = i % 8 == 0 ? i / 8 : i / 8 + 1;
byte[] bitmap = new byte[bytes];
for(int j = 0; j < i; j++) {
if(requested.get(j)) {
int offset = j / 8;
byte bit = (byte) (128 >> j % 8);
bitmap[offset] |= bit;
}
}
// Create a serialised request containing the bitmap
byte[] b = createRequest(bitmap);
// Deserialise the request
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
RequestReader requestReader =
new RequestReader(new RequestFactoryImpl());
reader.addObjectReader(Tags.REQUEST, requestReader);
Request r = reader.readUserDefined(Tags.REQUEST, Request.class);
BitSet decoded = r.getBitmap();
// Check that the decoded BitSet matches the original - we can't
// use equals() because of padding, but the first i bits should
// match and the cardinalities should be equal, indicating that no
// padding bits are set
for(int j = 0; j < i; j++) {
assertEquals(requested.get(j), decoded.get(j));
}
assertEquals(requested.cardinality(), decoded.cardinality());
}
}
private byte[] createRequest(boolean tooBig) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer w = writerFactory.createWriter(out);
w.writeUserDefinedTag(Tags.REQUEST);
// Allow one byte for the REQUEST tag, one byte for the BYTES tag, and
// five bytes for the length as an int32
if(tooBig) w.writeBytes(new byte[Request.MAX_SIZE - 6]);
else w.writeBytes(new byte[Request.MAX_SIZE - 7]);
assertEquals(tooBig, out.size() > Request.MAX_SIZE);
return out.toByteArray();
}
private byte[] createRequest(byte[] bitmap) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer w = writerFactory.createWriter(out);
w.writeUserDefinedTag(Tags.REQUEST);
w.writeBytes(bitmap);
return out.toByteArray();
}
}