mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-21 07:09:56 +01:00
Add first integration test for TransportKeyAgreementManager
This commit is contained in:
@@ -28,6 +28,7 @@ import java.util.Set;
|
|||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -217,6 +218,20 @@ public abstract class BrambleIntegrationTest<C extends BrambleIntegrationTestCom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void awaitPendingMessageDelivery(int num)
|
||||||
|
throws TimeoutException {
|
||||||
|
deliveryWaiter.await(TIMEOUT, num);
|
||||||
|
assertEquals("Messages delivered", num, deliveryCounter.getAndSet(0));
|
||||||
|
|
||||||
|
try {
|
||||||
|
messageSemaphore.tryAcquire(num, TIMEOUT, MILLISECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOG.info("Interrupted while waiting for messages");
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void sendAcks(BrambleIntegrationTestComponent fromComponent,
|
protected void sendAcks(BrambleIntegrationTestComponent fromComponent,
|
||||||
BrambleIntegrationTestComponent toComponent, ContactId toId,
|
BrambleIntegrationTestComponent toComponent, ContactId toId,
|
||||||
int num) throws Exception {
|
int num) throws Exception {
|
||||||
|
|||||||
@@ -27,14 +27,26 @@ public class TestPluginConfigModule {
|
|||||||
|
|
||||||
public static final TransportId SIMPLEX_TRANSPORT_ID = getTransportId();
|
public static final TransportId SIMPLEX_TRANSPORT_ID = getTransportId();
|
||||||
public static final TransportId DUPLEX_TRANSPORT_ID = getTransportId();
|
public static final TransportId DUPLEX_TRANSPORT_ID = getTransportId();
|
||||||
public static final int MAX_LATENCY = 30_000; // 30 seconds
|
private static final int MAX_LATENCY = 30_000; // 30 seconds
|
||||||
|
|
||||||
|
private final TransportId simplexTransportId, duplexTransportId;
|
||||||
|
|
||||||
|
public TestPluginConfigModule() {
|
||||||
|
this(SIMPLEX_TRANSPORT_ID, DUPLEX_TRANSPORT_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestPluginConfigModule(TransportId simplexTransportId,
|
||||||
|
TransportId duplexTransportId) {
|
||||||
|
this.simplexTransportId = simplexTransportId;
|
||||||
|
this.duplexTransportId = duplexTransportId;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
private final SimplexPluginFactory simplex = new SimplexPluginFactory() {
|
private final SimplexPluginFactory simplex = new SimplexPluginFactory() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TransportId getId() {
|
public TransportId getId() {
|
||||||
return SIMPLEX_TRANSPORT_ID;
|
return simplexTransportId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -54,7 +66,7 @@ public class TestPluginConfigModule {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TransportId getId() {
|
public TransportId getId() {
|
||||||
return DUPLEX_TRANSPORT_ID;
|
return duplexTransportId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -70,7 +82,7 @@ public class TestPluginConfigModule {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
PluginConfig providePluginConfig() {
|
public PluginConfig providePluginConfig() {
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
PluginConfig pluginConfig = new PluginConfig() {
|
PluginConfig pluginConfig = new PluginConfig() {
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,196 @@
|
|||||||
|
package org.briarproject.bramble.transport.agreement;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
|
||||||
|
import org.briarproject.bramble.api.Pair;
|
||||||
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.contact.ContactManager;
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
|
import org.briarproject.bramble.api.identity.Identity;
|
||||||
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
|
import org.briarproject.bramble.test.BrambleIntegrationTest;
|
||||||
|
import org.briarproject.bramble.test.TestDatabaseConfigModule;
|
||||||
|
import org.briarproject.bramble.test.TestPluginConfigModule;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.test.TestPluginConfigModule.DUPLEX_TRANSPORT_ID;
|
||||||
|
import static org.briarproject.bramble.test.TestPluginConfigModule.SIMPLEX_TRANSPORT_ID;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class TransportKeyAgreementIntegrationTest
|
||||||
|
extends BrambleIntegrationTest<TransportKeyAgreementTestComponent> {
|
||||||
|
|
||||||
|
private final File aliceDir = new File(testDir, "alice");
|
||||||
|
private final File bobDir = new File(testDir, "bob");
|
||||||
|
private final SecretKey masterKey = getSecretKey();
|
||||||
|
private final long timestamp = System.currentTimeMillis();
|
||||||
|
private final TransportId newTransportId =
|
||||||
|
new TransportId(getRandomString(8));
|
||||||
|
|
||||||
|
private TransportKeyAgreementTestComponent alice, bob;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
@Override
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
// Create the devices
|
||||||
|
alice = createComponent(aliceDir, false);
|
||||||
|
bob = createComponent(bobDir, false);
|
||||||
|
|
||||||
|
// Start both lifecycles
|
||||||
|
startLifecycle(alice, "Alice");
|
||||||
|
startLifecycle(bob, "Bob");
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransportKeyAgreementTestComponent createComponent(
|
||||||
|
File dir, boolean useNewTransport) {
|
||||||
|
TestPluginConfigModule pluginConfigModule = useNewTransport ?
|
||||||
|
new TestPluginConfigModule(SIMPLEX_TRANSPORT_ID, newTransportId)
|
||||||
|
: new TestPluginConfigModule();
|
||||||
|
TransportKeyAgreementTestComponent c =
|
||||||
|
DaggerTransportKeyAgreementTestComponent.builder()
|
||||||
|
.testDatabaseConfigModule(
|
||||||
|
new TestDatabaseConfigModule(dir))
|
||||||
|
.testPluginConfigModule(pluginConfigModule)
|
||||||
|
.build();
|
||||||
|
BrambleCoreIntegrationTestEagerSingletons.Helper
|
||||||
|
.injectEagerSingletons(c);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startLifecycle(
|
||||||
|
TransportKeyAgreementTestComponent device,
|
||||||
|
String identityName) throws Exception {
|
||||||
|
// Listen to message related events first to not miss early ones
|
||||||
|
addEventListener(device);
|
||||||
|
// Add an identity for the user
|
||||||
|
IdentityManager identityManager = device.getIdentityManager();
|
||||||
|
Identity identity = identityManager.createIdentity(identityName);
|
||||||
|
identityManager.registerIdentity(identity);
|
||||||
|
// Start the lifecycle manager
|
||||||
|
LifecycleManager lifecycleManager = device.getLifecycleManager();
|
||||||
|
lifecycleManager.startServices(masterKey); // re-using masterKey here
|
||||||
|
lifecycleManager.waitForStartup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
@Override
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
tearDown(alice);
|
||||||
|
tearDown(bob);
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tearDown(TransportKeyAgreementTestComponent device)
|
||||||
|
throws Exception {
|
||||||
|
// Stop the lifecycle manager
|
||||||
|
LifecycleManager lifecycleManager = device.getLifecycleManager();
|
||||||
|
lifecycleManager.stopServices();
|
||||||
|
lifecycleManager.waitForShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAliceAddsTransportBeforeBob() throws Exception {
|
||||||
|
// Alice and Bob add each other.
|
||||||
|
Pair<ContactId, ContactId> contactIds = addContacts();
|
||||||
|
ContactId aliceId = contactIds.getFirst();
|
||||||
|
ContactId bobId = contactIds.getSecond();
|
||||||
|
|
||||||
|
// Alice restarts and comes back with the new transport.
|
||||||
|
alice = restartWithNewTransport(alice, aliceDir, "Alice");
|
||||||
|
|
||||||
|
// Alice can still send via the old simplex,
|
||||||
|
// but not via the new duplex transport
|
||||||
|
assertTrue(alice.getKeyManager()
|
||||||
|
.canSendOutgoingStreams(bobId, SIMPLEX_TRANSPORT_ID));
|
||||||
|
assertFalse(alice.getKeyManager()
|
||||||
|
.canSendOutgoingStreams(bobId, newTransportId));
|
||||||
|
|
||||||
|
// Alice has started a session and sends KEY message to Bob
|
||||||
|
// which he can't read, as he doesn't support the new transport, yet.
|
||||||
|
syncMessage(alice, bob, bobId, 1, false);
|
||||||
|
|
||||||
|
// Bob restarts and comes back with the new transport.
|
||||||
|
bob = restartWithNewTransport(bob, bobDir, "Bob");
|
||||||
|
|
||||||
|
// Alice's pending KEY message now gets delivered async, so wait for it
|
||||||
|
awaitPendingMessageDelivery(1);
|
||||||
|
|
||||||
|
// Bobs now and sends his own KEY as well as his ACTIVATE message.
|
||||||
|
syncMessage(bob, alice, aliceId, 2, true);
|
||||||
|
|
||||||
|
// Alice can already send over the new transport while Bob still can't.
|
||||||
|
assertTrue(alice.getKeyManager()
|
||||||
|
.canSendOutgoingStreams(bobId, newTransportId));
|
||||||
|
assertFalse(bob.getKeyManager()
|
||||||
|
.canSendOutgoingStreams(aliceId, newTransportId));
|
||||||
|
|
||||||
|
// Now Alice sends her ACTIVATE message to Bob.
|
||||||
|
syncMessage(alice, bob, bobId, 1, true);
|
||||||
|
|
||||||
|
// Now Bob can also send over the new transport.
|
||||||
|
assertTrue(alice.getKeyManager()
|
||||||
|
.canSendOutgoingStreams(bobId, newTransportId));
|
||||||
|
assertTrue(bob.getKeyManager()
|
||||||
|
.canSendOutgoingStreams(aliceId, newTransportId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Pair<ContactId, ContactId> addContacts() throws Exception {
|
||||||
|
ContactId bobId = addContact(alice, bob, true);
|
||||||
|
ContactId aliceId = addContact(bob, alice, false);
|
||||||
|
|
||||||
|
// Alice and Bob can send messages via the default test transports
|
||||||
|
assertTrue(alice.getKeyManager()
|
||||||
|
.canSendOutgoingStreams(bobId, SIMPLEX_TRANSPORT_ID));
|
||||||
|
assertTrue(alice.getKeyManager()
|
||||||
|
.canSendOutgoingStreams(bobId, DUPLEX_TRANSPORT_ID));
|
||||||
|
assertTrue(bob.getKeyManager()
|
||||||
|
.canSendOutgoingStreams(aliceId, SIMPLEX_TRANSPORT_ID));
|
||||||
|
assertTrue(bob.getKeyManager()
|
||||||
|
.canSendOutgoingStreams(aliceId, DUPLEX_TRANSPORT_ID));
|
||||||
|
|
||||||
|
// Sync initial client versioning updates
|
||||||
|
syncMessage(alice, bob, bobId, 1, true);
|
||||||
|
syncMessage(bob, alice, aliceId, 1, true);
|
||||||
|
syncMessage(alice, bob, bobId, 1, true);
|
||||||
|
sendAcks(bob, alice, aliceId, 1);
|
||||||
|
|
||||||
|
return new Pair<>(aliceId, bobId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ContactId addContact(
|
||||||
|
TransportKeyAgreementTestComponent device,
|
||||||
|
TransportKeyAgreementTestComponent remote,
|
||||||
|
boolean alice) throws Exception {
|
||||||
|
// Get remote Author
|
||||||
|
Author remoteAuthor = remote.getIdentityManager().getLocalAuthor();
|
||||||
|
// Get ID of LocalAuthor
|
||||||
|
IdentityManager identityManager = device.getIdentityManager();
|
||||||
|
AuthorId localAuthorId = identityManager.getLocalAuthor().getId();
|
||||||
|
// Add the other user as a contact
|
||||||
|
ContactManager contactManager = device.getContactManager();
|
||||||
|
return contactManager.addContact(remoteAuthor, localAuthorId, masterKey,
|
||||||
|
timestamp, alice, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransportKeyAgreementTestComponent restartWithNewTransport(
|
||||||
|
TransportKeyAgreementTestComponent device, File dir, String name)
|
||||||
|
throws Exception {
|
||||||
|
tearDown(device);
|
||||||
|
TransportKeyAgreementTestComponent newDevice =
|
||||||
|
createComponent(dir, true);
|
||||||
|
startLifecycle(newDevice, name);
|
||||||
|
return newDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package org.briarproject.bramble.transport.agreement;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.BrambleCoreModule;
|
||||||
|
import org.briarproject.bramble.api.contact.ContactManager;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
|
import org.briarproject.bramble.api.transport.KeyManager;
|
||||||
|
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
|
||||||
|
import org.briarproject.bramble.test.BrambleIntegrationTestComponent;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import dagger.Component;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Component(modules = {
|
||||||
|
BrambleCoreIntegrationTestModule.class,
|
||||||
|
BrambleCoreModule.class
|
||||||
|
})
|
||||||
|
interface TransportKeyAgreementTestComponent
|
||||||
|
extends BrambleIntegrationTestComponent {
|
||||||
|
|
||||||
|
KeyManager getKeyManager();
|
||||||
|
|
||||||
|
TransportKeyAgreementManagerImpl getTransportKeyAgreementManager();
|
||||||
|
|
||||||
|
ContactManager getContactManager();
|
||||||
|
|
||||||
|
LifecycleManager getLifecycleManager();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user