Merge branch '1832-mirror-remote-self-destruct-timer' into '804-self-destructing-messages'

Mirror the contact's changes to the self-destruct timer

See merge request briar/briar!1312
This commit is contained in:
Torsten Grote
2020-12-04 14:59:15 +00:00
26 changed files with 706 additions and 80 deletions

View File

@@ -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);
}

View File

@@ -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

View File

@@ -24,8 +24,33 @@ public interface AutoDeleteManager {
*/
int MINOR_VERSION = 0;
/**
* Returns the auto-delete timer duration for the given contact. Use
* {@link #getAutoDeleteTimer(Transaction, ContactId, long)} if the timer
* will be used in an outgoing message.
*/
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;
}

View File

@@ -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;
}

View File

@@ -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;
@@ -75,8 +85,29 @@ class AutoDeleteManagerImpl
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);
return meta.getLong(GROUP_KEY_TIMER, NO_AUTO_DELETE_TIMER);
} catch (FormatException e) {
throw new DbException(e);
}
}
@Override
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());
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 +116,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 +177,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();
}
}
}

View File

@@ -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);
@@ -237,6 +240,13 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
return conversationManager.getTimestampForOutgoingMessage(txn, c);
}
void receiveAutoDeleteTimer(Transaction txn, AbstractIntroductionMessage m)
throws DbException {
ContactId c = getContactId(txn, m.getGroupId());
autoDeleteManager.receiveAutoDeleteTimer(txn, c, m.getAutoDeleteTimer(),
m.getTimestamp());
}
private ContactId getContactId(Transaction txn, GroupId contactGroupId)
throws DbException {
try {

View File

@@ -257,6 +257,9 @@ class IntroduceeProtocolEngine
messageTracker
.trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Broadcast IntroductionRequestReceivedEvent
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
Contact c = contactManager.getContact(txn, s.getIntroducer().getId(),
@@ -332,8 +335,7 @@ class IntroduceeProtocolEngine
}
private IntroduceeSession onRemoteAccept(Transaction txn,
IntroduceeSession s, AcceptMessage m)
throws DbException {
IntroduceeSession s, AcceptMessage m) throws DbException {
// The timestamp must be higher than the last request message
if (m.getTimestamp() <= s.getRequestTimestamp())
return abort(txn, s);
@@ -370,6 +372,9 @@ class IntroduceeProtocolEngine
messageTracker
.trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Broadcast IntroductionResponseReceivedEvent
broadcastIntroductionResponseReceivedEvent(txn, s,
s.getIntroducer().getId(), s.getRemote().author, m, false);

View File

@@ -260,6 +260,8 @@ class IntroducerProtocolEngine
// Track the incoming message
messageTracker
.trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Forward ACCEPT message
Introducee i = getOtherIntroducee(s, m.getGroupId());
@@ -321,6 +323,8 @@ class IntroducerProtocolEngine
// Track the incoming message
messageTracker
.trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Forward ACCEPT message
Introducee i = getOtherIntroducee(s, m.getGroupId());
@@ -374,6 +378,8 @@ class IntroducerProtocolEngine
// Track the incoming message
messageTracker
.trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Forward DECLINE message
Introducee i = getOtherIntroducee(s, m.getGroupId());
@@ -427,6 +433,8 @@ class IntroducerProtocolEngine
// Track the incoming message
messageTracker
.trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Forward DECLINE message
Introducee i = getOtherIntroducee(s, m.getGroupId());

View File

@@ -27,6 +27,7 @@ import org.briarproject.bramble.api.sync.MessageStatus;
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook;
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook;
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
import org.briarproject.briar.api.conversation.ConversationManager.ConversationClient;
@@ -89,18 +90,24 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
private final MessageTracker messageTracker;
private final ClientVersioningManager clientVersioningManager;
private final ContactGroupFactory contactGroupFactory;
private final AutoDeleteManager autoDeleteManager;
@Inject
MessagingManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
MessagingManagerImpl(
DatabaseComponent db,
ClientHelper clientHelper,
ClientVersioningManager clientVersioningManager,
MetadataParser metadataParser, MessageTracker messageTracker,
ContactGroupFactory contactGroupFactory) {
MetadataParser metadataParser,
MessageTracker messageTracker,
ContactGroupFactory contactGroupFactory,
AutoDeleteManager autoDeleteManager) {
this.db = db;
this.clientHelper = clientHelper;
this.metadataParser = metadataParser;
this.messageTracker = messageTracker;
this.clientVersioningManager = clientVersioningManager;
this.contactGroupFactory = contactGroupFactory;
this.autoDeleteManager = autoDeleteManager;
}
@Override
@@ -205,6 +212,8 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
new PrivateMessageReceivedEvent(header, contactId);
txn.attach(event);
messageTracker.trackIncomingMessage(txn, m);
autoDeleteManager.receiveAutoDeleteTimer(txn, contactId, timer,
timestamp);
}
private List<AttachmentHeader> parseAttachmentHeaders(BdfDictionary meta)

View File

@@ -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);
@@ -296,6 +300,13 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
return max(s.getLocalTimestamp(), s.getInviteTimestamp());
}
void receiveAutoDeleteTimer(Transaction txn,
DeletableGroupInvitationMessage m) throws DbException {
ContactId c = getContactId(txn, m.getContactGroupId());
autoDeleteManager.receiveAutoDeleteTimer(txn, c, m.getAutoDeleteTimer(),
m.getTimestamp());
}
private void sendMessage(Transaction txn, Message m, MessageType type,
GroupId privateGroupId, boolean visibleInConversation,
long autoDeleteTimer) throws DbException {

View File

@@ -201,6 +201,8 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
// Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(),
m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Share the private group with the contact
setPrivateGroupVisibility(txn, s, SHARED);
// Broadcast an event
@@ -226,6 +228,8 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
// Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(),
m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Broadcast an event
ContactId contactId =
clientHelper.getContactId(txn, m.getContactGroupId());

View File

@@ -251,6 +251,8 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
// Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(),
m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Broadcast an event
PrivateGroup privateGroup = privateGroupFactory.createPrivateGroup(
m.getGroupName(), m.getCreator(), m.getSalt());

View File

@@ -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);
@@ -357,6 +360,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
// Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(),
m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Broadcast an event
ContactId contactId =
clientHelper.getContactId(txn, s.getContactGroupId());
@@ -382,6 +387,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
// Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(),
m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Share the shareable with the contact
setShareableVisibility(txn, s, SHARED);
// Broadcast an event
@@ -429,6 +436,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
// Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(),
m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Broadcast an event
ContactId contactId =
clientHelper.getContactId(txn, m.getContactGroupId());
@@ -482,6 +491,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
// Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(),
m.getTimestamp(), false);
// Receive the auto-delete timer
receiveAutoDeleteTimer(txn, m);
// Make the shareable invisible (not actually needed in REMOTE_HANGING)
try {
setShareableVisibility(txn, s, INVISIBLE);
@@ -716,6 +727,13 @@ abstract class ProtocolEngineImpl<S extends Shareable>
return max(s.getLocalTimestamp(), s.getInviteTimestamp());
}
private void receiveAutoDeleteTimer(Transaction txn,
DeletableSharingMessage m) throws DbException {
ContactId c = getContactId(txn, m.getContactGroupId());
autoDeleteManager.receiveAutoDeleteTimer(txn, c, m.getAutoDeleteTimer(),
m.getTimestamp());
}
private ContactId getContactId(Transaction txn, GroupId contactGroupId)
throws DbException {
try {

View File

@@ -18,12 +18,17 @@ 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;
@SuppressWarnings("UnnecessaryLocalVariable") // Using them for readability
public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
@@ -35,6 +40,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 +119,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 +168,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 +179,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 +192,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 +239,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 {

View File

@@ -46,8 +46,6 @@ public class BlogManagerIntegrationTest
public void setUp() throws Exception {
super.setUp();
author0 = identityManager0.getLocalAuthor();
author1 = identityManager1.getLocalAuthor();
String rssTitle = getRandomString(MAX_AUTHOR_NAME_LENGTH);
rssAuthor = c0.getAuthorFactory().createLocalAuthor(rssTitle);

View File

@@ -263,8 +263,8 @@ public class IntroductionIntegrationTest
addListeners(true, true);
// 0 and 1 set an auto-delete timer for their conversation
setAutoDeleteTimer(c0, contactId1From0);
setAutoDeleteTimer(c1, contactId0From1);
setAutoDeleteTimer(c0, contactId1From0, MIN_AUTO_DELETE_TIMER_MS);
setAutoDeleteTimer(c1, contactId0From1, MIN_AUTO_DELETE_TIMER_MS);
// Make introduction
introductionManager0

View File

@@ -0,0 +1,241 @@
package org.briarproject.briar.messaging;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestDatabaseConfigModule;
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
import org.briarproject.briar.api.conversation.ConversationManager;
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
import org.briarproject.briar.api.messaging.MessagingManager;
import org.briarproject.briar.api.messaging.PrivateMessage;
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
import org.briarproject.briar.test.BriarIntegrationTest;
import org.briarproject.briar.test.BriarIntegrationTestComponent;
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static java.util.Collections.emptyList;
import static java.util.Collections.sort;
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.junit.Assert.assertEquals;
public class AutoDeleteIntegrationTest
extends BriarIntegrationTest<BriarIntegrationTestComponent> {
@Override
protected void createComponents() {
BriarIntegrationTestComponent component =
DaggerBriarIntegrationTestComponent.builder().build();
BriarIntegrationTestComponent.Helper.injectEagerSingletons(component);
component.inject(this);
c0 = DaggerBriarIntegrationTestComponent.builder()
.testDatabaseConfigModule(new TestDatabaseConfigModule(t0Dir))
.build();
BriarIntegrationTestComponent.Helper.injectEagerSingletons(c0);
c1 = DaggerBriarIntegrationTestComponent.builder()
.testDatabaseConfigModule(new TestDatabaseConfigModule(t1Dir))
.build();
BriarIntegrationTestComponent.Helper.injectEagerSingletons(c1);
c2 = DaggerBriarIntegrationTestComponent.builder()
.testDatabaseConfigModule(new TestDatabaseConfigModule(t2Dir))
.build();
BriarIntegrationTestComponent.Helper.injectEagerSingletons(c2);
}
@Test
public void testMessageWithoutTimer() throws Exception {
// 0 creates a message without a timer
MessageId messageId = createMessageWithoutTimer(c0, contactId1From0);
// The message should have been added to 0's view of the conversation
List<ConversationMessageHeader> headers0 =
getMessageHeaders(c0, contactId1From0);
assertEquals(1, headers0.size());
ConversationMessageHeader h0 = headers0.get(0);
assertEquals(messageId, h0.getId());
// The message should not have a timer
assertEquals(NO_AUTO_DELETE_TIMER, h0.getAutoDeleteTimer());
// Sync the message to 1
sync0To1(1, true);
// The message should have been added to 1's view of the conversation
List<ConversationMessageHeader> headers1 =
getMessageHeaders(c1, contactId0From1);
assertEquals(1, headers1.size());
ConversationMessageHeader h1 = headers1.get(0);
assertEquals(messageId, h1.getId());
// The message should not have a timer
assertEquals(NO_AUTO_DELETE_TIMER, h1.getAutoDeleteTimer());
}
@Test
public void testDefaultTimer() throws Exception {
// 0 creates a message with the default timer
MessageId messageId = createMessageWithTimer(c0, contactId1From0);
// The message should have been added to 0's view of the conversation
List<ConversationMessageHeader> headers0 =
getMessageHeaders(c0, contactId1From0);
assertEquals(1, headers0.size());
ConversationMessageHeader h0 = headers0.get(0);
assertEquals(messageId, h0.getId());
// The message should have the default timer (none)
assertEquals(NO_AUTO_DELETE_TIMER, h0.getAutoDeleteTimer());
// Sync the message to 1
sync0To1(1, true);
// The message should have been added to 1's view of the conversation
List<ConversationMessageHeader> headers1 =
getMessageHeaders(c1, contactId0From1);
assertEquals(1, headers1.size());
ConversationMessageHeader h1 = headers1.get(0);
assertEquals(messageId, h1.getId());
// The message should have the default timer (none)
assertEquals(NO_AUTO_DELETE_TIMER, h1.getAutoDeleteTimer());
// Both peers should still be using the default timer
assertEquals(NO_AUTO_DELETE_TIMER,
getAutoDeleteTimer(c0, contactId1From0));
assertEquals(NO_AUTO_DELETE_TIMER,
getAutoDeleteTimer(c1, contactId0From1));
}
@Test
public void testTimerIsMirrored() throws Exception {
// Set 0's timer
setAutoDeleteTimer(c0, contactId1From0, MIN_AUTO_DELETE_TIMER_MS);
// 0 should be using the new timer
assertEquals(MIN_AUTO_DELETE_TIMER_MS,
getAutoDeleteTimer(c0, contactId1From0));
// 1 should still be using the default timer
assertEquals(NO_AUTO_DELETE_TIMER,
getAutoDeleteTimer(c1, contactId0From1));
// 0 creates a message with the new timer
MessageId messageId0 = createMessageWithTimer(c0, contactId1From0);
// The message should have been added to 0's view of the conversation
List<ConversationMessageHeader> headers0 =
getMessageHeaders(c0, contactId1From0);
assertEquals(1, headers0.size());
ConversationMessageHeader h0 = headers0.get(0);
assertEquals(messageId0, h0.getId());
// The message should have the new timer
assertEquals(MIN_AUTO_DELETE_TIMER_MS, h0.getAutoDeleteTimer());
// Sync the message to 1
sync0To1(1, true);
// The message should have been added to 1's view of the conversation
List<ConversationMessageHeader> headers1 =
getMessageHeaders(c1, contactId0From1);
assertEquals(1, headers1.size());
ConversationMessageHeader h1 = headers1.get(0);
assertEquals(messageId0, h1.getId());
// The message should have the new timer
assertEquals(MIN_AUTO_DELETE_TIMER_MS, h1.getAutoDeleteTimer());
// 0 and 1 should both be using the new timer
assertEquals(MIN_AUTO_DELETE_TIMER_MS,
getAutoDeleteTimer(c0, contactId1From0));
assertEquals(MIN_AUTO_DELETE_TIMER_MS,
getAutoDeleteTimer(c1, contactId0From1));
// 1 creates a message
MessageId messageId1 = createMessageWithTimer(c1, contactId0From1);
// The message should have been added to 1's view of the conversation
headers1 = getMessageHeaders(c1, contactId0From1);
assertEquals(2, headers1.size());
assertEquals(messageId0, headers1.get(0).getId());
assertEquals(messageId1, headers1.get(1).getId());
// The message should have the new timer
assertEquals(MIN_AUTO_DELETE_TIMER_MS,
headers1.get(1).getAutoDeleteTimer());
// Sync the message to 0
sync1To0(1, true);
// The message should have been added to 0's view of the conversation
headers0 = getMessageHeaders(c0, contactId1From0);
assertEquals(2, headers0.size());
assertEquals(messageId0, headers0.get(0).getId());
assertEquals(messageId1, headers0.get(1).getId());
// The message should have the new timer
assertEquals(MIN_AUTO_DELETE_TIMER_MS,
headers0.get(1).getAutoDeleteTimer());
// 0 and 1 should both be using the new timer
assertEquals(MIN_AUTO_DELETE_TIMER_MS,
getAutoDeleteTimer(c0, contactId1From0));
assertEquals(MIN_AUTO_DELETE_TIMER_MS,
getAutoDeleteTimer(c1, contactId0From1));
}
private MessageId createMessageWithoutTimer(
BriarIntegrationTestComponent component, ContactId contactId)
throws Exception {
DatabaseComponent db = component.getDatabaseComponent();
ConversationManager conversationManager =
component.getConversationManager();
MessagingManager messagingManager = component.getMessagingManager();
PrivateMessageFactory factory = component.getPrivateMessageFactory();
GroupId groupId = messagingManager.getConversationId(contactId);
return db.transactionWithResult(false, txn -> {
long timestamp = conversationManager
.getTimestampForOutgoingMessage(txn, contactId);
PrivateMessage m = factory.createPrivateMessage(groupId, timestamp,
"Hi!", emptyList());
messagingManager.addLocalMessage(txn, m);
return m.getMessage().getId();
});
}
private MessageId createMessageWithTimer(
BriarIntegrationTestComponent component, ContactId contactId)
throws Exception {
DatabaseComponent db = component.getDatabaseComponent();
ConversationManager conversationManager =
component.getConversationManager();
AutoDeleteManager autoDeleteManager = component.getAutoDeleteManager();
MessagingManager messagingManager = component.getMessagingManager();
PrivateMessageFactory factory = component.getPrivateMessageFactory();
GroupId groupId = messagingManager.getConversationId(contactId);
return db.transactionWithResult(false, txn -> {
long timestamp = conversationManager
.getTimestampForOutgoingMessage(txn, contactId);
long timer = autoDeleteManager
.getAutoDeleteTimer(txn, contactId, timestamp);
PrivateMessage m = factory.createPrivateMessage(groupId, timestamp,
"Hi!", emptyList(), timer);
messagingManager.addLocalMessage(txn, m);
return m.getMessage().getId();
});
}
private List<ConversationMessageHeader> getMessageHeaders(
BriarIntegrationTestComponent component, ContactId contactId)
throws Exception {
DatabaseComponent db = component.getDatabaseComponent();
MessagingManager messagingManager = component.getMessagingManager();
return sortHeaders(db.transactionWithResult(true, txn ->
messagingManager.getMessageHeaders(txn, contactId)));
}
private long getAutoDeleteTimer(BriarIntegrationTestComponent component,
ContactId contactId) throws DbException {
DatabaseComponent db = component.getDatabaseComponent();
AutoDeleteManager autoDeleteManager = component.getAutoDeleteManager();
return db.transactionWithResult(false,
txn -> autoDeleteManager.getAutoDeleteTimer(txn, contactId));
}
@SuppressWarnings({"UseCompareMethod", "Java8ListSort"}) // Animal Sniffer
private List<ConversationMessageHeader> sortHeaders(
Collection<ConversationMessageHeader> in) {
List<ConversationMessageHeader> out = new ArrayList<>(in);
sort(out, (a, b) ->
Long.valueOf(a.getTimestamp()).compareTo(b.getTimestamp()));
return out;
}
}

View File

@@ -3,6 +3,7 @@ package org.briarproject.briar.messaging;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.briar.autodelete.AutoDeleteModule;
import org.briarproject.briar.client.BriarClientModule;
import org.briarproject.briar.forum.ForumModule;
@@ -12,6 +13,7 @@ import dagger.Component;
@Singleton
@Component(modules = {
AutoDeleteModule.class,
BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class,
BriarClientModule.class,

View File

@@ -10,6 +10,7 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.briar.api.messaging.MessagingManager;
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
import org.briarproject.briar.autodelete.AutoDeleteModule;
import org.briarproject.briar.client.BriarClientModule;
import javax.inject.Singleton;
@@ -18,6 +19,7 @@ import dagger.Component;
@Singleton
@Component(modules = {
AutoDeleteModule.class,
BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class,
BriarClientModule.class,

View File

@@ -153,7 +153,7 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
if (visible) expectGetTimestampForVisibleMessage(messageTimestamp);
else expectGetTimestampForInvisibleMessage(messageTimestamp);
expectCheckWhetherContactSupportsAutoDeletion();
if (visible) expectGetAutoDeleteTimer();
if (visible) expectGetAutoDeleteTimer(messageTimestamp);
context.checking(new Expectations() {{
oneOf(messageEncoder).encodeJoinMessage(m.getContactGroupId(),
m.getPrivateGroupId(), m.getTimestamp(),
@@ -167,7 +167,7 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
if (visible) expectGetTimestampForVisibleMessage(messageTimestamp);
else expectGetTimestampForInvisibleMessage(messageTimestamp);
expectCheckWhetherContactSupportsAutoDeletion();
if (visible) expectGetAutoDeleteTimer();
if (visible) expectGetAutoDeleteTimer(messageTimestamp);
context.checking(new Expectations() {{
oneOf(messageEncoder).encodeLeaveMessage(contactGroupId,
privateGroupId, messageTimestamp, lastLocalMessageId,
@@ -254,10 +254,28 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
}});
}
void expectGetAutoDeleteTimer() throws Exception {
void expectGetAutoDeleteTimer(long timestamp) throws Exception {
context.checking(new Expectations() {{
oneOf(autoDeleteManager).getAutoDeleteTimer(txn, contactId);
oneOf(autoDeleteManager).getAutoDeleteTimer(txn, contactId,
timestamp);
will(returnValue(NO_AUTO_DELETE_TIMER));
}});
}
void expectTrackUnreadMessage(long timestamp) throws Exception {
context.checking(new Expectations() {{
oneOf(messageTracker).trackMessage(txn, contactGroupId, timestamp,
false);
}});
}
void expectReceiveAutoDeleteTimer(DeletableGroupInvitationMessage m)
throws Exception {
context.checking(new Expectations() {{
oneOf(clientHelper).getContactId(txn, contactGroupId);
will(returnValue(contactId));
oneOf(autoDeleteManager).receiveAutoDeleteTimer(txn, contactId,
m.getAutoDeleteTimer(), m.getTimestamp());
}});
}
}

View File

@@ -308,11 +308,8 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
expectSendJoinMessage(properJoinMessage, false);
expectMarkMessageVisibleInUi(properJoinMessage.getId());
context.checking(new Expectations() {{
oneOf(messageTracker)
.trackMessage(txn, contactGroupId, inviteTimestamp + 1,
false);
}});
expectTrackUnreadMessage(properJoinMessage.getTimestamp());
expectReceiveAutoDeleteTimer(properJoinMessage);
expectGetContactId();
expectSetPrivateGroupVisibility(SHARED);
CreatorSession newSession =
@@ -399,11 +396,8 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
CreatorSession session = getDefaultSession(INVITED);
expectMarkMessageVisibleInUi(properLeaveMessage.getId());
context.checking(new Expectations() {{
oneOf(messageTracker)
.trackMessage(txn, contactGroupId, inviteTimestamp + 1,
false);
}});
expectTrackUnreadMessage(properLeaveMessage.getTimestamp());
expectReceiveAutoDeleteTimer(properLeaveMessage);
expectGetContactId();
CreatorSession newSession =
engine.onLeaveMessage(txn, session, properLeaveMessage);

View File

@@ -168,8 +168,8 @@ public class GroupInvitationIntegrationTest
@Test
public void testInvitationDeclineWithAutoDelete() throws Exception {
// 0 and 1 set an auto-delete timer for their conversation
setAutoDeleteTimer(c0, contactId1From0);
setAutoDeleteTimer(c1, contactId0From1);
setAutoDeleteTimer(c0, contactId1From0, MIN_AUTO_DELETE_TIMER_MS);
setAutoDeleteTimer(c1, contactId0From1, MIN_AUTO_DELETE_TIMER_MS);
// Send invitation
sendInvitation(clock.currentTimeMillis(), null);
@@ -253,8 +253,8 @@ public class GroupInvitationIntegrationTest
@Test
public void testInvitationAcceptWithAutoDelete() throws Exception {
// 0 and 1 set an auto-delete timer for their conversation
setAutoDeleteTimer(c0, contactId1From0);
setAutoDeleteTimer(c1, contactId0From1);
setAutoDeleteTimer(c0, contactId1From0, MIN_AUTO_DELETE_TIMER_MS);
setAutoDeleteTimer(c1, contactId0From1, MIN_AUTO_DELETE_TIMER_MS);
// Send invitation
sendInvitation(clock.currentTimeMillis(), null);
@@ -743,7 +743,7 @@ public class GroupInvitationIntegrationTest
throws DbException {
byte[] signature = groupInvitationFactory.signInvitation(contact1From0,
privateGroup.getId(), timestamp, author0.getPrivateKey());
long timer = getAutoDeleteTimer(c0, contactId1From0);
long timer = getAutoDeleteTimer(c0, contactId1From0, timestamp);
groupInvitationManager0.sendInvitation(privateGroup.getId(),
contactId1From0, text, timestamp, signature, timer);
}

View File

@@ -366,9 +366,9 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
}});
expectMarkMessageVisibleInUi(properInviteMessage.getId());
expectMarkMessageAvailableToAnswer(properInviteMessage.getId(), true);
expectTrackUnreadMessage(properInviteMessage.getTimestamp());
expectReceiveAutoDeleteTimer(properInviteMessage);
context.checking(new Expectations() {{
oneOf(messageTracker).trackMessage(txn, contactGroupId,
properInviteMessage.getTimestamp(), false);
oneOf(privateGroupFactory)
.createPrivateGroup(properInviteMessage.getGroupName(),
properInviteMessage.getCreator(),

View File

@@ -210,8 +210,8 @@ public class BlogSharingIntegrationTest
listenToEvents(true);
// Set an auto-delete timer for the conversation
setAutoDeleteTimer(c0, contactId1From0);
setAutoDeleteTimer(c1, contactId0From1);
setAutoDeleteTimer(c0, contactId1From0, MIN_AUTO_DELETE_TIMER_MS);
setAutoDeleteTimer(c1, contactId0From1, MIN_AUTO_DELETE_TIMER_MS);
// Send invitation
blogSharingManager0

View File

@@ -191,8 +191,8 @@ public class ForumSharingIntegrationTest
@Test
public void testSuccessfulSharingWithAutoDelete() throws Exception {
// Set an auto-delete timer for the conversation
setAutoDeleteTimer(c0, contactId1From0);
setAutoDeleteTimer(c1, contactId0From1);
setAutoDeleteTimer(c0, contactId1From0, MIN_AUTO_DELETE_TIMER_MS);
setAutoDeleteTimer(c1, contactId0From1, MIN_AUTO_DELETE_TIMER_MS);
// Send invitation
forumSharingManager0

View File

@@ -30,6 +30,7 @@ import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.TestTransportConnectionReader;
import org.briarproject.bramble.test.TestTransportConnectionWriter;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
import org.briarproject.briar.api.blog.BlogFactory;
import org.briarproject.briar.api.blog.BlogPostFactory;
import org.briarproject.briar.api.client.MessageTracker;
@@ -63,7 +64,6 @@ import static org.briarproject.bramble.api.sync.validation.MessageState.PENDING;
import static org.briarproject.bramble.test.TestPluginConfigModule.SIMPLEX_TRANSPORT_ID;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -453,16 +453,21 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
}
protected void setAutoDeleteTimer(BriarIntegrationTestComponent component,
ContactId contactId) throws DbException {
component.getDatabaseComponent().transaction(false, txn ->
component.getAutoDeleteManager().setAutoDeleteTimer(txn,
contactId, MIN_AUTO_DELETE_TIMER_MS));
ContactId contactId, long timer) throws DbException {
DatabaseComponent db = component.getDatabaseComponent();
AutoDeleteManager autoDeleteManager = component.getAutoDeleteManager();
db.transaction(false, txn ->
autoDeleteManager.setAutoDeleteTimer(txn, contactId, timer));
}
protected long getAutoDeleteTimer(BriarIntegrationTestComponent component,
ContactId contactId) throws DbException {
return component.getDatabaseComponent().transactionWithResult(true,
txn -> component.getAutoDeleteManager().getAutoDeleteTimer(txn,
contactId));
ContactId contactId, long timestamp) throws DbException {
DatabaseComponent db = component.getDatabaseComponent();
AutoDeleteManager autoDeleteManager = component.getAutoDeleteManager();
return db.transactionWithResult(false,
txn -> autoDeleteManager.getAutoDeleteTimer(txn, contactId,
timestamp));
}
}