Files
briar/test/net/sf/briar/protocol/simplex/SimplexConnectionReadWriteTest.java

205 lines
7.3 KiB
Java

package net.sf.briar.protocol.simplex;
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.Random;
import net.sf.briar.BriarTestCase;
import net.sf.briar.TestDatabaseModule;
import net.sf.briar.TestUtils;
import net.sf.briar.api.ContactId;
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.protocol.Message;
import net.sf.briar.api.protocol.MessageFactory;
import net.sf.briar.api.protocol.ProtocolReaderFactory;
import net.sf.briar.api.protocol.ProtocolWriterFactory;
import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportIndex;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.transport.ConnectionContext;
import net.sf.briar.api.transport.ConnectionReaderFactory;
import net.sf.briar.api.transport.ConnectionRecogniser;
import net.sf.briar.api.transport.ConnectionRegistry;
import net.sf.briar.api.transport.ConnectionWriterFactory;
import net.sf.briar.crypto.CryptoModule;
import net.sf.briar.db.DatabaseModule;
import net.sf.briar.lifecycle.LifecycleModule;
import net.sf.briar.plugins.ImmediateExecutor;
import net.sf.briar.protocol.ProtocolModule;
import net.sf.briar.protocol.duplex.DuplexProtocolModule;
import net.sf.briar.serial.SerialModule;
import net.sf.briar.transport.TransportModule;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class SimplexConnectionReadWriteTest extends BriarTestCase {
private final File testDir = TestUtils.getTestDirectory();
private final File aliceDir = new File(testDir, "alice");
private final File bobDir = new File(testDir, "bob");
private final TransportId transportId;
private final TransportIndex transportIndex;
private final byte[] aliceToBobSecret, bobToAliceSecret;
private Injector alice, bob;
public SimplexConnectionReadWriteTest() throws Exception {
super();
transportId = new TransportId(TestUtils.getRandomId());
transportIndex = new TransportIndex(1);
// Create matching secrets for Alice and Bob
Random r = new Random();
aliceToBobSecret = new byte[32];
r.nextBytes(aliceToBobSecret);
bobToAliceSecret = new byte[32];
r.nextBytes(bobToAliceSecret);
}
@Before
public void setUp() {
testDir.mkdirs();
alice = createInjector(aliceDir);
bob = createInjector(bobDir);
}
private Injector createInjector(File dir) {
return Guice.createInjector(new CryptoModule(), new DatabaseModule(),
new LifecycleModule(), new ProtocolModule(), new SerialModule(),
new TestDatabaseModule(dir), new SimplexProtocolModule(),
new TransportModule(), new DuplexProtocolModule());
}
@Test
public void testInjection() {
DatabaseComponent aliceDb = alice.getInstance(DatabaseComponent.class);
DatabaseComponent bobDb = bob.getInstance(DatabaseComponent.class);
assertFalse(aliceDb == bobDb);
}
@Test
public void testWriteAndRead() throws Exception {
read(write());
}
private byte[] write() throws Exception {
// Open Alice's database
DatabaseComponent db = alice.getInstance(DatabaseComponent.class);
db.open(false);
// Add Bob as a contact and send him a message
ContactId contactId = db.addContact(bobToAliceSecret, aliceToBobSecret);
String subject = "Hello";
byte[] body = "Hi Bob!".getBytes("UTF-8");
MessageFactory messageFactory = alice.getInstance(MessageFactory.class);
Message message = messageFactory.createMessage(null, subject, body);
db.addLocalPrivateMessage(message, contactId);
// Create an outgoing batch connection
ByteArrayOutputStream out = new ByteArrayOutputStream();
ConnectionRegistry connRegistry =
alice.getInstance(ConnectionRegistry.class);
ConnectionWriterFactory connFactory =
alice.getInstance(ConnectionWriterFactory.class);
ProtocolWriterFactory protoFactory =
alice.getInstance(ProtocolWriterFactory.class);
TestSimplexTransportWriter transport = new TestSimplexTransportWriter(
out, Long.MAX_VALUE, false);
OutgoingSimplexConnection simplex = new OutgoingSimplexConnection(db,
connRegistry, connFactory, protoFactory, contactId, transportId,
transportIndex, transport);
// Write whatever needs to be written
simplex.write();
assertTrue(transport.getDisposed());
assertFalse(transport.getException());
// Close Alice's database
db.close();
// Return the contents of the batch connection
return out.toByteArray();
}
private void read(byte[] b) throws Exception {
// Open Bob's database
DatabaseComponent db = bob.getInstance(DatabaseComponent.class);
db.open(false);
// Set up a database listener
MessageListener listener = new MessageListener();
db.addListener(listener);
// Add Alice as a contact
ContactId contactId = db.addContact(aliceToBobSecret, bobToAliceSecret);
// Add the transport
assertEquals(transportIndex, db.addTransport(transportId));
// Fake a transport update from Alice
TransportUpdate transportUpdate = new TransportUpdate() {
public Collection<Transport> getTransports() {
Transport t = new Transport(transportId, transportIndex);
return Collections.singletonList(t);
}
public long getTimestamp() {
return System.currentTimeMillis();
}
};
db.receiveTransportUpdate(contactId, transportUpdate);
// Create a connection recogniser and recognise the connection
ByteArrayInputStream in = new ByteArrayInputStream(b);
ConnectionRecogniser rec = bob.getInstance(ConnectionRecogniser.class);
byte[] tag = new byte[TAG_LENGTH];
int read = in.read(tag);
assertEquals(tag.length, read);
ConnectionContext ctx = rec.acceptConnection(transportId, tag);
assertNotNull(ctx);
assertEquals(contactId, ctx.getContactId());
assertEquals(transportIndex, ctx.getTransportIndex());
// Create an incoming batch connection
ConnectionRegistry connRegistry =
bob.getInstance(ConnectionRegistry.class);
ConnectionReaderFactory connFactory =
bob.getInstance(ConnectionReaderFactory.class);
ProtocolReaderFactory protoFactory =
bob.getInstance(ProtocolReaderFactory.class);
TestSimplexTransportReader transport = new TestSimplexTransportReader(in);
IncomingSimplexConnection simplex = new IncomingSimplexConnection(
new ImmediateExecutor(), new ImmediateExecutor(), db,
connRegistry, connFactory, protoFactory, ctx, transportId,
transport);
// No messages should have been added yet
assertFalse(listener.messagesAdded);
// Read whatever needs to be read
simplex.read();
assertTrue(transport.getDisposed());
assertFalse(transport.getException());
assertTrue(transport.getRecognised());
// The private message from Alice should have been added
assertTrue(listener.messagesAdded);
// Close Bob's database
db.close();
}
@After
public void tearDown() {
TestUtils.deleteTestDirectory(testDir);
}
private static class MessageListener implements DatabaseListener {
private boolean messagesAdded = false;
public void eventOccurred(DatabaseEvent e) {
if(e instanceof MessagesAddedEvent) messagesAdded = true;
}
}
}