Merge branch '760-integration-tests-for-private-group-invitation-protocol' into 'master'

Add integration tests for GroupInvitationManager

This MR is based on !433. It adds some integration tests for the private group invitation protocol. One of those tests fails at the moment.

It does not yet cover all corner cases, so it does not fully address #760, but addresses a part of it. Suggestions for more scenarios to test are welcome.

[Wording changed to prevent #760 from being closed automatically based on the description.]

See merge request !434
This commit is contained in:
akwizgran
2016-11-30 11:19:05 +00:00
7 changed files with 648 additions and 9 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,415 @@
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
@Override
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());
boolean foundResponse = false;
for (InvitationMessage m : messages) {
if (m instanceof GroupInvitationResponse) {
foundResponse = true;
GroupInvitationResponse response = (GroupInvitationResponse) m;
assertEquals(contactId0From1, response.getContactId());
assertTrue(response.isLocal());
assertFalse(response.wasAccepted());
}
}
assertTrue(foundResponse);
sync1To0(1, true);
messages =
groupInvitationManager0.getInvitationMessages(contactId1From0);
assertEquals(2, messages.size());
foundResponse = false;
for (InvitationMessage m : messages) {
if (m instanceof GroupInvitationResponse) {
foundResponse = true;
GroupInvitationResponse response = (GroupInvitationResponse) m;
assertEquals(contactId0From1, response.getContactId());
assertFalse(response.isLocal());
assertFalse(response.wasAccepted());
}
}
assertTrue(foundResponse);
// 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());
boolean foundResponse = false;
for (InvitationMessage m : messages) {
if (m instanceof GroupInvitationResponse) {
foundResponse = true;
GroupInvitationResponse response = (GroupInvitationResponse) m;
assertTrue(response.wasAccepted());
}
}
assertTrue(foundResponse);
sync1To0(1, true);
messages =
groupInvitationManager0.getInvitationMessages(contactId1From0);
assertEquals(2, messages.size());
foundResponse = false;
for (InvitationMessage m : messages) {
if (m instanceof GroupInvitationResponse) {
foundResponse = true;
GroupInvitationResponse response = (GroupInvitationResponse) m;
assertTrue(response.wasAccepted());
}
}
assertTrue(foundResponse);
// 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(expected = ProtocolStateException.class)
public void testCreatorLeavesBeforeInvitationAccepted() throws Exception {
// Creator invites invitee to join group
sendInvitation(clock.currentTimeMillis(), null);
// Creator's invite message is delivered to invitee
sync0To1(1, true);
// Creator leaves group
assertEquals(1, groupManager0.getPrivateGroups().size());
groupManager0.removePrivateGroup(privateGroup0.getId());
assertEquals(0, groupManager0.getPrivateGroups().size());
// Creator's leave message is delivered to invitee
sync0To1(1, true);
// Invitee accepts invitation, but it's no longer open - exception is
// thrown as the action has failed
assertEquals(0, groupManager1.getPrivateGroups().size());
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, true);
}
@Test
public void testCreatorLeavesBeforeInvitationDeclined() throws Exception {
// Creator invites invitee to join group
sendInvitation(clock.currentTimeMillis(), null);
// Creator's invite message is delivered to invitee
sync0To1(1, true);
// Creator leaves group
assertEquals(1, groupManager0.getPrivateGroups().size());
groupManager0.removePrivateGroup(privateGroup0.getId());
assertEquals(0, groupManager0.getPrivateGroups().size());
// Creator's leave message is delivered to invitee
sync0To1(1, true);
// Invitee declines invitation, but it's no longer open - no exception
// as the action has succeeded
assertEquals(0, groupManager1.getPrivateGroups().size());
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, false);
}
@Test
public void testCreatorLeavesConcurrentlyWithInvitationAccepted()
throws Exception {
// Creator invites invitee to join group
sendInvitation(clock.currentTimeMillis(), null);
// Creator's invite message is delivered to invitee
sync0To1(1, true);
// Creator leaves group
assertEquals(1, groupManager0.getPrivateGroups().size());
groupManager0.removePrivateGroup(privateGroup0.getId());
assertEquals(0, groupManager0.getPrivateGroups().size());
// Invitee accepts invitation
assertEquals(0, groupManager1.getPrivateGroups().size());
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, true);
assertEquals(1, groupManager1.getPrivateGroups().size());
assertFalse(groupManager1.isDissolved(privateGroup0.getId()));
// Invitee's join message is delivered to creator
sync1To0(1, true);
// Creator's leave message is delivered to invitee
sync0To1(1, true);
// Group is marked as dissolved
assertTrue(groupManager1.isDissolved(privateGroup0.getId()));
}
@Test
public void testCreatorLeavesConcurrentlyWithInvitationDeclined()
throws Exception {
// Creator invites invitee to join group
sendInvitation(clock.currentTimeMillis(), null);
// Creator's invite message is delivered to invitee
sync0To1(1, true);
// Creator leaves group
assertEquals(1, groupManager0.getPrivateGroups().size());
groupManager0.removePrivateGroup(privateGroup0.getId());
assertEquals(0, groupManager0.getPrivateGroups().size());
// Invitee declines invitation
assertEquals(0, groupManager1.getPrivateGroups().size());
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, false);
assertEquals(0, groupManager1.getPrivateGroups().size());
// Invitee's leave message is delivered to creator
sync1To0(1, true);
// Creator's leave message is delivered to invitee
sync0To1(1, true);
}
@Test
public void testCreatorLeavesConcurrentlyWithMemberLeaving()
throws Exception {
// Creator invites invitee to join group
sendInvitation(clock.currentTimeMillis(), null);
// Creator's invite message is delivered to invitee
sync0To1(1, true);
// Invitee responds to invitation
assertEquals(0, groupManager1.getPrivateGroups().size());
groupInvitationManager1
.respondToInvitation(contactId0From1, privateGroup0, true);
assertEquals(1, groupManager1.getPrivateGroups().size());
// Invitee's join message is delivered to creator
sync1To0(1, true);
// Creator leaves group
assertEquals(1, groupManager0.getPrivateGroups().size());
groupManager0.removePrivateGroup(privateGroup0.getId());
assertEquals(0, groupManager0.getPrivateGroups().size());
// Invitee leaves group
groupManager1.removePrivateGroup(privateGroup0.getId());
assertEquals(0, groupManager1.getPrivateGroups().size());
// Creator's leave message is delivered to invitee
sync0To1(1, true);
// Invitee's leave message is delivered to creator
sync1To0(1, true);
}
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,205 @@
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;
/**
* 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
@Override
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());
for (GroupMember m : members) {
if (m.getStatus() == OURSELVES) {
assertEquals(author0.getId(), m.getAuthor().getId());
} else {
assertEquals(author1.getId(), m.getAuthor().getId());
}
}
members = groupManager1.getMembers(groupId0);
assertEquals(2, members.size());
for (GroupMember m : members) {
if (m.getStatus() == OURSELVES) {
assertEquals(author1.getId(), m.getAuthor().getId());
} else {
assertEquals(author0.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());
boolean foundPost = false;
for (GroupMessageHeader h : headers) {
if (h instanceof JoinMessageHeader) continue;
foundPost = true;
assertEquals(time, h.getTimestamp());
assertEquals(groupId0, h.getGroupId());
assertEquals(author2.getId(), h.getAuthor().getId());
}
assertTrue(foundPost);
// 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;
}
throw new AssertionError();
}
}

View File

@@ -74,7 +74,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
private final Group localGroup;
@Inject
protected GroupInvitationManagerImpl(DatabaseComponent db,
GroupInvitationManagerImpl(DatabaseComponent db,
ClientHelper clientHelper, MetadataParser metadataParser,
MessageTracker messageTracker,
ContactGroupFactory contactGroupFactory,

View File

@@ -148,10 +148,11 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
case DISSOLVED:
return abort(txn, s); // Invalid in these states
case INVITED:
case LEFT:
return onRemoteLeaveWhenNotSubscribed(txn, s, m);
case ACCEPTED:
case JOINED:
case LEFT:
return onRemoteLeave(txn, s, m);
return onRemoteLeaveWhenSubscribed(txn, s, m);
case ERROR:
return s; // Ignored in this state
default:
@@ -260,8 +261,23 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
s.getInviteTimestamp(), JOINED);
}
private InviteeSession onRemoteLeave(Transaction txn, InviteeSession s,
LeaveMessage m) throws DbException, FormatException {
private InviteeSession onRemoteLeaveWhenNotSubscribed(Transaction txn,
InviteeSession s, LeaveMessage m)
throws DbException, FormatException {
// The timestamp must be higher than the last invite message, if any
if (m.getTimestamp() <= s.getInviteTimestamp()) return abort(txn, s);
// The dependency, if any, must be the last remote message
if (!isValidDependency(s, m.getPreviousMessageId()))
return abort(txn, s);
// Move to the DISSOLVED state
return new InviteeSession(s.getContactGroupId(), s.getPrivateGroupId(),
s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(),
s.getInviteTimestamp(), DISSOLVED);
}
private InviteeSession onRemoteLeaveWhenSubscribed(Transaction txn,
InviteeSession s, LeaveMessage m)
throws DbException, FormatException {
// The timestamp must be higher than the last invite message, if any
if (m.getTimestamp() <= s.getInviteTimestamp()) return abort(txn, s);
// The dependency, if any, must be the last remote message

View File

@@ -8,7 +8,6 @@ import org.briarproject.api.clients.BdfMessageContext;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.sync.InvalidMessageException;
import org.briarproject.api.sync.MessageId;
@@ -29,9 +28,6 @@ import static org.junit.Assert.assertFalse;
public class ForumPostValidatorTest extends ValidatorTestCase {
private final AuthorFactory authorFactory =
context.mock(AuthorFactory.class);
private final MessageId parentId = new MessageId(TestUtils.getRandomId());
private final String authorName =
TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);