From c042b1c6d079eb877d684ab84a1dfba6638d618f Mon Sep 17 00:00:00 2001 From: akwizgran Date: Wed, 2 Dec 2020 15:00:45 +0000 Subject: [PATCH 1/7] Mirror the remote auto-delete timer. --- .../conversation/ConversationViewModel.java | 3 +- .../creation/CreateGroupControllerImpl.java | 3 +- .../api/autodelete/AutoDeleteManager.java | 20 +- .../briar/autodelete/AutoDeleteConstants.java | 26 ++- .../autodelete/AutoDeleteManagerImpl.java | 92 +++++++-- .../introduction/AbstractProtocolEngine.java | 9 +- .../invitation/AbstractProtocolEngine.java | 16 +- .../briar/sharing/ProtocolEngineImpl.java | 9 +- .../autodelete/AutoDeleteManagerImplTest.java | 190 +++++++++++++++++- .../AbstractProtocolEngineTest.java | 3 +- 10 files changed, 331 insertions(+), 40 deletions(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java index 073005e16..94ce67231 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java @@ -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); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupControllerImpl.java index 743644590..87e8cf7a7 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupControllerImpl.java @@ -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 diff --git a/briar-api/src/main/java/org/briarproject/briar/api/autodelete/AutoDeleteManager.java b/briar-api/src/main/java/org/briarproject/briar/api/autodelete/AutoDeleteManager.java index 251178817..8599892d1 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/autodelete/AutoDeleteManager.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/autodelete/AutoDeleteManager.java @@ -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; } diff --git a/briar-core/src/main/java/org/briarproject/briar/autodelete/AutoDeleteConstants.java b/briar-core/src/main/java/org/briarproject/briar/autodelete/AutoDeleteConstants.java index 7dc94eced..ff274fcc7 100644 --- a/briar-core/src/main/java/org/briarproject/briar/autodelete/AutoDeleteConstants.java +++ b/briar-core/src/main/java/org/briarproject/briar/autodelete/AutoDeleteConstants.java @@ -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; } diff --git a/briar-core/src/main/java/org/briarproject/briar/autodelete/AutoDeleteManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/autodelete/AutoDeleteManagerImpl.java index ce83a3085..e0644c63e 100644 --- a/briar-core/src/main/java/org/briarproject/briar/autodelete/AutoDeleteManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/autodelete/AutoDeleteManagerImpl.java @@ -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(); + } + } } diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java index 9eb80ceb2..0aa66d126 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java @@ -96,7 +96,8 @@ abstract class AbstractProtocolEngine> 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> 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> 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); diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java index a8d355005..96a2f17f7 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java @@ -152,9 +152,11 @@ abstract class AbstractProtocolEngine> 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> 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); diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java index 37726ac70..8c3c423a5 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java @@ -142,7 +142,8 @@ abstract class ProtocolEngineImpl 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 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 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); diff --git a/briar-core/src/test/java/org/briarproject/briar/autodelete/AutoDeleteManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/autodelete/AutoDeleteManagerImplTest.java index ef2e83f77..d63ac338e 100644 --- a/briar-core/src/test/java/org/briarproject/briar/autodelete/AutoDeleteManagerImplTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/autodelete/AutoDeleteManagerImplTest.java @@ -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 { diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngineTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngineTest.java index 8eb16aa3c..991023c4b 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngineTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngineTest.java @@ -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)); }}); } From 482c90a45e4405fb105883928f76527b41314dc4 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 3 Dec 2020 12:44:28 +0000 Subject: [PATCH 2/7] Hook up incoming messages to the auto-delete manager. --- .../introduction/AbstractProtocolEngine.java | 7 ++++++ .../IntroduceeProtocolEngine.java | 12 +++++++-- .../IntroducerProtocolEngine.java | 8 ++++++ .../briar/messaging/MessagingManagerImpl.java | 15 ++++++++--- .../invitation/AbstractProtocolEngine.java | 7 ++++++ .../invitation/CreatorProtocolEngine.java | 4 +++ .../invitation/InviteeProtocolEngine.java | 2 ++ .../briar/sharing/ProtocolEngineImpl.java | 15 +++++++++++ .../autodelete/AutoDeleteManagerImplTest.java | 3 +-- .../MessageSizeIntegrationTestComponent.java | 2 ++ ...plexMessagingIntegrationTestComponent.java | 2 ++ .../AbstractProtocolEngineTest.java | 25 ++++++++++++++++--- .../invitation/CreatorProtocolEngineTest.java | 14 +++-------- .../invitation/InviteeProtocolEngineTest.java | 4 +-- 14 files changed, 97 insertions(+), 23 deletions(-) diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java index 0aa66d126..dfbbc00a3 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java @@ -240,6 +240,13 @@ abstract class AbstractProtocolEngine> 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 { diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java index 0c6b51f7b..dfb26dca5 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java @@ -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); @@ -341,6 +343,9 @@ class IntroduceeProtocolEngine if (isInvalidDependency(s, m.getPreviousMessageId())) return abort(txn, s); + // Receive the auto-delete timer + receiveAutoDeleteTimer(txn, m); + // Determine next state IntroduceeState state = s.getState() == AWAIT_RESPONSES ? REMOTE_ACCEPTED : AWAIT_AUTH; @@ -370,6 +375,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); diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroducerProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroducerProtocolEngine.java index a05b5807a..b77e3497b 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroducerProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroducerProtocolEngine.java @@ -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()); diff --git a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java index aec7fb62f..0d524c032 100644 --- a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java @@ -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 parseAttachmentHeaders(BdfDictionary meta) diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java index 96a2f17f7..d11db5bbb 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java @@ -300,6 +300,13 @@ abstract class AbstractProtocolEngine> 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 { diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java index ac483b1d6..07ff7a802 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java @@ -201,6 +201,8 @@ class CreatorProtocolEngine extends AbstractProtocolEngine { // 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 { // 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()); diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngine.java index 87d82fdff..d7fdd070b 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngine.java @@ -251,6 +251,8 @@ class InviteeProtocolEngine extends AbstractProtocolEngine { // 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()); diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java index 8c3c423a5..381c22a12 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java @@ -360,6 +360,8 @@ abstract class ProtocolEngineImpl // 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()); @@ -385,6 +387,8 @@ abstract class ProtocolEngineImpl // 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 @@ -432,6 +436,8 @@ abstract class ProtocolEngineImpl // 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()); @@ -485,6 +491,8 @@ abstract class ProtocolEngineImpl // 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); @@ -719,6 +727,13 @@ abstract class ProtocolEngineImpl 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 { diff --git a/briar-core/src/test/java/org/briarproject/briar/autodelete/AutoDeleteManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/autodelete/AutoDeleteManagerImplTest.java index d63ac338e..853b931eb 100644 --- a/briar-core/src/test/java/org/briarproject/briar/autodelete/AutoDeleteManagerImplTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/autodelete/AutoDeleteManagerImplTest.java @@ -28,8 +28,7 @@ import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_TI 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") +@SuppressWarnings("UnnecessaryLocalVariable") // Using them for readability public class AutoDeleteManagerImplTest extends BrambleMockTestCase { private final DatabaseComponent db = context.mock(DatabaseComponent.class); diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTestComponent.java index 634bd69f7..15e09c7d3 100644 --- a/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTestComponent.java @@ -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, diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java index 250e8bbda..56ba72fe3 100644 --- a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java @@ -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, diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngineTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngineTest.java index 991023c4b..1978d2b7f 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngineTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngineTest.java @@ -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,11 +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, - localTimestamp); + 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()); + }}); + } } diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngineTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngineTest.java index 6faaace02..4a3e7fb85 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngineTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngineTest.java @@ -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); diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngineTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngineTest.java index 27c635d3c..7631aeb83 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngineTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngineTest.java @@ -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(), From 6bac5b08abc2a068d040c1f8cafdf58343713bae Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 3 Dec 2020 16:55:18 +0000 Subject: [PATCH 3/7] Don't receive auto-delete timer from remote accept message as introducee. --- .../briar/introduction/IntroduceeProtocolEngine.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java index dfb26dca5..0a1e5ab56 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java @@ -343,9 +343,6 @@ class IntroduceeProtocolEngine if (isInvalidDependency(s, m.getPreviousMessageId())) return abort(txn, s); - // Receive the auto-delete timer - receiveAutoDeleteTimer(txn, m); - // Determine next state IntroduceeState state = s.getState() == AWAIT_RESPONSES ? REMOTE_ACCEPTED : AWAIT_AUTH; From 04cdf27a1c6998fc96e07a4474eaa4a85ad3f633 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 3 Dec 2020 18:00:31 +0000 Subject: [PATCH 4/7] Update integration tests. --- .../invitation/GroupInvitationIntegrationTest.java | 2 +- .../org/briarproject/briar/test/BriarIntegrationTest.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java index 5a9064f28..e2c49bb24 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java @@ -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); } diff --git a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java index 79cee06da..6711de50d 100644 --- a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java @@ -460,9 +460,9 @@ public abstract class BriarIntegrationTest component.getAutoDeleteManager().getAutoDeleteTimer(txn, - contactId)); + contactId, timestamp)); } } From 501ca326d7472b22376370493a6e5c9468922ac3 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Fri, 4 Dec 2020 12:10:10 +0000 Subject: [PATCH 5/7] Add method for UI and tests to get current timer. --- .../briar/api/autodelete/AutoDeleteManager.java | 7 +++++++ .../briar/autodelete/AutoDeleteManagerImpl.java | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/briar-api/src/main/java/org/briarproject/briar/api/autodelete/AutoDeleteManager.java b/briar-api/src/main/java/org/briarproject/briar/api/autodelete/AutoDeleteManager.java index 8599892d1..fac485335 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/autodelete/AutoDeleteManager.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/autodelete/AutoDeleteManager.java @@ -24,6 +24,13 @@ 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. diff --git a/briar-core/src/main/java/org/briarproject/briar/autodelete/AutoDeleteManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/autodelete/AutoDeleteManagerImpl.java index e0644c63e..c07759092 100644 --- a/briar-core/src/main/java/org/briarproject/briar/autodelete/AutoDeleteManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/autodelete/AutoDeleteManagerImpl.java @@ -78,6 +78,19 @@ class AutoDeleteManagerImpl db.removeGroup(txn, getGroup(c)); } + @Override + public long getAutoDeleteTimer(Transaction txn, ContactId c) + throws DbException { + try { + Group g = getGroup(db.getContact(txn, c)); + BdfDictionary meta = + clientHelper.getGroupMetadataAsDictionary(txn, g.getId()); + 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 { From aff649cb06194592a2d8964e5a25a63541c147fb Mon Sep 17 00:00:00 2001 From: akwizgran Date: Fri, 4 Dec 2020 12:10:43 +0000 Subject: [PATCH 6/7] Add integration tests for timer mirroring. --- .../blog/BlogManagerIntegrationTest.java | 2 - .../IntroductionIntegrationTest.java | 4 +- .../messaging/AutoDeleteIntegrationTest.java | 240 ++++++++++++++++++ .../GroupInvitationIntegrationTest.java | 8 +- .../sharing/BlogSharingIntegrationTest.java | 4 +- .../sharing/ForumSharingIntegrationTest.java | 4 +- .../briar/test/BriarIntegrationTest.java | 21 +- 7 files changed, 263 insertions(+), 20 deletions(-) create mode 100644 briar-core/src/test/java/org/briarproject/briar/messaging/AutoDeleteIntegrationTest.java diff --git a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java index 3140a5aad..15f16e606 100644 --- a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java @@ -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); diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java index 2c2eacf21..7ffdc7ccb 100644 --- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java @@ -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 diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/AutoDeleteIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/messaging/AutoDeleteIntegrationTest.java new file mode 100644 index 000000000..1778b7115 --- /dev/null +++ b/briar-core/src/test/java/org/briarproject/briar/messaging/AutoDeleteIntegrationTest.java @@ -0,0 +1,240 @@ +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 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 { + + @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 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 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 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 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 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 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 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)); + } + + private List sortHeaders( + Collection in) { + List out = new ArrayList<>(in); + //noinspection UseCompareMethod + out.sort((a, b) -> + Long.valueOf(a.getTimestamp()).compareTo(b.getTimestamp())); + return out; + } +} diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java index e2c49bb24..f4cbd6c7c 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java @@ -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); diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingIntegrationTest.java index b8454c72d..173d3bebf 100644 --- a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingIntegrationTest.java @@ -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 diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java index 999e9c022..f46b494aa 100644 --- a/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java @@ -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 diff --git a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java index 6711de50d..c2b353811 100644 --- a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java @@ -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 - 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, long timestamp) throws DbException { - return component.getDatabaseComponent().transactionWithResult(false, - txn -> component.getAutoDeleteManager().getAutoDeleteTimer(txn, - contactId, timestamp)); + DatabaseComponent db = component.getDatabaseComponent(); + AutoDeleteManager autoDeleteManager = component.getAutoDeleteManager(); + + return db.transactionWithResult(false, + txn -> autoDeleteManager.getAutoDeleteTimer(txn, contactId, + timestamp)); } } From 45c205e4ba90a644ebe9f09e534fb3bc92ed3272 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Fri, 4 Dec 2020 12:16:58 +0000 Subject: [PATCH 7/7] Use Collections.sort() to satisfy Animal Sniffer. --- .../briar/messaging/AutoDeleteIntegrationTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/AutoDeleteIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/messaging/AutoDeleteIntegrationTest.java index 1778b7115..163c445d1 100644 --- a/briar-core/src/test/java/org/briarproject/briar/messaging/AutoDeleteIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/messaging/AutoDeleteIntegrationTest.java @@ -22,6 +22,7 @@ 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; @@ -229,11 +230,11 @@ public class AutoDeleteIntegrationTest txn -> autoDeleteManager.getAutoDeleteTimer(txn, contactId)); } + @SuppressWarnings({"UseCompareMethod", "Java8ListSort"}) // Animal Sniffer private List sortHeaders( Collection in) { List out = new ArrayList<>(in); - //noinspection UseCompareMethod - out.sort((a, b) -> + sort(out, (a, b) -> Long.valueOf(a.getTimestamp()).compareTo(b.getTimestamp())); return out; }