Add integration tests for GroupInvitationManager

This commit is contained in:
Torsten Grote
2016-11-22 18:22:31 -02:00
committed by akwizgran
parent 24d68c4f5b
commit 67d9f3a7c2
4 changed files with 482 additions and 0 deletions

View File

@@ -39,6 +39,7 @@ import org.briarproject.introduction.IntroductionGroupFactory;
import org.briarproject.introduction.IntroductionModule;
import org.briarproject.lifecycle.LifecycleModule;
import org.briarproject.privategroup.PrivateGroupModule;
import org.briarproject.privategroup.invitation.GroupInvitationModule;
import org.briarproject.properties.PropertiesModule;
import org.briarproject.sharing.SharingModule;
import org.briarproject.sync.SyncModule;
@@ -180,6 +181,7 @@ public abstract class BriarIntegrationTest extends BriarTestCase {
component.inject(new CryptoModule.EagerSingletons());
component.inject(new ContactModule.EagerSingletons());
component.inject(new ForumModule.EagerSingletons());
component.inject(new GroupInvitationModule.EagerSingletons());
component.inject(new IntroductionModule.EagerSingletons());
component.inject(new PropertiesModule.EagerSingletons());
component.inject(new PrivateGroupModule.EagerSingletons());

View File

@@ -14,6 +14,7 @@ import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.introduction.IntroductionManager;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.privategroup.PrivateGroupManager;
import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
import org.briarproject.api.properties.TransportPropertyManager;
import org.briarproject.api.sync.SyncSessionFactory;
import org.briarproject.blogs.BlogsModule;
@@ -78,6 +79,8 @@ public interface BriarIntegrationTestComponent {
void inject(ForumModule.EagerSingletons init);
void inject(GroupInvitationModule.EagerSingletons init);
void inject(IntroductionModule.EagerSingletons init);
void inject(LifecycleModule.EagerSingletons init);
@@ -114,6 +117,8 @@ public interface BriarIntegrationTestComponent {
ForumManager getForumManager();
GroupInvitationManager getGroupInvitationManager();
IntroductionManager getIntroductionManager();
MessageTracker getMessageTracker();

View File

@@ -0,0 +1,278 @@
package org.briarproject;
import org.briarproject.api.clients.ProtocolStateException;
import org.briarproject.api.db.DbException;
import org.briarproject.api.privategroup.GroupMessage;
import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupManager;
import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
import org.briarproject.api.privategroup.invitation.GroupInvitationRequest;
import org.briarproject.api.privategroup.invitation.GroupInvitationResponse;
import org.briarproject.api.sharing.InvitationMessage;
import org.briarproject.api.sync.Group;
import org.jetbrains.annotations.Nullable;
import org.junit.Before;
import org.junit.Test;
import java.util.Collection;
import static junit.framework.TestCase.fail;
import static org.briarproject.TestUtils.assertGroupCount;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class GroupInvitationIntegrationTest extends BriarIntegrationTest {
private PrivateGroup privateGroup0;
private PrivateGroupManager groupManager0, groupManager1;
private GroupInvitationManager groupInvitationManager0,
groupInvitationManager1;
@Before
public void setUp() throws Exception {
super.setUp();
groupManager0 = c0.getPrivateGroupManager();
groupManager1 = c1.getPrivateGroupManager();
groupInvitationManager0 = c0.getGroupInvitationManager();
groupInvitationManager1 = c1.getGroupInvitationManager();
privateGroup0 =
privateGroupFactory.createPrivateGroup("Testgroup", author0);
long joinTime = clock.currentTimeMillis();
GroupMessage joinMsg0 = groupMessageFactory
.createJoinMessage(privateGroup0.getId(), joinTime, author0);
groupManager0.addPrivateGroup(privateGroup0, joinMsg0, true);
}
@Test
public void testSendInvitation() throws Exception {
long timestamp = clock.currentTimeMillis();
String msg = "Hi!";
sendInvitation(timestamp, msg);
sync0To1(1, true);
Collection<GroupInvitationItem> invitations =
groupInvitationManager1.getInvitations();
assertEquals(1, invitations.size());
GroupInvitationItem item = invitations.iterator().next();
assertEquals(contact0From1, item.getCreator());
assertEquals(privateGroup0, item.getShareable());
assertEquals(privateGroup0.getId(), item.getId());
assertEquals(privateGroup0.getName(), item.getName());
assertFalse(item.isSubscribed());
Collection<InvitationMessage> messages =
groupInvitationManager1.getInvitationMessages(contactId0From1);
assertEquals(1, messages.size());
GroupInvitationRequest request =
(GroupInvitationRequest) messages.iterator().next();
assertEquals(msg, request.getMessage());
assertEquals(author0, request.getCreator());
assertEquals(timestamp, request.getTimestamp());
assertEquals(contactId0From1, request.getContactId());
assertEquals(privateGroup0.getName(), request.getGroupName());
assertFalse(request.isLocal());
assertFalse(request.isRead());
}
@Test
public void testInvitationDecline() throws Exception {
long timestamp = clock.currentTimeMillis();
sendInvitation(timestamp, null);
sync0To1(1, true);
assertFalse(groupInvitationManager1.getInvitations().isEmpty());
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, false);
Collection<InvitationMessage> messages =
groupInvitationManager1.getInvitationMessages(contactId0From1);
assertEquals(2, messages.size());
for (InvitationMessage m : messages) {
if (m instanceof GroupInvitationResponse) {
GroupInvitationResponse response = (GroupInvitationResponse) m;
assertEquals(contactId0From1, response.getContactId());
assertTrue(response.isLocal());
assertFalse(response.wasAccepted());
}
}
sync1To0(1, true);
messages =
groupInvitationManager0.getInvitationMessages(contactId1From0);
assertEquals(2, messages.size());
for (InvitationMessage m : messages) {
if (m instanceof GroupInvitationResponse) {
GroupInvitationResponse response = (GroupInvitationResponse) m;
assertEquals(contactId0From1, response.getContactId());
assertFalse(response.isLocal());
assertFalse(response.wasAccepted());
}
}
// no invitations are open
assertTrue(groupInvitationManager1.getInvitations().isEmpty());
// no groups were added
assertEquals(0, groupManager1.getPrivateGroups().size());
}
@Test
public void testInvitationAccept() throws Exception {
long timestamp = clock.currentTimeMillis();
sendInvitation(timestamp, null);
sync0To1(1, true);
assertFalse(groupInvitationManager1.getInvitations().isEmpty());
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, true);
Collection<InvitationMessage> messages =
groupInvitationManager1.getInvitationMessages(contactId0From1);
assertEquals(2, messages.size());
for (InvitationMessage m : messages) {
if (m instanceof GroupInvitationResponse) {
GroupInvitationResponse response = (GroupInvitationResponse) m;
assertTrue(response.wasAccepted());
}
}
sync1To0(1, true);
messages =
groupInvitationManager0.getInvitationMessages(contactId1From0);
assertEquals(2, messages.size());
for (InvitationMessage m : messages) {
if (m instanceof GroupInvitationResponse) {
GroupInvitationResponse response = (GroupInvitationResponse) m;
assertTrue(response.wasAccepted());
}
}
// no invitations are open
assertTrue(groupInvitationManager1.getInvitations().isEmpty());
// group was added
Collection<PrivateGroup> groups = groupManager1.getPrivateGroups();
assertEquals(1, groups.size());
assertEquals(privateGroup0, groups.iterator().next());
}
@Test
public void testGroupCount() throws Exception {
long timestamp = clock.currentTimeMillis();
sendInvitation(timestamp, null);
// 0 has one read outgoing message
Group g1 = groupInvitationManager0.getContactGroup(contact1From0);
assertGroupCount(messageTracker0, g1.getId(), 1, 0, timestamp);
sync0To1(1, true);
// 1 has one unread message
Group g0 = groupInvitationManager1.getContactGroup(contact0From1);
assertGroupCount(messageTracker1, g0.getId(), 1, 1, timestamp);
InvitationMessage m =
groupInvitationManager1.getInvitationMessages(contactId0From1)
.iterator().next();
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, true);
// 1 has two messages, one still unread
assertGroupCount(messageTracker1, g0.getId(), 2, 1);
// now all messages should be read
groupInvitationManager1.setReadFlag(g0.getId(), m.getId(), true);
assertGroupCount(messageTracker1, g0.getId(), 2, 0);
sync1To0(1, true);
// now 0 has two messages, one of them unread
assertGroupCount(messageTracker0, g1.getId(), 2, 1);
}
@Test
public void testMultipleInvitations() throws Exception {
sendInvitation(clock.currentTimeMillis(), null);
// invitation is not allowed before the first hasn't been answered
assertFalse(groupInvitationManager0
.isInvitationAllowed(contact1From0, privateGroup0.getId()));
// deliver invitation and response
sync0To1(1, true);
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, false);
sync1To0(1, true);
// after invitation was declined, inviting again is possible
assertTrue(groupInvitationManager0
.isInvitationAllowed(contact1From0, privateGroup0.getId()));
// send and accept the second invitation
sendInvitation(clock.currentTimeMillis(), "Second Invitation");
sync0To1(1, true);
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, true);
sync1To0(1, true);
// invitation is not allowed since the member joined the group now
assertFalse(groupInvitationManager0
.isInvitationAllowed(contact1From0, privateGroup0.getId()));
// don't allow another invitation request
try {
sendInvitation(clock.currentTimeMillis(), "Third Invitation");
fail();
} catch (ProtocolStateException e) {
// expected
}
}
@Test(expected = ProtocolStateException.class)
public void testInvitationsWithSameTimestamp() throws Exception {
long timestamp = clock.currentTimeMillis();
sendInvitation(timestamp, null);
sync0To1(1, true);
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, false);
sync1To0(1, true);
sendInvitation(timestamp, "Second Invitation");
sync0To1(1, true);
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, true);
}
@Test
public void testCreatorLeavesBeforeInvitationAnswered() throws Exception {
sendInvitation(clock.currentTimeMillis(), null);
sync0To1(1, true);
groupManager0.removePrivateGroup(privateGroup0.getId());
assertEquals(0, groupManager0.getPrivateGroups().size());
// sync0To1(1, true);
// FIXME
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, true);
sync1To0(1, true);
assertEquals(0, groupManager1.getPrivateGroups().size());
}
private void sendInvitation(long timestamp, @Nullable String msg) throws
DbException {
byte[] signature = groupInvitationFactory.signInvitation(contact1From0,
privateGroup0.getId(), timestamp, author0.getPrivateKey());
groupInvitationManager0
.sendInvitation(privateGroup0.getId(), contactId1From0, msg,
timestamp, signature);
}
}

