Fixed a bug in the group invitation protocol, added tests.

This commit is contained in:
akwizgran
2016-11-30 11:12:04 +00:00
parent 6c90204c6e
commit d51f73151f
3 changed files with 131 additions and 8 deletions

View File

@@ -265,8 +265,8 @@ public class GroupInvitationIntegrationTest extends BriarIntegrationTest {
.respondToInvitation(contactId0From1, privateGroup0, true);
}
@Test
public void testCreatorLeavesBeforeInvitationAnswered() throws Exception {
@Test(expected = ProtocolStateException.class)
public void testCreatorLeavesBeforeInvitationAccepted() throws Exception {
// Creator invites invitee to join group
sendInvitation(clock.currentTimeMillis(), null);
@@ -278,7 +278,54 @@ public class GroupInvitationIntegrationTest extends BriarIntegrationTest {
groupManager0.removePrivateGroup(privateGroup0.getId());
assertEquals(0, groupManager0.getPrivateGroups().size());
// Invitee responds to invitation
// 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);
@@ -293,7 +340,67 @@ public class GroupInvitationIntegrationTest extends BriarIntegrationTest {
// 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

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