Removed batches from BMP. Messages are now sent and acked individually.

This commit is contained in:
akwizgran
2013-01-16 22:56:03 +00:00
parent 13cad40004
commit 50ad1f486e
55 changed files with 574 additions and 1666 deletions

View File

@@ -12,7 +12,6 @@ import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
@@ -22,26 +21,25 @@ import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.Author;
import net.sf.briar.api.protocol.AuthorFactory;
import net.sf.briar.api.protocol.Batch;
import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.GroupFactory;
import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageFactory;
import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.api.protocol.MessageVerifier;
import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.ProtocolReader;
import net.sf.briar.api.protocol.ProtocolReaderFactory;
import net.sf.briar.api.protocol.ProtocolWriter;
import net.sf.briar.api.protocol.ProtocolWriterFactory;
import net.sf.briar.api.protocol.RawBatch;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.protocol.UnverifiedMessage;
import net.sf.briar.api.transport.ConnectionContext;
import net.sf.briar.api.transport.ConnectionReader;
import net.sf.briar.api.transport.ConnectionReaderFactory;
@@ -64,15 +62,13 @@ import com.google.inject.Injector;
public class ProtocolIntegrationTest extends BriarTestCase {
private final BatchId ack = new BatchId(TestUtils.getRandomId());
private final long timestamp = System.currentTimeMillis();
private final ConnectionReaderFactory connectionReaderFactory;
private final ConnectionWriterFactory connectionWriterFactory;
private final ProtocolReaderFactory protocolReaderFactory;
private final ProtocolWriterFactory protocolWriterFactory;
private final PacketFactory packetFactory;
private final CryptoComponent crypto;
private final MessageVerifier messageVerifier;
private final ContactId contactId;
private final TransportId transportId;
private final byte[] secret;
@@ -82,30 +78,32 @@ public class ProtocolIntegrationTest extends BriarTestCase {
private final String authorName = "Alice";
private final String subject = "Hello";
private final String messageBody = "Hello world";
private final Collection<MessageId> messageIds;
private final Collection<Transport> transports;
private final long timestamp = System.currentTimeMillis();
public ProtocolIntegrationTest() throws Exception {
super();
Injector i = Guice.createInjector(new ClockModule(), new CryptoModule(),
new DatabaseModule(), new LifecycleModule(),
new ProtocolModule(), new SerialModule(),
new TestDatabaseModule(), new SimplexProtocolModule(),
new TransportModule(), new DuplexProtocolModule());
Injector i = Guice.createInjector(new TestDatabaseModule(),
new ClockModule(), new CryptoModule(), new DatabaseModule(),
new LifecycleModule(), new ProtocolModule(),
new DuplexProtocolModule(), new SimplexProtocolModule(),
new SerialModule(), new TransportModule());
connectionReaderFactory = i.getInstance(ConnectionReaderFactory.class);
connectionWriterFactory = i.getInstance(ConnectionWriterFactory.class);
protocolReaderFactory = i.getInstance(ProtocolReaderFactory.class);
protocolWriterFactory = i.getInstance(ProtocolWriterFactory.class);
packetFactory = i.getInstance(PacketFactory.class);
crypto = i.getInstance(CryptoComponent.class);
messageVerifier = i.getInstance(MessageVerifier.class);
contactId = new ContactId(234);
transportId = new TransportId(TestUtils.getRandomId());
// Create a shared secret
Random r = new Random();
secret = new byte[32];
r.nextBytes(secret);
new Random().nextBytes(secret);
// Create two groups: one restricted, one unrestricted
GroupFactory groupFactory = i.getInstance(GroupFactory.class);
group = groupFactory.createGroup("Unrestricted group", null);
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
KeyPair groupKeyPair = crypto.generateSignatureKeyPair();
group1 = groupFactory.createGroup("Restricted group",
groupKeyPair.getPublic().getEncoded());
@@ -127,6 +125,8 @@ public class ProtocolIntegrationTest extends BriarTestCase {
message3 = messageFactory.createMessage(null, group1,
groupKeyPair.getPrivate(), author, authorKeyPair.getPrivate(),
subject, messageBody.getBytes("UTF-8"));
messageIds = Arrays.asList(message.getId(),
message1.getId(), message2.getId(), message3.getId());
// Create some transports
TransportId transportId = new TransportId(TestUtils.getRandomId());
Transport transport = new Transport(transportId,
@@ -149,18 +149,15 @@ public class ProtocolIntegrationTest extends BriarTestCase {
ProtocolWriter writer = protocolWriterFactory.createProtocolWriter(out1,
false);
Ack a = packetFactory.createAck(Collections.singletonList(ack));
Ack a = packetFactory.createAck(messageIds);
writer.writeAck(a);
Collection<byte[]> batch = Arrays.asList(message.getSerialised(),
message1.getSerialised(), message2.getSerialised(),
message3.getSerialised());
RawBatch b = packetFactory.createBatch(batch);
writer.writeBatch(b);
writer.writeMessage(message.getSerialised());
writer.writeMessage(message1.getSerialised());
writer.writeMessage(message2.getSerialised());
writer.writeMessage(message3.getSerialised());
Collection<MessageId> offer = Arrays.asList(message.getId(),
message1.getId(), message2.getId(), message3.getId());
Offer o = packetFactory.createOffer(offer);
Offer o = packetFactory.createOffer(messageIds);
writer.writeOffer(o);
BitSet requested = new BitSet(4);
@@ -200,29 +197,26 @@ public class ProtocolIntegrationTest extends BriarTestCase {
// Read the ack
assertTrue(reader.hasAck());
Ack a = reader.readAck();
assertEquals(Collections.singletonList(ack), a.getBatchIds());
assertEquals(messageIds, a.getMessageIds());
// Read and verify the batch
assertTrue(reader.hasBatch());
Batch b = reader.readBatch().verify();
Collection<Message> messages = b.getMessages();
assertEquals(4, messages.size());
Iterator<Message> it = messages.iterator();
checkMessageEquality(message, it.next());
checkMessageEquality(message1, it.next());
checkMessageEquality(message2, it.next());
checkMessageEquality(message3, it.next());
// Read and verify the messages
assertTrue(reader.hasMessage());
UnverifiedMessage m = reader.readMessage();
checkMessageEquality(message, messageVerifier.verifyMessage(m));
assertTrue(reader.hasMessage());
m = reader.readMessage();
checkMessageEquality(message1, messageVerifier.verifyMessage(m));
assertTrue(reader.hasMessage());
m = reader.readMessage();
checkMessageEquality(message2, messageVerifier.verifyMessage(m));
assertTrue(reader.hasMessage());
m = reader.readMessage();
checkMessageEquality(message3, messageVerifier.verifyMessage(m));
// Read the offer
assertTrue(reader.hasOffer());
Offer o = reader.readOffer();
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());
assertEquals(messageIds, o.getMessageIds());
// Read the request
assertTrue(reader.hasRequest());

View File

@@ -1,4 +1,4 @@
package net.sf.briar.db;
package net.sf.briar;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
@@ -8,7 +8,7 @@ import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageId;
class TestMessage implements Message {
public class TestMessage implements Message {
private final MessageId id, parent;
private final GroupId group;

View File

@@ -7,6 +7,7 @@ import java.util.Collection;
import java.util.Collections;
import net.sf.briar.BriarTestCase;
import net.sf.briar.TestMessage;
import net.sf.briar.TestUtils;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.Rating;
@@ -17,21 +18,18 @@ import net.sf.briar.api.db.NoSuchContactTransportException;
import net.sf.briar.api.db.event.ContactAddedEvent;
import net.sf.briar.api.db.event.ContactRemovedEvent;
import net.sf.briar.api.db.event.DatabaseListener;
import net.sf.briar.api.db.event.MessagesAddedEvent;
import net.sf.briar.api.db.event.MessageAddedEvent;
import net.sf.briar.api.db.event.RatingChangedEvent;
import net.sf.briar.api.db.event.SubscriptionsUpdatedEvent;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.AuthorId;
import net.sf.briar.api.protocol.Batch;
import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.RawBatch;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.Transport;
@@ -48,10 +46,9 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
protected final Object txn = new Object();
protected final AuthorId authorId;
protected final BatchId batchId;
protected final ContactId contactId;
protected final GroupId groupId;
protected final MessageId messageId, parentId;
protected final MessageId messageId, messageId1;
private final String subject;
private final long timestamp;
private final int size;
@@ -66,11 +63,10 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
public DatabaseComponentTest() {
super();
authorId = new AuthorId(TestUtils.getRandomId());
batchId = new BatchId(TestUtils.getRandomId());
contactId = new ContactId(234);
groupId = new GroupId(TestUtils.getRandomId());
messageId = new MessageId(TestUtils.getRandomId());
parentId = new MessageId(TestUtils.getRandomId());
messageId1 = new MessageId(TestUtils.getRandomId());
subject = "Foo";
timestamp = System.currentTimeMillis();
size = 1234;
@@ -250,11 +246,11 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).setSendability(txn, messageId, 1);
// The parent exists, is in the DB, and is in the same group
oneOf(database).getGroupMessageParent(txn, messageId);
will(returnValue(parentId));
will(returnValue(messageId1));
// The parent is already sendable
oneOf(database).getSendability(txn, parentId);
oneOf(database).getSendability(txn, messageId1);
will(returnValue(1));
oneOf(database).setSendability(txn, parentId, 2);
oneOf(database).setSendability(txn, messageId1, 2);
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
@@ -288,13 +284,13 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).setSendability(txn, messageId, 1);
// The parent exists, is in the DB, and is in the same group
oneOf(database).getGroupMessageParent(txn, messageId);
will(returnValue(parentId));
will(returnValue(messageId1));
// The parent is not already sendable
oneOf(database).getSendability(txn, parentId);
oneOf(database).getSendability(txn, messageId1);
will(returnValue(0));
oneOf(database).setSendability(txn, parentId, 1);
oneOf(database).setSendability(txn, messageId1, 1);
// The parent has no parent
oneOf(database).getGroupMessageParent(txn, parentId);
oneOf(database).getGroupMessageParent(txn, messageId1);
will(returnValue(null));
oneOf(database).commitTransaction(txn);
}});
@@ -494,7 +490,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final Ack ack = context.mock(Ack.class);
final Batch batch = context.mock(Batch.class);
final Offer offer = context.mock(Offer.class);
final SubscriptionUpdate subscriptionUpdate =
context.mock(SubscriptionUpdate.class);
@@ -563,7 +558,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
} catch(NoSuchContactException expected) {}
try {
db.receiveBatch(contactId, batch);
db.receiveMessage(contactId, message);
fail();
} catch(NoSuchContactException expected) {}
@@ -631,10 +626,8 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
@Test
public void testGenerateAck() throws Exception {
final BatchId batchId1 = new BatchId(TestUtils.getRandomId());
final Collection<BatchId> batchesToAck = new ArrayList<BatchId>();
batchesToAck.add(batchId);
batchesToAck.add(batchId1);
final Collection<MessageId> messagesToAck = Arrays.asList(messageId,
messageId1);
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
@@ -648,14 +641,14 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
allowing(database).commitTransaction(txn);
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
// Get the batches to ack
oneOf(database).getBatchesToAck(txn, contactId, 123);
will(returnValue(batchesToAck));
// Create the packet
oneOf(packetFactory).createAck(batchesToAck);
// Get the messages to ack
oneOf(database).getMessagesToAck(txn, contactId, 123);
will(returnValue(messagesToAck));
// Create the ack packet
oneOf(packetFactory).createAck(messagesToAck);
will(returnValue(ack));
// Record the batches that were acked
oneOf(database).removeBatchesToAck(txn, contactId, batchesToAck);
// Record the messages that were acked
oneOf(database).removeMessagesToAck(txn, contactId, messagesToAck);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
@@ -667,7 +660,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
@Test
public void testGenerateBatch() throws Exception {
final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
final byte[] raw1 = new byte[size];
final Collection<MessageId> sendable = Arrays.asList(messageId,
messageId1);
@@ -678,7 +670,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final RawBatch batch = context.mock(RawBatch.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -692,40 +683,32 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
will(returnValue(raw));
oneOf(database).getMessage(txn, messageId1);
will(returnValue(raw1));
// Create the packet
oneOf(packetFactory).createBatch(messages);
will(returnValue(batch));
// Record the outstanding batch
oneOf(batch).getId();
will(returnValue(batchId));
oneOf(database).addOutstandingBatch(txn, contactId, batchId,
sendable);
// Record the outstanding messages
oneOf(database).addOutstandingMessages(txn, contactId, sendable);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
assertEquals(batch, db.generateBatch(contactId, size * 2));
assertEquals(messages, db.generateBatch(contactId, size * 2));
context.assertIsSatisfied();
}
@Test
public void testGenerateBatchFromRequest() throws Exception {
final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
final MessageId messageId2 = new MessageId(TestUtils.getRandomId());
final byte[] raw1 = new byte[size];
final Collection<MessageId> requested = new ArrayList<MessageId>();
requested.add(messageId);
requested.add(messageId1);
requested.add(messageId2);
final Collection<byte[]> msgs = Arrays.asList(raw1);
final Collection<byte[]> messages = Arrays.asList(raw1);
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final RawBatch batch = context.mock(RawBatch.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -739,19 +722,15 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
will(returnValue(raw1)); // Message is sendable
oneOf(database).getMessageIfSendable(txn, contactId, messageId2);
will(returnValue(null)); // Message is not sendable
// Create the packet
oneOf(packetFactory).createBatch(msgs);
will(returnValue(batch));
// Record the outstanding batch
oneOf(batch).getId();
will(returnValue(batchId));
oneOf(database).addOutstandingBatch(txn, contactId, batchId,
// Record the outstanding messages
oneOf(database).addOutstandingMessages(txn, contactId,
Collections.singletonList(messageId1));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
assertEquals(batch, db.generateBatch(contactId, size * 3, requested));
assertEquals(messages, db.generateBatch(contactId, size * 3,
requested));
context.assertIsSatisfied();
}
@@ -903,7 +882,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
@Test
public void testReceiveAck() throws Exception {
final BatchId batchId1 = new BatchId(TestUtils.getRandomId());
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
@@ -917,14 +895,14 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
allowing(database).commitTransaction(txn);
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
// Get the acked batches
oneOf(ack).getBatchIds();
will(returnValue(Collections.singletonList(batchId)));
oneOf(database).removeAckedBatch(txn, contactId, batchId);
// Find lost batches
oneOf(database).getLostBatches(txn, contactId);
will(returnValue(Collections.singletonList(batchId1)));
oneOf(database).removeLostBatch(txn, contactId, batchId1);
// Get the acked messages
oneOf(ack).getMessageIds();
will(returnValue(Collections.singletonList(messageId)));
oneOf(database).removeAckedMessages(txn, contactId,
Collections.singletonList(messageId));
// Find lost messages
oneOf(database).getLostMessages(txn, contactId);
will(returnValue(Collections.emptyList()));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
@@ -935,74 +913,64 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
}
@Test
public void testReceiveBatchStoresPrivateMessage() throws Exception {
public void testReceivePrivateMessage() throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final Batch batch = context.mock(Batch.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
allowing(database).commitTransaction(txn);
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
oneOf(batch).getMessages();
will(returnValue(Collections.singletonList(privateMessage)));
// The message is stored
oneOf(database).addPrivateMessage(txn, privateMessage, contactId);
will(returnValue(true));
oneOf(database).setStatus(txn, contactId, messageId, Status.SEEN);
// The batch must be acked
oneOf(batch).getId();
will(returnValue(batchId));
oneOf(database).addBatchToAck(txn, contactId, batchId);
// The message must be acked
oneOf(database).addMessageToAck(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
db.receiveBatch(contactId, batch);
db.receiveMessage(contactId, privateMessage);
context.assertIsSatisfied();
}
@Test
public void testReceiveBatchWithDuplicatePrivateMessage() throws Exception {
public void testReceiveDuplicatePrivateMessage() throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final Batch batch = context.mock(Batch.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
allowing(database).commitTransaction(txn);
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
oneOf(batch).getMessages();
will(returnValue(Collections.singletonList(privateMessage)));
// The message is stored, but it's a duplicate
oneOf(database).addPrivateMessage(txn, privateMessage, contactId);
will(returnValue(false));
// The batch must still be acked
oneOf(batch).getId();
will(returnValue(batchId));
oneOf(database).addBatchToAck(txn, contactId, batchId);
// The message must still be acked
oneOf(database).addMessageToAck(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
db.receiveBatch(contactId, batch);
db.receiveMessage(contactId, privateMessage);
context.assertIsSatisfied();
}
@Test
public void testReceiveBatchDoesNotStoreGroupMessageUnlessSubscribed()
public void testReceiveMessageDoesNotStoreGroupMessageUnlessSubscribed()
throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
@@ -1010,7 +978,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final Batch batch = context.mock(Batch.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -1018,26 +985,22 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
// Only store messages belonging to visible, subscribed groups
oneOf(batch).getMessages();
will(returnValue(Collections.singletonList(message)));
oneOf(database).containsVisibleSubscription(txn, groupId,
contactId, timestamp);
will(returnValue(false));
// The message is not stored but the batch must still be acked
oneOf(batch).getId();
will(returnValue(batchId));
oneOf(database).addBatchToAck(txn, contactId, batchId);
// The message is not stored but it must still be acked
oneOf(database).addMessageToAck(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
db.receiveBatch(contactId, batch);
db.receiveMessage(contactId, message);
context.assertIsSatisfied();
}
@Test
public void testReceiveBatchDoesNotCalculateSendabilityForDuplicates()
public void testReceiveMessageDoesNotCalculateSendabilityForDuplicates()
throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
@@ -1045,7 +1008,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final Batch batch = context.mock(Batch.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -1053,8 +1015,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
// Only store messages belonging to visible, subscribed groups
oneOf(batch).getMessages();
will(returnValue(Collections.singletonList(message)));
oneOf(database).containsVisibleSubscription(txn, groupId,
contactId, timestamp);
will(returnValue(true));
@@ -1062,28 +1022,25 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).addGroupMessage(txn, message);
will(returnValue(false));
oneOf(database).setStatus(txn, contactId, messageId, Status.SEEN);
// The batch needs to be acknowledged
oneOf(batch).getId();
will(returnValue(batchId));
oneOf(database).addBatchToAck(txn, contactId, batchId);
// The message must be acked
oneOf(database).addMessageToAck(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
db.receiveBatch(contactId, batch);
db.receiveMessage(contactId, message);
context.assertIsSatisfied();
}
@Test
public void testReceiveBatchCalculatesSendability() throws Exception {
public void testReceiveMessageCalculatesSendability() throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final Batch batch = context.mock(Batch.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -1091,8 +1048,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
// Only store messages belonging to visible, subscribed groups
oneOf(batch).getMessages();
will(returnValue(Collections.singletonList(message)));
oneOf(database).containsVisibleSubscription(txn, groupId,
contactId, timestamp);
will(returnValue(true));
@@ -1109,28 +1064,26 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).getNumberOfSendableChildren(txn, messageId);
will(returnValue(0));
oneOf(database).setSendability(txn, messageId, 0);
// The batch needs to be acknowledged
oneOf(batch).getId();
will(returnValue(batchId));
oneOf(database).addBatchToAck(txn, contactId, batchId);
// The message must be acked
oneOf(database).addMessageToAck(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
db.receiveBatch(contactId, batch);
db.receiveMessage(contactId, message);
context.assertIsSatisfied();
}
@Test
public void testReceiveBatchUpdatesAncestorSendability() throws Exception {
public void testReceiveMessageUpdatesAncestorSendability()
throws Exception {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final Batch batch = context.mock(Batch.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -1138,8 +1091,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
// Only store messages belonging to visible, subscribed groups
oneOf(batch).getMessages();
will(returnValue(Collections.singletonList(message)));
oneOf(database).containsVisibleSubscription(txn, groupId,
contactId, timestamp);
will(returnValue(true));
@@ -1158,15 +1109,13 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).setSendability(txn, messageId, 2);
oneOf(database).getGroupMessageParent(txn, messageId);
will(returnValue(null));
// The batch needs to be acknowledged
oneOf(batch).getId();
will(returnValue(batchId));
oneOf(database).addBatchToAck(txn, contactId, batchId);
// The message must be acked
oneOf(database).addMessageToAck(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
db.receiveBatch(contactId, batch);
db.receiveMessage(contactId, message);
context.assertIsSatisfied();
}
@@ -1319,7 +1268,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).setSendability(txn, messageId, 0);
oneOf(database).commitTransaction(txn);
// The message was added, so the listener should be called
oneOf(listener).eventOccurred(with(any(MessagesAddedEvent.class)));
oneOf(listener).eventOccurred(with(any(MessageAddedEvent.class)));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
@@ -1350,7 +1299,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
will(returnValue(true));
oneOf(database).setStatus(txn, contactId, messageId, Status.NEW);
// The message was added, so the listener should be called
oneOf(listener).eventOccurred(with(any(MessagesAddedEvent.class)));
oneOf(listener).eventOccurred(with(any(MessageAddedEvent.class)));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);

View File

@@ -1,7 +1,6 @@
package net.sf.briar.db;
import static java.util.concurrent.TimeUnit.SECONDS;
import static net.sf.briar.db.DatabaseConstants.RETRANSMIT_THRESHOLD;
import static org.junit.Assert.assertArrayEquals;
import java.io.File;
@@ -20,6 +19,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import net.sf.briar.BriarTestCase;
import net.sf.briar.TestDatabaseConfig;
import net.sf.briar.TestMessage;
import net.sf.briar.TestUtils;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.Rating;
@@ -29,7 +29,6 @@ import net.sf.briar.api.clock.SystemClock;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.db.MessageHeader;
import net.sf.briar.api.protocol.AuthorId;
import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message;
@@ -53,10 +52,9 @@ public class H2DatabaseTest extends BriarTestCase {
private final Random random = new Random();
private final Group group;
private final AuthorId authorId;
private final BatchId batchId;
private final ContactId contactId;
private final GroupId groupId;
private final MessageId messageId, privateMessageId;
private final MessageId messageId, messageId1;
private final String subject;
private final long timestamp;
private final int size;
@@ -67,11 +65,10 @@ public class H2DatabaseTest extends BriarTestCase {
public H2DatabaseTest() throws Exception {
super();
authorId = new AuthorId(TestUtils.getRandomId());
batchId = new BatchId(TestUtils.getRandomId());
contactId = new ContactId(1);
groupId = new GroupId(TestUtils.getRandomId());
messageId = new MessageId(TestUtils.getRandomId());
privateMessageId = new MessageId(TestUtils.getRandomId());
messageId1 = new MessageId(TestUtils.getRandomId());
group = new Group(groupId, "Foo", null);
subject = "Foo";
timestamp = System.currentTimeMillis();
@@ -80,7 +77,7 @@ public class H2DatabaseTest extends BriarTestCase {
random.nextBytes(raw);
message = new TestMessage(messageId, null, groupId, authorId, subject,
timestamp, raw);
privateMessage = new TestMessage(privateMessageId, null, null, null,
privateMessage = new TestMessage(messageId1, null, null, null,
subject, timestamp, raw);
transportId = new TransportId(TestUtils.getRandomId());
}
@@ -104,9 +101,9 @@ public class H2DatabaseTest extends BriarTestCase {
assertFalse(db.containsMessage(txn, messageId));
db.addGroupMessage(txn, message);
assertTrue(db.containsMessage(txn, messageId));
assertFalse(db.containsMessage(txn, privateMessageId));
assertFalse(db.containsMessage(txn, messageId1));
db.addPrivateMessage(txn, privateMessage, contactId);
assertTrue(db.containsMessage(txn, privateMessageId));
assertTrue(db.containsMessage(txn, messageId1));
db.commitTransaction(txn);
db.close();
@@ -118,12 +115,12 @@ public class H2DatabaseTest extends BriarTestCase {
assertTrue(db.containsMessage(txn, messageId));
byte[] raw1 = db.getMessage(txn, messageId);
assertArrayEquals(raw, raw1);
assertTrue(db.containsMessage(txn, privateMessageId));
raw1 = db.getMessage(txn, privateMessageId);
assertTrue(db.containsMessage(txn, messageId1));
raw1 = db.getMessage(txn, messageId1);
assertArrayEquals(raw, raw1);
// Delete the records
db.removeMessage(txn, messageId);
db.removeMessage(txn, privateMessageId);
db.removeMessage(txn, messageId1);
db.removeContact(txn, contactId);
db.removeSubscription(txn, groupId);
db.commitTransaction(txn);
@@ -137,7 +134,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.getRemoteProperties(txn, transportId));
assertFalse(db.containsSubscription(txn, groupId));
assertFalse(db.containsMessage(txn, messageId));
assertFalse(db.containsMessage(txn, privateMessageId));
assertFalse(db.containsMessage(txn, messageId1));
db.commitTransaction(txn);
db.close();
}
@@ -216,9 +213,9 @@ public class H2DatabaseTest extends BriarTestCase {
db.addPrivateMessage(txn, privateMessage, contactId);
// Removing the contact should remove the message
assertTrue(db.containsMessage(txn, privateMessageId));
assertTrue(db.containsMessage(txn, messageId1));
db.removeContact(txn, contactId);
assertFalse(db.containsMessage(txn, privateMessageId));
assertFalse(db.containsMessage(txn, messageId1));
db.commitTransaction(txn);
db.close();
@@ -241,21 +238,21 @@ public class H2DatabaseTest extends BriarTestCase {
assertFalse(it.hasNext());
// Changing the status to NEW should make the message sendable
db.setStatus(txn, contactId, privateMessageId, Status.NEW);
db.setStatus(txn, contactId, messageId1, Status.NEW);
assertTrue(db.hasSendableMessages(txn, contactId));
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
assertTrue(it.hasNext());
assertEquals(privateMessageId, it.next());
assertEquals(messageId1, it.next());
assertFalse(it.hasNext());
// Changing the status to SENT should make the message unsendable
db.setStatus(txn, contactId, privateMessageId, Status.SENT);
db.setStatus(txn, contactId, messageId1, Status.SENT);
assertFalse(db.hasSendableMessages(txn, contactId));
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
assertFalse(it.hasNext());
// Changing the status to SEEN should also make the message unsendable
db.setStatus(txn, contactId, privateMessageId, Status.SEEN);
db.setStatus(txn, contactId, messageId1, Status.SEEN);
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
assertFalse(it.hasNext());
@@ -272,7 +269,7 @@ public class H2DatabaseTest extends BriarTestCase {
// Add a contact and store a private message
assertEquals(contactId, db.addContact(txn));
db.addPrivateMessage(txn, privateMessage, contactId);
db.setStatus(txn, contactId, privateMessageId, Status.NEW);
db.setStatus(txn, contactId, messageId1, Status.NEW);
// The message is sendable, but too large to send
assertTrue(db.hasSendableMessages(txn, contactId));
@@ -284,7 +281,7 @@ public class H2DatabaseTest extends BriarTestCase {
assertTrue(db.hasSendableMessages(txn, contactId));
it = db.getSendableMessages(txn, contactId, size).iterator();
assertTrue(it.hasNext());
assertEquals(privateMessageId, it.next());
assertEquals(messageId1, it.next());
assertFalse(it.hasNext());
db.commitTransaction(txn);
@@ -508,109 +505,58 @@ public class H2DatabaseTest extends BriarTestCase {
}
@Test
public void testBatchesToAck() throws Exception {
BatchId batchId1 = new BatchId(TestUtils.getRandomId());
public void testMessagesToAck() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a contact and some batches to ack
// Add a contact and some messages to ack
assertEquals(contactId, db.addContact(txn));
db.addBatchToAck(txn, contactId, batchId);
db.addBatchToAck(txn, contactId, batchId1);
db.addMessageToAck(txn, contactId, messageId);
db.addMessageToAck(txn, contactId, messageId1);
// Both batch IDs should be returned
Collection<BatchId> acks = db.getBatchesToAck(txn, contactId, 1234);
assertEquals(2, acks.size());
assertTrue(acks.contains(batchId));
assertTrue(acks.contains(batchId1));
// Both message IDs should be returned
Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
assertEquals(ids, db.getMessagesToAck(txn, contactId, 1234));
// Remove the batch IDs
db.removeBatchesToAck(txn, contactId, acks);
// Remove both message IDs
db.removeMessagesToAck(txn, contactId, ids);
// Both batch IDs should have been removed
acks = db.getBatchesToAck(txn, contactId, 1234);
assertEquals(0, acks.size());
// Both message IDs should have been removed
assertEquals(Collections.emptyList(), db.getMessagesToAck(txn,
contactId, 1234));
db.commitTransaction(txn);
db.close();
}
@Test
public void testDuplicateBatchesReceived() throws Exception {
public void testDuplicateMessageReceived() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a contact and receive the same batch twice
// Add a contact and receive the same message twice
assertEquals(contactId, db.addContact(txn));
db.addBatchToAck(txn, contactId, batchId);
db.addBatchToAck(txn, contactId, batchId);
db.addMessageToAck(txn, contactId, messageId);
db.addMessageToAck(txn, contactId, messageId);
// The batch ID should only be returned once
Collection<BatchId> acks = db.getBatchesToAck(txn, contactId, 1234);
assertEquals(1, acks.size());
assertTrue(acks.contains(batchId));
// The message ID should only be returned once
Collection<MessageId> ids = db.getMessagesToAck(txn, contactId, 1234);
assertEquals(Collections.singletonList(messageId), ids);
// Remove the batch ID
db.removeBatchesToAck(txn, contactId, acks);
// Remove the message ID
db.removeMessagesToAck(txn, contactId,
Collections.singletonList(messageId));
// The batch ID should have been removed
acks = db.getBatchesToAck(txn, contactId, 1234);
assertEquals(0, acks.size());
// The message ID should have been removed
assertEquals(Collections.emptyList(), db.getMessagesToAck(txn,
contactId, 1234));
db.commitTransaction(txn);
db.close();
}
@Test
public void testSameBatchCannotBeSentTwice() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a contact, subscribe to a group and store a message
assertEquals(contactId, db.addContact(txn));
db.addSubscription(txn, group);
db.addGroupMessage(txn, message);
// Add an outstanding batch
db.addOutstandingBatch(txn, contactId, batchId,
Collections.singletonList(messageId));
// It should not be possible to add the same outstanding batch again
try {
db.addOutstandingBatch(txn, contactId, batchId,
Collections.singletonList(messageId));
fail();
} catch(DbException expected) {}
db.abortTransaction(txn);
db.close();
}
@Test
public void testSameBatchCanBeSentToDifferentContacts() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add two contacts, subscribe to a group and store a message
assertEquals(contactId, db.addContact(txn));
ContactId contactId1 = db.addContact(txn);
db.addSubscription(txn, group);
db.addGroupMessage(txn, message);
// Add an outstanding batch for the first contact
db.addOutstandingBatch(txn, contactId, batchId,
Collections.singletonList(messageId));
// Add the same outstanding batch for the second contact
db.addOutstandingBatch(txn, contactId1, batchId,
Collections.singletonList(messageId));
db.commitTransaction(txn);
db.close();
}
@Test
public void testRemoveAckedBatch() throws Exception {
public void testRemoveAckedMessage() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
@@ -630,15 +576,16 @@ public class H2DatabaseTest extends BriarTestCase {
assertEquals(messageId, it.next());
assertFalse(it.hasNext());
db.setStatus(txn, contactId, messageId, Status.SENT);
db.addOutstandingBatch(txn, contactId, batchId,
db.addOutstandingMessages(txn, contactId,
Collections.singletonList(messageId));
// The message should no longer be sendable
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
assertFalse(it.hasNext());
// Pretend that the batch was acked
db.removeAckedBatch(txn, contactId, batchId);
// Pretend that the message was acked
db.removeAckedMessages(txn, contactId,
Collections.singletonList(messageId));
// The message still should not be sendable
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
@@ -649,7 +596,7 @@ public class H2DatabaseTest extends BriarTestCase {
}
@Test
public void testRemoveLostBatch() throws Exception {
public void testRemoveLostMessage() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
@@ -669,15 +616,16 @@ public class H2DatabaseTest extends BriarTestCase {
assertEquals(messageId, it.next());
assertFalse(it.hasNext());
db.setStatus(txn, contactId, messageId, Status.SENT);
db.addOutstandingBatch(txn, contactId, batchId,
db.addOutstandingMessages(txn, contactId,
Collections.singletonList(messageId));
// The message should no longer be sendable
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
assertFalse(it.hasNext());
// Pretend that the batch was lost
db.removeLostBatch(txn, contactId, batchId);
// Pretend that the message was lost
db.removeLostMessages(txn, contactId,
Collections.singletonList(messageId));
// The message should be sendable again
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
@@ -689,77 +637,6 @@ public class H2DatabaseTest extends BriarTestCase {
db.close();
}
@Test
public void testRetransmission() throws Exception {
BatchId[] ids = new BatchId[RETRANSMIT_THRESHOLD + 5];
for(int i = 0; i < ids.length; i++) {
ids[i] = new BatchId(TestUtils.getRandomId());
}
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a contact
assertEquals(contactId, db.addContact(txn));
// Add some outstanding batches, a few ms apart
for(int i = 0; i < ids.length; i++) {
db.addOutstandingBatch(txn, contactId, ids[i],
Collections.<MessageId>emptyList());
Thread.sleep(5);
}
// The contact acks the batches in reverse order. The first
// RETRANSMIT_THRESHOLD - 1 acks should not trigger any retransmissions
for(int i = 0; i < RETRANSMIT_THRESHOLD - 1; i++) {
db.removeAckedBatch(txn, contactId, ids[ids.length - i - 1]);
Collection<BatchId> lost = db.getLostBatches(txn, contactId);
assertEquals(Collections.emptyList(), lost);
}
// The next ack should trigger the retransmission of the remaining
// five outstanding batches
int index = ids.length - RETRANSMIT_THRESHOLD;
db.removeAckedBatch(txn, contactId, ids[index]);
Collection<BatchId> lost = db.getLostBatches(txn, contactId);
for(int i = 0; i < index; i++) {
assertTrue(lost.contains(ids[i]));
}
db.commitTransaction(txn);
db.close();
}
@Test
public void testNoRetransmission() throws Exception {
BatchId[] ids = new BatchId[RETRANSMIT_THRESHOLD * 2];
for(int i = 0; i < ids.length; i++) {
ids[i] = new BatchId(TestUtils.getRandomId());
}
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a contact
assertEquals(contactId, db.addContact(txn));
// Add some outstanding batches, a few ms apart
for(int i = 0; i < ids.length; i++) {
db.addOutstandingBatch(txn, contactId, ids[i],
Collections.<MessageId>emptyList());
Thread.sleep(5);
}
// The contact acks the batches in the order they were sent - nothing
// should be retransmitted
for(int i = 0; i < ids.length; i++) {
db.removeAckedBatch(txn, contactId, ids[i]);
Collection<BatchId> lost = db.getLostBatches(txn, contactId);
assertEquals(Collections.emptyList(), lost);
}
db.commitTransaction(txn);
db.close();
}
@Test
public void testGetMessagesByAuthor() throws Exception {
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
@@ -1426,12 +1303,12 @@ public class H2DatabaseTest extends BriarTestCase {
// A message with a private parent should return null
MessageId childId = new MessageId(TestUtils.getRandomId());
Message child = new TestMessage(childId, privateMessageId, groupId,
Message child = new TestMessage(childId, messageId1, groupId,
null, subject, timestamp, raw);
db.addGroupMessage(txn, child);
db.addPrivateMessage(txn, privateMessage, contactId);
assertTrue(db.containsMessage(txn, childId));
assertTrue(db.containsMessage(txn, privateMessageId));
assertTrue(db.containsMessage(txn, messageId1));
assertNull(db.getGroupMessageParent(txn, childId));
db.commitTransaction(txn);
@@ -1477,7 +1354,7 @@ public class H2DatabaseTest extends BriarTestCase {
int bodyLength = raw.length - 20;
Message message1 = new TestMessage(messageId, null, groupId, null,
subject, timestamp, raw, 5, bodyLength);
Message privateMessage1 = new TestMessage(privateMessageId, null, null,
Message privateMessage1 = new TestMessage(messageId1, null, null,
null, subject, timestamp, raw, 10, bodyLength);
db.addGroupMessage(txn, message1);
db.addPrivateMessage(txn, privateMessage1, contactId);
@@ -1492,12 +1369,12 @@ public class H2DatabaseTest extends BriarTestCase {
// Retrieve the raw messages
assertArrayEquals(raw, db.getMessage(txn, messageId));
assertArrayEquals(raw, db.getMessage(txn, privateMessageId));
assertArrayEquals(raw, db.getMessage(txn, messageId1));
// Retrieve the message bodies
byte[] body = db.getMessageBody(txn, messageId);
assertArrayEquals(expectedBody, body);
byte[] body1 = db.getMessageBody(txn, privateMessageId);
byte[] body1 = db.getMessageBody(txn, messageId1);
assertArrayEquals(expectedBody1, body1);
db.commitTransaction(txn);

View File

@@ -1,137 +0,0 @@
package net.sf.briar.protocol;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import net.sf.briar.BriarTestCase;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.protocol.Types;
import net.sf.briar.api.protocol.UnverifiedBatch;
import net.sf.briar.api.serial.Reader;
import net.sf.briar.api.serial.ReaderFactory;
import net.sf.briar.api.serial.StructReader;
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 BatchReaderTest extends BriarTestCase {
// FIXME: This is an integration test, not a unit test
private final ReaderFactory readerFactory;
private final WriterFactory writerFactory;
private final Mockery context;
private final UnverifiedMessage message;
private final StructReader<UnverifiedMessage> messageReader;
public BatchReaderTest() throws Exception {
super();
Injector i = Guice.createInjector(new SerialModule());
readerFactory = i.getInstance(ReaderFactory.class);
writerFactory = i.getInstance(WriterFactory.class);
context = new Mockery();
message = context.mock(UnverifiedMessage.class);
messageReader = new TestMessageReader();
}
@Test
public void testFormatExceptionIfBatchIsTooLarge() throws Exception {
UnverifiedBatchFactory batchFactory =
context.mock(UnverifiedBatchFactory.class);
BatchReader batchReader = new BatchReader(messageReader, batchFactory);
byte[] b = createBatch(MAX_PACKET_LENGTH + 1);
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addStructReader(Types.BATCH, batchReader);
try {
reader.readStruct(Types.BATCH, UnverifiedBatch.class);
fail();
} catch(FormatException expected) {}
context.assertIsSatisfied();
}
@Test
public void testNoFormatExceptionIfBatchIsMaximumSize() throws Exception {
final UnverifiedBatchFactory batchFactory =
context.mock(UnverifiedBatchFactory.class);
BatchReader batchReader = new BatchReader(messageReader, batchFactory);
final UnverifiedBatch batch = context.mock(UnverifiedBatch.class);
context.checking(new Expectations() {{
oneOf(batchFactory).createUnverifiedBatch(
Collections.singletonList(message));
will(returnValue(batch));
}});
byte[] b = createBatch(MAX_PACKET_LENGTH);
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addStructReader(Types.BATCH, batchReader);
assertEquals(batch, reader.readStruct(Types.BATCH,
UnverifiedBatch.class));
context.assertIsSatisfied();
}
@Test
public void testEmptyBatch() throws Exception {
final UnverifiedBatchFactory batchFactory =
context.mock(UnverifiedBatchFactory.class);
BatchReader batchReader = new BatchReader(messageReader, batchFactory);
byte[] b = createEmptyBatch();
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addStructReader(Types.BATCH, batchReader);
try {
reader.readStruct(Types.BATCH, UnverifiedBatch.class);
fail();
} catch(FormatException expected) {}
context.assertIsSatisfied();
}
private byte[] createBatch(int size) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream(size);
Writer w = writerFactory.createWriter(out);
w.writeStructId(Types.BATCH);
w.writeListStart();
// We're using a fake message reader, so it's OK to use a fake message
w.writeStructId(Types.MESSAGE);
w.writeBytes(new byte[size - 10]);
w.writeListEnd();
byte[] b = out.toByteArray();
assertEquals(size, b.length);
return b;
}
private byte[] createEmptyBatch() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer w = writerFactory.createWriter(out);
w.writeStructId(Types.BATCH);
w.writeListStart();
w.writeListEnd();
return out.toByteArray();
}
private class TestMessageReader implements StructReader<UnverifiedMessage> {
public UnverifiedMessage readStruct(Reader r) throws IOException {
r.readStructId(Types.MESSAGE);
r.readBytes();
return message;
}
}
}

View File

@@ -14,7 +14,6 @@ import java.io.ByteArrayOutputStream;
import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import net.sf.briar.BriarTestCase;
@@ -23,7 +22,6 @@ import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.Author;
import net.sf.briar.api.protocol.AuthorFactory;
import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.GroupFactory;
import net.sf.briar.api.protocol.Message;
@@ -33,7 +31,6 @@ import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.ProtocolWriter;
import net.sf.briar.api.protocol.ProtocolWriterFactory;
import net.sf.briar.api.protocol.RawBatch;
import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportUpdate;
@@ -69,24 +66,24 @@ public class ConstantsTest extends BriarTestCase {
}
@Test
public void testBatchesFitIntoLargeAck() throws Exception {
testBatchesFitIntoAck(MAX_PACKET_LENGTH);
public void testMessageIdsFitIntoLargeAck() throws Exception {
testMessageIdsFitIntoAck(MAX_PACKET_LENGTH);
}
@Test
public void testBatchesFitIntoSmallAck() throws Exception {
testBatchesFitIntoAck(1000);
public void testMessageIdsFitIntoSmallAck() throws Exception {
testMessageIdsFitIntoAck(1000);
}
private void testBatchesFitIntoAck(int length) throws Exception {
// Create an ack with as many batch IDs as possible
private void testMessageIdsFitIntoAck(int length) throws Exception {
// Create an ack with as many message IDs as possible
ByteArrayOutputStream out = new ByteArrayOutputStream(length);
ProtocolWriter writer = protocolWriterFactory.createProtocolWriter(out,
true);
int maxBatches = writer.getMaxBatchesForAck(length);
Collection<BatchId> acked = new ArrayList<BatchId>();
for(int i = 0; i < maxBatches; i++) {
acked.add(new BatchId(TestUtils.getRandomId()));
int maxMessages = writer.getMaxMessagesForAck(length);
Collection<MessageId> acked = new ArrayList<MessageId>();
for(int i = 0; i < maxMessages; i++) {
acked.add(new MessageId(TestUtils.getRandomId()));
}
Ack a = packetFactory.createAck(acked);
writer.writeAck(a);
@@ -95,7 +92,7 @@ public class ConstantsTest extends BriarTestCase {
}
@Test
public void testMessageFitsIntoBatch() throws Exception {
public void testMessageFitsIntoPacket() throws Exception {
// Create a maximum-length group
String groupName = createRandomString(MAX_GROUP_NAME_LENGTH);
byte[] groupPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
@@ -111,32 +108,25 @@ public class ConstantsTest extends BriarTestCase {
byte[] body = new byte[MAX_BODY_LENGTH];
Message message = messageFactory.createMessage(null, group,
groupPrivate, author, authorPrivate, subject, body);
// Add the message to a batch
ByteArrayOutputStream out =
new ByteArrayOutputStream(MAX_PACKET_LENGTH);
ProtocolWriter writer = protocolWriterFactory.createProtocolWriter(out,
true);
RawBatch b = packetFactory.createBatch(Collections.singletonList(
message.getSerialised()));
writer.writeBatch(b);
// Check the size of the serialised batch
assertTrue(out.size() > UniqueId.LENGTH + MAX_GROUP_NAME_LENGTH
// Check the size of the serialised message
int length = message.getSerialised().length;
assertTrue(length > UniqueId.LENGTH + MAX_GROUP_NAME_LENGTH
+ MAX_PUBLIC_KEY_LENGTH + MAX_AUTHOR_NAME_LENGTH
+ MAX_PUBLIC_KEY_LENGTH + MAX_BODY_LENGTH);
assertTrue(out.size() <= MAX_PACKET_LENGTH);
assertTrue(length <= MAX_PACKET_LENGTH);
}
@Test
public void testMessagesFitIntoLargeOffer() throws Exception {
testMessagesFitIntoOffer(MAX_PACKET_LENGTH);
public void testMessageIdsFitIntoLargeOffer() throws Exception {
testMessageIdsFitIntoOffer(MAX_PACKET_LENGTH);
}
@Test
public void testMessagesFitIntoSmallOffer() throws Exception {
testMessagesFitIntoOffer(1000);
public void testMessageIdsFitIntoSmallOffer() throws Exception {
testMessageIdsFitIntoOffer(1000);
}
private void testMessagesFitIntoOffer(int length) throws Exception {
private void testMessageIdsFitIntoOffer(int length) throws Exception {
// Create an offer with as many message IDs as possible
ByteArrayOutputStream out = new ByteArrayOutputStream(length);
ProtocolWriter writer = protocolWriterFactory.createProtocolWriter(out,
@@ -170,7 +160,7 @@ public class ConstantsTest extends BriarTestCase {
}
// Add the transports to an update
ByteArrayOutputStream out =
new ByteArrayOutputStream(MAX_PACKET_LENGTH);
new ByteArrayOutputStream(MAX_PACKET_LENGTH);
ProtocolWriter writer = protocolWriterFactory.createProtocolWriter(out,
true);
TransportUpdate t = packetFactory.createTransportUpdate(transports,

View File

@@ -1,134 +0,0 @@
package net.sf.briar.protocol;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import net.sf.briar.BriarTestCase;
import net.sf.briar.TestUtils;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.Batch;
import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.GroupFactory;
import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageFactory;
import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.ProtocolReader;
import net.sf.briar.api.protocol.ProtocolReaderFactory;
import net.sf.briar.api.protocol.ProtocolWriter;
import net.sf.briar.api.protocol.ProtocolWriterFactory;
import net.sf.briar.api.protocol.RawBatch;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.clock.ClockModule;
import net.sf.briar.crypto.CryptoModule;
import net.sf.briar.serial.SerialModule;
import org.junit.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class ProtocolIntegrationTest extends BriarTestCase {
private final ProtocolReaderFactory readerFactory;
private final ProtocolWriterFactory writerFactory;
private final PacketFactory packetFactory;
private final BatchId batchId;
private final Group group;
private final Message message;
private final String subject = "Hello";
private final String messageBody = "Hello world";
private final BitSet bitSet;
private final Map<Group, Long> subscriptions;
private final Collection<Transport> transports;
private final long timestamp = System.currentTimeMillis();
public ProtocolIntegrationTest() throws Exception {
super();
Injector i = Guice.createInjector(new ClockModule(), new CryptoModule(),
new ProtocolModule(), new SerialModule());
readerFactory = i.getInstance(ProtocolReaderFactory.class);
writerFactory = i.getInstance(ProtocolWriterFactory.class);
packetFactory = i.getInstance(PacketFactory.class);
batchId = new BatchId(TestUtils.getRandomId());
GroupFactory groupFactory = i.getInstance(GroupFactory.class);
group = groupFactory.createGroup("Unrestricted group", null);
MessageFactory messageFactory = i.getInstance(MessageFactory.class);
message = messageFactory.createMessage(null, group, subject,
messageBody.getBytes("UTF-8"));
bitSet = new BitSet();
bitSet.set(3);
bitSet.set(7);
subscriptions = Collections.singletonMap(group, 123L);
TransportId transportId = new TransportId(TestUtils.getRandomId());
Transport transport = new Transport(transportId,
Collections.singletonMap("bar", "baz"));
transports = Collections.singletonList(transport);
}
@Test
public void testWriteAndRead() throws Exception {
// Write
ByteArrayOutputStream out = new ByteArrayOutputStream();
ProtocolWriter writer = writerFactory.createProtocolWriter(out, true);
Ack a = packetFactory.createAck(Collections.singletonList(batchId));
writer.writeAck(a);
RawBatch b = packetFactory.createBatch(Collections.singletonList(
message.getSerialised()));
writer.writeBatch(b);
Offer o = packetFactory.createOffer(Collections.singletonList(
message.getId()));
writer.writeOffer(o);
Request r = packetFactory.createRequest(bitSet, 10);
writer.writeRequest(r);
SubscriptionUpdate s = packetFactory.createSubscriptionUpdate(
Collections.<GroupId, GroupId>emptyMap(), subscriptions, 0L,
timestamp);
writer.writeSubscriptionUpdate(s);
TransportUpdate t = packetFactory.createTransportUpdate(transports,
timestamp);
writer.writeTransportUpdate(t);
// Read
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
ProtocolReader reader = readerFactory.createProtocolReader(in);
a = reader.readAck();
assertEquals(Collections.singletonList(batchId), a.getBatchIds());
Batch b1 = reader.readBatch().verify();
assertEquals(Collections.singletonList(message), b1.getMessages());
o = reader.readOffer();
assertEquals(Collections.singletonList(message.getId()),
o.getMessageIds());
r = reader.readRequest();
assertEquals(bitSet, r.getBitmap());
assertEquals(10, r.getLength());
s = reader.readSubscriptionUpdate();
assertEquals(subscriptions, s.getSubscriptions());
assertEquals(timestamp, s.getTimestamp());
t = reader.readTransportUpdate();
assertEquals(transports, t.getTransports());
assertEquals(timestamp, t.getTimestamp());
}
}

View File

@@ -1,242 +0,0 @@
package net.sf.briar.protocol;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.Signature;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Random;
import net.sf.briar.BriarTestCase;
import net.sf.briar.TestUtils;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.MessageDigest;
import net.sf.briar.api.protocol.Author;
import net.sf.briar.api.protocol.AuthorId;
import net.sf.briar.api.protocol.Batch;
import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.api.protocol.UnverifiedBatch;
import net.sf.briar.crypto.CryptoModule;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class UnverifiedBatchImplTest extends BriarTestCase {
// FIXME: This is an integration test, not a unit test
private final CryptoComponent crypto;
private final byte[] raw, raw1;
private final String subject;
private final long timestamp;
public UnverifiedBatchImplTest() {
super();
Injector i = Guice.createInjector(new CryptoModule());
crypto = i.getInstance(CryptoComponent.class);
Random r = new Random();
raw = new byte[123];
r.nextBytes(raw);
raw1 = new byte[1234];
r.nextBytes(raw1);
subject = "Unit tests are exciting";
timestamp = System.currentTimeMillis();
}
@Test
public void testIds() throws Exception {
// Calculate the expected batch and message IDs
MessageDigest messageDigest = crypto.getMessageDigest();
messageDigest.update(raw);
messageDigest.update(raw1);
BatchId batchId = new BatchId(messageDigest.digest());
messageDigest.update(raw);
MessageId messageId = new MessageId(messageDigest.digest());
messageDigest.update(raw1);
MessageId messageId1 = new MessageId(messageDigest.digest());
// Verify the batch
Mockery context = new Mockery();
final UnverifiedMessage message =
context.mock(UnverifiedMessage.class, "message");
final UnverifiedMessage message1 =
context.mock(UnverifiedMessage.class, "message1");
context.checking(new Expectations() {{
// First message
oneOf(message).getRaw();
will(returnValue(raw));
oneOf(message).getAuthor();
will(returnValue(null));
oneOf(message).getGroup();
will(returnValue(null));
oneOf(message).getParent();
will(returnValue(null));
oneOf(message).getSubject();
will(returnValue(subject));
oneOf(message).getTimestamp();
will(returnValue(timestamp));
oneOf(message).getBodyStart();
will(returnValue(10));
oneOf(message).getBodyLength();
will(returnValue(100));
// Second message
oneOf(message1).getRaw();
will(returnValue(raw1));
oneOf(message1).getAuthor();
will(returnValue(null));
oneOf(message1).getGroup();
will(returnValue(null));
oneOf(message1).getParent();
will(returnValue(null));
oneOf(message1).getSubject();
will(returnValue(subject));
oneOf(message1).getTimestamp();
will(returnValue(timestamp));
oneOf(message1).getBodyStart();
will(returnValue(10));
oneOf(message1).getBodyLength();
will(returnValue(1000));
}});
Collection<UnverifiedMessage> messages = Arrays.asList(message,
message1);
UnverifiedBatch batch = new UnverifiedBatchImpl(crypto, messages);
Batch verifiedBatch = batch.verify();
// Check that the batch and message IDs match
assertEquals(batchId, verifiedBatch.getId());
Collection<Message> verifiedMessages = verifiedBatch.getMessages();
assertEquals(2, verifiedMessages.size());
Iterator<Message> it = verifiedMessages.iterator();
Message verifiedMessage = it.next();
assertEquals(messageId, verifiedMessage.getId());
Message verifiedMessage1 = it.next();
assertEquals(messageId1, verifiedMessage1.getId());
context.assertIsSatisfied();
}
@Test
public void testSignatures() throws Exception {
final int signedByAuthor = 100, signedByGroup = 110;
final KeyPair authorKeyPair = crypto.generateSignatureKeyPair();
final KeyPair groupKeyPair = crypto.generateSignatureKeyPair();
GroupId groupId = new GroupId(TestUtils.getRandomId());
final Group group = new Group(groupId, "Group name",
groupKeyPair.getPublic().getEncoded());
Signature signature = crypto.getSignature();
// Calculate the expected author and group signatures
signature.initSign(authorKeyPair.getPrivate());
signature.update(raw, 0, signedByAuthor);
final byte[] authorSignature = signature.sign();
signature.initSign(groupKeyPair.getPrivate());
signature.update(raw, 0, signedByGroup);
final byte[] groupSignature = signature.sign();
// Verify the batch
Mockery context = new Mockery();
final UnverifiedMessage message =
context.mock(UnverifiedMessage.class, "message");
final Author author = context.mock(Author.class);
final UnverifiedMessage message1 =
context.mock(UnverifiedMessage.class, "message1");
context.checking(new Expectations() {{
// First message
oneOf(message).getRaw();
will(returnValue(raw));
oneOf(message).getAuthor();
will(returnValue(author));
oneOf(author).getPublicKey();
will(returnValue(authorKeyPair.getPublic().getEncoded()));
oneOf(message).getLengthSignedByAuthor();
will(returnValue(signedByAuthor));
oneOf(message).getAuthorSignature();
will(returnValue(authorSignature));
oneOf(message).getGroup();
will(returnValue(group));
oneOf(message).getLengthSignedByGroup();
will(returnValue(signedByGroup));
oneOf(message).getGroupSignature();
will(returnValue(groupSignature));
oneOf(author).getId();
will(returnValue(new AuthorId(TestUtils.getRandomId())));
oneOf(message).getParent();
will(returnValue(null));
oneOf(message).getSubject();
will(returnValue(subject));
oneOf(message).getTimestamp();
will(returnValue(timestamp));
oneOf(message).getBodyStart();
will(returnValue(10));
oneOf(message).getBodyLength();
will(returnValue(100));
// Second message
oneOf(message1).getRaw();
will(returnValue(raw1));
oneOf(message1).getAuthor();
will(returnValue(null));
oneOf(message1).getGroup();
will(returnValue(null));
oneOf(message1).getParent();
will(returnValue(null));
oneOf(message1).getSubject();
will(returnValue(subject));
oneOf(message1).getTimestamp();
will(returnValue(timestamp));
oneOf(message1).getBodyStart();
will(returnValue(10));
oneOf(message1).getBodyLength();
will(returnValue(1000));
}});
Collection<UnverifiedMessage> messages = Arrays.asList(message,
message1);
UnverifiedBatch batch = new UnverifiedBatchImpl(crypto, messages);
batch.verify();
context.assertIsSatisfied();
}
@Test
public void testExceptionThrownIfMessageIsModified() throws Exception {
final int signedByAuthor = 100;
final KeyPair authorKeyPair = crypto.generateSignatureKeyPair();
Signature signature = crypto.getSignature();
// Calculate the expected author signature
signature.initSign(authorKeyPair.getPrivate());
signature.update(raw, 0, signedByAuthor);
final byte[] authorSignature = signature.sign();
// Modify the message
raw[signedByAuthor / 2] ^= 0xff;
// Verify the batch
Mockery context = new Mockery();
final UnverifiedMessage message =
context.mock(UnverifiedMessage.class, "message");
final Author author = context.mock(Author.class);
final UnverifiedMessage message1 =
context.mock(UnverifiedMessage.class, "message1");
context.checking(new Expectations() {{
// First message - verification will fail at the author's signature
oneOf(message).getRaw();
will(returnValue(raw));
oneOf(message).getAuthor();
will(returnValue(author));
oneOf(author).getPublicKey();
will(returnValue(authorKeyPair.getPublic().getEncoded()));
oneOf(message).getLengthSignedByAuthor();
will(returnValue(signedByAuthor));
oneOf(message).getAuthorSignature();
will(returnValue(authorSignature));
}});
Collection<UnverifiedMessage> messages = Arrays.asList(message,
message1);
UnverifiedBatch batch = new UnverifiedBatchImpl(crypto, messages);
try {
batch.verify();
fail();
} catch(GeneralSecurityException expected) {}
context.assertIsSatisfied();
}
}

View File

@@ -17,9 +17,8 @@ import net.sf.briar.api.ContactId;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DatabaseExecutor;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.api.protocol.ProtocolWriterFactory;
import net.sf.briar.api.protocol.RawBatch;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.UniqueId;
import net.sf.briar.api.transport.ConnectionContext;
@@ -51,6 +50,7 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
private final ConnectionWriterFactory connFactory;
private final ProtocolWriterFactory protoFactory;
private final ContactId contactId;
private final MessageId messageId;
private final TransportId transportId;
private final byte[] secret;
@@ -75,6 +75,7 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
connFactory = i.getInstance(ConnectionWriterFactory.class);
protoFactory = i.getInstance(ProtocolWriterFactory.class);
contactId = new ContactId(234);
messageId = new MessageId(TestUtils.getRandomId());
transportId = new TransportId(TestUtils.getRandomId());
secret = new byte[32];
}
@@ -115,7 +116,7 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
// No acks to send
oneOf(db).generateAck(with(contactId), with(any(int.class)));
will(returnValue(null));
// No batches to send
// No messages to send
oneOf(db).generateBatch(with(contactId), with(any(int.class)));
will(returnValue(null));
}});
@@ -138,9 +139,7 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
OutgoingSimplexConnection connection = new OutgoingSimplexConnection(db,
connRegistry, connFactory, protoFactory, ctx, transport);
final Ack ack = context.mock(Ack.class);
final BatchId batchId = new BatchId(TestUtils.getRandomId());
final RawBatch batch = context.mock(RawBatch.class);
final byte[] message = new byte[1234];
final byte[] raw = new byte[1234];
context.checking(new Expectations() {{
// No transports to send
oneOf(db).generateTransportUpdate(contactId);
@@ -151,24 +150,22 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
// One ack to send
oneOf(db).generateAck(with(contactId), with(any(int.class)));
will(returnValue(ack));
oneOf(ack).getBatchIds();
will(returnValue(Collections.singletonList(batchId)));
oneOf(ack).getMessageIds();
will(returnValue(Collections.singletonList(messageId)));
// No more acks
oneOf(db).generateAck(with(contactId), with(any(int.class)));
will(returnValue(null));
// One batch to send
// One message to send
oneOf(db).generateBatch(with(contactId), with(any(int.class)));
will(returnValue(batch));
oneOf(batch).getMessages();
will(returnValue(Collections.singletonList(message)));
// No more batches
will(returnValue(Collections.singletonList(raw)));
// No more messages
oneOf(db).generateBatch(with(contactId), with(any(int.class)));
will(returnValue(null));
}});
connection.write();
// Something should have been written
int overhead = TAG_LENGTH + HEADER_LENGTH + MAC_LENGTH;
assertTrue(out.size() > overhead + UniqueId.LENGTH + message.length);
assertTrue(out.size() > overhead + UniqueId.LENGTH + raw.length);
// The transport should have been disposed with exception == false
assertTrue(transport.getDisposed());
assertFalse(transport.getException());

View File

@@ -17,9 +17,10 @@ import net.sf.briar.api.crypto.KeyManager;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.event.DatabaseEvent;
import net.sf.briar.api.db.event.DatabaseListener;
import net.sf.briar.api.db.event.MessagesAddedEvent;
import net.sf.briar.api.db.event.MessageAddedEvent;
import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageFactory;
import net.sf.briar.api.protocol.MessageVerifier;
import net.sf.briar.api.protocol.ProtocolReaderFactory;
import net.sf.briar.api.protocol.ProtocolWriterFactory;
import net.sf.briar.api.protocol.Transport;
@@ -181,6 +182,8 @@ public class SimplexProtocolIntegrationTest extends BriarTestCase {
ConnectionContext ctx = rec.acceptConnection(transportId, tag);
assertNotNull(ctx);
// Create an incoming simplex connection
MessageVerifier messageVerifier =
bob.getInstance(MessageVerifier.class);
ConnectionRegistry connRegistry =
bob.getInstance(ConnectionRegistry.class);
ConnectionReaderFactory connFactory =
@@ -190,8 +193,9 @@ public class SimplexProtocolIntegrationTest extends BriarTestCase {
TestSimplexTransportReader transport =
new TestSimplexTransportReader(in);
IncomingSimplexConnection simplex = new IncomingSimplexConnection(
new ImmediateExecutor(), new ImmediateExecutor(), db,
connRegistry, connFactory, protoFactory, ctx, transport);
new ImmediateExecutor(), new ImmediateExecutor(),
messageVerifier, db, connRegistry, connFactory, protoFactory,
ctx, transport);
// No messages should have been added yet
assertFalse(listener.messagesAdded);
// Read whatever needs to be read
@@ -216,8 +220,7 @@ public class SimplexProtocolIntegrationTest extends BriarTestCase {
private boolean messagesAdded = false;
public void eventOccurred(DatabaseEvent e) {
if(e instanceof MessagesAddedEvent)
messagesAdded = true;
if(e instanceof MessageAddedEvent) messagesAdded = true;
}
}
}

View File

@@ -8,7 +8,6 @@ import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
public class ConnectionWriterImplTest extends BriarTestCase {
private static final int FRAME_LENGTH = 1024;

View File

@@ -18,19 +18,12 @@ import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.ErasableKey;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.transport.ConnectionContext;
import net.sf.briar.api.transport.ConnectionReader;
import net.sf.briar.api.transport.ConnectionWriter;
import net.sf.briar.api.transport.ConnectionWriterFactory;
import net.sf.briar.crypto.CryptoModule;
import net.sf.briar.transport.ConnectionReaderImpl;
import net.sf.briar.transport.ConnectionWriterFactoryImpl;
import net.sf.briar.transport.ConnectionWriterImpl;
import net.sf.briar.transport.IncomingEncryptionLayer;
import net.sf.briar.transport.OutgoingEncryptionLayer;
import org.junit.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
@@ -93,7 +86,7 @@ public class TransportIntegrationTest extends BriarTestCase {
ByteArrayOutputStream out = new ByteArrayOutputStream();
FrameWriter encryptionOut = new OutgoingEncryptionLayer(out,
Long.MAX_VALUE, frameCipher, frameCopy, FRAME_LENGTH);
ConnectionWriter writer = new ConnectionWriterImpl(encryptionOut,
ConnectionWriterImpl writer = new ConnectionWriterImpl(encryptionOut,
FRAME_LENGTH);
OutputStream out1 = writer.getOutputStream();
out1.write(frame);
@@ -106,7 +99,7 @@ public class TransportIntegrationTest extends BriarTestCase {
ByteArrayInputStream in = new ByteArrayInputStream(output);
FrameReader encryptionIn = new IncomingEncryptionLayer(in, frameCipher,
frameKey, FRAME_LENGTH);
ConnectionReader reader = new ConnectionReaderImpl(encryptionIn,
ConnectionReaderImpl reader = new ConnectionReaderImpl(encryptionIn,
FRAME_LENGTH);
InputStream in1 = reader.getInputStream();
byte[] recovered = new byte[frame.length];