View File

@@ -0,0 +1,197 @@
package org.briarproject;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.privategroup.GroupMember;
import org.briarproject.api.privategroup.GroupMessage;
import org.briarproject.api.privategroup.GroupMessageHeader;
import org.briarproject.api.privategroup.JoinMessageHeader;
import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupManager;
import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
import org.jetbrains.annotations.Nullable;
import org.junit.Before;
import org.junit.Test;
import java.util.Collection;
import static org.briarproject.api.identity.Author.Status.OURSELVES;
import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_CONTACT;
import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_US;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* This class tests how PrivateGroupManager and GroupInvitationManager
* play together.
*/
public class PrivateGroupIntegrationTest extends BriarIntegrationTest {
private GroupId groupId0;
private PrivateGroup privateGroup0;
private PrivateGroupManager groupManager0, groupManager1, groupManager2;
private GroupInvitationManager groupInvitationManager0,
groupInvitationManager1, groupInvitationManager2;
@Before
public void setUp() throws Exception {
super.setUp();
groupManager0 = c0.getPrivateGroupManager();
groupManager1 = c1.getPrivateGroupManager();
groupManager2 = c2.getPrivateGroupManager();
groupInvitationManager0 = c0.getGroupInvitationManager();
groupInvitationManager1 = c1.getGroupInvitationManager();
groupInvitationManager2 = c2.getGroupInvitationManager();
privateGroup0 =
privateGroupFactory.createPrivateGroup("Test Group", author0);
groupId0 = privateGroup0.getId();
long joinTime = clock.currentTimeMillis();
GroupMessage joinMsg0 = groupMessageFactory
.createJoinMessage(groupId0, joinTime, author0);
groupManager0.addPrivateGroup(privateGroup0, joinMsg0, true);
}
@Test
public void testMembership() throws Exception {
sendInvitation(contactId1From0, clock.currentTimeMillis(), "Hi!");
// our group has only one member (ourselves)
Collection<GroupMember> members = groupManager0.getMembers(groupId0);
assertEquals(1, members.size());
assertEquals(author0, members.iterator().next().getAuthor());
assertEquals(OURSELVES, members.iterator().next().getStatus());
sync0To1(1, true);
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, true);
sync1To0(1, true);
// sync group join messages
sync0To1(2, true); // + one invitation protocol join message
sync1To0(1, true);
// now the group has two members
members = groupManager0.getMembers(groupId0);
assertEquals(2, members.size());
members = groupManager1.getMembers(groupId0);
assertEquals(2, members.size());
// make sure 1's member list is as expected
for (GroupMember m : members) {
if (m.getStatus() != OURSELVES) {
assertEquals(author0.getId(), m.getAuthor().getId());
} else {
assertEquals(author1.getId(), m.getAuthor().getId());
}
}
}
@Test
public void testRevealContacts() throws Exception {
// invite two contacts
sendInvitation(contactId1From0, clock.currentTimeMillis(), "Hi 1!");
sendInvitation(contactId2From0, clock.currentTimeMillis(), "Hi 2!");
sync0To1(1, true);
sync0To2(1, true);
// accept both invitations
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, true);
groupInvitationManager2
.respondToInvitation(contactId0From2, privateGroup0, true);
sync1To0(1, true);
sync2To0(1, true);
// sync group join messages
sync0To1(2, true); // + one invitation protocol join message
assertEquals(2, groupManager1.getMembers(groupId0).size());
sync1To0(1, true);
assertEquals(2, groupManager0.getMembers(groupId0).size());
sync0To2(3, true); // 2 join messages and 1 invite join message
assertEquals(3, groupManager2.getMembers(groupId0).size());
sync2To0(1, true);
assertEquals(3, groupManager0.getMembers(groupId0).size());
sync0To1(1, true);
assertEquals(3, groupManager1.getMembers(groupId0).size());
// 1 and 2 add each other as contacts
addContacts1And2();
// their relationship is still invisible
assertEquals(INVISIBLE,
getGroupMember(groupManager1, author2.getId()).getVisibility());
assertEquals(INVISIBLE,
getGroupMember(groupManager2, author1.getId()).getVisibility());
// 1 reveals the contact relationship to 2
assertTrue(contactId2From1 != null);
groupInvitationManager1.revealRelationship(contactId2From1, groupId0);
sync1To2(1, true);
sync2To1(1, true);
// their relationship is now revealed
assertEquals(REVEALED_BY_US,
getGroupMember(groupManager1, author2.getId()).getVisibility());
assertEquals(REVEALED_BY_CONTACT,
getGroupMember(groupManager2, author1.getId()).getVisibility());
// 2 sends a message to the group
long time = clock.currentTimeMillis();
String body = "This is a test message!";
MessageId previousMsgId = groupManager2.getPreviousMsgId(groupId0);
GroupMessage msg = groupMessageFactory
.createGroupMessage(groupId0, time, null, author2, body,
previousMsgId);
groupManager2.addLocalMessage(msg);
// 1 has only the three join messages in the group
Collection<GroupMessageHeader> headers =
groupManager1.getHeaders(groupId0);
assertEquals(3, headers.size());
// message should sync to 1 without creator (0) being involved
sync2To1(1, true);
headers = groupManager1.getHeaders(groupId0);
assertEquals(4, headers.size());
for (GroupMessageHeader h : headers) {
if (h instanceof JoinMessageHeader) continue;
assertEquals(time, h.getTimestamp());
assertEquals(groupId0, h.getGroupId());
assertEquals(author2.getId(), h.getAuthor().getId());
}
// message should sync from 1 to 0 without 2 being involved
sync1To0(1, true);
headers = groupManager0.getHeaders(groupId0);
assertEquals(4, headers.size());
}
private void sendInvitation(ContactId c, long timestamp,
@Nullable String msg) throws DbException {
Contact contact = contactManager0.getContact(c);
byte[] signature = groupInvitationFactory
.signInvitation(contact, groupId0, timestamp,
author0.getPrivateKey());
groupInvitationManager0
.sendInvitation(groupId0, c, msg, timestamp, signature);
}
private GroupMember getGroupMember(PrivateGroupManager groupManager,
AuthorId a) throws DbException {
Collection<GroupMember> members = groupManager.getMembers(groupId0);
for (GroupMember m : members) {
if (m.getAuthor().getId().equals(a)) return m;
}
fail();
throw new RuntimeException();
}
}