mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Add unit tests for group invitation client
This commit is contained in:
@@ -0,0 +1,924 @@
|
||||
package org.briarproject.privategroup.invitation;
|
||||
|
||||
import org.briarproject.BriarMockTestCase;
|
||||
import org.briarproject.TestUtils;
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.clients.ContactGroupFactory;
|
||||
import org.briarproject.api.clients.MessageTracker;
|
||||
import org.briarproject.api.clients.SessionId;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.data.BdfEntry;
|
||||
import org.briarproject.api.data.BdfList;
|
||||
import org.briarproject.api.data.MetadataParser;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.Metadata;
|
||||
import org.briarproject.api.db.Transaction;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.privategroup.PrivateGroup;
|
||||
import org.briarproject.api.privategroup.PrivateGroupFactory;
|
||||
import org.briarproject.api.privategroup.PrivateGroupManager;
|
||||
import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
|
||||
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.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jmock.AbstractExpectations;
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.lib.legacy.ClassImposteriser;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static junit.framework.TestCase.fail;
|
||||
import static org.briarproject.TestUtils.getRandomBytes;
|
||||
import static org.briarproject.TestUtils.getRandomId;
|
||||
import static org.briarproject.TestUtils.getRandomString;
|
||||
import static org.briarproject.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
|
||||
import static org.briarproject.api.sync.Group.Visibility.SHARED;
|
||||
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
||||
import static org.briarproject.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
|
||||
import static org.briarproject.privategroup.invitation.MessageType.ABORT;
|
||||
import static org.briarproject.privategroup.invitation.MessageType.INVITE;
|
||||
import static org.briarproject.privategroup.invitation.MessageType.JOIN;
|
||||
import static org.briarproject.privategroup.invitation.MessageType.LEAVE;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class GroupInvitationManagerImplTest extends BriarMockTestCase {
|
||||
|
||||
private final GroupInvitationManagerImpl groupInvitationManager;
|
||||
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
|
||||
private final ContactGroupFactory contactGroupFactory =
|
||||
context.mock(ContactGroupFactory.class);
|
||||
private final PrivateGroupFactory privateGroupFactory =
|
||||
context.mock(PrivateGroupFactory.class);
|
||||
private final PrivateGroupManager privateGroupManager =
|
||||
context.mock(PrivateGroupManager.class);
|
||||
private final MessageParser messageParser =
|
||||
context.mock(MessageParser.class);
|
||||
private final SessionParser sessionParser =
|
||||
context.mock(SessionParser.class);
|
||||
private final SessionEncoder sessionEncoder =
|
||||
context.mock(SessionEncoder.class);
|
||||
private final ProtocolEngineFactory engineFactory =
|
||||
context.mock(ProtocolEngineFactory.class);
|
||||
private final CreatorProtocolEngine creatorEngine;
|
||||
private final InviteeProtocolEngine inviteeEngine;
|
||||
private final PeerProtocolEngine peerEngine;
|
||||
private final CreatorSession creatorSession;
|
||||
private final InviteeSession inviteeSession;
|
||||
private final PeerSession peerSession;
|
||||
private final Group localGroup =
|
||||
new Group(new GroupId(getRandomId()), CLIENT_ID, getRandomBytes(5));
|
||||
private final Transaction txn = new Transaction(null, false);
|
||||
private final ContactId contactId = new ContactId(0);
|
||||
private final Author author =
|
||||
new Author(new AuthorId(getRandomId()), getRandomString(5),
|
||||
getRandomBytes(5));
|
||||
private final Contact contact =
|
||||
new Contact(contactId, author, new AuthorId(getRandomId()), true,
|
||||
true);
|
||||
private final Group contactGroup =
|
||||
new Group(new GroupId(getRandomId()), CLIENT_ID, getRandomBytes(5));
|
||||
private final Group privateGroup =
|
||||
new Group(new GroupId(getRandomId()), CLIENT_ID, getRandomBytes(5));
|
||||
private final BdfDictionary meta = BdfDictionary.of(new BdfEntry("f", "o"));
|
||||
private final Message message =
|
||||
new Message(new MessageId(getRandomId()), contactGroup.getId(),
|
||||
0L, getRandomBytes(MESSAGE_HEADER_LENGTH + 1));
|
||||
private final BdfList body = new BdfList();
|
||||
private final Message storageMessage =
|
||||
new Message(new MessageId(getRandomId()), contactGroup.getId(),
|
||||
0L, getRandomBytes(MESSAGE_HEADER_LENGTH + 1));
|
||||
|
||||
public GroupInvitationManagerImplTest() {
|
||||
context.setImposteriser(ClassImposteriser.INSTANCE);
|
||||
creatorEngine = context.mock(CreatorProtocolEngine.class);
|
||||
inviteeEngine = context.mock(InviteeProtocolEngine.class);
|
||||
peerEngine = context.mock(PeerProtocolEngine.class);
|
||||
|
||||
creatorSession = context.mock(CreatorSession.class);
|
||||
inviteeSession = context.mock(InviteeSession.class);
|
||||
peerSession = context.mock(PeerSession.class);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(engineFactory).createCreatorEngine();
|
||||
will(returnValue(creatorEngine));
|
||||
oneOf(engineFactory).createInviteeEngine();
|
||||
will(returnValue(inviteeEngine));
|
||||
oneOf(engineFactory).createPeerEngine();
|
||||
will(returnValue(peerEngine));
|
||||
oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID);
|
||||
will(returnValue(localGroup));
|
||||
}});
|
||||
MetadataParser metadataParser = context.mock(MetadataParser.class);
|
||||
MessageTracker messageTracker = context.mock(MessageTracker.class);
|
||||
groupInvitationManager =
|
||||
new GroupInvitationManagerImpl(db, clientHelper, metadataParser,
|
||||
messageTracker, contactGroupFactory,
|
||||
privateGroupFactory, privateGroupManager, messageParser,
|
||||
sessionParser, sessionEncoder, engineFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateLocalState() throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).addGroup(txn, localGroup);
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(Collections.singletonList(contact)));
|
||||
}});
|
||||
expectAddingContact(contact, true);
|
||||
groupInvitationManager.createLocalState(txn);
|
||||
}
|
||||
|
||||
private void expectAddingContact(final Contact c,
|
||||
final boolean contactExists) throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, c);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(db).containsGroup(txn, contactGroup.getId());
|
||||
will(returnValue(contactExists));
|
||||
}});
|
||||
if (contactExists) return;
|
||||
|
||||
final BdfDictionary meta = BdfDictionary
|
||||
.of(new BdfEntry(GROUP_KEY_CONTACT_ID, c.getId().getInt()));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).addGroup(txn, contactGroup);
|
||||
oneOf(db).setGroupVisibility(txn, c.getId(), contactGroup.getId(),
|
||||
SHARED);
|
||||
oneOf(clientHelper)
|
||||
.mergeGroupMetadata(txn, contactGroup.getId(), meta);
|
||||
oneOf(db).getGroups(txn, PrivateGroupManager.CLIENT_ID);
|
||||
will(returnValue(Collections.singletonList(privateGroup)));
|
||||
oneOf(privateGroupManager)
|
||||
.isMember(txn, privateGroup.getId(), c.getAuthor());
|
||||
will(returnValue(true));
|
||||
}});
|
||||
expectAddingMember(privateGroup.getId(), c);
|
||||
}
|
||||
|
||||
private void expectAddingMember(final GroupId g, final Contact c)
|
||||
throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, c);
|
||||
will(returnValue(contactGroup));
|
||||
}});
|
||||
expectGetSession(Collections.<MessageId, BdfDictionary>emptyMap(),
|
||||
new SessionId(g.getBytes()));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(peerEngine).onMemberAddedAction(with(equal(txn)),
|
||||
with(any(PeerSession.class)));
|
||||
will(returnValue(peerSession));
|
||||
}});
|
||||
expectStoreSession(peerSession, storageMessage.getId());
|
||||
expectCreateStorageId();
|
||||
}
|
||||
|
||||
private void expectCreateStorageId() throws DbException {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper)
|
||||
.createMessageForStoringMetadata(contactGroup.getId());
|
||||
will(returnValue(storageMessage));
|
||||
oneOf(db).addLocalMessage(txn, storageMessage, new Metadata(),
|
||||
false);
|
||||
}});
|
||||
}
|
||||
|
||||
private void expectStoreSession(final Session session,
|
||||
final MessageId storageId) throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(sessionEncoder).encodeSession(session);
|
||||
will(returnValue(meta));
|
||||
oneOf(clientHelper).mergeMessageMetadata(txn, storageId, meta);
|
||||
}});
|
||||
}
|
||||
|
||||
private void expectGetSession(final Map<MessageId, BdfDictionary> result,
|
||||
final SessionId sessionId) throws Exception {
|
||||
final BdfDictionary query = BdfDictionary.of(new BdfEntry("q", "u"));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(sessionParser).getSessionQuery(sessionId);
|
||||
will(returnValue(query));
|
||||
oneOf(clientHelper)
|
||||
.getMessageMetadataAsDictionary(txn, contactGroup.getId(),
|
||||
query);
|
||||
will(returnValue(result));
|
||||
}});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingContact() throws Exception {
|
||||
expectAddingContact(contact, false);
|
||||
groupInvitationManager.addingContact(txn, contact);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemovingContact() throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(db).removeGroup(txn, contactGroup);
|
||||
}});
|
||||
groupInvitationManager.removingContact(txn, contact);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testIncomingUnknownMessage() throws Exception {
|
||||
expectFirstIncomingMessage(Role.INVITEE, ABORT);
|
||||
groupInvitationManager.incomingMessage(txn, message, body, meta);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncomingFirstInviteMessage() throws Exception {
|
||||
expectFirstIncomingMessage(Role.INVITEE, INVITE);
|
||||
groupInvitationManager.incomingMessage(txn, message, body, meta);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncomingFirstJoinMessage() throws Exception {
|
||||
expectFirstIncomingMessage(Role.PEER, JOIN);
|
||||
groupInvitationManager.incomingMessage(txn, message, body, meta);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncomingInviteMessage() throws Exception {
|
||||
expectIncomingMessage(Role.INVITEE, INVITE);
|
||||
groupInvitationManager.incomingMessage(txn, message, body, meta);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncomingJoinMessage() throws Exception {
|
||||
expectIncomingMessage(Role.INVITEE, JOIN);
|
||||
groupInvitationManager.incomingMessage(txn, message, body, meta);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncomingJoinMessageForCreator() throws Exception {
|
||||
expectIncomingMessage(Role.CREATOR, JOIN);
|
||||
groupInvitationManager.incomingMessage(txn, message, body, meta);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncomingLeaveMessage() throws Exception {
|
||||
expectIncomingMessage(Role.INVITEE, LEAVE);
|
||||
groupInvitationManager.incomingMessage(txn, message, body, meta);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncomingAbortMessage() throws Exception {
|
||||
expectIncomingMessage(Role.INVITEE, ABORT);
|
||||
groupInvitationManager.incomingMessage(txn, message, body, meta);
|
||||
}
|
||||
|
||||
private void expectFirstIncomingMessage(Role role, MessageType type)
|
||||
throws Exception {
|
||||
expectIncomingMessage(role, type,
|
||||
Collections.<MessageId, BdfDictionary>emptyMap());
|
||||
}
|
||||
|
||||
private void expectIncomingMessage(Role role, MessageType type)
|
||||
throws Exception {
|
||||
BdfDictionary state = BdfDictionary.of(new BdfEntry("state", "test"));
|
||||
Map<MessageId, BdfDictionary> states =
|
||||
Collections.singletonMap(storageMessage.getId(), state);
|
||||
expectIncomingMessage(role, type, states);
|
||||
}
|
||||
|
||||
private void expectIncomingMessage(final Role role,
|
||||
final MessageType type, final Map<MessageId, BdfDictionary> states)
|
||||
throws Exception {
|
||||
final MessageMetadata messageMetadata =
|
||||
context.mock(MessageMetadata.class);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageParser).parseMetadata(meta);
|
||||
will(returnValue(messageMetadata));
|
||||
oneOf(messageMetadata).getPrivateGroupId();
|
||||
will(returnValue(privateGroup.getId()));
|
||||
}});
|
||||
expectGetSession(states,
|
||||
new SessionId(privateGroup.getId().getBytes()));
|
||||
|
||||
Session session;
|
||||
if (states.isEmpty()) {
|
||||
session = expectHandleFirstMessage(role, messageMetadata, type);
|
||||
if (session != null) {
|
||||
expectCreateStorageId();
|
||||
expectStoreSession(session, storageMessage.getId());
|
||||
}
|
||||
} else {
|
||||
assertEquals(1, states.size());
|
||||
session = expectHandleMessage(role, messageMetadata,
|
||||
states.values().iterator().next(), type);
|
||||
expectStoreSession(session, storageMessage.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Session expectHandleFirstMessage(Role role,
|
||||
final MessageMetadata messageMetadata, final MessageType type)
|
||||
throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageMetadata).getPrivateGroupId();
|
||||
will(returnValue(privateGroup.getId()));
|
||||
oneOf(messageMetadata).getMessageType();
|
||||
will(returnValue(type));
|
||||
}});
|
||||
if (type == ABORT || type == LEAVE) return null;
|
||||
|
||||
AbstractProtocolEngine engine;
|
||||
Session session;
|
||||
if (type == INVITE) {
|
||||
assertEquals(Role.INVITEE, role);
|
||||
engine = inviteeEngine;
|
||||
session = inviteeSession;
|
||||
} else if (type == JOIN) {
|
||||
assertEquals(Role.PEER, role);
|
||||
engine = peerEngine;
|
||||
session = peerSession;
|
||||
} else {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
expectIndividualMessage(type, engine, session);
|
||||
return session;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Session expectHandleMessage(final Role role,
|
||||
final MessageMetadata messageMetadata, final BdfDictionary state,
|
||||
final MessageType type) throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageMetadata).getMessageType();
|
||||
will(returnValue(type));
|
||||
oneOf(sessionParser).getRole(state);
|
||||
will(returnValue(role));
|
||||
}});
|
||||
if (role == Role.CREATOR) {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(sessionParser)
|
||||
.parseCreatorSession(contactGroup.getId(), state);
|
||||
will(returnValue(creatorSession));
|
||||
}});
|
||||
expectIndividualMessage(type, creatorEngine, creatorSession);
|
||||
return creatorSession;
|
||||
} else if (role == Role.INVITEE) {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(sessionParser)
|
||||
.parseInviteeSession(contactGroup.getId(), state);
|
||||
will(returnValue(inviteeSession));
|
||||
}});
|
||||
expectIndividualMessage(type, inviteeEngine, inviteeSession);
|
||||
return inviteeSession;
|
||||
} else if (role == Role.PEER) {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(sessionParser)
|
||||
.parsePeerSession(contactGroup.getId(), state);
|
||||
will(returnValue(peerSession));
|
||||
}});
|
||||
expectIndividualMessage(type, peerEngine, peerSession);
|
||||
return peerSession;
|
||||
} else {
|
||||
fail();
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private <S extends Session> void expectIndividualMessage(
|
||||
final MessageType type, final ProtocolEngine<S> engine,
|
||||
final S session) throws Exception {
|
||||
if (type == INVITE) {
|
||||
final InviteMessage msg = context.mock(InviteMessage.class);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageParser).parseInviteMessage(message, body);
|
||||
will(returnValue(msg));
|
||||
oneOf(engine).onInviteMessage(with(equal(txn)),
|
||||
with(AbstractExpectations.<S>anything()),
|
||||
with(equal(msg)));
|
||||
will(returnValue(session));
|
||||
}});
|
||||
} else if (type == JOIN) {
|
||||
final JoinMessage msg = context.mock(JoinMessage.class);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageParser).parseJoinMessage(message, body);
|
||||
will(returnValue(msg));
|
||||
oneOf(engine).onJoinMessage(with(equal(txn)),
|
||||
with(AbstractExpectations.<S>anything()),
|
||||
with(equal(msg)));
|
||||
will(returnValue(session));
|
||||
}});
|
||||
} else if (type == LEAVE) {
|
||||
final LeaveMessage msg = context.mock(LeaveMessage.class);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageParser).parseLeaveMessage(message, body);
|
||||
will(returnValue(msg));
|
||||
oneOf(engine).onLeaveMessage(with(equal(txn)),
|
||||
with(AbstractExpectations.<S>anything()),
|
||||
with(equal(msg)));
|
||||
will(returnValue(session));
|
||||
}});
|
||||
} else if (type == ABORT) {
|
||||
final AbortMessage msg = context.mock(AbortMessage.class);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageParser).parseAbortMessage(message, body);
|
||||
will(returnValue(msg));
|
||||
oneOf(engine).onAbortMessage(with(equal(txn)),
|
||||
with(AbstractExpectations.<S>anything()),
|
||||
with(equal(msg)));
|
||||
will(returnValue(session));
|
||||
}});
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendFirstInvitation() throws Exception {
|
||||
final String msg = "Invitation text for first invitation";
|
||||
final long time = 42L;
|
||||
final byte[] signature = TestUtils.getRandomBytes(42);
|
||||
Map<MessageId, BdfDictionary> states = Collections.emptyMap();
|
||||
|
||||
expectGetSession(states,
|
||||
new SessionId(privateGroup.getId().getBytes()));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getContact(txn, contactId);
|
||||
will(returnValue(contact));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
}});
|
||||
expectCreateStorageId();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(creatorEngine).onInviteAction(with(same(txn)),
|
||||
with(any(CreatorSession.class)), with(equal(msg)),
|
||||
with(equal(time)), with(equal(signature)));
|
||||
will(returnValue(creatorSession));
|
||||
}});
|
||||
expectStoreSession(creatorSession, storageMessage.getId());
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
groupInvitationManager.sendInvitation(privateGroup.getId(), contactId,
|
||||
msg, time, signature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendSubsequentInvitation() throws Exception {
|
||||
final String msg = "Invitation text for subsequent invitation";
|
||||
final long time = 43L;
|
||||
final byte[] signature = TestUtils.getRandomBytes(43);
|
||||
final BdfDictionary state =
|
||||
BdfDictionary.of(new BdfEntry("state", "test"));
|
||||
Map<MessageId, BdfDictionary> states =
|
||||
Collections.singletonMap(storageMessage.getId(), state);
|
||||
|
||||
expectGetSession(states,
|
||||
new SessionId(privateGroup.getId().getBytes()));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getContact(txn, contactId);
|
||||
will(returnValue(contact));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(sessionParser)
|
||||
.parseCreatorSession(contactGroup.getId(), state);
|
||||
will(returnValue(creatorSession));
|
||||
oneOf(creatorEngine).onInviteAction(with(same(txn)),
|
||||
with(any(CreatorSession.class)), with(equal(msg)),
|
||||
with(equal(time)), with(equal(signature)));
|
||||
will(returnValue(creatorSession));
|
||||
}});
|
||||
expectStoreSession(creatorSession, storageMessage.getId());
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
groupInvitationManager.sendInvitation(privateGroup.getId(), contactId,
|
||||
msg, time, signature);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testRespondToInvitationWithoutSession() throws Exception {
|
||||
final SessionId sessionId = new SessionId(getRandomId());
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getContact(txn, contactId);
|
||||
will(returnValue(contact));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
expectGetSession(Collections.<MessageId, BdfDictionary>emptyMap(),
|
||||
sessionId);
|
||||
|
||||
groupInvitationManager.respondToInvitation(contactId, sessionId, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptInvitationWithSession() throws Exception {
|
||||
final boolean accept = true;
|
||||
SessionId sessionId = new SessionId(getRandomId());
|
||||
BdfDictionary state = BdfDictionary.of(new BdfEntry("f", "o"));
|
||||
Map<MessageId, BdfDictionary> states =
|
||||
Collections.singletonMap(storageMessage.getId(), state);
|
||||
|
||||
expectRespondToInvitation(states, sessionId, accept);
|
||||
groupInvitationManager
|
||||
.respondToInvitation(contactId, sessionId, accept);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeclineInvitationWithSession() throws Exception {
|
||||
final boolean accept = false;
|
||||
SessionId sessionId = new SessionId(getRandomId());
|
||||
BdfDictionary state = BdfDictionary.of(new BdfEntry("f", "o"));
|
||||
Map<MessageId, BdfDictionary> states =
|
||||
Collections.singletonMap(storageMessage.getId(), state);
|
||||
|
||||
expectRespondToInvitation(states, sessionId, accept);
|
||||
groupInvitationManager
|
||||
.respondToInvitation(contactId, sessionId, accept);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRespondToInvitationWithGroupId() throws Exception {
|
||||
final boolean accept = true;
|
||||
final PrivateGroup g = context.mock(PrivateGroup.class);
|
||||
SessionId sessionId = new SessionId(privateGroup.getId().getBytes());
|
||||
BdfDictionary state = BdfDictionary.of(new BdfEntry("f", "o"));
|
||||
Map<MessageId, BdfDictionary> states =
|
||||
Collections.singletonMap(storageMessage.getId(), state);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(g).getId();
|
||||
will(returnValue(privateGroup.getId()));
|
||||
}});
|
||||
expectRespondToInvitation(states, sessionId, accept);
|
||||
groupInvitationManager.respondToInvitation(contactId, g, accept);
|
||||
}
|
||||
|
||||
private void expectRespondToInvitation(
|
||||
final Map<MessageId, BdfDictionary> states,
|
||||
final SessionId sessionId, final boolean accept) throws Exception {
|
||||
expectGetSession(states, sessionId);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getContact(txn, contactId);
|
||||
will(returnValue(contact));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
}});
|
||||
|
||||
if (states.isEmpty()) return;
|
||||
assertEquals(1, states.size());
|
||||
|
||||
final BdfDictionary state = states.values().iterator().next();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(sessionParser)
|
||||
.parseInviteeSession(contactGroup.getId(), state);
|
||||
will(returnValue(inviteeSession));
|
||||
if (accept) oneOf(inviteeEngine).onJoinAction(txn, inviteeSession);
|
||||
else oneOf(inviteeEngine).onLeaveAction(txn, inviteeSession);
|
||||
will(returnValue(inviteeSession));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
expectStoreSession(inviteeSession, storageMessage.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevealRelationship() throws Exception {
|
||||
SessionId sessionId = new SessionId(privateGroup.getId().getBytes());
|
||||
final BdfDictionary state = BdfDictionary.of(new BdfEntry("f", "o"));
|
||||
Map<MessageId, BdfDictionary> states =
|
||||
Collections.singletonMap(storageMessage.getId(), state);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getContact(txn, contactId);
|
||||
will(returnValue(contact));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(sessionParser).parsePeerSession(contactGroup.getId(), state);
|
||||
will(returnValue(peerSession));
|
||||
oneOf(peerEngine).onJoinAction(txn, peerSession);
|
||||
will(returnValue(peerSession));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
expectGetSession(states, sessionId);
|
||||
expectStoreSession(peerSession, storageMessage.getId());
|
||||
|
||||
groupInvitationManager
|
||||
.revealRelationship(contactId, privateGroup.getId());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testRevealRelationshipWithoutSession() throws Exception {
|
||||
SessionId sessionId = new SessionId(privateGroup.getId().getBytes());
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getContact(txn, contactId);
|
||||
will(returnValue(contact));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
expectGetSession(Collections.<MessageId, BdfDictionary>emptyMap(),
|
||||
sessionId);
|
||||
|
||||
groupInvitationManager
|
||||
.revealRelationship(contactId, privateGroup.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInvitationMessages() throws Exception {
|
||||
final BdfDictionary query = new BdfDictionary();
|
||||
final BdfDictionary d1 = BdfDictionary.of(new BdfEntry("m1", "d"));
|
||||
final BdfDictionary d2 = BdfDictionary.of(new BdfEntry("m2", "d"));
|
||||
final Map<MessageId, BdfDictionary> results = new HashMap<>();
|
||||
results.put(message.getId(), d1);
|
||||
results.put(storageMessage.getId(), d2);
|
||||
long time1 = 1L, time2 = 2L;
|
||||
final MessageMetadata meta1 =
|
||||
new MessageMetadata(INVITE, privateGroup.getId(), time1, true,
|
||||
true, true, true);
|
||||
final MessageMetadata meta2 =
|
||||
new MessageMetadata(JOIN, privateGroup.getId(), time2, true,
|
||||
true, true, true);
|
||||
final BdfList list1 = BdfList.of(1);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getContact(txn, contactId);
|
||||
will(returnValue(contact));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(messageParser).getMessagesVisibleInUiQuery();
|
||||
will(returnValue(query));
|
||||
oneOf(clientHelper)
|
||||
.getMessageMetadataAsDictionary(txn, contactGroup.getId(),
|
||||
query);
|
||||
will(returnValue(results));
|
||||
// first message
|
||||
oneOf(messageParser).parseMetadata(d1);
|
||||
will(returnValue(meta1));
|
||||
oneOf(db).getMessageStatus(txn, contactId, message.getId());
|
||||
oneOf(clientHelper).getMessage(txn, message.getId());
|
||||
will(returnValue(message));
|
||||
oneOf(clientHelper).toList(message);
|
||||
will(returnValue(list1));
|
||||
oneOf(messageParser).parseInviteMessage(message, list1);
|
||||
// second message
|
||||
oneOf(messageParser).parseMetadata(d2);
|
||||
will(returnValue(meta2));
|
||||
oneOf(db).getMessageStatus(txn, contactId, storageMessage.getId());
|
||||
// end transaction
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
Collection<InvitationMessage> messages =
|
||||
groupInvitationManager.getInvitationMessages(contactId);
|
||||
assertEquals(2, messages.size());
|
||||
for (InvitationMessage m : messages) {
|
||||
assertEquals(contactGroup.getId(), m.getGroupId());
|
||||
assertEquals(contactId, m.getContactId());
|
||||
if (m.getId().equals(message.getId())) {
|
||||
assertTrue(m instanceof GroupInvitationRequest);
|
||||
assertEquals(time1, m.getTimestamp());
|
||||
} else if (m.getId().equals(storageMessage.getId())) {
|
||||
assertTrue(m instanceof GroupInvitationResponse);
|
||||
assertEquals(time2, m.getTimestamp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInvitations() throws Exception {
|
||||
final BdfDictionary query = new BdfDictionary();
|
||||
BdfDictionary d1 = BdfDictionary.of(new BdfEntry("m1", "d"));
|
||||
BdfDictionary d2 = BdfDictionary.of(new BdfEntry("m2", "d"));
|
||||
final Map<MessageId, BdfDictionary> results = new HashMap<>();
|
||||
results.put(message.getId(), d1);
|
||||
results.put(storageMessage.getId(), d2);
|
||||
final BdfList list1 = BdfList.of(1);
|
||||
final BdfList list2 = BdfList.of(2);
|
||||
long time1 = 1L, time2 = 2L;
|
||||
final InviteMessage m1 =
|
||||
new InviteMessage(message.getId(), contactGroup.getId(),
|
||||
privateGroup.getId(), time1, "test", author,
|
||||
getRandomBytes(5), null, getRandomBytes(5));
|
||||
final InviteMessage m2 =
|
||||
new InviteMessage(message.getId(), contactGroup.getId(),
|
||||
privateGroup.getId(), time2, "test", author,
|
||||
getRandomBytes(5), null, getRandomBytes(5));
|
||||
final PrivateGroup g = context.mock(PrivateGroup.class);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageParser).getInvitesAvailableToAnswerQuery();
|
||||
will(returnValue(query));
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(Collections.singletonList(contact)));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(clientHelper)
|
||||
.getMessageMetadataAsDictionary(txn, contactGroup.getId(),
|
||||
query);
|
||||
will(returnValue(results));
|
||||
// message 1
|
||||
oneOf(clientHelper).getMessage(txn, message.getId());
|
||||
will(returnValue(message));
|
||||
oneOf(clientHelper).toList(message);
|
||||
will(returnValue(list1));
|
||||
oneOf(messageParser).parseInviteMessage(message, list1);
|
||||
will(returnValue(m1));
|
||||
oneOf(privateGroupFactory)
|
||||
.createPrivateGroup(m1.getGroupName(), m1.getCreator(),
|
||||
m1.getSalt());
|
||||
will(returnValue(g));
|
||||
// message 2
|
||||
oneOf(clientHelper).getMessage(txn, storageMessage.getId());
|
||||
will(returnValue(storageMessage));
|
||||
oneOf(clientHelper).toList(storageMessage);
|
||||
will(returnValue(list2));
|
||||
oneOf(messageParser).parseInviteMessage(storageMessage, list2);
|
||||
will(returnValue(m2));
|
||||
oneOf(privateGroupFactory)
|
||||
.createPrivateGroup(m2.getGroupName(), m2.getCreator(),
|
||||
m2.getSalt());
|
||||
will(returnValue(g));
|
||||
// end transaction
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
Collection<GroupInvitationItem> items =
|
||||
groupInvitationManager.getInvitations();
|
||||
assertEquals(2, items.size());
|
||||
for (GroupInvitationItem i : items) {
|
||||
assertEquals(contact, i.getCreator());
|
||||
assertEquals(author, i.getCreator().getAuthor());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsInvitationAllowed() throws Exception {
|
||||
expectIsInvitationAllowed(CreatorState.START);
|
||||
assertTrue(groupInvitationManager
|
||||
.isInvitationAllowed(contact, privateGroup.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsNotInvitationAllowed() throws Exception {
|
||||
expectIsInvitationAllowed(CreatorState.DISSOLVED);
|
||||
assertFalse(groupInvitationManager
|
||||
.isInvitationAllowed(contact, privateGroup.getId()));
|
||||
|
||||
expectIsInvitationAllowed(CreatorState.ERROR);
|
||||
assertFalse(groupInvitationManager
|
||||
.isInvitationAllowed(contact, privateGroup.getId()));
|
||||
|
||||
expectIsInvitationAllowed(CreatorState.INVITED);
|
||||
assertFalse(groupInvitationManager
|
||||
.isInvitationAllowed(contact, privateGroup.getId()));
|
||||
|
||||
expectIsInvitationAllowed(CreatorState.JOINED);
|
||||
assertFalse(groupInvitationManager
|
||||
.isInvitationAllowed(contact, privateGroup.getId()));
|
||||
|
||||
expectIsInvitationAllowed(CreatorState.LEFT);
|
||||
assertFalse(groupInvitationManager
|
||||
.isInvitationAllowed(contact, privateGroup.getId()));
|
||||
}
|
||||
|
||||
private void expectIsInvitationAllowed(final CreatorState state)
|
||||
throws Exception {
|
||||
final SessionId sessionId =
|
||||
new SessionId(privateGroup.getId().getBytes());
|
||||
final BdfDictionary meta = BdfDictionary.of(new BdfEntry("m", "d"));
|
||||
final Map<MessageId, BdfDictionary> results = new HashMap<>();
|
||||
results.put(message.getId(), meta);
|
||||
|
||||
expectGetSession(results, sessionId);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(sessionParser)
|
||||
.parseCreatorSession(contactGroup.getId(), meta);
|
||||
will(returnValue(creatorSession));
|
||||
oneOf(creatorSession).getState();
|
||||
will(returnValue(state));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingMember() throws Exception {
|
||||
expectAddingMember(privateGroup.getId(), contact);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).getContactsByAuthorId(txn, author.getId());
|
||||
will(returnValue(Collections.singletonList(contact)));
|
||||
}});
|
||||
groupInvitationManager.addingMember(txn, privateGroup.getId(), author);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemovingGroupEndsSessions() throws Exception {
|
||||
final Contact contact2 =
|
||||
new Contact(new ContactId(2), author, author.getId(), true,
|
||||
true);
|
||||
final Contact contact3 =
|
||||
new Contact(new ContactId(3), author, author.getId(), true,
|
||||
true);
|
||||
final Collection<Contact> contacts = new ArrayList<>();
|
||||
contacts.add(contact);
|
||||
contacts.add(contact2);
|
||||
contacts.add(contact3);
|
||||
final MessageId mId2 = new MessageId(getRandomId());
|
||||
final MessageId mId3 = new MessageId(getRandomId());
|
||||
final BdfDictionary meta1 = BdfDictionary.of(new BdfEntry("m1", "d"));
|
||||
final BdfDictionary meta2 = BdfDictionary.of(new BdfEntry("m2", "d"));
|
||||
final BdfDictionary meta3 = BdfDictionary.of(new BdfEntry("m3", "d"));
|
||||
|
||||
expectGetSession(
|
||||
Collections.singletonMap(storageMessage.getId(), meta1),
|
||||
new SessionId(privateGroup.getId().getBytes()));
|
||||
expectGetSession(
|
||||
Collections.singletonMap(mId2, meta2),
|
||||
new SessionId(privateGroup.getId().getBytes()));
|
||||
expectGetSession(
|
||||
Collections.singletonMap(mId3, meta3),
|
||||
new SessionId(privateGroup.getId().getBytes()));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(contacts));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact2);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact3);
|
||||
will(returnValue(contactGroup));
|
||||
// session 1
|
||||
oneOf(sessionParser).getRole(meta1);
|
||||
will(returnValue(Role.CREATOR));
|
||||
oneOf(sessionParser)
|
||||
.parseCreatorSession(contactGroup.getId(), meta1);
|
||||
will(returnValue(creatorSession));
|
||||
oneOf(creatorEngine).onLeaveAction(txn, creatorSession);
|
||||
will(returnValue(creatorSession));
|
||||
// session 2
|
||||
oneOf(sessionParser).getRole(meta2);
|
||||
will(returnValue(Role.INVITEE));
|
||||
oneOf(sessionParser)
|
||||
.parseInviteeSession(contactGroup.getId(), meta2);
|
||||
will(returnValue(inviteeSession));
|
||||
oneOf(inviteeEngine).onLeaveAction(txn, inviteeSession);
|
||||
will(returnValue(inviteeSession));
|
||||
// session 3
|
||||
oneOf(sessionParser).getRole(meta3);
|
||||
will(returnValue(Role.PEER));
|
||||
oneOf(sessionParser)
|
||||
.parsePeerSession(contactGroup.getId(), meta3);
|
||||
will(returnValue(peerSession));
|
||||
oneOf(peerEngine).onLeaveAction(txn, peerSession);
|
||||
will(returnValue(peerSession));
|
||||
}});
|
||||
expectStoreSession(creatorSession, storageMessage.getId());
|
||||
expectStoreSession(inviteeSession, mId2);
|
||||
expectStoreSession(peerSession, mId3);
|
||||
groupInvitationManager.removingGroup(txn, privateGroup.getId());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user