Add first integration test for TransportKeyAgreementManager

This commit is contained in:
Torsten Grote
2021-06-23 14:34:53 -03:00
parent f5cab63052
commit 65110090de
4 changed files with 256 additions and 4 deletions

View File

@@ -28,6 +28,7 @@ import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
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,
BrambleIntegrationTestComponent toComponent, ContactId toId,
int num) throws Exception {

View File

@@ -27,14 +27,26 @@ public class TestPluginConfigModule {
public static final TransportId SIMPLEX_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
private final SimplexPluginFactory simplex = new SimplexPluginFactory() {
@Override
public TransportId getId() {
return SIMPLEX_TRANSPORT_ID;
return simplexTransportId;
}
@Override
@@ -54,7 +66,7 @@ public class TestPluginConfigModule {
@Override
public TransportId getId() {
return DUPLEX_TRANSPORT_ID;
return duplexTransportId;
}
@Override
@@ -70,7 +82,7 @@ public class TestPluginConfigModule {
};
@Provides
PluginConfig providePluginConfig() {
public PluginConfig providePluginConfig() {
@NotNullByDefault
PluginConfig pluginConfig = new PluginConfig() {

View File

@@ -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;
}
}

View File

@@ -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();
}