From 1aa579a44f7962874906d1c835e59618a4c51b33 Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Wed, 5 Jun 2019 12:23:15 +0100 Subject: [PATCH] Add unit tests for pending contact state. --- .../contact/ContactManagerImplTest.java | 108 ++++++++++++++++-- 1 file changed, 99 insertions(+), 9 deletions(-) diff --git a/bramble-core/src/test/java/org/briarproject/bramble/contact/ContactManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/contact/ContactManagerImplTest.java index a96f730fc6..543822a3ea 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/contact/ContactManagerImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/contact/ContactManagerImplTest.java @@ -1,11 +1,12 @@ package org.briarproject.bramble.contact; +import org.briarproject.bramble.api.Pair; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactId; -import org.briarproject.bramble.api.contact.ContactManager; +import org.briarproject.bramble.api.contact.PendingContact; +import org.briarproject.bramble.api.contact.PendingContactState; +import org.briarproject.bramble.api.contact.event.PendingContactStateChangedEvent; import org.briarproject.bramble.api.crypto.KeyPair; -import org.briarproject.bramble.api.crypto.PrivateKey; -import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DbException; @@ -17,8 +18,12 @@ import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorInfo; import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.LocalAuthor; +import org.briarproject.bramble.api.rendezvous.event.RendezvousConnectionClosedEvent; +import org.briarproject.bramble.api.rendezvous.event.RendezvousConnectionOpenedEvent; +import org.briarproject.bramble.api.rendezvous.event.RendezvousFailedEvent; import org.briarproject.bramble.api.transport.KeyManager; import org.briarproject.bramble.test.BrambleMockTestCase; +import org.briarproject.bramble.test.CaptureArgumentAction; import org.briarproject.bramble.test.DbExpectations; import org.jmock.Expectations; import org.junit.Before; @@ -26,10 +31,14 @@ import org.junit.Test; import java.util.Collection; import java.util.Random; +import java.util.concurrent.atomic.AtomicReference; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.BASE32_LINK_BYTES; +import static org.briarproject.bramble.api.contact.PendingContactState.ADDING_CONTACT; +import static org.briarproject.bramble.api.contact.PendingContactState.FAILED; +import static org.briarproject.bramble.api.contact.PendingContactState.WAITING_FOR_CONNECTION; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES; import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNKNOWN; @@ -40,6 +49,7 @@ import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey; import static org.briarproject.bramble.test.TestUtils.getAuthor; import static org.briarproject.bramble.test.TestUtils.getContact; import static org.briarproject.bramble.test.TestUtils.getLocalAuthor; +import static org.briarproject.bramble.test.TestUtils.getPendingContact; import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.util.StringUtils.getRandomBase32String; @@ -64,8 +74,11 @@ public class ContactManagerImplTest extends BrambleMockTestCase { private final boolean verified = false, active = true; private final Contact contact = getContact(remote, local, verified); private final ContactId contactId = contact.getId(); + private final KeyPair handshakeKeyPair = + new KeyPair(getAgreementPublicKey(), getAgreementPrivateKey()); + private final PendingContact pendingContact = getPendingContact(); - private ContactManager contactManager; + private ContactManagerImpl contactManager; @Before public void setUp() { @@ -97,6 +110,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase { @Test public void testGetContact() throws Exception { Transaction txn = new Transaction(null, true); + context.checking(new DbExpectations() {{ oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).getContact(txn, contactId); @@ -110,6 +124,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase { public void testGetContactByAuthor() throws Exception { Transaction txn = new Transaction(null, true); Collection<Contact> contacts = singletonList(contact); + context.checking(new DbExpectations() {{ oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).getContactsByAuthorId(txn, remote.getId()); @@ -122,6 +137,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase { @Test(expected = NoSuchContactException.class) public void testGetContactByUnknownAuthor() throws Exception { Transaction txn = new Transaction(null, true); + context.checking(new DbExpectations() {{ oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).getContactsByAuthorId(txn, remote.getId()); @@ -135,6 +151,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase { public void testGetContactByUnknownLocalAuthor() throws Exception { Transaction txn = new Transaction(null, true); Collection<Contact> contacts = singletonList(contact); + context.checking(new DbExpectations() {{ oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).getContactsByAuthorId(txn, remote.getId()); @@ -148,6 +165,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase { public void testGetContacts() throws Exception { Collection<Contact> contacts = singletonList(contact); Transaction txn = new Transaction(null, true); + context.checking(new DbExpectations() {{ oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).getContacts(txn); @@ -160,6 +178,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase { @Test public void testRemoveContact() throws Exception { Transaction txn = new Transaction(null, false); + context.checking(new DbExpectations() {{ oneOf(db).transaction(with(false), withDbRunnable(txn)); oneOf(db).getContact(txn, contactId); @@ -193,6 +212,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase { @Test public void testContactExists() throws Exception { Transaction txn = new Transaction(null, true); + context.checking(new DbExpectations() {{ oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).containsContact(txn, remote.getId(), local); @@ -212,6 +232,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase { oneOf(db).getContactsByAuthorId(txn, remote.getId()); will(returnValue(singletonList(contact))); }}); + AuthorInfo authorInfo = contactManager.getAuthorInfo(txn, remote.getId()); assertEquals(UNVERIFIED, authorInfo.getStatus()); @@ -229,6 +250,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase { oneOf(db).getContactsByAuthorId(txn, remote.getId()); will(returnValue(emptyList())); }}); + AuthorInfo authorInfo = contactManager.getAuthorInfo(txn, remote.getId()); assertEquals(UNKNOWN, authorInfo.getStatus()); @@ -253,6 +275,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase { will(returnValue(localAuthor)); never(db).getContactsByAuthorId(txn, remote.getId()); }}); + authorInfo = contactManager.getAuthorInfo(txn, localAuthor.getId()); assertEquals(OURSELVES, authorInfo.getStatus()); assertNull(authorInfo.getAlias()); @@ -271,19 +294,86 @@ public class ContactManagerImplTest extends BrambleMockTestCase { @Test public void testGetHandshakeLink() throws Exception { Transaction txn = new Transaction(null, true); - PublicKey publicKey = getAgreementPublicKey(); - PrivateKey privateKey = getAgreementPrivateKey(); - KeyPair keyPair = new KeyPair(publicKey, privateKey); String link = "briar://" + getRandomBase32String(BASE32_LINK_BYTES); context.checking(new DbExpectations() {{ oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(identityManager).getHandshakeKeys(txn); - will(returnValue(keyPair)); - oneOf(pendingContactFactory).createHandshakeLink(publicKey); + will(returnValue(handshakeKeyPair)); + oneOf(pendingContactFactory).createHandshakeLink( + handshakeKeyPair.getPublic()); will(returnValue(link)); }}); assertEquals(link, contactManager.getHandshakeLink()); } + + @Test + public void testDefaultPendingContactState() throws Exception { + Transaction txn = new Transaction(null, true); + + context.checking(new DbExpectations() {{ + oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); + oneOf(db).getPendingContacts(txn); + will(returnValue(singletonList(pendingContact))); + }}); + + // No events have happened for this pending contact, so the state + // should be WAITING_FOR_CONNECTION + Collection<Pair<PendingContact, PendingContactState>> pairs = + contactManager.getPendingContacts(); + assertEquals(1, pairs.size()); + Pair<PendingContact, PendingContactState> pair = + pairs.iterator().next(); + assertEquals(pendingContact, pair.getFirst()); + assertEquals(WAITING_FOR_CONNECTION, pair.getSecond()); + } + + @Test + public void testFailedStateIsNotReplaced() throws Exception { + Transaction txn = new Transaction(null, true); + AtomicReference<PendingContactStateChangedEvent> captureFirstEvent = + new AtomicReference<>(); + AtomicReference<PendingContactStateChangedEvent> captureSecondEvent = + new AtomicReference<>(); + + context.checking(new Expectations() {{ + oneOf(eventBus).broadcast(with(any( + PendingContactStateChangedEvent.class))); + will(new CaptureArgumentAction<>(captureFirstEvent, + PendingContactStateChangedEvent.class, 0)); + oneOf(eventBus).broadcast(with(any( + PendingContactStateChangedEvent.class))); + will(new CaptureArgumentAction<>(captureSecondEvent, + PendingContactStateChangedEvent.class, 0)); + }}); + + // A rendezvous connection is opened, then the pending contact expires, + // then the rendezvous connection is closed + contactManager.eventOccurred(new RendezvousConnectionOpenedEvent( + pendingContact.getId())); + contactManager.eventOccurred(new RendezvousFailedEvent( + pendingContact.getId())); + contactManager.eventOccurred(new RendezvousConnectionClosedEvent( + pendingContact.getId(), false)); + + assertEquals(ADDING_CONTACT, + captureFirstEvent.get().getPendingContactState()); + assertEquals(FAILED, captureSecondEvent.get().getPendingContactState()); + + context.checking(new DbExpectations() {{ + oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); + oneOf(db).getPendingContacts(txn); + will(returnValue(singletonList(pendingContact))); + }}); + + // The FAILED state should not have been overwritten + Collection<Pair<PendingContact, PendingContactState>> pairs = + contactManager.getPendingContacts(); + assertEquals(1, pairs.size()); + Pair<PendingContact, PendingContactState> pair = + pairs.iterator().next(); + assertEquals(pendingContact, pair.getFirst()); + assertEquals(FAILED, pair.getSecond()); + } } -- GitLab