messageIds)
throws DbException;
@NotNullByDefault
@@ -75,10 +77,8 @@ public interface ConversationManager {
/**
* Deletes all messages associated with the given contact.
- *
- * @return true if all messages could be deleted, false otherwise
*/
- boolean deleteAllMessages(Transaction txn,
+ DeletionResult deleteAllMessages(Transaction txn,
ContactId c) throws DbException;
/**
@@ -86,10 +86,8 @@ public interface ConversationManager {
*
* The set of message IDs must only include message IDs returned by
* {@link #getMessageIds}.
- *
- * @return true if all messages could be deleted, false otherwise
*/
- boolean deleteMessages(Transaction txn, ContactId c,
+ DeletionResult deleteMessages(Transaction txn, ContactId c,
Set messageIds) throws DbException;
}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/conversation/DeletionResult.java b/briar-api/src/main/java/org/briarproject/briar/api/conversation/DeletionResult.java
new file mode 100644
index 000000000..214024cd1
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/conversation/DeletionResult.java
@@ -0,0 +1,67 @@
+package org.briarproject.briar.api.conversation;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.NotThreadSafe;
+
+import static org.briarproject.briar.api.conversation.ConversationManager.DELETE_NOT_DOWNLOADED;
+import static org.briarproject.briar.api.conversation.ConversationManager.DELETE_SESSION_INCOMPLETE;
+import static org.briarproject.briar.api.conversation.ConversationManager.DELETE_SESSION_IN_PROGRESS;
+import static org.briarproject.briar.api.conversation.ConversationManager.DELETE_SESSION_IS_INTRODUCTION;
+import static org.briarproject.briar.api.conversation.ConversationManager.DELETE_SESSION_IS_INVITATION;
+
+@NotThreadSafe
+@NotNullByDefault
+public class DeletionResult {
+
+ private int result = 0;
+
+ public void addDeletionResult(DeletionResult deletionResult) {
+ result |= deletionResult.result;
+ }
+
+ public void addInvitationNotAllSelected() {
+ result |= DELETE_SESSION_INCOMPLETE | DELETE_SESSION_IS_INVITATION;
+ }
+
+ public void addInvitationSessionInProgress() {
+ result |= DELETE_SESSION_IN_PROGRESS | DELETE_SESSION_IS_INVITATION;
+ }
+
+ public void addIntroductionNotAllSelected() {
+ result |= DELETE_SESSION_INCOMPLETE | DELETE_SESSION_IS_INTRODUCTION;
+ }
+
+ public void addIntroductionSessionInProgress() {
+ result |= DELETE_SESSION_IN_PROGRESS | DELETE_SESSION_IS_INTRODUCTION;
+ }
+
+ public void addNotFullyDownloaded() {
+ result |= DELETE_NOT_DOWNLOADED;
+ }
+
+ public boolean allDeleted() {
+ return result == 0;
+ }
+
+ public boolean hasIntroduction() {
+ return (result & DELETE_SESSION_IS_INTRODUCTION) != 0;
+ }
+
+ public boolean hasInvitation() {
+ return (result & DELETE_SESSION_IS_INVITATION) != 0;
+ }
+
+ public boolean hasSessionInProgress() {
+ return (result & DELETE_SESSION_IN_PROGRESS) != 0;
+ }
+
+ public boolean hasNotAllSelected() {
+ return (result & DELETE_SESSION_INCOMPLETE) != 0;
+ }
+
+ public boolean hasNotFullyDownloaded() {
+ return (result & DELETE_NOT_DOWNLOADED) != 0;
+ }
+
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java
index 0fdb774ca..cc3bfb2c9 100644
--- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java
@@ -32,6 +32,7 @@ import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVer
import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
+import org.briarproject.briar.api.conversation.DeletionResult;
import org.briarproject.briar.api.introduction.IntroductionManager;
import org.briarproject.briar.api.introduction.IntroductionRequest;
import org.briarproject.briar.api.introduction.IntroductionResponse;
@@ -561,73 +562,45 @@ class IntroductionManagerImpl extends ConversationClientImpl
@FunctionalInterface
private interface MessageRetriever {
- Map getMessages(Transaction txn,
- GroupId contactGroup) throws DbException;
- }
-
- @FunctionalInterface
- private interface MessageDeletionChecker {
- /**
- * This is called for all messages belonging to a session.
- * It returns true if the given {@link MessageId} causes a problem
- * so that the session can not be deleted.
- */
- boolean causesProblem(MessageId messageId);
+ Set getMessages(Set allMessages);
}
@Override
- public boolean deleteAllMessages(Transaction txn, ContactId c)
+ public DeletionResult deleteAllMessages(Transaction txn, ContactId c)
throws DbException {
- return deleteMessages(txn, c, (txn1, g) -> {
- // get metadata for all messages in the group
- Map messages;
- try {
- messages = clientHelper.getMessageMetadataAsDictionary(txn1, g);
- } catch (FormatException e) {
- throw new DbException(e);
- }
- return messages;
- }, messageId -> false);
+ return deleteMessages(txn, c, allMessages -> allMessages);
}
@Override
- public boolean deleteMessages(Transaction txn, ContactId c,
+ public DeletionResult deleteMessages(Transaction txn, ContactId c,
Set messageIds) throws DbException {
- return deleteMessages(txn, c, (txn1, g) -> {
- // get metadata for messages that shall be deleted
- Map messages =
- new HashMap<>(messageIds.size());
- for (MessageId m : messageIds) {
- BdfDictionary d;
- try {
- d = clientHelper.getMessageMetadataAsDictionary(txn1, m);
- } catch (FormatException e) {
- throw new DbException(e);
- }
- // If message metadata does not exist,
- // getMessageMetadataAsDictionary(txn, m) returns empty Metadata
- if (!d.isEmpty()) messages.put(m, d);
- }
- return messages;
- // don't delete sessions if a message is not part of messageIds
- }, messageId -> !messageIds.contains(messageId));
+ return deleteMessages(txn, c, allMessages -> messageIds);
}
- private boolean deleteMessages(Transaction txn, ContactId c,
- MessageRetriever retriever, MessageDeletionChecker checker)
- throws DbException {
+ private DeletionResult deleteMessages(Transaction txn, ContactId c,
+ MessageRetriever retriever) throws DbException {
// get ID of the contact group
GroupId g = getContactGroup(db.getContact(txn, c)).getId();
- // get messages to be deleted
- Map messages = retriever.getMessages(txn, g);
+ // get metadata for all messages in the group
+ Map messages;
+ try {
+ messages = clientHelper.getMessageMetadataAsDictionary(txn, g);
+ } catch (FormatException e) {
+ throw new DbException(e);
+ }
- // assign protocol messages to their sessions
+ // get messages to be deleted
+ Set selected = retriever.getMessages(messages.keySet());
+
+ // get sessions for selected messages
Map sessions = new HashMap<>();
- for (Entry entry : messages.entrySet()) {
+ for (MessageId id : selected) {
+ BdfDictionary d = messages.get(id);
+ if (d == null) continue; // throw new NoSuchMessageException()
MessageMetadata m;
try {
- m = messageParser.parseMetadata(entry.getValue());
+ m = messageParser.parseMetadata(d);
} catch (FormatException e) {
throw new DbException(e);
}
@@ -644,6 +617,31 @@ class IntroductionManagerImpl extends ConversationClientImpl
session = getDeletableSession(txn, g, m.getSessionId());
sessions.put(m.getSessionId(), session);
}
+ session.messages.add(id);
+ }
+
+ // assign other protocol messages to their sessions
+ for (Entry entry : messages.entrySet()) {
+ // we handled selected messages above
+ if (selected.contains(entry.getKey())) continue;
+
+ MessageMetadata m;
+ try {
+ m = messageParser.parseMetadata(entry.getValue());
+ } catch (FormatException e) {
+ throw new DbException(e);
+ }
+ if (!m.isVisibleInConversation()) continue;
+ if (m.getSessionId() == null) {
+ // This can only be an unhandled REQUEST message.
+ // Its session is created and stored in incomingMessage(),
+ // and getMessageMetadata() only returns delivered messages,
+ // so the session ID should have been assigned.
+ throw new AssertionError("missing session ID");
+ }
+ // get session from map or database
+ DeletableSession session = sessions.get(m.getSessionId());
+ if (session == null) continue; // not a session of a selected msg
session.messages.add(entry.getKey());
}
@@ -652,10 +650,10 @@ class IntroductionManagerImpl extends ConversationClientImpl
for (MessageStatus status : db.getMessageStatus(txn, c, g)) {
if (!status.isSeen()) notAcked.add(status.getMessageId());
}
- boolean allDeleted =
- deleteCompletedSessions(txn, sessions, notAcked, checker);
+ DeletionResult result =
+ deleteCompletedSessions(txn, sessions, notAcked, selected);
recalculateGroupCount(txn, g);
- return allDeleted;
+ return result;
}
private DeletableSession getDeletableSession(Transaction txn,
@@ -677,28 +675,31 @@ class IntroductionManagerImpl extends ConversationClientImpl
}
}
- private boolean deleteCompletedSessions(Transaction txn,
+ private DeletionResult deleteCompletedSessions(Transaction txn,
Map sessions, Set notAcked,
- MessageDeletionChecker checker) throws DbException {
+ Set selected) throws DbException {
// find completed sessions to delete
- boolean allDeleted = true;
+ DeletionResult result = new DeletionResult();
for (DeletableSession session : sessions.values()) {
if (!session.state.isComplete()) {
- allDeleted = false;
+ result.addIntroductionSessionInProgress();
continue;
}
// we can only delete sessions
// where delivery of all messages was confirmed (aka ACKed)
- boolean allAcked = true;
+ boolean sessionDeletable = true;
for (MessageId m : session.messages) {
- if (notAcked.contains(m) || checker.causesProblem(m)) {
- allAcked = false;
- allDeleted = false;
+ if (notAcked.contains(m) || !selected.contains(m)) {
+ sessionDeletable = false;
+ if (notAcked.contains(m))
+ result.addIntroductionSessionInProgress();
+ if (!selected.contains(m))
+ result.addIntroductionNotAllSelected();
break;
}
}
// delete messages of session, if all were ACKed
- if (allAcked) {
+ if (sessionDeletable) {
for (MessageId m : session.messages) {
db.deleteMessage(txn, m);
db.deleteMessageMetadata(txn, m);
@@ -707,7 +708,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
// and then needs the previous MessageIds
}
}
- return allDeleted;
+ return result;
}
@Override
diff --git a/briar-core/src/main/java/org/briarproject/briar/messaging/ConversationManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/messaging/ConversationManagerImpl.java
index 7163e4c80..7b991f3de 100644
--- a/briar-core/src/main/java/org/briarproject/briar/messaging/ConversationManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/messaging/ConversationManagerImpl.java
@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
import org.briarproject.briar.api.conversation.ConversationManager;
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
+import org.briarproject.briar.api.conversation.DeletionResult;
import java.util.ArrayList;
import java.util.Collection;
@@ -75,27 +76,27 @@ class ConversationManagerImpl implements ConversationManager {
}
@Override
- public boolean deleteAllMessages(ContactId c) throws DbException {
+ public DeletionResult deleteAllMessages(ContactId c) throws DbException {
return db.transactionWithResult(false, txn -> {
- boolean allDeleted = true;
+ DeletionResult result = new DeletionResult();
for (ConversationClient client : clients) {
- allDeleted = client.deleteAllMessages(txn, c) && allDeleted;
+ result.addDeletionResult(client.deleteAllMessages(txn, c));
}
- return allDeleted;
+ return result;
});
}
@Override
- public boolean deleteMessages(ContactId c, Collection toDelete)
+ public DeletionResult deleteMessages(ContactId c, Collection toDelete)
throws DbException {
return db.transactionWithResult(false, txn -> {
- boolean allDeleted = true;
+ DeletionResult result = new DeletionResult();
for (ConversationClient client : clients) {
Set idSet = client.getMessageIds(txn, c);
idSet.retainAll(toDelete);
- allDeleted = client.deleteMessages(txn, c, idSet) && allDeleted;
+ result.addDeletionResult(client.deleteMessages(txn, c, idSet));
}
- return allDeleted;
+ return result;
});
}
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 36072a4d7..c048e0034 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
@@ -31,6 +31,7 @@ import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
import org.briarproject.briar.api.conversation.ConversationManager.ConversationClient;
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
+import org.briarproject.briar.api.conversation.DeletionResult;
import org.briarproject.briar.api.messaging.Attachment;
import org.briarproject.briar.api.messaging.AttachmentHeader;
import org.briarproject.briar.api.messaging.FileTooBigException;
@@ -430,7 +431,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
}
@Override
- public boolean deleteAllMessages(Transaction txn, ContactId c)
+ public DeletionResult deleteAllMessages(Transaction txn, ContactId c)
throws DbException {
GroupId g = getContactGroup(db.getContact(txn, c)).getId();
// this indiscriminately deletes all raw messages in this group
@@ -440,13 +441,13 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
db.deleteMessageMetadata(txn, messageId);
}
messageTracker.initializeGroupCount(txn, g);
- return true;
+ return new DeletionResult();
}
@Override
- public boolean deleteMessages(Transaction txn, ContactId c,
+ public DeletionResult deleteMessages(Transaction txn, ContactId c,
Set messageIds) throws DbException {
- boolean allDeleted = true;
+ DeletionResult result = new DeletionResult();
for (MessageId m : messageIds) {
// get attachment headers
List headers;
@@ -480,12 +481,12 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
db.deleteMessage(txn, m);
db.deleteMessageMetadata(txn, m);
} else {
- allDeleted = false;
+ result.addNotFullyDownloaded();
}
}
GroupId g = getContactGroup(db.getContact(txn, c)).getId();
recalculateGroupCount(txn, g);
- return allDeleted;
+ return result;
}
private void recalculateGroupCount(Transaction txn, GroupId g)
diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java
index fdacd865e..f3c18e328 100644
--- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java
@@ -27,6 +27,7 @@ import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVer
import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
+import org.briarproject.briar.api.conversation.DeletionResult;
import org.briarproject.briar.api.privategroup.PrivateGroup;
import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
@@ -636,7 +637,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
}
@Override
- public boolean deleteAllMessages(Transaction txn, ContactId c)
+ public DeletionResult deleteAllMessages(Transaction txn, ContactId c)
throws DbException {
return deleteMessages(txn, c, (txn1, g, metadata) -> {
// get all sessions and their states
@@ -657,7 +658,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
}
@Override
- public boolean deleteMessages(Transaction txn, ContactId c,
+ public DeletionResult deleteMessages(Transaction txn, ContactId c,
Set messageIds) throws DbException {
return deleteMessages(txn, c, (txn1, g, metadata) -> {
// get only sessions from given messageIds
@@ -685,7 +686,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
}, messageId -> !messageIds.contains(messageId));
}
- private boolean deleteMessages(Transaction txn, ContactId c,
+ private DeletionResult deleteMessages(Transaction txn, ContactId c,
DeletableSessionRetriever retriever, MessageDeletionChecker checker)
throws DbException {
// get ID of the contact group
@@ -729,40 +730,43 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
for (MessageStatus status : db.getMessageStatus(txn, c, g)) {
if (!status.isSeen()) notAcked.add(status.getMessageId());
}
- boolean allDeleted = deleteCompletedSessions(txn, sessions.values(),
+ DeletionResult result = deleteCompletedSessions(txn, sessions.values(),
notAcked, checker);
recalculateGroupCount(txn, g);
- return allDeleted;
+ return result;
}
- private boolean deleteCompletedSessions(Transaction txn,
+ private DeletionResult deleteCompletedSessions(Transaction txn,
Collection sessions, Set notAcked,
MessageDeletionChecker checker) throws DbException {
// find completed sessions to delete
- boolean allDeleted = true;
+ DeletionResult result = new DeletionResult();
for (DeletableSession session : sessions) {
if (session.state.isAwaitingResponse()) {
- allDeleted = false;
+ result.addInvitationSessionInProgress();
continue;
}
// we can only delete sessions
// where delivery of all messages was confirmed (aka ACKed)
- boolean allAcked = true;
+ boolean sessionDeletable = true;
for (MessageId m : session.messages) {
if (notAcked.contains(m) || checker.causesProblem(m)) {
- allAcked = false;
- allDeleted = false;
+ sessionDeletable = false;
+ if (notAcked.contains(m))
+ result.addInvitationSessionInProgress();
+ if (checker.causesProblem(m))
+ result.addInvitationNotAllSelected();
break;
}
}
- if (allAcked) {
+ if (sessionDeletable) {
for (MessageId m : session.messages) {
db.deleteMessage(txn, m);
db.deleteMessageMetadata(txn, m);
}
}
}
- return allDeleted;
+ return result;
}
@Override
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java
index 4f7ce604a..0e3aba42b 100644
--- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java
@@ -28,6 +28,7 @@ import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
import org.briarproject.briar.api.conversation.ConversationRequest;
+import org.briarproject.briar.api.conversation.DeletionResult;
import org.briarproject.briar.api.sharing.InvitationResponse;
import org.briarproject.briar.api.sharing.Shareable;
import org.briarproject.briar.api.sharing.SharingInvitationItem;
@@ -557,7 +558,7 @@ abstract class SharingManagerImpl
}
@Override
- public boolean deleteAllMessages(Transaction txn, ContactId c)
+ public DeletionResult deleteAllMessages(Transaction txn, ContactId c)
throws DbException {
return deleteMessages(txn, c, (txn1, contactGroup, metadata) -> {
// get all sessions and their states
@@ -578,7 +579,7 @@ abstract class SharingManagerImpl
}
@Override
- public boolean deleteMessages(Transaction txn, ContactId c,
+ public DeletionResult deleteMessages(Transaction txn, ContactId c,
Set messageIds) throws DbException {
return deleteMessages(txn, c, (txn1, g, metadata) -> {
// get only sessions from given messageIds
@@ -606,7 +607,7 @@ abstract class SharingManagerImpl
}, messageId -> !messageIds.contains(messageId));
}
- private boolean deleteMessages(Transaction txn, ContactId c,
+ private DeletionResult deleteMessages(Transaction txn, ContactId c,
DeletableSessionRetriever retriever, MessageDeletionChecker checker)
throws DbException {
// get ID of the contact group
@@ -621,7 +622,7 @@ abstract class SharingManagerImpl
throw new DbException(e);
}
- // get all sessions and their states
+ // get sessions and their states
Map sessions =
retriever.getDeletableSessions(txn, g, metadata);
@@ -650,40 +651,43 @@ abstract class SharingManagerImpl
for (MessageStatus status : db.getMessageStatus(txn, c, g)) {
if (!status.isSeen()) notAcked.add(status.getMessageId());
}
- boolean allDeleted = deleteCompletedSessions(txn, sessions.values(),
+ DeletionResult result = deleteCompletedSessions(txn, sessions.values(),
notAcked, checker);
recalculateGroupCount(txn, g);
- return allDeleted;
+ return result;
}
- private boolean deleteCompletedSessions(Transaction txn,
+ private DeletionResult deleteCompletedSessions(Transaction txn,
Collection sessions, Set notAcked,
MessageDeletionChecker checker) throws DbException {
// find completed sessions to delete
- boolean allDeleted = true;
+ DeletionResult result = new DeletionResult();
for (DeletableSession session : sessions) {
if (session.state.isAwaitingResponse()) {
- allDeleted = false;
+ result.addInvitationSessionInProgress();
continue;
}
// we can only delete sessions
// where delivery of all messages was confirmed (aka ACKed)
- boolean allAcked = true;
+ boolean sessionDeletable = true;
for (MessageId m : session.messages) {
if (notAcked.contains(m) || checker.causesProblem(m)) {
- allAcked = false;
- allDeleted = false;
+ sessionDeletable = false;
+ if (notAcked.contains(m))
+ result.addInvitationSessionInProgress();
+ if (checker.causesProblem(m))
+ result.addInvitationNotAllSelected();
break;
}
}
- if (allAcked) {
+ if (sessionDeletable) {
for (MessageId m : session.messages) {
db.deleteMessage(txn, m);
db.deleteMessageMetadata(txn, m);
}
}
}
- return allDeleted;
+ return result;
}
@Override
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 b53b6465d..720bf8219 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
@@ -28,6 +28,7 @@ import org.briarproject.briar.api.client.ProtocolStateException;
import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
import org.briarproject.briar.api.conversation.ConversationResponse;
+import org.briarproject.briar.api.conversation.DeletionResult;
import org.briarproject.briar.api.introduction.IntroductionManager;
import org.briarproject.briar.api.introduction.IntroductionRequest;
import org.briarproject.briar.api.introduction.IntroductionResponse;
@@ -1152,61 +1153,77 @@ public class IntroductionIntegrationTest
eventWaiter.await(TIMEOUT, 1);
// introducer can not yet remove messages
- assertFalse(deleteAllMessages1From0());
+ assertFalse(deleteAllMessages1From0().allDeleted());
+ assertTrue(deleteAllMessages1From0().hasIntroduction());
+ assertTrue(deleteAllMessages1From0().hasSessionInProgress());
// introducee1 can not yet remove messages
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertTrue(deleteAllMessages0From1().hasIntroduction());
+ assertTrue(deleteAllMessages0From1().hasSessionInProgress());
// sync second REQUEST message
sync0To2(1, true);
eventWaiter.await(TIMEOUT, 1);
// introducer can not yet remove messages
- assertFalse(deleteAllMessages2From0());
+ assertFalse(deleteAllMessages2From0().allDeleted());
+ assertTrue(deleteAllMessages2From0().hasSessionInProgress());
// introducee2 can not yet remove messages
- assertFalse(deleteAllMessages0From2());
+ assertFalse(deleteAllMessages0From2().allDeleted());
+ assertTrue(deleteAllMessages0From2().hasSessionInProgress());
// sync first ACCEPT message
sync1To0(1, true);
eventWaiter.await(TIMEOUT, 1);
// introducer can not yet remove messages
- assertFalse(deleteAllMessages1From0());
+ assertFalse(deleteAllMessages1From0().allDeleted());
+ assertTrue(deleteAllMessages1From0().hasSessionInProgress());
// sync second ACCEPT message
sync2To0(1, true);
eventWaiter.await(TIMEOUT, 1);
// introducer can not yet remove messages
- assertFalse(deleteAllMessages2From0());
+ assertFalse(deleteAllMessages2From0().allDeleted());
+ assertTrue(deleteAllMessages2From0().hasSessionInProgress());
// sync forwarded ACCEPT messages to introducees
sync0To1(1, true);
sync0To2(1, true);
// introducee1 can not yet remove messages
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertTrue(deleteAllMessages0From1().hasSessionInProgress());
// introducee2 can not yet remove messages
- assertFalse(deleteAllMessages0From2());
+ assertFalse(deleteAllMessages0From2().allDeleted());
+ assertTrue(deleteAllMessages0From2().hasSessionInProgress());
// sync first AUTH and its forward
sync1To0(1, true);
sync0To2(1, true);
// introducer can not yet remove messages
- assertFalse(deleteAllMessages1From0());
- assertFalse(deleteAllMessages2From0());
+ assertFalse(deleteAllMessages1From0().allDeleted());
+ assertTrue(deleteAllMessages1From0().hasSessionInProgress());
+ assertFalse(deleteAllMessages2From0().allDeleted());
+ assertTrue(deleteAllMessages2From0().hasSessionInProgress());
// introducee2 can not yet remove messages
- assertFalse(deleteAllMessages0From2());
+ assertFalse(deleteAllMessages0From2().allDeleted());
+ assertTrue(deleteAllMessages0From2().hasSessionInProgress());
// sync second AUTH and its forward as well as the following ACTIVATE
sync2To0(2, true);
sync0To1(2, true);
// introducer can not yet remove messages
- assertFalse(deleteAllMessages1From0());
- assertFalse(deleteAllMessages2From0());
+ assertFalse(deleteAllMessages1From0().allDeleted());
+ assertTrue(deleteAllMessages1From0().hasSessionInProgress());
+ assertFalse(deleteAllMessages2From0().allDeleted());
+ assertTrue(deleteAllMessages2From0().hasSessionInProgress());
// introducee1 can not yet remove messages
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertTrue(deleteAllMessages0From1().hasSessionInProgress());
// sync second ACTIVATE and its forward
sync1To0(1, true);
@@ -1221,13 +1238,15 @@ public class IntroductionIntegrationTest
assertGroupCount(messageTracker0, g1.getId(), 2, 1);
// introducer can now remove messages
- assertTrue(deleteAllMessages1From0());
+ assertTrue(deleteAllMessages1From0().allDeleted());
assertEquals(0, getMessages1From0().size());
- assertTrue(deleteAllMessages1From0()); // a second time returns true
+ // a second time returns true
+ assertTrue(deleteAllMessages1From0().allDeleted());
assertGroupCount(messageTracker0, g1.getId(), 0, 0);
// introducee1 can not yet remove messages, because last not ACKed
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertTrue(deleteAllMessages0From1().hasSessionInProgress());
assertEquals(2, getMessages0From1().size());
// check that introducee1 messages are tracked properly
@@ -1237,18 +1256,20 @@ public class IntroductionIntegrationTest
sendAcks(c0, c1, contactId1From0, 1);
// introducee1 can now remove messages
- assertTrue(deleteAllMessages0From1());
+ assertTrue(deleteAllMessages0From1().allDeleted());
assertEquals(0, getMessages0From1().size());
- assertTrue(deleteAllMessages0From1()); // a second time returns true
+ // a second time returns true
+ assertTrue(deleteAllMessages0From1().allDeleted());
assertGroupCount(messageTracker1, g1.getId(), 0, 0);
// check that introducee2 messages are tracked properly
assertGroupCount(messageTracker2, g2.getId(), 2, 1);
// introducee2 can remove messages (last message was incoming)
- assertTrue(deleteAllMessages0From2());
+ assertTrue(deleteAllMessages0From2().allDeleted());
assertEquals(0, getMessages0From2().size());
- assertTrue(deleteAllMessages0From2()); // a second time returns true
+ // a second time returns true
+ assertTrue(deleteAllMessages0From2().allDeleted());
assertGroupCount(messageTracker2, g2.getId(), 0, 0);
// a new introduction is still possible
@@ -1271,10 +1292,14 @@ public class IntroductionIntegrationTest
assertFalse(listener2.aborted);
// nobody can delete anything again
- assertFalse(deleteAllMessages1From0());
- assertFalse(deleteAllMessages2From0());
- assertFalse(deleteAllMessages0From1());
- assertFalse(deleteAllMessages0From2());
+ assertFalse(deleteAllMessages1From0().allDeleted());
+ assertTrue(deleteAllMessages1From0().hasSessionInProgress());
+ assertFalse(deleteAllMessages2From0().allDeleted());
+ assertTrue(deleteAllMessages2From0().hasSessionInProgress());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertTrue(deleteAllMessages0From1().hasSessionInProgress());
+ assertFalse(deleteAllMessages0From2().allDeleted());
+ assertTrue(deleteAllMessages0From2().hasSessionInProgress());
// group counts get counted up again correctly
assertGroupCount(messageTracker0, g1.getId(), 2, 1);
@@ -1302,50 +1327,54 @@ public class IntroductionIntegrationTest
eventWaiter.await(TIMEOUT, 1);
// introducer can not yet remove messages
- assertFalse(deleteAllMessages1From0());
+ assertFalse(deleteAllMessages1From0().allDeleted());
// introducee1 can not yet remove messages
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages0From1().allDeleted());
// sync second DECLINE message
sync2To0(1, true);
eventWaiter.await(TIMEOUT, 1);
// introducer can not yet remove messages
- assertFalse(deleteAllMessages2From0());
+ assertFalse(deleteAllMessages2From0().allDeleted());
// introducee2 can not yet remove messages
- assertFalse(deleteAllMessages0From2());
+ assertFalse(deleteAllMessages0From2().allDeleted());
// forward first DECLINE message
sync0To2(1, true);
// introducee2 can now remove messages
- assertTrue(deleteAllMessages0From2());
+ assertTrue(deleteAllMessages0From2().allDeleted());
assertEquals(0, getMessages0From2().size());
- assertTrue(deleteAllMessages0From2()); // a second time nothing happens
+ // a second time nothing happens
+ assertTrue(deleteAllMessages0From2().allDeleted());
// forward second DECLINE message
sync0To1(1, true);
// introducee1 can now remove messages
- assertTrue(deleteAllMessages0From1());
+ assertTrue(deleteAllMessages0From1().allDeleted());
assertEquals(0, getMessages0From1().size());
- assertTrue(deleteAllMessages0From1()); // a second time nothing happens
+ // a second time nothing happens
+ assertTrue(deleteAllMessages0From1().allDeleted());
// introducer can not yet remove messages
- assertFalse(deleteAllMessages1From0());
- assertFalse(deleteAllMessages2From0());
+ assertFalse(deleteAllMessages1From0().allDeleted());
+ assertFalse(deleteAllMessages2From0().allDeleted());
// introducer can remove messages after getting ACK from introducee1
sendAcks(c1, c0, contactId0From1, 1);
- assertTrue(deleteAllMessages1From0());
+ assertTrue(deleteAllMessages1From0().allDeleted());
assertEquals(0, getMessages1From0().size());
- assertTrue(deleteAllMessages1From0()); // a second time nothing happens
+ // a second time nothing happens
+ assertTrue(deleteAllMessages1From0().allDeleted());
// introducer can remove messages after getting ACK from introducee2
sendAcks(c2, c0, contactId0From2, 1);
- assertTrue(deleteAllMessages2From0());
+ assertTrue(deleteAllMessages2From0().allDeleted());
assertEquals(0, getMessages2From0().size());
- assertTrue(deleteAllMessages2From0()); // a second time nothing happens
+ // a second time nothing happens
+ assertTrue(deleteAllMessages2From0().allDeleted());
// a new introduction is still possible
assertTrue(introductionManager0
@@ -1368,10 +1397,10 @@ public class IntroductionIntegrationTest
assertFalse(listener2.aborted);
// nobody can delete anything again
- assertFalse(deleteAllMessages1From0());
- assertFalse(deleteAllMessages2From0());
- assertFalse(deleteAllMessages0From1());
- assertFalse(deleteAllMessages0From2());
+ assertFalse(deleteAllMessages1From0().allDeleted());
+ assertFalse(deleteAllMessages2From0().allDeleted());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertFalse(deleteAllMessages0From2().allDeleted());
}
@Test
@@ -1401,9 +1430,10 @@ public class IntroductionIntegrationTest
// introducer can remove messages after getting ACK from introducee1
sendAcks(c1, c0, contactId0From1, 1);
- assertTrue(deleteAllMessages1From0());
+ assertTrue(deleteAllMessages1From0().allDeleted());
assertEquals(0, getMessages1From0().size());
- assertTrue(deleteAllMessages1From0()); // a second time nothing happens
+ // a second time nothing happens
+ assertTrue(deleteAllMessages1From0().allDeleted());
// a new introduction is still possible
assertTrue(introductionManager0
@@ -1422,16 +1452,16 @@ public class IntroductionIntegrationTest
// introducer can remove messages after getting ACK from introducee1
sendAcks(c1, c0, contactId0From1, 1);
- assertTrue(deleteAllMessages1From0());
+ assertTrue(deleteAllMessages1From0().allDeleted());
assertEquals(0, getMessages1From0().size());
- assertTrue(deleteAllMessages1From0()); // a second time nothing happens
+ assertTrue(deleteAllMessages1From0().allDeleted()); // a second time nothing happens
// introducer can remove messages after getting ACK from introducee2
// if this succeeds, we still had the session object after delete above
sendAcks(c2, c0, contactId0From2, 1);
- assertTrue(deleteAllMessages2From0());
+ assertTrue(deleteAllMessages2From0().allDeleted());
assertEquals(0, getMessages2From0().size());
- assertTrue(deleteAllMessages2From0()); // a second time nothing happens
+ assertTrue(deleteAllMessages2From0().allDeleted()); // a second time nothing happens
// no one should have aborted
assertFalse(listener0.aborted);
@@ -1454,7 +1484,9 @@ public class IntroductionIntegrationTest
MessageId messageId1 = m1From0.iterator().next().getId();
Set toDelete1 = new HashSet<>();
toDelete1.add(messageId1);
- assertFalse(deleteMessages1From0(toDelete1));
+ assertFalse(deleteMessages1From0(toDelete1).allDeleted());
+ assertTrue(deleteMessages1From0(toDelete1).hasIntroduction());
+ assertTrue(deleteMessages1From0(toDelete1).hasSessionInProgress());
// deleting the introduction for introducee2 will fail as well
Collection m2From0 = getMessages2From0();
@@ -1462,7 +1494,9 @@ public class IntroductionIntegrationTest
MessageId messageId2 = m2From0.iterator().next().getId();
Set toDelete2 = new HashSet<>();
toDelete2.add(messageId2);
- assertFalse(deleteMessages2From0(toDelete2));
+ assertFalse(deleteMessages2From0(toDelete2).allDeleted());
+ assertTrue(deleteMessages2From0(toDelete2).hasIntroduction());
+ assertTrue(deleteMessages2From0(toDelete2).hasSessionInProgress());
// sync REQUEST messages
sync0To1(1, true);
@@ -1470,33 +1504,38 @@ public class IntroductionIntegrationTest
sync0To2(1, true);
eventWaiter.await(TIMEOUT, 1);
- // deleting introduction fails for introducees,
- // because response is not yet selected for deletion
- assertFalse(deleteMessages0From1(toDelete1));
- assertFalse(deleteMessages0From2(toDelete2));
+ // deleting introduction fails, because responses did not arrive
+ assertFalse(deleteMessages0From1(toDelete1).allDeleted());
+ assertTrue(deleteMessages0From1(toDelete1).hasSessionInProgress());
+ assertFalse(deleteMessages0From2(toDelete2).allDeleted());
+ assertTrue(deleteMessages0From2(toDelete2).hasSessionInProgress());
- // add response of introducee1 for deletion
+ // remember response of introducee1 for future deletion
Collection m0From1 = getMessages0From1();
assertEquals(2, m0From1.size());
+ MessageId response1 = null;
for (ConversationMessageHeader h : m0From1) {
- if (!h.getId().equals(messageId1)) toDelete1.add(h.getId());
+ if (!h.getId().equals(messageId1)) response1 = h.getId();
}
+ assertNotNull(response1);
- // add response of introducee2 for deletion
+ // remember response of introducee2 for future deletion
Collection m0From2 = getMessages0From2();
assertEquals(2, m0From2.size());
+ MessageId response2 = null;
for (ConversationMessageHeader h : m0From2) {
- if (!h.getId().equals(messageId2)) toDelete2.add(h.getId());
+ if (!h.getId().equals(messageId2)) response2 = h.getId();
}
+ assertNotNull(response2);
// sync first DECLINE message
sync1To0(1, true);
eventWaiter.await(TIMEOUT, 1);
// introducer can not yet remove messages
- assertFalse(deleteMessages1From0(toDelete1));
+ assertFalse(deleteMessages1From0(toDelete1).allDeleted());
// introducee1 can not yet remove messages
- assertFalse(deleteMessages0From1(toDelete1));
+ assertFalse(deleteMessages0From1(toDelete1).allDeleted());
// sync second DECLINE message
sync2To0(1, true);
@@ -1508,77 +1547,104 @@ public class IntroductionIntegrationTest
assertGroupCount(messageTracker1, g1.getId(), 2, 1);
assertGroupCount(messageTracker2, g2.getId(), 2, 1);
- // introducer can now remove messages with both introducees
- assertTrue(deleteMessages1From0(toDelete1));
- assertTrue(deleteMessages2From0(toDelete2));
+ // introducer can now remove messages with both introducees,
+ // if the responses are also selected
+ Set toDelete1From0 = new HashSet<>(toDelete1);
+ toDelete1From0.add(response1);
+ DeletionResult result = deleteMessages1From0(toDelete1From0);
+ assertTrue(result.allDeleted());
+ Set toDelete2From0 = new HashSet<>(toDelete2);
+ toDelete2From0.add(response2);
+ assertTrue(deleteMessages2From0(toDelete2From0).allDeleted());
assertGroupCount(messageTracker0, g1.getId(), 0, 0);
assertGroupCount(messageTracker0, g2.getId(), 0, 0);
+
// introducee2 can not yet remove messages, missing the other response
- assertFalse(deleteMessages0From1(toDelete1));
+ assertFalse(deleteMessages0From1(toDelete1).allDeleted());
// forward first DECLINE message
sync0To2(1, true);
+ // deleting introduction fails for introducee 2,
+ // because response is not yet selected for deletion
+ assertFalse(deleteMessages0From2(toDelete2).allDeleted());
+ assertTrue(deleteMessages0From2(toDelete2).hasIntroduction());
+ assertTrue(deleteMessages0From2(toDelete2).hasNotAllSelected());
+
+ // add response to be deleted as well
+ toDelete2.add(response2);
+
// introducee2 can now remove messages
- assertTrue(deleteMessages0From2(toDelete2));
+ assertTrue(deleteMessages0From2(toDelete2).allDeleted());
assertEquals(0, getMessages0From2().size());
- assertTrue(deleteMessages0From2(toDelete2)); // a second time nothing happens
+ // a second time nothing happens
+ assertTrue(deleteMessages0From2(toDelete2).allDeleted());
assertGroupCount(messageTracker2, g2.getId(), 0, 0);
// forward second DECLINE message
sync0To1(1, true);
+ // deleting introduction fails for introducee 1,
+ // because response is not yet selected for deletion
+ assertFalse(deleteMessages0From1(toDelete1).allDeleted());
+ assertTrue(deleteMessages0From1(toDelete1).hasIntroduction());
+ assertTrue(deleteMessages0From1(toDelete1).hasNotAllSelected());
+
+ // add response to be deleted as well
+ toDelete1.add(response1);
+
// introducee1 can now also remove messages
- assertTrue(deleteMessages0From1(toDelete1));
+ assertTrue(deleteMessages0From1(toDelete1).allDeleted());
assertEquals(0, getMessages0From1().size());
- assertTrue(deleteMessages0From1(toDelete1)); // a second time nothing happens
+ // a second time nothing happens
+ assertTrue(deleteMessages0From1(toDelete1).allDeleted());
assertGroupCount(messageTracker1, g1.getId(), 0, 0);
}
@Test
public void testDeletingEmptySet() throws Exception {
- assertTrue(deleteMessages0From1(emptySet()));
+ assertTrue(deleteMessages0From1(emptySet()).allDeleted());
}
- private boolean deleteAllMessages1From0() throws DbException {
+ private DeletionResult deleteAllMessages1From0() throws DbException {
return db0.transactionWithResult(false, txn -> introductionManager0
.deleteAllMessages(txn, contactId1From0));
}
- private boolean deleteAllMessages2From0() throws DbException {
+ private DeletionResult deleteAllMessages2From0() throws DbException {
return db0.transactionWithResult(false, txn -> introductionManager0
.deleteAllMessages(txn, contactId2From0));
}
- private boolean deleteAllMessages0From1() throws DbException {
+ private DeletionResult deleteAllMessages0From1() throws DbException {
return db1.transactionWithResult(false, txn -> introductionManager1
.deleteAllMessages(txn, contactId0From1));
}
- private boolean deleteAllMessages0From2() throws DbException {
+ private DeletionResult deleteAllMessages0From2() throws DbException {
return db2.transactionWithResult(false, txn -> introductionManager2
.deleteAllMessages(txn, contactId0From2));
}
- private boolean deleteMessages1From0(Set toDelete)
+ private DeletionResult deleteMessages1From0(Set toDelete)
throws DbException {
return db0.transactionWithResult(false, txn -> introductionManager0
.deleteMessages(txn, contactId1From0, toDelete));
}
- private boolean deleteMessages2From0(Set toDelete)
+ private DeletionResult deleteMessages2From0(Set toDelete)
throws DbException {
return db0.transactionWithResult(false, txn -> introductionManager0
.deleteMessages(txn, contactId2From0, toDelete));
}
- private boolean deleteMessages0From1(Set toDelete)
+ private DeletionResult deleteMessages0From1(Set toDelete)
throws DbException {
return db1.transactionWithResult(false, txn -> introductionManager1
.deleteMessages(txn, contactId0From1, toDelete));
}
- private boolean deleteMessages0From2(Set toDelete)
+ private DeletionResult deleteMessages0From2(Set toDelete)
throws DbException {
return db2.transactionWithResult(false, txn -> introductionManager2
.deleteMessages(txn, contactId0From2, toDelete));
diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/MessagingManagerIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/messaging/MessagingManagerIntegrationTest.java
index f5cf206f9..44333fb6d 100644
--- a/briar-core/src/test/java/org/briarproject/briar/messaging/MessagingManagerIntegrationTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/messaging/MessagingManagerIntegrationTest.java
@@ -7,6 +7,7 @@ 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.conversation.ConversationMessageHeader;
+import org.briarproject.briar.api.conversation.DeletionResult;
import org.briarproject.briar.api.messaging.AttachmentHeader;
import org.briarproject.briar.api.messaging.MessagingManager;
import org.briarproject.briar.api.messaging.PrivateMessage;
@@ -159,9 +160,11 @@ public class MessagingManagerIntegrationTest
// delete all messages on both sides (deletes all, because returns true)
assertTrue(db0.transactionWithResult(false,
- txn -> messagingManager0.deleteAllMessages(txn, contactId)));
+ txn -> messagingManager0.deleteAllMessages(txn, contactId))
+ .allDeleted());
assertTrue(db1.transactionWithResult(false,
- txn -> messagingManager1.deleteAllMessages(txn, contactId)));
+ txn -> messagingManager1.deleteAllMessages(txn, contactId))
+ .allDeleted());
// all messages are gone
assertEquals(0, getMessages(c0).size());
@@ -185,9 +188,11 @@ public class MessagingManagerIntegrationTest
toDelete.add(m1.getMessage().getId());
toDelete.add(m2.getMessage().getId());
assertTrue(db0.transactionWithResult(false, txn ->
- messagingManager0.deleteMessages(txn, contactId, toDelete)));
+ messagingManager0.deleteMessages(txn, contactId, toDelete))
+ .allDeleted());
assertTrue(db1.transactionWithResult(false, txn ->
- messagingManager1.deleteMessages(txn, contactId, toDelete)));
+ messagingManager1.deleteMessages(txn, contactId, toDelete))
+ .allDeleted());
// all messages except 1 are gone
assertEquals(1, getMessages(c0).size());
@@ -203,7 +208,8 @@ public class MessagingManagerIntegrationTest
toDelete.clear();
toDelete.add(m0.getMessage().getId());
assertTrue(db0.transactionWithResult(false, txn ->
- messagingManager0.deleteMessages(txn, contactId, toDelete)));
+ messagingManager0.deleteMessages(txn, contactId, toDelete))
+ .allDeleted());
assertEquals(0, getMessages(c0).size());
assertGroupCounts(c0, 0, 0);
}
@@ -225,9 +231,9 @@ public class MessagingManagerIntegrationTest
Set toDelete = new HashSet<>();
toDelete.add(m0.getMessage().getId());
assertTrue(c0.getConversationManager()
- .deleteMessages(contactId, toDelete));
+ .deleteMessages(contactId, toDelete).allDeleted());
assertTrue(c1.getConversationManager()
- .deleteMessages(contactId, toDelete));
+ .deleteMessages(contactId, toDelete).allDeleted());
// message was deleted
assertEquals(0, getMessages(c0).size());
@@ -246,9 +252,11 @@ public class MessagingManagerIntegrationTest
// delete message on both sides (deletes all, because returns true)
assertTrue(db0.transactionWithResult(false,
- txn -> messagingManager0.deleteAllMessages(txn, contactId)));
+ txn -> messagingManager0.deleteAllMessages(txn, contactId))
+ .allDeleted());
assertTrue(db1.transactionWithResult(false,
- txn -> messagingManager1.deleteAllMessages(txn, contactId)));
+ txn -> messagingManager1.deleteAllMessages(txn, contactId))
+ .allDeleted());
// attachment was deleted on both devices
try {
@@ -285,10 +293,14 @@ public class MessagingManagerIntegrationTest
// deleting message fails (on both sides),
// because attachment is not yet delivered
Set toDelete = singleton(m.getMessage().getId());
- assertFalse(db0.transactionWithResult(false, txn ->
- messagingManager0.deleteMessages(txn, contactId, toDelete)));
- assertFalse(db1.transactionWithResult(false, txn ->
- messagingManager1.deleteMessages(txn, contactId, toDelete)));
+ DeletionResult result0 = db0.transactionWithResult(false, txn ->
+ messagingManager0.deleteMessages(txn, contactId, toDelete));
+ assertFalse(result0.allDeleted());
+ assertTrue(result0.hasNotFullyDownloaded());
+ DeletionResult result1 = db1.transactionWithResult(false, txn ->
+ messagingManager1.deleteMessages(txn, contactId, toDelete));
+ assertFalse(result1.allDeleted());
+ assertTrue(result1.hasNotFullyDownloaded());
// deliver attachment
db0.transaction(false,
@@ -298,9 +310,11 @@ public class MessagingManagerIntegrationTest
// deleting message and attachment on both sides works now
assertTrue(db0.transactionWithResult(false, txn ->
- messagingManager0.deleteMessages(txn, contactId, toDelete)));
+ messagingManager0.deleteMessages(txn, contactId, toDelete))
+ .allDeleted());
assertTrue(db1.transactionWithResult(false, txn ->
- messagingManager1.deleteMessages(txn, contactId, toDelete)));
+ messagingManager1.deleteMessages(txn, contactId, toDelete))
+ .allDeleted());
// attachment was deleted on both devices
try {
@@ -320,7 +334,8 @@ public class MessagingManagerIntegrationTest
@Test
public void testDeletingEmptySet() throws Exception {
assertTrue(db0.transactionWithResult(false, txn ->
- messagingManager0.deleteMessages(txn, contactId, emptySet())));
+ messagingManager0.deleteMessages(txn, contactId, emptySet()))
+ .allDeleted());
}
private PrivateMessage sendMessage(BriarIntegrationTestComponent from,
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 70406c7eb..b89448c2f 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
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestDatabaseConfigModule;
import org.briarproject.briar.api.client.ProtocolStateException;
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
+import org.briarproject.briar.api.conversation.DeletionResult;
import org.briarproject.briar.api.privategroup.GroupMessage;
import org.briarproject.briar.api.privategroup.PrivateGroup;
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
@@ -463,9 +464,13 @@ public class GroupInvitationIntegrationTest
sync0To1(1, true);
// messages can not be deleted
- assertFalse(deleteAllMessages1From0());
+ assertFalse(deleteAllMessages1From0().allDeleted());
+ assertTrue(deleteAllMessages1From0().hasInvitation());
+ assertTrue(deleteAllMessages1From0().hasSessionInProgress());
assertEquals(1, getMessages1From0().size());
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertTrue(deleteAllMessages0From1().hasInvitation());
+ assertTrue(deleteAllMessages0From1().hasSessionInProgress());
assertEquals(1, getMessages0From1().size());
// respond
@@ -478,13 +483,15 @@ public class GroupInvitationIntegrationTest
assertGroupCount(messageTracker1, g0From1.getId(), 2, 1);
// messages can be deleted now by creator, invitee needs to wait for ACK
- assertTrue(deleteAllMessages1From0());
+ assertTrue(deleteAllMessages1From0().allDeleted());
assertEquals(0, getMessages1From0().size());
- assertTrue(deleteAllMessages1From0()); // a second time nothing happens
+ assertTrue(deleteAllMessages1From0().allDeleted()); // a second time nothing happens
assertGroupCount(messageTracker0, g1From0.getId(), 0, 0);
// trying to delete fails for invitee
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertTrue(deleteAllMessages0From1().hasInvitation());
+ assertTrue(deleteAllMessages0From1().hasSessionInProgress());
assertEquals(2, getMessages0From1().size());
// creator sends two JOIN messages (one sharing + one in private group)
@@ -492,9 +499,10 @@ public class GroupInvitationIntegrationTest
sync0To1(2, true);
// now invitee can also delete messages
- assertTrue(deleteAllMessages0From1());
+ assertTrue(deleteAllMessages0From1().allDeleted());
assertEquals(0, getMessages0From1().size());
- assertTrue(deleteAllMessages0From1()); // a second time nothing happens
+ // a second time nothing happens
+ assertTrue(deleteAllMessages0From1().allDeleted());
assertGroupCount(messageTracker1, g0From1.getId(), 0, 0);
// invitee now leaves
@@ -524,21 +532,25 @@ public class GroupInvitationIntegrationTest
assertGroupCount(messageTracker1, g0From1.getId(), 2, 1);
// messages can be deleted now by creator, invitee needs to wait for ACK
- assertTrue(deleteAllMessages1From0());
+ assertTrue(deleteAllMessages1From0().allDeleted());
assertEquals(0, getMessages1From0().size());
- assertTrue(deleteAllMessages1From0()); // a second time nothing happens
+ // a second time nothing happens
+ assertTrue(deleteAllMessages1From0().allDeleted());
// trying to delete fails for invitee
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertTrue(deleteAllMessages0From1().hasInvitation());
+ assertTrue(deleteAllMessages0From1().hasSessionInProgress());
assertEquals(2, getMessages0From1().size());
// creator sends ACK
sendAcks(c0, c1, contactId1From0, 1);
// now invitee can also delete messages
- assertTrue(deleteAllMessages0From1());
+ assertTrue(deleteAllMessages0From1().allDeleted());
assertEquals(0, getMessages0From1().size());
- assertTrue(deleteAllMessages0From1()); // a second time nothing happens
+ // a second time nothing happens
+ assertTrue(deleteAllMessages0From1().allDeleted());
assertGroupCount(messageTracker1, g0From1.getId(), 0, 0);
// creator can re-invite
@@ -546,8 +558,10 @@ public class GroupInvitationIntegrationTest
sync0To1(1, true);
// now new messages can not be deleted anymore
- assertFalse(deleteAllMessages1From0());
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages1From0().allDeleted());
+ assertTrue(deleteAllMessages1From0().hasSessionInProgress());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertTrue(deleteAllMessages0From1().hasSessionInProgress());
// responding again
groupInvitationManager1
@@ -562,8 +576,8 @@ public class GroupInvitationIntegrationTest
assertGroupCount(messageTracker0, g1From0.getId(), 2, 1);
// deleting is possible again
- assertTrue(deleteAllMessages1From0());
- assertTrue(deleteAllMessages0From1());
+ assertTrue(deleteAllMessages1From0().allDeleted());
+ assertTrue(deleteAllMessages0From1().allDeleted());
assertGroupCount(messageTracker1, g0From1.getId(), 0, 0);
assertGroupCount(messageTracker0, g1From0.getId(), 0, 0);
}
@@ -580,8 +594,10 @@ public class GroupInvitationIntegrationTest
MessageId messageId = m0.iterator().next().getId();
Set toDelete = new HashSet<>();
toDelete.add(messageId);
- assertFalse(deleteMessages1From0(toDelete));
- assertFalse(deleteMessages0From1(toDelete));
+ assertFalse(deleteMessages1From0(toDelete).allDeleted());
+ assertTrue(deleteMessages1From0(toDelete).hasSessionInProgress());
+ assertFalse(deleteMessages0From1(toDelete).allDeleted());
+ assertTrue(deleteMessages0From1(toDelete).hasSessionInProgress());
// respond
groupInvitationManager1
@@ -590,8 +606,10 @@ public class GroupInvitationIntegrationTest
// both can still not delete the invitation,
// because the response was not selected for deletion as well
- assertFalse(deleteMessages1From0(toDelete));
- assertFalse(deleteMessages0From1(toDelete));
+ assertFalse(deleteMessages1From0(toDelete).allDeleted());
+ assertTrue(deleteMessages1From0(toDelete).hasNotAllSelected());
+ assertFalse(deleteMessages0From1(toDelete).allDeleted());
+ assertTrue(deleteMessages0From1(toDelete).hasNotAllSelected());
// after selecting response, both messages can be deleted by creator
m0 = getMessages1From0();
@@ -600,14 +618,15 @@ public class GroupInvitationIntegrationTest
if (!h.getId().equals(messageId)) toDelete.add(h.getId());
}
assertGroupCount(messageTracker0, g1From0.getId(), 2, 1);
- assertTrue(deleteMessages1From0(toDelete));
+ assertTrue(deleteMessages1From0(toDelete).allDeleted());
assertEquals(0, getMessages1From0().size());
// a second time nothing happens
- assertTrue(deleteMessages1From0(toDelete));
+ assertTrue(deleteMessages1From0(toDelete).allDeleted());
assertGroupCount(messageTracker0, g1From0.getId(), 0, 0);
// 1 can still not delete the messages, as last one has not been ACKed
- assertFalse(deleteMessages0From1(toDelete));
+ assertFalse(deleteMessages0From1(toDelete).allDeleted());
+ assertTrue(deleteMessages0From1(toDelete).hasSessionInProgress());
assertEquals(2, getMessages0From1().size());
assertGroupCount(messageTracker1, g0From1.getId(), 2, 1);
@@ -615,16 +634,16 @@ public class GroupInvitationIntegrationTest
sendAcks(c0, c1, contactId1From0, 1);
// 1 can now delete all messages, as last one has been ACKed
- assertTrue(deleteMessages0From1(toDelete));
+ assertTrue(deleteMessages0From1(toDelete).allDeleted());
assertEquals(0, getMessages0From1().size());
assertGroupCount(messageTracker1, g0From1.getId(), 0, 0);
// a second time nothing happens
- assertTrue(deleteMessages0From1(toDelete));
+ assertTrue(deleteMessages0From1(toDelete).allDeleted());
}
@Test
public void testDeletingEmptySet() throws Exception {
- assertTrue(deleteMessages0From1(emptySet()));
+ assertTrue(deleteMessages0From1(emptySet()).allDeleted());
}
private Collection getMessages1From0()
@@ -639,23 +658,23 @@ public class GroupInvitationIntegrationTest
.getMessageHeaders(txn, contactId0From1));
}
- private boolean deleteAllMessages1From0() throws DbException {
+ private DeletionResult deleteAllMessages1From0() throws DbException {
return db0.transactionWithResult(false, txn -> groupInvitationManager0
.deleteAllMessages(txn, contactId1From0));
}
- private boolean deleteAllMessages0From1() throws DbException {
+ private DeletionResult deleteAllMessages0From1() throws DbException {
return db1.transactionWithResult(false, txn -> groupInvitationManager1
.deleteAllMessages(txn, contactId0From1));
}
- private boolean deleteMessages1From0(Set toDelete)
+ private DeletionResult deleteMessages1From0(Set toDelete)
throws DbException {
return db0.transactionWithResult(false, txn -> groupInvitationManager0
.deleteMessages(txn, contactId1From0, toDelete));
}
- private boolean deleteMessages0From1(Set toDelete)
+ private DeletionResult deleteMessages0From1(Set toDelete)
throws DbException {
return db1.transactionWithResult(false, txn -> groupInvitationManager1
.deleteMessages(txn, contactId0From1, toDelete));
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 20084eb98..17ce546f6 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
@@ -16,6 +16,7 @@ import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestDatabaseConfigModule;
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
import org.briarproject.briar.api.conversation.ConversationResponse;
+import org.briarproject.briar.api.conversation.DeletionResult;
import org.briarproject.briar.api.forum.Forum;
import org.briarproject.briar.api.forum.ForumInvitationRequest;
import org.briarproject.briar.api.forum.ForumInvitationResponse;
@@ -864,8 +865,12 @@ public class ForumSharingIntegrationTest
eventWaiter.await(TIMEOUT, 1);
// messages can not be deleted
- assertFalse(deleteAllMessages1From0());
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages1From0().allDeleted());
+ assertTrue(deleteAllMessages1From0().hasInvitation());
+ assertTrue(deleteAllMessages1From0().hasSessionInProgress());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertTrue(deleteAllMessages0From1().hasInvitation());
+ assertTrue(deleteAllMessages0From1().hasSessionInProgress());
// accept invitation
respondToRequest(contactId0From1, true);
@@ -881,19 +886,20 @@ public class ForumSharingIntegrationTest
assertGroupCount(messageTracker1, g0From1, 2, 1);
// 0 deletes all messages
- assertTrue(deleteAllMessages1From0());
+ assertTrue(deleteAllMessages1From0().allDeleted());
assertEquals(0, getMessages1From0().size());
assertGroupCount(messageTracker0, g1From0, 0, 0);
// 1 can not delete all messages, as last one has not been ACKed
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertTrue(deleteAllMessages0From1().hasSessionInProgress());
assertGroupCount(messageTracker1, g0From1, 2, 1);
// 0 sends an ACK to their last message
sendAcks(c0, c1, contactId1From0, 1);
// 1 can now delete all messages, as last one has been ACKed
- assertTrue(deleteAllMessages0From1());
+ assertTrue(deleteAllMessages0From1().allDeleted());
assertEquals(0, getMessages0From1().size());
assertGroupCount(messageTracker1, g0From1, 0, 0);
@@ -911,10 +917,12 @@ public class ForumSharingIntegrationTest
eventWaiter.await(TIMEOUT, 1);
// messages can not be deleted anymore
- assertFalse(deleteAllMessages1From0());
+ assertFalse(deleteAllMessages1From0().allDeleted());
+ assertTrue(deleteAllMessages1From0().hasSessionInProgress());
assertEquals(1, getMessages1From0().size());
assertGroupCount(messageTracker0, g1From0, 1, 1);
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages0From1().allDeleted());
+ assertTrue(deleteAllMessages0From1().hasSessionInProgress());
assertEquals(1, getMessages0From1().size());
assertGroupCount(messageTracker1, g0From1, 1, 0);
@@ -926,10 +934,10 @@ public class ForumSharingIntegrationTest
sendAcks(c1, c0, contactId0From1, 1);
// messages can now get deleted again
- assertTrue(deleteAllMessages1From0());
+ assertTrue(deleteAllMessages1From0().allDeleted());
assertEquals(0, getMessages1From0().size());
assertGroupCount(messageTracker0, g1From0, 0, 0);
- assertTrue(deleteAllMessages0From1());
+ assertTrue(deleteAllMessages0From1().allDeleted());
assertEquals(0, getMessages0From1().size());
assertGroupCount(messageTracker1, g0From1, 0, 0);
}
@@ -949,17 +957,17 @@ public class ForumSharingIntegrationTest
eventWaiter.await(TIMEOUT, 1);
// 0 deletes all messages
- assertTrue(deleteAllMessages1From0());
+ assertTrue(deleteAllMessages1From0().allDeleted());
assertEquals(0, getMessages1From0().size());
// 1 can not delete all messages, as last one has not been ACKed
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages0From1().allDeleted());
// 0 sends an ACK to their last message
sendAcks(c0, c1, contactId1From0, 1);
// 1 can now delete all messages, as last one has been ACKed
- assertTrue(deleteAllMessages0From1());
+ assertTrue(deleteAllMessages0From1().allDeleted());
assertEquals(0, getMessages0From1().size());
// re-sending invitation is possible
@@ -969,9 +977,9 @@ public class ForumSharingIntegrationTest
eventWaiter.await(TIMEOUT, 1);
// messages can not be deleted anymore
- assertFalse(deleteAllMessages1From0());
+ assertFalse(deleteAllMessages1From0().allDeleted());
assertEquals(1, getMessages1From0().size());
- assertFalse(deleteAllMessages0From1());
+ assertFalse(deleteAllMessages0From1().allDeleted());
assertEquals(1, getMessages0From1().size());
}
@@ -989,7 +997,9 @@ public class ForumSharingIntegrationTest
MessageId messageId = m0.iterator().next().getId();
Set toDelete = new HashSet<>();
toDelete.add(messageId);
- assertFalse(deleteMessages1From0(toDelete));
+ assertFalse(deleteMessages1From0(toDelete).allDeleted());
+ assertTrue(deleteMessages1From0(toDelete).hasInvitation());
+ assertTrue(deleteMessages1From0(toDelete).hasSessionInProgress());
// decline invitation
respondToRequest(contactId0From1, true);
@@ -998,8 +1008,12 @@ public class ForumSharingIntegrationTest
// both can still not delete the invitation,
// because the response was not selected for deletion as well
- assertFalse(deleteMessages1From0(toDelete));
- assertFalse(deleteMessages0From1(toDelete));
+ assertFalse(deleteMessages1From0(toDelete).allDeleted());
+ assertTrue(deleteMessages1From0(toDelete).hasInvitation());
+ assertTrue(deleteMessages1From0(toDelete).hasNotAllSelected());
+ assertFalse(deleteMessages0From1(toDelete).allDeleted());
+ assertTrue(deleteMessages0From1(toDelete).hasInvitation());
+ assertTrue(deleteMessages0From1(toDelete).hasNotAllSelected());
// after selecting response, both messages can be deleted
m0 = getMessages1From0();
@@ -1007,27 +1021,30 @@ public class ForumSharingIntegrationTest
for (ConversationMessageHeader h : m0) {
if (!h.getId().equals(messageId)) toDelete.add(h.getId());
}
- assertTrue(deleteMessages1From0(toDelete));
+ assertTrue(deleteMessages1From0(toDelete).allDeleted());
assertEquals(0, getMessages1From0().size());
// a second time nothing happens
- assertTrue(deleteMessages1From0(toDelete));
+ assertTrue(deleteMessages1From0(toDelete).allDeleted());
// 1 can still not delete the messages, as last one has not been ACKed
- assertFalse(deleteMessages0From1(toDelete));
+ assertFalse(deleteMessages0From1(toDelete).allDeleted());
+ assertFalse(deleteMessages0From1(toDelete).hasNotAllSelected());
+ assertTrue(deleteMessages0From1(toDelete).hasInvitation());
+ assertTrue(deleteMessages0From1(toDelete).hasSessionInProgress());
// 0 sends an ACK to their last message
sendAcks(c0, c1, contactId1From0, 1);
// 1 can now delete all messages, as last one has been ACKed
- assertTrue(deleteMessages0From1(toDelete));
+ assertTrue(deleteMessages0From1(toDelete).allDeleted());
assertEquals(0, getMessages0From1().size());
// a second time nothing happens
- assertTrue(deleteMessages0From1(toDelete));
+ assertTrue(deleteMessages0From1(toDelete).allDeleted());
}
@Test
public void testDeletingEmptySet() throws Exception {
- assertTrue(deleteMessages0From1(emptySet()));
+ assertTrue(deleteMessages0From1(emptySet()).allDeleted());
}
private Collection getMessages1From0()
@@ -1042,23 +1059,23 @@ public class ForumSharingIntegrationTest
.getMessageHeaders(txn, contactId0From1));
}
- private boolean deleteAllMessages1From0() throws DbException {
+ private DeletionResult deleteAllMessages1From0() throws DbException {
return db0.transactionWithResult(false, txn -> forumSharingManager0
.deleteAllMessages(txn, contactId1From0));
}
- private boolean deleteAllMessages0From1() throws DbException {
+ private DeletionResult deleteAllMessages0From1() throws DbException {
return db1.transactionWithResult(false, txn -> forumSharingManager1
.deleteAllMessages(txn, contactId0From1));
}
- private boolean deleteMessages1From0(Set toDelete)
+ private DeletionResult deleteMessages1From0(Set toDelete)
throws DbException {
return db0.transactionWithResult(false, txn -> forumSharingManager0
.deleteMessages(txn, contactId1From0, toDelete));
}
- private boolean deleteMessages0From1(Set toDelete)
+ private DeletionResult deleteMessages0From1(Set toDelete)
throws DbException {
return db1.transactionWithResult(false, txn -> forumSharingManager1
.deleteMessages(txn, contactId0From1, toDelete));