mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-14 19:59:05 +01:00
First stage of key rotation refactoring. Some tests are failing.
This commit is contained in:
@@ -17,6 +17,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import net.sf.briar.api.ContactId;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.protocol.Ack;
|
||||
import net.sf.briar.api.protocol.Author;
|
||||
@@ -40,8 +41,8 @@ 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.TransportIndex;
|
||||
import net.sf.briar.api.protocol.TransportUpdate;
|
||||
import net.sf.briar.api.transport.ConnectionContext;
|
||||
import net.sf.briar.api.transport.ConnectionReader;
|
||||
import net.sf.briar.api.transport.ConnectionReaderFactory;
|
||||
import net.sf.briar.api.transport.ConnectionWriter;
|
||||
@@ -72,8 +73,9 @@ public class ProtocolIntegrationTest extends BriarTestCase {
|
||||
private final ProtocolWriterFactory protocolWriterFactory;
|
||||
private final PacketFactory packetFactory;
|
||||
private final CryptoComponent crypto;
|
||||
private final ContactId contactId;
|
||||
private final TransportId transportId;
|
||||
private final byte[] secret;
|
||||
private final TransportIndex transportIndex = new TransportIndex(13);
|
||||
private final Author author;
|
||||
private final Group group, group1;
|
||||
private final Message message, message1, message2, message3;
|
||||
@@ -95,6 +97,8 @@ public class ProtocolIntegrationTest extends BriarTestCase {
|
||||
protocolWriterFactory = i.getInstance(ProtocolWriterFactory.class);
|
||||
packetFactory = i.getInstance(PacketFactory.class);
|
||||
crypto = i.getInstance(CryptoComponent.class);
|
||||
contactId = new ContactId(234);
|
||||
transportId = new TransportId(TestUtils.getRandomId());
|
||||
// Create a shared secret
|
||||
Random r = new Random();
|
||||
secret = new byte[32];
|
||||
@@ -125,7 +129,7 @@ public class ProtocolIntegrationTest extends BriarTestCase {
|
||||
subject, messageBody.getBytes("UTF-8"));
|
||||
// Create some transports
|
||||
TransportId transportId = new TransportId(TestUtils.getRandomId());
|
||||
Transport transport = new Transport(transportId, transportIndex,
|
||||
Transport transport = new Transport(transportId,
|
||||
Collections.singletonMap("bar", "baz"));
|
||||
transports = Collections.singletonList(transport);
|
||||
}
|
||||
@@ -137,8 +141,11 @@ public class ProtocolIntegrationTest extends BriarTestCase {
|
||||
|
||||
private byte[] write() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
ConnectionContext ctx = new ConnectionContext(contactId, transportId,
|
||||
tag, secret.clone(), 0L, true);
|
||||
ConnectionWriter conn = connectionWriterFactory.createConnectionWriter(
|
||||
out, Long.MAX_VALUE, secret.clone(), true);
|
||||
out, Long.MAX_VALUE, ctx, true);
|
||||
OutputStream out1 = conn.getOutputStream();
|
||||
ProtocolWriter writer = protocolWriterFactory.createProtocolWriter(out1,
|
||||
false);
|
||||
@@ -190,8 +197,11 @@ public class ProtocolIntegrationTest extends BriarTestCase {
|
||||
InputStream in = new ByteArrayInputStream(connectionData);
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
assertEquals(TAG_LENGTH, in.read(tag, 0, TAG_LENGTH));
|
||||
assertArrayEquals(new byte[TAG_LENGTH], tag);
|
||||
ConnectionContext ctx = new ConnectionContext(contactId, transportId,
|
||||
tag, secret.clone(), 0L, true);
|
||||
ConnectionReader conn = connectionReaderFactory.createConnectionReader(
|
||||
in, secret.clone(), true);
|
||||
in, ctx, true);
|
||||
InputStream in1 = conn.getInputStream();
|
||||
ProtocolReader reader = protocolReaderFactory.createProtocolReader(in1);
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import java.util.Random;
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.protocol.ProtocolConstants;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -27,8 +26,10 @@ public class KeyDerivationTest extends BriarTestCase {
|
||||
@Test
|
||||
public void testKeysAreDistinct() {
|
||||
List<ErasableKey> keys = new ArrayList<ErasableKey>();
|
||||
keys.add(crypto.deriveFrameKey(secret, true));
|
||||
keys.add(crypto.deriveFrameKey(secret, false));
|
||||
keys.add(crypto.deriveFrameKey(secret, 0, false, false));
|
||||
keys.add(crypto.deriveFrameKey(secret, 0, false, true));
|
||||
keys.add(crypto.deriveFrameKey(secret, 0, true, false));
|
||||
keys.add(crypto.deriveFrameKey(secret, 0, true, true));
|
||||
keys.add(crypto.deriveTagKey(secret, true));
|
||||
keys.add(crypto.deriveTagKey(secret, false));
|
||||
for(int i = 0; i < 4; i++) {
|
||||
@@ -47,7 +48,7 @@ public class KeyDerivationTest extends BriarTestCase {
|
||||
for(int i = 0; i < 20; i++) {
|
||||
byte[] b = new byte[32];
|
||||
r.nextBytes(b);
|
||||
secrets.add(crypto.deriveNextSecret(b, 0, 0));
|
||||
secrets.add(crypto.deriveNextSecret(b, 0));
|
||||
}
|
||||
for(int i = 0; i < 20; i++) {
|
||||
byte[] secretI = secrets.get(i);
|
||||
@@ -58,26 +59,11 @@ public class KeyDerivationTest extends BriarTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransportIndexAffectsDerivation() {
|
||||
List<byte[]> secrets = new ArrayList<byte[]>();
|
||||
for(int i = 0; i < ProtocolConstants.MAX_TRANSPORTS; i++) {
|
||||
secrets.add(crypto.deriveNextSecret(secret, i, 0));
|
||||
}
|
||||
for(int i = 0; i < ProtocolConstants.MAX_TRANSPORTS; i++) {
|
||||
byte[] secretI = secrets.get(i);
|
||||
for(int j = 0; j < ProtocolConstants.MAX_TRANSPORTS; j++) {
|
||||
byte[] secretJ = secrets.get(j);
|
||||
assertEquals(i == j, Arrays.equals(secretI, secretJ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionNumberAffectsDerivation() {
|
||||
List<byte[]> secrets = new ArrayList<byte[]>();
|
||||
for(int i = 0; i < 20; i++) {
|
||||
secrets.add(crypto.deriveNextSecret(secret, 0, i));
|
||||
secrets.add(crypto.deriveNextSecret(secret, i));
|
||||
}
|
||||
for(int i = 0; i < 20; i++) {
|
||||
byte[] secretI = secrets.get(i);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package net.sf.briar.db;
|
||||
package net.sf.briar.crypto;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.db.KeyRotator.Callback;
|
||||
import net.sf.briar.crypto.KeyRotatorImpl;
|
||||
import net.sf.briar.crypto.KeyRotator.Callback;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -23,7 +23,6 @@ import net.sf.briar.api.db.event.DatabaseListener;
|
||||
import net.sf.briar.api.db.event.MessagesAddedEvent;
|
||||
import net.sf.briar.api.db.event.RatingChangedEvent;
|
||||
import net.sf.briar.api.db.event.SubscriptionsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.TransportAddedEvent;
|
||||
import net.sf.briar.api.lifecycle.ShutdownManager;
|
||||
import net.sf.briar.api.protocol.Ack;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
@@ -40,9 +39,7 @@ 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.TransportIndex;
|
||||
import net.sf.briar.api.protocol.TransportUpdate;
|
||||
import net.sf.briar.api.transport.ConnectionWindow;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
@@ -63,7 +60,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
private final Message message, privateMessage;
|
||||
private final Group group;
|
||||
private final TransportId transportId;
|
||||
private final TransportIndex localIndex, remoteIndex;
|
||||
private final Collection<Transport> transports;
|
||||
private final Map<ContactId, TransportProperties> remoteProperties;
|
||||
private final byte[] inSecret, outSecret;
|
||||
@@ -72,7 +68,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
super();
|
||||
authorId = new AuthorId(TestUtils.getRandomId());
|
||||
batchId = new BatchId(TestUtils.getRandomId());
|
||||
contactId = new ContactId(123);
|
||||
contactId = new ContactId(234);
|
||||
groupId = new GroupId(TestUtils.getRandomId());
|
||||
messageId = new MessageId(TestUtils.getRandomId());
|
||||
parentId = new MessageId(TestUtils.getRandomId());
|
||||
@@ -86,13 +82,10 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
timestamp, raw);
|
||||
group = new TestGroup(groupId, "The really exciting group", null);
|
||||
transportId = new TransportId(TestUtils.getRandomId());
|
||||
localIndex = new TransportIndex(0);
|
||||
remoteIndex = new TransportIndex(13);
|
||||
TransportProperties properties = new TransportProperties(
|
||||
Collections.singletonMap("foo", "bar"));
|
||||
remoteProperties = Collections.singletonMap(contactId, properties);
|
||||
Transport transport = new Transport(transportId, localIndex,
|
||||
properties);
|
||||
Transport transport = new Transport(transportId, properties);
|
||||
transports = Collections.singletonList(transport);
|
||||
Random r = new Random();
|
||||
inSecret = new byte[32];
|
||||
@@ -108,14 +101,13 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testSimpleCalls() throws Exception {
|
||||
// FIXME: Test new methods
|
||||
final int shutdownHandle = 12345;
|
||||
Mockery context = new Mockery();
|
||||
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 ConnectionWindow connectionWindow =
|
||||
context.mock(ConnectionWindow.class);
|
||||
final Group group = context.mock(Group.class);
|
||||
final DatabaseListener listener = context.mock(DatabaseListener.class);
|
||||
context.checking(new Expectations() {{
|
||||
@@ -142,18 +134,12 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
oneOf(database).setRating(txn, authorId, Rating.GOOD);
|
||||
will(returnValue(Rating.GOOD));
|
||||
// addContact()
|
||||
oneOf(database).addContact(with(txn), with(inSecret),
|
||||
with(outSecret), with(any(Collection.class)));
|
||||
oneOf(database).addContact(txn);
|
||||
will(returnValue(contactId));
|
||||
oneOf(listener).eventOccurred(with(any(ContactAddedEvent.class)));
|
||||
// getContacts()
|
||||
oneOf(database).getContacts(txn);
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
// getConnectionWindow(contactId, 13)
|
||||
oneOf(database).containsContact(txn, contactId);
|
||||
will(returnValue(true));
|
||||
oneOf(database).getConnectionWindow(txn, contactId, remoteIndex);
|
||||
will(returnValue(connectionWindow));
|
||||
// getTransportProperties(transportId)
|
||||
oneOf(database).getRemoteProperties(txn, transportId);
|
||||
will(returnValue(remoteProperties));
|
||||
@@ -183,11 +169,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
// unsubscribe(groupId) again
|
||||
oneOf(database).containsSubscription(txn, groupId);
|
||||
will(returnValue(false));
|
||||
// setConnectionWindow(contactId, 13, connectionWindow)
|
||||
oneOf(database).containsContact(txn, contactId);
|
||||
will(returnValue(true));
|
||||
oneOf(database).setConnectionWindow(txn, contactId, remoteIndex,
|
||||
connectionWindow);
|
||||
// removeContact(contactId)
|
||||
oneOf(database).containsContact(txn, contactId);
|
||||
will(returnValue(true));
|
||||
@@ -206,10 +187,8 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
assertEquals(Rating.UNRATED, db.getRating(authorId));
|
||||
db.setRating(authorId, Rating.GOOD); // First time - listeners called
|
||||
db.setRating(authorId, Rating.GOOD); // Second time - not called
|
||||
assertEquals(contactId, db.addContact(inSecret, outSecret));
|
||||
assertEquals(contactId, db.addContact());
|
||||
assertEquals(Collections.singletonList(contactId), db.getContacts());
|
||||
assertEquals(connectionWindow,
|
||||
db.getConnectionWindow(contactId, remoteIndex));
|
||||
assertEquals(remoteProperties, db.getRemoteProperties(transportId));
|
||||
db.subscribe(group); // First time - listeners called
|
||||
db.subscribe(group); // Second time - not called
|
||||
@@ -217,7 +196,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
assertEquals(Collections.singletonList(groupId), db.getSubscriptions());
|
||||
db.unsubscribe(groupId); // First time - listeners called
|
||||
db.unsubscribe(groupId); // Second time - not called
|
||||
db.setConnectionWindow(contactId, remoteIndex, connectionWindow);
|
||||
db.removeContact(contactId);
|
||||
db.removeListener(listener);
|
||||
db.close();
|
||||
@@ -297,7 +275,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testAffectedParentContinuesBackwardInclusion()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
@@ -338,7 +316,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testGroupMessagesAreNotStoredUnlessSubscribed()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
@@ -424,7 +402,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testAddingSendableMessageTriggersBackwardInclusion()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
@@ -516,7 +494,8 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testVariousMethodsThrowExceptionIfContactIsMissing()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
// FIXME: Test new methods
|
||||
Mockery context = new Mockery();
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
@@ -527,16 +506,16 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
final Batch batch = context.mock(Batch.class);
|
||||
final Offer offer = context.mock(Offer.class);
|
||||
final SubscriptionUpdate subscriptionUpdate =
|
||||
context.mock(SubscriptionUpdate.class);
|
||||
context.mock(SubscriptionUpdate.class);
|
||||
final TransportUpdate transportUpdate =
|
||||
context.mock(TransportUpdate.class);
|
||||
context.mock(TransportUpdate.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Check whether the contact is still in the DB (which it's not)
|
||||
exactly(19).of(database).startTransaction();
|
||||
exactly(15).of(database).startTransaction();
|
||||
will(returnValue(txn));
|
||||
exactly(19).of(database).containsContact(txn, contactId);
|
||||
exactly(15).of(database).containsContact(txn, contactId);
|
||||
will(returnValue(false));
|
||||
exactly(19).of(database).commitTransaction(txn);
|
||||
exactly(15).of(database).abortTransaction(txn);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
shutdown, packetFactory);
|
||||
@@ -577,21 +556,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
fail();
|
||||
} catch(NoSuchContactException expected) {}
|
||||
|
||||
try {
|
||||
db.getConnectionContext(contactId, remoteIndex);
|
||||
fail();
|
||||
} catch(NoSuchContactException expected) {}
|
||||
|
||||
try {
|
||||
db.getConnectionWindow(contactId, remoteIndex);
|
||||
fail();
|
||||
} catch(NoSuchContactException expected) {}
|
||||
|
||||
try {
|
||||
db.getRemoteIndex(contactId, transportId);
|
||||
fail();
|
||||
} catch(NoSuchContactException expected) {}
|
||||
|
||||
try {
|
||||
db.hasSendableMessages(contactId);
|
||||
fail();
|
||||
@@ -627,11 +591,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
fail();
|
||||
} catch(NoSuchContactException expected) {}
|
||||
|
||||
try {
|
||||
db.setConnectionWindow(contactId, remoteIndex, null);
|
||||
fail();
|
||||
} catch(NoSuchContactException expected) {}
|
||||
|
||||
try {
|
||||
db.setSeen(contactId, Collections.singletonList(messageId));
|
||||
fail();
|
||||
@@ -811,7 +770,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
||||
final PacketFactory packetFactory = context.mock(PacketFactory.class);
|
||||
final SubscriptionUpdate subscriptionUpdate =
|
||||
context.mock(SubscriptionUpdate.class);
|
||||
context.mock(SubscriptionUpdate.class);
|
||||
context.checking(new Expectations() {{
|
||||
allowing(database).startTransaction();
|
||||
will(returnValue(txn));
|
||||
@@ -883,7 +842,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
||||
final PacketFactory packetFactory = context.mock(PacketFactory.class);
|
||||
final TransportUpdate transportUpdate =
|
||||
context.mock(TransportUpdate.class);
|
||||
context.mock(TransportUpdate.class);
|
||||
context.checking(new Expectations() {{
|
||||
allowing(database).startTransaction();
|
||||
will(returnValue(txn));
|
||||
@@ -1015,7 +974,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReceiveBatchDoesNotStoreGroupMessageUnlessSubscribed()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
@@ -1050,7 +1009,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testReceiveBatchDoesNotCalculateSendabilityForDuplicates()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
@@ -1241,7 +1200,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
||||
final PacketFactory packetFactory = context.mock(PacketFactory.class);
|
||||
final SubscriptionUpdate subscriptionUpdate =
|
||||
context.mock(SubscriptionUpdate.class);
|
||||
context.mock(SubscriptionUpdate.class);
|
||||
context.checking(new Expectations() {{
|
||||
allowing(database).startTransaction();
|
||||
will(returnValue(txn));
|
||||
@@ -1281,7 +1240,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
||||
final PacketFactory packetFactory = context.mock(PacketFactory.class);
|
||||
final TransportUpdate transportUpdate =
|
||||
context.mock(TransportUpdate.class);
|
||||
context.mock(TransportUpdate.class);
|
||||
context.checking(new Expectations() {{
|
||||
allowing(database).startTransaction();
|
||||
will(returnValue(txn));
|
||||
@@ -1375,7 +1334,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testAddingDuplicateGroupMessageDoesNotCallListeners()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
@@ -1405,7 +1364,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testAddingDuplicatePrivateMessageDoesNotCallListeners()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
@@ -1435,16 +1394,15 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testTransportPropertiesChangedCallsListeners()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
final TransportProperties properties =
|
||||
new TransportProperties(Collections.singletonMap("bar", "baz"));
|
||||
new TransportProperties(Collections.singletonMap("bar", "baz"));
|
||||
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 DatabaseListener listener = context.mock(DatabaseListener.class);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(database).startTransaction();
|
||||
will(returnValue(txn));
|
||||
@@ -1454,13 +1412,10 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
oneOf(database).setTransportsModified(with(txn),
|
||||
with(any(long.class)));
|
||||
oneOf(database).commitTransaction(txn);
|
||||
oneOf(listener).eventOccurred(with(any(
|
||||
TransportAddedEvent.class)));
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
shutdown, packetFactory);
|
||||
|
||||
db.addListener(listener);
|
||||
db.setLocalProperties(transportId, properties);
|
||||
|
||||
context.assertIsSatisfied();
|
||||
@@ -1468,9 +1423,9 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testTransportPropertiesUnchangedDoesNotCallListeners()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
final TransportProperties properties =
|
||||
new TransportProperties(Collections.singletonMap("bar", "baz"));
|
||||
new TransportProperties(Collections.singletonMap("bar", "baz"));
|
||||
Mockery context = new Mockery();
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
@@ -1521,7 +1476,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testVisibilityChangedCallsListeners() throws Exception {
|
||||
final ContactId contactId1 = new ContactId(234);
|
||||
final ContactId contactId1 = new ContactId(123);
|
||||
final Collection<ContactId> both =
|
||||
Arrays.asList(new ContactId[] {contactId, contactId1});
|
||||
Mockery context = new Mockery();
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.sf.briar.db;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -18,7 +19,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
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.Rating;
|
||||
@@ -38,28 +38,12 @@ import net.sf.briar.api.protocol.Message;
|
||||
import net.sf.briar.api.protocol.MessageId;
|
||||
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.transport.ConnectionContextFactory;
|
||||
import net.sf.briar.api.transport.ConnectionWindow;
|
||||
import net.sf.briar.api.transport.ConnectionWindowFactory;
|
||||
import net.sf.briar.api.transport.TransportConstants;
|
||||
import net.sf.briar.clock.ClockModule;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
import net.sf.briar.lifecycle.LifecycleModule;
|
||||
import net.sf.briar.protocol.ProtocolModule;
|
||||
import net.sf.briar.protocol.duplex.DuplexProtocolModule;
|
||||
import net.sf.briar.protocol.simplex.SimplexProtocolModule;
|
||||
import net.sf.briar.serial.SerialModule;
|
||||
import net.sf.briar.transport.TransportModule;
|
||||
|
||||
import org.apache.commons.io.FileSystemUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
private static final int ONE_MEGABYTE = 1024 * 1024;
|
||||
@@ -70,10 +54,8 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
private final String passwordString = "foo bar";
|
||||
private final Password password = new TestPassword();
|
||||
private final Random random = new Random();
|
||||
private final ConnectionContextFactory connectionContextFactory;
|
||||
private final ConnectionWindowFactory connectionWindowFactory;
|
||||
private final GroupFactory groupFactory;
|
||||
|
||||
private final Group group;
|
||||
private final AuthorId authorId;
|
||||
private final BatchId batchId;
|
||||
private final ContactId contactId;
|
||||
@@ -84,33 +66,21 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
private final int size;
|
||||
private final byte[] raw;
|
||||
private final Message message, privateMessage;
|
||||
private final Group group;
|
||||
private final TransportId transportId;
|
||||
private final TransportIndex localIndex, remoteIndex;
|
||||
private final TransportProperties properties;
|
||||
private final Map<ContactId, TransportProperties> remoteProperties;
|
||||
private final Collection<Transport> remoteTransports;
|
||||
private final byte[] inSecret, outSecret;
|
||||
private final Collection<byte[]> erase;
|
||||
|
||||
public H2DatabaseTest() throws Exception {
|
||||
super();
|
||||
// FIXME: Use mocks for the factories rather than building the whole app
|
||||
Injector i = Guice.createInjector(new ClockModule(), new CryptoModule(),
|
||||
new DatabaseModule(), new LifecycleModule(),
|
||||
new ProtocolModule(), new SerialModule(),
|
||||
new SimplexProtocolModule(), new TransportModule(),
|
||||
new DuplexProtocolModule(), new TestDatabaseModule(testDir));
|
||||
connectionContextFactory =
|
||||
i.getInstance(ConnectionContextFactory.class);
|
||||
connectionWindowFactory = i.getInstance(ConnectionWindowFactory.class);
|
||||
groupFactory = i.getInstance(GroupFactory.class);
|
||||
groupFactory = new TestGroupFactory();
|
||||
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());
|
||||
group = new TestGroup(groupId, "Foo", null);
|
||||
subject = "Foo";
|
||||
timestamp = System.currentTimeMillis();
|
||||
size = 1234;
|
||||
@@ -120,22 +90,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
timestamp, raw);
|
||||
privateMessage = new TestMessage(privateMessageId, null, null, null,
|
||||
subject, timestamp, raw);
|
||||
group = groupFactory.createGroup(groupId, "Group name", null);
|
||||
transportId = new TransportId(TestUtils.getRandomId());
|
||||
localIndex = new TransportIndex(1);
|
||||
remoteIndex = new TransportIndex(13);
|
||||
properties = new TransportProperties(
|
||||
Collections.singletonMap("foo", "bar"));
|
||||
remoteProperties = Collections.singletonMap(contactId, properties);
|
||||
Transport remoteTransport = new Transport(transportId, remoteIndex,
|
||||
properties);
|
||||
Transport remoteTransport = new Transport(transportId, properties);
|
||||
remoteTransports = Collections.singletonList(remoteTransport);
|
||||
Random r = new Random();
|
||||
inSecret = new byte[32];
|
||||
r.nextBytes(inSecret);
|
||||
outSecret = new byte[32];
|
||||
r.nextBytes(outSecret);
|
||||
erase = new ArrayList<byte[]>();
|
||||
}
|
||||
|
||||
@Before
|
||||
@@ -149,7 +109,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
assertFalse(db.containsContact(txn, contactId));
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
assertTrue(db.containsContact(txn, contactId));
|
||||
assertFalse(db.containsSubscription(txn, groupId));
|
||||
db.addSubscription(txn, group);
|
||||
@@ -205,23 +165,20 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
// Create three contacts
|
||||
assertFalse(db.containsContact(txn, contactId));
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
assertTrue(db.containsContact(txn, contactId));
|
||||
assertFalse(db.containsContact(txn, contactId1));
|
||||
assertEquals(contactId1,
|
||||
db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId1, db.addContact(txn));
|
||||
assertTrue(db.containsContact(txn, contactId1));
|
||||
assertFalse(db.containsContact(txn, contactId2));
|
||||
assertEquals(contactId2,
|
||||
db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId2, db.addContact(txn));
|
||||
assertTrue(db.containsContact(txn, contactId2));
|
||||
// Delete the contact with the highest ID
|
||||
db.removeContact(txn, contactId2);
|
||||
assertFalse(db.containsContact(txn, contactId2));
|
||||
// Add another contact - a new ID should be created
|
||||
assertFalse(db.containsContact(txn, contactId3));
|
||||
assertEquals(contactId3,
|
||||
db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId3, db.addContact(txn));
|
||||
assertTrue(db.containsContact(txn, contactId3));
|
||||
|
||||
db.commitTransaction(txn);
|
||||
@@ -268,7 +225,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact and store a private message
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addPrivateMessage(txn, privateMessage, contactId);
|
||||
|
||||
// Removing the contact should remove the message
|
||||
@@ -282,18 +239,18 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testSendablePrivateMessagesMustHaveStatusNew()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact and store a private message
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addPrivateMessage(txn, privateMessage, contactId);
|
||||
|
||||
// The message has no status yet, so it should not be sendable
|
||||
assertFalse(db.hasSendableMessages(txn, contactId));
|
||||
Iterator<MessageId> it =
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
assertFalse(it.hasNext());
|
||||
|
||||
// Changing the status to NEW should make the message sendable
|
||||
@@ -321,19 +278,19 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testSendablePrivateMessagesMustFitCapacity()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact and store a private message
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addPrivateMessage(txn, privateMessage, contactId);
|
||||
db.setStatus(txn, contactId, privateMessageId, Status.NEW);
|
||||
|
||||
// The message is sendable, but too large to send
|
||||
assertTrue(db.hasSendableMessages(txn, contactId));
|
||||
Iterator<MessageId> it =
|
||||
db.getSendableMessages(txn, contactId, size - 1).iterator();
|
||||
db.getSendableMessages(txn, contactId, size - 1).iterator();
|
||||
assertFalse(it.hasNext());
|
||||
|
||||
// The message is just the right size to send
|
||||
@@ -349,12 +306,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testSendableGroupMessagesMustHavePositiveSendability()
|
||||
throws Exception {
|
||||
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, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
@@ -364,7 +321,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
// The message should not be sendable
|
||||
assertFalse(db.hasSendableMessages(txn, contactId));
|
||||
Iterator<MessageId> it =
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
assertFalse(it.hasNext());
|
||||
|
||||
// Changing the sendability to > 0 should make the message sendable
|
||||
@@ -387,12 +344,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testSendableGroupMessagesMustHaveStatusNew()
|
||||
throws Exception {
|
||||
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, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
@@ -402,7 +359,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
// The message has no status yet, so it should not be sendable
|
||||
assertFalse(db.hasSendableMessages(txn, contactId));
|
||||
Iterator<MessageId> it =
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
assertFalse(it.hasNext());
|
||||
|
||||
// Changing the status to Status.NEW should make the message sendable
|
||||
@@ -434,7 +391,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact, subscribe to a group and store a message
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addGroupMessage(txn, message);
|
||||
@@ -444,7 +401,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
// The contact is not subscribed, so the message should not be sendable
|
||||
assertFalse(db.hasSendableMessages(txn, contactId));
|
||||
Iterator<MessageId> it =
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
assertFalse(it.hasNext());
|
||||
|
||||
// The contact subscribing should make the message sendable
|
||||
@@ -467,12 +424,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testSendableGroupMessagesMustBeNewerThanSubscriptions()
|
||||
throws Exception {
|
||||
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, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addGroupMessage(txn, message);
|
||||
@@ -484,7 +441,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
db.addSubscription(txn, contactId, group, timestamp + 1);
|
||||
assertFalse(db.hasSendableMessages(txn, contactId));
|
||||
Iterator<MessageId> it =
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
assertFalse(it.hasNext());
|
||||
|
||||
// Changing the contact's subscription should make the message sendable
|
||||
@@ -506,7 +463,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact, subscribe to a group and store a message
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
@@ -517,7 +474,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
// The message is sendable, but too large to send
|
||||
assertTrue(db.hasSendableMessages(txn, contactId));
|
||||
Iterator<MessageId> it =
|
||||
db.getSendableMessages(txn, contactId, size - 1).iterator();
|
||||
db.getSendableMessages(txn, contactId, size - 1).iterator();
|
||||
assertFalse(it.hasNext());
|
||||
|
||||
// The message is just the right size to send
|
||||
@@ -537,7 +494,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact, subscribe to a group and store a message
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
db.addGroupMessage(txn, message);
|
||||
@@ -548,7 +505,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
// should not be sendable
|
||||
assertFalse(db.hasSendableMessages(txn, contactId));
|
||||
Iterator<MessageId> it =
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
assertFalse(it.hasNext());
|
||||
|
||||
// Making the subscription visible should make the message sendable
|
||||
@@ -570,7 +527,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact and some batches to ack
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addBatchToAck(txn, contactId, batchId);
|
||||
db.addBatchToAck(txn, contactId, batchId1);
|
||||
|
||||
@@ -597,7 +554,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact and receive the same batch twice
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addBatchToAck(txn, contactId, batchId);
|
||||
db.addBatchToAck(txn, contactId, batchId);
|
||||
|
||||
@@ -623,7 +580,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact, subscribe to a group and store a message
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addGroupMessage(txn, message);
|
||||
|
||||
@@ -648,8 +605,8 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add two contacts, subscribe to a group and store a message
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
ContactId contactId1 = db.addContact(txn, inSecret, outSecret, erase);
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
ContactId contactId1 = db.addContact(txn);
|
||||
db.addSubscription(txn, group);
|
||||
db.addGroupMessage(txn, message);
|
||||
|
||||
@@ -671,7 +628,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact, subscribe to a group and store a message
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
@@ -681,7 +638,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
// Retrieve the message from the database and mark it as sent
|
||||
Iterator<MessageId> it =
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(messageId, it.next());
|
||||
assertFalse(it.hasNext());
|
||||
@@ -710,7 +667,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact, subscribe to a group and store a message
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
@@ -720,7 +677,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
// Get the message and mark it as sent
|
||||
Iterator<MessageId> it =
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(messageId, it.next());
|
||||
assertFalse(it.hasNext());
|
||||
@@ -755,7 +712,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
|
||||
// Add some outstanding batches, a few ms apart
|
||||
for(int i = 0; i < ids.length; i++) {
|
||||
@@ -795,7 +752,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
|
||||
// Add some outstanding batches, a few ms apart
|
||||
for(int i = 0; i < ids.length; i++) {
|
||||
@@ -832,7 +789,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
// Check that each message is retrievable via its author
|
||||
Iterator<MessageId> it =
|
||||
db.getMessagesByAuthor(txn, authorId).iterator();
|
||||
db.getMessagesByAuthor(txn, authorId).iterator();
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(messageId, it.next());
|
||||
assertFalse(it.hasNext());
|
||||
@@ -1021,35 +978,29 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact with a transport
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.setTransports(txn, contactId, remoteTransports, 1);
|
||||
assertEquals(remoteProperties,
|
||||
db.getRemoteProperties(txn, transportId));
|
||||
|
||||
// Replace the transport properties
|
||||
TransportProperties properties1 =
|
||||
new TransportProperties(Collections.singletonMap("baz", "bam"));
|
||||
Transport remoteTransport1 =
|
||||
new Transport(transportId, remoteIndex, properties1);
|
||||
new TransportProperties(Collections.singletonMap("baz", "bam"));
|
||||
Transport remoteTransport1 = new Transport(transportId, properties1);
|
||||
Collection<Transport> remoteTransports1 =
|
||||
Collections.singletonList(remoteTransport1);
|
||||
Collections.singletonList(remoteTransport1);
|
||||
Map<ContactId, TransportProperties> remoteProperties1 =
|
||||
Collections.singletonMap(contactId, properties1);
|
||||
Collections.singletonMap(contactId, properties1);
|
||||
db.setTransports(txn, contactId, remoteTransports1, 2);
|
||||
assertEquals(remoteProperties1,
|
||||
db.getRemoteProperties(txn, transportId));
|
||||
|
||||
// Remove the transport properties but leave the transport
|
||||
// Remove the transport properties
|
||||
properties1 = new TransportProperties();
|
||||
remoteTransport1 = new Transport(transportId, remoteIndex, properties1);
|
||||
remoteTransport1 = new Transport(transportId, properties1);
|
||||
remoteTransports1 = Collections.singletonList(remoteTransport1);
|
||||
remoteProperties1 = Collections.singletonMap(contactId, properties1);
|
||||
db.setTransports(txn, contactId, remoteTransports1, 3);
|
||||
assertEquals(remoteProperties1,
|
||||
db.getRemoteProperties(txn, transportId));
|
||||
|
||||
// Remove the transport
|
||||
db.setTransports(txn, contactId, Collections.<Transport>emptyList(), 4);
|
||||
assertEquals(Collections.emptyMap(),
|
||||
db.getRemoteProperties(txn, transportId));
|
||||
|
||||
@@ -1062,9 +1013,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Allocate a transport index
|
||||
assertEquals(localIndex, db.addTransport(txn, transportId));
|
||||
|
||||
// Set the transport properties
|
||||
db.setLocalProperties(txn, transportId, properties);
|
||||
assertEquals(Collections.singletonList(properties),
|
||||
@@ -1072,8 +1020,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
// Remove the transport properties but leave the transport
|
||||
db.setLocalProperties(txn, transportId, new TransportProperties());
|
||||
assertEquals(Collections.singletonList(Collections.emptyMap()),
|
||||
db.getLocalTransports(txn));
|
||||
assertEquals(Collections.emptyList(), db.getLocalTransports(txn));
|
||||
|
||||
db.commitTransaction(txn);
|
||||
db.close();
|
||||
@@ -1082,16 +1029,13 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
@Test
|
||||
public void testUpdateTransportConfig() throws Exception {
|
||||
TransportConfig config =
|
||||
new TransportConfig(Collections.singletonMap("foo", "bar"));
|
||||
new TransportConfig(Collections.singletonMap("foo", "bar"));
|
||||
TransportConfig config1 =
|
||||
new TransportConfig(Collections.singletonMap("baz", "bam"));
|
||||
new TransportConfig(Collections.singletonMap("baz", "bam"));
|
||||
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Allocate a transport index
|
||||
assertEquals(localIndex, db.addTransport(txn, transportId));
|
||||
|
||||
// Set the transport config
|
||||
db.setConfig(txn, transportId, config);
|
||||
assertEquals(config, db.getConfig(txn, transportId));
|
||||
@@ -1114,31 +1058,29 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact with a transport
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.setTransports(txn, contactId, remoteTransports, 1);
|
||||
assertEquals(remoteProperties,
|
||||
db.getRemoteProperties(txn, transportId));
|
||||
|
||||
// Replace the transport properties using a timestamp of 2
|
||||
TransportProperties properties1 =
|
||||
new TransportProperties(Collections.singletonMap("baz", "bam"));
|
||||
Transport remoteTransport1 =
|
||||
new Transport(transportId, remoteIndex, properties1);
|
||||
new TransportProperties(Collections.singletonMap("baz", "bam"));
|
||||
Transport remoteTransport1 = new Transport(transportId, properties1);
|
||||
Collection<Transport> remoteTransports1 =
|
||||
Collections.singletonList(remoteTransport1);
|
||||
Collections.singletonList(remoteTransport1);
|
||||
Map<ContactId, TransportProperties> remoteProperties1 =
|
||||
Collections.singletonMap(contactId, properties1);
|
||||
Collections.singletonMap(contactId, properties1);
|
||||
db.setTransports(txn, contactId, remoteTransports1, 2);
|
||||
assertEquals(remoteProperties1,
|
||||
db.getRemoteProperties(txn, transportId));
|
||||
|
||||
// Try to replace the transport properties using a timestamp of 1
|
||||
TransportProperties properties2 =
|
||||
new TransportProperties(Collections.singletonMap("quux", "etc"));
|
||||
Transport remoteTransport2 =
|
||||
new Transport(transportId, remoteIndex, properties2);
|
||||
new TransportProperties(Collections.singletonMap("quux", "etc"));
|
||||
Transport remoteTransport2 = new Transport(transportId, properties2);
|
||||
Collection<Transport> remoteTransports2 =
|
||||
Collections.singletonList(remoteTransport2);
|
||||
Collections.singletonList(remoteTransport2);
|
||||
db.setTransports(txn, contactId, remoteTransports2, 1);
|
||||
|
||||
// The old properties should still be there
|
||||
@@ -1151,12 +1093,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testGetMessageIfSendableReturnsNullIfNotInDatabase()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact and subscribe to a group
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
|
||||
@@ -1169,12 +1111,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testGetMessageIfSendableReturnsNullIfSeen()
|
||||
throws Exception {
|
||||
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, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
db.addGroupMessage(txn, message);
|
||||
@@ -1192,12 +1134,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testGetMessageIfSendableReturnsNullIfNotSendable()
|
||||
throws Exception {
|
||||
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, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
db.addGroupMessage(txn, message);
|
||||
@@ -1220,7 +1162,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
// Add a contact, subscribe to a group and store a message -
|
||||
// the message is older than the contact's subscription
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addSubscription(txn, contactId, group, timestamp + 1);
|
||||
@@ -1243,7 +1185,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact, subscribe to a group and store a message
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
@@ -1263,12 +1205,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testSetStatusSeenIfVisibleRequiresMessageInDatabase()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact and subscribe to a group
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
@@ -1282,12 +1224,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testSetStatusSeenIfVisibleRequiresLocalSubscription()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact with a subscription
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
|
||||
// There's no local subscription for the group
|
||||
@@ -1299,12 +1241,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testSetStatusSeenIfVisibleRequiresContactSubscription()
|
||||
throws Exception {
|
||||
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, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addGroupMessage(txn, message);
|
||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
||||
@@ -1318,12 +1260,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testSetStatusSeenIfVisibleRequiresVisibility()
|
||||
throws Exception {
|
||||
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, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addGroupMessage(txn, message);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
@@ -1338,12 +1280,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testSetStatusSeenIfVisibleReturnsTrueIfAlreadySeen()
|
||||
throws Exception {
|
||||
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, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
@@ -1360,12 +1302,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testSetStatusSeenIfVisibleReturnsTrueIfNew()
|
||||
throws Exception {
|
||||
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, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addSubscription(txn, contactId, group, 0L);
|
||||
@@ -1386,7 +1328,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact and subscribe to a group
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
// The group should not be visible to the contact
|
||||
assertEquals(Collections.emptyList(), db.getVisibility(txn, groupId));
|
||||
@@ -1402,58 +1344,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGettingUnknownConnectionWindowReturnsDefault()
|
||||
throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
// Get the connection window for a new index
|
||||
ConnectionWindow w = db.getConnectionWindow(txn, contactId,
|
||||
remoteIndex);
|
||||
// The connection window should exist and be in the initial state
|
||||
assertNotNull(w);
|
||||
long top = TransportConstants.CONNECTION_WINDOW_SIZE / 2 - 1;
|
||||
for(long l = 0; l <= top; l++) assertFalse(w.isSeen(l));
|
||||
|
||||
db.commitTransaction(txn);
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionWindow() throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
// Get the connection window for a new index
|
||||
ConnectionWindow w = db.getConnectionWindow(txn, contactId,
|
||||
remoteIndex);
|
||||
// The connection window should exist and be in the initial state
|
||||
assertNotNull(w);
|
||||
Map<Long, byte[]> unseen = w.getUnseen();
|
||||
long top = TransportConstants.CONNECTION_WINDOW_SIZE / 2 - 1;
|
||||
assertEquals(top + 1, unseen.size());
|
||||
for(long l = 0; l <= top; l++) {
|
||||
assertFalse(w.isSeen(l));
|
||||
assertTrue(unseen.containsKey(l));
|
||||
}
|
||||
// Update the connection window and store it
|
||||
w.setSeen(5);
|
||||
db.setConnectionWindow(txn, contactId, remoteIndex, w);
|
||||
// Check that the connection window was stored
|
||||
w = db.getConnectionWindow(txn, contactId, remoteIndex);
|
||||
assertNotNull(w);
|
||||
top += 5;
|
||||
for(long l = 0; l <= top; l++) assertEquals(l == 5, w.isSeen(l));
|
||||
|
||||
db.commitTransaction(txn);
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGroupMessageParentWithNoParent() throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
@@ -1498,7 +1388,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testGetGroupMessageParentWithParentInAnotherGroup()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
||||
Group group1 = groupFactory.createGroup(groupId1, "Group name", null);
|
||||
Database<Connection> db = open(false);
|
||||
@@ -1527,12 +1417,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testGetGroupMessageParentWithPrivateParent()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact and subscribe to a group
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
|
||||
// A message with a private parent should return null
|
||||
@@ -1551,7 +1441,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testGetGroupMessageParentWithParentInSameGroup()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
@@ -1581,7 +1471,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact and subscribe to a group
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
db.addSubscription(txn, group);
|
||||
|
||||
// Store a couple of messages
|
||||
@@ -1813,7 +1703,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
// Subscribe to the groups and add a contact
|
||||
for(Group g : groups) db.addSubscription(txn, g);
|
||||
assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase));
|
||||
assertEquals(contactId, db.addContact(txn));
|
||||
|
||||
// Make the groups visible to the contact
|
||||
Collections.shuffle(groups);
|
||||
@@ -1849,7 +1739,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
private Database<Connection> open(boolean resume) throws Exception {
|
||||
Database<Connection> db = new H2Database(testDir, password, MAX_SIZE,
|
||||
connectionContextFactory, connectionWindowFactory,
|
||||
groupFactory, new SystemClock());
|
||||
db.open(resume);
|
||||
return db;
|
||||
@@ -1857,7 +1746,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
erase.clear();
|
||||
TestUtils.deleteTestDirectory(testDir);
|
||||
}
|
||||
|
||||
@@ -1867,4 +1755,17 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
return passwordString.toCharArray();
|
||||
}
|
||||
}
|
||||
|
||||
private class TestGroupFactory implements GroupFactory {
|
||||
|
||||
public Group createGroup(String name, byte[] publicKey)
|
||||
throws IOException {
|
||||
GroupId id = new GroupId(TestUtils.getRandomId());
|
||||
return new TestGroup(id, name, publicKey);
|
||||
}
|
||||
|
||||
public Group createGroup(GroupId id, String name, byte[] publicKey) {
|
||||
return new TestGroup(id, name, publicKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ abstract class DuplexTest {
|
||||
protected static final String RESPONSE = "Potatoes!";
|
||||
protected static final long INVITATION_TIMEOUT = 30 * 1000;
|
||||
|
||||
protected final ContactId contactId = new ContactId(0);
|
||||
protected final ContactId contactId = new ContactId(234);
|
||||
|
||||
protected DuplexPlugin plugin = null;
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ import com.google.inject.Injector;
|
||||
|
||||
public class InvitationStarterImplTest extends BriarTestCase {
|
||||
|
||||
// FIXME: This is actually a test of CryptoComponent
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
|
||||
public InvitationStarterImplTest() {
|
||||
@@ -32,13 +34,8 @@ public class InvitationStarterImplTest extends BriarTestCase {
|
||||
KeyPair b = crypto.generateAgreementKeyPair();
|
||||
byte[] bPub = b.getPublic().getEncoded();
|
||||
PrivateKey bPriv = b.getPrivate();
|
||||
byte[][] aSecrets = crypto.deriveInitialSecrets(aPub, bPub, aPriv, 123,
|
||||
true);
|
||||
byte[][] bSecrets = crypto.deriveInitialSecrets(bPub, aPub, bPriv, 123,
|
||||
false);
|
||||
assertEquals(2, aSecrets.length);
|
||||
assertEquals(2, bSecrets.length);
|
||||
assertArrayEquals(aSecrets[0], bSecrets[0]);
|
||||
assertArrayEquals(aSecrets[1], bSecrets[1]);
|
||||
byte[] aSecret = crypto.deriveInitialSecret(aPub, bPub, aPriv, true);
|
||||
byte[] bSecret = crypto.deriveInitialSecret(bPub, aPub, bPriv, false);
|
||||
assertArrayEquals(aSecret, bSecret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,12 @@ package net.sf.briar.plugins;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.TransportConfig;
|
||||
import net.sf.briar.api.TransportProperties;
|
||||
import net.sf.briar.api.db.DatabaseComponent;
|
||||
import net.sf.briar.api.protocol.TransportId;
|
||||
import net.sf.briar.api.protocol.TransportIndex;
|
||||
import net.sf.briar.api.transport.ConnectionDispatcher;
|
||||
import net.sf.briar.api.ui.UiCallback;
|
||||
|
||||
@@ -29,13 +27,8 @@ public class PluginManagerImplTest extends BriarTestCase {
|
||||
final ConnectionDispatcher dispatcher =
|
||||
context.mock(ConnectionDispatcher.class);
|
||||
final UiCallback uiCallback = context.mock(UiCallback.class);
|
||||
final AtomicInteger index = new AtomicInteger(0);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(poller).start(with(any(Collection.class)));
|
||||
allowing(db).getLocalIndex(with(any(TransportId.class)));
|
||||
will(returnValue(null));
|
||||
allowing(db).addTransport(with(any(TransportId.class)));
|
||||
will(returnValue(new TransportIndex(index.getAndIncrement())));
|
||||
allowing(db).getConfig(with(any(TransportId.class)));
|
||||
will(returnValue(new TransportConfig()));
|
||||
allowing(db).getLocalProperties(with(any(TransportId.class)));
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
package net.sf.briar.plugins.email;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.ContactId;
|
||||
import net.sf.briar.api.TransportConfig;
|
||||
import net.sf.briar.api.TransportProperties;
|
||||
@@ -19,7 +16,6 @@ import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
|
||||
import net.sf.briar.api.plugins.simplex.SimplexTransportReader;
|
||||
import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
|
||||
|
||||
import org.jmock.Mockery;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -47,7 +43,7 @@ public class GmailPluginTest {
|
||||
|
||||
props1 = new TransportProperties();
|
||||
props1.put("email", System.getenv("CONTACT1_EMAIL"));
|
||||
test1 = new ContactId(12);
|
||||
test1 = new ContactId(234);
|
||||
map.put(test1, props1);
|
||||
assertEquals(1, map.size());
|
||||
|
||||
@@ -120,7 +116,7 @@ public class GmailPluginTest {
|
||||
GmailPlugin pluginTest = new GmailPlugin(
|
||||
Executors.newSingleThreadExecutor(), callback);
|
||||
assertEquals(true, pluginTest.connectSMTP(test1));
|
||||
assertEquals(false, pluginTest.connectSMTP(new ContactId(7)));
|
||||
assertEquals(false, pluginTest.connectSMTP(new ContactId(123)));
|
||||
pluginTest.stop();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.junit.Test;
|
||||
public class RemovableDrivePluginTest extends BriarTestCase {
|
||||
|
||||
private final File testDir = TestUtils.getTestDirectory();
|
||||
private final ContactId contactId = new ContactId(0);
|
||||
private final ContactId contactId = new ContactId(234);
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.junit.Test;
|
||||
|
||||
public class SimpleSocketPluginTest extends BriarTestCase {
|
||||
|
||||
private final ContactId contactId = new ContactId(0);
|
||||
private final ContactId contactId = new ContactId(234);
|
||||
|
||||
@Test
|
||||
public void testIncomingConnection() throws Exception {
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.junit.Test;
|
||||
|
||||
public class TorPluginTest extends BriarTestCase {
|
||||
|
||||
private final ContactId contactId = new ContactId(1);
|
||||
private final ContactId contactId = new ContactId(234);
|
||||
|
||||
@Test
|
||||
public void testHiddenService() throws Exception {
|
||||
|
||||
@@ -35,7 +35,6 @@ 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.TransportIndex;
|
||||
import net.sf.briar.api.protocol.TransportUpdate;
|
||||
import net.sf.briar.api.protocol.UniqueId;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
@@ -158,8 +157,7 @@ public class ConstantsTest extends BriarTestCase {
|
||||
Collection<Transport> transports = new ArrayList<Transport>();
|
||||
for(int i = 0; i < MAX_TRANSPORTS; i++) {
|
||||
TransportId id = new TransportId(TestUtils.getRandomId());
|
||||
TransportIndex index = new TransportIndex(i);
|
||||
Transport t = new Transport(id, index);
|
||||
Transport t = new Transport(id);
|
||||
for(int j = 0; j < MAX_PROPERTIES_PER_TRANSPORT; j++) {
|
||||
String key = createRandomString(MAX_PROPERTY_LENGTH);
|
||||
String value = createRandomString(MAX_PROPERTY_LENGTH);
|
||||
|
||||
@@ -28,7 +28,6 @@ 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.TransportIndex;
|
||||
import net.sf.briar.api.protocol.TransportUpdate;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
import net.sf.briar.serial.SerialModule;
|
||||
@@ -71,8 +70,7 @@ public class ProtocolReadWriteTest extends BriarTestCase {
|
||||
bitSet.set(7);
|
||||
subscriptions = Collections.singletonMap(group, 123L);
|
||||
TransportId transportId = new TransportId(TestUtils.getRandomId());
|
||||
TransportIndex transportIndex = new TransportIndex(13);
|
||||
Transport transport = new Transport(transportId, transportIndex,
|
||||
Transport transport = new Transport(transportId,
|
||||
Collections.singletonMap("bar", "baz"));
|
||||
transports = Collections.singletonList(transport);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package net.sf.briar.protocol.simplex;
|
||||
|
||||
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.HEADER_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.MIN_CONNECTION_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -12,20 +14,19 @@ import java.util.concurrent.Executors;
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.TestUtils;
|
||||
import net.sf.briar.api.ContactId;
|
||||
import net.sf.briar.api.crypto.KeyManager;
|
||||
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.TransportId;
|
||||
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.ConnectionRecogniser;
|
||||
import net.sf.briar.api.transport.ConnectionRegistry;
|
||||
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.duplex.DuplexProtocolModule;
|
||||
@@ -43,24 +44,31 @@ import com.google.inject.Module;
|
||||
|
||||
public class OutgoingSimplexConnectionTest extends BriarTestCase {
|
||||
|
||||
// FIXME: This is an integration test, not a unit test
|
||||
|
||||
private final Mockery context;
|
||||
private final DatabaseComponent db;
|
||||
private final KeyManager keyManager;
|
||||
private final ConnectionRecogniser connRecogniser;
|
||||
private final ConnectionRegistry connRegistry;
|
||||
private final ConnectionWriterFactory connFactory;
|
||||
private final ProtocolWriterFactory protoFactory;
|
||||
private final ContactId contactId;
|
||||
private final TransportId transportId;
|
||||
private final TransportIndex transportIndex;
|
||||
private final byte[] secret;
|
||||
|
||||
public OutgoingSimplexConnectionTest() {
|
||||
super();
|
||||
context = new Mockery();
|
||||
db = context.mock(DatabaseComponent.class);
|
||||
keyManager = context.mock(KeyManager.class);
|
||||
connRecogniser = context.mock(ConnectionRecogniser.class);
|
||||
Module testModule = new AbstractModule() {
|
||||
@Override
|
||||
public void configure() {
|
||||
bind(DatabaseComponent.class).toInstance(db);
|
||||
bind(KeyManager.class).toInstance(keyManager);
|
||||
bind(ConnectionRecogniser.class).toInstance(connRecogniser);
|
||||
bind(Executor.class).annotatedWith(
|
||||
DatabaseExecutor.class).toInstance(
|
||||
Executors.newCachedThreadPool());
|
||||
@@ -73,9 +81,8 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
|
||||
connRegistry = i.getInstance(ConnectionRegistry.class);
|
||||
connFactory = i.getInstance(ConnectionWriterFactory.class);
|
||||
protoFactory = i.getInstance(ProtocolWriterFactory.class);
|
||||
contactId = new ContactId(1);
|
||||
contactId = new ContactId(234);
|
||||
transportId = new TransportId(TestUtils.getRandomId());
|
||||
transportIndex = new TransportIndex(13);
|
||||
secret = new byte[32];
|
||||
}
|
||||
|
||||
@@ -83,40 +90,31 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
|
||||
public void testConnectionTooShort() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
TestSimplexTransportWriter transport = new TestSimplexTransportWriter(
|
||||
out, ProtocolConstants.MAX_PACKET_LENGTH, true);
|
||||
out, MAX_PACKET_LENGTH, true);
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
ConnectionContext ctx = new ConnectionContext(contactId, transportId,
|
||||
tag, secret, 0L, true);
|
||||
OutgoingSimplexConnection connection = new OutgoingSimplexConnection(db,
|
||||
connRegistry, connFactory, protoFactory, contactId, transportId,
|
||||
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));
|
||||
}});
|
||||
connRegistry, connFactory, protoFactory, ctx, transport);
|
||||
connection.write();
|
||||
// Nothing should have been written
|
||||
assertEquals(0, out.size());
|
||||
// The transport should have been disposed with exception == true
|
||||
assertTrue(transport.getDisposed());
|
||||
assertTrue(transport.getException());
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNothingToSend() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
TestSimplexTransportWriter transport = new TestSimplexTransportWriter(
|
||||
out, TransportConstants.MIN_CONNECTION_LENGTH, true);
|
||||
out, MIN_CONNECTION_LENGTH, true);
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
ConnectionContext ctx = new ConnectionContext(contactId, transportId,
|
||||
tag, secret, 0L, true);
|
||||
OutgoingSimplexConnection connection = new OutgoingSimplexConnection(db,
|
||||
connRegistry, connFactory, protoFactory, contactId, transportId,
|
||||
transportIndex, transport);
|
||||
final ConnectionContext ctx = context.mock(ConnectionContext.class);
|
||||
connRegistry, connFactory, protoFactory, ctx, transport);
|
||||
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));
|
||||
@@ -143,20 +141,17 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
|
||||
public void testSomethingToSend() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
TestSimplexTransportWriter transport = new TestSimplexTransportWriter(
|
||||
out, TransportConstants.MIN_CONNECTION_LENGTH, true);
|
||||
out, MIN_CONNECTION_LENGTH, true);
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
ConnectionContext ctx = new ConnectionContext(contactId, transportId,
|
||||
tag, secret, 0L, true);
|
||||
OutgoingSimplexConnection connection = new OutgoingSimplexConnection(db,
|
||||
connRegistry, connFactory, protoFactory, contactId, transportId,
|
||||
transportIndex, transport);
|
||||
final ConnectionContext ctx = context.mock(ConnectionContext.class);
|
||||
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];
|
||||
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));
|
||||
|
||||
@@ -23,7 +23,6 @@ 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;
|
||||
@@ -49,11 +48,12 @@ import com.google.inject.Injector;
|
||||
|
||||
public class SimplexConnectionReadWriteTest extends BriarTestCase {
|
||||
|
||||
// FIXME: This is an integration test, not a unit test
|
||||
|
||||
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;
|
||||
@@ -61,7 +61,6 @@ public class SimplexConnectionReadWriteTest extends BriarTestCase {
|
||||
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];
|
||||
@@ -102,7 +101,7 @@ public class SimplexConnectionReadWriteTest extends BriarTestCase {
|
||||
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);
|
||||
ContactId contactId = db.addContact();
|
||||
String subject = "Hello";
|
||||
byte[] body = "Hi Bob!".getBytes("UTF-8");
|
||||
MessageFactory messageFactory = alice.getInstance(MessageFactory.class);
|
||||
@@ -111,16 +110,19 @@ public class SimplexConnectionReadWriteTest extends BriarTestCase {
|
||||
// Create an outgoing batch connection
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ConnectionRegistry connRegistry =
|
||||
alice.getInstance(ConnectionRegistry.class);
|
||||
alice.getInstance(ConnectionRegistry.class);
|
||||
ConnectionWriterFactory connFactory =
|
||||
alice.getInstance(ConnectionWriterFactory.class);
|
||||
alice.getInstance(ConnectionWriterFactory.class);
|
||||
ProtocolWriterFactory protoFactory =
|
||||
alice.getInstance(ProtocolWriterFactory.class);
|
||||
alice.getInstance(ProtocolWriterFactory.class);
|
||||
TestSimplexTransportWriter transport = new TestSimplexTransportWriter(
|
||||
out, Long.MAX_VALUE, false);
|
||||
// FIXME: Encode the tag
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
ConnectionContext ctx = new ConnectionContext(contactId, transportId,
|
||||
tag, aliceToBobSecret, 0L, true);
|
||||
OutgoingSimplexConnection simplex = new OutgoingSimplexConnection(db,
|
||||
connRegistry, connFactory, protoFactory, contactId, transportId,
|
||||
transportIndex, transport);
|
||||
connRegistry, connFactory, protoFactory, ctx, transport);
|
||||
// Write whatever needs to be written
|
||||
simplex.write();
|
||||
assertTrue(transport.getDisposed());
|
||||
@@ -139,14 +141,12 @@ public class SimplexConnectionReadWriteTest extends BriarTestCase {
|
||||
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));
|
||||
ContactId contactId = db.addContact();
|
||||
// Fake a transport update from Alice
|
||||
TransportUpdate transportUpdate = new TransportUpdate() {
|
||||
|
||||
public Collection<Transport> getTransports() {
|
||||
Transport t = new Transport(transportId, transportIndex);
|
||||
Transport t = new Transport(transportId);
|
||||
return Collections.singletonList(t);
|
||||
}
|
||||
|
||||
@@ -164,19 +164,17 @@ public class SimplexConnectionReadWriteTest extends BriarTestCase {
|
||||
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);
|
||||
bob.getInstance(ConnectionRegistry.class);
|
||||
ConnectionReaderFactory connFactory =
|
||||
bob.getInstance(ConnectionReaderFactory.class);
|
||||
bob.getInstance(ConnectionReaderFactory.class);
|
||||
ProtocolReaderFactory protoFactory =
|
||||
bob.getInstance(ProtocolReaderFactory.class);
|
||||
bob.getInstance(ProtocolReaderFactory.class);
|
||||
TestSimplexTransportReader transport = new TestSimplexTransportReader(in);
|
||||
IncomingSimplexConnection simplex = new IncomingSimplexConnection(
|
||||
new ImmediateExecutor(), new ImmediateExecutor(), db,
|
||||
connRegistry, connFactory, protoFactory, ctx, transportId,
|
||||
transport);
|
||||
connRegistry, connFactory, protoFactory, ctx, transport);
|
||||
// No messages should have been added yet
|
||||
assertFalse(listener.messagesAdded);
|
||||
// Read whatever needs to be read
|
||||
|
||||
@@ -1,624 +0,0 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.TestUtils;
|
||||
import net.sf.briar.api.ContactId;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.db.DatabaseComponent;
|
||||
import net.sf.briar.api.db.event.ContactRemovedEvent;
|
||||
import net.sf.briar.api.db.event.RemoteTransportsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.TransportAddedEvent;
|
||||
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.transport.ConnectionContext;
|
||||
import net.sf.briar.api.transport.ConnectionWindow;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
import net.sf.briar.plugins.ImmediateExecutor;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
public class ConnectionRecogniserImplTest extends BriarTestCase {
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final ContactId contactId;
|
||||
private final byte[] inSecret;
|
||||
private final TransportId transportId;
|
||||
private final TransportIndex localIndex, remoteIndex;
|
||||
private final Collection<Transport> localTransports, remoteTransports;
|
||||
|
||||
public ConnectionRecogniserImplTest() {
|
||||
super();
|
||||
Injector i = Guice.createInjector(new CryptoModule());
|
||||
crypto = i.getInstance(CryptoComponent.class);
|
||||
contactId = new ContactId(1);
|
||||
inSecret = new byte[32];
|
||||
new Random().nextBytes(inSecret);
|
||||
transportId = new TransportId(TestUtils.getRandomId());
|
||||
localIndex = new TransportIndex(13);
|
||||
remoteIndex = new TransportIndex(7);
|
||||
Map<String, String> properties = Collections.singletonMap("foo", "bar");
|
||||
Transport localTransport = new Transport(transportId, localIndex,
|
||||
properties);
|
||||
localTransports = Collections.singletonList(localTransport);
|
||||
Transport remoteTransport = new Transport(transportId, remoteIndex,
|
||||
properties);
|
||||
remoteTransports = Collections.singletonList(remoteTransport);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnexpectedIv() throws Exception {
|
||||
final ConnectionWindow window = createConnectionWindow(remoteIndex);
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Initialise
|
||||
oneOf(db).addListener(with(any(ConnectionRecogniserImpl.class)));
|
||||
oneOf(db).getLocalTransports();
|
||||
will(returnValue(localTransports));
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||
will(returnValue(remoteIndex));
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
}});
|
||||
Executor executor = new ImmediateExecutor();
|
||||
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
|
||||
crypto);
|
||||
assertNull(c.acceptConnection(transportId, new byte[TAG_LENGTH]));
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpectedIv() throws Exception {
|
||||
final ConnectionWindow window = createConnectionWindow(remoteIndex);
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Initialise
|
||||
oneOf(db).addListener(with(any(ConnectionRecogniserImpl.class)));
|
||||
oneOf(db).getLocalTransports();
|
||||
will(returnValue(localTransports));
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||
will(returnValue(remoteIndex));
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
// Update the window
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
|
||||
}});
|
||||
Executor executor = new ImmediateExecutor();
|
||||
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
|
||||
crypto);
|
||||
byte[] tag = calculateTag();
|
||||
// The tag should not be expected by the wrong transport
|
||||
TransportId wrong = new TransportId(TestUtils.getRandomId());
|
||||
assertNull(c.acceptConnection(wrong, tag));
|
||||
// The tag should be expected by the right transport
|
||||
ConnectionContext ctx = c.acceptConnection(transportId, tag);
|
||||
assertNotNull(ctx);
|
||||
assertEquals(contactId, ctx.getContactId());
|
||||
assertEquals(remoteIndex, ctx.getTransportIndex());
|
||||
assertEquals(3, ctx.getConnectionNumber());
|
||||
// The tag should no longer be expected
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
// The window should have advanced
|
||||
Map<Long, byte[]> unseen = window.getUnseen();
|
||||
assertEquals(19, unseen.size());
|
||||
for(int i = 0; i < 19; i++) {
|
||||
assertEquals(i != 3, unseen.containsKey(Long.valueOf(i)));
|
||||
}
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContactRemovedAfterInit() throws Exception {
|
||||
final ConnectionWindow window = createConnectionWindow(remoteIndex);
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Initialise before removing contact
|
||||
oneOf(db).addListener(with(any(ConnectionRecogniserImpl.class)));
|
||||
oneOf(db).getLocalTransports();
|
||||
will(returnValue(localTransports));
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||
will(returnValue(remoteIndex));
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
}});
|
||||
Executor executor = new ImmediateExecutor();
|
||||
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
|
||||
crypto);
|
||||
byte[] tag = calculateTag();
|
||||
// Ensure the recogniser is initialised
|
||||
assertFalse(c.isInitialised());
|
||||
assertNull(c.acceptConnection(transportId, new byte[TAG_LENGTH]));
|
||||
assertTrue(c.isInitialised());
|
||||
// Remove the contact
|
||||
c.eventOccurred(new ContactRemovedEvent(contactId));
|
||||
// The tag should not be expected
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContactRemovedBeforeInit() throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Initialise after removing contact
|
||||
oneOf(db).addListener(with(any(ConnectionRecogniserImpl.class)));
|
||||
oneOf(db).getLocalTransports();
|
||||
will(returnValue(localTransports));
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.emptyList()));
|
||||
}});
|
||||
Executor executor = new ImmediateExecutor();
|
||||
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
|
||||
crypto);
|
||||
byte[] tag = calculateTag();
|
||||
// Remove the contact
|
||||
c.eventOccurred(new ContactRemovedEvent(contactId));
|
||||
// The tag should not be expected
|
||||
assertFalse(c.isInitialised());
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
assertTrue(c.isInitialised());
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalTransportAddedAfterInit() throws Exception {
|
||||
final ConnectionWindow window = createConnectionWindow(remoteIndex);
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Initialise before adding transport
|
||||
oneOf(db).addListener(with(any(ConnectionRecogniserImpl.class)));
|
||||
oneOf(db).getLocalTransports();
|
||||
will(returnValue(Collections.emptyList()));
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
// Add the transport
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||
will(returnValue(remoteIndex));
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
// Update the window
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
|
||||
}});
|
||||
Executor executor = new ImmediateExecutor();
|
||||
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
|
||||
crypto);
|
||||
byte[] tag = calculateTag();
|
||||
// The tag should not be expected
|
||||
assertFalse(c.isInitialised());
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
assertTrue(c.isInitialised());
|
||||
// Add the transport
|
||||
c.eventOccurred(new TransportAddedEvent(transportId));
|
||||
// The tag should be expected
|
||||
ConnectionContext ctx = c.acceptConnection(transportId, tag);
|
||||
assertNotNull(ctx);
|
||||
assertEquals(contactId, ctx.getContactId());
|
||||
assertEquals(remoteIndex, ctx.getTransportIndex());
|
||||
assertEquals(3, ctx.getConnectionNumber());
|
||||
// The tag should no longer be expected
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
// The window should have advanced
|
||||
Map<Long, byte[]> unseen = window.getUnseen();
|
||||
assertEquals(19, unseen.size());
|
||||
for(int i = 0; i < 19; i++) {
|
||||
assertEquals(i != 3, unseen.containsKey(Long.valueOf(i)));
|
||||
}
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalTransportAddedBeforeInit() throws Exception {
|
||||
final ConnectionWindow window = createConnectionWindow(remoteIndex);
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Initialise after adding transport
|
||||
oneOf(db).addListener(with(any(ConnectionRecogniserImpl.class)));
|
||||
oneOf(db).getLocalTransports();
|
||||
will(returnValue(localTransports));
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||
will(returnValue(remoteIndex));
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
// Update the window
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
|
||||
}});
|
||||
Executor executor = new ImmediateExecutor();
|
||||
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
|
||||
crypto);
|
||||
byte[] tag = calculateTag();
|
||||
// Add the transport
|
||||
c.eventOccurred(new TransportAddedEvent(transportId));
|
||||
// The tag should be expected
|
||||
assertFalse(c.isInitialised());
|
||||
ConnectionContext ctx = c.acceptConnection(transportId, tag);
|
||||
assertTrue(c.isInitialised());
|
||||
assertNotNull(ctx);
|
||||
assertEquals(contactId, ctx.getContactId());
|
||||
assertEquals(remoteIndex, ctx.getTransportIndex());
|
||||
assertEquals(3, ctx.getConnectionNumber());
|
||||
// The tag should no longer be expected
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
// The window should have advanced
|
||||
Map<Long, byte[]> unseen = window.getUnseen();
|
||||
assertEquals(19, unseen.size());
|
||||
for(int i = 0; i < 19; i++) {
|
||||
assertEquals(i != 3, unseen.containsKey(Long.valueOf(i)));
|
||||
}
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoteTransportAddedAfterInit() throws Exception {
|
||||
final ConnectionWindow window = createConnectionWindow(remoteIndex);
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Initialise before updating the contact
|
||||
oneOf(db).addListener(with(any(ConnectionRecogniserImpl.class)));
|
||||
oneOf(db).getLocalTransports();
|
||||
will(returnValue(localTransports));
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||
will(returnValue(null));
|
||||
// Update the contact
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
// Update the window
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
|
||||
}});
|
||||
Executor executor = new ImmediateExecutor();
|
||||
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
|
||||
crypto);
|
||||
byte[] tag = calculateTag();
|
||||
// The tag should not be expected
|
||||
assertFalse(c.isInitialised());
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
assertTrue(c.isInitialised());
|
||||
// Update the contact
|
||||
c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
|
||||
remoteTransports));
|
||||
// The tag should be expected
|
||||
ConnectionContext ctx = c.acceptConnection(transportId, tag);
|
||||
assertNotNull(ctx);
|
||||
assertEquals(contactId, ctx.getContactId());
|
||||
assertEquals(remoteIndex, ctx.getTransportIndex());
|
||||
assertEquals(3, ctx.getConnectionNumber());
|
||||
// The tag should no longer be expected
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
// The window should have advanced
|
||||
Map<Long, byte[]> unseen = window.getUnseen();
|
||||
assertEquals(19, unseen.size());
|
||||
for(int i = 0; i < 19; i++) {
|
||||
assertEquals(i != 3, unseen.containsKey(Long.valueOf(i)));
|
||||
}
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoteTransportAddedBeforeInit() throws Exception {
|
||||
final ConnectionWindow window = createConnectionWindow(remoteIndex);
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Initialise after updating the contact
|
||||
oneOf(db).addListener(with(any(ConnectionRecogniserImpl.class)));
|
||||
oneOf(db).getLocalTransports();
|
||||
will(returnValue(localTransports));
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||
will(returnValue(remoteIndex));
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
// Update the window
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
|
||||
}});
|
||||
Executor executor = new ImmediateExecutor();
|
||||
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
|
||||
crypto);
|
||||
byte[] tag = calculateTag();
|
||||
// Update the contact
|
||||
c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
|
||||
remoteTransports));
|
||||
// The tag should be expected
|
||||
assertFalse(c.isInitialised());
|
||||
ConnectionContext ctx = c.acceptConnection(transportId, tag);
|
||||
assertTrue(c.isInitialised());
|
||||
assertNotNull(ctx);
|
||||
assertEquals(contactId, ctx.getContactId());
|
||||
assertEquals(remoteIndex, ctx.getTransportIndex());
|
||||
assertEquals(3, ctx.getConnectionNumber());
|
||||
// The tag should no longer be expected
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
// The window should have advanced
|
||||
Map<Long, byte[]> unseen = window.getUnseen();
|
||||
assertEquals(19, unseen.size());
|
||||
for(int i = 0; i < 19; i++) {
|
||||
assertEquals(i != 3, unseen.containsKey(Long.valueOf(i)));
|
||||
}
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoteTransportRemovedAfterInit() throws Exception {
|
||||
final ConnectionWindow window = createConnectionWindow(remoteIndex);
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Initialise before updating the contact
|
||||
oneOf(db).addListener(with(any(ConnectionRecogniserImpl.class)));
|
||||
oneOf(db).getLocalTransports();
|
||||
will(returnValue(localTransports));
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||
will(returnValue(remoteIndex));
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
}});
|
||||
Executor executor = new ImmediateExecutor();
|
||||
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
|
||||
crypto);
|
||||
byte[] tag = calculateTag();
|
||||
// Ensure the recogniser is initialised
|
||||
assertFalse(c.isInitialised());
|
||||
assertNull(c.acceptConnection(transportId, new byte[TAG_LENGTH]));
|
||||
assertTrue(c.isInitialised());
|
||||
// Update the contact
|
||||
c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
|
||||
Collections.<Transport>emptyList()));
|
||||
// The tag should not be expected
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoteTransportRemovedBeforeInit() throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Initialise after updating the contact
|
||||
oneOf(db).addListener(with(any(ConnectionRecogniserImpl.class)));
|
||||
oneOf(db).getLocalTransports();
|
||||
will(returnValue(localTransports));
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||
will(returnValue(null));
|
||||
}});
|
||||
Executor executor = new ImmediateExecutor();
|
||||
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
|
||||
crypto);
|
||||
byte[] tag = calculateTag();
|
||||
// Update the contact
|
||||
c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
|
||||
Collections.<Transport>emptyList()));
|
||||
// The tag should not be expected
|
||||
assertFalse(c.isInitialised());
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
assertTrue(c.isInitialised());
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoteTransportIndexChangedAfterInit() throws Exception {
|
||||
// The contact changes the transport ID <-> index relationships
|
||||
final TransportId transportId1 =
|
||||
new TransportId(TestUtils.getRandomId());
|
||||
final TransportIndex remoteIndex1 = new TransportIndex(11);
|
||||
Map<String, String> properties = Collections.singletonMap("foo", "bar");
|
||||
Transport remoteTransport = new Transport(transportId, remoteIndex1,
|
||||
properties);
|
||||
Transport remoteTransport1 = new Transport(transportId1, remoteIndex,
|
||||
properties);
|
||||
Collection<Transport> remoteTransports1 = Arrays.asList(
|
||||
new Transport[] {remoteTransport, remoteTransport1});
|
||||
// Use two local transports for this test
|
||||
TransportIndex localIndex1 = new TransportIndex(17);
|
||||
Transport localTransport = new Transport(transportId, localIndex,
|
||||
properties);
|
||||
Transport localTransport1 = new Transport(transportId1, localIndex1,
|
||||
properties);
|
||||
final Collection<Transport> localTransports1 = Arrays.asList(
|
||||
new Transport[] {localTransport, localTransport1});
|
||||
|
||||
final ConnectionWindow window = createConnectionWindow(remoteIndex);
|
||||
final ConnectionWindow window1 = createConnectionWindow(remoteIndex1);
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Initialise before updating the contact
|
||||
oneOf(db).addListener(with(any(ConnectionRecogniserImpl.class)));
|
||||
oneOf(db).getLocalTransports();
|
||||
will(returnValue(localTransports1));
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
// First, transportId <-> remoteIndex, transportId1 <-> remoteIndex
|
||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||
will(returnValue(remoteIndex));
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
oneOf(db).getRemoteIndex(contactId, transportId1);
|
||||
will(returnValue(remoteIndex1));
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex1);
|
||||
will(returnValue(window1));
|
||||
// Later, transportId <-> remoteIndex1, transportId1 <-> remoteIndex
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex1);
|
||||
will(returnValue(window1));
|
||||
// Update the window
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
|
||||
}});
|
||||
Executor executor = new ImmediateExecutor();
|
||||
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
|
||||
crypto);
|
||||
byte[] tag = calculateTag();
|
||||
// Ensure the recogniser is initialised
|
||||
assertFalse(c.isInitialised());
|
||||
assertNull(c.acceptConnection(transportId, new byte[TAG_LENGTH]));
|
||||
assertTrue(c.isInitialised());
|
||||
// Update the contact
|
||||
c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
|
||||
remoteTransports1));
|
||||
// The tag should not be expected by the old transport
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
// The tag should be expected by the new transport
|
||||
ConnectionContext ctx = c.acceptConnection(transportId1, tag);
|
||||
assertNotNull(ctx);
|
||||
assertEquals(contactId, ctx.getContactId());
|
||||
assertEquals(remoteIndex, ctx.getTransportIndex());
|
||||
assertEquals(3, ctx.getConnectionNumber());
|
||||
// The tag should no longer be expected
|
||||
assertNull(c.acceptConnection(transportId1, tag));
|
||||
// The window should have advanced
|
||||
Map<Long, byte[]> unseen = window.getUnseen();
|
||||
assertEquals(19, unseen.size());
|
||||
for(int i = 0; i < 19; i++) {
|
||||
assertEquals(i != 3, unseen.containsKey(Long.valueOf(i)));
|
||||
}
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoteTransportIndexChangedBeforeInit() throws Exception {
|
||||
// The contact changes the transport ID <-> index relationships
|
||||
final TransportId transportId1 =
|
||||
new TransportId(TestUtils.getRandomId());
|
||||
final TransportIndex remoteIndex1 = new TransportIndex(11);
|
||||
Map<String, String> properties = Collections.singletonMap("foo", "bar");
|
||||
Transport remoteTransport = new Transport(transportId, remoteIndex1,
|
||||
properties);
|
||||
Transport remoteTransport1 = new Transport(transportId1, remoteIndex,
|
||||
properties);
|
||||
Collection<Transport> remoteTransports1 = Arrays.asList(
|
||||
new Transport[] {remoteTransport, remoteTransport1});
|
||||
// Use two local transports for this test
|
||||
TransportIndex localIndex1 = new TransportIndex(17);
|
||||
Transport localTransport = new Transport(transportId, localIndex,
|
||||
properties);
|
||||
Transport localTransport1 = new Transport(transportId1, localIndex1,
|
||||
properties);
|
||||
final Collection<Transport> localTransports1 = Arrays.asList(
|
||||
new Transport[] {localTransport, localTransport1});
|
||||
|
||||
final ConnectionWindow window = createConnectionWindow(remoteIndex);
|
||||
final ConnectionWindow window1 = createConnectionWindow(remoteIndex1);
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Initialise after updating the contact
|
||||
oneOf(db).addListener(with(any(ConnectionRecogniserImpl.class)));
|
||||
oneOf(db).getLocalTransports();
|
||||
will(returnValue(localTransports1));
|
||||
oneOf(db).getContacts();
|
||||
will(returnValue(Collections.singletonList(contactId)));
|
||||
// First, transportId <-> remoteIndex1, transportId1 <-> remoteIndex
|
||||
oneOf(db).getRemoteIndex(contactId, transportId);
|
||||
will(returnValue(remoteIndex1));
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex1);
|
||||
will(returnValue(window1));
|
||||
oneOf(db).getRemoteIndex(contactId, transportId1);
|
||||
will(returnValue(remoteIndex));
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
// Update the window
|
||||
oneOf(db).getConnectionWindow(contactId, remoteIndex);
|
||||
will(returnValue(window));
|
||||
oneOf(db).setConnectionWindow(contactId, remoteIndex, window);
|
||||
}});
|
||||
Executor executor = new ImmediateExecutor();
|
||||
ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(executor, db,
|
||||
crypto);
|
||||
byte[] tag = calculateTag();
|
||||
// Update the contact
|
||||
c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
|
||||
remoteTransports1));
|
||||
// The tag should not be expected by the old transport
|
||||
assertFalse(c.isInitialised());
|
||||
assertNull(c.acceptConnection(transportId, tag));
|
||||
assertTrue(c.isInitialised());
|
||||
// The tag should be expected by the new transport
|
||||
ConnectionContext ctx = c.acceptConnection(transportId1, tag);
|
||||
assertNotNull(ctx);
|
||||
assertEquals(contactId, ctx.getContactId());
|
||||
assertEquals(remoteIndex, ctx.getTransportIndex());
|
||||
assertEquals(3, ctx.getConnectionNumber());
|
||||
// The tag should no longer be expected
|
||||
assertNull(c.acceptConnection(transportId1, tag));
|
||||
// The window should have advanced
|
||||
Map<Long, byte[]> unseen = window.getUnseen();
|
||||
assertEquals(19, unseen.size());
|
||||
for(int i = 0; i < 19; i++) {
|
||||
assertEquals(i != 3, unseen.containsKey(Long.valueOf(i)));
|
||||
}
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
private ConnectionWindow createConnectionWindow(TransportIndex index) {
|
||||
return new ConnectionWindowImpl(crypto, index, inSecret) {
|
||||
@Override
|
||||
public void erase() {}
|
||||
};
|
||||
}
|
||||
|
||||
private byte[] calculateTag() throws Exception {
|
||||
// Calculate the shared secret for connection number 3
|
||||
byte[] secret = inSecret;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
secret = crypto.deriveNextSecret(secret, remoteIndex.getInt(), i);
|
||||
}
|
||||
// Calculate the expected tag for connection number 3
|
||||
ErasableKey tagKey = crypto.deriveTagKey(secret, true);
|
||||
Cipher tagCipher = crypto.getTagCipher();
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
TagEncoder.encodeTag(tag, tagCipher, tagKey);
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,19 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.protocol.TransportIndex;
|
||||
import net.sf.briar.api.transport.ConnectionWindow;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
public class ConnectionWindowImplTest extends BriarTestCase {
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final byte[] secret;
|
||||
private final TransportIndex transportIndex = new TransportIndex(13);
|
||||
|
||||
public ConnectionWindowImplTest() {
|
||||
super();
|
||||
Injector i = Guice.createInjector(new CryptoModule());
|
||||
crypto = i.getInstance(CryptoComponent.class);
|
||||
secret = new byte[32];
|
||||
new Random().nextBytes(secret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWindowSliding() {
|
||||
ConnectionWindow w = new ConnectionWindowImpl(crypto,
|
||||
transportIndex, secret);
|
||||
ConnectionWindow w = new ConnectionWindowImpl();
|
||||
for(int i = 0; i < 100; i++) {
|
||||
assertFalse(w.isSeen(i));
|
||||
w.setSeen(i);
|
||||
@@ -43,8 +23,7 @@ public class ConnectionWindowImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testWindowJumping() {
|
||||
ConnectionWindow w = new ConnectionWindowImpl(crypto, transportIndex,
|
||||
secret);
|
||||
ConnectionWindow w = new ConnectionWindowImpl();
|
||||
for(int i = 0; i < 100; i += 13) {
|
||||
assertFalse(w.isSeen(i));
|
||||
w.setSeen(i);
|
||||
@@ -54,8 +33,7 @@ public class ConnectionWindowImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testWindowUpperLimit() {
|
||||
ConnectionWindow w = new ConnectionWindowImpl(crypto, transportIndex,
|
||||
secret);
|
||||
ConnectionWindow w = new ConnectionWindowImpl();
|
||||
// Centre is 0, highest value in window is 15
|
||||
w.setSeen(15);
|
||||
// Centre is 16, highest value in window is 31
|
||||
@@ -66,11 +44,11 @@ public class ConnectionWindowImplTest extends BriarTestCase {
|
||||
fail();
|
||||
} catch(IllegalArgumentException expected) {}
|
||||
// Values greater than 2^32 - 1 should never be allowed
|
||||
Map<Long, byte[]> unseen = new HashMap<Long, byte[]>();
|
||||
Set<Long> unseen = new HashSet<Long>();
|
||||
for(int i = 0; i < 32; i++) {
|
||||
unseen.put(ByteUtils.MAX_32_BIT_UNSIGNED - i, secret);
|
||||
unseen.add(ByteUtils.MAX_32_BIT_UNSIGNED - i);
|
||||
}
|
||||
w = new ConnectionWindowImpl(crypto, transportIndex, unseen);
|
||||
w = new ConnectionWindowImpl(unseen);
|
||||
w.setSeen(ByteUtils.MAX_32_BIT_UNSIGNED);
|
||||
try {
|
||||
w.setSeen(ByteUtils.MAX_32_BIT_UNSIGNED + 1);
|
||||
@@ -80,8 +58,7 @@ public class ConnectionWindowImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testWindowLowerLimit() {
|
||||
ConnectionWindow w = new ConnectionWindowImpl(crypto, transportIndex,
|
||||
secret);
|
||||
ConnectionWindow w = new ConnectionWindowImpl();
|
||||
// Centre is 0, negative values should never be allowed
|
||||
try {
|
||||
w.setSeen(-1);
|
||||
@@ -111,8 +88,7 @@ public class ConnectionWindowImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testCannotSetSeenTwice() {
|
||||
ConnectionWindow w = new ConnectionWindowImpl(crypto, transportIndex,
|
||||
secret);
|
||||
ConnectionWindow w = new ConnectionWindowImpl();
|
||||
w.setSeen(15);
|
||||
try {
|
||||
w.setSeen(15);
|
||||
@@ -122,13 +98,12 @@ public class ConnectionWindowImplTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testGetUnseenConnectionNumbers() {
|
||||
ConnectionWindow w = new ConnectionWindowImpl(crypto, transportIndex,
|
||||
secret);
|
||||
ConnectionWindow w = new ConnectionWindowImpl();
|
||||
// Centre is 0; window should cover 0 to 15, inclusive, with none seen
|
||||
Map<Long, byte[]> unseen = w.getUnseen();
|
||||
Set<Long> unseen = w.getUnseen();
|
||||
assertEquals(16, unseen.size());
|
||||
for(int i = 0; i < 16; i++) {
|
||||
assertTrue(unseen.containsKey(Long.valueOf(i)));
|
||||
assertTrue(unseen.contains(Long.valueOf(i)));
|
||||
assertFalse(w.isSeen(i));
|
||||
}
|
||||
w.setSeen(3);
|
||||
@@ -138,10 +113,10 @@ public class ConnectionWindowImplTest extends BriarTestCase {
|
||||
assertEquals(19, unseen.size());
|
||||
for(int i = 0; i < 21; i++) {
|
||||
if(i == 3 || i == 4) {
|
||||
assertFalse(unseen.containsKey(Long.valueOf(i)));
|
||||
assertFalse(unseen.contains(Long.valueOf(i)));
|
||||
assertTrue(w.isSeen(i));
|
||||
} else {
|
||||
assertTrue(unseen.containsKey(Long.valueOf(i)));
|
||||
assertTrue(unseen.contains(Long.valueOf(i)));
|
||||
assertFalse(w.isSeen(i));
|
||||
}
|
||||
}
|
||||
@@ -151,10 +126,10 @@ public class ConnectionWindowImplTest extends BriarTestCase {
|
||||
assertEquals(30, unseen.size());
|
||||
for(int i = 4; i < 36; i++) {
|
||||
if(i == 4 || i == 19) {
|
||||
assertFalse(unseen.containsKey(Long.valueOf(i)));
|
||||
assertFalse(unseen.contains(Long.valueOf(i)));
|
||||
assertTrue(w.isSeen(i));
|
||||
} else {
|
||||
assertTrue(unseen.containsKey(Long.valueOf(i)));
|
||||
assertTrue(unseen.contains(Long.valueOf(i)));
|
||||
assertFalse(w.isSeen(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,17 @@ package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.MIN_CONNECTION_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
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.protocol.TransportId;
|
||||
import net.sf.briar.api.transport.ConnectionContext;
|
||||
import net.sf.briar.api.transport.ConnectionWriter;
|
||||
import net.sf.briar.api.transport.ConnectionWriterFactory;
|
||||
import net.sf.briar.clock.ClockModule;
|
||||
@@ -27,6 +32,8 @@ import com.google.inject.Injector;
|
||||
public class ConnectionWriterTest extends BriarTestCase {
|
||||
|
||||
private final ConnectionWriterFactory connectionWriterFactory;
|
||||
private final ContactId contactId;
|
||||
private final TransportId transportId;
|
||||
private final byte[] secret;
|
||||
|
||||
public ConnectionWriterTest() throws Exception {
|
||||
@@ -37,6 +44,8 @@ public class ConnectionWriterTest extends BriarTestCase {
|
||||
new TestDatabaseModule(), new SimplexProtocolModule(),
|
||||
new TransportModule(), new DuplexProtocolModule());
|
||||
connectionWriterFactory = i.getInstance(ConnectionWriterFactory.class);
|
||||
contactId = new ContactId(234);
|
||||
transportId = new TransportId(TestUtils.getRandomId());
|
||||
secret = new byte[32];
|
||||
new Random().nextBytes(secret);
|
||||
}
|
||||
@@ -44,9 +53,12 @@ public class ConnectionWriterTest extends BriarTestCase {
|
||||
@Test
|
||||
public void testOverheadWithTag() throws Exception {
|
||||
ByteArrayOutputStream out =
|
||||
new ByteArrayOutputStream(MIN_CONNECTION_LENGTH);
|
||||
new ByteArrayOutputStream(MIN_CONNECTION_LENGTH);
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
ConnectionContext ctx = new ConnectionContext(contactId, transportId,
|
||||
tag, secret, 0L, true);
|
||||
ConnectionWriter w = connectionWriterFactory.createConnectionWriter(out,
|
||||
MIN_CONNECTION_LENGTH, secret, true);
|
||||
MIN_CONNECTION_LENGTH, ctx, true);
|
||||
// Check that the connection writer thinks there's room for a packet
|
||||
long capacity = w.getRemainingCapacity();
|
||||
assertTrue(capacity > MAX_PACKET_LENGTH);
|
||||
@@ -63,9 +75,11 @@ public class ConnectionWriterTest extends BriarTestCase {
|
||||
@Test
|
||||
public void testOverheadWithoutTag() throws Exception {
|
||||
ByteArrayOutputStream out =
|
||||
new ByteArrayOutputStream(MIN_CONNECTION_LENGTH);
|
||||
new ByteArrayOutputStream(MIN_CONNECTION_LENGTH);
|
||||
ConnectionContext ctx = new ConnectionContext(contactId, transportId,
|
||||
null, secret, 0L, true);
|
||||
ConnectionWriter w = connectionWriterFactory.createConnectionWriter(out,
|
||||
MIN_CONNECTION_LENGTH, secret, false);
|
||||
MIN_CONNECTION_LENGTH, ctx, false);
|
||||
// Check that the connection writer thinks there's room for a packet
|
||||
long capacity = w.getRemainingCapacity();
|
||||
assertTrue(capacity > MAX_PACKET_LENGTH);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -9,8 +8,6 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.crypto.AuthenticatedCipher;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
@@ -29,24 +26,21 @@ public class FrameReadWriteTest extends BriarTestCase {
|
||||
private final int FRAME_LENGTH = 2048;
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final Cipher tagCipher;
|
||||
private final AuthenticatedCipher frameCipher;
|
||||
private final Random random;
|
||||
private final byte[] outSecret;
|
||||
private final ErasableKey tagKey, frameKey;
|
||||
private final ErasableKey frameKey;
|
||||
|
||||
public FrameReadWriteTest() {
|
||||
super();
|
||||
Injector i = Guice.createInjector(new CryptoModule());
|
||||
crypto = i.getInstance(CryptoComponent.class);
|
||||
tagCipher = crypto.getTagCipher();
|
||||
frameCipher = crypto.getFrameCipher();
|
||||
random = new Random();
|
||||
// Since we're sending frames to ourselves, we only need outgoing keys
|
||||
outSecret = new byte[32];
|
||||
random.nextBytes(outSecret);
|
||||
tagKey = crypto.deriveTagKey(outSecret, true);
|
||||
frameKey = crypto.deriveFrameKey(outSecret, true);
|
||||
frameKey = crypto.deriveFrameKey(outSecret, 0L, true, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,22 +54,17 @@ public class FrameReadWriteTest extends BriarTestCase {
|
||||
}
|
||||
|
||||
private void testWriteAndRead(boolean initiator) throws Exception {
|
||||
// Encode the tag
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
TagEncoder.encodeTag(tag, tagCipher, tagKey);
|
||||
// Generate two random frames
|
||||
byte[] frame = new byte[1234];
|
||||
random.nextBytes(frame);
|
||||
byte[] frame1 = new byte[321];
|
||||
random.nextBytes(frame1);
|
||||
// Copy the keys - the copies will be erased
|
||||
ErasableKey tagCopy = tagKey.copy();
|
||||
// Copy the frame key - the copy will be erased
|
||||
ErasableKey frameCopy = frameKey.copy();
|
||||
// Write the frames
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
FrameWriter encryptionOut = new OutgoingEncryptionLayer(out,
|
||||
Long.MAX_VALUE, tagCipher, frameCipher, tagCopy, frameCopy,
|
||||
FRAME_LENGTH);
|
||||
Long.MAX_VALUE, frameCipher, frameCopy, FRAME_LENGTH);
|
||||
ConnectionWriter writer = new ConnectionWriterImpl(encryptionOut,
|
||||
FRAME_LENGTH);
|
||||
OutputStream out1 = writer.getOutputStream();
|
||||
@@ -84,11 +73,11 @@ public class FrameReadWriteTest extends BriarTestCase {
|
||||
out1.write(frame1);
|
||||
out1.flush();
|
||||
byte[] output = out.toByteArray();
|
||||
assertEquals(TAG_LENGTH + FRAME_LENGTH * 2, output.length);
|
||||
assertEquals(FRAME_LENGTH * 2, output.length);
|
||||
// Read the tag and the frames back
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(output);
|
||||
FrameReader encryptionIn = new IncomingEncryptionLayer(in, tagCipher,
|
||||
frameCipher, tagKey, frameKey, FRAME_LENGTH);
|
||||
FrameReader encryptionIn = new IncomingEncryptionLayer(in, frameCipher,
|
||||
frameKey, FRAME_LENGTH);
|
||||
ConnectionReader reader = new ConnectionReaderImpl(encryptionIn,
|
||||
FRAME_LENGTH);
|
||||
InputStream in1 = reader.getInputStream();
|
||||
|
||||
@@ -5,12 +5,8 @@ import static net.sf.briar.api.transport.TransportConstants.AAD_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.HEADER_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.EOFException;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.FormatException;
|
||||
@@ -19,7 +15,6 @@ import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
@@ -32,99 +27,46 @@ public class IncomingEncryptionLayerTest extends BriarTestCase {
|
||||
FRAME_LENGTH - HEADER_LENGTH - MAC_LENGTH;
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final Cipher tagCipher;
|
||||
private final AuthenticatedCipher frameCipher;
|
||||
|
||||
private ErasableKey tagKey = null, frameKey = null;
|
||||
private final ErasableKey frameKey;
|
||||
|
||||
public IncomingEncryptionLayerTest() {
|
||||
super();
|
||||
Injector i = Guice.createInjector(new CryptoModule());
|
||||
crypto = i.getInstance(CryptoComponent.class);
|
||||
tagCipher = crypto.getTagCipher();
|
||||
frameCipher = crypto.getFrameCipher();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
tagKey = crypto.generateTestKey();
|
||||
frameKey = crypto.generateTestKey();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadValidTagAndFrames() throws Exception {
|
||||
// Generate a valid tag
|
||||
byte[] tag = generateTag(tagKey);
|
||||
public void testReadValidFrames() throws Exception {
|
||||
// Generate two valid frames
|
||||
byte[] frame = generateFrame(0L, FRAME_LENGTH, 123, false, false);
|
||||
byte[] frame1 = generateFrame(1L, FRAME_LENGTH, 123, false, false);
|
||||
// Concatenate the tag and the frames
|
||||
byte[] valid = new byte[TAG_LENGTH + FRAME_LENGTH * 2];
|
||||
System.arraycopy(tag, 0, valid, 0, TAG_LENGTH);
|
||||
System.arraycopy(frame, 0, valid, TAG_LENGTH, FRAME_LENGTH);
|
||||
System.arraycopy(frame1, 0, valid, TAG_LENGTH + FRAME_LENGTH,
|
||||
FRAME_LENGTH);
|
||||
// Read the frames, which should first read the tag
|
||||
// Concatenate the frames
|
||||
byte[] valid = new byte[FRAME_LENGTH * 2];
|
||||
System.arraycopy(frame, 0, valid, 0, FRAME_LENGTH);
|
||||
System.arraycopy(frame1, 0, valid, FRAME_LENGTH, FRAME_LENGTH);
|
||||
// Read the frames
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(valid);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, tagCipher,
|
||||
frameCipher, tagKey, frameKey, FRAME_LENGTH);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, frameCipher,
|
||||
frameKey, FRAME_LENGTH);
|
||||
byte[] buf = new byte[FRAME_LENGTH - MAC_LENGTH];
|
||||
assertEquals(123, i.readFrame(buf));
|
||||
assertEquals(123, i.readFrame(buf));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruncatedTagThrowsException() throws Exception {
|
||||
// Generate a valid tag
|
||||
byte[] tag = generateTag(tagKey);
|
||||
// Chop off the last byte
|
||||
byte[] truncated = new byte[TAG_LENGTH - 1];
|
||||
System.arraycopy(tag, 0, truncated, 0, TAG_LENGTH - 1);
|
||||
// Try to read the frame, which should first try to read the tag
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(truncated);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, tagCipher,
|
||||
frameCipher, tagKey, crypto.generateTestKey(), FRAME_LENGTH);
|
||||
try {
|
||||
i.readFrame(new byte[FRAME_LENGTH - MAC_LENGTH]);
|
||||
fail();
|
||||
} catch(EOFException expected) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruncatedFrameThrowsException() throws Exception {
|
||||
// Generate a valid tag
|
||||
byte[] tag = generateTag(tagKey);
|
||||
// Generate a valid frame
|
||||
byte[] frame = generateFrame(0L, FRAME_LENGTH, 123, false, false);
|
||||
// Chop off the last byte
|
||||
byte[] truncated = new byte[TAG_LENGTH + FRAME_LENGTH - 1];
|
||||
System.arraycopy(tag, 0, truncated, 0, TAG_LENGTH);
|
||||
System.arraycopy(frame, 0, truncated, TAG_LENGTH, FRAME_LENGTH - 1);
|
||||
byte[] truncated = new byte[FRAME_LENGTH - 1];
|
||||
System.arraycopy(frame, 0, truncated, 0, FRAME_LENGTH - 1);
|
||||
// Try to read the frame, which should fail due to truncation
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(truncated);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, tagCipher,
|
||||
frameCipher, tagKey, frameKey, FRAME_LENGTH);
|
||||
try {
|
||||
i.readFrame(new byte[FRAME_LENGTH - MAC_LENGTH]);
|
||||
fail();
|
||||
} catch(FormatException expected) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModifiedTagThrowsException() throws Exception {
|
||||
// Generate a valid tag
|
||||
byte[] tag = generateTag(tagKey);
|
||||
// Generate a valid frame
|
||||
byte[] frame = generateFrame(0L, FRAME_LENGTH, 123, false, false);
|
||||
// Modify a randomly chosen byte of the tag
|
||||
byte[] modified = new byte[TAG_LENGTH + FRAME_LENGTH];
|
||||
System.arraycopy(tag, 0, modified, 0, TAG_LENGTH);
|
||||
System.arraycopy(frame, 0, modified, TAG_LENGTH, FRAME_LENGTH);
|
||||
modified[(int) (Math.random() * TAG_LENGTH)] ^= 1;
|
||||
// Try to read the frame, which should fail due to modification
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(modified);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, tagCipher,
|
||||
frameCipher, tagKey, frameKey, FRAME_LENGTH);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, frameCipher,
|
||||
frameKey, FRAME_LENGTH);
|
||||
try {
|
||||
i.readFrame(new byte[FRAME_LENGTH - MAC_LENGTH]);
|
||||
fail();
|
||||
@@ -133,19 +75,14 @@ public class IncomingEncryptionLayerTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testModifiedFrameThrowsException() throws Exception {
|
||||
// Generate a valid tag
|
||||
byte[] tag = generateTag(tagKey);
|
||||
// Generate a valid frame
|
||||
byte[] frame = generateFrame(0L, FRAME_LENGTH, 123, false, false);
|
||||
// Modify a randomly chosen byte of the frame
|
||||
byte[] modified = new byte[TAG_LENGTH + FRAME_LENGTH];
|
||||
System.arraycopy(tag, 0, modified, 0, TAG_LENGTH);
|
||||
System.arraycopy(frame, 0, modified, TAG_LENGTH, FRAME_LENGTH);
|
||||
modified[TAG_LENGTH + (int) (Math.random() * FRAME_LENGTH)] ^= 1;
|
||||
frame[(int) (Math.random() * FRAME_LENGTH)] ^= 1;
|
||||
// Try to read the frame, which should fail due to modification
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(modified);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, tagCipher,
|
||||
frameCipher, tagKey, frameKey, FRAME_LENGTH);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, frameCipher,
|
||||
frameKey, FRAME_LENGTH);
|
||||
try {
|
||||
i.readFrame(new byte[FRAME_LENGTH - MAC_LENGTH]);
|
||||
fail();
|
||||
@@ -154,18 +91,12 @@ public class IncomingEncryptionLayerTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testShortNonFinalFrameThrowsException() throws Exception {
|
||||
// Generate a valid tag
|
||||
byte[] tag = generateTag(tagKey);
|
||||
// Generate a short non-final frame
|
||||
byte[] frame = generateFrame(0L, FRAME_LENGTH - 1, 123, false, false);
|
||||
// Concatenate the tag and the frame
|
||||
byte[] tooShort = new byte[TAG_LENGTH + FRAME_LENGTH - 1];
|
||||
System.arraycopy(tag, 0, tooShort, 0, TAG_LENGTH);
|
||||
System.arraycopy(frame, 0, tooShort, TAG_LENGTH, FRAME_LENGTH - 1);
|
||||
// Try to read the frame, which should fail due to invalid length
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(tooShort);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, tagCipher,
|
||||
frameCipher, tagKey, frameKey, FRAME_LENGTH);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, frameCipher,
|
||||
frameKey, FRAME_LENGTH);
|
||||
try {
|
||||
i.readFrame(new byte[FRAME_LENGTH - MAC_LENGTH]);
|
||||
fail();
|
||||
@@ -174,37 +105,25 @@ public class IncomingEncryptionLayerTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testShortFinalFrameDoesNotThrowException() throws Exception {
|
||||
// Generate a valid tag
|
||||
byte[] tag = generateTag(tagKey);
|
||||
// Generate a short final frame
|
||||
byte[] frame = generateFrame(0L, FRAME_LENGTH - 1, 123, true, false);
|
||||
// Concatenate the tag and the frame
|
||||
byte[] valid = new byte[TAG_LENGTH + FRAME_LENGTH - 1];
|
||||
System.arraycopy(tag, 0, valid, 0, TAG_LENGTH);
|
||||
System.arraycopy(frame, 0, valid, TAG_LENGTH, FRAME_LENGTH - 1);
|
||||
// Read the frame, which should first read the tag
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(valid);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, tagCipher,
|
||||
frameCipher, tagKey, frameKey, FRAME_LENGTH);
|
||||
// Read the frame
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, frameCipher,
|
||||
frameKey, FRAME_LENGTH);
|
||||
int length = i.readFrame(new byte[FRAME_LENGTH - MAC_LENGTH]);
|
||||
assertEquals(123, length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidPayloadLengthThrowsException() throws Exception {
|
||||
// Generate a valid tag
|
||||
byte[] tag = generateTag(tagKey);
|
||||
// Generate a frame with an invalid payload length
|
||||
byte[] frame = generateFrame(0L, FRAME_LENGTH, MAX_PAYLOAD_LENGTH + 1,
|
||||
false, false);
|
||||
// Concatenate the tag and the frame
|
||||
byte[] tooLong = new byte[TAG_LENGTH + FRAME_LENGTH];
|
||||
System.arraycopy(tag, 0, tooLong, 0, TAG_LENGTH);
|
||||
System.arraycopy(frame, 0, tooLong, TAG_LENGTH, FRAME_LENGTH);
|
||||
// Try to read the frame, which should fail due to invalid length
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(tooLong);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, tagCipher,
|
||||
frameCipher, tagKey, frameKey, FRAME_LENGTH);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, frameCipher,
|
||||
frameKey, FRAME_LENGTH);
|
||||
try {
|
||||
i.readFrame(new byte[FRAME_LENGTH - MAC_LENGTH]);
|
||||
fail();
|
||||
@@ -213,18 +132,12 @@ public class IncomingEncryptionLayerTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testNonZeroPaddingThrowsException() throws Exception {
|
||||
// Generate a valid tag
|
||||
byte[] tag = generateTag(tagKey);
|
||||
// Generate a frame with pad padding
|
||||
// Generate a frame with bad padding
|
||||
byte[] frame = generateFrame(0L, FRAME_LENGTH, 123, false, true);
|
||||
// Concatenate the tag and the frame
|
||||
byte[] badPadding = new byte[TAG_LENGTH + FRAME_LENGTH];
|
||||
System.arraycopy(tag, 0, badPadding, 0, TAG_LENGTH);
|
||||
System.arraycopy(frame, 0, badPadding, TAG_LENGTH, FRAME_LENGTH);
|
||||
// Try to read the frame, which should fail due to bad padding
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(badPadding);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, tagCipher,
|
||||
frameCipher, tagKey, frameKey, FRAME_LENGTH);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(frame);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, frameCipher,
|
||||
frameKey, FRAME_LENGTH);
|
||||
try {
|
||||
i.readFrame(new byte[FRAME_LENGTH - MAC_LENGTH]);
|
||||
fail();
|
||||
@@ -233,34 +146,24 @@ public class IncomingEncryptionLayerTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testCannotReadBeyondFinalFrame() throws Exception {
|
||||
// Generate a valid tag
|
||||
byte[] tag = generateTag(tagKey);
|
||||
// Generate a valid final frame and another valid final frame after it
|
||||
byte[] frame = generateFrame(0L, FRAME_LENGTH, MAX_PAYLOAD_LENGTH, true,
|
||||
false);
|
||||
byte[] frame1 = generateFrame(1L, FRAME_LENGTH, 123, true, false);
|
||||
// Concatenate the tag and the frames
|
||||
byte[] extraFrame = new byte[TAG_LENGTH + FRAME_LENGTH * 2];
|
||||
System.arraycopy(tag, 0, extraFrame, 0, TAG_LENGTH);
|
||||
System.arraycopy(frame, 0, extraFrame, TAG_LENGTH, FRAME_LENGTH);
|
||||
System.arraycopy(frame1, 0, extraFrame, TAG_LENGTH + FRAME_LENGTH,
|
||||
FRAME_LENGTH);
|
||||
// Concatenate the frames
|
||||
byte[] extraFrame = new byte[FRAME_LENGTH * 2];
|
||||
System.arraycopy(frame, 0, extraFrame, 0, FRAME_LENGTH);
|
||||
System.arraycopy(frame1, 0, extraFrame, FRAME_LENGTH, FRAME_LENGTH);
|
||||
// Read the final frame, which should first read the tag
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(extraFrame);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, tagCipher,
|
||||
frameCipher, tagKey, frameKey, FRAME_LENGTH);
|
||||
IncomingEncryptionLayer i = new IncomingEncryptionLayer(in, frameCipher,
|
||||
frameKey, FRAME_LENGTH);
|
||||
byte[] buf = new byte[FRAME_LENGTH - MAC_LENGTH];
|
||||
assertEquals(MAX_PAYLOAD_LENGTH, i.readFrame(buf));
|
||||
// The frame after the final frame should not be read
|
||||
assertEquals(-1, i.readFrame(buf));
|
||||
}
|
||||
|
||||
private byte[] generateTag(ErasableKey tagKey) {
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
TagEncoder.encodeTag(tag, tagCipher, tagKey);
|
||||
return tag;
|
||||
}
|
||||
|
||||
private byte[] generateFrame(long frameNumber, int frameLength,
|
||||
int payloadLength, boolean finalFrame, boolean badPadding)
|
||||
throws Exception {
|
||||
|
||||
@@ -9,8 +9,6 @@ import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import net.sf.briar.BriarTestCase;
|
||||
import net.sf.briar.api.crypto.AuthenticatedCipher;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
@@ -29,28 +27,24 @@ public class OutgoingEncryptionLayerTest extends BriarTestCase {
|
||||
FRAME_LENGTH - HEADER_LENGTH - MAC_LENGTH;
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final Cipher tagCipher;
|
||||
private final AuthenticatedCipher frameCipher;
|
||||
private final byte[] tag;
|
||||
|
||||
public OutgoingEncryptionLayerTest() {
|
||||
super();
|
||||
Injector i = Guice.createInjector(new CryptoModule());
|
||||
crypto = i.getInstance(CryptoComponent.class);
|
||||
tagCipher = crypto.getTagCipher();
|
||||
frameCipher = crypto.getFrameCipher();
|
||||
tag = new byte[TAG_LENGTH];
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncryption() throws Exception {
|
||||
int payloadLength = 123;
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
byte[] iv = new byte[IV_LENGTH], aad = new byte[AAD_LENGTH];
|
||||
byte[] plaintext = new byte[FRAME_LENGTH - MAC_LENGTH];
|
||||
byte[] ciphertext = new byte[FRAME_LENGTH];
|
||||
ErasableKey tagKey = crypto.generateTestKey();
|
||||
ErasableKey frameKey = crypto.generateTestKey();
|
||||
// Calculate the expected tag
|
||||
TagEncoder.encodeTag(tag, tagCipher, tagKey);
|
||||
// Calculate the expected ciphertext
|
||||
FrameEncoder.encodeIv(iv, 0);
|
||||
FrameEncoder.encodeAad(aad, 0, plaintext.length);
|
||||
@@ -60,14 +54,11 @@ public class OutgoingEncryptionLayerTest extends BriarTestCase {
|
||||
// Check that the actual tag and ciphertext match what's expected
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out,
|
||||
10 * FRAME_LENGTH, tagCipher, frameCipher, tagKey, frameKey,
|
||||
FRAME_LENGTH);
|
||||
10 * FRAME_LENGTH, frameCipher, frameKey, FRAME_LENGTH, tag);
|
||||
o.writeFrame(new byte[FRAME_LENGTH - MAC_LENGTH], payloadLength, false);
|
||||
byte[] actual = out.toByteArray();
|
||||
assertEquals(TAG_LENGTH + FRAME_LENGTH, actual.length);
|
||||
for(int i = 0; i < TAG_LENGTH; i++) {
|
||||
assertEquals(tag[i], actual[i]);
|
||||
}
|
||||
for(int i = 0; i < TAG_LENGTH; i++) assertEquals(tag[i], actual[i]);
|
||||
for(int i = 0; i < FRAME_LENGTH; i++) {
|
||||
assertEquals("" + i, ciphertext[i], actual[TAG_LENGTH + i]);
|
||||
}
|
||||
@@ -78,9 +69,8 @@ public class OutgoingEncryptionLayerTest extends BriarTestCase {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
// Initiator's constructor
|
||||
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out,
|
||||
10 * FRAME_LENGTH, tagCipher, frameCipher,
|
||||
crypto.generateTestKey(), crypto.generateTestKey(),
|
||||
FRAME_LENGTH);
|
||||
10 * FRAME_LENGTH, frameCipher, crypto.generateTestKey(),
|
||||
FRAME_LENGTH, tag);
|
||||
// Write an empty final frame without having written any other frames
|
||||
o.writeFrame(new byte[FRAME_LENGTH - MAC_LENGTH], 0, true);
|
||||
// Nothing should be written to the output stream
|
||||
@@ -106,9 +96,8 @@ public class OutgoingEncryptionLayerTest extends BriarTestCase {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
// Initiator's constructor
|
||||
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out,
|
||||
10 * FRAME_LENGTH, tagCipher, frameCipher,
|
||||
crypto.generateTestKey(), crypto.generateTestKey(),
|
||||
FRAME_LENGTH);
|
||||
10 * FRAME_LENGTH, frameCipher, crypto.generateTestKey(),
|
||||
FRAME_LENGTH, tag);
|
||||
// There should be space for nine full frames and one partial frame
|
||||
byte[] frame = new byte[FRAME_LENGTH - MAC_LENGTH];
|
||||
assertEquals(10 * MAX_PAYLOAD_LENGTH - TAG_LENGTH,
|
||||
|
||||
Reference in New Issue
Block a user