diff --git a/test/build.xml b/test/build.xml index 62fc80685ca28919793da009f517d345b8a97277..2a0ca52a5453687ea5d2187afe1684ce55972087 100644 --- a/test/build.xml +++ b/test/build.xml @@ -45,6 +45,7 @@ <test name='net.sf.briar.protocol.RequestReaderTest'/> <test name='net.sf.briar.protocol.UnverifiedBatchImplTest'/> <test name='net.sf.briar.protocol.batch.BatchConnectionReadWriteTest'/> + <test name='net.sf.briar.protocol.batch.OutgoingBatchConnectionTest'/> <test name='net.sf.briar.serial.ReaderImplTest'/> <test name='net.sf.briar.serial.WriterImplTest'/> <test name='net.sf.briar.setup.SetupWorkerTest'/> diff --git a/test/net/sf/briar/protocol/batch/OutgoingBatchConnectionTest.java b/test/net/sf/briar/protocol/batch/OutgoingBatchConnectionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..74bbc358e97c4468a054bc4bbb7de124fda7df71 --- /dev/null +++ b/test/net/sf/briar/protocol/batch/OutgoingBatchConnectionTest.java @@ -0,0 +1,178 @@ +package net.sf.briar.protocol.batch; + +import java.io.ByteArrayOutputStream; +import java.util.Collections; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +import junit.framework.TestCase; +import net.sf.briar.TestUtils; +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.ProtocolConstants; +import net.sf.briar.api.protocol.ProtocolWriterFactory; +import net.sf.briar.api.protocol.RawBatch; +import net.sf.briar.api.protocol.TransportIndex; +import net.sf.briar.api.protocol.UniqueId; +import net.sf.briar.api.transport.ConnectionContext; +import net.sf.briar.api.transport.ConnectionWriterFactory; +import net.sf.briar.api.transport.TransportConstants; +import net.sf.briar.crypto.CryptoModule; +import net.sf.briar.protocol.ProtocolModule; +import net.sf.briar.protocol.stream.ProtocolStreamModule; +import net.sf.briar.serial.SerialModule; +import net.sf.briar.transport.TransportModule; + +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.junit.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Module; + +public class OutgoingBatchConnectionTest extends TestCase { + + private final Mockery context; + private final DatabaseComponent db; + private final ConnectionWriterFactory connFactory; + private final ProtocolWriterFactory protoFactory; + private final ContactId contactId; + private final TransportIndex transportIndex; + private final byte[] secret; + + public OutgoingBatchConnectionTest() { + super(); + context = new Mockery(); + db = context.mock(DatabaseComponent.class); + Module testModule = new AbstractModule() { + @Override + public void configure() { + bind(DatabaseComponent.class).toInstance(db); + bind(Executor.class).annotatedWith( + DatabaseExecutor.class).toInstance( + Executors.newCachedThreadPool()); + } + }; + Injector i = Guice.createInjector(testModule, new CryptoModule(), + new SerialModule(), new TransportModule(), + new ProtocolBatchModule(), new ProtocolModule(), + new ProtocolStreamModule()); + connFactory = i.getInstance(ConnectionWriterFactory.class); + protoFactory = i.getInstance(ProtocolWriterFactory.class); + contactId = new ContactId(1); + transportIndex = new TransportIndex(13); + secret = new byte[32]; + } + + @Test + public void testConnectionTooShort() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + TestBatchTransportWriter transport = new TestBatchTransportWriter(out, + ProtocolConstants.MAX_PACKET_LENGTH); + OutgoingBatchConnection connection = new OutgoingBatchConnection(db, + connFactory, protoFactory, contactId, transportIndex, + transport); + final ConnectionContext ctx = context.mock(ConnectionContext.class); + context.checking(new Expectations() {{ + oneOf(db).getConnectionContext(contactId, transportIndex); + will(returnValue(ctx)); + oneOf(ctx).getSecret(); + will(returnValue(secret)); + }}); + connection.write(); + // Nothing should have been written + assertEquals(0, out.size()); + // The transport should have been disposed with success == false + assertFalse(transport.getSuccess()); + context.assertIsSatisfied(); + } + + @Test + public void testNothingToSend() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + TestBatchTransportWriter transport = new TestBatchTransportWriter(out, + TransportConstants.MIN_CONNECTION_LENGTH); + OutgoingBatchConnection connection = new OutgoingBatchConnection(db, + connFactory, protoFactory, contactId, transportIndex, + transport); + final ConnectionContext ctx = context.mock(ConnectionContext.class); + context.checking(new Expectations() {{ + oneOf(db).getConnectionContext(contactId, transportIndex); + will(returnValue(ctx)); + oneOf(ctx).getSecret(); + will(returnValue(secret)); + // No transports to send + oneOf(db).generateTransportUpdate(contactId); + will(returnValue(null)); + // No subscriptions to send + oneOf(db).generateSubscriptionUpdate(contactId); + will(returnValue(null)); + // No acks to send + oneOf(db).generateAck(with(contactId), with(any(int.class))); + will(returnValue(null)); + // No batches to send + oneOf(db).generateBatch(with(contactId), with(any(int.class))); + will(returnValue(null)); + }}); + connection.write(); + // Nothing should have been written + assertEquals(0, out.size()); + // The transport should have been disposed with success == true + assertTrue(transport.getSuccess()); + context.assertIsSatisfied(); + } + + @Test + public void testSomethingToSend() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + TestBatchTransportWriter transport = new TestBatchTransportWriter(out, + TransportConstants.MIN_CONNECTION_LENGTH); + OutgoingBatchConnection connection = new OutgoingBatchConnection(db, + connFactory, protoFactory, contactId, transportIndex, + transport); + final ConnectionContext ctx = context.mock(ConnectionContext.class); + 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]; + context.checking(new Expectations() {{ + oneOf(db).getConnectionContext(contactId, transportIndex); + will(returnValue(ctx)); + oneOf(ctx).getSecret(); + will(returnValue(secret)); + // No transports to send + oneOf(db).generateTransportUpdate(contactId); + will(returnValue(null)); + // No subscriptions to send + oneOf(db).generateSubscriptionUpdate(contactId); + will(returnValue(null)); + // One ack to send + oneOf(db).generateAck(with(contactId), with(any(int.class))); + will(returnValue(ack)); + oneOf(ack).getBatchIds(); + will(returnValue(Collections.singletonList(batchId))); + // No more acks + oneOf(db).generateAck(with(contactId), with(any(int.class))); + will(returnValue(null)); + // One batch 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 + oneOf(db).generateBatch(with(contactId), with(any(int.class))); + will(returnValue(null)); + }}); + connection.write(); + // Something should have been written + assertTrue(out.size() > UniqueId.LENGTH + message.length); + // The transport should have been disposed with success == true + assertTrue(transport.getSuccess()); + context.assertIsSatisfied(); + } +}