mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Mirror the remote auto-delete timer.
This commit is contained in:
@@ -297,7 +297,8 @@ public class ConversationViewModel extends AndroidViewModel
|
||||
return privateMessageFactory.createPrivateMessage(groupId,
|
||||
timestamp, text, headers);
|
||||
} else {
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||
timestamp);
|
||||
return privateMessageFactory.createPrivateMessage(groupId,
|
||||
timestamp, text, headers, timer);
|
||||
}
|
||||
|
||||
@@ -171,7 +171,8 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
||||
Contact contact = contactManager.getContact(txn, c);
|
||||
long timestamp = conversationManager
|
||||
.getTimestampForOutgoingMessage(txn, c);
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||
timestamp);
|
||||
contexts.add(new InvitationContext(contact, timestamp, timer));
|
||||
} catch (NoSuchContactException e) {
|
||||
// Continue
|
||||
|
||||
@@ -24,8 +24,26 @@ public interface AutoDeleteManager {
|
||||
*/
|
||||
int MINOR_VERSION = 0;
|
||||
|
||||
long getAutoDeleteTimer(Transaction txn, ContactId c) throws DbException;
|
||||
/**
|
||||
* Returns the auto-delete timer duration for the given contact, for use in
|
||||
* a message with the given timestamp. The timestamp is stored.
|
||||
*/
|
||||
long getAutoDeleteTimer(Transaction txn, ContactId c, long timestamp)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Sets the auto-delete timer duration for the given contact.
|
||||
*/
|
||||
void setAutoDeleteTimer(Transaction txn, ContactId c, long timer)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Receives an auto-delete timer duration from the given contact, carried
|
||||
* in a message with the given timestamp. The local timer is set to the
|
||||
* same duration unless it has been
|
||||
* {@link #setAutoDeleteTimer(Transaction, ContactId, long) changed} more
|
||||
* recently than the remote timer.
|
||||
*/
|
||||
void receiveAutoDeleteTimer(Transaction txn, ContactId c, long timer,
|
||||
long timestamp) throws DbException;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,28 @@ package org.briarproject.briar.autodelete;
|
||||
|
||||
interface AutoDeleteConstants {
|
||||
|
||||
// Group metadata key for storing the auto-delete timer
|
||||
String GROUP_KEY_AUTO_DELETE_TIMER = "autoDeleteTimer";
|
||||
/**
|
||||
* Group metadata key for storing the auto-delete timer duration.
|
||||
*/
|
||||
String GROUP_KEY_TIMER = "autoDeleteTimer";
|
||||
|
||||
/**
|
||||
* Group metadata key for storing the timestamp of the latest incoming or
|
||||
* outgoing message carrying an auto-delete timer (including a null timer).
|
||||
*/
|
||||
String GROUP_KEY_TIMESTAMP = "autoDeleteTimestamp";
|
||||
|
||||
/**
|
||||
* Group metadata key for storing the previous auto-delete timer duration.
|
||||
* This is used to decide whether a local change to the duration should be
|
||||
* overwritten by a duration received from the contact.
|
||||
*/
|
||||
String GROUP_KEY_PREVIOUS_TIMER = "autoDeletePreviousTimer";
|
||||
|
||||
/**
|
||||
* Special value for {@link #GROUP_KEY_PREVIOUS_TIMER} indicating that
|
||||
* there are no local changes to the auto-delete timer duration that need
|
||||
* to be compared with durations received from the contact.
|
||||
*/
|
||||
long NO_PREVIOUS_TIMER = 0;
|
||||
}
|
||||
|
||||
@@ -17,19 +17,29 @@ import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.GroupFactory;
|
||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MAX_AUTO_DELETE_TIMER_MS;
|
||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS;
|
||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_PREVIOUS_TIMER;
|
||||
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_TIMER;
|
||||
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_TIMESTAMP;
|
||||
import static org.briarproject.briar.autodelete.AutoDeleteConstants.NO_PREVIOUS_TIMER;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
class AutoDeleteManagerImpl
|
||||
implements AutoDeleteManager, OpenDatabaseHook, ContactHook {
|
||||
|
||||
private static final Logger LOG =
|
||||
getLogger(AutoDeleteManagerImpl.class.getName());
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final ClientHelper clientHelper;
|
||||
private final GroupFactory groupFactory;
|
||||
@@ -69,14 +79,22 @@ class AutoDeleteManagerImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAutoDeleteTimer(Transaction txn, ContactId c)
|
||||
public long getAutoDeleteTimer(Transaction txn, ContactId c, long timestamp)
|
||||
throws DbException {
|
||||
try {
|
||||
Group g = getGroup(db.getContact(txn, c));
|
||||
BdfDictionary meta =
|
||||
clientHelper.getGroupMetadataAsDictionary(txn, g.getId());
|
||||
return meta.getLong(GROUP_KEY_AUTO_DELETE_TIMER,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
long timer = meta.getLong(GROUP_KEY_TIMER, NO_AUTO_DELETE_TIMER);
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Sending message with auto-delete timer " + timer);
|
||||
}
|
||||
// Update the timestamp and clear the previous timer, if any
|
||||
meta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMESTAMP, timestamp),
|
||||
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER));
|
||||
clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
|
||||
return timer;
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
@@ -85,18 +103,60 @@ class AutoDeleteManagerImpl
|
||||
@Override
|
||||
public void setAutoDeleteTimer(Transaction txn, ContactId c, long timer)
|
||||
throws DbException {
|
||||
if (timer != NO_AUTO_DELETE_TIMER &&
|
||||
(timer < MIN_AUTO_DELETE_TIMER_MS ||
|
||||
timer > MAX_AUTO_DELETE_TIMER_MS)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
validateTimer(timer);
|
||||
try {
|
||||
Group g = getGroup(db.getContact(txn, c));
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_AUTO_DELETE_TIMER, timer));
|
||||
BdfDictionary meta =
|
||||
clientHelper.getGroupMetadataAsDictionary(txn, g.getId());
|
||||
long oldTimer = meta.getLong(GROUP_KEY_TIMER, NO_AUTO_DELETE_TIMER);
|
||||
if (timer == oldTimer) return;
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Setting auto-delete timer to " + timer);
|
||||
}
|
||||
// Store the new timer and the previous timer
|
||||
meta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMER, timer),
|
||||
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, oldTimer));
|
||||
clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError(e);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveAutoDeleteTimer(Transaction txn, ContactId c,
|
||||
long timer, long timestamp) throws DbException {
|
||||
validateTimer(timer);
|
||||
try {
|
||||
Group g = getGroup(db.getContact(txn, c));
|
||||
BdfDictionary meta =
|
||||
clientHelper.getGroupMetadataAsDictionary(txn, g.getId());
|
||||
long oldTimestamp = meta.getLong(GROUP_KEY_TIMESTAMP, 0L);
|
||||
if (timestamp <= oldTimestamp) return;
|
||||
long oldTimer =
|
||||
meta.getLong(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER);
|
||||
meta = new BdfDictionary();
|
||||
if (oldTimer == NO_PREVIOUS_TIMER) {
|
||||
// We don't have an unsent change. Mirror their timer
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Mirroring auto-delete timer " + timer);
|
||||
}
|
||||
meta.put(GROUP_KEY_TIMER, timer);
|
||||
} else if (timer != oldTimer) {
|
||||
// Their sent change trumps our unsent change. Mirror their
|
||||
// timer and clear the previous timer to drop our unsent change
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Mirroring auto-delete timer " + timer
|
||||
+ " and forgetting unsent change");
|
||||
}
|
||||
meta.put(GROUP_KEY_TIMER, timer);
|
||||
meta.put(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER);
|
||||
}
|
||||
// Always update the timestamp
|
||||
meta.put(GROUP_KEY_TIMESTAMP, timestamp);
|
||||
clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,4 +164,12 @@ class AutoDeleteManagerImpl
|
||||
byte[] descriptor = c.getAuthor().getId().getBytes();
|
||||
return groupFactory.createGroup(CLIENT_ID, MAJOR_VERSION, descriptor);
|
||||
}
|
||||
|
||||
private void validateTimer(long timer) {
|
||||
if (timer != NO_AUTO_DELETE_TIMER &&
|
||||
(timer < MIN_AUTO_DELETE_TIMER_MS ||
|
||||
timer > MAX_AUTO_DELETE_TIMER_MS)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,8 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
Message m;
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||
timestamp);
|
||||
m = messageEncoder.encodeRequestMessage(s.getContactGroupId(),
|
||||
timestamp, s.getLastLocalMessageId(), author, text, timer);
|
||||
sendMessage(txn, REQUEST, s.getSessionId(), m, true, timer);
|
||||
@@ -116,7 +117,8 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
Message m;
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||
timestamp);
|
||||
m = messageEncoder.encodeAcceptMessage(s.getContactGroupId(),
|
||||
timestamp, s.getLastLocalMessageId(), s.getSessionId(),
|
||||
ephemeralPublicKey, acceptTimestamp, transportProperties,
|
||||
@@ -137,7 +139,8 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
Message m;
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||
timestamp);
|
||||
m = messageEncoder.encodeDeclineMessage(s.getContactGroupId(),
|
||||
timestamp, s.getLastLocalMessageId(), s.getSessionId(),
|
||||
timer);
|
||||
|
||||
@@ -152,9 +152,11 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
// Set auto-delete timer if manually accepting an invitation
|
||||
long timer = visibleInUi
|
||||
? autoDeleteManager.getAutoDeleteTimer(txn, c)
|
||||
: NO_AUTO_DELETE_TIMER;
|
||||
long timer = NO_AUTO_DELETE_TIMER;
|
||||
if (visibleInUi) {
|
||||
timer = autoDeleteManager
|
||||
.getAutoDeleteTimer(txn, c, localTimestamp);
|
||||
}
|
||||
m = messageEncoder.encodeJoinMessage(s.getContactGroupId(),
|
||||
s.getPrivateGroupId(), localTimestamp,
|
||||
s.getLastLocalMessageId(), timer);
|
||||
@@ -179,9 +181,11 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
// Set auto-delete timer if manually accepting an invitation
|
||||
long timer = visibleInUi
|
||||
? autoDeleteManager.getAutoDeleteTimer(txn, c)
|
||||
: NO_AUTO_DELETE_TIMER;
|
||||
long timer = NO_AUTO_DELETE_TIMER;
|
||||
if (visibleInUi) {
|
||||
timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||
localTimestamp);
|
||||
}
|
||||
m = messageEncoder.encodeLeaveMessage(s.getContactGroupId(),
|
||||
s.getPrivateGroupId(), localTimestamp,
|
||||
s.getLastLocalMessageId(), timer);
|
||||
|
||||
@@ -142,7 +142,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||
localTimestamp);
|
||||
m = messageEncoder.encodeInviteMessage(s.getContactGroupId(),
|
||||
localTimestamp, s.getLastLocalMessageId(), descriptor,
|
||||
text, timer);
|
||||
@@ -209,7 +210,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||
localTimestamp);
|
||||
m = messageEncoder.encodeAcceptMessage(s.getContactGroupId(),
|
||||
s.getShareableId(), localTimestamp,
|
||||
s.getLastLocalMessageId(), timer);
|
||||
@@ -263,7 +265,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||
localTimestamp);
|
||||
m = messageEncoder.encodeDeclineMessage(s.getContactGroupId(),
|
||||
s.getShareableId(), localTimestamp,
|
||||
s.getLastLocalMessageId(), timer);
|
||||
|
||||
@@ -18,12 +18,18 @@ import static org.briarproject.bramble.api.client.ContactGroupConstants.GROUP_KE
|
||||
import static org.briarproject.bramble.test.TestUtils.getContact;
|
||||
import static org.briarproject.bramble.test.TestUtils.getGroup;
|
||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MAX_AUTO_DELETE_TIMER_MS;
|
||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS;
|
||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.api.autodelete.AutoDeleteManager.CLIENT_ID;
|
||||
import static org.briarproject.briar.api.autodelete.AutoDeleteManager.MAJOR_VERSION;
|
||||
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_PREVIOUS_TIMER;
|
||||
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_TIMER;
|
||||
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_TIMESTAMP;
|
||||
import static org.briarproject.briar.autodelete.AutoDeleteConstants.NO_PREVIOUS_TIMER;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
// Thank you, I'm using them for readability
|
||||
@SuppressWarnings("UnnecessaryLocalVariable")
|
||||
public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
@@ -35,6 +41,7 @@ public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
||||
private final Group localGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
private final Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
private final Contact contact = getContact();
|
||||
private final long now = System.currentTimeMillis();
|
||||
|
||||
private final AutoDeleteManagerImpl autoDeleteManager;
|
||||
|
||||
@@ -113,15 +120,44 @@ public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
||||
@Test
|
||||
public void testStoresTimer() throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
long timer = MAX_AUTO_DELETE_TIMER_MS;
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_AUTO_DELETE_TIMER, timer));
|
||||
long oldTimer = MIN_AUTO_DELETE_TIMER_MS;
|
||||
long newTimer = MAX_AUTO_DELETE_TIMER_MS;
|
||||
BdfDictionary oldMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMER, oldTimer),
|
||||
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER),
|
||||
new BdfEntry(GROUP_KEY_TIMESTAMP, now));
|
||||
BdfDictionary newMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMER, newTimer),
|
||||
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, oldTimer));
|
||||
|
||||
expectGetContact(txn);
|
||||
expectGetContactGroup();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(oldMeta));
|
||||
oneOf(clientHelper).mergeGroupMetadata(txn,
|
||||
contactGroup.getId(), meta);
|
||||
contactGroup.getId(), newMeta);
|
||||
}});
|
||||
|
||||
autoDeleteManager.setAutoDeleteTimer(txn, contact.getId(), newTimer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotStoreTimerIfUnchanged() throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
long timer = MAX_AUTO_DELETE_TIMER_MS;
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMER, timer),
|
||||
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER),
|
||||
new BdfEntry(GROUP_KEY_TIMESTAMP, now));
|
||||
|
||||
expectGetContact(txn);
|
||||
expectGetContactGroup();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(meta));
|
||||
}});
|
||||
|
||||
autoDeleteManager.setAutoDeleteTimer(txn, contact.getId(), timer);
|
||||
@@ -133,7 +169,10 @@ public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
||||
long timer = MAX_AUTO_DELETE_TIMER_MS;
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt()),
|
||||
new BdfEntry(GROUP_KEY_AUTO_DELETE_TIMER, timer));
|
||||
new BdfEntry(GROUP_KEY_TIMER, timer));
|
||||
BdfDictionary newMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMESTAMP, now),
|
||||
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER));
|
||||
|
||||
expectGetContact(txn);
|
||||
expectGetContactGroup();
|
||||
@@ -141,10 +180,12 @@ public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(meta));
|
||||
oneOf(clientHelper).mergeGroupMetadata(txn, contactGroup.getId(),
|
||||
newMeta);
|
||||
}});
|
||||
|
||||
assertEquals(timer,
|
||||
autoDeleteManager.getAutoDeleteTimer(txn, contact.getId()));
|
||||
assertEquals(timer, autoDeleteManager
|
||||
.getAutoDeleteTimer(txn, contact.getId(), now));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -152,6 +193,44 @@ public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt()));
|
||||
BdfDictionary newMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMESTAMP, now),
|
||||
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER));
|
||||
|
||||
expectGetContact(txn);
|
||||
expectGetContactGroup();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(meta));
|
||||
oneOf(clientHelper).mergeGroupMetadata(txn, contactGroup.getId(),
|
||||
newMeta);
|
||||
}});
|
||||
|
||||
assertEquals(NO_AUTO_DELETE_TIMER, autoDeleteManager
|
||||
.getAutoDeleteTimer(txn, contact.getId(), now));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoresReceivedTimerWithEarlierTimestamp()
|
||||
throws Exception {
|
||||
testIgnoresReceivedTimerWithTimestamp(now - 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoresReceivedTimerWithEqualTimestamp() throws Exception {
|
||||
testIgnoresReceivedTimerWithTimestamp(now);
|
||||
}
|
||||
|
||||
private void testIgnoresReceivedTimerWithTimestamp(long remoteTimestamp)
|
||||
throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
long localTimer = MIN_AUTO_DELETE_TIMER_MS;
|
||||
long remoteTimer = MAX_AUTO_DELETE_TIMER_MS;
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMER, localTimer),
|
||||
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER),
|
||||
new BdfEntry(GROUP_KEY_TIMESTAMP, now));
|
||||
|
||||
expectGetContact(txn);
|
||||
expectGetContactGroup();
|
||||
@@ -161,8 +240,99 @@ public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
||||
will(returnValue(meta));
|
||||
}});
|
||||
|
||||
assertEquals(NO_AUTO_DELETE_TIMER,
|
||||
autoDeleteManager.getAutoDeleteTimer(txn, contact.getId()));
|
||||
autoDeleteManager.receiveAutoDeleteTimer(txn, contact.getId(),
|
||||
remoteTimer, remoteTimestamp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMirrorsRemoteTimestampIfNoUnsentChange() throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
long localTimer = MIN_AUTO_DELETE_TIMER_MS;
|
||||
long remoteTimer = MAX_AUTO_DELETE_TIMER_MS;
|
||||
long remoteTimestamp = now + 1;
|
||||
BdfDictionary oldMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMER, localTimer),
|
||||
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER),
|
||||
new BdfEntry(GROUP_KEY_TIMESTAMP, now));
|
||||
// The timestamp should be updated and the timer should be mirrored
|
||||
BdfDictionary newMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMESTAMP, remoteTimestamp),
|
||||
new BdfEntry(GROUP_KEY_TIMER, remoteTimer));
|
||||
|
||||
expectGetContact(txn);
|
||||
expectGetContactGroup();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(oldMeta));
|
||||
oneOf(clientHelper).mergeGroupMetadata(txn,
|
||||
contactGroup.getId(), newMeta);
|
||||
}});
|
||||
|
||||
autoDeleteManager.receiveAutoDeleteTimer(txn, contact.getId(),
|
||||
remoteTimer, remoteTimestamp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotMirrorUnchangedRemoteTimestampIfUnsentChange()
|
||||
throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
long localTimer = MIN_AUTO_DELETE_TIMER_MS;
|
||||
long remoteTimer = MAX_AUTO_DELETE_TIMER_MS;
|
||||
long remoteTimestamp = now + 1;
|
||||
BdfDictionary oldMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMER, localTimer),
|
||||
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, remoteTimer),
|
||||
new BdfEntry(GROUP_KEY_TIMESTAMP, now));
|
||||
// The timestamp should be updated but the timer should not revert
|
||||
BdfDictionary newMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMESTAMP, remoteTimestamp));
|
||||
|
||||
expectGetContact(txn);
|
||||
expectGetContactGroup();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(oldMeta));
|
||||
oneOf(clientHelper).mergeGroupMetadata(txn,
|
||||
contactGroup.getId(), newMeta);
|
||||
}});
|
||||
|
||||
autoDeleteManager.receiveAutoDeleteTimer(txn, contact.getId(),
|
||||
remoteTimer, remoteTimestamp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMirrorsChangedRemoteTimestampIfUnsentChange()
|
||||
throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
long localTimer = MIN_AUTO_DELETE_TIMER_MS;
|
||||
long oldRemoteTimer = MAX_AUTO_DELETE_TIMER_MS;
|
||||
long newRemoteTimer = MAX_AUTO_DELETE_TIMER_MS - 1;
|
||||
long remoteTimestamp = now + 1;
|
||||
BdfDictionary oldMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMER, localTimer),
|
||||
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, oldRemoteTimer),
|
||||
new BdfEntry(GROUP_KEY_TIMESTAMP, now));
|
||||
// The timestamp should be updated , the timer should be mirrored and
|
||||
// the previous timer should be cleared
|
||||
BdfDictionary newMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_TIMESTAMP, remoteTimestamp),
|
||||
new BdfEntry(GROUP_KEY_TIMER, newRemoteTimer),
|
||||
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER));
|
||||
|
||||
expectGetContact(txn);
|
||||
expectGetContactGroup();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(oldMeta));
|
||||
oneOf(clientHelper).mergeGroupMetadata(txn,
|
||||
contactGroup.getId(), newMeta);
|
||||
}});
|
||||
|
||||
autoDeleteManager.receiveAutoDeleteTimer(txn, contact.getId(),
|
||||
newRemoteTimer, remoteTimestamp);
|
||||
}
|
||||
|
||||
private void expectGetContact(Transaction txn) throws Exception {
|
||||
|
||||
@@ -256,7 +256,8 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
|
||||
|
||||
void expectGetAutoDeleteTimer() throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(autoDeleteManager).getAutoDeleteTimer(txn, contactId);
|
||||
oneOf(autoDeleteManager).getAutoDeleteTimer(txn, contactId,
|
||||
localTimestamp);
|
||||
will(returnValue(NO_AUTO_DELETE_TIMER));
|
||||
}});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user