mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Unit tests for client versioning manager.
This commit is contained in:
@@ -0,0 +1,669 @@
|
||||
package org.briarproject.bramble.versioning;
|
||||
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.client.ContactGroupFactory;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
import org.briarproject.bramble.api.data.BdfEntry;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.Metadata;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.sync.ClientId;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.Group.Visibility;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.jmock.Expectations;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
|
||||
import static org.briarproject.bramble.api.versioning.ClientVersioningManager.CLIENT_ID;
|
||||
import static org.briarproject.bramble.api.versioning.ClientVersioningManager.MAJOR_VERSION;
|
||||
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
||||
import static org.briarproject.bramble.test.TestUtils.getClientId;
|
||||
import static org.briarproject.bramble.test.TestUtils.getGroup;
|
||||
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
|
||||
import static org.briarproject.bramble.test.TestUtils.getMessage;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||
import static org.briarproject.bramble.versioning.ClientVersioningConstants.GROUP_KEY_CONTACT_ID;
|
||||
import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_LOCAL;
|
||||
import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_UPDATE_VERSION;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
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 Clock clock = context.mock(Clock.class);
|
||||
private final ClientVersioningHook hook =
|
||||
context.mock(ClientVersioningHook.class);
|
||||
|
||||
private final Group localGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
private final Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
private final Contact contact = new Contact(new ContactId(123),
|
||||
getAuthor(), getLocalAuthor().getId(), true, true);
|
||||
private final ClientId clientId = getClientId();
|
||||
private final long now = System.currentTimeMillis();
|
||||
private final Transaction txn = new Transaction(null, false);
|
||||
|
||||
private ClientVersioningManagerImpl createInstance() throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID,
|
||||
MAJOR_VERSION);
|
||||
will(returnValue(localGroup));
|
||||
}});
|
||||
return new ClientVersioningManagerImpl(db, clientHelper,
|
||||
contactGroupFactory, clock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatesGroupsAtStartup() throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).containsGroup(txn, localGroup.getId());
|
||||
will(returnValue(false));
|
||||
oneOf(db).addGroup(txn, localGroup);
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(singletonList(contact)));
|
||||
}});
|
||||
expectAddingContact();
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.createLocalState(txn);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotCreateGroupsAtStartupIfAlreadyCreated()
|
||||
throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).containsGroup(txn, localGroup.getId());
|
||||
will(returnValue(true));
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.createLocalState(txn);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatesContactGroupWhenAddingContact() throws Exception {
|
||||
expectAddingContact();
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.addingContact(txn, contact);
|
||||
}
|
||||
|
||||
private void expectAddingContact() throws Exception {
|
||||
BdfDictionary groupMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt()));
|
||||
long now = System.currentTimeMillis();
|
||||
BdfList localUpdateBody = BdfList.of(new BdfList(), 1L);
|
||||
Message localUpdate = getMessage(contactGroup.getId());
|
||||
BdfDictionary localUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
|
||||
MAJOR_VERSION, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(db).addGroup(txn, contactGroup);
|
||||
oneOf(db).setGroupVisibility(txn, contact.getId(),
|
||||
contactGroup.getId(), SHARED);
|
||||
oneOf(clientHelper).mergeGroupMetadata(txn, contactGroup.getId(),
|
||||
groupMeta);
|
||||
oneOf(clock).currentTimeMillis();
|
||||
will(returnValue(now));
|
||||
oneOf(clientHelper).createMessage(contactGroup.getId(), now,
|
||||
localUpdateBody);
|
||||
will(returnValue(localUpdate));
|
||||
oneOf(clientHelper).addLocalMessage(txn, localUpdate,
|
||||
localUpdateMeta, true);
|
||||
}});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemovesGroupWhenRemovingContact() throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
|
||||
MAJOR_VERSION, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(db).removeGroup(txn, contactGroup);
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.removingContact(txn, contact);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoresClientVersionsAtFirstStartup() throws Exception {
|
||||
BdfList localVersionsBody =
|
||||
BdfList.of(BdfList.of(clientId.getString(), 123, 234));
|
||||
Message localVersions = getMessage(localGroup.getId());
|
||||
MessageId localUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary localUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
BdfList localUpdateBody = BdfList.of(BdfList.of(
|
||||
BdfList.of(clientId.getString(), 123, 234, false)), 1L);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
// No client versions have been stored yet
|
||||
oneOf(db).getMessageIds(txn, localGroup.getId());
|
||||
will(returnValue(emptyList()));
|
||||
// Store the client versions
|
||||
oneOf(clock).currentTimeMillis();
|
||||
will(returnValue(now));
|
||||
oneOf(clientHelper).createMessage(localGroup.getId(), now,
|
||||
localVersionsBody);
|
||||
will(returnValue(localVersions));
|
||||
oneOf(db).addLocalMessage(txn, localVersions, new Metadata(),
|
||||
false);
|
||||
// Inform contacts that client versions have changed
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(singletonList(contact)));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
|
||||
MAJOR_VERSION, contact);
|
||||
will(returnValue(contactGroup));
|
||||
// Find the latest local and remote updates (no remote update)
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(singletonMap(localUpdateId, localUpdateMeta)));
|
||||
// Load the latest local update
|
||||
oneOf(clientHelper).getMessageAsList(txn, localUpdateId);
|
||||
will(returnValue(localUpdateBody));
|
||||
// Latest local update is up-to-date, no visibilities have changed
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.registerClient(clientId, 123, 234, hook);
|
||||
c.startService();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComparesClientVersionsAtSubsequentStartup()
|
||||
throws Exception {
|
||||
MessageId localVersionsId = new MessageId(getRandomId());
|
||||
BdfList localVersionsBody =
|
||||
BdfList.of(BdfList.of(clientId.getString(), 123, 234));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
// Load the old client versions
|
||||
oneOf(db).getMessageIds(txn, localGroup.getId());
|
||||
will(returnValue(singletonList(localVersionsId)));
|
||||
oneOf(clientHelper).getMessageAsList(txn, localVersionsId);
|
||||
will(returnValue(localVersionsBody));
|
||||
// Client versions are up-to-date
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.registerClient(clientId, 123, 234, hook);
|
||||
c.startService();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoresClientVersionsAtSubsequentStartupIfChanged()
|
||||
throws Exception {
|
||||
// The client had minor version 234 in the old client versions
|
||||
BdfList oldLocalVersionsBody =
|
||||
BdfList.of(BdfList.of(clientId.getString(), 123, 234));
|
||||
// The client has minor version 345 in the new client versions
|
||||
BdfList newLocalVersionsBody =
|
||||
BdfList.of(BdfList.of(clientId.getString(), 123, 345));
|
||||
// The client had minor version 234 in the old local update
|
||||
BdfList oldLocalUpdateBody = BdfList.of(BdfList.of(
|
||||
BdfList.of(clientId.getString(), 123, 234, false)), 1L);
|
||||
// The client has minor version 345 in the new local update
|
||||
BdfList newLocalUpdateBody = BdfList.of(BdfList.of(
|
||||
BdfList.of(clientId.getString(), 123, 345, false)), 2L);
|
||||
|
||||
MessageId oldLocalVersionsId = new MessageId(getRandomId());
|
||||
Message newLocalVersions = getMessage(localGroup.getId());
|
||||
MessageId oldLocalUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary oldLocalUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
Message newLocalUpdate = getMessage(contactGroup.getId());
|
||||
BdfDictionary newLocalUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 2L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
// Load the old client versions
|
||||
oneOf(db).getMessageIds(txn, localGroup.getId());
|
||||
will(returnValue(singletonList(oldLocalVersionsId)));
|
||||
oneOf(clientHelper).getMessageAsList(txn, oldLocalVersionsId);
|
||||
will(returnValue(oldLocalVersionsBody));
|
||||
// Delete the old client versions
|
||||
oneOf(db).removeMessage(txn, oldLocalVersionsId);
|
||||
// Store the new client versions
|
||||
oneOf(clock).currentTimeMillis();
|
||||
will(returnValue(now));
|
||||
oneOf(clientHelper).createMessage(localGroup.getId(), now,
|
||||
newLocalVersionsBody);
|
||||
will(returnValue(newLocalVersions));
|
||||
oneOf(db).addLocalMessage(txn, newLocalVersions, new Metadata(),
|
||||
false);
|
||||
// Inform contacts that client versions have changed
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(singletonList(contact)));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
|
||||
MAJOR_VERSION, contact);
|
||||
will(returnValue(contactGroup));
|
||||
// Find the latest local and remote updates (no remote update)
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(singletonMap(oldLocalUpdateId,
|
||||
oldLocalUpdateMeta)));
|
||||
// Load the latest local update
|
||||
oneOf(clientHelper).getMessageAsList(txn, oldLocalUpdateId);
|
||||
will(returnValue(oldLocalUpdateBody));
|
||||
// Delete the latest local update
|
||||
oneOf(db).deleteMessage(txn, oldLocalUpdateId);
|
||||
oneOf(db).deleteMessageMetadata(txn, oldLocalUpdateId);
|
||||
// Store the new local update
|
||||
oneOf(clock).currentTimeMillis();
|
||||
will(returnValue(now));
|
||||
oneOf(clientHelper).createMessage(contactGroup.getId(), now,
|
||||
newLocalUpdateBody);
|
||||
will(returnValue(newLocalUpdate));
|
||||
oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate,
|
||||
newLocalUpdateMeta, true);
|
||||
// No visibilities have changed
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.registerClient(clientId, 123, 345, hook);
|
||||
c.startService();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testActivatesNewClientAtStartupIfAlreadyAdvertisedByContact()
|
||||
throws Exception {
|
||||
testActivatesNewClientAtStartup(false, VISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testActivatesNewClientAtStartupIfAlreadyActivatedByContact()
|
||||
throws Exception {
|
||||
testActivatesNewClientAtStartup(true, SHARED);
|
||||
}
|
||||
|
||||
private void testActivatesNewClientAtStartup(boolean remoteActive,
|
||||
Visibility visibility) throws Exception {
|
||||
// The client was missing from the old client versions
|
||||
BdfList oldLocalVersionsBody = new BdfList();
|
||||
// The client is included in the new client versions
|
||||
BdfList newLocalVersionsBody =
|
||||
BdfList.of(BdfList.of(clientId.getString(), 123, 234));
|
||||
// The client was missing from the old local update
|
||||
BdfList oldLocalUpdateBody = BdfList.of(new BdfList(), 1L);
|
||||
// The client was included in the old remote update
|
||||
BdfList oldRemoteUpdateBody = BdfList.of(BdfList.of(
|
||||
BdfList.of(clientId.getString(), 123, 345, remoteActive)), 1L);
|
||||
// The client is active in the new local update
|
||||
BdfList newLocalUpdateBody = BdfList.of(BdfList.of(
|
||||
BdfList.of(clientId.getString(), 123, 234, true)), 2L);
|
||||
|
||||
MessageId oldLocalVersionsId = new MessageId(getRandomId());
|
||||
Message newLocalVersions = getMessage(localGroup.getId());
|
||||
MessageId oldLocalUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary oldLocalUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
MessageId oldRemoteUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary oldRemoteUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false));
|
||||
Map<MessageId, BdfDictionary> messageMetadata = new HashMap<>();
|
||||
messageMetadata.put(oldLocalUpdateId, oldLocalUpdateMeta);
|
||||
messageMetadata.put(oldRemoteUpdateId, oldRemoteUpdateMeta);
|
||||
Message newLocalUpdate = getMessage(localGroup.getId());
|
||||
BdfDictionary newLocalUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 2L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
// Load the old client versions
|
||||
oneOf(db).getMessageIds(txn, localGroup.getId());
|
||||
will(returnValue(singletonList(oldLocalVersionsId)));
|
||||
oneOf(clientHelper).getMessageAsList(txn, oldLocalVersionsId);
|
||||
will(returnValue(oldLocalVersionsBody));
|
||||
// Delete the old client versions
|
||||
oneOf(db).removeMessage(txn, oldLocalVersionsId);
|
||||
// Store the new client versions
|
||||
oneOf(clock).currentTimeMillis();
|
||||
will(returnValue(now));
|
||||
oneOf(clientHelper).createMessage(localGroup.getId(), now,
|
||||
newLocalVersionsBody);
|
||||
will(returnValue(newLocalVersions));
|
||||
oneOf(db).addLocalMessage(txn, newLocalVersions, new Metadata(),
|
||||
false);
|
||||
// Inform contacts that client versions have changed
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(singletonList(contact)));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
|
||||
MAJOR_VERSION, contact);
|
||||
will(returnValue(contactGroup));
|
||||
// Find the latest local and remote updates
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(messageMetadata));
|
||||
// Load the latest local update
|
||||
oneOf(clientHelper).getMessageAsList(txn, oldLocalUpdateId);
|
||||
will(returnValue(oldLocalUpdateBody));
|
||||
// Load the latest remote update
|
||||
oneOf(clientHelper).getMessageAsList(txn, oldRemoteUpdateId);
|
||||
will(returnValue(oldRemoteUpdateBody));
|
||||
// Delete the latest local update
|
||||
oneOf(db).deleteMessage(txn, oldLocalUpdateId);
|
||||
oneOf(db).deleteMessageMetadata(txn, oldLocalUpdateId);
|
||||
// Store the new local update
|
||||
oneOf(clock).currentTimeMillis();
|
||||
will(returnValue(now));
|
||||
oneOf(clientHelper).createMessage(contactGroup.getId(), now,
|
||||
newLocalUpdateBody);
|
||||
will(returnValue(newLocalUpdate));
|
||||
oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate,
|
||||
newLocalUpdateMeta, true);
|
||||
// The client's visibility has changed
|
||||
oneOf(hook).onClientVisibilityChanging(txn, contact, visibility);
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.registerClient(clientId, 123, 234, hook);
|
||||
c.startService();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletesObsoleteRemoteUpdate() throws Exception {
|
||||
Message newRemoteUpdate = getMessage(contactGroup.getId());
|
||||
BdfList newRemoteUpdateBody = BdfList.of(new BdfList(), 1L);
|
||||
MessageId oldLocalUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary oldLocalUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
MessageId oldRemoteUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary oldRemoteUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 2L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false));
|
||||
Map<MessageId, BdfDictionary> messageMetadata = new HashMap<>();
|
||||
messageMetadata.put(oldLocalUpdateId, oldLocalUpdateMeta);
|
||||
messageMetadata.put(oldRemoteUpdateId, oldRemoteUpdateMeta);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).toList(newRemoteUpdate);
|
||||
will(returnValue(newRemoteUpdateBody));
|
||||
// Find the latest local and remote updates
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(messageMetadata));
|
||||
// Delete the new remote update, which is obsolete
|
||||
oneOf(db).deleteMessage(txn, newRemoteUpdate.getId());
|
||||
oneOf(db).deleteMessageMetadata(txn, newRemoteUpdate.getId());
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.registerClient(clientId, 123, 234, hook);
|
||||
assertFalse(c.incomingMessage(txn, newRemoteUpdate, new Metadata()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletesPreviousRemoteUpdate() throws Exception {
|
||||
Message newRemoteUpdate = getMessage(contactGroup.getId());
|
||||
BdfList newRemoteUpdateBody = BdfList.of(new BdfList(), 2L);
|
||||
MessageId oldLocalUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary oldLocalUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
MessageId oldRemoteUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary oldRemoteUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false));
|
||||
Map<MessageId, BdfDictionary> messageMetadata = new HashMap<>();
|
||||
messageMetadata.put(oldLocalUpdateId, oldLocalUpdateMeta);
|
||||
messageMetadata.put(oldRemoteUpdateId, oldRemoteUpdateMeta);
|
||||
BdfList oldLocalUpdateBody = BdfList.of(new BdfList(), 1L);
|
||||
BdfList oldRemoteUpdateBody = BdfList.of(new BdfList(), 1L);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).toList(newRemoteUpdate);
|
||||
will(returnValue(newRemoteUpdateBody));
|
||||
// Find the latest local and remote updates
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(messageMetadata));
|
||||
// Load the latest local update
|
||||
oneOf(clientHelper).getMessageAsList(txn, oldLocalUpdateId);
|
||||
will(returnValue(oldLocalUpdateBody));
|
||||
// Load the latest remote update
|
||||
oneOf(clientHelper).getMessageAsList(txn, oldRemoteUpdateId);
|
||||
will(returnValue(oldRemoteUpdateBody));
|
||||
// Delete the old remote update
|
||||
oneOf(db).deleteMessage(txn, oldRemoteUpdateId);
|
||||
oneOf(db).deleteMessageMetadata(txn, oldRemoteUpdateId);
|
||||
// No states or visibilities have changed
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.registerClient(clientId, 123, 234, hook);
|
||||
assertFalse(c.incomingMessage(txn, newRemoteUpdate, new Metadata()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptsFirstRemoteUpdate() throws Exception {
|
||||
Message newRemoteUpdate = getMessage(contactGroup.getId());
|
||||
BdfList newRemoteUpdateBody = BdfList.of(new BdfList(), 1L);
|
||||
MessageId oldLocalUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary oldLocalUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
BdfList oldLocalUpdateBody = BdfList.of(new BdfList(), 1L);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).toList(newRemoteUpdate);
|
||||
will(returnValue(newRemoteUpdateBody));
|
||||
// Find the latest local and remote updates (no remote update)
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(singletonMap(oldLocalUpdateId,
|
||||
oldLocalUpdateMeta)));
|
||||
// Load the latest local update
|
||||
oneOf(clientHelper).getMessageAsList(txn, oldLocalUpdateId);
|
||||
will(returnValue(oldLocalUpdateBody));
|
||||
// No states or visibilities have changed
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.registerClient(clientId, 123, 234, hook);
|
||||
assertFalse(c.incomingMessage(txn, newRemoteUpdate, new Metadata()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testActivatesClientOnIncomingMessageWhenAdvertisedByContact()
|
||||
throws Exception {
|
||||
testActivatesClientOnIncomingMessage(false, VISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testActivatesClientOnIncomingMessageWhenActivatedByContact()
|
||||
throws Exception {
|
||||
testActivatesClientOnIncomingMessage(true, SHARED);
|
||||
}
|
||||
|
||||
private void testActivatesClientOnIncomingMessage(boolean remoteActive,
|
||||
Visibility visibility) throws Exception {
|
||||
// The client was missing from the old remote update
|
||||
BdfList oldRemoteUpdateBody = BdfList.of(new BdfList(), 1L);
|
||||
// The client was inactive in the old local update
|
||||
BdfList oldLocalUpdateBody = BdfList.of(BdfList.of(
|
||||
BdfList.of(clientId.getString(), 123, 234, false)), 1L);
|
||||
// The client is included in the new remote update
|
||||
BdfList newRemoteUpdateBody = BdfList.of(BdfList.of(
|
||||
BdfList.of(clientId.getString(), 123, 234, remoteActive)), 2L);
|
||||
// The client is active in the new local update
|
||||
BdfList newLocalUpdateBody = BdfList.of(BdfList.of(
|
||||
BdfList.of(clientId.getString(), 123, 234, true)), 2L);
|
||||
|
||||
Message newRemoteUpdate = getMessage(contactGroup.getId());
|
||||
MessageId oldLocalUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary oldLocalUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
MessageId oldRemoteUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary oldRemoteUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false));
|
||||
Map<MessageId, BdfDictionary> messageMetadata = new HashMap<>();
|
||||
messageMetadata.put(oldLocalUpdateId, oldLocalUpdateMeta);
|
||||
messageMetadata.put(oldRemoteUpdateId, oldRemoteUpdateMeta);
|
||||
Message newLocalUpdate = getMessage(contactGroup.getId());
|
||||
BdfDictionary newLocalUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 2L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
BdfDictionary groupMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt()));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).toList(newRemoteUpdate);
|
||||
will(returnValue(newRemoteUpdateBody));
|
||||
// Find the latest local and remote updates
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(messageMetadata));
|
||||
// Load the latest local update
|
||||
oneOf(clientHelper).getMessageAsList(txn, oldLocalUpdateId);
|
||||
will(returnValue(oldLocalUpdateBody));
|
||||
// Load the latest remote update
|
||||
oneOf(clientHelper).getMessageAsList(txn, oldRemoteUpdateId);
|
||||
will(returnValue(oldRemoteUpdateBody));
|
||||
// Delete the old remote update
|
||||
oneOf(db).deleteMessage(txn, oldRemoteUpdateId);
|
||||
oneOf(db).deleteMessageMetadata(txn, oldRemoteUpdateId);
|
||||
// Delete the old local update
|
||||
oneOf(db).deleteMessage(txn, oldLocalUpdateId);
|
||||
oneOf(db).deleteMessageMetadata(txn, oldLocalUpdateId);
|
||||
// Store the new local update
|
||||
oneOf(clock).currentTimeMillis();
|
||||
will(returnValue(now));
|
||||
oneOf(clientHelper).createMessage(contactGroup.getId(), now,
|
||||
newLocalUpdateBody);
|
||||
will(returnValue(newLocalUpdate));
|
||||
oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate,
|
||||
newLocalUpdateMeta, true);
|
||||
// The client's visibility has changed
|
||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(groupMeta));
|
||||
oneOf(db).getContact(txn, contact.getId());
|
||||
will(returnValue(contact));
|
||||
oneOf(hook).onClientVisibilityChanging(txn, contact, visibility);
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.registerClient(clientId, 123, 234, hook);
|
||||
assertFalse(c.incomingMessage(txn, newRemoteUpdate, new Metadata()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeactivatesClientOnIncomingMessage() throws Exception {
|
||||
// The client was active in the old local and remote updates
|
||||
BdfList oldLocalUpdateBody = BdfList.of(BdfList.of(
|
||||
BdfList.of(clientId.getString(), 123, 234, true)), 1L);
|
||||
BdfList oldRemoteUpdateBody = BdfList.of(BdfList.of(
|
||||
BdfList.of(clientId.getString(), 123, 234, true)), 1L);
|
||||
// The client is missing from the new remote update
|
||||
BdfList newRemoteUpdateBody = BdfList.of(new BdfList(), 2L);
|
||||
// The client is inactive in the new local update
|
||||
BdfList newLocalUpdateBody = BdfList.of(BdfList.of(
|
||||
BdfList.of(clientId.getString(), 123, 234, false)), 2L);
|
||||
|
||||
Message newRemoteUpdate = getMessage(contactGroup.getId());
|
||||
MessageId oldLocalUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary oldLocalUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
MessageId oldRemoteUpdateId = new MessageId(getRandomId());
|
||||
BdfDictionary oldRemoteUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 1L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false));
|
||||
Map<MessageId, BdfDictionary> messageMetadata = new HashMap<>();
|
||||
messageMetadata.put(oldLocalUpdateId, oldLocalUpdateMeta);
|
||||
messageMetadata.put(oldRemoteUpdateId, oldRemoteUpdateMeta);
|
||||
Message newLocalUpdate = getMessage(contactGroup.getId());
|
||||
BdfDictionary newLocalUpdateMeta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 2L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
BdfDictionary groupMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt()));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).toList(newRemoteUpdate);
|
||||
will(returnValue(newRemoteUpdateBody));
|
||||
// Find the latest local and remote updates
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(messageMetadata));
|
||||
// Load the latest local update
|
||||
oneOf(clientHelper).getMessageAsList(txn, oldLocalUpdateId);
|
||||
will(returnValue(oldLocalUpdateBody));
|
||||
// Load the latest remote update
|
||||
oneOf(clientHelper).getMessageAsList(txn, oldRemoteUpdateId);
|
||||
will(returnValue(oldRemoteUpdateBody));
|
||||
// Delete the old remote update
|
||||
oneOf(db).deleteMessage(txn, oldRemoteUpdateId);
|
||||
oneOf(db).deleteMessageMetadata(txn, oldRemoteUpdateId);
|
||||
// Delete the old local update
|
||||
oneOf(db).deleteMessage(txn, oldLocalUpdateId);
|
||||
oneOf(db).deleteMessageMetadata(txn, oldLocalUpdateId);
|
||||
// Store the new local update
|
||||
oneOf(clock).currentTimeMillis();
|
||||
will(returnValue(now));
|
||||
oneOf(clientHelper).createMessage(contactGroup.getId(), now,
|
||||
newLocalUpdateBody);
|
||||
will(returnValue(newLocalUpdate));
|
||||
oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate,
|
||||
newLocalUpdateMeta, true);
|
||||
// The client's visibility has changed
|
||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(groupMeta));
|
||||
oneOf(db).getContact(txn, contact.getId());
|
||||
will(returnValue(contact));
|
||||
oneOf(hook).onClientVisibilityChanging(txn, contact, INVISIBLE);
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
c.registerClient(clientId, 123, 234, hook);
|
||||
assertFalse(c.incomingMessage(txn, newRemoteUpdate, new Metadata()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user