Add unit tests for pending contact state.

This commit is contained in:
akwizgran
2019-06-05 12:23:15 +01:00
parent 98191fb059
commit 1aa579a44f

View File

@@ -1,11 +1,12 @@
package org.briarproject.bramble.contact; package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId; 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.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.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; 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.AuthorInfo;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; 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.api.transport.KeyManager;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.CaptureArgumentAction;
import org.briarproject.bramble.test.DbExpectations; import org.briarproject.bramble.test.DbExpectations;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.junit.Before; import org.junit.Before;
@@ -26,10 +31,14 @@ import org.junit.Test;
import java.util.Collection; import java.util.Collection;
import java.util.Random; import java.util.Random;
import java.util.concurrent.atomic.AtomicReference;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.BASE32_LINK_BYTES; 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.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES; import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNKNOWN; 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.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getContact; import static org.briarproject.bramble.test.TestUtils.getContact;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor; 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.getRandomId;
import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.util.StringUtils.getRandomBase32String; 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 boolean verified = false, active = true;
private final Contact contact = getContact(remote, local, verified); private final Contact contact = getContact(remote, local, verified);
private final ContactId contactId = contact.getId(); 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 @Before
public void setUp() { public void setUp() {
@@ -97,6 +110,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testGetContact() throws Exception { public void testGetContact() throws Exception {
Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new DbExpectations() {{ context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).getContact(txn, contactId); oneOf(db).getContact(txn, contactId);
@@ -110,6 +124,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
public void testGetContactByAuthor() throws Exception { public void testGetContactByAuthor() throws Exception {
Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
Collection<Contact> contacts = singletonList(contact); Collection<Contact> contacts = singletonList(contact);
context.checking(new DbExpectations() {{ context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).getContactsByAuthorId(txn, remote.getId()); oneOf(db).getContactsByAuthorId(txn, remote.getId());
@@ -122,6 +137,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test(expected = NoSuchContactException.class) @Test(expected = NoSuchContactException.class)
public void testGetContactByUnknownAuthor() throws Exception { public void testGetContactByUnknownAuthor() throws Exception {
Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new DbExpectations() {{ context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).getContactsByAuthorId(txn, remote.getId()); oneOf(db).getContactsByAuthorId(txn, remote.getId());
@@ -135,6 +151,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
public void testGetContactByUnknownLocalAuthor() throws Exception { public void testGetContactByUnknownLocalAuthor() throws Exception {
Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
Collection<Contact> contacts = singletonList(contact); Collection<Contact> contacts = singletonList(contact);
context.checking(new DbExpectations() {{ context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).getContactsByAuthorId(txn, remote.getId()); oneOf(db).getContactsByAuthorId(txn, remote.getId());
@@ -148,6 +165,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
public void testGetContacts() throws Exception { public void testGetContacts() throws Exception {
Collection<Contact> contacts = singletonList(contact); Collection<Contact> contacts = singletonList(contact);
Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new DbExpectations() {{ context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).getContacts(txn); oneOf(db).getContacts(txn);
@@ -160,6 +178,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testRemoveContact() throws Exception { public void testRemoveContact() throws Exception {
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new DbExpectations() {{ context.checking(new DbExpectations() {{
oneOf(db).transaction(with(false), withDbRunnable(txn)); oneOf(db).transaction(with(false), withDbRunnable(txn));
oneOf(db).getContact(txn, contactId); oneOf(db).getContact(txn, contactId);
@@ -193,6 +212,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testContactExists() throws Exception { public void testContactExists() throws Exception {
Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new DbExpectations() {{ context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).containsContact(txn, remote.getId(), local); oneOf(db).containsContact(txn, remote.getId(), local);
@@ -212,6 +232,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
oneOf(db).getContactsByAuthorId(txn, remote.getId()); oneOf(db).getContactsByAuthorId(txn, remote.getId());
will(returnValue(singletonList(contact))); will(returnValue(singletonList(contact)));
}}); }});
AuthorInfo authorInfo = AuthorInfo authorInfo =
contactManager.getAuthorInfo(txn, remote.getId()); contactManager.getAuthorInfo(txn, remote.getId());
assertEquals(UNVERIFIED, authorInfo.getStatus()); assertEquals(UNVERIFIED, authorInfo.getStatus());
@@ -229,6 +250,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
oneOf(db).getContactsByAuthorId(txn, remote.getId()); oneOf(db).getContactsByAuthorId(txn, remote.getId());
will(returnValue(emptyList())); will(returnValue(emptyList()));
}}); }});
AuthorInfo authorInfo = AuthorInfo authorInfo =
contactManager.getAuthorInfo(txn, remote.getId()); contactManager.getAuthorInfo(txn, remote.getId());
assertEquals(UNKNOWN, authorInfo.getStatus()); assertEquals(UNKNOWN, authorInfo.getStatus());
@@ -253,6 +275,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
will(returnValue(localAuthor)); will(returnValue(localAuthor));
never(db).getContactsByAuthorId(txn, remote.getId()); never(db).getContactsByAuthorId(txn, remote.getId());
}}); }});
authorInfo = contactManager.getAuthorInfo(txn, localAuthor.getId()); authorInfo = contactManager.getAuthorInfo(txn, localAuthor.getId());
assertEquals(OURSELVES, authorInfo.getStatus()); assertEquals(OURSELVES, authorInfo.getStatus());
assertNull(authorInfo.getAlias()); assertNull(authorInfo.getAlias());
@@ -271,19 +294,86 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testGetHandshakeLink() throws Exception { public void testGetHandshakeLink() throws Exception {
Transaction txn = new Transaction(null, true); 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); String link = "briar://" + getRandomBase32String(BASE32_LINK_BYTES);
context.checking(new DbExpectations() {{ context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn)); oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(identityManager).getHandshakeKeys(txn); oneOf(identityManager).getHandshakeKeys(txn);
will(returnValue(keyPair)); will(returnValue(handshakeKeyPair));
oneOf(pendingContactFactory).createHandshakeLink(publicKey); oneOf(pendingContactFactory).createHandshakeLink(
handshakeKeyPair.getPublic());
will(returnValue(link)); will(returnValue(link));
}}); }});
assertEquals(link, contactManager.getHandshakeLink()); 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());
}
} }